diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 8fbe614ad..70ca195ef 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -469,11 +469,10 @@ static char* draw_C8_to_string(ivl_net_const_t cptr, return result; } -static char* draw_Cr_to_string(ivl_net_const_t cptr) +static char* draw_Cr_to_string(double value) { char tmp[256]; - double value = ivl_const_real(cptr); uint64_t mant = 0; if (isinf(value)) { @@ -641,7 +640,7 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) break; case IVL_VT_REAL: - result = draw_Cr_to_string(cptr); + result = draw_Cr_to_string(ivl_const_real(cptr)); break; default: @@ -2468,6 +2467,12 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) } fprintf(vvp_out, ">;\n"); break; + case IVL_EX_REALNUM: + fprintf(vvp_out, "P_%p .param/real \"%s\", %s; value=%g\n", + par, ivl_parameter_basename(par), + draw_Cr_to_string(ivl_expr_dvalue(pex)), + ivl_expr_dvalue(pex)); + break; default: fprintf(vvp_out, "; parameter type %d unsupported\n", ivl_expr_type(pex)); diff --git a/vvp/compile.cc b/vvp/compile.cc index 3068380a2..272e6c961 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -737,6 +737,47 @@ void compile_vpi_time_precision(long pre) vpip_set_time_precision(pre); } +/* + * Convert a Cr string value to double. + * + * The format is broken into mantissa and exponent. + * The exponent in turn includes a sign bit. + * + * The mantissa is a 64bit integer value (encoded in hex). + * + * The exponent included the sign bit (0x4000) and the binary + * exponent offset by 0x1000. The actual exponent is the + * encoded exponent - 0x1000. + * + * The real value is sign * (mant ** exp). + */ +double crstring_to_double(char*label) +{ + char*cp = label+3; + assert(*cp == 'm'); + cp += 1; + uint64_t mant = strtoull(cp, &cp, 16); + assert(*cp == 'g'); + cp += 1; + int exp = strtoul(cp, 0, 16); + + double tmp; + if (mant == 0 && exp == 0x3fff) { + tmp = INFINITY; + } else if (mant == 0 && exp == 0x7fff) { + tmp = -INFINITY; + } else if (exp == 0x3fff) { + tmp = nan(""); + } else { + double sign = (exp & 0x4000)? -1.0 : 1.0; + exp &= 0x1fff; + + tmp = sign * ldexp((double)mant, exp - 0x1000); + } + + return tmp; +} + /* * Run through the arguments looking for the nodes that are * connected to my input ports. For each source functor that I @@ -819,42 +860,13 @@ void input_connect(vvp_net_t*fdx, unsigned port, char*label) } /* Handle the Cr<> constant driver, which is a real-value - driver. The format is broken into mantissa and - exponent. The exponent in turn includes a sign bit. - - The mantissa is a 64bit integer value (encoded in hex). - - The exponent included the sign bit (0x4000) and the binary - exponent offset by 0x1000. The actual exponent is the - encoded exponent - 0x1000. - - The real value is sign * (mant ** exp). */ + driver. */ if ((strncmp(label, "Cr<", 3) == 0) && ((tp = strchr(label,'>'))) && (tp[1] == 0) && (strspn(label+3, "0123456789abcdefmg")+3 == (unsigned)(tp-label))) { - char*cp = label+3; - assert(*cp == 'm'); - cp += 1; - uint64_t mant = strtoull(cp, &cp, 16); - assert(*cp == 'g'); - cp += 1; - int exp = strtoul(cp, 0, 16); - - double tmp; - if (mant == 0 && exp == 0x3fff) { - tmp = INFINITY; - } else if (mant == 0 && exp == 0x7fff) { - tmp = -INFINITY; - } else if (exp == 0x3fff) { - tmp = nan(""); - } else { - double sign = (exp & 0x4000)? -1.0 : 1.0; - exp &= 0x1fff; - - tmp = sign * ldexp((double)mant, exp - 0x1000); - } + double tmp = crstring_to_double(label); schedule_set_vector(ifdx, tmp); free(label); @@ -1842,3 +1854,14 @@ void compile_param_string(char*label, char*name, char*value) free(label); } + +void compile_param_real(char*label, char*name, char*value) +{ + double dvalue = crstring_to_double(value); + vpiHandle obj = vpip_make_real_param(name, dvalue); + compile_vpi_symbol(label, obj); + vpip_attach_to_current_scope(obj); + + free(label); + free(value); +} diff --git a/vvp/compile.h b/vvp/compile.h index 49da17e13..92a6cffd4 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -234,6 +234,7 @@ extern void compile_vpi_lookup(vpiHandle *objref, char*label); extern void compile_param_string(char*label, char*name, char*value); extern void compile_param_logic(char*label, char*name, char*value, bool signed_flag); +extern void compile_param_real(char*label, char*name, char*value); /* * This function schedules a lookup of an indexed label. The ref diff --git a/vvp/lexor.lex b/vvp/lexor.lex index c0513c65a..2621729a1 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -133,6 +133,7 @@ ".net/s" { return K_NET_S; } ".param/l" { return K_PARAM_L; } ".param/str" { return K_PARAM_STR; } +".param/real" { return K_PARAM_REAL; } ".part" { return K_PART; } ".part/pv" { return K_PART_PV; } ".part/v" { return K_PART_V; } diff --git a/vvp/parse.y b/vvp/parse.y index 9cd696016..188f9df84 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -75,7 +75,7 @@ static struct __vpiModPath*modpath_dst = 0; %token K_CONCAT K_DEBUG K_DELAY K_DFF %token K_EVENT K_EVENT_OR K_EXTEND_S K_FUNCTOR K_MODPATH K_NET K_NET_S K_NET_R %token K_NET8 K_NET8_S -%token K_PARAM_STR K_PARAM_L K_PART K_PART_PV +%token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV %token K_PART_V K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR %token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT %token K_RESOLV K_SCOPE K_SFUNC K_SHIFTL K_SHIFTR K_SHIFTRS @@ -654,6 +654,9 @@ statement | T_LABEL K_PARAM_L T_STRING ',' '+' T_SYMBOL ';' { compile_param_logic($1, $3, $6, true); } + | T_LABEL K_PARAM_REAL T_STRING ',' T_SYMBOL ';' + { compile_param_real($1, $3, $5); } + /* Oh and by the way, empty statements are OK as well. */ | ';' diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 3fccc1280..3f2f04856 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -589,6 +589,12 @@ static int real_get(int code, vpiHandle ref) { switch (code) { + case vpiLineNo: + return 0; // Not implemented for now! + + case vpiSize: + return 1; + case vpiConstType: return vpiRealConst; @@ -606,7 +612,8 @@ static int real_get(int code, vpiHandle ref) static void real_value(vpiHandle ref, p_vpi_value vp) { struct __vpiRealConst*rfp = (struct __vpiRealConst*)ref; - assert(ref->vpi_type->type_code == vpiConstant); + assert((ref->vpi_type->type_code == vpiConstant) || + (ref->vpi_type->type_code == vpiParameter)); switch (vp->format) { case vpiObjTypeVal: @@ -644,3 +651,62 @@ vpiHandle vpip_make_real_const(double value) return vpip_make_real_const(obj, value); } +struct __vpiRealParam : public __vpiRealConst { + const char*basename; + struct __vpiScope* scope; +}; + +static char* real_param_get_str(int code, vpiHandle obj) +{ + struct __vpiRealParam*rfp = (struct __vpiRealParam*)obj; + + assert(obj->vpi_type->type_code == vpiParameter); + + if (code == vpiFile) { // Not implemented for now! + return simple_set_rbuf_str(file_names[0]); + } + return generic_get_str(code, &rfp->scope->base, rfp->basename, NULL); +} + +static vpiHandle real_param_handle(int code, vpiHandle obj) +{ + struct __vpiRealParam*rfp = (struct __vpiRealParam*)obj; + + assert(obj->vpi_type->type_code == vpiParameter); + + switch (code) { + case vpiScope: + return &rfp->scope->base; + + default: + return 0; + } +} + +static const struct __vpirt vpip_real_param_rt = { + vpiParameter, + real_get, + real_param_get_str, + real_value, + 0, + + real_param_handle, + 0, + 0, + + 0 +}; + +vpiHandle vpip_make_real_param(char*name, double value) +{ + struct __vpiRealParam*obj; + + obj = (struct __vpiRealParam*) + malloc(sizeof (struct __vpiRealParam)); + obj->base.vpi_type = &vpip_real_param_rt; + obj->value = value; + obj->basename = name; + obj->scope = vpip_peek_current_scope(); + + return &obj->base; +} diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index e9d373d98..232293bd0 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1,7 +1,7 @@ #ifndef __vpi_priv_H #define __vpi_priv_H /* - * Copyright (c) 2001-2007 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -415,6 +415,7 @@ struct __vpiRealConst { }; vpiHandle vpip_make_real_const(double value); +vpiHandle vpip_make_real_param(char*name, double value); /* * This one looks like a constant, but really is a vector in the current