From 609c03848419d4cc3dac27272bbec2e45b294687 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 19 Sep 2011 18:50:06 -0700 Subject: [PATCH] Add more support for signed enumerations in SV. This patch add support for passing if the enumeration is signed or not to the run time. This is really only needed for debug and VPI access. --- tgt-vvp/draw_enum.c | 49 ++++++++++++++++++--------------------------- vvp/compile.h | 4 ++-- vvp/enum_type.cc | 15 +++++++++++--- vvp/lexor.lex | 2 ++ vvp/parse.y | 13 +++++++----- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/tgt-vvp/draw_enum.c b/tgt-vvp/draw_enum.c index 61ad79604..b4eb94573 100644 --- a/tgt-vvp/draw_enum.c +++ b/tgt-vvp/draw_enum.c @@ -22,42 +22,33 @@ # include # include # include +# include -// HERE: This still needs work! Fall back to 'b format for -// very large constants. This should also be int64_t sized values. -// The run time still needs to be modified to work with signed values -// and we also need to pass the file and line information. +// HERE: This still needs work! Fall back to 'b format for +// very large constants. We also should pass the file and +// line number information for the enum type and the MSB and +// LSB should be used instead of the width. +/* + * If it fits we always print this as a uint64_t the run time will turn + * it back into a signed value when needed. + */ static void draw_enum2_value(ivl_enumtype_t enumtype, unsigned idx) { - long val, mask; + uint64_t val, mask; const char*bits = ivl_enum_bits(enumtype, idx); const char*bit; unsigned len = strlen(bits); - /* Sign extend if needed. */ - if (ivl_enum_signed(enumtype)) { - assert(len <= sizeof(long)*8); - if ((bits[len-1] == '1') && (len < sizeof(long)*8)) { - val = -1L & ~((1L << len) - 1L); -// HERE: Remove once vvp has been updated. - if (ivl_enum_signed(enumtype)) { - fprintf(stderr, "%s:%u: tgt-vvp sorry: signed " - "enumerations with negative values are not " - "currently supported by vvp.\n", - ivl_enum_file(enumtype), - ivl_enum_lineno(enumtype)); - vvp_errors += 1; - } - } else val = 0; - } else { - assert(len < sizeof(long)*8); - val = 0; - } + +// HERE: If this doesn't fit then write it as a enum4 and modify the run +// time to deal with the conversion. + assert(len <= sizeof(uint64_t)*8); + val = 0; for (bit = bits, mask = 1 ; *bit != 0 ; bit += 1, mask <<= 1) { if (*bit == '1') val |= mask; } - fprintf(vvp_out, "%ld", val); + fprintf(vvp_out, "%" PRIu64, val); } static void draw_enum4_value(ivl_enumtype_t enumtype, unsigned idx) @@ -65,8 +56,7 @@ static void draw_enum4_value(ivl_enumtype_t enumtype, unsigned idx) const char*bits = ivl_enum_bits(enumtype, idx); const char*bit; - fprintf(vvp_out, "%u'%sb", ivl_enum_width(enumtype), - ivl_enum_signed(enumtype) ? "s" : ""); + fprintf(vvp_out, "%u'b", ivl_enum_width(enumtype)); for (bit = bits+strlen(bits) ; bit > bits ; bit -= 1) fputc(bit[-1], vvp_out); @@ -78,9 +68,10 @@ void draw_enumeration_in_scope(ivl_enumtype_t enumtype) unsigned idx; unsigned name_count = ivl_enum_names(enumtype); const char*dtype = ivl_enum_type(enumtype)==IVL_VT_BOOL? "2" : "4"; + const char*stype = ivl_enum_signed(enumtype) ? "/s" : ""; - fprintf(vvp_out, "enum%p .enum%s (%u)\n", enumtype, - dtype, ivl_enum_width(enumtype)); + fprintf(vvp_out, "enum%p .enum%s%s (%u)\n", enumtype, dtype, stype, + ivl_enum_width(enumtype)); for (idx = 0 ; idx < name_count ; idx += 1) { fprintf(vvp_out, " \"%s\" ", ivl_enum_name(enumtype, idx)); diff --git a/vvp/compile.h b/vvp/compile.h index a37042d34..547891c18 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -202,9 +202,9 @@ extern void compile_dff(char*label, struct symb_s arg_e, struct symb_s arg_a); -extern void compile_enum2_type(char*label, long width, +extern void compile_enum2_type(char*label, long width, bool signed_flag, std::list*names); -extern void compile_enum4_type(char*label, long width, +extern void compile_enum4_type(char*label, long width, bool signed_flag, std::list*names); class __vpiModPath; diff --git a/vvp/enum_type.cc b/vvp/enum_type.cc index f628a43df..4e11191de 100644 --- a/vvp/enum_type.cc +++ b/vvp/enum_type.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2011 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 @@ -40,6 +40,7 @@ static struct enumconst_s* enumconst_from_handle(vpiHandle obj) struct __vpiEnumTypespec { struct __vpiHandle base; std::vector names; + bool is_signed; }; static struct __vpiEnumTypespec* vpip_enum_typespec_from_handle(vpiHandle obj) @@ -58,6 +59,10 @@ static int enum_type_get(int code, vpiHandle obj) switch (code) { case vpiSize: return ref->names.size(); + + case vpiSigned: + return ref->is_signed; + default: fprintf(stderr, "vvp error: get %d not supported " "by __vpiEnumTypespec\n", code); @@ -148,11 +153,13 @@ static const struct __vpirt enum_name_rt = { 0, //enum_name_put_delays }; -void compile_enum2_type(char*label, long width, std::list*names) +void compile_enum2_type(char*label, long width, bool signed_flag, + std::list*names) { struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec; spec->base.vpi_type = &enum_type_rt; spec->names = std::vector (names->size()); + spec->is_signed = signed_flag; size_t idx = 0; for (list::iterator cur = names->begin() @@ -170,11 +177,13 @@ void compile_enum2_type(char*label, long width, std::list*na delete names; } -void compile_enum4_type(char*label, long width, std::list*names) +void compile_enum4_type(char*label, long width, bool signed_flag, + std::list*names) { struct __vpiEnumTypespec*spec = new struct __vpiEnumTypespec; spec->base.vpi_type = &enum_type_rt; spec->names = std::vector (names->size()); + spec->is_signed = signed_flag; size_t idx = 0; for (list::iterator cur = names->begin() diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 6ea6745e5..66bed1b7b 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -143,7 +143,9 @@ static char* strdupnew(char const *str) ".delay" { return K_DELAY; } ".dff" { return K_DFF; } ".enum2" { return K_ENUM2; } +".enum2/s" { return K_ENUM2_S; } ".enum4" { return K_ENUM4; } +".enum4/s" { return K_ENUM4_S; } ".event" { return K_EVENT; } ".event/or" { return K_EVENT_OR; } ".export" { return K_EXPORT; } diff --git a/vvp/parse.y b/vvp/parse.y index 5b7a310f1..6c03a3335 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -80,9 +80,8 @@ static struct __vpiModPath*modpath_dst = 0; %token K_CMP_EEQ K_CMP_EQ K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R %token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S %token K_CONCAT K_DEBUG K_DELAY K_DFF -%token K_ENUM2 K_ENUM4 K_EVENT K_EVENT_OR K_EXPORT K_EXTEND_S K_FUNCTOR -%token K_IMPORT K_ISLAND -%token K_MODPATH +%token K_ENUM2 K_ENUM2_S K_ENUM4 K_ENUM4_S K_EVENT K_EVENT_OR +%token K_EXPORT K_EXTEND_S K_FUNCTOR K_IMPORT K_ISLAND K_MODPATH %token K_NET K_NET_S K_NET_R K_NET_2S K_NET_2U K_NET8 K_NET8_S %token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV %token K_PART_V K_PART_V_S K_PORT K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR @@ -810,9 +809,13 @@ statement /* Enumeration types */ enum_type : T_LABEL K_ENUM2 '(' T_NUMBER ')' enum_type_names ';' - { compile_enum2_type($1, $4, $6); } + { compile_enum2_type($1, $4, false, $6); } + | T_LABEL K_ENUM2_S '(' T_NUMBER ')' enum_type_names ';' + { compile_enum2_type($1, $4, true, $6); } | T_LABEL K_ENUM4 '(' T_NUMBER ')' enum_type_names ';' - { compile_enum4_type($1, $4, $6); } + { compile_enum4_type($1, $4, false, $6); } + | T_LABEL K_ENUM4_S '(' T_NUMBER ')' enum_type_names ';' + { compile_enum4_type($1, $4, true, $6); } ; enum_type_names