From f379cd0a14047d0972d6be891370f8aad35e4398 Mon Sep 17 00:00:00 2001 From: Patrick Doyle Date: Fri, 24 Apr 2009 07:21:58 -0400 Subject: [PATCH 1/8] Teach vvp about -N Added support for the -N option, which causes $stop and ^C to behave like $finish with an exit code of 1. While I was at it, I noticed that the summary line in the man page for vvp was missing a couple of options, so I fixed that. --- vvp/main.cc | 8 +++++++- vvp/stop.cc | 2 ++ vvp/vvp.man | 7 ++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index 539e277d3..76d66a168 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -207,6 +207,7 @@ int main(int argc, char*argv[]) FILE *logfile = 0x0; extern void vpi_set_vlog_info(int, char**); extern bool stop_is_finish; + extern int stop_is_finish_exit_code; #ifdef __MINGW32__ /* In the Windows world, we get the first module path @@ -225,7 +226,7 @@ int main(int argc, char*argv[]) /* For non-interactive runs we do not want to run the interactive * debugger, so make $stop just execute a $finish. */ stop_is_finish = false; - while ((opt = getopt(argc, argv, "+hl:M:m:nsvV")) != EOF) switch (opt) { + while ((opt = getopt(argc, argv, "+hl:M:m:nNsvV")) != EOF) switch (opt) { case 'h': fprintf(stderr, "Usage: vvp [options] input-file [+plusargs...]\n" @@ -236,6 +237,7 @@ int main(int argc, char*argv[]) " -M - Clear VPI module path\n" " -m module Load vpi module.\n" " -n Non-interactive ($stop = $finish).\n" + " -N Same as -n, but exit code is 1 instead of 0\n" " -s $stop right away.\n" " -v Verbose progress messages.\n" " -V Print the version information.\n" ); @@ -257,6 +259,10 @@ int main(int argc, char*argv[]) case 'n': stop_is_finish = true; break; + case 'N': + stop_is_finish = true; + stop_is_finish_exit_code = 1; + break; case 's': schedule_stop(0); break; diff --git a/vvp/stop.cc b/vvp/stop.cc index 889f1b90f..a404f1325 100644 --- a/vvp/stop.cc +++ b/vvp/stop.cc @@ -44,6 +44,7 @@ struct __vpiScope*stop_current_scope = 0; bool stop_is_finish; /* When set, $stop acts like $finish (set in main.cc). */ +int stop_is_finish_exit_code = 0; #ifndef USE_READLINE static char* readline_stub(const char*prompt) @@ -490,6 +491,7 @@ void stop_handler(int rc) /* The user may be running in a non-interactive environment, so * they want $stop and to be the same as $finish. */ if (stop_is_finish) { + vpip_set_return_value(stop_is_finish_exit_code); schedule_finish(0); return; } diff --git a/vvp/vvp.man b/vvp/vvp.man index c680c91cb..d1c0e3c9c 100644 --- a/vvp/vvp.man +++ b/vvp/vvp.man @@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine .SH SYNOPSIS .B vvp -[-sv] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...] +[-nNsvV] [-Mpath] [-mmodule] [-llogfile] inputfile [extended-args...] .SH DESCRIPTION .PP @@ -46,6 +46,11 @@ This flag makes $stop or a a synonym for $finish. It can be used to give the program a more meaningful interface when running in a non-interactive environment. .TP 8 +.B -N +This flag does the same thing as -n, but results in an exit code +of 1 if the stimulation calls $stop. It can be used to indicate a +simulation failure when running a testbench. +.TP 8 .B -s Stop. This will cause the simulation to stop in the beginning, before any events are scheduled. This allows the interactive user to get From d98c925f53dc55bc6d0cdfb8111ae03d1f2bb250 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 9 Jun 2009 13:12:45 -0700 Subject: [PATCH 2/8] Some compiler cleanup and minor memory leak fixes. This patch cleans up some unneeded code. Releases some allocated memory before the compiler quits and fixes a couple minor memory leaks in the compiler and vvp code generator. --- StringHeap.cc | 30 ++++++++++++++++++++++++++++-- StringHeap.h | 3 ++- compiler.h | 1 + config.h.in | 8 +++++++- elaborate.cc | 7 +++---- lexor.lex | 14 ++++++++++++++ main.cc | 37 +++++++++++++++++++++++++++++++++---- parse_misc.h | 2 ++ pform.cc | 1 + sys_funcs.cc | 14 ++++++++++++-- tgt-vvp/draw_mux.c | 3 --- tgt-vvp/draw_net_input.c | 12 ++++++++++-- tgt-vvp/vvp.c | 1 + tgt-vvp/vvp_priv.h | 3 ++- tgt-vvp/vvp_scope.c | 32 ++++++++++---------------------- 15 files changed, 126 insertions(+), 42 deletions(-) diff --git a/StringHeap.cc b/StringHeap.cc index dc2909e69..5ac7006da 100644 --- a/StringHeap.cc +++ b/StringHeap.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2009 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 @@ -25,6 +25,11 @@ # include # include +#ifdef CHECK_WITH_VALGRIND +static char **string_pool = NULL; +static unsigned string_pool_count = 0; +#endif + StringHeap::StringHeap() { cell_base_ = 0; @@ -46,6 +51,12 @@ const char* StringHeap::add(const char*text) unsigned rem = HEAPCELL - cell_ptr_; if (rem < (len+1)) { cell_base_ = (char*)malloc(HEAPCELL); +#ifdef CHECK_WITH_VALGRIND + string_pool_count += 1; + string_pool = (char **) realloc(string_pool, + string_pool_count*sizeof(char **)); + string_pool[string_pool_count-1] = cell_base_; +#endif cell_ptr_ = 0; cell_count_ += 1; assert(cell_base_ != 0); @@ -80,6 +91,22 @@ StringHeapLex::~StringHeapLex() { } +void StringHeapLex::cleanup() +{ +#ifdef CHECK_WITH_VALGRIND + for (unsigned idx = 0 ; idx < string_pool_count ; idx += 1) { + free(string_pool[idx]); + } + free(string_pool); + string_pool = NULL; + string_pool_count = 0; + + for (unsigned idx = 0 ; idx < HASH_SIZE ; idx += 1) { + hash_table_[idx] = 0; + } +#endif +} + unsigned StringHeapLex::add_hit_count() const { return hit_count_; @@ -175,4 +202,3 @@ bool operator < (perm_string a, perm_string b) return false; } - diff --git a/StringHeap.h b/StringHeap.h index a8d76ed7d..664483d83 100644 --- a/StringHeap.h +++ b/StringHeap.h @@ -1,7 +1,7 @@ #ifndef __StringHeap_H #define __StringHeap_H /* - * Copyright (c) 2002-2004 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2009 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 @@ -104,6 +104,7 @@ class StringHeapLex : private StringHeap { unsigned add_count() const; unsigned add_hit_count() const; + void cleanup(); private: enum { HASH_SIZE = 4096 }; diff --git a/compiler.h b/compiler.h index 5ced0b0b0..934344b74 100644 --- a/compiler.h +++ b/compiler.h @@ -202,5 +202,6 @@ struct sfunc_return_type { extern const struct sfunc_return_type* lookup_sys_func(const char*name); extern int load_sys_func_table(const char*path); +extern void cleanup_sys_func_table(); #endif diff --git a/config.h.in b/config.h.in index 7ba02b763..d8f3c9161 100644 --- a/config.h.in +++ b/config.h.in @@ -1,7 +1,7 @@ #ifndef __config_H /* -*- c++ -*- */ #define __config_H /* - * Copyright (c) 2001 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2009 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 @@ -50,4 +50,10 @@ # include #endif +/* + * Define this if you want to compile vvp with memory freeing and + * special valgrind hooks for the memory pools. + */ +# undef CHECK_WITH_VALGRIND + #endif /* __config_H */ diff --git a/elaborate.cc b/elaborate.cc index 3dec83463..935d1b846 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -3786,14 +3786,12 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const /* Do not elaborate specify delay paths if this feature is turned off. */ - if (!gn_specify_blocks_flag) - return; + if (!gn_specify_blocks_flag) return; ivl_assert(*this, conditional || (condition==0)); ndelays = delays.size(); - if (ndelays > 12) - ndelays = 12; + if (ndelays > 12) ndelays = 12; /* Print a warning if we find default and `timescale based * delays in the design, since this is likely an error. */ @@ -4453,6 +4451,7 @@ Design* elaborate(listroots) NetScope *scope = root_elems[i]->scope; rc &= rmod->elaborate(des, scope); + delete root_elems[i]; } if (rc == false) { diff --git a/lexor.lex b/lexor.lex index d62325d87..954a2ab61 100644 --- a/lexor.lex +++ b/lexor.lex @@ -1374,3 +1374,17 @@ void reset_lexor() /* Announce the first file name. */ yylloc.text = set_file_name(strdupnew(vl_file.c_str())); } + +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ +void destroy_lexor() +{ +# ifdef FLEX_SCANNER +# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 +# if defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 + yylex_destroy(); +# endif +# endif +# endif +} diff --git a/main.cc b/main.cc index ad4de617a..c80b2baed 100644 --- a/main.cc +++ b/main.cc @@ -77,7 +77,7 @@ extern "C" const char*optarg; /* Count errors detected in flag processing. */ unsigned flag_errors = 0; -const char*basedir = "."; +const char*basedir = strdup("."); /* * These are the language support control flags. These support which @@ -280,7 +280,7 @@ static void parm_to_flagmap(const string&flag) unsigned off = flag.find('='); if (off > flag.size()) { key = flag; - value = ""; + value = strdup(""); } else { key = flag.substr(0, off); @@ -399,6 +399,7 @@ static void read_iconfig_file(const char*ipath) } if (strcmp(buf, "basedir") == 0) { + free((char *)basedir); basedir = strdup(cp); } else if (strcmp(buf, "debug") == 0) { @@ -472,6 +473,7 @@ static void read_iconfig_file(const char*ipath) flags["VPI_MODULE_LIST"] = vpi_module_list; } else if (strcmp(buf, "out") == 0) { + free((char *)flags["-o"]); flags["-o"] = strdup(cp); } else if (strcmp(buf, "sys_func") == 0) { @@ -529,6 +531,7 @@ static void read_iconfig_file(const char*ipath) } } + fclose(ifile); } extern Design* elaborate(list root); @@ -555,6 +558,30 @@ inline static void times(struct tms *) { } inline static double cycles_diff(struct tms *a, struct tms *b) { return 0; } #endif // ! defined(HAVE_TIMES) +static void EOC_cleanup(void) +{ + cleanup_sys_func_table(); + + for (list::iterator suf = library_suff.begin() ; + suf != library_suff.end() ; suf ++ ) { + free((char *)*suf); + } + library_suff.clear(); + + free((char *) basedir); + free(ivlpp_string); + free(depfile_name); + + for (map::iterator flg = flags.begin() ; + flg != flags.end() ; flg ++ ) { + free((char *)flg->second); + } + flags.clear(); + + lex_strings.cleanup(); + filename_strings.cleanup(); +} + int main(int argc, char*argv[]) { bool help_flag = false; @@ -567,11 +594,11 @@ int main(int argc, char*argv[]) struct tms cycles[5]; - library_suff.push_back(".v"); + library_suff.push_back(strdup(".v")); vpi_module_list = strdup("system"); flags["VPI_MODULE_LIST"] = vpi_module_list; - flags["-o"] = "a.out"; + flags["-o"] = strdup("a.out"); min_typ_max_flag = TYP; min_typ_max_warn = 10; @@ -933,6 +960,8 @@ int main(int argc, char*argv[]) << endl; } + delete des; + EOC_cleanup(); return 0; errors_summary: diff --git a/parse_misc.h b/parse_misc.h index 0a33c6999..8b58aa4e8 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -60,6 +60,8 @@ extern void VLerror(const YYLTYPE&loc, const char*msg); #define yywarn VLwarn extern void VLwarn(const YYLTYPE&loc, const char*msg); +extern void destroy_lexor(); + extern ostream& operator << (ostream&, const YYLTYPE&loc); extern unsigned error_count, warn_count; diff --git a/pform.cc b/pform.cc index 69ca9de36..1e881c80f 100644 --- a/pform.cc +++ b/pform.cc @@ -2170,6 +2170,7 @@ int pform_parse(const char*path, FILE*file) error_count += 1; } + destroy_lexor(); return error_count; } diff --git a/sys_funcs.cc b/sys_funcs.cc index a82ac0b62..4d2002606 100644 --- a/sys_funcs.cc +++ b/sys_funcs.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2009 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 @@ -46,6 +46,16 @@ struct sfunc_return_type_cell : sfunc_return_type { static struct sfunc_return_type_cell*sfunc_stack = 0; +void cleanup_sys_func_table() +{ + struct sfunc_return_type_cell *next, *cur = sfunc_stack; + while (cur) { + next = cur->next; + delete cur; + cur = next; + } +} + const struct sfunc_return_type* lookup_sys_func(const char*name) { /* First, try to find then name in the function stack. */ @@ -186,7 +196,7 @@ int load_sys_func_table(const char*path) fprintf(stderr, "%s:%s: Unknown type: %s\n", path, name, stype); } + fclose(fd); return 0; } - diff --git a/tgt-vvp/draw_mux.c b/tgt-vvp/draw_mux.c index 0ccd46cf7..592afea73 100644 --- a/tgt-vvp/draw_mux.c +++ b/tgt-vvp/draw_mux.c @@ -19,9 +19,6 @@ # include "vvp_priv.h" # include -#ifdef HAVE_MALLOC_H -# include -#endif # include # include diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 5f1394a8e..c65e826f0 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -505,6 +505,16 @@ static char* draw_island_port(ivl_island_t island, /* Omit LPMPART_BI device pin-data(0) drivers. */ # define OMIT_PART_BI_DATA 0x0001 +static ivl_nexus_ptr_t *drivers = 0x0; +static unsigned adrivers = 0; + +void EOC_cleanup_drivers() +{ + free(drivers); + drivers = NULL; + adrivers = 0; +} + char* draw_net_input_x(ivl_nexus_t nex, ivl_nexus_ptr_t omit_ptr, int omit_flags, struct vvp_nexus_data*nex_data) @@ -515,8 +525,6 @@ char* draw_net_input_x(ivl_nexus_t nex, unsigned idx; int level; unsigned ndrivers = 0; - static ivl_nexus_ptr_t *drivers = 0x0; - static unsigned adrivers = 0; const char*resolv_type; diff --git a/tgt-vvp/vvp.c b/tgt-vvp/vvp.c index d8e847a86..8f0cb882e 100644 --- a/tgt-vvp/vvp.c +++ b/tgt-vvp/vvp.c @@ -140,6 +140,7 @@ int target_design(ivl_design_t des) } fclose(vvp_out); + EOC_cleanup_drivers(); return rc + vvp_errors; } diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index fda6bb5ad..f67e94506 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -1,7 +1,7 @@ #ifndef __vvp_priv_H #define __vvp_priv_H /* - * Copyright (c) 2001-2008 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2009 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 @@ -141,6 +141,7 @@ struct vvp_nexus_data { * cache it. */ extern const char* draw_net_input(ivl_nexus_t nex); +void EOC_cleanup_drivers(); /* * See draw_net_input.c for details on draw_net_input_x. (It would be diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 3d6b119ca..160044b1a 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -665,25 +665,12 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) ivl_drive_t str0, str1; int level; - int ninp = ivl_logic_pins(lptr) - 1; - typedef const char*const_charp; - const_charp*input_strings = calloc(ninp, sizeof(const_charp)); - - for (pdx = 0 ; pdx < ninp ; pdx += 1) { - ivl_nexus_t nex = ivl_logic_pin(lptr, pdx+1); - if (nex == 0) { - /* Only UDPs can have unconnected inputs. */ - assert(ivl_logic_type(lptr) == IVL_LO_UDP); - input_strings[pdx] = 0; - } else { - input_strings[pdx] = draw_net_input(nex); - } - } + int ninp; + const char **input_strings; switch (ivl_logic_type(lptr)) { case IVL_LO_UDP: - free(input_strings); draw_udp_in_scope(lptr); return; @@ -706,7 +693,6 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) /* Skip pullup and pulldown objects. Things that have pull objects as inputs will instead generate the appropriate C symbol. */ - free(input_strings); return; case IVL_LO_AND: @@ -1862,12 +1848,14 @@ 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\" %d %d, %s; value=%#g\n", - par, ivl_parameter_basename(par), - ivl_file_table_index(ivl_parameter_file(par)), - ivl_parameter_lineno(par), - draw_Cr_to_string(ivl_expr_dvalue(pex)), - ivl_expr_dvalue(pex)); + { char *res = draw_Cr_to_string(ivl_expr_dvalue(pex)); + fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d, %s; " + "value=%#g\n", par, ivl_parameter_basename(par), + ivl_file_table_index(ivl_parameter_file(par)), + ivl_parameter_lineno(par), res, + ivl_expr_dvalue(pex)); + free(res); + } break; default: fprintf(vvp_out, "; parameter type %d unsupported\n", From 81822c2d50b5ebebf55d5c988ea1b16adf565d54 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 12 Jun 2009 16:21:20 -0700 Subject: [PATCH 3/8] Parse the config declarations and report they will be ignored. This patch adds code to parse config declarations and reports that they are not currently supported and will be ignored. --- parse.y | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/parse.y b/parse.y index d25591943..44f09da35 100644 --- a/parse.y +++ b/parse.y @@ -719,6 +719,7 @@ delay_value_simple description : module | udp_primitive + | config_declaration | nature_declaration | discipline_declaration | KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' @@ -783,6 +784,54 @@ nature_item { delete[] $3; } ; +config_declaration + : K_config IDENTIFIER ';' + K_design lib_cell_identifiers ';' + list_of_config_rule_statements + K_endconfig + { cerr << @1 << ": sorry: config declarations are not supported and " + "will be skipped." << endl; + delete[] $2; + } + ; + +lib_cell_identifiers + : /* The BNF implies this can be blank, but I'm not sure exactly what + * this means. */ + | lib_cell_identifiers lib_cell_id + ; + +list_of_config_rule_statements + : /* config rules are optional. */ + | list_of_config_rule_statements config_rule_statement + ; + +config_rule_statement + : K_default K_liblist list_of_libraries ';' + | K_instance hierarchy_identifier K_liblist list_of_libraries ';' + { delete $2; } + | K_instance hierarchy_identifier K_use lib_cell_id opt_config ';' + { delete $2; } + | K_cell lib_cell_id K_liblist list_of_libraries ';' + | K_cell lib_cell_id K_use lib_cell_id opt_config ';' + ; + +opt_config + : /* The use clause takse an optional :config. */ + | ':' K_config + +lib_cell_id + : IDENTIFIER + { delete[] $1; } + | IDENTIFIER '.' IDENTIFIER + { delete[] $1; delete[] $3; } + ; + +list_of_libraries + : /* A NULL library means use the parents cell library. */ + | list_of_libraries IDENTIFIER + { delete[] $2; } + drive_strength : '(' dr_strength0 ',' dr_strength1 ')' { $$.str0 = $2.str0; From 1d2577b2fdd445f60dfc5431a815d7d92df8c0d5 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 15 Jun 2009 11:11:38 -0700 Subject: [PATCH 4/8] Use a default buffer size of 512 vs 256 for displaying. This patch changes the initial buffer size when displaying results to 512 from 256. This initial buffer is used as the default for the floating point results and failed when %f is given a large, but valid value. To make this even more safe we add the precision to the size to make sure we do not overflow the buffer. --- vpi/sys_display.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 3b8d5d7d3..fbbbcc768 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -263,7 +263,7 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, s_vpi_value value; char *result, *fmtb; unsigned int size; - unsigned int ini_size = 256; /* The initial size of the buffer. */ + unsigned int ini_size = 512; /* The initial size of the buffer. */ /* Make sure the width fits in the initial buffer. */ if (width+1 > ini_size) ini_size = width + 1; @@ -488,12 +488,15 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, /* If the default buffer is too small make it big enough. * - * This size may not always be correct, but if the default - * size is big enough for any practical value then all we - * need to worry about is extra padding and this should work - * correctly for that case, but since this uses the standard - * sprintf() routine we don't know exactly what it will do. */ + * This should always give enough space. The maximum double + * is approximately 1.8*10^308 this means we could need 310 + * characters plus the precision. We'll use 320 to give some + * extra buffer space. The initial buffers size should work + * for most cases, but to be safe we add the precision to + * the maximum size (think %6.300f when passed 1.2*10^308). */ size = width + 1; + if (size < 320) size = 320; + size += prec; if (size > ini_size) result = realloc(result, size*sizeof(char)); sprintf(result, fmtb+1, value.value.real); size = strlen(result) + 1; From e592b525157d94fc93f0374fe6d848c24c6a26e8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 15 Jun 2009 16:50:18 -0700 Subject: [PATCH 5/8] For real expressions evaluate non-real sub-exprs as bits and convert. When processing procedural real expressions we need to evaluate non-real sub-expressions as bit based expressions and then convert the result to a real value. This is particularly import for integer division. --- tgt-vvp/eval_real.c | 87 +++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index 304f8921b..23ebcac4f 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -22,9 +22,6 @@ */ # include "vvp_priv.h" # include -#ifdef HAVE_MALLOC_H -# include -#endif # include # include # include @@ -55,9 +52,6 @@ static int draw_binary_real(ivl_expr_t expr) { int l, r = -1; - /* If the opcode is a vector only opcode then the sub expression - * must not be a real expression, so use vector evaluation and - * then convert that result to a real value. */ switch (ivl_expr_opcode(expr)) { case 'E': case 'N': @@ -70,22 +64,8 @@ static int draw_binary_real(ivl_expr_t expr) case 'A': case 'O': case 'X': - { - struct vector_info vi; - int res; - const char*sign_flag; - - vi = draw_eval_expr(expr, STUFF_OK_XZ); - res = allocate_word(); - sign_flag = ivl_expr_signed(expr)? "/s" : ""; - fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", - sign_flag, res, vi.base, vi.wid); - - fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res); - - clr_vector(vi); - return res; - } + /* These should be caught in draw_eval_real(). */ + assert(0); } l = draw_eval_real(ivl_expr_oper1(expr)); @@ -120,16 +100,20 @@ static int draw_binary_real(ivl_expr_t expr) int lab_out = local_count++; int lab_r = local_count++; /* If r is NaN, the go out and accept l as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out); + fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, + lab_out); /* If l is NaN, the go out and accept r as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r); + fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, + lab_r); /* If l <= r then go out. */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out); + fprintf(vvp_out, " %%cmp/wr %d, %d;\n", r, l); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, + lab_out); /* At this point we know we want r as the result. */ - fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r); + fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, + lab_r, l, r); fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out); break; } @@ -138,16 +122,20 @@ static int draw_binary_real(ivl_expr_t expr) int lab_out = local_count++; int lab_r = local_count++; /* If r is NaN, the go out and accept l as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_out); + fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", r, r); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, + lab_out); /* If l is NaN, the go out and accept r as result. */ - fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, lab_r); + fprintf(vvp_out, " %%cmp/wr %d, %d; Is NaN?\n", l, l); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 4;\n", thread_count, + lab_r); /* if l >= r then go out. */ - fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r); - fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, lab_out); + fprintf(vvp_out, " %%cmp/wr %d, %d;\n", l, r); + fprintf(vvp_out, " %%jmp/0xz T_%d.%d, 5;\n", thread_count, + lab_out); - fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, lab_r, l, r); + fprintf(vvp_out, "T_%d.%d %%mov/wr %d, %d;\n", thread_count, + lab_r, l, r); fprintf(vvp_out, "T_%d.%d ;\n", thread_count, lab_out); break; } @@ -508,8 +496,10 @@ static int draw_unary_real(ivl_expr_t expr) return sub; } - fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub); - fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", ivl_expr_opcode(expr), sub); + fprintf(vvp_out, "; XXXX unary (%c) on sube in %d\n", + ivl_expr_opcode(expr), sub); + fprintf(stderr, "XXXX evaluate unary (%c) on sube in %d\n", + ivl_expr_opcode(expr), sub); return 0; } @@ -517,6 +507,27 @@ int draw_eval_real(ivl_expr_t expr) { int res = 0; + /* If this expression/sub-expression is not real then we need + * to evaluate it as a bit value and then convert the bit based + * result to a real value. This is required to get integer + * division to work correctly. */ + if (ivl_expr_value(expr) != IVL_VT_REAL) { + struct vector_info vi; + int res; + const char*sign_flag; + + vi = draw_eval_expr(expr, STUFF_OK_XZ); + res = allocate_word(); + sign_flag = ivl_expr_signed(expr)? "/s" : ""; + fprintf(vvp_out, " %%ix/get%s %d, %u, %u;\n", sign_flag, res, + vi.base, vi.wid); + + fprintf(vvp_out, " %%cvt/ri %d, %d;\n", res, res); + + clr_vector(vi); + return res; + } + switch (ivl_expr_type(expr)) { case IVL_EX_BINARY: From 95ba25b9be777a99af462d01fb9f8c3df76af8c8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 16 Jun 2009 13:55:30 -0700 Subject: [PATCH 6/8] Make the dumpers match better (VCD, LXT, LXT2). This patch removes some of the unneeded differences in the various dumper routines. This is the start of a complete refactoring, but the first task is to make them as common as possible and this is the start of that. --- vpi/sys_lxt.c | 67 +++++++++++++++++++++++++------------------------- vpi/sys_lxt2.c | 66 ++++++++++++++++++++++++------------------------- vpi/sys_vcd.c | 55 ++++++++++++++++++++--------------------- 3 files changed, 92 insertions(+), 96 deletions(-) diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index a784a4643..eb53451a3 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -17,10 +17,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "sys_priv.h" # include "lxt_write.h" -# include "vcd_priv.h" # include "sys_priv.h" +# include "vcd_priv.h" /* * This file contains the implementations of the LXT related @@ -39,6 +38,29 @@ # include "stringheap.h" +static char *dump_path = NULL; +static struct lt_trace *dump_file = NULL; + +struct vcd_info { + vpiHandle item; + vpiHandle cb; + struct t_vpi_time time; + struct lt_symbol *sym; + struct vcd_info *next; + struct vcd_info *dmp_next; + int scheduled; +}; + + +static struct vcd_info *vcd_list = NULL; +static struct vcd_info *vcd_dmp_list = NULL; +static PLI_UINT64 vcd_cur_time = 0; +static int dump_is_off = 0; +static long dump_limit = 0; +static int dump_is_full = 0; +static int finish_status = 0; + + static enum lxm_optimum_mode_e { LXM_NONE = 0, LXM_SPACE = 1, @@ -140,30 +162,6 @@ static char *create_full_name(const char *name) return n; } - -static char *dump_path = 0; -static struct lt_trace *dump_file = 0; - -struct vcd_info { - vpiHandle item; - vpiHandle cb; - struct t_vpi_time time; - struct lt_symbol *sym; - struct vcd_info *next; - struct vcd_info *dmp_next; - int scheduled; -}; - - -static struct vcd_info*vcd_list = 0; -static struct vcd_info*vcd_dmp_list = 0; -static PLI_UINT64 vcd_cur_time = 0; -static int dump_is_off = 0; -static long dump_limit = 0; -static int dump_is_full = 0; -static int finish_status = 0; - - static void show_this_item(struct vcd_info*info) { s_vpi_value value; @@ -434,7 +432,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) static void *close_dumpfile(void) { lt_close(dump_file); - return (dump_file = NULL); + dump_file = NULL; + return NULL; } static void open_dumpfile(vpiHandle callh) @@ -552,7 +551,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiNet: type = "wire"; if(0){ case vpiMemoryWord: - if (vpi_get(vpiConstantSelect, item) == 0) { + if (vpi_get(vpiConstantSelect, item) == 0) { /* Turn a non-constant array word select into a * constant word select. */ vpiHandle array = vpi_handle(vpiParent, item); @@ -592,12 +591,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lt_symbol_add(dump_file, ident, - 0 /* array rows */, - vpi_get(vpiLeftRange, item), - vpi_get(vpiRightRange, item), - LT_SYM_F_BITS); + info->item = item; + info->sym = lt_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiLeftRange, item), + vpi_get(vpiRightRange, item), + LT_SYM_F_BITS); info->scheduled = 0; cb.time = &info->time; diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index 016aeb8c2..5eddf6ad4 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -17,10 +17,9 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -# include "sys_priv.h" # include "lxt2_write.h" -# include "vcd_priv.h" # include "sys_priv.h" +# include "vcd_priv.h" /* * This file contains the implementations of the LXT2 related @@ -39,6 +38,29 @@ # include "stringheap.h" +static char *dump_path = NULL; +static struct lxt2_wr_trace *dump_file = NULL; + +struct vcd_info { + vpiHandle item; + vpiHandle cb; + struct t_vpi_time time; + struct lxt2_wr_symbol *sym; + struct vcd_info *next; + struct vcd_info *dmp_next; + int scheduled; +}; + + +static struct vcd_info *vcd_list = NULL; +static struct vcd_info *vcd_dmp_list = NULL; +static PLI_UINT64 vcd_cur_time = 0; +static int dump_is_off = 0; +static long dump_limit = 0; +static int dump_is_full = 0; +static int finish_status = 0; + + static enum lxm_optimum_mode_e { LXM_NONE = 0, LXM_SPACE = 1, @@ -141,30 +163,6 @@ static char *create_full_name(const char *name) return n; } - -static char *dump_path = 0; -static struct lxt2_wr_trace *dump_file = 0; - -struct vcd_info { - vpiHandle item; - vpiHandle cb; - struct t_vpi_time time; - struct lxt2_wr_symbol *sym; - struct vcd_info *next; - struct vcd_info *dmp_next; - int scheduled; -}; - - -static struct vcd_info*vcd_list = 0; -static struct vcd_info*vcd_dmp_list = 0; -static PLI_UINT64 vcd_cur_time = 0; -static int dump_is_off = 0; -static long dump_limit = 0; -static int dump_is_full = 0; -static int finish_status = 0; - - static void show_this_item(struct vcd_info*info) { s_vpi_value value; @@ -436,8 +434,8 @@ static PLI_INT32 sys_dumpall_calltf(PLI_BYTE8*name) static void *close_dumpfile(void) { lxt2_wr_close(dump_file); - dump_file = 0; - return 0; + dump_file = NULL; + return NULL; } static void open_dumpfile(vpiHandle callh) @@ -604,12 +602,12 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) info = malloc(sizeof(*info)); info->time.type = vpiSimTime; - info->item = item; - info->sym = lxt2_wr_symbol_add(dump_file, ident, - 0 /* array rows */, - vpi_get(vpiLeftRange, item), - vpi_get(vpiRightRange, item), - LXT2_WR_SYM_F_BITS); + info->item = item; + info->sym = lxt2_wr_symbol_add(dump_file, ident, + 0 /* array rows */, + vpi_get(vpiLeftRange, item), + vpi_get(vpiRightRange, item), + LXT2_WR_SYM_F_BITS); info->scheduled = 0; cb.time = &info->time; diff --git a/vpi/sys_vcd.c b/vpi/sys_vcd.c index 12780d78c..6fbbfd95c 100644 --- a/vpi/sys_vcd.c +++ b/vpi/sys_vcd.c @@ -18,6 +18,7 @@ */ # include "sys_priv.h" +# include "vcd_priv.h" /* * This file contains the implementations of the VCD related @@ -33,10 +34,29 @@ #ifdef HAVE_MALLOC_H # include #endif -# include "vcd_priv.h" -static char*dump_path = 0; -static FILE*dump_file = 0; +static char *dump_path = NULL; +static FILE *dump_file = NULL; + +struct vcd_info { + vpiHandle item; + vpiHandle cb; + struct t_vpi_time time; + const char *ident; + struct vcd_info *next; + struct vcd_info *dmp_next; + int scheduled; +}; + + +static struct vcd_info *vcd_list = NULL; +static struct vcd_info *vcd_dmp_list = NULL; +static PLI_UINT64 vcd_cur_time = 0; +static int dump_is_off = 0; +static long dump_limit = 0; +static int dump_is_full = 0; +static int finish_status = 0; + static const char*units_names[] = { "s", @@ -47,17 +67,6 @@ static const char*units_names[] = { "fs" }; -struct vcd_info { - vpiHandle item; - vpiHandle cb; - struct t_vpi_time time; - const char*ident; - struct vcd_info* next; - struct vcd_info* dmp_next; - int scheduled; -}; - - static char vcdid[8] = "!"; static void gen_new_vcd_id(void) @@ -76,14 +85,6 @@ static void gen_new_vcd_id(void) } } -static struct vcd_info *vcd_list = 0; -static struct vcd_info *vcd_dmp_list = 0; -PLI_UINT64 vcd_cur_time = 0; -static int dump_is_off = 0; -static long dump_limit = 0; -static int dump_is_full = 0; -static int finish_status = 0; - static char *truncate_bitvec(char *s) { char l, r; @@ -480,7 +481,6 @@ static PLI_INT32 sys_dumplimit_calltf(PLI_BYTE8 *name) s_vpi_value val; /* Get the value and set the dump limit. */ - assert(argv); val.format = vpiIntVal; vpi_get_value(vpi_scan(argv), &val); dump_limit = val.value.integer; @@ -520,13 +520,13 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) case vpiNet: type = "wire"; if(0){ case vpiMemoryWord: - if (vpi_get(vpiConstantSelect, item) == 0) { + if (vpi_get(vpiConstantSelect, item) == 0) { /* Turn a non-constant array word select into a * constant word select. */ vpiHandle array = vpi_handle(vpiParent, item); PLI_INT32 index = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, index); - } + } case vpiIntegerVar: case vpiTimeVar: case vpiReg: type = "reg"; } @@ -581,9 +581,8 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) cb.reason = cbValueChange; cb.cb_rtn = variable_cb_1; - - info->next = vcd_list; - info->dmp_next = 0; + info->dmp_next = 0; + info->next = vcd_list; vcd_list = info; info->cb = vpi_register_cb(&cb); From b22dc5f621da6a760ec0c2ebcded66682c899e56 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 16 Jun 2009 15:14:02 -0700 Subject: [PATCH 7/8] Fix real variable array and net array bugs. This patch fixes a number of bugs related to real variable and net arrays. Specifically the following: 1. When iterating over (scanning) a net array start at base index 0 not index 1. 2. Don't fail when iterating over (scanning) a real variable array. 3. Run the array_word_change() routine when a real variable array word is changed. This allows array ports and value change callbacks to work correctly. 4. Update the array_word_change() routine to work with real variable arrays. 5. Update the array port code to support real variable arrays. 6. find_name() needs to also iterate over net array words just like memory array words. 7. Initialize all real array words to 0.0 when the array is created. --- vvp/array.cc | 67 ++++++++++++++++++++++++++++++++----------------- vvp/vpi_priv.cc | 3 ++- vvp/vvp_net.cc | 4 +++ 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/vvp/array.cc b/vvp/array.cc index 270544fce..f7678acca 100644 --- a/vvp/array.cc +++ b/vvp/array.cc @@ -598,13 +598,11 @@ static vpiHandle array_iterator_scan(vpiHandle ref, int) unsigned use_index = obj->next; obj->next += 1; - if (obj->array->nets) - return obj->array->nets[obj->next]; + if (obj->array->nets) return obj->array->nets[use_index]; - assert(obj->array->vals4); + assert(obj->array->vals4 || obj->array->valsr); - if (obj->array->vals_words == 0) - array_make_vals_words(obj->array); + if (obj->array->vals_words == 0) array_make_vals_words(obj->array); return &(obj->array->vals_words[use_index].as_word); } @@ -850,6 +848,7 @@ void array_set_word(vvp_array_t arr, unsigned address, double val) assert(arr->nets == 0); arr->valsr->set_word(address, val); + array_word_change(arr, address); } vvp_vector4_t array_get_word(vvp_array_t arr, unsigned address) @@ -1144,9 +1143,12 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit case 0: // Address input addr_valid_flag = vector4_to_value(bit, addr_); - if (! addr_valid_flag) - addr_ = arr_->array_count; - vvp_send_vec4(port.ptr()->out, array_get_word(arr_,addr_), 0); + if (! addr_valid_flag) addr_ = arr_->array_count; + if (vpi_array_is_real(arr_)) { + vvp_send_real(net_->out, array_get_word_r(arr_, addr_), 0); + } else { + vvp_send_vec4(net_->out, array_get_word(arr_, addr_), 0); + } break; default: @@ -1157,11 +1159,13 @@ void vvp_fun_arrayport_sa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit void vvp_fun_arrayport_sa::check_word_change(unsigned long addr) { - if (addr != addr_) - return; + if (addr != addr_) return; - vvp_vector4_t bit = array_get_word(arr_, addr_); - vvp_send_vec4(net_->out, bit, 0); + if (vpi_array_is_real(arr_)) { + vvp_send_real(net_->out, array_get_word_r(arr_, addr_), 0); + } else { + vvp_send_vec4(net_->out, array_get_word(arr_, addr_), 0); + } } class vvp_fun_arrayport_aa : public vvp_fun_arrayport, public automatic_hooks_s { @@ -1243,10 +1247,16 @@ void vvp_fun_arrayport_aa::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit case 0: // Address input addr_valid_flag = vector4_to_value(bit, *addr); - if (! addr_valid_flag) - *addr = arr_->array_count; - vvp_send_vec4(port.ptr()->out, array_get_word(arr_,*addr), - context); + if (! addr_valid_flag) *addr = arr_->array_count; + if (vpi_array_is_real(arr_)) { + vvp_send_real(port.ptr()->out, + array_get_word_r(arr_, *addr), + context); + } else { + vvp_send_vec4(port.ptr()->out, + array_get_word(arr_, *addr), + context); + } break; default: @@ -1270,8 +1280,13 @@ void vvp_fun_arrayport_aa::check_word_change(unsigned long addr) if (addr != *port_addr) return; - vvp_vector4_t bit = array_get_word(arr_, addr); - vvp_send_vec4(net_->out, bit, vthread_get_wt_context()); + if (vpi_array_is_real(arr_)) { + vvp_send_real(net_->out, array_get_word_r(arr_, addr), + vthread_get_wt_context()); + } else { + vvp_send_vec4(net_->out, array_get_word(arr_, addr), + vthread_get_wt_context()); + } } static void array_attach_port(vvp_array_t array, vvp_fun_arrayport*fun) @@ -1307,11 +1322,17 @@ void array_word_change(vvp_array_t array, unsigned long addr) } if (cur->cb_data.cb_rtn != 0) { - if (cur->cb_data.value) - vpip_vec4_get_value(array->vals4->get_word(addr), - array->vals_width, - array->signed_flag, - cur->cb_data.value); + if (cur->cb_data.value) { + if (vpi_array_is_real(array)) { + vpip_real_get_value(array->valsr->get_word(addr), + cur->cb_data.value); + } else { + vpip_vec4_get_value(array->vals4->get_word(addr), + array->vals_width, + array->signed_flag, + cur->cb_data.value); + } + } callback_execute(cur); prev = cur; diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 82f82ae4a..74acb2c13 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1002,7 +1002,8 @@ static vpiHandle find_name(const char *name, vpiHandle handle) if (!strcmp(name, nm)) { rtn = ref->intern[i]; break; - } else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory) { + } else if (vpi_get(vpiType, ref->intern[i]) == vpiMemory || + vpi_get(vpiType, ref->intern[i]) == vpiNetArray) { /* We need to iterate on the words */ vpiHandle word_i, word_h; word_i = vpi_iterate(vpiMemoryWord, ref->intern[i]); diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index f4792eebf..825b8ed1f 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1344,6 +1344,10 @@ vvp_realarray_t::vvp_realarray_t(unsigned wor) : words_(wor) { array_ = new double[words_]; + // Real array words have a default value of zero. + for (unsigned idx = 0 ; idx < words_; idx += 1) { + array_[idx] = 0.0; + } } vvp_realarray_t::~vvp_realarray_t() From 291dc5265194ded56674d6b17d6a9d2ecf791128 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 19 Jun 2009 10:11:57 -0700 Subject: [PATCH 8/8] Print a warning for an implicit sensitivity list that has selects. An implicit sensitivity list that has selects (bit, part, indexed part or array) will include more than the user expects so print a warning to let them know what will happen. Other simulators have the same behavior, but I believe this is incorrect and needs to be fixed to only include the appropriate parts. The warnings can go when we fix this functionality, but we need them now to warn the user that they may not be getting what they expect. One other simulator warns for array selects. This patch also adds the array index to the sensitivity list. --- net_nex_input.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/net_nex_input.cc b/net_nex_input.cc index aeddc73eb..a1f81829c 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -114,6 +114,11 @@ NexusSet* NetESelect::nex_input(bool rem_out) } result->add(*tmp); delete tmp; + /* See the comment for NetESignal below. */ + if (base_) { + cerr << get_fileline() << ": warning: @* is sensitive to all " + "bits in '" << *expr_ << "'." << endl; + } return result; } @@ -133,7 +138,23 @@ NexusSet* NetESFunc::nex_input(bool rem_out) NexusSet* NetESignal::nex_input(bool rem_out) { + /* + * This is not what I would expect for the various selects (bit, + * part, index, array). This code adds all the bits/array words + * instead of building the appropriate select and then using it + * as the trigger. Other simulators also add everything. + */ NexusSet*result = new NexusSet; + /* If we have an array index add it to the sensitivity list. */ + if (word_) { + NexusSet*tmp; + tmp = word_->nex_input(rem_out); + result->add(*tmp); + delete tmp; + cerr << get_fileline() << ": warning: @* is sensitive to all " + << net_->array_count() << " words in array '" + << name() << "'." << endl; + } for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1) result->add(net_->pin(idx).nexus());