From 12f8af645f63772944d9401b2bf5877cd561fde3 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 21 Mar 2008 19:16:19 -0700 Subject: [PATCH] Add support for real parameters in vvp. vvp did not have the ability to handle real parameters. This patch fixes that omission. Parameters are only used by vpi calls to get compile time information. --- tgt-vvp/vvp_scope.c | 11 ++++-- vvp/compile.cc | 85 ++++++++++++++++++++++++++++----------------- vvp/compile.h | 1 + vvp/lexor.lex | 1 + vvp/parse.y | 5 ++- vvp/vpi_const.cc | 70 +++++++++++++++++++++++++++++++++++-- vvp/vpi_priv.h | 3 +- 7 files changed, 138 insertions(+), 38 deletions(-) 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