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