From fb2cd4775f20876c2976085560f6df9de40b4508 Mon Sep 17 00:00:00 2001 From: Daniel Andrade Date: Sun, 4 Sep 2016 00:51:57 -0300 Subject: [PATCH 001/138] Added missing compilation instruction on README --- README.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index f47d03f5f..8d5f1bbb9 100644 --- a/README.txt +++ b/README.txt @@ -77,7 +77,8 @@ the configure scripts. Unpack the tar-ball and cd into the verilog-######### directory (presumably that is how you got to this README) and compile the source with the commands: - + + sh autoconf.sh ./configure make From 6e5558e67d35f573fa4c943989fddd1631fce170 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 29 Dec 2016 09:39:45 -0800 Subject: [PATCH 002/138] Trivial fixes to pform dumps. --- pform_dump.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pform_dump.cc b/pform_dump.cc index 07b9cbf59..6d2d3a9cd 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -627,10 +627,10 @@ void PGBuiltin::dump(ostream&out, unsigned ind) const out << "bufif1 "; break; case PGBuiltin::NOTIF0: - out << "bufif0 "; + out << "notif0 "; break; case PGBuiltin::NOTIF1: - out << "bufif1 "; + out << "notif1 "; break; case PGBuiltin::NAND: out << "nand "; From c79df7c44b3312b8fbda70e21f1b663f964fe45f Mon Sep 17 00:00:00 2001 From: Johann Klammer Date: Tue, 27 Dec 2016 14:51:41 +0100 Subject: [PATCH 003/138] fix failing VPI callbacks the vpip_cur_task was left dangling --- vvp/vpi_callback.cc | 2 ++ vvp/vpi_tasks.cc | 1 + 2 files changed, 3 insertions(+) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index b9f9b1e60..3ee85f2f4 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -316,7 +316,9 @@ void sync_cb::run_run() if (cur->cb_data.cb_rtn != 0) { assert(vpi_mode_flag == VPI_MODE_NONE); vpi_mode_flag = sync_flag? VPI_MODE_ROSYNC : VPI_MODE_RWSYNC; + vpip_cur_task = dynamic_cast<__vpiSysTaskCall*>(cur->cb_data.obj); (cur->cb_data.cb_rtn)(&cur->cb_data); + vpip_cur_task = 0; vpi_mode_flag = VPI_MODE_NONE; } diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index 31368b391..b0aa19bfa 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -978,6 +978,7 @@ void vpip_execute_vpi_call(vthread_t thr, vpiHandle ref) else if (sysfunc_vec4*func_vec4 = dynamic_cast(ref)) { vthread_push_vec4(thr, func_vec4->return_value()); } + vpip_cur_task = 0; } /* From 3d9e777ae57b34436b466b0b49e7b6593f4f5b58 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 8 Jan 2017 20:44:17 -0800 Subject: [PATCH 004/138] Allocate the correct amount of memory when escaping a string --- vpi/sys_priv.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index 1d5e977bb..b8f333ebe 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2017 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 @@ -37,17 +37,17 @@ PLI_UINT64 timerec_to_time64(const struct t_vpi_time*timerec) char *as_escaped(char *arg) { - unsigned idx, cur, cnt, len = strlen(arg); - char *res = (char *) malloc(sizeof(char *) * len); + unsigned idx, cur, cnt, len = strlen(arg) + 1; + char *res = (char *) malloc(sizeof(char) * len); cur = 0; - cnt = len; + cnt = len - 1; for (idx = 0; idx < cnt; idx++) { if (isprint((int)arg[idx])) { res[cur] = arg[idx]; cur += 1; } else { len += 3; - res = (char *) realloc(res, sizeof(char *) * len); + res = (char *) realloc(res, sizeof(char) * len); sprintf(&(res[cur]), "\\%03o", arg[idx]); cur += 4; } From 221084d838f3cd85ff77046c28a3fe2906e5c040 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 10 Jan 2017 11:38:38 -0800 Subject: [PATCH 005/138] Sorry message for procedural assertion statements. --- parse.y | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/parse.y b/parse.y index 86e075a47..34d9064c3 100644 --- a/parse.y +++ b/parse.y @@ -655,6 +655,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type statement statement_item statement_or_null %type compressed_statement %type loop_statement for_step jump_statement +%type procedural_assertion_statement %type statement_or_null_list statement_or_null_list_opt %type analog_statement @@ -1815,6 +1816,21 @@ property_expr /* IEEE1800-2012 A.2.10 */ : expression ; +procedural_assertion_statement /* IEEE1800-2012 A.6.10 */ + : K_assert '(' expression ')' statement %prec less_than_K_else + { yyerror(@1, "sorry: Simple immediate assertion statements not implemented."); + $$ = 0; + } + | K_assert '(' expression ')' K_else statement + { yyerror(@1, "sorry: Simple immediate assertion statements not implemented."); + $$ = 0; + } + | K_assert '(' expression ')' statement K_else statement + { yyerror(@1, "sorry: Simple immediate assertion statements not implemented."); + $$ = 0; + } + ; + /* The property_qualifier rule is as literally described in the LRM, but the use is usually as { property_qualifier }, which is implemented by the property_qualifier_opt rule below. */ @@ -6241,6 +6257,8 @@ statement_item /* This is roughly statement_item in the LRM */ $$ = tmp; } + | procedural_assertion_statement { $$ = $1; } + | loop_statement { $$ = $1; } | jump_statement { $$ = $1; } From 4e2ba29dc6f49b5b505e277ff2f0433666d9d007 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 29 Jan 2017 09:32:14 +0000 Subject: [PATCH 006/138] Add library search path option to iverilog-vpi (GitHub issue #145). --- iverilog-vpi.man.in | 9 +++++++-- iverilog-vpi.sh | 6 +++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/iverilog-vpi.man.in b/iverilog-vpi.man.in index 2f5f090b0..bd8f7a930 100644 --- a/iverilog-vpi.man.in +++ b/iverilog-vpi.man.in @@ -1,4 +1,4 @@ -.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%n%E" +.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E" .SH NAME iverilog-vpi - Compile front end for VPI modules @@ -26,6 +26,11 @@ becomes \fIfoo.vpi\fP. Include the named library in the link of the VPI module. This allows VPI modules to further reference external libraries. +.TP 8 +.B -L\fIdirectory\fP +Add \fIdirectory\fP to the list of directories that will be searched +for library files. + .TP 8 .B -I\fIdirectory\fP Add \fIdirectory\fP to the list of directories that will be searched @@ -115,7 +120,7 @@ iverilog(1), vvp(1), .SH COPYRIGHT .nf -Copyright \(co 2002\-2015 Stephen Williams +Copyright \(co 2002\-2017 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index d1554d420..3b918d7f0 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -35,6 +35,7 @@ CCSRC= CXSRC= OBJ= LIB= +LIBDIR= OUT= INCOPT= DEFS= @@ -81,6 +82,9 @@ do -l*) LIB="$LIB $parm" ;; + -L*) LIBDIR="$LIBDIR $parm" + ;; + -I*) INCOPT="$INCOPT $parm" ;; @@ -148,4 +152,4 @@ then fi echo "Making $OUT from $OBJ..." -exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS +exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS From 8f6f999ea721d42ddba1bd78d48fd0534a983038 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 29 Jan 2017 10:47:54 +0000 Subject: [PATCH 007/138] Fix for GitHub issue #142 - assertion failure when parameter expression contains undefined variable. --- elab_expr.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/elab_expr.cc b/elab_expr.cc index 453f91b02..b15d1aecf 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -5685,7 +5685,6 @@ unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode) } else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) { expr_type_ = IVL_VT_LOGIC; } else { - ivl_assert(*this, tru_type == fal_type); expr_type_ = tru_type; } if (expr_type_ == IVL_VT_REAL) { From 3c91630b538a3f35d07131dbd2ad356c0f311bb4 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 29 Jan 2017 20:13:01 +0000 Subject: [PATCH 008/138] Improved error checking for defparam values supplied on the command line. Fixes GitHub issue #139 plus various assertion failures when invalid values are specified. --- pform.cc | 236 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 160 insertions(+), 76 deletions(-) diff --git a/pform.cc b/pform.cc index 1cf58e4fa..329b8a797 100644 --- a/pform.cc +++ b/pform.cc @@ -40,6 +40,7 @@ # include # include # include +# include # include "ivl_assert.h" # include "ivl_alloc.h" @@ -86,6 +87,42 @@ std::string vlltype::get_fileline() const } +static bool is_hex_digit_str(const char *str) +{ + while (*str) { + if (!isxdigit(*str)) return false; + str++; + } + return true; +} + +static bool is_dec_digit_str(const char *str) +{ + while (*str) { + if (!isdigit(*str)) return false; + str++; + } + return true; +} + +static bool is_oct_digit_str(const char *str) +{ + while (*str) { + if (*str < '0' || *str > '7') return false; + str++; + } + return true; +} + +static bool is_bin_digit_str(const char *str) +{ + while (*str) { + if (*str != '0' && *str != '1') return false; + str++; + } + return true; +} + /* * Parse configuration file with format =, where key * is the hierarchical name of a valid parameter name, and value @@ -152,90 +189,137 @@ void parm_to_defparam_list(const string¶m) ptr = strchr(nkey, '.'); } name.push_back(name_component_t(lex_strings.make(nkey))); + free(key); // Resolve value to PExpr class. Should support all kind of constant // format including based number, dec number, real number and string. - if (*value == '"') { // string type - char *buf = strdup (value); - char *buf_ptr = buf+1; - // Parse until another '"' or '\0' - while (*buf_ptr != '"' && *buf_ptr != '\0') { - buf_ptr++; - // Check for escape, especially '\"', which does not mean the - // end of string. - if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0') - buf_ptr += 2; - } - if (*buf_ptr == '\0') // String end without '"' - cerr << ": error: missing close quote of string for defparam: " << name << endl; - else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape - cerr << buf_ptr << endl; - cerr << ": error: \'\"\' appears within string value for defparam: " << name - << ". Ignore characters after \'\"\'" << endl; - } - *buf_ptr = '\0'; - buf_ptr = buf+1; - // Remember to use 'new' to allocate string for PEString - // because 'delete' is used by its destructor. - char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); - PExpr* ndec = new PEString(nchar); + // Is it a string? + if (*value == '"') { + char *buf = strdup (value); + char *buf_ptr = buf+1; + // Parse until another '"' or '\0' + while (*buf_ptr != '"' && *buf_ptr != '\0') { + buf_ptr++; + // Check for escape, especially '\"', which does not mean the + // end of string. + if (*buf_ptr == '\\' && *(buf_ptr+1) != '\0') + buf_ptr += 2; + } + if (*buf_ptr == '\0') // String end without '"' + cerr << ": error: missing close quote of string for defparam: " << name << endl; + else if (*(buf_ptr+1) != 0) { // '"' appears within string with no escape + cerr << buf_ptr << endl; + cerr << ": error: \'\"\' appears within string value for defparam: " << name + << ". Ignore characters after \'\"\'" << endl; + } + + *buf_ptr = '\0'; + buf_ptr = buf+1; + // Remember to use 'new' to allocate string for PEString + // because 'delete' is used by its destructor. + char *nchar = strcpy(new char [strlen(buf_ptr)+1], buf_ptr); + PExpr* ndec = new PEString(nchar); Module::user_defparms.push_back( make_pair(name, ndec) ); - free(buf); + free(buf); + free(value); + return; } - else { // number type - char *num = strchr(value, '\''); - if (num != 0) { - verinum *val; - // BASED_NUMBER, something like - scope.parameter='b11 - // make sure to check 'h' first because 'b'&'d' may be included - // in hex format - if (strchr(num, 'h') || strchr(num, 'H')) - val = make_unsized_hex(num); - else if (strchr(num, 'd') || strchr(num, 'D')) - if (strchr(num, 'x') || strchr(num, 'X') || strchr(num, 'z') || strchr(num, 'Z')) - val = make_undef_highz_dec(num); - else - val = make_unsized_dec(num); - else if (strchr(num, 'b') || strchr(num, 'B')) { - val = make_unsized_binary(num); - } - else if (strchr(num, 'o') || strchr(num, 'O')) - val = make_unsized_octal(num); - else { - cerr << ": error: value specify error for defparam: " << name << endl; - free(key); - free(value); - return; - } - // BASED_NUMBER with size, something like - scope.parameter=2'b11 - if (num != value) { - *num = 0; - verinum *siz = make_unsized_dec(value); - val = pform_verinum_with_size(siz, val, "", 0); - } - - PExpr* ndec = new PENumber(val); - Module::user_defparms.push_back( make_pair(name, ndec) ); - - } - else { - // REALTIME, something like - scope.parameter=1.22 or scope.parameter=1e2 - if (strchr(value, '.') || strchr(value, 'e') || strchr(value, 'E')) { - verireal *val = new verireal(value); - PExpr* nreal = new PEFNumber(val); - Module::user_defparms.push_back( make_pair(name, nreal) ); - } - else { - // DEC_NUMBER, something like - scope.parameter=3 - verinum *val = make_unsized_dec(value); - PExpr* ndec = new PENumber(val); - Module::user_defparms.push_back( make_pair(name, ndec) ); - } - } + // Is it a based number? + char *num = strchr(value, '\''); + if (num != 0) { + verinum *val; + const char *base = num + 1; + if (*base == 's' || *base == 'S') + base++; + switch (*base) { + case 'h': + case 'H': + if (is_hex_digit_str(base+1)) { + val = make_unsized_hex(num); + } else { + cerr << ": error: invalid digit in hex value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'd': + case 'D': + if (is_dec_digit_str(base+1)) { + val = make_unsized_dec(num); + } else { + cerr << ": error: invalid digit in decimal value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'o': + case 'O': + if (is_oct_digit_str(base+1)) { + val = make_unsized_octal(num); + } else { + cerr << ": error: invalid digit in octal value specified for defparam: " << name << endl; + free(value); + return; + } + break; + case 'b': + case 'B': + if (is_bin_digit_str(base+1)) { + val = make_unsized_binary(num); + } else { + cerr << ": error: invalid digit in binary value specified for defparam: " << name << endl; + free(value); + return; + } + break; + default: + cerr << ": error: invalid numeric base specified for defparam: " << name << endl; + free(value); + return; + } + if (num != value) { // based number with size + *num = 0; + if (is_dec_digit_str(value)) { + verinum *siz = make_unsized_dec(value); + val = pform_verinum_with_size(siz, val, "", 0); + } else { + cerr << ": error: invalid size for value specified for defparam: " << name << endl; + free(value); + return; + } + } + PExpr* ndec = new PENumber(val); + Module::user_defparms.push_back( make_pair(name, ndec) ); + free(value); + return; } - free(key); + + // Is it a decimal number? + num = (value[0] == '-') ? value + 1 : value; + if (is_dec_digit_str(num)) { + verinum *val = make_unsized_dec(num); + if (value[0] == '-') *val = -(*val); + PExpr* ndec = new PENumber(val); + Module::user_defparms.push_back( make_pair(name, ndec) ); + free(value); + return; + } + + // Is it a real number? + char *end = 0; + double rval = strtod(value, &end); + if (end != value && *end == 0) { + verireal *val = new verireal(rval); + PExpr* nreal = new PEFNumber(val); + Module::user_defparms.push_back( make_pair(name, nreal) ); + free(value); + return; + } + + // None of the above. + cerr << ": error: invalid value specified for defparam: " << name << endl; free(value); } From 8bccbe7cb5a629f5a0f41ff8beba5af987356a9e Mon Sep 17 00:00:00 2001 From: Johann Klammer Date: Sat, 11 Feb 2017 20:47:01 +0100 Subject: [PATCH 009/138] fix for const eval --- elab_scope.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elab_scope.cc b/elab_scope.cc index 73834249c..182518bb0 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1169,7 +1169,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) container->genvar_tmp_val = genvar; delete step; delete test_ex; - test_ex = elab_and_eval(des, container, loop_test, -1); + test_ex = elab_and_eval(des, container, loop_test, -1, true); test = dynamic_cast(test_ex); assert(test); } From bef04508f249925bb6e13f741d1ba03f612d7db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Arroyo=20Torrens?= Date: Fri, 24 Feb 2017 10:43:30 +0100 Subject: [PATCH 010/138] Fix x86_64-w64-mingw32 build: undefined ___strtod --- aclocal.m4 | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aclocal.m4 b/aclocal.m4 index f44632fe2..830553165 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -223,8 +223,10 @@ AC_SUBST(strip_dynamic) # ------------- AC_DEFUN([AX_C99_STRTOD], [# On MinGW we need to jump through hoops to get a C99 compliant strtod(). - # mingw-w64 doesn't need this, and the 64-bit version doesn't support it. case "${host}" in + x86_64-w64-mingw32) + LDFLAGS+=" -Wl,--undefined=__strtod,--wrap,strtod,--defsym,___wrap_strtod=__strtod" + ;; *-*-mingw32) LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod" ;; From cfd3b893be43b3a4e06febeb0a3e1bc2ad9bfdda Mon Sep 17 00:00:00 2001 From: Vamsi Vytla Date: Thu, 16 Mar 2017 07:41:10 -0700 Subject: [PATCH 011/138] Add support to handle attributes at module instantiation sites. (* my_fancy_attribute *) foobar1 foobar (clk(clk), rst(rst) ...); - Modifies PGModule to hold the attribute map (can be verified with pform_dump) - pform_make_modgate(s) bind the attributes from the parser to the above map - The attributes from PGModule are inserted into the NetScope of that module PGModule::elaborate_scope_mod_instances_ - Currently these attributes automatically make it into netlist - These attributes are accessible via ivl_scope_attr_cnt and ivl_scope_attr_val from ivl_target.h --- PGate.h | 2 ++ elab_scope.cc | 8 ++++++++ parse.y | 3 +-- pform.cc | 17 +++++++++++------ pform.h | 3 ++- pform_dump.cc | 1 + 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/PGate.h b/PGate.h index 5d9bde9f2..ee6f10f79 100644 --- a/PGate.h +++ b/PGate.h @@ -217,6 +217,8 @@ class PGModule : public PGate { // method to pass the range to the pform. void set_range(PExpr*msb, PExpr*lsb); + map attributes; + virtual void dump(ostream&out, unsigned ind =4) const; virtual void elaborate(Design*, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*sc) const; diff --git a/elab_scope.cc b/elab_scope.cc index 182518bb0..9796ce7fc 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1728,6 +1728,10 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s << "." << endl; } + struct attrib_list_t*attrib_list; + unsigned attrib_list_n = 0; + attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc); + // Run through the module instances, and make scopes out of // them. Also do parameter overrides that are done on the // instantiation line. @@ -1762,6 +1766,9 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s get_lineno(), mod->get_lineno()); my_scope->set_module_name(mod->mod_name()); + for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1) + my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val); + instances[idx] = my_scope; set_scope_timescale(des, my_scope, mod); @@ -1820,6 +1827,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s mod->elaborate_scope(des, my_scope, replace); } + delete[]attrib_list; /* Stash the instance array of scopes into the parent scope. Later elaboration passes will use this vector to diff --git a/parse.y b/parse.y index 34d9064c3..882509da8 100644 --- a/parse.y +++ b/parse.y @@ -4855,9 +4855,8 @@ module_item | attribute_list_opt IDENTIFIER parameter_value_opt gate_instance_list ';' { perm_string tmp1 = lex_strings.make($2); - pform_make_modgates(@2, tmp1, $3, $4); + pform_make_modgates(@2, tmp1, $3, $4, $1); delete[]$2; - if ($1) delete $1; } | attribute_list_opt diff --git a/pform.cc b/pform.cc index 329b8a797..9bfa23b8b 100644 --- a/pform.cc +++ b/pform.cc @@ -2213,7 +2213,8 @@ static void pform_make_modgate(perm_string type, struct parmvalue_t*overrides, list*wires, PExpr*msb, PExpr*lsb, - const char*fn, unsigned ln) + const char*fn, unsigned ln, + std::list*attr) { for (list::iterator idx = wires->begin() ; idx != wires->end() ; ++idx) { @@ -2244,6 +2245,7 @@ static void pform_make_modgate(perm_string type, pform_cur_generate->add_gate(cur); else pform_cur_module.front()->add_gate(cur); + pform_bind_attributes(cur->attributes, attr); } static void pform_make_modgate(perm_string type, @@ -2251,7 +2253,8 @@ static void pform_make_modgate(perm_string type, struct parmvalue_t*overrides, list*bind, PExpr*msb, PExpr*lsb, - const char*fn, unsigned ln) + const char*fn, unsigned ln, + std::list*attr) { unsigned npins = bind->size(); named*pins = new named[npins]; @@ -2288,12 +2291,14 @@ static void pform_make_modgate(perm_string type, pform_cur_generate->add_gate(cur); else pform_cur_module.front()->add_gate(cur); + pform_bind_attributes(cur->attributes, attr); } void pform_make_modgates(const struct vlltype&loc, perm_string type, struct parmvalue_t*overrides, - svector*gates) + svector*gates, + std::list*attr) { assert(! pform_cur_module.empty()); if (pform_cur_module.front()->program_block) { @@ -2315,7 +2320,7 @@ void pform_make_modgates(const struct vlltype&loc, pform_make_modgate(type, cur_name, overrides, cur.parms_by_name, cur.range.first, cur.range.second, - cur.file, cur.lineno); + cur.file, cur.lineno, attr); } else if (cur.parms) { @@ -2329,14 +2334,14 @@ void pform_make_modgates(const struct vlltype&loc, pform_make_modgate(type, cur_name, overrides, cur.parms, cur.range.first, cur.range.second, - cur.file, cur.lineno); + cur.file, cur.lineno, attr); } else { list*wires = new list; pform_make_modgate(type, cur_name, overrides, wires, cur.range.first, cur.range.second, - cur.file, cur.lineno); + cur.file, cur.lineno, attr); } } diff --git a/pform.h b/pform.h index e9d553127..8666386eb 100644 --- a/pform.h +++ b/pform.h @@ -478,7 +478,8 @@ extern void pform_makegates(const struct vlltype&loc, extern void pform_make_modgates(const struct vlltype&loc, perm_string type, struct parmvalue_t*overrides, - svector*gates); + svector*gates, + list*attr); /* Make a continuous assignment node, with optional bit- or part- select. */ extern void pform_make_pgassign_list(list*alist, diff --git a/pform_dump.cc b/pform_dump.cc index 6d2d3a9cd..de03de673 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -729,6 +729,7 @@ void PGModule::dump(ostream&out, unsigned ind) const dump_pins(out); } out << ");" << endl; + dump_attributes_map(out, attributes, 8); } void Statement::dump(ostream&out, unsigned ind) const From c967ed238ce45d141e1baa16af34237cc297c55e Mon Sep 17 00:00:00 2001 From: Mikael Tuomisalo Date: Tue, 21 Mar 2017 17:34:44 +0200 Subject: [PATCH 012/138] Added option for ignoring errors about missing modules --- compiler.h | 3 +++ driver/main.c | 12 ++++++++++-- elaborate.cc | 14 +++++++++----- main.cc | 12 ++++++++++++ 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/compiler.h b/compiler.h index b847b6f05..eae1ec460 100644 --- a/compiler.h +++ b/compiler.h @@ -117,6 +117,9 @@ extern bool debug_emit; extern bool debug_synth2; extern bool debug_optimizer; +/* Ignore errors about missing modules */ +extern bool ignore_missing_modules; + /* Control evaluation of functions at compile time: * 0 = only for functions in constant expressions * 1 = only for automatic functions diff --git a/driver/main.c b/driver/main.c index a15235a98..0fe8130d1 100644 --- a/driver/main.c +++ b/driver/main.c @@ -38,7 +38,7 @@ const char NOTICE[] = ; const char HELP[] = -"Usage: iverilog [-ESvV] [-B base] [-c cmdfile|-f cmdfile]\n" +"Usage: iverilog [-EiSvV] [-B base] [-c cmdfile|-f cmdfile]\n" " [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g]\n" " [-D macro[=defn]] [-I includedir]\n" " [-M [mode=]depfile] [-m module]\n" @@ -140,6 +140,9 @@ int gen_relative_include = 0; char warning_flags[16] = "n"; +/* Boolean: true means ignore errors about missing modules */ +int ignore_missing_modules = 0; + unsigned integer_width = 32; unsigned width_cap = 65536; @@ -987,7 +990,7 @@ int main(int argc, char **argv) } } - while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) { + while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iM:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) { switch (opt) { case 'B': @@ -1042,6 +1045,10 @@ int main(int argc, char **argv) process_include_dir(optarg); break; + case 'i': + ignore_missing_modules = 1; + break; + case 'l': process_file_name(optarg, 1); break; @@ -1184,6 +1191,7 @@ int main(int argc, char **argv) fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams); fprintf(iconfig_file, "generation:%s\n", gen_icarus); fprintf(iconfig_file, "warnings:%s\n", warning_flags); + fprintf(iconfig_file, "ignore_missing_modules:%s\n", ignore_missing_modules ? "true" : "false"); fprintf(iconfig_file, "out:%s\n", opath); if (depfile) { fprintf(iconfig_file, "depfile:%s\n", depfile); diff --git a/elaborate.cc b/elaborate.cc index a4245e67b..82b90fc7d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2204,8 +2204,10 @@ void PGModule::elaborate(Design*des, NetScope*scope) const return; } - cerr << get_fileline() << ": internal error: Unknown module type: " << - type_ << endl; + if (!ignore_missing_modules) { + cerr << get_fileline() << ": internal error: Unknown module type: " << + type_ << endl; + } } void PGModule::elaborate_scope(Design*des, NetScope*sc) const @@ -2249,9 +2251,11 @@ void PGModule::elaborate_scope(Design*des, NetScope*sc) const // Not a module or primitive that I know about or can find by // any means, so give up. - cerr << get_fileline() << ": error: Unknown module type: " << type_ << endl; - missing_modules[type_] += 1; - des->errors += 1; + if (!ignore_missing_modules) { + cerr << get_fileline() << ": error: Unknown module type: " << type_ << endl; + missing_modules[type_] += 1; + des->errors += 1; + } } diff --git a/main.cc b/main.cc index 366ca150b..e814b7466 100644 --- a/main.cc +++ b/main.cc @@ -164,6 +164,11 @@ bool warn_sens_entire_arr = false; bool warn_anachronisms = false; bool warn_floating_nets = false; +/* + * Ignore errors about missing modules + */ +bool ignore_missing_modules = false; + /* * Debug message class flags. */ @@ -570,6 +575,9 @@ static bool set_default_timescale(const char*ts_string) * * warnings: * Warning flag letters. + * + * ignore_missing_modules: + * true to ignore errors about missing modules */ bool had_timescale = false; static void read_iconfig_file(const char*ipath) @@ -720,6 +728,10 @@ static void read_iconfig_file(const char*ipath) break; } + } else if (strcmp(buf, "ignore_missing_modules") == 0) { + if (strcmp(cp, "true") == 0) + ignore_missing_modules = true; + } else if (strcmp(buf, "-y") == 0) { build_library_index(cp, CASE_SENSITIVE); From cac53884510583c9f441a2cdc574bd939af8cb2d Mon Sep 17 00:00:00 2001 From: 8tab Date: Sun, 9 Apr 2017 23:18:49 +0200 Subject: [PATCH 013/138] Return if unable to open dependencies file Return and print an error if iverilog is unable to open dependencies file. User can pass e.g path to existing directory in '-M' option, which makes fopen to return NULL followed by crash in fclose. --- driver/main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/driver/main.c b/driver/main.c index 0fe8130d1..03054ef8f 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1268,8 +1268,12 @@ int main(int argc, char **argv) will append to the file, so this is necessary to make sure it starts out empty. */ if (depfile) { - FILE*fd = fopen(depfile, "w"); - fclose(fd); + FILE *fd = fopen(depfile, "w"); + if (!fd) { + fprintf(stderr, "%s: can't open %s file.\n\n%s\n", argv[0], depfile, HELP); + return 1; + } + fclose(fd); } if (source_count == 0 && !version_flag) { From 8a5cbd441583f6b24918d9b0f846a74d4f2c9cf1 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 21 Apr 2017 21:37:17 +0100 Subject: [PATCH 014/138] Fix for GitHub issue #152 - segfault on gate connection syntax error. If there is a syntax error in the source code, pform_makegate may be passed a null list of port connections. The error is already reported, so we just need to ignore it. --- pform.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pform.cc b/pform.cc index 9bfa23b8b..b9e36042e 100644 --- a/pform.cc +++ b/pform.cc @@ -2142,9 +2142,11 @@ static void pform_makegate(PGBuiltin::Type type, return; } - for (list::iterator cur = info.parms->begin() - ; cur != info.parms->end() ; ++cur) { - pform_declare_implicit_nets(*cur); + if (info.parms) { + for (list::iterator cur = info.parms->begin() + ; cur != info.parms->end() ; ++cur) { + pform_declare_implicit_nets(*cur); + } } perm_string dev_name = lex_strings.make(info.name); From 3de7c234f7e01fb2e1e58c95de0d9440e7df762e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 15 Jun 2017 08:47:29 +0100 Subject: [PATCH 015/138] Implement vpi_put_value() for named events (GitHub issue #158). --- vvp/vpi_event.cc | 12 +++++++++++- vvp/vpi_priv.cc | 13 +++++++++++-- vvp/vpi_priv.h | 4 +++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/vvp/vpi_event.cc b/vvp/vpi_event.cc index f531ca2a5..f1ce84baa 100644 --- a/vvp/vpi_event.cc +++ b/vvp/vpi_event.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2017 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 @@ -63,6 +63,16 @@ char* __vpiNamedEvent::vpi_get_str(int code) return generic_get_str(code, scope_, name_, NULL); } +vpiHandle __vpiNamedEvent::vpi_put_value(p_vpi_value, int) +{ + // p_vpi_value may be NULL, and an event doesn't care + // what the value is + vvp_vector4_t val; + vvp_net_ptr_t dest(funct, 0); + vvp_send_vec4(dest, val, vthread_get_wt_context()); + + return this; +} vpiHandle __vpiNamedEvent::vpi_handle(int code) { diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index c77ebee37..d12ac50d2 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2017 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 @@ -464,6 +464,7 @@ int vpip_time_units_from_handle(vpiHandle obj) struct __vpiSysTaskCall*task; __vpiScope*scope; struct __vpiSignal*signal; + struct __vpiNamedEvent*event; if (obj == 0) return vpip_get_time_precision(); @@ -483,6 +484,11 @@ int vpip_time_units_from_handle(vpiHandle obj) scope = vpip_scope(signal); return scope->time_units; + case vpiNamedEvent: + event = dynamic_cast<__vpiNamedEvent*>(obj); + scope = event->get_scope(); + return scope->time_units; + default: fprintf(stderr, "ERROR: vpip_time_units_from_handle called with " "object handle type=%u\n", obj->get_type_code()); @@ -1104,7 +1110,10 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp, vpip_put_value_event*put = new vpip_put_value_event; put->handle = obj; - put->value = *vp; + if (!dynamic_cast<__vpiNamedEvent*>(obj)) { + assert(vp); + put->value = *vp; + } /* Since this is a scheduled put event we must copy any pointer * data to keep it available until the event is actually run. */ switch (put->value.format) { diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 5479a1f0b..c26e6da50 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vpi_priv_H #define IVL_vpi_priv_H /* - * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it @@ -479,8 +479,10 @@ class __vpiNamedEvent : public __vpiHandle { __vpiNamedEvent(__vpiScope*scope, const char*name); ~__vpiNamedEvent(); int get_type_code(void) const; + __vpiScope*get_scope(void) const { return scope_; } int vpi_get(int code); char* vpi_get_str(int code); + vpiHandle vpi_put_value(p_vpi_value val, int flags); vpiHandle vpi_handle(int code); inline void add_vpi_callback(__vpiCallback*cb) From e2be64558b594c5597feb25342c552374a8f5eee Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 15 Jun 2017 09:11:11 +0100 Subject: [PATCH 016/138] Ensure value passed to named event via vpi_put_value() is initialised. The __vpiNamedEvent::vpi_put_value() function ignores the value, but intermediate code looks at it. --- vvp/vpi_priv.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index d12ac50d2..e9305e212 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1110,7 +1110,10 @@ vpiHandle vpi_put_value(vpiHandle obj, s_vpi_value*vp, vpip_put_value_event*put = new vpip_put_value_event; put->handle = obj; - if (!dynamic_cast<__vpiNamedEvent*>(obj)) { + if (dynamic_cast<__vpiNamedEvent*>(obj)) { + put->value.format = vpiIntVal; + put->value.value.integer = 0; + } else { assert(vp); put->value = *vp; } From 42422d99401a3a97e224811d9ac731896a79685c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 16 Jun 2017 20:56:31 +0100 Subject: [PATCH 017/138] Don't allow localparams to be overridden (GitHub issue #157) Currently we only issue a warning if a parameter override references a parameter that doesn't exist, so do the same in this case. --- net_scope.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net_scope.cc b/net_scope.cc index 42eab5a51..f3f5a4518 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it @@ -304,16 +304,16 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix) */ bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope) { - bool flag = false; + if (parameters.find(key) == parameters.end()) + return false; - if (parameters.find(key) != parameters.end()) { - param_expr_t&ref = parameters[key]; - ref.val_expr = val; - ref.val_scope = scope; - flag = true; - } + param_expr_t&ref = parameters[key]; + if (ref.local_flag) + return false; - return flag; + ref.val_expr = val; + ref.val_scope = scope; + return true; } bool NetScope::make_parameter_unannotatable(perm_string key) From 10ef0eb1093b246bf0d6965feae16aabb19824dc Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 19 Jun 2017 21:09:15 -0700 Subject: [PATCH 018/138] Fix class versus struct warning in clang --- vvp/vpi_priv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index e9305e212..ee53234cd 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -464,7 +464,7 @@ int vpip_time_units_from_handle(vpiHandle obj) struct __vpiSysTaskCall*task; __vpiScope*scope; struct __vpiSignal*signal; - struct __vpiNamedEvent*event; + class __vpiNamedEvent*event; if (obj == 0) return vpip_get_time_precision(); From 62e0f59b07d001547bdf73da31ea3b5216bae531 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 19 Jun 2017 21:25:07 -0700 Subject: [PATCH 019/138] No need for class in previous patch --- vvp/vpi_priv.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index ee53234cd..0d72ea4ad 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -464,7 +464,7 @@ int vpip_time_units_from_handle(vpiHandle obj) struct __vpiSysTaskCall*task; __vpiScope*scope; struct __vpiSignal*signal; - class __vpiNamedEvent*event; + __vpiNamedEvent*event; if (obj == 0) return vpip_get_time_precision(); From 7362c7cbf8c8d822fb24deead5e0b83893291ee2 Mon Sep 17 00:00:00 2001 From: Daniel Andrade Date: Fri, 30 Jun 2017 20:41:55 -0300 Subject: [PATCH 020/138] Clarifying compilation instructions --- README.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index 8d5f1bbb9..a2e535955 100644 --- a/README.txt +++ b/README.txt @@ -78,10 +78,15 @@ Unpack the tar-ball and cd into the verilog-######### directory (presumably that is how you got to this README) and compile the source with the commands: - sh autoconf.sh ./configure make +If you are building from git, you have to run the command below before +compile the source. This will generate the "configure" file, which is +automatically done when building from tarball. + + sh configure.sh + Normally, this command automatically figures out everything it needs to know. It generally works pretty well. There are a few flags to the configure script that modify its behavior: From 917d754e371f3afb43e8aacd7fbf7605ac6cbf84 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 22 Jul 2017 13:00:15 -0700 Subject: [PATCH 021/138] Fix space issue --- driver/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/driver/main.c b/driver/main.c index 03054ef8f..bda5697ca 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1046,8 +1046,8 @@ int main(int argc, char **argv) break; case 'i': - ignore_missing_modules = 1; - break; + ignore_missing_modules = 1; + break; case 'l': process_file_name(optarg, 1); From ac87138c44cd6089046668c59a328b4d14c16ddc Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 12 Aug 2017 12:23:43 +0100 Subject: [PATCH 022/138] Fix for br1019 - allow multiple array words to be attached to a vpi callback. Normally there is at most one signal attached to a vvp functor, but due to port collapsing, there can be more than one. If these signals are array words, we need to trigger vpi callbacks on all the associated arrays when the functor value changes. --- vvp/vpi_callback.cc | 36 +++++++++++++++++++++++++++++------- vvp/vvp_vpi_callback.h | 3 +-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 3ee85f2f4..914afb7ec 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -636,24 +636,37 @@ void callback_execute(struct __vpiCallback*cur) vpi_mode_flag = save_mode; } +/* + * Usually there is at most one array word associated with a vvp signal, but + * due to port collapsing, there may be more. Using a linked list to record + * the array words minimises memory use for the most common case (no array + * words) or next most common case (one array word). + */ +struct __vpi_array_word { + struct __vpi_array_word* next; + struct __vpiArray* array; + unsigned long word; +}; + vvp_vpi_callback::vvp_vpi_callback() { vpi_callbacks_ = 0; - array_ = 0; - array_word_ = 0; + array_words_ = 0; } vvp_vpi_callback::~vvp_vpi_callback() { assert(vpi_callbacks_ == 0); - assert(array_ == 0); + assert(array_words_ == 0); } void vvp_vpi_callback::attach_as_word(vvp_array_t arr, unsigned long addr) { - assert(array_ == 0); - array_ = arr; - array_word_ = addr; + struct __vpi_array_word*tmp = new __vpi_array_word; + tmp->array = arr; + tmp->word = addr; + tmp->next = array_words_; + array_words_ = tmp; } void vvp_vpi_callback::add_vpi_callback(value_callback*cb) @@ -671,6 +684,11 @@ void vvp_vpi_callback::clear_all_callbacks() delete vpi_callbacks_; vpi_callbacks_ = tmp; } + while (array_words_) { + struct __vpi_array_word*tmp = array_words_->next; + delete array_words_; + array_words_ = tmp; + } } #endif @@ -682,7 +700,11 @@ void vvp_vpi_callback::clear_all_callbacks() */ void vvp_vpi_callback::run_vpi_callbacks() { - if (array_) array_->word_change(array_word_); + struct __vpi_array_word*array_word = array_words_; + while (array_word) { + array_word->array->word_change(array_word->word); + array_word = array_word->next; + } value_callback *next = vpi_callbacks_; value_callback *prev = 0; diff --git a/vvp/vvp_vpi_callback.h b/vvp/vvp_vpi_callback.h index e319d20e0..b263c2deb 100644 --- a/vvp/vvp_vpi_callback.h +++ b/vvp/vvp_vpi_callback.h @@ -57,8 +57,7 @@ class vvp_vpi_callback { private: value_callback*vpi_callbacks_; - struct __vpiArray* array_; - unsigned long array_word_; + struct __vpi_array_word*array_words_; }; From c855b8926e9a950d5d65e35b443e2ad7f6d20015 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 11 Sep 2017 21:49:35 +0100 Subject: [PATCH 023/138] Fix for GitHub issue #162 : very wide busses cause assertion failure. This occurs when tgt-vvp attempts to generate a C4<..> constant value with a bit width >= 65536. The actual failure occurs in the StringHeap class, which originally supported a maximum string length of 65535. This fix enables the StringHeap class to support any size string (provided the system has sufficient memory). --- libmisc/StringHeap.cc | 24 ++++++++++++++---------- libmisc/StringHeap.h | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/libmisc/StringHeap.cc b/libmisc/StringHeap.cc index f87c4fcf8..10259dc34 100644 --- a/libmisc/StringHeap.cc +++ b/libmisc/StringHeap.cc @@ -32,8 +32,8 @@ static unsigned string_pool_count = 0; StringHeap::StringHeap() { cell_base_ = 0; - cell_ptr_ = HEAPCELL; - cell_count_ = 0; + cell_size_ = 0; + cell_ptr_ = 0; } StringHeap::~StringHeap() @@ -45,20 +45,24 @@ StringHeap::~StringHeap() const char* StringHeap::add(const char*text) { unsigned len = strlen(text); - assert((len+1) <= HEAPCELL); - - unsigned rem = HEAPCELL - cell_ptr_; + unsigned rem = cell_size_ - cell_ptr_; if (rem < (len+1)) { - cell_base_ = (char*)malloc(HEAPCELL); + // release any unused memory + if (rem > 0) { + cell_base_ = (char*)realloc(cell_base_, cell_ptr_); + assert(cell_base_ != 0); + } + // start new cell + cell_size_ = (len+1) > DEFAULT_CELL_SIZE ? len+1 : DEFAULT_CELL_SIZE; + cell_base_ = (char*)malloc(cell_size_); + cell_ptr_ = 0; + assert(cell_base_ != 0); #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); } char*res = cell_base_ + cell_ptr_; @@ -66,7 +70,7 @@ const char* StringHeap::add(const char*text) cell_ptr_ += len; cell_base_[cell_ptr_++] = 0; - assert(cell_ptr_ <= HEAPCELL); + assert(cell_ptr_ <= cell_size_); return res; } diff --git a/libmisc/StringHeap.h b/libmisc/StringHeap.h index 4d619accf..2d4b97d43 100644 --- a/libmisc/StringHeap.h +++ b/libmisc/StringHeap.h @@ -78,11 +78,11 @@ class StringHeap { perm_string make(const char*); private: - enum { HEAPCELL = 0x10000 }; + static const unsigned DEFAULT_CELL_SIZE = 0x10000; char*cell_base_; + unsigned cell_size_; unsigned cell_ptr_; - unsigned cell_count_; private: // not implemented StringHeap(const StringHeap&); From 0bed890bc61542cac8b0785136a7620e33206aa0 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 Sep 2017 19:48:54 +0100 Subject: [PATCH 024/138] Fix use after free bug in vvp when a task or function is disabled. Use test_joinable() and do_join() to ensure everything gets cleaned up before the thread is reaped. This should fix br1016, br1017, and br1018. --- vvp/vthread.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index cabd75ccf..d9e34b1d7 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2325,7 +2325,7 @@ static bool do_disable(vthread_t thr, vthread_t match) } vthread_t parent = thr->parent; - if (parent && parent->i_am_joining) { + if (parent && parent->i_am_joining && test_joinable(parent, thr)) { // If a parent is waiting in a %join, wake it up. Note // that it is possible to be waiting in a %join yet // already scheduled if multiple child threads are @@ -2335,7 +2335,7 @@ static bool do_disable(vthread_t thr, vthread_t match) if (! parent->i_have_ended) schedule_vthread(parent, 0, true); - // Let the parent do the reaping. +// do_join(parent, thr); vthread_reap(thr); } else if (parent) { From a1a7f5deff4e3c8262c1924f12f28a11a6228413 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 Sep 2017 19:58:13 +0100 Subject: [PATCH 025/138] Fix error in last commit. --- vvp/vthread.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index d9e34b1d7..5ea584cbe 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2335,8 +2335,7 @@ static bool do_disable(vthread_t thr, vthread_t match) if (! parent->i_have_ended) schedule_vthread(parent, 0, true); -// do_join(parent, thr); - vthread_reap(thr); + do_join(parent, thr); } else if (parent) { /* If the parent is yet to %join me, let its %join From 3566ff4cd4abff790b68737f0bcbe5ee1a7c87fe Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 28 Sep 2017 19:24:04 +0100 Subject: [PATCH 026/138] Fix for GitHub issue #163 : assertion failure caused by syntax error in task. --- parse.y | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 882509da8..1a06fa83f 100644 --- a/parse.y +++ b/parse.y @@ -2044,7 +2044,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */ | K_task lifetime_opt IDENTIFIER error K_endtask { - assert(current_task == 0); + if (current_task) { + pform_pop_scope(); + current_task = 0; + } } endlabel_opt { // Last step: check any closing name. This is done late so From 85fa24fa58021552e14ed68b6c5932503179cdd3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 4 Oct 2017 21:31:56 +0100 Subject: [PATCH 027/138] Fix for br1025 : support nested scopes in root level tasks/functions. --- t-dll.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/t-dll.cc b/t-dll.cc index 626f3a74f..fa62dc484 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -288,6 +288,13 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur) return scope; } + for (map::iterator idx = des.root_tasks.begin() + ; idx != des.root_tasks.end() ; ++ idx) { + ivl_scope_t scope = find_scope_from_root(idx->second, cur); + if (scope) + return scope; + } + return 0; } From e315cafa0167d86620802ab0663247ee4f5f708b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 7 Oct 2017 16:41:26 +0100 Subject: [PATCH 028/138] Fix for GitHub issue #165 : assertion failure on thread join. If a thread becomes detached due to a join_any statement, that thread must not attempt to join its parent, even if the parent is waiting on a subsequent join statement. --- vvp/vthread.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 5ea584cbe..64fc3b6a0 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2738,7 +2738,7 @@ bool of_END(vthread_t thr, vvp_code_t) /* If I have a parent who is waiting for me, then mark that I have ended, and schedule that parent. Also, finish the %join for the parent. */ - if (thr->parent && thr->parent->i_am_joining) { + if (!thr->i_am_detached && thr->parent && thr->parent->i_am_joining) { vthread_t tmp = thr->parent; assert(! thr->i_am_detached); From 73167563d5f1d05ddb690038420c4b23d1d1e1dd Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Sun, 8 Oct 2017 14:18:32 +0300 Subject: [PATCH 029/138] ivlpp: Warn about macro redefinition Verilog spec has a very nasty system of macros jumping from file to file, resulting in a global macro scope. We abosolutely MUST track macro redefinitions and warn user about them. Signed-off-by: Andrew Andrianov --- ivlpp/lexor.lex | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index c81af7397..a0aa71b42 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -858,6 +858,19 @@ void define_macro(const char* name, const char* value, int keyword, int argc) { int idx; struct define_t* def; + struct define_t* prev; + + /* Verilog spec has a very nasty system of macros jumping from + * file to file, resulting in a global macro scope. We abosolutely + * MUST track macro redefinitions and warn user about them. + */ + + prev = def_lookup(name); + if (prev) { + emit_pathline(istack); + fprintf(stderr, "warning: redefinition of macro %s\n", + name); + } def = malloc(sizeof(struct define_t)); def->name = strdup(name); From 8a36849fdaecdbf6309e47471bdbf1f18c274e12 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 12:59:30 +0100 Subject: [PATCH 030/138] Generate proper error messages for invalid dynamic array initialisers. Invalid user code should not result in an "internal_error". --- elab_expr.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index b15d1aecf..178636fe4 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3448,29 +3448,29 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, } if (net == 0) { - cerr << get_fileline() << ": internal error: " - << "Expecting idents with ntype to be signals." << endl; + cerr << get_fileline() << ": error: Unable to bind variable `" + << path_ << "' in `" << scope_path(use_scope) << "'" << endl; des->errors += 1; return 0; } if (! ntype->type_compatible(net->net_type())) { - cerr << get_fileline() << ": internal_error: " - << "net type doesn't match context type." << endl; + cerr << get_fileline() << ": error: the type of the variable '" + << path_ << "' doesn't match the context type." << endl; - cerr << get_fileline() << ": : " - << "net type="; + cerr << get_fileline() << ": : " << "variable type="; if (net->net_type()) net->net_type()->debug_dump(cerr); else cerr << ""; cerr << endl; - cerr << get_fileline() << ": : " - << "context type="; + cerr << get_fileline() << ": : " << "context type="; ivl_assert(*this, ntype); ntype->debug_dump(cerr); cerr << endl; + des->errors += 1; + return 0; } ivl_assert(*this, ntype->type_compatible(net->net_type())); From 1aeaafa96c29ed0db35bc7b0d37da0578fc95111 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 13:55:55 +0100 Subject: [PATCH 031/138] Add support for vec4 darray initialisation from an array pattern. This was just a missing case label in tgt-vvp. --- tgt-vvp/eval_object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index fb6240d17..2bcd1500e 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -82,6 +82,7 @@ static int eval_darray_new(ivl_expr_t ex) unsigned idx; switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: + case IVL_VT_LOGIC: for (idx = 0 ; idx < ivl_expr_parms(init_expr) ; idx += 1) { draw_eval_vec4(ivl_expr_parm(init_expr,idx)); fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); From 5ca058bfb5fdb6fdc3382e10895b2d8ba75385c7 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 13:52:50 +0100 Subject: [PATCH 032/138] Add support for darray initialisation from another darray. Fixes GitHub issue #164. --- elab_expr.cc | 19 +++++++++++-- tgt-vvp/eval_object.c | 5 ++++ vvp/vvp_darray.cc | 64 +++++++++++++++++++++++++++++++++++++++++++ vvp/vvp_darray.h | 8 ++++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 178636fe4..1ff7b7b67 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3454,6 +3454,18 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, return 0; } + if (const netdarray_t*array_type = dynamic_cast (ntype)) { + if (array_type->type_compatible(net->net_type())) { + NetESignal*tmp = new NetESignal(net); + tmp->set_line(*this); + return tmp; + } + + // Icarus allows a dynamic array to be initialised with a + // single elementary value, so try that next. + ntype = array_type->element_type(); + } + if (! ntype->type_compatible(net->net_type())) { cerr << get_fileline() << ": error: the type of the variable '" << path_ << "' doesn't match the context type." << endl; @@ -5326,9 +5338,8 @@ NetExpr* PENewArray::elaborate_expr(Design*des, NetScope*scope, // expression. Elaborate the expression as an element // type. The run-time will assign this value to each element. const netarray_t*array_type = dynamic_cast (ntype); - ivl_type_t elem_type = array_type->element_type(); - init_val = init_->elaborate_expr(des, scope, elem_type, flags); + init_val = init_->elaborate_expr(des, scope, array_type, flags); } NetENew*tmp = new NetENew(ntype, size, init_val); @@ -5579,6 +5590,10 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode) NetExpr* PENumber::elaborate_expr(Design*des, NetScope*, ivl_type_t ntype, unsigned) const { + // Icarus allows dynamic arrays to be initialised with a single value. + if (const netdarray_t*array_type = dynamic_cast (ntype)) + ntype = array_type->element_type(); + const netvector_t*use_type = dynamic_cast (ntype); if (use_type == 0) { cerr << get_fileline() << ": internal error: " diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 2bcd1500e..7a307b150 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -111,6 +111,11 @@ static int eval_darray_new(ivl_expr_t ex) errors += 1; break; } + } else if (init_expr && (ivl_expr_value(init_expr) == IVL_VT_DARRAY)) { + ivl_signal_t sig = ivl_expr_signal(init_expr); + fprintf(vvp_out, " %%load/obj v%p_0;\n", sig); + fprintf(vvp_out, " %%scopy;\n"); + } else if (init_expr && number_is_immediate(size_expr,32,0)) { /* In this case, there is an init expression, the expression is NOT an array_pattern, and the size diff --git a/vvp/vvp_darray.cc b/vvp/vvp_darray.cc index 3c8086c03..94e940f45 100644 --- a/vvp/vvp_darray.cc +++ b/vvp/vvp_darray.cc @@ -67,6 +67,11 @@ void vvp_darray::get_word(unsigned, vvp_object_t&) cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl; } +void vvp_darray::shallow_copy(const vvp_object*) +{ + cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl; +} + template vvp_darray_atom::~vvp_darray_atom() { } @@ -101,6 +106,16 @@ template void vvp_darray_atom::get_word(unsigned adr, vvp_vec value = tmp; } +template void vvp_darray_atom::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_atom*that = dynamic_cast*>(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} + template class vvp_darray_atom; template class vvp_darray_atom; template class vvp_darray_atom; @@ -140,6 +155,16 @@ void vvp_darray_vec4::get_word(unsigned adr, vvp_vector4_t&value) assert(value.size() == word_wid_); } +void vvp_darray_vec4::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_vec4*that = dynamic_cast(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} + vvp_darray_vec2::~vvp_darray_vec2() { } @@ -173,6 +198,15 @@ void vvp_darray_vec2::get_word(unsigned adr, vvp_vector4_t&value) } } +void vvp_darray_vec2::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_vec2*that = dynamic_cast(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} vvp_darray_object::~vvp_darray_object() { @@ -200,6 +234,16 @@ void vvp_darray_object::get_word(unsigned adr, vvp_object_t&value) value = array_[adr]; } +void vvp_darray_object::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_object*that = dynamic_cast(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} + vvp_darray_real::~vvp_darray_real() { } @@ -226,6 +270,16 @@ void vvp_darray_real::get_word(unsigned adr, double&value) value = array_[adr]; } +void vvp_darray_real::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_real*that = dynamic_cast(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} + vvp_darray_string::~vvp_darray_string() { } @@ -252,6 +306,16 @@ void vvp_darray_string::get_word(unsigned adr, string&value) value = array_[adr]; } +void vvp_darray_string::shallow_copy(const vvp_object*obj) +{ + const vvp_darray_string*that = dynamic_cast(obj); + assert(that); + + unsigned num_items = min(array_.size(), that->array_.size()); + for (unsigned idx = 0 ; idx < num_items ; idx += 1) + array_[idx] = that->array_[idx]; +} + vvp_queue::~vvp_queue() { } diff --git a/vvp/vvp_darray.h b/vvp/vvp_darray.h index b914110be..2ad520222 100644 --- a/vvp/vvp_darray.h +++ b/vvp/vvp_darray.h @@ -44,6 +44,8 @@ class vvp_darray : public vvp_object { virtual void set_word(unsigned adr, const vvp_object_t&value); virtual void get_word(unsigned adr, vvp_object_t&value); + + virtual void shallow_copy(const vvp_object*obj); }; template class vvp_darray_atom : public vvp_darray { @@ -55,6 +57,7 @@ template class vvp_darray_atom : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -70,6 +73,7 @@ class vvp_darray_vec4 : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -86,6 +90,7 @@ class vvp_darray_vec2 : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_vector4_t&value); void get_word(unsigned adr, vvp_vector4_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -101,6 +106,7 @@ class vvp_darray_real : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, double value); void get_word(unsigned adr, double&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -115,6 +121,7 @@ class vvp_darray_string : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const std::string&value); void get_word(unsigned adr, std::string&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; @@ -129,6 +136,7 @@ class vvp_darray_object : public vvp_darray { size_t get_size(void) const; void set_word(unsigned adr, const vvp_object_t&value); void get_word(unsigned adr, vvp_object_t&value); + void shallow_copy(const vvp_object*obj); private: std::vector array_; From 87cddf33dcadec01bf2738a297aa4ea7572bb189 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 20:45:07 +0100 Subject: [PATCH 033/138] Fix for GitHub issue #98 and #167 Two fixes needed: - when searching for a base class, we need to look in the root scope if the base class isn't found in the scope hierarchy - the classes in the root scope need to be stored in an ordered list, not a map, to ensure they are elaborated in the order they were declared. Without this, the compiler may try elaborating an extended class before its base class is known about. --- elab_scope.cc | 18 ++++++++---------- main.cc | 7 +++---- parse_api.h | 4 ++-- pform.cc | 6 +++--- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index 9796ce7fc..53ebf37af 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -509,8 +509,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) netclass_t*use_base_class = 0; if (base_class) { - ivl_assert(*pclass, scope); - use_base_class = scope->find_class(base_class->name); + if (scope) + use_base_class = scope->find_class(base_class->name); + if (use_base_class == 0) + use_base_class = des->find_class(base_class->name); if (use_base_class == 0) { cerr << pclass->get_fileline() << ": error: " << "Base class " << base_class->name @@ -605,13 +607,9 @@ static void elaborate_scope_classes(Design*des, NetScope*scope, void elaborate_rootscope_classes(Design*des) { - if (pform_classes.empty()) - return; - - for (map::iterator cur = pform_classes.begin() - ; cur != pform_classes.end() ; ++ cur) { - blend_class_constructors(cur->second); - elaborate_scope_class(des, 0, cur->second); + for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { + blend_class_constructors(pform_classes[idx]); + elaborate_scope_class(des, 0, pform_classes[idx]); } } diff --git a/main.cc b/main.cc index e814b7466..e80ba1983 100644 --- a/main.cc +++ b/main.cc @@ -1,5 +1,5 @@ const char COPYRIGHT[] = - "Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)"; + "Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com)"; /* * This source code is free software; you can redistribute it @@ -1056,9 +1056,8 @@ int main(int argc, char*argv[]) pform_dump(out, cur->second); } out << "PFORM DUMP $ROOT CLASSES:" << endl; - for (map::iterator cur = pform_classes.begin() - ; cur != pform_classes.end() ; ++ cur) { - pform_dump(out, cur->second); + for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { + pform_dump(out, pform_classes[idx]); } out << "PFORM DUMP PACKAGES:" << endl; for (map::iterator pac = pform_packages.begin() diff --git a/parse_api.h b/parse_api.h index a698c3bee..87ae28d11 100644 --- a/parse_api.h +++ b/parse_api.h @@ -1,7 +1,7 @@ #ifndef IVL_parse_api_H #define IVL_parse_api_H /* - * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -45,7 +45,7 @@ extern std::map pform_primitives; extern std::map pform_typedefs; extern std::set pform_enum_sets; extern std::map pform_tasks; -extern std::map pform_classes; +extern std::vector pform_classes; extern std::map pform_packages; extern void pform_dump(std::ostream&out, const PClass*pac); diff --git a/pform.cc b/pform.cc index b9e36042e..0478fba79 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -71,7 +71,7 @@ setpform_enum_sets; /* * Class definitions in the $root scope go here. */ -map pform_classes; +vector pform_classes; /* * Task and function definitions in the $root scope go here. @@ -467,7 +467,7 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, /* If no scope was found then this is being defined in the * compilation unit scope. */ if (scopex == 0) { - pform_classes[name] = class_scope; + pform_classes.push_back(class_scope); lexical_scope = class_scope; return class_scope; } From 4f383a8a119b8dc00c1fa6491c44e08f1309b8b1 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 8 Oct 2017 21:16:50 +0100 Subject: [PATCH 034/138] Enable base class tasks to be used in an extended class. --- netclass.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/netclass.cc b/netclass.cc index 0ae3ba1dc..7e69a604d 100644 --- a/netclass.cc +++ b/netclass.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2017 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 @@ -165,7 +165,8 @@ bool netclass_t::test_for_missing_initializers() const NetScope*netclass_t::method_from_name(perm_string name) const { NetScope*task = class_scope_->child( hname_t(name) ); - if (task == 0) return 0; + if ((task == 0) && super_) + task = super_->method_from_name(name); return task; } From 0c84413347a9fc76f46e1c8d41e66033d7e1634e Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Wed, 18 Oct 2017 19:18:14 +0300 Subject: [PATCH 035/138] ivlpp: Add -Wredef option to enable redefinition warnings Signed-off-by: Andrew Andrianov --- ivlpp/globals.h | 2 ++ ivlpp/lexor.lex | 4 ++-- ivlpp/main.c | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ivlpp/globals.h b/ivlpp/globals.h index 90b4632b9..1c4cee43d 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -53,6 +53,8 @@ extern char dep_mode; extern int verbose_flag; +extern int warn_redef; + /* This is the entry to the lexer. */ extern int yylex(void); diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index a0aa71b42..c03057d65 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -868,8 +868,8 @@ void define_macro(const char* name, const char* value, int keyword, int argc) prev = def_lookup(name); if (prev) { emit_pathline(istack); - fprintf(stderr, "warning: redefinition of macro %s\n", - name); + fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n", + name, prev->value, value); } def = malloc(sizeof(struct define_t)); diff --git a/ivlpp/main.c b/ivlpp/main.c index 7ec80cb86..b4909b647 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -98,6 +98,9 @@ int line_direct_flag = 0; unsigned error_count = 0; FILE *depend_file = NULL; +/* Should we warn about macro redefinitions? */ +int warn_redef = 0; + static int flist_read_flags(const char*path) { char line_buf[2048]; @@ -282,7 +285,7 @@ int main(int argc, char*argv[]) include_dir[0] = 0; /* 0 is reserved for the current files path. */ include_dir[1] = strdup("."); - while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vV")) != EOF) switch (opt) { + while ((opt=getopt(argc, argv, "F:f:K:Lo:p:P:vVW:")) != EOF) switch (opt) { case 'F': flist_read_flags(optarg); @@ -336,6 +339,12 @@ int main(int argc, char*argv[]) break; } + case 'W': { + if (strcmp(optarg, "redef")==0) + warn_redef = 1; + break; + } + case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version " VERSION " (" VERSION_TAG ")\n\n"); @@ -366,7 +375,8 @@ int main(int argc, char*argv[]) " -p - Write precompiled defines to \n" " -P - Read precompiled defines from \n" " -v - Verbose\n" - " -V - Print version information and quit\n", + " -V - Print version information and quit\n" + " -W - Enable extra ivlpp warning category (e.g. redef)\n", argv[0]); return flag_errors; } From 6c2fba1139f506323cefdf6cf551ab7953ba24c8 Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Thu, 19 Oct 2017 11:40:07 +0300 Subject: [PATCH 036/138] driver: Implement -Wr handling for macro redefinitions Signed-off-by: Andrew Andrianov --- driver/main.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/driver/main.c b/driver/main.c index bda5697ca..a4873e829 100644 --- a/driver/main.c +++ b/driver/main.c @@ -138,7 +138,7 @@ int gen_std_include = 1; of the include list. */ int gen_relative_include = 0; -char warning_flags[16] = "n"; +char warning_flags[17] = "n"; /* Boolean: true means ignore errors about missing modules */ int ignore_missing_modules = 0; @@ -505,6 +505,10 @@ static void process_warning_switch(const char*name) process_warning_switch("select-range"); process_warning_switch("timescale"); process_warning_switch("sensitivity-entire-array"); + process_warning_switch("macro-redefinition"); + } else if (strcmp(name,"macro-redefinition") == 0) { + if (! strchr(warning_flags, 'r')) + strcat(warning_flags, "r"); } else if (strcmp(name,"anachronisms") == 0) { if (! strchr(warning_flags, 'n')) strcat(warning_flags, "n"); @@ -1288,8 +1292,10 @@ int main(int argc, char **argv) /* Write the preprocessor command needed to preprocess a single file. This may be used to preprocess library files. */ - fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\"\n", - ivlpp_dir, sep, defines_path, compiled_defines_path); + fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\" %s\n", + ivlpp_dir, sep, defines_path, compiled_defines_path, + strchr(warning_flags, 'r') ? "-Wredef" : "" + ); /* Done writing to the iconfig file. Close it now. */ fclose(iconfig_file); From 94e42e5bfc0071a74d7ab3fe539ac26857487738 Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Thu, 19 Oct 2017 11:40:50 +0300 Subject: [PATCH 037/138] driver: Update manpage Signed-off-by: Andrew Andrianov --- driver/iverilog.man.in | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index ba05d2a0a..f8425713a 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -310,8 +310,8 @@ after a \fB\-Wall\fP argument to suppress isolated warning types. .TP 8 .B all -This enables the anachronisms, implicit, portbind, select\-range, -timescale, and sensitivity\-entire\-array warning categories. +This enables the anachronisms, implicit, macro-redefinition, portbind, +select\-range, timescale, and sensitivity\-entire\-array warning categories. .TP 8 .B anachronisms @@ -324,6 +324,10 @@ This enables warnings for creation of implicit declarations. For example, if a scalar wire X is used but not declared in the Verilog source, this will print a warning at its first use. +.TP 8 +.B macro-redefinition +This enables preprocessor warnings when a macro is being redefined. + .TP 8 .B portbind This enables warnings for ports of module instantiations that are not From 9e2252bc398144e6505e6af81a31e59ef2e4de8c Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Sun, 22 Oct 2017 13:28:15 +0300 Subject: [PATCH 038/138] ivlpp: Actually take warn_redef flag into account Signed-off-by: Andrew Andrianov --- ivlpp/lexor.lex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index c03057d65..b8ccb6296 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -866,7 +866,7 @@ void define_macro(const char* name, const char* value, int keyword, int argc) */ prev = def_lookup(name); - if (prev) { + if (prev && warn_redef) { emit_pathline(istack); fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n", name, prev->value, value); From 3e87a4d242b9ad7919229ff29419149016cccdba Mon Sep 17 00:00:00 2001 From: Andrew Andrianov Date: Sun, 22 Oct 2017 13:53:07 +0300 Subject: [PATCH 039/138] driver: Add -Wno-macro-redefinition, properly pass -Wredef to ivlpp Signed-off-by: Andrew Andrianov --- driver/main.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/driver/main.c b/driver/main.c index a4873e829..c39e1bd37 100644 --- a/driver/main.c +++ b/driver/main.c @@ -344,9 +344,12 @@ static int t_version_only(void) static void build_preprocess_command(int e_flag) { - snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ", - ivlpp_dir, sep, verbose_flag?" -v":"", - e_flag?"":" -L", defines_path, source_path, + snprintf(tmp, sizeof tmp, "%s%civlpp %s%s%s -F\"%s\" -f\"%s\" -p\"%s\" ", + ivlpp_dir, sep, + verbose_flag?" -v":"", + e_flag?"":" -L", + strchr(warning_flags, 'r') ? " -Wredef " : "", + defines_path, source_path, compiled_defines_path); } @@ -547,6 +550,12 @@ static void process_warning_switch(const char*name) cp[0] = cp[1]; cp += 1; } + } else if (strcmp(name,"no-macro-redefinition") == 0) { + char*cp = strchr(warning_flags, 'r'); + if (cp) while (*cp) { + cp[0] = cp[1]; + cp += 1; + } } else if (strcmp(name,"no-floating-nets") == 0) { char*cp = strchr(warning_flags, 'f'); if (cp) while (*cp) { @@ -1292,9 +1301,10 @@ int main(int argc, char **argv) /* Write the preprocessor command needed to preprocess a single file. This may be used to preprocess library files. */ - fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F\"%s\" -P\"%s\" %s\n", - ivlpp_dir, sep, defines_path, compiled_defines_path, - strchr(warning_flags, 'r') ? "-Wredef" : "" + fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n", + ivlpp_dir, sep, + strchr(warning_flags, 'r') ? "-Wredef" : "", + defines_path, compiled_defines_path ); /* Done writing to the iconfig file. Close it now. */ From 97e212372456cdb1f619892b42b691ea85254f8e Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 22 Oct 2017 19:39:07 -0700 Subject: [PATCH 040/138] Update to latest files from GTKWave --- vpi/fstapi.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vpi/fstapi.h b/vpi/fstapi.h index df86ef079..e66c20467 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015 Tony Bybell. + * Copyright (c) 2009-2017 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -168,7 +168,11 @@ enum fstHierType { FST_HT_ATTRBEGIN = 3, FST_HT_ATTREND = 4, - FST_HT_MAX = 4 + /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */ + FST_HT_TREEBEGIN = 5, + FST_HT_TREEEND = 6, + + FST_HT_MAX = 6 }; enum fstAttrType { From d9478bd8377a451edfea7be92a85f21d53cb3724 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 23 Oct 2017 00:16:51 -0700 Subject: [PATCH 041/138] Update cppcheck waiver files --- cppcheck.sup | 750 ++++++++++++++++++++++++----------------------- vpi/cppcheck.sup | 82 +++--- vvp/cppcheck.sup | 44 +++ 3 files changed, 465 insertions(+), 411 deletions(-) diff --git a/cppcheck.sup b/cppcheck.sup index c3648b228..500f28945 100644 --- a/cppcheck.sup +++ b/cppcheck.sup @@ -1,613 +1,619 @@ // These are correct and are used to find the base (zero) pin. -thisSubtraction:netlist.h:5081 -thisSubtraction:netlist.h:5090 +thisSubtraction:netlist.h:5082 +thisSubtraction:netlist.h:5091 // These are the functions that the compiler exports to the targets. //ivl_branch_island() -unusedFunction:t-dll-api.cc:38 +unusedFunction:t-dll-api.cc:39 //ivl_branch_terminal() -unusedFunction:t-dll-api.cc:43 +unusedFunction:t-dll-api.cc:45 //ivl_const_bits() -unusedFunction:t-dll-api.cc:180 +unusedFunction:t-dll-api.cc:196 //ivl_const_delay() -unusedFunction:t-dll-api.cc:198 +unusedFunction:t-dll-api.cc:214 //ivl_const_file() -unusedFunction:t-dll-api.cc:204 +unusedFunction:t-dll-api.cc:221 //ivl_const_lineno() -unusedFunction:t-dll-api.cc:210 +unusedFunction:t-dll-api.cc:227 //ivl_const_nex() -unusedFunction:t-dll-api.cc:216 +unusedFunction:t-dll-api.cc:233 //ivl_const_real() -unusedFunction:t-dll-api.cc:222 +unusedFunction:t-dll-api.cc:239 //ivl_const_scope() -unusedFunction:t-dll-api.cc:229 +unusedFunction:t-dll-api.cc:246 //ivl_const_signed() -unusedFunction:t-dll-api.cc:235 +unusedFunction:t-dll-api.cc:252 //ivl_const_type() -unusedFunction:t-dll-api.cc:174 +unusedFunction:t-dll-api.cc:190 //ivl_const_width() -unusedFunction:t-dll-api.cc:241 +unusedFunction:t-dll-api.cc:258 //ivl_design_const() -unusedFunction:t-dll-api.cc:116 +unusedFunction:t-dll-api.cc:127 //ivl_design_consts() -unusedFunction:t-dll-api.cc:111 +unusedFunction:t-dll-api.cc:121 //ivl_design_delay_sel() -unusedFunction:t-dll-api.cc:49 +unusedFunction:t-dll-api.cc:52 //ivl_design_discipline() -unusedFunction:t-dll-api.cc:128 +unusedFunction:t-dll-api.cc:140 //ivl_design_disciplines() -unusedFunction:t-dll-api.cc:122 +unusedFunction:t-dll-api.cc:134 //ivl_design_flag() -unusedFunction:t-dll-api.cc:54 -//ivl_design_process() unusedFunction:t-dll-api.cc:59 +//ivl_design_process() +unusedFunction:t-dll-api.cc:66 //ivl_design_root() -unusedFunction:t-dll-api.cc:72 +unusedFunction:t-dll-api.cc:80 //ivl_design_roots() -unusedFunction:t-dll-api.cc:81 +unusedFunction:t-dll-api.cc:89 //ivl_design_time_precision() -unusedFunction:t-dll-api.cc:106 +unusedFunction:t-dll-api.cc:115 //ivl_discipline_domain() -unusedFunction:t-dll-api.cc:135 +unusedFunction:t-dll-api.cc:147 //ivl_discipline_flow() -unusedFunction:t-dll-api.cc:140 +unusedFunction:t-dll-api.cc:153 //ivl_discipline_name() -unusedFunction:t-dll-api.cc:145 +unusedFunction:t-dll-api.cc:159 //ivl_discipline_potential() -unusedFunction:t-dll-api.cc:150 +unusedFunction:t-dll-api.cc:165 //ivl_enum_bits() -unusedFunction:t-dll-api.cc:260 +unusedFunction:t-dll-api.cc:277 //ivl_enum_file() -unusedFunction:t-dll-api.cc:285 +unusedFunction:t-dll-api.cc:302 //ivl_enum_lineno() -unusedFunction:t-dll-api.cc:291 +unusedFunction:t-dll-api.cc:308 //ivl_enum_name() -unusedFunction:t-dll-api.cc:253 +unusedFunction:t-dll-api.cc:270 //ivl_enum_names() -unusedFunction:t-dll-api.cc:247 +unusedFunction:t-dll-api.cc:264 //ivl_enum_signed() -unusedFunction:t-dll-api.cc:279 +unusedFunction:t-dll-api.cc:296 //ivl_enum_type() -unusedFunction:t-dll-api.cc:267 +unusedFunction:t-dll-api.cc:284 //ivl_enum_width() -unusedFunction:t-dll-api.cc:273 +unusedFunction:t-dll-api.cc:290 //ivl_event_any() -unusedFunction:t-dll-api.cc:349 -//ivl_event_file() -unusedFunction:t-dll-api.cc:326 -//ivl_event_lineno() -unusedFunction:t-dll-api.cc:332 -//ivl_event_name() -unusedFunction:t-dll-api.cc:297 -//ivl_event_nany() -unusedFunction:t-dll-api.cc:343 -//ivl_event_neg() -unusedFunction:t-dll-api.cc:362 -//ivl_event_nneg() -unusedFunction:t-dll-api.cc:356 -//ivl_event_npos() unusedFunction:t-dll-api.cc:369 +//ivl_event_file() +unusedFunction:t-dll-api.cc:345 +//ivl_event_lineno() +unusedFunction:t-dll-api.cc:351 +//ivl_event_name() +unusedFunction:t-dll-api.cc:314 +//ivl_event_nany() +unusedFunction:t-dll-api.cc:363 +//ivl_event_neg() +unusedFunction:t-dll-api.cc:382 +//ivl_event_nneg() +unusedFunction:t-dll-api.cc:376 +//ivl_event_npos() +unusedFunction:t-dll-api.cc:389 //ivl_event_pos() -unusedFunction:t-dll-api.cc:375 +unusedFunction:t-dll-api.cc:395 //ivl_event_scope() -unusedFunction:t-dll-api.cc:338 +unusedFunction:t-dll-api.cc:357 //ivl_expr_bits() -unusedFunction:t-dll-api.cc:382 +unusedFunction:t-dll-api.cc:402 //ivl_expr_branch() -unusedFunction:t-dll-api.cc:388 +unusedFunction:t-dll-api.cc:409 //ivl_expr_def() -unusedFunction:t-dll-api.cc:394 -//ivl_expr_delay_val() -unusedFunction:t-dll-api.cc:410 -//ivl_expr_dvalue() unusedFunction:t-dll-api.cc:416 +//ivl_expr_delay_val() +unusedFunction:t-dll-api.cc:432 +//ivl_expr_dvalue() +unusedFunction:t-dll-api.cc:439 //ivl_expr_enumtype() -unusedFunction:t-dll-api.cc:422 +unusedFunction:t-dll-api.cc:446 //ivl_expr_event() -unusedFunction:t-dll-api.cc:628 +unusedFunction:t-dll-api.cc:656 //ivl_expr_file() -unusedFunction:t-dll-api.cc:162 +unusedFunction:t-dll-api.cc:178 //ivl_expr_lineno() -unusedFunction:t-dll-api.cc:168 +unusedFunction:t-dll-api.cc:184 //ivl_expr_name() -unusedFunction:t-dll-api.cc:433 +unusedFunction:t-dll-api.cc:459 //ivl_expr_nature() -unusedFunction:t-dll-api.cc:456 +unusedFunction:t-dll-api.cc:483 //ivl_expr_net_type() -unusedFunction:t-dll-api.cc:428 +unusedFunction:t-dll-api.cc:453 //ivl_expr_opcode() -unusedFunction:t-dll-api.cc:462 +unusedFunction:t-dll-api.cc:490 //ivl_expr_oper1() -unusedFunction:t-dll-api.cc:478 +unusedFunction:t-dll-api.cc:506 //ivl_expr_oper2() -unusedFunction:t-dll-api.cc:516 +unusedFunction:t-dll-api.cc:544 //ivl_expr_oper3() -unusedFunction:t-dll-api.cc:542 +unusedFunction:t-dll-api.cc:570 //ivl_expr_parameter() -unusedFunction:t-dll-api.cc:556 +unusedFunction:t-dll-api.cc:584 //ivl_expr_parm() -unusedFunction:t-dll-api.cc:571 +unusedFunction:t-dll-api.cc:599 //ivl_expr_parms() -unusedFunction:t-dll-api.cc:598 +unusedFunction:t-dll-api.cc:626 //ivl_expr_repeat() -unusedFunction:t-dll-api.cc:621 -//ivl_expr_scope() -unusedFunction:t-dll-api.cc:642 -//ivl_expr_sel_type() unusedFunction:t-dll-api.cc:649 +//ivl_expr_scope() +unusedFunction:t-dll-api.cc:670 +//ivl_expr_sel_type() +unusedFunction:t-dll-api.cc:677 //ivl_expr_signed() -unusedFunction:t-dll-api.cc:674 +unusedFunction:t-dll-api.cc:702 //ivl_expr_sized() -unusedFunction:t-dll-api.cc:680 +unusedFunction:t-dll-api.cc:708 //ivl_expr_string() -unusedFunction:t-dll-api.cc:686 +unusedFunction:t-dll-api.cc:714 //ivl_expr_type() -unusedFunction:t-dll-api.cc:155 +unusedFunction:t-dll-api.cc:171 //ivl_expr_uvalue() -unusedFunction:t-dll-api.cc:692 +unusedFunction:t-dll-api.cc:721 //ivl_expr_value() -unusedFunction:t-dll-api.cc:717 +unusedFunction:t-dll-api.cc:747 //ivl_expr_width() +unusedFunction:t-dll-api.cc:753 -unusedFunction:t-dll-api.cc:723 //ivl_file_table_index() -unusedFunction:t-dll-api.cc:765 +unusedFunction:t-dll-api.cc:795 //ivl_file_table_item() -unusedFunction:t-dll-api.cc:755 +unusedFunction:t-dll-api.cc:785 //ivl_file_table_size() -unusedFunction:t-dll-api.cc:783 +unusedFunction:t-dll-api.cc:813 //ivl_island_flag_set() -unusedFunction:t-dll-api.cc:792 +unusedFunction:t-dll-api.cc:822 //ivl_island_flag_test() -unusedFunction:t-dll-api.cc:806 +unusedFunction:t-dll-api.cc:837 //ivl_logic_attr() -unusedFunction:t-dll-api.cc:832 +unusedFunction:t-dll-api.cc:864 //ivl_logic_attr_cnt() -unusedFunction:t-dll-api.cc:848 +unusedFunction:t-dll-api.cc:880 //ivl_logic_attr_val() -unusedFunction:t-dll-api.cc:853 +unusedFunction:t-dll-api.cc:886 //ivl_logic_basename() -unusedFunction:t-dll-api.cc:901 +unusedFunction:t-dll-api.cc:935 //ivl_logic_delay() -unusedFunction:t-dll-api.cc:936 +unusedFunction:t-dll-api.cc:974 //ivl_logic_drive0() -unusedFunction:t-dll-api.cc:860 -//ivl_logic_drive1() -unusedFunction:t-dll-api.cc:877 -//ivl_logic_file() -unusedFunction:t-dll-api.cc:814 -//ivl_logic_is_cassign() -unusedFunction:t-dll-api.cc:826 -//ivl_logic_lineno() -unusedFunction:t-dll-api.cc:820 -//ivl_logic_name() unusedFunction:t-dll-api.cc:894 +//ivl_logic_drive1() +unusedFunction:t-dll-api.cc:911 +//ivl_logic_file() +unusedFunction:t-dll-api.cc:846 +//ivl_logic_is_cassign() +unusedFunction:t-dll-api.cc:858 +//ivl_logic_lineno() +unusedFunction:t-dll-api.cc:852 +//ivl_logic_name() +unusedFunction:t-dll-api.cc:928 //ivl_logic_pins() -unusedFunction:t-dll-api.cc:918 +unusedFunction:t-dll-api.cc:953 //ivl_logic_scope() -unusedFunction:t-dll-api.cc:907 +unusedFunction:t-dll-api.cc:941 //ivl_logic_type() -unusedFunction:t-dll-api.cc:913 +unusedFunction:t-dll-api.cc:947 //ivl_logic_udp() -unusedFunction:t-dll-api.cc:929 +unusedFunction:t-dll-api.cc:966 //ivl_logic_width() -unusedFunction:t-dll-api.cc:942 +unusedFunction:t-dll-api.cc:981 //ivl_lpm_array() -unusedFunction:t-dll-api.cc:1059 +unusedFunction:t-dll-api.cc:1109 //ivl_lpm_aset_value() -unusedFunction:t-dll-api.cc:1110 +unusedFunction:t-dll-api.cc:1160 //ivl_lpm_async_clr() -unusedFunction:t-dll-api.cc:1005 +unusedFunction:t-dll-api.cc:1054 //ivl_lpm_async_set() -unusedFunction:t-dll-api.cc:1035 +unusedFunction:t-dll-api.cc:1085 //ivl_lpm_base() -unusedFunction:t-dll-api.cc:1071 -//ivl_lpm_basename() -unusedFunction:t-dll-api.cc:1000 -//ivl_lpm_clk() -unusedFunction:t-dll-api.cc:1098 -//ivl_lpm_data() -unusedFunction:t-dll-api.cc:1167 -//ivl_lpm_datab() -unusedFunction:t-dll-api.cc:1264 -//ivl_lpm_define() -unusedFunction:t-dll-api.cc:1133 -//ivl_lpm_delay() -unusedFunction:t-dll-api.cc:1029 -//ivl_lpm_drive0() -unusedFunction:t-dll-api.cc:1393 -//ivl_lpm_drive1() -unusedFunction:t-dll-api.cc:1410 -//ivl_lpm_enable() -unusedFunction:t-dll-api.cc:1145 -//ivl_lpm_file() -unusedFunction:t-dll-api.cc:1157 -//ivl_lpm_lineno() -unusedFunction:t-dll-api.cc:1162 -//ivl_lpm_name() -unusedFunction:t-dll-api.cc:1298 -//ivl_lpm_negedge() -unusedFunction:t-dll-api.cc:1086 -//ivl_lpm_select() -unusedFunction:t-dll-api.cc:1433 -//ivl_lpm_selects() -unusedFunction:t-dll-api.cc:1449 -//ivl_lpm_signed() -unusedFunction:t-dll-api.cc:1466 -//ivl_lpm_size() -unusedFunction:t-dll-api.cc:1525 -//ivl_lpm_sset_value() unusedFunction:t-dll-api.cc:1121 +//ivl_lpm_basename() +unusedFunction:t-dll-api.cc:1048 +//ivl_lpm_clk() +unusedFunction:t-dll-api.cc:1148 +//ivl_lpm_data() +unusedFunction:t-dll-api.cc:1221 +//ivl_lpm_datab() +unusedFunction:t-dll-api.cc:1321 +//ivl_lpm_define() +unusedFunction:t-dll-api.cc:1183 +//ivl_lpm_delay() +unusedFunction:t-dll-api.cc:1078 +//ivl_lpm_drive0() +unusedFunction:t-dll-api.cc:1453 +//ivl_lpm_drive1() +unusedFunction:t-dll-api.cc:1470 +//ivl_lpm_enable() +unusedFunction:t-dll-api.cc:1195 +//ivl_lpm_file() +unusedFunction:t-dll-api.cc:1209 +//ivl_lpm_lineno() +unusedFunction:t-dll-api.cc:1215 +//ivl_lpm_name() +unusedFunction:t-dll-api.cc:1355 +//ivl_lpm_negedge() +unusedFunction:t-dll-api.cc:1136 +//ivl_lpm_select() +unusedFunction:t-dll-api.cc:1493 +//ivl_lpm_selects() +unusedFunction:t-dll-api.cc:1510 +//ivl_lpm_signed() +unusedFunction:t-dll-api.cc:1528 +//ivl_lpm_size() +unusedFunction:t-dll-api.cc:1587 +//ivl_lpm_sset_value() +unusedFunction:t-dll-api.cc:1171 //ivl_lpm_string() -unusedFunction:t-dll-api.cc:1577 +unusedFunction:t-dll-api.cc:1640 //ivl_lpm_sync_clr() -unusedFunction:t-dll-api.cc:1017 +unusedFunction:t-dll-api.cc:1066 //ivl_lpm_sync_set() -unusedFunction:t-dll-api.cc:1047 +unusedFunction:t-dll-api.cc:1097 //ivl_lpm_trigger() -unusedFunction:t-dll-api.cc:1594 +unusedFunction:t-dll-api.cc:1659 //ivl_lpm_type() -unusedFunction:t-dll-api.cc:1583 +unusedFunction:t-dll-api.cc:1647 //ivl_lpm_width() -unusedFunction:t-dll-api.cc:1588 +unusedFunction:t-dll-api.cc:1653 //ivl_lval_idx() -unusedFunction:t-dll-api.cc:1616 +unusedFunction:t-dll-api.cc:1681 //ivl_lval_mux() -unusedFunction:t-dll-api.cc:1611 +unusedFunction:t-dll-api.cc:1676 //ivl_lval_nest() -unusedFunction:t-dll-api.cc:1661 +unusedFunction:t-dll-api.cc:1726 //ivl_lval_part_off() -unusedFunction:t-dll-api.cc:1625 +unusedFunction:t-dll-api.cc:1690 //ivl_lval_property_idx() -unusedFunction:t-dll-api.cc:1643 +unusedFunction:t-dll-api.cc:1708 //ivl_lval_sel_type() -unusedFunction:t-dll-api.cc:1631 +unusedFunction:t-dll-api.cc:1696 //ivl_lval_sig() -unusedFunction:t-dll-api.cc:1649 +unusedFunction:t-dll-api.cc:1714 //ivl_nature_name() -unusedFunction:t-dll-api.cc:1670 +unusedFunction:t-dll-api.cc:1735 //ivl_nexus_get_private() -unusedFunction:t-dll-api.cc:1690 +unusedFunction:t-dll-api.cc:1756 //ivl_nexus_name() -unusedFunction:t-dll-api.cc:1679 +unusedFunction:t-dll-api.cc:1745 //ivl_nexus_ptr_branch() -unusedFunction:t-dll-api.cc:1733 +unusedFunction:t-dll-api.cc:1799 //ivl_nexus_ptr_con() -unusedFunction:t-dll-api.cc:1742 +unusedFunction:t-dll-api.cc:1808 //ivl_nexus_ptr_sig() -unusedFunction:t-dll-api.cc:1769 +unusedFunction:t-dll-api.cc:1835 //ivl_nexus_ptr_switch() -unusedFunction:t-dll-api.cc:1778 +unusedFunction:t-dll-api.cc:1844 //ivl_nexus_set_private() -unusedFunction:t-dll-api.cc:1696 +unusedFunction:t-dll-api.cc:1762 //ivl_parameter_basename() -unusedFunction:t-dll-api.cc:1787 +unusedFunction:t-dll-api.cc:1853 //ivl_parameter_expr() -unusedFunction:t-dll-api.cc:1830 +unusedFunction:t-dll-api.cc:1896 //ivl_parameter_file() -unusedFunction:t-dll-api.cc:1836 +unusedFunction:t-dll-api.cc:1902 //ivl_parameter_lineno() -unusedFunction:t-dll-api.cc:1842 +unusedFunction:t-dll-api.cc:1908 //ivl_parameter_local() -unusedFunction:t-dll-api.cc:1793 +unusedFunction:t-dll-api.cc:1859 //ivl_parameter_lsb() -unusedFunction:t-dll-api.cc:1811 +unusedFunction:t-dll-api.cc:1877 //ivl_parameter_msb() -unusedFunction:t-dll-api.cc:1805 +unusedFunction:t-dll-api.cc:1871 //ivl_parameter_scope() -unusedFunction:t-dll-api.cc:1848 +unusedFunction:t-dll-api.cc:1914 //ivl_parameter_signed() -unusedFunction:t-dll-api.cc:1799 +unusedFunction:t-dll-api.cc:1865 //ivl_parameter_width() -unusedFunction:t-dll-api.cc:1821 +unusedFunction:t-dll-api.cc:1887 //ivl_path_condit() -unusedFunction:t-dll-api.cc:1854 +unusedFunction:t-dll-api.cc:1920 //ivl_path_delay() -unusedFunction:t-dll-api.cc:1866 +unusedFunction:t-dll-api.cc:1932 //ivl_path_is_condit() -unusedFunction:t-dll-api.cc:1860 +unusedFunction:t-dll-api.cc:1926 //ivl_path_scope() -unusedFunction:t-dll-api.cc:1872 +unusedFunction:t-dll-api.cc:1938 //ivl_path_source() -unusedFunction:t-dll-api.cc:1879 +unusedFunction:t-dll-api.cc:1945 //ivl_path_source_negedge() -unusedFunction:t-dll-api.cc:1889 +unusedFunction:t-dll-api.cc:1957 //ivl_path_source_posedge() -unusedFunction:t-dll-api.cc:1884 +unusedFunction:t-dll-api.cc:1951 //ivl_process_analog() -unusedFunction:t-dll-api.cc:1911 +unusedFunction:t-dll-api.cc:1981 //ivl_process_attr_cnt() -unusedFunction:t-dll-api.cc:1926 +unusedFunction:t-dll-api.cc:1999 //ivl_process_attr_val() -unusedFunction:t-dll-api.cc:1931 +unusedFunction:t-dll-api.cc:2005 //ivl_process_file() -unusedFunction:t-dll-api.cc:1894 +unusedFunction:t-dll-api.cc:1963 //ivl_process_lineno() -unusedFunction:t-dll-api.cc:1900 +unusedFunction:t-dll-api.cc:1969 //ivl_process_scope() -unusedFunction:t-dll-api.cc:1916 +unusedFunction:t-dll-api.cc:1987 //ivl_process_stmt() -unusedFunction:t-dll-api.cc:1921 +unusedFunction:t-dll-api.cc:1993 //ivl_process_type() -unusedFunction:t-dll-api.cc:1906 +unusedFunction:t-dll-api.cc:1975 //ivl_scope_attr_cnt() -unusedFunction:t-dll-api.cc:1938 +unusedFunction:t-dll-api.cc:2013 //ivl_scope_attr_val() -unusedFunction:t-dll-api.cc:1944 +unusedFunction:t-dll-api.cc:2019 //ivl_scope_basename() -unusedFunction:t-dll-api.cc:1951 -//ivl_scope_child() -unusedFunction:t-dll-api.cc:1978 -//ivl_scope_children() -unusedFunction:t-dll-api.cc:1958 -//ivl_scope_childs() -unusedFunction:t-dll-api.cc:1972 -//ivl_scope_class() -unusedFunction:t-dll-api.cc:1984 -//ivl_scope_classes() -unusedFunction:t-dll-api.cc:1990 -//ivl_scope_def() -unusedFunction:t-dll-api.cc:1996 -//ivl_scope_def_file() -unusedFunction:t-dll-api.cc:2002 -//ivl_scope_def_lineno() -unusedFunction:t-dll-api.cc:2008 -//ivl_scope_enumerate() -unusedFunction:t-dll-api.cc:2020 -//ivl_scope_enumerates() -unusedFunction:t-dll-api.cc:2014 -//ivl_scope_event() -unusedFunction:t-dll-api.cc:2033 -//ivl_scope_events() unusedFunction:t-dll-api.cc:2027 +//ivl_scope_child() +unusedFunction:t-dll-api.cc:2054 +//ivl_scope_children() +unusedFunction:t-dll-api.cc:2033 +//ivl_scope_childs() +unusedFunction:t-dll-api.cc:2047 +//ivl_scope_class() +unusedFunction:t-dll-api.cc:2061 +//ivl_scope_classes() +unusedFunction:t-dll-api.cc:2068 +//ivl_scope_def() +unusedFunction:t-dll-api.cc:2075 +//ivl_scope_def_file() +unusedFunction:t-dll-api.cc:2081 +//ivl_scope_def_lineno() +unusedFunction:t-dll-api.cc:2087 +//ivl_scope_enumerate() +unusedFunction:t-dll-api.cc:2099 +//ivl_scope_enumerates() +unusedFunction:t-dll-api.cc:2093 +//ivl_scope_event() +unusedFunction:t-dll-api.cc:2112 +//ivl_scope_events() +unusedFunction:t-dll-api.cc:2106 //ivl_scope_file() -unusedFunction:t-dll-api.cc:2040 +unusedFunction:t-dll-api.cc:2119 +//ivl_scope_func_signed +unusedFunction:t-dll-api.cc:2132 +//ivl_scope_func_type +unusedFunction:t-dll-api.cc:2125 +//ivl_scope_func_width +unusedFunction:t-dll-api.cc:2140 //ivl_scope_is_auto() -unusedFunction:t-dll-api.cc:2046 +unusedFunction:t-dll-api.cc:2148 //ivl_scope_is_cell() -unusedFunction:t-dll-api.cc:2052 +unusedFunction:t-dll-api.cc:2154 //ivl_scope_lineno() -unusedFunction:t-dll-api.cc:2058 -//ivl_scope_log() -unusedFunction:t-dll-api.cc:2070 -//ivl_scope_logs() -unusedFunction:t-dll-api.cc:2064 -//ivl_scope_lpm() -unusedFunction:t-dll-api.cc:2083 -//ivl_scope_lpms() -unusedFunction:t-dll-api.cc:2077 -//ivl_scope_mod_module_port_name() unusedFunction:t-dll-api.cc:2160 +//ivl_scope_log() +unusedFunction:t-dll-api.cc:2172 +//ivl_scope_logs() +unusedFunction:t-dll-api.cc:2166 +//ivl_scope_lpm() +unusedFunction:t-dll-api.cc:2185 +//ivl_scope_lpms() +unusedFunction:t-dll-api.cc:2179 +//ivl_scope_mod_module_port_name() +unusedFunction:t-dll-api.cc:2264 //ivl_scope_mod_module_port_type() -unusedFunction:t-dll-api.cc:2169 +unusedFunction:t-dll-api.cc:2273 //ivl_scope_mod_module_port_width() -unusedFunction:t-dll-api.cc:2180 +unusedFunction:t-dll-api.cc:2285 //ivl_scope_mod_module_ports() -unusedFunction:t-dll-api.cc:2153 +unusedFunction:t-dll-api.cc:2257 //ivl_scope_mod_port() -unusedFunction:t-dll-api.cc:2204 +unusedFunction:t-dll-api.cc:2310 //ivl_scope_param() -unusedFunction:t-dll-api.cc:2139 +unusedFunction:t-dll-api.cc:2243 //ivl_scope_params() -unusedFunction:t-dll-api.cc:2133 +unusedFunction:t-dll-api.cc:2237 //ivl_scope_parent() -unusedFunction:t-dll-api.cc:2146 -//ivl_scope_port() -unusedFunction:t-dll-api.cc:2195 -//ivl_scope_ports() -unusedFunction:t-dll-api.cc:2186 -//ivl_scope_sig() -unusedFunction:t-dll-api.cc:2218 -//ivl_scope_sigs() -unusedFunction:t-dll-api.cc:2212 -//ivl_scope_switch() -unusedFunction:t-dll-api.cc:2231 -//ivl_scope_switches() -unusedFunction:t-dll-api.cc:2225 -//ivl_scope_time_precision() -unusedFunction:t-dll-api.cc:2238 -//ivl_scope_time_units() -unusedFunction:t-dll-api.cc:2244 -//ivl_scope_tname() -unusedFunction:t-dll-api.cc:2256 -//ivl_scope_type() unusedFunction:t-dll-api.cc:2250 +//ivl_scope_port() +unusedFunction:t-dll-api.cc:2301 +//ivl_scope_ports() +unusedFunction:t-dll-api.cc:2292 +//ivl_scope_sig() +unusedFunction:t-dll-api.cc:2324 +//ivl_scope_sigs() +unusedFunction:t-dll-api.cc:2318 +//ivl_scope_switch() +unusedFunction:t-dll-api.cc:2337 +//ivl_scope_switches() +unusedFunction:t-dll-api.cc:2331 +//ivl_scope_time_precision() +unusedFunction:t-dll-api.cc:2344 +//ivl_scope_time_units() +unusedFunction:t-dll-api.cc:2350 +//ivl_scope_tname() +unusedFunction:t-dll-api.cc:2362 +//ivl_scope_type() +unusedFunction:t-dll-api.cc:2356 //ivl_signal_array_addr_swapped() -unusedFunction:t-dll-api.cc:2272 -//ivl_signal_array_base() -unusedFunction:t-dll-api.cc:2262 -//ivl_signal_array_count() -unusedFunction:t-dll-api.cc:2267 -//ivl_signal_attr() -unusedFunction:t-dll-api.cc:2287 -//ivl_signal_attr_cnt() -unusedFunction:t-dll-api.cc:2302 -//ivl_signal_attr_val() -unusedFunction:t-dll-api.cc:2307 -//ivl_signal_basename() -unusedFunction:t-dll-api.cc:2313 -//ivl_signal_data_type() -unusedFunction:t-dll-api.cc:2447 -//ivl_signal_dimensions() -unusedFunction:t-dll-api.cc:2277 -//ivl_signal_discipline() -unusedFunction:t-dll-api.cc:2282 -//ivl_signal_file() -unusedFunction:t-dll-api.cc:2425 -//ivl_signal_forced_net() -unusedFunction:t-dll-api.cc:2420 -//ivl_signal_integer() -unusedFunction:t-dll-api.cc:2437 -//ivl_signal_lineno() -unusedFunction:t-dll-api.cc:2431 -//ivl_signal_local() -unusedFunction:t-dll-api.cc:2410 -//ivl_signal_lsb() unusedFunction:t-dll-api.cc:2380 +//ivl_signal_array_base() +unusedFunction:t-dll-api.cc:2368 +//ivl_signal_array_count() +unusedFunction:t-dll-api.cc:2374 +//ivl_signal_attr() +unusedFunction:t-dll-api.cc:2398 +//ivl_signal_attr_cnt() +unusedFunction:t-dll-api.cc:2414 +//ivl_signal_attr_val() +unusedFunction:t-dll-api.cc:2420 +//ivl_signal_basename() +unusedFunction:t-dll-api.cc:2427 +//ivl_signal_data_type() +unusedFunction:t-dll-api.cc:2578 +//ivl_signal_dimensions() +unusedFunction:t-dll-api.cc:2386 +//ivl_signal_discipline() +unusedFunction:t-dll-api.cc:2392 +//ivl_signal_file() +unusedFunction:t-dll-api.cc:2555 +//ivl_signal_forced_net() +unusedFunction:t-dll-api.cc:2549 +//ivl_signal_integer() +unusedFunction:t-dll-api.cc:2567 +//ivl_signal_lineno() +unusedFunction:t-dll-api.cc:2561 +//ivl_signal_local() +unusedFunction:t-dll-api.cc:2536 +//ivl_signal_lsb() +unusedFunction:t-dll-api.cc:2501 //ivl_signal_module_port_index() -unusedFunction:t-dll-api.cc:2405 +unusedFunction:t-dll-api.cc:2530 //ivl_signal_msb() -unusedFunction:t-dll-api.cc:2371 +unusedFunction:t-dll-api.cc:2491 //ivl_signal_name() -unusedFunction:t-dll-api.cc:2318 +unusedFunction:t-dll-api.cc:2433 //ivl_signal_nex() -unusedFunction:t-dll-api.cc:2338 +unusedFunction:t-dll-api.cc:2454 //ivl_signal_npath() -unusedFunction:t-dll-api.cc:2457 +unusedFunction:t-dll-api.cc:2591 //ivl_signal_packed_dimensions() -unusedFunction:t-dll-api.cc:2354 +unusedFunction:t-dll-api.cc:2471 //ivl_signal_packed_lsb() -unusedFunction:t-dll-api.cc:2365 +unusedFunction:t-dll-api.cc:2484 //ivl_signal_packed_msb() -unusedFunction:t-dll-api.cc:2359 +unusedFunction:t-dll-api.cc:2477 //ivl_signal_path() -unusedFunction:t-dll-api.cc:2462 +unusedFunction:t-dll-api.cc:2597 //ivl_signal_port() -unusedFunction:t-dll-api.cc:2400 +unusedFunction:t-dll-api.cc:2524 //ivl_signal_scope() -unusedFunction:t-dll-api.cc:2389 +unusedFunction:t-dll-api.cc:2511 //ivl_signal_signed() -unusedFunction:t-dll-api.cc:2415 +unusedFunction:t-dll-api.cc:2542 //ivl_signal_width() -unusedFunction:t-dll-api.cc:2395 +unusedFunction:t-dll-api.cc:2517 //ivl_statement_type() -unusedFunction:t-dll-api.cc:2473 +unusedFunction:t-dll-api.cc:2610 //ivl_stmt_block_count() -unusedFunction:t-dll-api.cc:2502 +unusedFunction:t-dll-api.cc:2643 //ivl_stmt_block_scope() -unusedFunction:t-dll-api.cc:2488 +unusedFunction:t-dll-api.cc:2628 //ivl_stmt_block_stmt() -unusedFunction:t-dll-api.cc:2516 +unusedFunction:t-dll-api.cc:2658 //ivl_stmt_call() -unusedFunction:t-dll-api.cc:2531 +unusedFunction:t-dll-api.cc:2674 //ivl_stmt_case_count() -unusedFunction:t-dll-api.cc:2551 +unusedFunction:t-dll-api.cc:2695 //ivl_stmt_case_expr() -unusedFunction:t-dll-api.cc:2565 +unusedFunction:t-dll-api.cc:2710 //ivl_stmt_case_stmt() -unusedFunction:t-dll-api.cc:2581 +unusedFunction:t-dll-api.cc:2727 //ivl_stmt_cond_expr() -unusedFunction:t-dll-api.cc:2597 +unusedFunction:t-dll-api.cc:2744 //ivl_stmt_cond_false() -unusedFunction:t-dll-api.cc:2623 +unusedFunction:t-dll-api.cc:2771 //ivl_stmt_cond_true() -unusedFunction:t-dll-api.cc:2632 +unusedFunction:t-dll-api.cc:2781 //ivl_stmt_delay_expr() -unusedFunction:t-dll-api.cc:2641 +unusedFunction:t-dll-api.cc:2791 //ivl_stmt_delay_val() -unusedFunction:t-dll-api.cc:2657 +unusedFunction:t-dll-api.cc:2808 //ivl_stmt_events() -unusedFunction:t-dll-api.cc:2681 +unusedFunction:t-dll-api.cc:2834 //ivl_stmt_file() -unusedFunction:t-dll-api.cc:2478 +unusedFunction:t-dll-api.cc:2616 //ivl_stmt_lexp() -unusedFunction:t-dll-api.cc:2708 -//ivl_stmt_lineno() -unusedFunction:t-dll-api.cc:2483 -//ivl_stmt_lval() -unusedFunction:t-dll-api.cc:2719 -//ivl_stmt_lvals() -unusedFunction:t-dll-api.cc:2737 -//ivl_stmt_lwidth() -unusedFunction:t-dll-api.cc:2754 -//ivl_stmt_name() -unusedFunction:t-dll-api.cc:2786 -//ivl_stmt_nevent() -unusedFunction:t-dll-api.cc:2663 -//ivl_stmt_opcode() -unusedFunction:t-dll-api.cc:2798 -//ivl_stmt_parm() -unusedFunction:t-dll-api.cc:2809 -//ivl_stmt_parm_count() -unusedFunction:t-dll-api.cc:2822 -//ivl_stmt_rval() -unusedFunction:t-dll-api.cc:2833 -//ivl_stmt_sfunc_as_task() -unusedFunction:t-dll-api.cc:2850 -//ivl_stmt_sub_stmt() unusedFunction:t-dll-api.cc:2862 +//ivl_stmt_lineno() +unusedFunction:t-dll-api.cc:2622 +//ivl_stmt_lval() +unusedFunction:t-dll-api.cc:2874 +//ivl_stmt_lvals() +unusedFunction:t-dll-api.cc:2893 +//ivl_stmt_lwidth() +unusedFunction:t-dll-api.cc:2911 +//ivl_stmt_name() +unusedFunction:t-dll-api.cc:2944 +//ivl_stmt_nevent() +unusedFunction:t-dll-api.cc:2815 +//ivl_stmt_opcode() +unusedFunction:t-dll-api.cc:2957 +//ivl_stmt_parm() +unusedFunction:t-dll-api.cc:2969 +//ivl_stmt_parm_count() +unusedFunction:t-dll-api.cc:2983 +//ivl_stmt_rval() +unusedFunction:t-dll-api.cc:2995 +//ivl_stmt_sfunc_as_task() +unusedFunction:t-dll-api.cc:3013 +//ivl_stmt_sub_stmt() +unusedFunction:t-dll-api.cc:3026 //ivl_switch_a() -unusedFunction:t-dll-api.cc:2899 +unusedFunction:t-dll-api.cc:3067 //ivl_switch_b() -unusedFunction:t-dll-api.cc:2904 +unusedFunction:t-dll-api.cc:3073 //ivl_switch_basename() -unusedFunction:t-dll-api.cc:2884 +unusedFunction:t-dll-api.cc:3049 //ivl_switch_delay() -unusedFunction:t-dll-api.cc:2929 +unusedFunction:t-dll-api.cc:3103 //ivl_switch_enable() -unusedFunction:t-dll-api.cc:2909 +unusedFunction:t-dll-api.cc:3079 //ivl_switch_file() -unusedFunction:t-dll-api.cc:2935 +unusedFunction:t-dll-api.cc:3110 //ivl_switch_island() -unusedFunction:t-dll-api.cc:2940 +unusedFunction:t-dll-api.cc:3116 //ivl_switch_lineno() -unusedFunction:t-dll-api.cc:2945 +unusedFunction:t-dll-api.cc:3122 //ivl_switch_offset() -unusedFunction:t-dll-api.cc:2924 +unusedFunction:t-dll-api.cc:3097 //ivl_switch_part() -unusedFunction:t-dll-api.cc:2919 +unusedFunction:t-dll-api.cc:3091 //ivl_switch_scope() -unusedFunction:t-dll-api.cc:2889 +unusedFunction:t-dll-api.cc:3055 //ivl_switch_type() -unusedFunction:t-dll-api.cc:2894 +unusedFunction:t-dll-api.cc:3061 //ivl_switch_width() -unusedFunction:t-dll-api.cc:2914 +unusedFunction:t-dll-api.cc:3085 //ivl_type_base() -unusedFunction:t-dll-api.cc:2950 +unusedFunction:t-dll-api.cc:3128 //ivl_type_element() -unusedFunction:t-dll-api.cc:2956 +unusedFunction:t-dll-api.cc:3134 //ivl_type_name() -unusedFunction:t-dll-api.cc:2985 +unusedFunction:t-dll-api.cc:3166 //ivl_type_packed_dimensions() -unusedFunction:t-dll-api.cc:2965 +unusedFunction:t-dll-api.cc:3143 //ivl_type_packed_lsb() -unusedFunction:t-dll-api.cc:2971 +unusedFunction:t-dll-api.cc:3150 //ivl_type_packed_msb() -unusedFunction:t-dll-api.cc:2978 +unusedFunction:t-dll-api.cc:3158 //ivl_type_prop_type() -unusedFunction:t-dll-api.cc:3011 +unusedFunction:t-dll-api.cc:3191 //ivl_type_properties() -unusedFunction:t-dll-api.cc:2994 +unusedFunction:t-dll-api.cc:3174 //ivl_type_signed() -unusedFunction:t-dll-api.cc:3019 +unusedFunction:t-dll-api.cc:3199 //ivl_udp_file() -unusedFunction:t-dll-api.cc:990 +unusedFunction:t-dll-api.cc:1036 //ivl_udp_init() -unusedFunction:t-dll-api.cc:958 +unusedFunction:t-dll-api.cc:999 //ivl_udp_lineno() -unusedFunction:t-dll-api.cc:995 +unusedFunction:t-dll-api.cc:1042 //ivl_udp_name() -unusedFunction:t-dll-api.cc:984 +unusedFunction:t-dll-api.cc:1029 //ivl_udp_nin() -unusedFunction:t-dll-api.cc:953 +unusedFunction:t-dll-api.cc:993 //ivl_udp_port() -unusedFunction:t-dll-api.cc:963 +unusedFunction:t-dll-api.cc:1005 //ivl_udp_row() -unusedFunction:t-dll-api.cc:971 +unusedFunction:t-dll-api.cc:1014 //ivl_udp_rows() -unusedFunction:t-dll-api.cc:979 +unusedFunction:t-dll-api.cc:1023 // ivl_udp_sequ() -unusedFunction:t-dll-api.cc:948 +unusedFunction:t-dll-api.cc:987 diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index 82af710f0..f0fd8584d 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -45,83 +45,83 @@ variableScope:fstapi.c:6238 variableScope:fstapi.c:6466 // These functions are not used by Icarus // fstReaderClrFacProcessMask() -unusedFunction:fstapi.c:3344 +unusedFunction:fstapi.c:3345 // fstReaderClrFacProcessMaskAll() -unusedFunction:fstapi.c:3373 +unusedFunction:fstapi.c:3374 // fstReaderGetAliasCount() -unusedFunction:fstapi.c:3436 +unusedFunction:fstapi.c:3437 // fstReaderGetCurrentFlatScope() -unusedFunction:fstapi.c:3182 +unusedFunction:fstapi.c:3183 // fstReaderGetAliasCount() -unusedFunction:fstapi.c:3279 +unusedFunction:fstapi.c:3280 // fstReaderGetCurrentScopeUserInfo() -unusedFunction:fstapi.c:3196 +unusedFunction:fstapi.c:3197 // fstReaderGetDateString() -unusedFunction:fstapi.c:3464 +unusedFunction:fstapi.c:3465 // fstReaderGetDoubleEndianMatchState() -unusedFunction:fstapi.c:3450 +unusedFunction:fstapi.c:3451 // fstReaderGetDumpActivityChangeTime() -unusedFunction:fstapi.c:3492 +unusedFunction:fstapi.c:3493 // fstReaderGetDumpActivityChangeValue() -unusedFunction:fstapi.c:3507 +unusedFunction:fstapi.c:3508 // fstReaderGetEndTime() -unusedFunction:fstapi.c:3401 +unusedFunction:fstapi.c:3402 // fstReaderGetFacProcessMask() -unusedFunction:fstapi.c:3307 +unusedFunction:fstapi.c:3308 // fstReaderGetFileType() -unusedFunction:fstapi.c:3471 +unusedFunction:fstapi.c:3472 // fstReaderGetFseekFailed() -unusedFunction:fstapi.c:3292 +unusedFunction:fstapi.c:3293 // fstReaderGetMaxHandle() -unusedFunction:fstapi.c:3429 +unusedFunction:fstapi.c:3430 // fstReaderGetMemoryUsedByWriter() -unusedFunction:fstapi.c:3408 +unusedFunction:fstapi.c:3409 // fstReaderGetNumberDumpActivityChanges() -unusedFunction:fstapi.c:3485 +unusedFunction:fstapi.c:3486 // fstReaderGetScopeCount() -unusedFunction:fstapi.c:3415 +unusedFunction:fstapi.c:3416 // fstReaderGetStartTime() -unusedFunction:fstapi.c:3394 +unusedFunction:fstapi.c:3395 // fstReaderGetTimescale() -unusedFunction:fstapi.c:3387 +unusedFunction:fstapi.c:3388 // fstReaderGetTimezero() -unusedFunction:fstapi.c:3478 +unusedFunction:fstapi.c:3479 // fstReaderGetValueChangeSectionCount() -unusedFunction:fstapi.c:3443 +unusedFunction:fstapi.c:3444 // fstReaderGetValueFromHandleAtTime() -unusedFunction:fstapi.c:5685 +unusedFunction:fstapi.c:5686 // fstReaderGetVarCount() -unusedFunction:fstapi.c:3422 +unusedFunction:fstapi.c:3423 // fstReaderGetVersionString() -unusedFunction:fstapi.c:3457 +unusedFunction:fstapi.c:3458 // fstReaderIterBlocks() -unusedFunction:fstapi.c:4652 +unusedFunction:fstapi.c:4653 // fstReaderIterBlocksSetNativeDoublesOnCallback() -unusedFunction:fstapi.c:3557 +unusedFunction:fstapi.c:3558 // fstReaderIterateHier() -unusedFunction:fstapi.c:3782 +unusedFunction:fstapi.c:3783 // fstReaderIterateHierRewind() -unusedFunction:fstapi.c:3762 +unusedFunction:fstapi.c:3763 // fstReaderOpen() -unusedFunction:fstapi.c:4550 +unusedFunction:fstapi.c:4551 // fstReaderOpenForUtilitiesOnly() -unusedFunction:fstapi.c:4542 +unusedFunction:fstapi.c:4543 // fstReaderPushScope() -unusedFunction:fstapi.c:3244 +unusedFunction:fstapi.c:3245 // fstReaderResetScope() -unusedFunction:fstapi.c:3233 +unusedFunction:fstapi.c:3234 // fstReaderSetFacProcessMask() -unusedFunction:fstapi.c:3326 +unusedFunction:fstapi.c:3327 // fstReaderSetFacProcessMaskAll() -unusedFunction:fstapi.c:3362 +unusedFunction:fstapi.c:3363 // fstReaderSetLimitTimeRange() -unusedFunction:fstapi.c:3522 +unusedFunction:fstapi.c:3523 // fstReaderSetUnlimitedTimeRange() -unusedFunction:fstapi.c:3535 +unusedFunction:fstapi.c:3536 // fstReaderSetVcdExtensions() -unusedFunction:fstapi.c:3546 +unusedFunction:fstapi.c:3547 // fstUtilityEscToBin() -unusedFunction:fstapi.c:6485 +unusedFunction:fstapi.c:6544 // fstWriterCreateVar2() unusedFunction:fstapi.c:2528 // fstWriterEmitVariableLengthValueChange() @@ -232,6 +232,10 @@ unusedLabel:fastlz.c:545 // These functions are not used by Icarus // fastlz_compress_level() unusedFunction:fastlz.c:150 +// FASTLZ_COMPRESSOR() +unusedFunction:fastlz.c:162 +// FASTLZ_DECOMPRESSOR() +unusedFunction:fastlz.c:416 // lz4.c from GTKWave // These functions are not used by Icarus diff --git a/vvp/cppcheck.sup b/vvp/cppcheck.sup index 2e52e77f2..049c11041 100644 --- a/vvp/cppcheck.sup +++ b/vvp/cppcheck.sup @@ -5,3 +5,47 @@ uninitVar:vvp_net.cc:167 // These functions are not used by Icarus // __libvpi_c_dummy_function() unusedFunction:libvpi.c:24 + +// These functions are not used by Icarus +// vpi_chk_error() +unusedFunction:vpi_priv.cc:193 +// vpi_compare_objects() +unusedFunction:vpi_priv.cc:209 +// vpi_control() +unusedFunction:vpi_priv.cc:1556 +// vpi_flush() +unusedFunction:vpi_priv.cc:1519 +// vpi_fopen() +unusedFunction:vpi_mcd.cc:287 +// vpi_get_file() +unusedFunction:vpi_mcd.cc:321 +// vpi_get_systf_info() +unusedFunction:vpi_priv.cc:225 +// vpi_get_time() +unusedFunction:vpi_priv.cc:532 +// vpi_get_userdata() +unusedFunction:vpi_tasks.cc:1020 +// vpi_get_vlog_info() +unusedFunction:vpi_priv.cc:561 +// vpi_handle_by_index() +unusedFunction:vpi_priv.cc:1273 +// vpi_handle_by_name() +unusedFunction:vpi_priv.cc:1356 +// vpi_mcd_close() +unusedFunction:vpi_mcd.cc:111 +// vpi_mcd_name() +unusedFunction:vpi_mcd.cc:138 +// vpi_mcd_open() +unusedFunction:vpi_mcd.cc:153 +// vpi_put_userdata() +unusedFunction:vpi_tasks.cc:1010 +// vpi_register_cb() +unusedFunction:vpi_callback.cc:552 +// vpi_register_systf() +unusedFunction:vpi_tasks.cc:990 +// vpi_remove_cb() +unusedFunction:vpi_callback.cc:601 +// vpi_sim_control() +unusedFunction:vpi_priv.cc:1548 +// vpi_vprintf() +unusedFunction:vpi_priv.cc:1505 From 7d78f5b2ea2026ae93dc72d0920edc71caed22db Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 23 Oct 2017 00:19:45 -0700 Subject: [PATCH 042/138] A few updates based on cppcheck results --- netlist.h | 4 ++-- pform_dump.cc | 4 ++-- svector.h | 4 ++-- t-dll-api.cc | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/netlist.h b/netlist.h index 57acafd64..431b0d020 100644 --- a/netlist.h +++ b/netlist.h @@ -1,7 +1,7 @@ #ifndef IVL_netlist_H #define IVL_netlist_H /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -4561,7 +4561,7 @@ class NetESFunc : public NetExpr { bool takes_nargs_(ID func, unsigned nargs) { if (nargs > 15) nargs = 15; - return func & (1 << (nargs + 16)); + return func & (1U << (nargs + 16)); } const char* name_; diff --git a/pform_dump.cc b/pform_dump.cc index de03de673..7d57b1704 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -844,7 +844,7 @@ void PCase::dump(ostream&out, unsigned ind) const for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) { PCase::Item*cur = (*items_)[idx]; - if (cur->expr.size()) { + if (! cur->expr.empty()) { out << setw(ind+2) << "" << "default:"; } else { diff --git a/svector.h b/svector.h index 730428474..44864bda6 100644 --- a/svector.h +++ b/svector.h @@ -1,7 +1,7 @@ #ifndef IVL_svector_H #define IVL_svector_H /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -57,7 +57,7 @@ template class svector { items_[l.nitems_+idx] = r[idx]; } - svector(const svector&l, TYPE r) + svector(const svector&l, TYPE&r) : nitems_(l.nitems_ + 1), items_(new TYPE[nitems_]) { for (unsigned idx = 0 ; idx < l.nitems_ ; idx += 1) items_[idx] = l[idx]; diff --git a/t-dll-api.cc b/t-dll-api.cc index 82772e67b..1e4a0c0ec 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * @@ -2134,7 +2134,7 @@ extern "C" int ivl_scope_func_signed(ivl_scope_t net) assert(net); assert(net->type_==IVL_SCT_FUNCTION); assert(net->func_type==IVL_VT_LOGIC || net->func_type==IVL_VT_BOOL); - return net->func_signed? !0 : 0; + return net->func_signed? 1 : 0; } extern "C" unsigned ivl_scope_func_width(ivl_scope_t net) From dfddbea26b3cad01e4420385d373b6740955813f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 15 Oct 2017 11:45:35 +0100 Subject: [PATCH 043/138] First step towards supporting separate compilation units in SV. This adds a -u option to the driver to allow the user to specify that they want each source file to be treated as a separate compilation unit, and modifies the compiler to accept a list of files (either on the command line or via a file specified by a new -F option). This list of files is then preprocessed and parsed separately, causing all compiler directives (including macro definitions) to only apply to the file containing them, as required by the SystemVerilog standard. --- compiler.h | 6 ++++- driver/iverilog.man.in | 12 ++++++--- driver/main.c | 40 +++++++++++++++++++-------- lexor.lex | 29 +++++++++++++++----- load_module.cc | 33 +++-------------------- main.cc | 61 +++++++++++++++++++++++++++++++++++++++--- parse_api.h | 12 ++++----- pform.cc | 42 +++++++++++++++++++++-------- 8 files changed, 163 insertions(+), 72 deletions(-) diff --git a/compiler.h b/compiler.h index eae1ec460..6eccc8743 100644 --- a/compiler.h +++ b/compiler.h @@ -1,7 +1,7 @@ #ifndef IVL_compiler_H #define IVL_compiler_H /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -120,6 +120,10 @@ extern bool debug_optimizer; /* Ignore errors about missing modules */ extern bool ignore_missing_modules; +/* Treat each source file as a separate compilation unit (as defined + by SystemVerilog). */ +extern bool separate_compilation; + /* Control evaluation of functions at compile time: * 0 = only for functions in constant expressions * 1 = only for automatic functions diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index ba05d2a0a..47ebf4669 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,10 +1,10 @@ -.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E" +.TH iverilog 1 "Oct 14th, 2017" "" "Version %M.%n%E" .SH NAME iverilog - Icarus Verilog compiler .SH SYNOPSIS .B iverilog -[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] +[\-ESuVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]] [\-Pparameter=value] [\-pflag=value] [\-dname] [\-g1995\:|\-g2001\:|\-g2005\:|\-g2005-sv\:|\-g2009\:|\-g2012\:|\-g] [\-Iincludedir] [\-mmodule] [\-M[mode=]file] [\-Nfile] [\-ooutputfilename] @@ -222,6 +222,12 @@ will suppress the warning that the compiler is making a choice. Use this switch to specify the target output format. See the \fBTARGETS\fP section below for a list of valid output formats. .TP 8 +.B -u +Treat each source file as a separate compilation unit (as defined in +SystemVerilog). If compiling for an \fIIEEE1364\fP generation, this +will just reset all compiler directives (including macro definitions) +before each new file is processed. +.TP 8 .B -v Turn on verbose messages. This will print the command lines that are executed to perform the actual compilation, along with version @@ -564,7 +570,7 @@ Tips on using, debugging, and developing the compiler can be found at .SH COPYRIGHT .nf -Copyright \(co 2002\-2016 Stephen Williams +Copyright \(co 2002\-2017 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/driver/main.c b/driver/main.c index bda5697ca..fa038bfe6 100644 --- a/driver/main.c +++ b/driver/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -38,7 +38,7 @@ const char NOTICE[] = ; const char HELP[] = -"Usage: iverilog [-EiSvV] [-B base] [-c cmdfile|-f cmdfile]\n" +"Usage: iverilog [-EiSuvV] [-B base] [-c cmdfile|-f cmdfile]\n" " [-g1995|-g2001|-g2005|-g2005-sv|-g2009|-g2012] [-g]\n" " [-D macro[=defn]] [-I includedir]\n" " [-M [mode=]depfile] [-m module]\n" @@ -140,6 +140,8 @@ int gen_relative_include = 0; char warning_flags[16] = "n"; +int separate_compilation_flag = 0; + /* Boolean: true means ignore errors about missing modules */ int ignore_missing_modules = 0; @@ -344,10 +346,10 @@ static int t_version_only(void) static void build_preprocess_command(int e_flag) { - snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\" ", + snprintf(tmp, sizeof tmp, "%s%civlpp %s%s -F\"%s\" -f\"%s\" -p\"%s\"%s", ivlpp_dir, sep, verbose_flag?" -v":"", e_flag?"":" -L", defines_path, source_path, - compiled_defines_path); + compiled_defines_path, e_flag?"":" | "); } static int t_preprocess_only(void) @@ -410,8 +412,12 @@ static int t_compile(void) { unsigned rc; - /* Start by building the preprocess command line. */ - build_preprocess_command(0); + /* Start by building the preprocess command line, if required. + This pipes into the main ivl command. */ + if (!separate_compilation_flag) + build_preprocess_command(0); + else + strcpy(tmp, ""); size_t ncmd = strlen(tmp); char*cmd = malloc(ncmd + 1); @@ -421,8 +427,8 @@ static int t_compile(void) int rtn; #endif - /* Build the ivl command and pipe it to the preprocessor. */ - snprintf(tmp, sizeof tmp, " | %s%civl", base, sep); + /* Build the ivl command. */ + snprintf(tmp, sizeof tmp, "%s%civl", base, sep); rc = strlen(tmp); cmd = realloc(cmd, ncmd+rc+1); strcpy(cmd+ncmd, tmp); @@ -450,7 +456,16 @@ static int t_compile(void) strcpy(cmd+ncmd, tmp); ncmd += rc; - snprintf(tmp, sizeof tmp, " -C\"%s\" -- -", iconfig_common_path); + snprintf(tmp, sizeof tmp, " -C\"%s\"", iconfig_common_path); + rc = strlen(tmp); + cmd = realloc(cmd, ncmd+rc+1); + strcpy(cmd+ncmd, tmp); + ncmd += rc; + + if (separate_compilation_flag) + snprintf(tmp, sizeof tmp, " -F\"%s\"", source_path); + else + snprintf(tmp, sizeof tmp, " -- -"); rc = strlen(tmp); cmd = realloc(cmd, ncmd+rc+1); strcpy(cmd+ncmd, tmp); @@ -990,7 +1005,7 @@ int main(int argc, char **argv) } } - while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iM:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) { + while ((opt = getopt(argc, argv, "B:c:D:d:Ef:g:hl:I:iM:m:N:o:P:p:Ss:T:t:uvVW:y:Y:")) != EOF) { switch (opt) { case 'B': @@ -1093,6 +1108,9 @@ int main(int argc, char **argv) case 't': targ = optarg; break; + case 'u': + separate_compilation_flag = 1; + break; case 'v': verbose_flag = 1; break; @@ -1135,7 +1153,7 @@ int main(int argc, char **argv) if (version_flag || verbose_flag) { printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n"); - printf("Copyright 1998-2015 Stephen Williams\n\n"); + printf("Copyright 1998-2017 Stephen Williams\n\n"); puts(NOTICE); } diff --git a/lexor.lex b/lexor.lex index 06d9b1744..bac72dedd 100644 --- a/lexor.lex +++ b/lexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -72,6 +72,7 @@ static const char* set_file_name(char*text) void reset_lexor(); static void line_directive(); static void line_directive2(); +static void reset_all(); verinum*make_unsized_binary(const char*txt); verinum*make_undef_highz_dec(const char*txt); @@ -566,11 +567,7 @@ TU [munpf] "definition." << endl; error_count += 1; } else { - pform_set_default_nettype(NetNet::WIRE, yylloc.text, - yylloc.first_line); - in_celldefine = false; - uc_drive = UCD_NONE; - pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); + reset_all(); } } /* Notice and handle the `unconnected_drive directive. */ @@ -1597,6 +1594,18 @@ static void line_directive2() yylloc.first_line = lineno; } +/* + * Reset all compiler directives. This will be called when a `resetall + * directive is encountered or when a new compilation unit is started. + */ +static void reset_all() +{ + pform_set_default_nettype(NetNet::WIRE, yylloc.text, yylloc.first_line); + in_celldefine = false; + uc_drive = UCD_NONE; + pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); +} + extern FILE*vl_input; void reset_lexor() { @@ -1605,6 +1614,14 @@ void reset_lexor() /* Announce the first file name. */ yylloc.text = set_file_name(strdupnew(vl_file.c_str())); + + if (separate_compilation) { + reset_all(); + if (!keyword_mask_stack.empty()) { + lexor_keyword_mask = keyword_mask_stack.back(); + keyword_mask_stack.clear(); + } + } } /* diff --git a/load_module.cc b/load_module.cc index 665b865e9..b285302f2 100644 --- a/load_module.cc +++ b/load_module.cc @@ -82,36 +82,10 @@ bool load_module(const char*type) fflush(depend_file); } - if (ivlpp_string) { - char*cmdline = (char*)malloc(strlen(ivlpp_string) + - strlen(path) + 4); - strcpy(cmdline, ivlpp_string); - strcat(cmdline, " \""); - strcat(cmdline, path); - strcat(cmdline, "\""); + if (verbose_flag) + cerr << "Loading library file " << path << "." << endl; - if (verbose_flag) - cerr << "Executing: " << cmdline << endl<< flush; - - FILE*file = popen(cmdline, "r"); - - if (verbose_flag) - cerr << "...parsing output from preprocessor..." << endl << flush; - - pform_parse(path, file); - pclose(file); - free(cmdline); - - } else { - if (verbose_flag) - cerr << "Loading library file " - << path << "." << endl; - - FILE*file = fopen(path, "r"); - assert(file); - pform_parse(path, file); - fclose(file); - } + pform_parse(path); if (verbose_flag) cerr << "... Load module complete." << endl << flush; @@ -119,7 +93,6 @@ bool load_module(const char*type) return true; } - return false; } diff --git a/main.cc b/main.cc index e80ba1983..5a87b3266 100644 --- a/main.cc +++ b/main.cc @@ -140,6 +140,8 @@ void add_vpi_module(const char*name) map missing_modules; map library_file_map; +vector source_files; + list library_suff; list roots; @@ -179,6 +181,11 @@ bool debug_emit = false; bool debug_synth2 = false; bool debug_optimizer = false; +/* + * Compilation control flags. + */ +bool separate_compilation = false; + /* * Optimization control flags. */ @@ -777,6 +784,38 @@ static void read_iconfig_file(const char*ipath) fclose(ifile); } +/* + * This function reads a list of source file names. Each name starts + * with the first non-space character, and ends with the last non-space + * character. Spaces in the middle are OK. + */ +static void read_sources_file(const char*path) +{ + char line_buf[2048]; + + FILE*fd = fopen(path, "r"); + if (fd == 0) { + cerr << "ERROR: Unable to read source file list: " << path << endl; + return; + } + + while (fgets(line_buf, sizeof line_buf, fd) != 0) { + char*cp = line_buf + strspn(line_buf, " \t\r\b\f"); + char*tail = cp + strlen(cp); + while (tail > cp) { + if (! isspace((int)tail[-1])) + break; + tail -= 1; + tail[0] = 0; + } + + if (cp < tail) + source_files.push_back(filename_strings.make(cp)); + } + + fclose(fd); +} + extern Design* elaborate(list root); #if defined(HAVE_TIMES) @@ -863,12 +902,14 @@ int main(int argc, char*argv[]) min_typ_max_flag = TYP; min_typ_max_warn = 10; - while ((opt = getopt(argc, argv, "C:f:hN:P:p:Vv")) != EOF) switch (opt) { + while ((opt = getopt(argc, argv, "C:F:f:hN:P:p:Vv")) != EOF) switch (opt) { case 'C': read_iconfig_file(optarg); break; - + case 'F': + read_sources_file(optarg); + break; case 'f': parm_to_flagmap(optarg); break; @@ -921,6 +962,7 @@ int main(int argc, char*argv[]) "usage: ivl \n" "options:\n" "\t-C Config file from driver.\n" +"\t-F List of source files from driver.\n" "\t-h Print usage information, and exit.\n" "\t-N Dump the elaborated netlist to .\n" "\t-P Write the parsed input to .\n" @@ -936,11 +978,19 @@ int main(int argc, char*argv[]) return 0; } - if (optind == argc) { + int arg = optind; + while (arg < argc) { + perm_string path = filename_strings.make(argv[arg++]); + source_files.push_back(path); + } + + if (source_files.empty()) { cerr << "No input files." << endl; return 1; } + separate_compilation = source_files.size() > 1; + if( depfile_name ) { depend_file = fopen(depfile_name, "a"); if(! depend_file) { @@ -1036,7 +1086,10 @@ int main(int argc, char*argv[]) /* Parse the input. Make the pform. */ pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); - int rc = pform_parse(argv[optind]); + int rc = 0; + for (unsigned idx = 0; idx < source_files.size(); idx += 1) { + rc += pform_parse(source_files[idx]); + } if (pf_path) { ofstream out (pf_path); diff --git a/parse_api.h b/parse_api.h index 87ae28d11..25be3f57f 100644 --- a/parse_api.h +++ b/parse_api.h @@ -57,13 +57,13 @@ extern void elaborate_rootscope_classes(Design*des); extern void elaborate_rootscope_tasks(Design*des); /* - * This code actually invokes the parser to make modules. The first - * parameter is the name of the file that is to be parsed. The - * optional second parameter is the opened descriptor for the file. If - * the descriptor is 0 (or skipped) then the function will attempt to - * open the file on its own. + * This code actually invokes the parser to make modules. If the path + * parameter is "-", the parser reads from stdin, otherwise it attempts + * to open and read the specified file. When reading from a file, if + * the ivlpp_string variable is not set to null, the file will be piped + * through the command specified by ivlpp_string before being parsed. */ -extern int pform_parse(const char*path, FILE*file =0); +extern int pform_parse(const char*path); extern string vl_file; diff --git a/pform.cc b/pform.cc index 0478fba79..ed10b46e9 100644 --- a/pform.cc +++ b/pform.cc @@ -3715,22 +3715,38 @@ void pform_add_modport_port(const struct vlltype&loc, FILE*vl_input = 0; extern void reset_lexor(); -int pform_parse(const char*path, FILE*file) +int pform_parse(const char*path) { vl_file = path; - if (file == 0) { + if (strcmp(path, "-") == 0) { + vl_input = stdin; + } else if (ivlpp_string) { + char*cmdline = (char*)malloc(strlen(ivlpp_string) + + strlen(path) + 4); + strcpy(cmdline, ivlpp_string); + strcat(cmdline, " \""); + strcat(cmdline, path); + strcat(cmdline, "\""); - if (strcmp(path, "-") == 0) - vl_input = stdin; - else - vl_input = fopen(path, "r"); + if (verbose_flag) + cerr << "Executing: " << cmdline << endl<< flush; + + vl_input = popen(cmdline, "r"); if (vl_input == 0) { - cerr << "Unable to open " < Date: Sat, 21 Oct 2017 15:04:25 +0100 Subject: [PATCH 044/138] Support separate compilation units in SystemVerilog. The compilation unit scope is now treated as a specialised form of package (with an automatically generated name). All items declared outside a design element are added to the current compilation unit package. Apart from when searching for a symbol, once we get into elaboration we can treat these just like any other package. --- design_dump.cc | 16 +--- elab_scope.cc | 81 ++---------------- elab_sig.cc | 26 +----- elab_type.cc | 13 ++- elaborate.cc | 72 ++++++++-------- emit.cc | 20 +---- ivl_target_priv.h | 3 +- main.cc | 16 ---- net_design.cc | 207 +++++++++++++++++++++++++++------------------- net_scope.cc | 45 +++++----- netlist.h | 55 ++++++------ parse_api.h | 9 +- pform.cc | 138 ++++++++++--------------------- symbol_search.cc | 17 ++-- t-dll-api.cc | 5 +- t-dll.cc | 42 +--------- 16 files changed, 283 insertions(+), 482 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 44a9b8ddc..d42f61485 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -1390,6 +1390,8 @@ void NetScope::dump(ostream&o) const if (is_interface()) o << " (interface)"; o << " " << children_.size() << " children, " << classes_.size() << " classes" << endl; + if (unit() && !is_unit()) + o << " in compilation unit " << unit()->basename() << endl; for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1) o << " (* " << attr_key(idx) << " = " @@ -1902,18 +1904,6 @@ void Design::dump(ostream&o) const cur->second->dump(o); } - o << "$ROOT CLASSES:" << endl; - for (map::const_iterator cur = classes_.begin() - ; cur != classes_.end() ; ++cur) { - cur->second->dump_scope(o); - } - - o << "$ROOT TASKS/FUNCTIONS:" << endl; - for (map::const_iterator cur = root_tasks_.begin() - ; cur != root_tasks_.end() ; ++ cur) { - cur->first->dump(o); - } - o << "SCOPES:" << endl; for (list::const_iterator scope = root_scopes_.begin(); scope != root_scopes_.end(); ++ scope ) { diff --git a/elab_scope.cc b/elab_scope.cc index 53ebf37af..7917ea2df 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -167,8 +167,7 @@ static void collect_scope_specparams_(Design*des, NetScope*scope, } /* - * Elaborate the enumeration into the given scope. If scope==0, then - * the enumeration goes into $root instead of a scope. + * Elaborate the enumeration into the given scope. */ static void elaborate_scope_enumeration(Design*des, NetScope*scope, enum_type_t*enum_type) @@ -193,10 +192,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, enum_type); use_enum->set_line(enum_type->li); - if (scope) - scope->add_enumeration_set(enum_type, use_enum); - else - des->add_enumeration_set(enum_type, use_enum); + scope->add_enumeration_set(enum_type, use_enum); size_t name_idx = 0; // Find the enumeration width. @@ -364,10 +360,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, } rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value); - if (scope) - rc_flag &= scope->add_enumeration_name(use_enum, cur->name); - else - rc_flag &= des->add_enumeration_name(use_enum, cur->name); + rc_flag &= scope->add_enumeration_name(use_enum, cur->name); if (! rc_flag) { cerr << use_enum->get_fileline() @@ -397,15 +390,6 @@ static void elaborate_scope_enumerations(Design*des, NetScope*scope, } } -void elaborate_rootscope_enumerations(Design*des) -{ - for (set::const_iterator cur = pform_enum_sets.begin() - ; cur != pform_enum_sets.end() ; ++ cur) { - enum_type_t*curp = *cur; - elaborate_scope_enumeration(des, 0, curp); - } -} - /* * If the pclass includes an implicit and explicit constructor, then * merge the implicit constructor into the explicit constructor as @@ -509,10 +493,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) netclass_t*use_base_class = 0; if (base_class) { - if (scope) - use_base_class = scope->find_class(base_class->name); - if (use_base_class == 0) - use_base_class = des->find_class(base_class->name); + use_base_class = scope->find_class(base_class->name); if (use_base_class == 0) { cerr << pclass->get_fileline() << ": error: " << "Base class " << base_class->name @@ -527,9 +508,10 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) use_type->save_elaborated_type = use_class; // Class scopes have no parent scope, because references are - // not allowed to escape a class method. + // not allowed to escape a class method. But they are allowed + // to reference the compilation unit scope. NetScope*class_scope = new NetScope(0, hname_t(pclass->pscope_name()), - NetScope::CLASS); + NetScope::CLASS, scope->unit()); class_scope->set_line(pclass); class_scope->set_class_def(use_class); use_class->set_class_scope(class_scope); @@ -588,12 +570,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass) cur->second->elaborate_scope(des, method_scope); } - if (scope) { - scope->add_class(use_class); - - } else { - des->add_class(use_class, pclass); - } + scope->add_class(use_class); } static void elaborate_scope_classes(Design*des, NetScope*scope, @@ -605,14 +582,6 @@ static void elaborate_scope_classes(Design*des, NetScope*scope, } } -void elaborate_rootscope_classes(Design*des) -{ - for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { - blend_class_constructors(pform_classes[idx]); - elaborate_scope_class(des, 0, pform_classes[idx]); - } -} - static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc, const Module::replace_t&replacements) { @@ -662,11 +631,6 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task) task_scope->is_auto(task->is_auto()); task_scope->set_line(task); - if (scope==0) { - set_scope_timescale(des, task_scope, task); - des->add_root_task(task_scope, task); - } - if (debug_scopes) { cerr << task->get_fileline() << ": elaborate_scope_task: " << "Elaborate task scope " << scope_path(task_scope) << endl; @@ -729,11 +693,6 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task) task_scope->is_auto(task->is_auto()); task_scope->set_line(task); - if (scope==0) { - set_scope_timescale(des, task_scope, task); - des->add_root_task(task_scope, task); - } - if (debug_scopes) { cerr << task->get_fileline() << ": elaborate_scope_func: " << "Elaborate task scope " << scope_path(task_scope) << endl; @@ -789,28 +748,6 @@ static void elaborate_scope_funcs(Design*des, NetScope*scope, } -void elaborate_rootscope_tasks(Design*des) -{ - for (map::iterator cur = pform_tasks.begin() - ; cur != pform_tasks.end() ; ++ cur) { - - if (PTask*task = dynamic_cast (cur->second)) { - elaborate_scope_task(des, 0, task); - continue; - } - - if (PFunction*func = dynamic_cast(cur->second)) { - elaborate_scope_func(des, 0, func); - continue; - } - - cerr << cur->second->get_fileline() << ": internal error: " - << "elaborate_rootscope_tasks does not understand " - << "this object," << endl; - des->errors += 1; - } -} - class generate_schemes_work_item_t : public elaborator_work_item_t { public: generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod) @@ -1756,7 +1693,7 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s // Create the new scope as a MODULE with my name. Note // that if this is a nested module, mark it thus so that // scope searches will continue into the parent scope. - NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, + NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0, bound_type_? true : false, mod->program_block, mod->is_interface); diff --git a/elab_sig.cc b/elab_sig.cc index e92ad6667..efe1997a4 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1333,27 +1333,3 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const return sig; } - - -void Design::root_elaborate_sig(void) -{ - for (map::const_iterator cur = classes_.begin() - ; cur != classes_.end() ; ++ cur) { - - netclass_t*cur_class = cur->second; - PClass*cur_pclass = class_to_pclass_[cur_class]; - - cur_class->elaborate_sig(this, cur_pclass); - } - - for (map::iterator cur = root_tasks_.begin() - ; cur != root_tasks_.end() ; ++ cur) { - - if (debug_elaborate) { - cerr << cur->second->get_fileline() << ": root_elaborate_sig: " - << "Elaborate_sig for root task/func " << scope_path(cur->first) << endl; - } - - cur->second->elaborate_sig(this, cur->first); - } -} diff --git a/elab_type.cc b/elab_type.cc index 4c1814909..73d7842dc 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2017 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 @@ -78,9 +78,8 @@ static void elaborate_array_ranges(Design*des, NetScope*scope, */ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) { + ivl_assert(*this, scope); Definitions*use_definitions = scope; - if (use_definitions == 0) - use_definitions = des; map::iterator pos = cache_type_elaborate_.lower_bound(use_definitions); if (pos != cache_type_elaborate_.end() && pos->first == use_definitions) @@ -147,13 +146,13 @@ ivl_type_s* class_type_t::elaborate_type_raw(Design*, NetScope*) const * available at the right time. At that time, the netenum_t* object is * stashed in the scope so that I can retrieve it here. */ -ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const +ivl_type_s* enum_type_t::elaborate_type_raw(Design*, NetScope*scope) const { ivl_assert(*this, scope); ivl_type_s*tmp = scope->enumeration_for_key(this); - if (tmp) return tmp; - - tmp = des->enumeration_for_key(this); + if (tmp == 0 && scope->unit()) { + tmp = scope->unit()->enumeration_for_key(this); +} return tmp; } diff --git a/elaborate.cc b/elaborate.cc index 82b90fc7d..2e294d00d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -6170,28 +6170,6 @@ bool Design::check_proc_delay() const return result_flag; } -void Design::root_elaborate(void) -{ - for (map::const_iterator cur = classes_.begin() - ; cur != classes_.end() ; ++ cur) { - netclass_t*cur_class = cur->second; - PClass*cur_pclass = class_to_pclass_[cur_class]; - cur_class->elaborate(this, cur_pclass); - } - - for (map::iterator cur = root_tasks_.begin() - ; cur != root_tasks_.end() ; ++ cur) { - - if (debug_elaborate) { - cerr << cur->second->get_fileline() << ": Design::root_elaborate: " - << "Elaborate for root task/func " << scope_path(cur->first) << endl; - } - - cur->second->elaborate(this, cur->first); - } - -} - /* * This function is the root of all elaboration. The input is the list * of root module names. The function locates the Module definitions @@ -6211,8 +6189,13 @@ struct root_elem { Design* elaborate(listroots) { + unsigned npackages = pform_packages.size(); + if (gn_system_verilog()) + npackages += pform_units.size(); + vector root_elems(roots.size()); - vector pack_elems(pform_packages.size()); + vector pack_elems(npackages); + map unit_scopes; bool rc = true; unsigned i = 0; @@ -6220,23 +6203,36 @@ Design* elaborate(listroots) // module and elaborate what I find. Design*des = new Design; - // Elaborate enum sets in $root scope. - elaborate_rootscope_enumerations(des); + // Elaborate the compilation unit scopes. From here on, these are + // treated as an additional set of packages. + if (gn_system_verilog()) { + for (i = 0; i < pform_units.size(); i += 1) { + PPackage*unit = pform_units[i]; + NetScope*scope = des->make_package_scope(unit->pscope_name(), 0, true); + scope->set_line(unit); + set_scope_timescale(des, scope, unit); - // Elaborate tasks and functions in $root scope. - elaborate_rootscope_tasks(des); + elaborator_work_item_t*es = new elaborate_package_t(des, scope, unit); + des->elaboration_work_list.push_back(es); - // Elaborate classes in $root scope. - elaborate_rootscope_classes(des); + pack_elems[i].pack = unit; + pack_elems[i].scope = scope; + + unit_scopes[unit] = scope; + } + } // Elaborate the packages. Package elaboration is simpler - // because there are fewer sub-scopes involved. - i = 0; + // because there are fewer sub-scopes involved. Note that + // in SystemVerilog, packages are not allowed to refer to + // the compilation unit scope, but the VHDL preprocessor + // assumes they can. for (map::iterator pac = pform_packages.begin() ; pac != pform_packages.end() ; ++ pac) { ivl_assert(*pac->second, pac->first == pac->second->pscope_name()); - NetScope*scope = des->make_package_scope(pac->first); + NetScope*unit_scope = unit_scopes[pac->second->parent_scope()]; + NetScope*scope = des->make_package_scope(pac->first, unit_scope, false); scope->set_line(pac->second); set_scope_timescale(des, scope, pac->second); @@ -6267,9 +6263,13 @@ Design* elaborate(listroots) // Get the module definition for this root instance. Module *rmod = (*mod).second; + // Get the compilation unit scope for this module. + NetScope*unit_scope = unit_scopes[rmod->parent_scope()]; + // Make the root scope. This makes a NetScope object and // pushes it into the list of root scopes in the Design. - NetScope*scope = des->make_root_scope(*root, rmod->program_block, + NetScope*scope = des->make_root_scope(*root, unit_scope, + rmod->program_block, rmod->is_interface); // Collect some basic properties of this scope from the @@ -6367,8 +6367,6 @@ Design* elaborate(listroots) << "Start calling $root elaborate_sig methods." << endl; } - des->root_elaborate_sig(); - if (debug_elaborate) { cerr << ": elaborate: " << "Start calling root module elaborate_sig methods." << endl; @@ -6430,8 +6428,6 @@ Design* elaborate(listroots) rc &= pkg->elaborate(des, scope); } - des->root_elaborate(); - for (i = 0; i < root_elems.size(); i++) { Module *rmod = root_elems[i].mod; NetScope *scope = root_elems[i].scope; diff --git a/emit.cc b/emit.cc index eaa183454..c5c64c9d3 100644 --- a/emit.cc +++ b/emit.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -510,24 +510,12 @@ int Design::emit(struct target_t*tgt) const if (tgt->start_design(this) == false) return -2; - for (map::const_iterator scope = root_tasks_.begin() - ; scope != root_tasks_.end() ; ++ scope) { - scope->first->emit_scope(tgt); - } - // enumerate package scopes for (map::const_iterator scope = packages_.begin() ; scope != packages_.end() ; ++ scope) { scope->second->emit_scope(tgt); } - for (map::const_iterator cur = classes_.begin() - ; cur != classes_.end() ; ++cur) { - const NetScope*use_scope = cur->second->class_scope(); - cur->second->emit_scope(tgt); - tgt->class_type(use_scope, cur->second); - } - // enumerate root scopes for (list::const_iterator scope = root_scopes_.begin() ; scope != root_scopes_.end(); ++ scope ) { @@ -552,12 +540,6 @@ int Design::emit(struct target_t*tgt) const // emit task and function definitions bool tasks_rc = true; - for (map::const_iterator scope = root_tasks_.begin() - ; scope != root_tasks_.end() ; ++ scope) - tasks_rc &= scope->first->emit_defs(tgt); - for (map::const_iterator cur = classes_.begin() - ; cur != classes_.end() ; ++cur) - tasks_rc &= cur->second->emit_defs(tgt); for (map::const_iterator scope = packages_.begin() ; scope != packages_.end() ; ++ scope ) tasks_rc &= scope->second->emit_defs(tgt); diff --git a/ivl_target_priv.h b/ivl_target_priv.h index 489d801eb..3ae882b63 100644 --- a/ivl_target_priv.h +++ b/ivl_target_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_ivl_target_priv_H #define IVL_ivl_target_priv_H /* - * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2017 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 @@ -52,7 +52,6 @@ struct ivl_design_s { // Keep arrays of root scopes. std::map classes; - std::map root_tasks; std::vector packages; std::vector roots; diff --git a/main.cc b/main.cc index 5a87b3266..e3ee2a56a 100644 --- a/main.cc +++ b/main.cc @@ -1103,21 +1103,11 @@ int main(int argc, char*argv[]) ; cur != disciplines.end() ; ++ cur ) { pform_dump(out, (*cur).second); } - out << "PFORM DUMP $ROOT TASKS/FUNCTIONS:" << endl; - for (map::iterator cur = pform_tasks.begin() - ; cur != pform_tasks.end() ; ++ cur) { - pform_dump(out, cur->second); - } - out << "PFORM DUMP $ROOT CLASSES:" << endl; - for (size_t idx = 0 ; idx < pform_classes.size() ; idx += 1) { - pform_dump(out, pform_classes[idx]); - } out << "PFORM DUMP PACKAGES:" << endl; for (map::iterator pac = pform_packages.begin() ; pac != pform_packages.end() ; ++ pac) { pform_dump(out, pac->second); } - out << "PFORM DUMP MODULES:" << endl; for (map::iterator mod = pform_modules.begin() ; mod != pform_modules.end() ; ++ mod ) { @@ -1235,12 +1225,6 @@ int main(int argc, char*argv[]) (*idx).second = 0; } - for(map::iterator it = pform_typedefs.begin() - ; it != pform_typedefs.end() ; ++it) { - delete (*it).second; - (*it).second = 0; - } - if (verbose_flag) { if (times_flag) { times(cycles+2); diff --git a/net_design.cc b/net_design.cc index c0d03cf9f..b071469e2 100644 --- a/net_design.cc +++ b/net_design.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -101,11 +101,11 @@ uint64_t Design::scale_to_precision(uint64_t val, return val; } -NetScope* Design::make_root_scope(perm_string root, bool program_block, - bool is_interface) +NetScope* Design::make_root_scope(perm_string root, NetScope*unit_scope, + bool program_block, bool is_interface) { NetScope *root_scope_; - root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, + root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE, unit_scope, false, program_block, is_interface); /* This relies on the fact that the basename return value is permallocated. */ @@ -125,31 +125,18 @@ list Design::find_root_scopes() const return root_scopes_; } -NetScope* Design::make_package_scope(perm_string name) +NetScope* Design::make_package_scope(perm_string name, NetScope*unit_scope, + bool is_unit) { NetScope*scope; - scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, false, false); + scope = new NetScope(0, hname_t(name), NetScope::PACKAGE, unit_scope, + false, false, false, is_unit); scope->set_module_name(scope->basename()); packages_[name] = scope; return scope; } -void Design::add_class(netclass_t*cl, PClass*pclass) -{ - Definitions::add_class(cl); - class_to_pclass_[cl] = pclass; -} - -netclass_t* Design::find_class(perm_string name) const -{ - map::const_iterator cur = classes_.find(name); - if (cur != classes_.end()) - return cur->second; - - return 0; -} - NetScope* Design::find_package(perm_string name) const { map::const_iterator cur = packages_.find(name); @@ -170,17 +157,6 @@ list Design::find_package_scopes() const return res; } -list Design::find_roottask_scopes() const -{ - listres; - for (map::const_iterator cur = root_tasks_.begin() - ; cur != root_tasks_.end() ; ++ cur) { - res.push_back (cur->first); - } - - return res; -} - /* * This method locates a scope in the design, given its rooted * hierarchical name. Each component of the key is used to scan one @@ -211,25 +187,6 @@ NetScope* Design::find_scope(const std::list&path) const } } - for (map::const_iterator root = root_tasks_.begin() - ; root != root_tasks_.end() ; ++ root) { - - NetScope*cur = root->first; - if (path.front() != cur->fullname()) - continue; - - std::list tmp = path; - tmp.pop_front(); - - while (cur) { - if (tmp.empty()) return cur; - - cur = cur->child( tmp.front() ); - - tmp.pop_front(); - } - } - return 0; } @@ -253,6 +210,49 @@ NetScope* Design::find_scope(const hname_t&path) const return 0; } +static bool is_design_unit(NetScope*scope) +{ + return (scope->type() == NetScope::MODULE && !scope->nested_module()) + || (scope->type() == NetScope::PACKAGE); +} + +static bool is_subroutine(NetScope::TYPE type) +{ + return type == NetScope::TASK || type == NetScope::FUNC; +} + +/* + * This method locates a scope within another scope, given its relative + * hierarchical name. Each component of the key is used to scan one + * more step down the tree until the name runs out or the search + * fails. + */ +NetScope* Design::find_scope_(NetScope*scope, const std::list&path, + NetScope::TYPE type) const +{ + std::list tmp = path; + + do { + hname_t key = tmp.front(); + /* If we are looking for a module or we are not + * looking at the last path component check for + * a name match (second line). */ + if (scope->type() == NetScope::MODULE + && (type == NetScope::MODULE || tmp.size() > 1) + && scope->module_name()==key.peek_name()) { + + /* Up references may match module name */ + + } else { + scope = scope->child( key ); + if (scope == 0) break; + } + tmp.pop_front(); + } while (! tmp.empty()); + + return scope; +} + /* * This is a relative lookup of a scope by name. The starting point is * the scope parameter within which I start looking for the scope. If @@ -266,36 +266,62 @@ NetScope* Design::find_scope(NetScope*scope, const std::list&path, if (path.empty()) return scope; - for ( ; scope ; scope = scope->parent()) { + // Record the compilation unit scope for use later. + NetScope*unit_scope = scope->unit(); - std::list tmp = path; + // First search upwards through the hierarchy. + while (scope) { + NetScope*found_scope = find_scope_(scope, path, type); + if (found_scope) + return found_scope; - NetScope*cur = scope; - do { - hname_t key = tmp.front(); - /* If we are looking for a module or we are not - * looking at the last path component check for - * a name match (second line). */ - if (cur->type() == NetScope::MODULE - && (type == NetScope::MODULE || tmp.size() > 1) - && cur->module_name()==key.peek_name()) { + // Avoid searching the unit scope twice. + if (scope == unit_scope) + unit_scope = 0; - /* Up references may match module name */ + // Special case - see IEEE 1800-2012 section 23.8.1. + if (unit_scope && is_design_unit(scope) && is_subroutine(type)) { + found_scope = find_scope_(unit_scope, path, type); + if (found_scope) + return found_scope; - } else { - cur = cur->child( key ); - if (cur == 0) break; - } - tmp.pop_front(); - } while (! tmp.empty()); + unit_scope = 0; + } - if (cur) return cur; + scope = scope->parent(); + } + + // If we haven't already done so, search the compilation unit scope. + if (unit_scope) { + NetScope*found_scope = find_scope_(unit_scope, path, type); + if (found_scope) + return found_scope; } // Last chance. Look for the name starting at the root. return find_scope(path); } +/* + * This method locates a scope within another scope, given its relative + * hierarchical name. Each component of the key is used to scan one + * more step down the tree until the name runs out or the search + * fails. + */ +NetScope* Design::find_scope_(NetScope*scope, const hname_t&path, + NetScope::TYPE type) const +{ + /* If we are looking for a module or we are not + * looking at the last path component check for + * a name match (second line). */ + if ((scope->type() == NetScope::MODULE) && (type == NetScope::MODULE) + && (scope->module_name() == path.peek_name())) { + /* Up references may match module name */ + return scope; + } + return scope->child( path ); +} + /* * This is a relative lookup of a scope by name. The starting point is * the scope parameter within which I start looking for the scope. If @@ -307,24 +333,36 @@ NetScope* Design::find_scope(NetScope*scope, const hname_t&path, { assert(scope); - for ( ; scope ; scope = scope->parent()) { + // Record the compilation unit scope for use later. + NetScope*unit_scope = scope->unit(); - NetScope*cur = scope; + // First search upwards through the hierarchy. + while (scope) { + NetScope*found_scope = find_scope_(scope, path, type); + if (found_scope) + return found_scope; - /* If we are looking for a module or we are not - * looking at the last path component check for - * a name match (second line). */ - if (cur->type() == NetScope::MODULE - && (type == NetScope::MODULE) - && cur->module_name()==path.peek_name()) { + // Avoid searching the unit scope twice. + if (scope == unit_scope) + unit_scope = 0; - /* Up references may match module name */ + // Special case - see IEEE 1800-2012 section 23.8.1. + if (unit_scope && is_design_unit(scope) && is_subroutine(type)) { + found_scope = find_scope_(unit_scope, path, type); + if (found_scope) + return found_scope; - } else { - cur = cur->child( path ); + unit_scope = 0; } - if (cur) return cur; + scope = scope->parent(); + } + + // If we haven't already done so, search the compilation unit scope. + if (unit_scope) { + NetScope*found_scope = find_scope_(unit_scope, path, type); + if (found_scope) + return found_scope; } // Last chance. Look for the name starting at the root. @@ -867,11 +905,6 @@ NetScope* Design::find_task(NetScope*scope, const pform_name_t&name) return 0; } -void Design::add_root_task(NetScope*tscope, PTaskFunc*tf) -{ - root_tasks_[tscope] = tf; -} - void Design::add_node(NetNode*net) { assert(net->design_ == 0); diff --git a/net_scope.cc b/net_scope.cc index f3f5a4518..d1c386fef 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -112,10 +112,10 @@ void Definitions::add_class(netclass_t*net_class) * in question. */ -NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, - bool program, bool interface) +NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*unit, + bool nest, bool program, bool interface, bool compilation_unit) : type_(t), name_(n), nested_module_(nest), program_block_(program), - is_interface_(interface), up_(up) + is_interface_(interface), is_unit_(compilation_unit), unit_(unit), up_(up) { events_ = 0; lcounter_ = 0; @@ -124,6 +124,9 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, calls_stask_ = false; in_final_ = false; + if (compilation_unit) + unit_ = this; + if (up) { assert(t!=CLASS); need_const_func_ = up->need_const_func_; @@ -133,6 +136,8 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, time_from_timescale_ = up->time_from_timescale(); // Need to check for duplicate names? up_->children_[name_] = this; + if (unit_ == 0) + unit_ = up_->unit_; } else { need_const_func_ = false; is_const_func_ = false; @@ -210,6 +215,8 @@ const netenum_t*NetScope::find_enumeration_for_name(perm_string name) NetEConstEnum*tmp = cur_scope->enum_names_[name]; if (tmp) break; cur_scope = cur_scope->parent(); + if (cur_scope == 0) + cur_scope = unit_; } assert(cur_scope); @@ -364,12 +371,7 @@ const NetExpr* NetScope::get_parameter(Design*des, msb = 0; lsb = 0; const NetExpr*tmp = enumeration_expr(key); - if (tmp) return tmp; - - tmp = des->enumeration_expr(key); - if (tmp) return tmp; - - return 0; + return tmp; } NetScope::param_ref_t NetScope::find_parameter(perm_string key) @@ -386,11 +388,6 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key) return idx; } -NetScope::TYPE NetScope::type() const -{ - return type_; -} - void NetScope::print_type(ostream&stream) const { switch (type_) { @@ -657,15 +654,11 @@ netclass_t*NetScope::find_class(perm_string name) if (type_==CLASS && name_==hname_t(name)) return class_def_; - // Look for the class that directly within this scope. + // Look for the class directly within this scope. map::const_iterator cur = classes_.find(name); if (cur != classes_.end()) return cur->second; - // If this is a module scope, then look no further. - if (type_==MODULE) - return 0; - if (up_==0 && type_==CLASS) { assert(class_def_); @@ -673,12 +666,16 @@ netclass_t*NetScope::find_class(perm_string name) return def_parent->find_class(name); } - // If there is no further to look, ... - if (up_ == 0) - return 0; - // Try looking up for the class. - return up_->find_class(name); + if (up_!=0 && type_!=MODULE) + return up_->find_class(name); + + // Try the compilation unit. + if (unit_ != 0) + return unit_->find_class(name); + + // Nowhere left to try... + return 0; } /* diff --git a/netlist.h b/netlist.h index 431b0d020..35ac3cab8 100644 --- a/netlist.h +++ b/netlist.h @@ -927,10 +927,13 @@ class NetScope : public Definitions, public Attrib { public: enum TYPE { MODULE, CLASS, TASK, FUNC, BEGIN_END, FORK_JOIN, GENBLOCK, PACKAGE }; - /* Create a new scope, and attach it to the given parent. The - name is expected to have been permallocated. */ - NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, - bool program=false, bool interface=false); + /* Create a new scope associated with a given compilation unit, + and attach it to the given parent. If no compilation unit is + specified, the parent's compilation unit is used. The name + is expected to have been permallocated. */ + NetScope(NetScope*up, const hname_t&name, TYPE t, NetScope*unit=0, + bool nest=false, bool program=false, bool interface=false, + bool compilation_unit=false); ~NetScope(); /* Rename the scope using the name generated by inserting as @@ -1002,10 +1005,12 @@ class NetScope : public Definitions, public Attrib { netclass_t* find_class(perm_string name); - /* The parent and child() methods allow users of NetScope - objects to locate nearby scopes. */ + /* The unit(), parent(), and child() methods allow users of + NetScope objects to locate nearby scopes. */ + NetScope* unit() { return unit_; } NetScope* parent() { return up_; } NetScope* child(const hname_t&name); + const NetScope* unit() const { return unit_; } const NetScope* parent() const { return up_; } const NetScope* child(const hname_t&name) const; @@ -1023,7 +1028,8 @@ class NetScope : public Definitions, public Attrib { // Program blocks and interfaces have elaboration constraints. inline bool program_block() const { return program_block_; } inline bool is_interface() const { return is_interface_; } - TYPE type() const; + inline bool is_unit() const { return is_unit_; } + inline TYPE type() const { return type_; } void print_type(ostream&) const; // This provides a link to the variable initialisation process @@ -1249,6 +1255,8 @@ class NetScope : public Definitions, public Attrib { bool program_block_; // True if the scope is an interface bool is_interface_; + // True if the scope is a compilation unit + bool is_unit_; perm_string file_; perm_string def_file_; @@ -1279,6 +1287,7 @@ class NetScope : public Definitions, public Attrib { const PFunction*func_pform_; unsigned elab_stage_; + NetScope*unit_; NetScope*up_; map children_; @@ -4835,7 +4844,7 @@ struct elaborator_work_item_t { * This class contains an entire design. It includes processes and a * netlist, and can be passed around from function to function. */ -class Design : public Definitions { +class Design { public: Design(); @@ -4857,12 +4866,13 @@ class Design : public Definitions { const char* get_flag(const string&key) const; - NetScope* make_root_scope(perm_string name, bool program_block, - bool is_interface); + NetScope* make_root_scope(perm_string name, NetScope*unit_scope, + bool program_block, bool is_interface); NetScope* find_root_scope(); std::list find_root_scopes() const; - NetScope* make_package_scope(perm_string name); + NetScope* make_package_scope(perm_string name, NetScope*unit_scope, + bool is_unit); std::list find_package_scopes() const; /* Attempt to set the precision to the specified value. If the @@ -4912,11 +4922,6 @@ class Design : public Definitions { // Look for defparams that never matched, and print warnings. void residual_defparams(); - // Do elaborate_sig for objects in $root scope. - void root_elaborate_sig(void); - - void root_elaborate(void); - /* This method locates a signal, starting at a given scope. The name parameter may be partially hierarchical, so this method, unlike the NetScope::find_signal method, @@ -4929,12 +4934,6 @@ class Design : public Definitions { // Tasks NetScope* find_task(NetScope*scope, const pform_name_t&name); - void add_root_task(NetScope*tscope, PTaskFunc*tf); - std::list find_roottask_scopes(void) const; - - // Find a class in the $root scope. - void add_class(netclass_t*cl, PClass*pclass); - netclass_t* find_class(perm_string name) const; // NODES void add_node(NetNode*); @@ -4962,6 +4961,12 @@ class Design : public Definitions { unsigned errors; private: + NetScope* find_scope_(NetScope*, const hname_t&name, + NetScope::TYPE type = NetScope::MODULE) const; + + NetScope* find_scope_(NetScope*, const std::list&path, + NetScope::TYPE type = NetScope::MODULE) const; + // Keep a tree of scopes. The NetScope class handles the wide // tree and per-hop searches for me. listroot_scopes_; @@ -4970,12 +4975,6 @@ class Design : public Definitions { // packages do not nest. std::mappackages_; - // Tasks in the $root scope - std::maproot_tasks_; - - // Need this for elaboration of $root scope pclass objects. - std::map class_to_pclass_; - // List the nodes in the design. NetNode*nodes_; // These are in support of the node functor iterator. diff --git a/parse_api.h b/parse_api.h index 25be3f57f..1b76b767b 100644 --- a/parse_api.h +++ b/parse_api.h @@ -42,20 +42,13 @@ struct enum_type_t; */ extern std::map pform_modules; extern std::map pform_primitives; -extern std::map pform_typedefs; -extern std::set pform_enum_sets; -extern std::map pform_tasks; -extern std::vector pform_classes; +extern std::vector pform_units; extern std::map pform_packages; extern void pform_dump(std::ostream&out, const PClass*pac); extern void pform_dump(std::ostream&out, const PPackage*pac); extern void pform_dump(std::ostream&out, const PTaskFunc*tf); -extern void elaborate_rootscope_enumerations(Design*des); -extern void elaborate_rootscope_classes(Design*des); -extern void elaborate_rootscope_tasks(Design*des); - /* * This code actually invokes the parser to make modules. If the path * parameter is "-", the parser reads from stdin, otherwise it attempts diff --git a/pform.cc b/pform.cc index ed10b46e9..1be0e2b46 100644 --- a/pform.cc +++ b/pform.cc @@ -63,20 +63,18 @@ map pform_modules; map pform_primitives; /* - * typedefs in the $root scope go here. + * The pform_units is a list of the SystemVerilog compilation unit scopes. + * The current compilation unit is the last element in the list. All items + * declared or defined at the top level (outside any design element) are + * added to the current compilation unit scope. */ -mappform_typedefs; -setpform_enum_sets; +vector pform_units; -/* - * Class definitions in the $root scope go here. - */ -vector pform_classes; - -/* - * Task and function definitions in the $root scope go here. - */ -map pform_tasks; +static bool is_compilation_unit(LexicalScope*scope) +{ + // A compilation unit is the only scope that doesn't have a parent. + return scope->parent_scope() == 0; +} std::string vlltype::get_fileline() const { @@ -406,6 +404,7 @@ void pform_pop_scope() { assert(lexical_scope); lexical_scope = lexical_scope->parent_scope(); + assert(lexical_scope); } static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime) @@ -413,10 +412,7 @@ static LexicalScope::lifetime_t find_lifetime(LexicalScope::lifetime_t lifetime) if (lifetime != LexicalScope::INHERITED) return lifetime; - if (lexical_scope != 0) - return lexical_scope->default_lifetime; - - return LexicalScope::STATIC; + return lexical_scope->default_lifetime; } static PScopeExtra* find_nearest_scopex(LexicalScope*scope) @@ -440,7 +436,7 @@ static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc) * a timescale directive. */ scope->time_from_timescale = pform_timescale_file != 0; - if (warn_timescale && (lexical_scope == 0) && pform_timescale_file + if (warn_timescale && is_compilation_unit(lexical_scope) && pform_timescale_file && (strcmp(pform_timescale_file, loc.text) != 0)) { cerr << loc.get_fileline() << ": warning: " @@ -461,17 +457,9 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, pform_set_scope_timescale(class_scope, loc); PScopeExtra*scopex = find_nearest_scopex(lexical_scope); - + assert(scopex); assert(!pform_cur_generate); - /* If no scope was found then this is being defined in the - * compilation unit scope. */ - if (scopex == 0) { - pform_classes.push_back(class_scope); - lexical_scope = class_scope; - return class_scope; - } - if (scopex->classes.find(name) != scopex->classes.end()) { cerr << class_scope->get_fileline() << ": error: duplicate " "definition for class '" << name << "' in '" @@ -513,7 +501,8 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, pform_set_scope_timescale(task, loc); PScopeExtra*scopex = find_nearest_scopex(lexical_scope); - if ((scopex == 0) && !gn_system_verilog()) { + assert(scopex); + if (is_compilation_unit(scopex) && !gn_system_verilog()) { cerr << task->get_fileline() << ": error: task declarations " "must be contained within a module." << endl; error_count += 1; @@ -530,7 +519,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, error_count += 1; } pform_cur_generate->tasks[task->pscope_name()] = task; - } else if (scopex) { + } else { // Check if the task is already in the dictionary. if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) { cerr << task->get_fileline() << ": error: duplicate " @@ -539,15 +528,6 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, error_count += 1; } scopex->tasks[task->pscope_name()] = task; - - } else { - if (pform_tasks.find(task_name) != pform_tasks.end()) { - cerr << task->get_fileline() << ": error: " - << "Duplicate definition for task '" << name - << "' in $root scope." << endl; - error_count += 1; - } - pform_tasks[task_name] = task; } lexical_scope = task; @@ -570,7 +550,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, pform_set_scope_timescale(func, loc); PScopeExtra*scopex = find_nearest_scopex(lexical_scope); - if ((scopex == 0) && !gn_system_verilog()) { + assert(scopex); + if (is_compilation_unit(scopex) && !gn_system_verilog()) { cerr << func->get_fileline() << ": error: function declarations " "must be contained within a module." << endl; error_count += 1; @@ -588,7 +569,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, } pform_cur_generate->funcs[func->pscope_name()] = func; - } else if (scopex != 0) { + } else { // Check if the function is already in the dictionary. if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) { cerr << func->get_fileline() << ": error: duplicate " @@ -597,15 +578,6 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, error_count += 1; } scopex->funcs[func->pscope_name()] = func; - - } else { - if (pform_tasks.find(func_name) != pform_tasks.end()) { - cerr << func->get_fileline() << ": error: " - << "Duplicate definition for function '" << name - << "' in $root scope." << endl; - error_count += 1; - } - pform_tasks[func_name] = func; } lexical_scope = func; @@ -705,11 +677,7 @@ static void pform_put_wire_in_scope(perm_string name, PWire*net) static void pform_put_enum_type_in_scope(enum_type_t*enum_set) { - if (lexical_scope) { - lexical_scope->enum_sets.insert(enum_set); - } else { - pform_enum_sets.insert(enum_set); - } + lexical_scope->enum_sets.insert(enum_set); } PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type) @@ -736,12 +704,7 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::listtypedefs[name] - : pform_typedefs[name]; + data_type_t*&ref = lexical_scope->typedefs[name]; ivl_assert(*data_type, ref == 0); ref = data_type; @@ -751,25 +714,10 @@ void pform_set_typedef(perm_string name, data_type_t*data_type, std::list::iterator cur = pform_typedefs.find(name); - if (cur != pform_typedefs.end()) - return cur->second; - else - return 0; -} - data_type_t* pform_test_type_identifier(const char*txt) { perm_string name = lex_strings.make(txt); - // If there is no lexical_scope yet, then look only in the - // $root scope for typedefs. - if (lexical_scope == 0) { - return test_type_identifier_in_root(name); - } - LexicalScope*cur_scope = lexical_scope; do { map::iterator cur; @@ -799,10 +747,6 @@ data_type_t* pform_test_type_identifier(const char*txt) cur_scope = cur_scope->parent_scope(); } while (cur_scope); - // See if there is a typedef in the $root scope. - if (data_type_t*tmp = test_type_identifier_in_root(name)) - return tmp; - return 0; } @@ -813,13 +757,6 @@ data_type_t* pform_test_type_identifier(const char*txt) */ bool pform_test_type_identifier_local(perm_string name) { - if (lexical_scope == 0) { - if (test_type_identifier_in_root(name)) - return true; - else - return false; - } - LexicalScope*cur_scope = lexical_scope; map::iterator cur; @@ -1418,11 +1355,9 @@ void pform_endmodule(const char*name, bool inside_celldefine, use_module_map[mod_name] = cur_module; } - // The current lexical scope should be this module by now, and - // this module should not have a parent lexical scope. + // The current lexical scope should be this module by now. ivl_assert(*cur_module, lexical_scope == cur_module); pform_pop_scope(); - ivl_assert(*cur_module, ! pform_cur_module.empty() || lexical_scope == 0); tp_decl_flag = false; tu_decl_flag = false; @@ -2773,11 +2708,11 @@ void pform_makewire(const struct vlltype&li, NetNet::Type type, data_type_t*data_type) { - if ((lexical_scope == 0) && !gn_system_verilog()) { + if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) { VLerror(li, "error: variable declarations must be contained within a module."); return; } - if (lexical_scope == 0) { + if (is_compilation_unit(lexical_scope)) { VLerror(li, "sorry: variable declarations in the $root scope are not yet supported."); return; } @@ -3080,11 +3015,11 @@ void pform_set_parameter(const struct vlltype&loc, LexicalScope::range_t*value_range) { LexicalScope*scope = lexical_scope; - if ((scope == 0) && !gn_system_verilog()) { + if (is_compilation_unit(scope) && !gn_system_verilog()) { VLerror(loc, "error: parameter declarations must be contained within a module."); return; } - if (scope == 0) { + if (is_compilation_unit(scope)) { VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported."); return; } @@ -3155,11 +3090,11 @@ void pform_set_localparam(const struct vlltype&loc, bool signed_flag, list*range, PExpr*expr) { LexicalScope*scope = lexical_scope; - if ((scope == 0) && !gn_system_verilog()) { + if (is_compilation_unit(scope) && !gn_system_verilog()) { VLerror(loc, "error: localparam declarations must be contained within a module."); return; } - if (scope == 0) { + if (is_compilation_unit(scope)) { VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported."); return; } @@ -3749,6 +3684,21 @@ int pform_parse(const char*path) } } + if (pform_units.empty() || separate_compilation) { + char unit_name[20]; + static unsigned nunits = 0; + if (separate_compilation) + sprintf(unit_name, "$unit#%u", ++nunits); + else + sprintf(unit_name, "$unit"); + PPackage*unit = new PPackage(lex_strings.make(unit_name), 0); + unit->default_lifetime = LexicalScope::STATIC; + unit->time_unit = def_ts_units; + unit->time_precision = def_ts_prec; + unit->time_from_timescale = false; + pform_units.push_back(unit); + lexical_scope = unit; + } reset_lexor(); error_count = 0; warn_count = 0; diff --git a/symbol_search.cc b/symbol_search.cc index fe24e33a0..8b8e22239 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2012 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -143,14 +143,21 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } } - // Don't scan up past a module boundary. - if (scope->type()==NetScope::MODULE && !scope->nested_module()) - break; // Don't scan up if we are searching within a prefixed scope. if (prefix_scope) break; - scope = scope->parent(); + // Don't scan up past a module boundary. + if (scope->type()==NetScope::MODULE && !scope->nested_module()) + scope = 0; + else + scope = scope->parent(); + + // Last chance - try the compilation unit. + if (scope == 0 && start_scope != 0) { + scope = start_scope->unit(); + start_scope = 0; + } } // Last chance: this is a single name, so it might be the name diff --git a/t-dll-api.cc b/t-dll-api.cc index 1e4a0c0ec..c07e18366 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -93,10 +93,7 @@ extern "C" void ivl_design_roots(ivl_design_t des, ivl_scope_t **scopes, assert (nscopes && scopes); if (des->root_scope_list.size() == 0) { size_t fill = 0; - des->root_scope_list.resize(des->root_tasks.size() + des->packages.size() + des->roots.size() + des->classes.size()); - for (map::iterator idx = des->root_tasks.begin() - ; idx != des->root_tasks.end() ; ++ idx) - des->root_scope_list[fill++] = idx->second; + des->root_scope_list.resize(des->packages.size() + des->roots.size() + des->classes.size()); for (map::iterator idx = des->classes.begin() ; idx != des->classes.end() ; ++ idx) diff --git a/t-dll.cc b/t-dll.cc index fa62dc484..39f1f892c 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -261,12 +261,6 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur) return tmp; } - if (cur->type()==NetScope::TASK || cur->type()==NetScope::FUNC) { - map::const_iterator idx = des.root_tasks.find(cur); - if (idx != des.root_tasks.end()) - return idx->second; - } - for (unsigned idx = 0; idx < des.roots.size(); idx += 1) { assert(des.roots[idx]); ivl_scope_t scope = find_scope_from_root(des.roots[idx], cur); @@ -288,13 +282,6 @@ ivl_scope_t dll_target::find_scope(ivl_design_s &des, const NetScope*cur) return scope; } - for (map::iterator idx = des.root_tasks.begin() - ; idx != des.root_tasks.end() ; ++ idx) { - ivl_scope_t scope = find_scope_from_root(idx->second, cur); - if (scope) - return scope; - } - return 0; } @@ -657,22 +644,6 @@ void dll_target::add_root(const NetScope *s) case NetScope::CLASS: root_->type_ = IVL_SCT_CLASS; break; - case NetScope::TASK: { - const NetTaskDef*def = s->task_def(); - if (def == 0) { - cerr << "?:?" << ": internal error: " - << "task " << root_->name_ - << " has no definition." << endl; - } - assert(def); - root_->type_ = IVL_SCT_TASK; - root_->tname_ = def->scope()->basename(); - break; - } - break; - case NetScope::FUNC: - fill_in_scope_function(root_, s); - break; default: assert(0); } @@ -701,11 +672,6 @@ void dll_target::add_root(const NetScope *s) des_.classes[s] = root_; break; - case NetScope::TASK: - case NetScope::FUNC: - des_.root_tasks[s] = root_; - break; - default: assert(0); break; @@ -747,11 +713,7 @@ bool dll_target::start_design(const Design*des) } assert(idx == des_.disciplines.size()); - list scope_list = des->find_roottask_scopes(); - for (list::const_iterator cur = scope_list.begin() - ; cur != scope_list.end() ; ++ cur) { - add_root(*cur); - } + list scope_list; scope_list = des->find_package_scopes(); for (list::const_iterator cur = scope_list.begin() From 913fb34799f3fd9e737c93eeb97aa7033a3e3f0e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 31 Oct 2017 20:26:49 +0000 Subject: [PATCH 045/138] Add support for the $unit scope identifier. This relies on using the automatically generated name for the unit scope. This could collide with an escaped identifier, so it would be better to identify the scope by a reference to the PPackage object, but for now, do it the easy way. --- lexor.lex | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lexor.lex b/lexor.lex index bac72dedd..3381581a7 100644 --- a/lexor.lex +++ b/lexor.lex @@ -429,6 +429,12 @@ TU [munpf] if (strcmp(yytext,"$attribute") == 0) return KK_attribute; + + if (gn_system_verilog() && strcmp(yytext,"$unit") == 0) { + yylval.package = pform_units.back(); + return PACKAGE_IDENTIFIER; + } + yylval.text = strdupnew(yytext); return SYSTEM_IDENTIFIER; } From e54d19e2d2f3838cd23e8027ec4ef6162d9ed7cf Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 09:26:33 +0000 Subject: [PATCH 046/138] Fix $printtimescale to support 10s and 100s values. --- vpi/sys_display.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index dc04182fd..5ecc8c5b4 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -1971,6 +1971,8 @@ static const char *pts_convert(int value) { const char *string; switch (value) { + case 2: string = "100s"; break; + case 1: string = "10s"; break; case 0: string = "1s"; break; case -1: string = "100ms"; break; case -2: string = "10ms"; break; From 9382d22063fc2e0b0636eced774610c222d1c36c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 09:35:02 +0000 Subject: [PATCH 047/138] Factor out common code for warning about inconsistent timescales. Also reword the warning for SystemVerilog, where `timescale is not the only (or indeed preferred) way of specifying timescales. --- PDelays.cc | 21 ++------------------- elaborate.cc | 28 ++-------------------------- netmisc.cc | 37 ++++++++++++++++++++++++++++++++++++- netmisc.h | 12 +++++++----- 4 files changed, 47 insertions(+), 51 deletions(-) diff --git a/PDelays.cc b/PDelays.cc index 5fd72a37b..3759d39fe 100644 --- a/PDelays.cc +++ b/PDelays.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -26,11 +26,6 @@ # include "verinum.h" # include "netmisc.h" -bool dly_used_no_timescale = false; -bool dly_used_timescale = false; -bool display_ts_dly_warning = true; - - PDelays::PDelays() { delete_flag_ = true; @@ -80,19 +75,7 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, PExpr*expr) { NetExpr*dex = elab_and_eval(des, scope, expr, -1); - /* Print a warning if we find default and `timescale based - * delays in the design, since this is likely an error. */ - if (scope->time_from_timescale()) dly_used_timescale = true; - else dly_used_no_timescale = true; - - if (display_ts_dly_warning && - dly_used_no_timescale && dly_used_timescale) { - cerr << "warning: Found both default and " - "`timescale based delays. Use" << endl; - cerr << " -Wtimescale to find the " - "module(s) with no `timescale." << endl; - display_ts_dly_warning = false; - } + check_for_inconsistent_delays(scope); /* If the delay expression is a real constant or vector constant, then evaluate it, scale it to the local time diff --git a/elaborate.cc b/elaborate.cc index 2e294d00d..be0a77d0a 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2355,19 +2355,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope) { NetExpr*dex = elab_and_eval(des, scope, expr, -1); - /* Print a warning if we find default and `timescale based - * delays in the design, since this is likely an error. */ - if (scope->time_from_timescale()) dly_used_timescale = true; - else dly_used_no_timescale = true; - - if (display_ts_dly_warning && - dly_used_no_timescale && dly_used_timescale) { - cerr << "warning: Found both default and " - "`timescale based delays. Use" << endl; - cerr << " -Wtimescale to find the " - "module(s) with no `timescale." << endl; - display_ts_dly_warning = false; - } + check_for_inconsistent_delays(scope); /* If the delay expression is a real constant or vector constant, then evaluate it, scale it to the local time @@ -5415,19 +5403,7 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const ndelays = delays.size(); 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. */ - if (scope->time_from_timescale()) dly_used_timescale = true; - else dly_used_no_timescale = true; - - if (display_ts_dly_warning && - dly_used_no_timescale && dly_used_timescale) { - cerr << "warning: Found both default and " - "`timescale based delays. Use" << endl; - cerr << " -Wtimescale to find the " - "module(s) with no `timescale." << endl; - display_ts_dly_warning = false; - } + check_for_inconsistent_delays(scope); /* Elaborate the delay values themselves. Remember to scale them for the timescale/precision of the scope. */ diff --git a/netmisc.cc b/netmisc.cc index b0bf41b98..1adf66658 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -1665,3 +1665,38 @@ NetScope* find_method_containing_scope(const LineInfo&, NetScope*scope) return scope; } + + +/* + * Print a warning if we find a mixture of default and explicit timescale + * based delays in the design, since this is likely an error. + */ +void check_for_inconsistent_delays(NetScope*scope) +{ + static bool used_implicit_timescale = false; + static bool used_explicit_timescale = false; + static bool display_ts_dly_warning = true; + + if (scope->time_from_timescale()) + used_explicit_timescale = true; + else + used_implicit_timescale = true; + + if (display_ts_dly_warning && + used_explicit_timescale && + used_implicit_timescale) { + if (gn_system_verilog()) { + cerr << "warning: Found both default and explicit " + "timescale based delays. Use" << endl; + cerr << " : -Wtimescale to find the design " + "element(s) with no explicit" << endl; + cerr << " : timescale." << endl; + } else { + cerr << "warning: Found both default and " + "`timescale based delays. Use" << endl; + cerr << " : -Wtimescale to find the " + "module(s) with no `timescale." << endl; + } + display_ts_dly_warning = false; + } +} diff --git a/netmisc.h b/netmisc.h index ce65701be..af639da2b 100644 --- a/netmisc.h +++ b/netmisc.h @@ -1,7 +1,7 @@ #ifndef IVL_netmisc_H #define IVL_netmisc_H /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -378,10 +378,6 @@ const char *human_readable_op(const char op, bool unary = false); enum const_bool { C_NON, C_0, C_1, C_X }; const_bool const_logical(const NetExpr*expr); -extern bool dly_used_no_timescale; -extern bool dly_used_timescale; -extern bool display_ts_dly_warning; - /* * When scaling a real value to a time we need to do some standard * processing. @@ -409,4 +405,10 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope, extern NetPartSelect* detect_partselect_lval(Link&pin); +/* + * Print a warning if we find a mixture of default and explicit timescale + * based delays in the design, since this is likely an error. + */ +extern void check_for_inconsistent_delays(NetScope*scope); + #endif /* IVL_netmisc_H */ From fd807a7700feb8d991e5cb9a6dd0e7b284507daf Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 17:50:05 +0000 Subject: [PATCH 048/138] Rework handling of timescales in parser. This implements and enforces the full set of rules for determining timescales in SystemVerilog. The previous relaxation of the rules that allowed timescales to be redefined within the compilation unit scope has been removed. Time unit and precision redeclarations are now recognised after a nested module declaration. --- Module.cc | 3 +- Module.h | 4 +- PScope.cc | 7 +- PScope.h | 17 ++- elab_scope.cc | 2 +- elaborate.cc | 129 +++++++++++++++++++++++ lexor.lex | 9 -- main.cc | 1 - parse.y | 121 +++++++--------------- parse_misc.h | 8 +- pform.cc | 281 ++++++++++++++++++++++++-------------------------- pform.h | 9 +- 12 files changed, 328 insertions(+), 263 deletions(-) diff --git a/Module.cc b/Module.cc index 7c2d14dfb..c5980637e 100644 --- a/Module.cc +++ b/Module.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -35,7 +35,6 @@ Module::Module(LexicalScope*parent, perm_string n) is_interface = false; program_block = false; uc_drive = UCD_NONE; - timescale_warn_done = false; } Module::~Module() diff --git a/Module.h b/Module.h index 66c60af4f..411c99f9f 100644 --- a/Module.h +++ b/Module.h @@ -1,7 +1,7 @@ #ifndef IVL_Module_H #define IVL_Module_H /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -121,8 +121,6 @@ class Module : public PScopeExtra, public LineInfo { map attributes; - bool timescale_warn_done; - /* The module has a list of generate schemes that appear in the module definition. These are used at elaboration time. */ list generate_schemes; diff --git a/PScope.cc b/PScope.cc index 0b6a132d3..c0738cc29 100644 --- a/PScope.cc +++ b/PScope.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008,2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2017 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 @@ -38,7 +38,8 @@ PScope::PScope(perm_string n, LexicalScope*parent) { time_unit = 0; time_precision = 0; - time_from_timescale = false; + time_unit_is_default = true; + time_prec_is_default = true; } PScope::~PScope() @@ -51,6 +52,8 @@ PScope::~PScope() PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent) : PScope(n, parent) { + time_unit_is_local = false; + time_prec_is_local = false; } PScopeExtra::~PScopeExtra() diff --git a/PScope.h b/PScope.h index 7e4fd6fa3..24674d6df 100644 --- a/PScope.h +++ b/PScope.h @@ -1,7 +1,7 @@ #ifndef IVL_PScope_H #define IVL_PScope_H /* - * Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2017 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 @@ -164,11 +164,18 @@ class PScope : public LexicalScope { perm_string pscope_name() const { return name_; } - /* These are the timescale for this scope. The default is + /* These are the timescale for this scope. The value is set by the `timescale directive or, in SystemVerilog, by timeunit and timeprecision statements. */ int time_unit, time_precision; - bool time_from_timescale; + + /* Flags used to support warnings about timescales. */ + bool time_unit_is_default; + bool time_prec_is_default; + + bool has_explicit_timescale() const { + return !(time_unit_is_default || time_prec_is_default); + } protected: bool elaborate_sig_wires_(Design*des, NetScope*scope) const; @@ -199,6 +206,10 @@ class PScopeExtra : public PScope { elaboration to choose an elaboration order. */ std::vector classes_lexical; + /* Flags used to support warnings about timescales. */ + bool time_unit_is_local; + bool time_prec_is_local; + protected: void dump_classes_(ostream&out, unsigned indent) const; void dump_tasks_(ostream&out, unsigned indent) const; diff --git a/elab_scope.cc b/elab_scope.cc index 7917ea2df..cfbc2a50d 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -59,7 +59,7 @@ void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope) { scope->time_unit(pscope->time_unit); scope->time_precision(pscope->time_precision); - scope->time_from_timescale(pscope->time_from_timescale); + scope->time_from_timescale(pscope->has_explicit_timescale()); des->set_precision(pscope->time_precision); } diff --git a/elaborate.cc b/elaborate.cc index be0a77d0a..7db362504 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6146,6 +6146,131 @@ bool Design::check_proc_delay() const return result_flag; } +/* + * Check whether all design elements have an explicit timescale or all + * design elements use the default timescale. If a mixture of explicit + * and default timescales is found, a warning message is output. Note + * that we only need to check the top level design elements - nested + * design elements will always inherit the timescale from their parent + * if they don't have any local timescale declarations. + * + * NOTE: Strictly speaking, this should be an error for SystemVerilog + * (1800-2012 section 3.14.2). + */ +static void check_timescales(bool&some_explicit, bool&some_implicit, + const PScope*scope) +{ + if (scope->time_unit_is_default) + some_implicit = true; + else + some_explicit = true; + if (scope->time_prec_is_default) + some_implicit = true; + else + some_explicit = true; +} + +static void check_timescales() +{ + bool some_explicit = false; + bool some_implicit = false; + map::iterator mod; + for (mod = pform_modules.begin(); mod != pform_modules.end(); ++mod) { + const Module*mp = (*mod).second; + check_timescales(some_explicit, some_implicit, mp); + if (some_explicit && some_implicit) + break; + } + map::iterator pkg; + if (gn_system_verilog() && !(some_explicit && some_implicit)) { + for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) { + const PPackage*pp = (*pkg).second; + check_timescales(some_explicit, some_implicit, pp); + if (some_explicit && some_implicit) + break; + } + } + if (gn_system_verilog() && !(some_explicit && some_implicit)) { + for (unsigned idx = 0; idx < pform_units.size(); idx += 1) { + const PPackage*pp = pform_units[idx]; + // We don't need a timescale if the compilation unit + // contains no items outside a design element. + if (pp->parameters.empty() && + pp->localparams.empty() && + pp->wires.empty() && + pp->tasks.empty() && + pp->funcs.empty() && + pp->classes.empty()) + continue; + + check_timescales(some_explicit, some_implicit, pp); + if (some_explicit && some_implicit) + break; + } + } + + if (!(some_explicit && some_implicit)) + return; + + if (gn_system_verilog()) { + cerr << "warning: " + << "Some design elements have no explicit time unit and/or" + << endl; + cerr << " : " + << "time precision. This may cause confusing timing results." + << endl; + cerr << " : " + << "Affected design elements are:" + << endl; + } else { + cerr << "warning: " + << "Some modules have no timescale. This may cause" + << endl; + cerr << " : " + << "confusing timing results. Affected modules are:" + << endl; + } + + for (mod = pform_modules.begin(); mod != pform_modules.end(); ++mod) { + Module*mp = (*mod).second; + if (mp->has_explicit_timescale()) + continue; + cerr << " : -- module " << (*mod).first + << " declared here: " << mp->get_fileline() << endl; + } + + if (!gn_system_verilog()) + return; + + for (pkg = pform_packages.begin(); pkg != pform_packages.end(); ++pkg) { + PPackage*pp = (*pkg).second; + if (pp->has_explicit_timescale()) + continue; + cerr << " : -- package " << (*pkg).first + << " declared here: " << pp->get_fileline() << endl; + } + + for (unsigned idx = 0; idx < pform_units.size(); idx += 1) { + PPackage*pp = pform_units[idx]; + if (pp->has_explicit_timescale()) + continue; + + if (pp->parameters.empty() && + pp->localparams.empty() && + pp->wires.empty() && + pp->tasks.empty() && + pp->funcs.empty() && + pp->classes.empty()) + continue; + + cerr << " : -- compilation unit"; + if (pform_units.size() > 1) { + cerr << " from: " << pp->get_file(); + } + cerr << endl; + } +} + /* * This function is the root of all elaboration. The input is the list * of root module names. The function locates the Module definitions @@ -6315,6 +6440,10 @@ Design* elaborate(listroots) if (des->errors > 0) return des; + // Now we have the full design, check for timescale inconsistencies. + if (warn_timescale) + check_timescales(); + if (debug_elaborate) { cerr << ": elaborate: " << "Start calling Package elaborate_sig methods." << endl; diff --git a/lexor.lex b/lexor.lex index 3381581a7..70fc1fda9 100644 --- a/lexor.lex +++ b/lexor.lex @@ -311,15 +311,6 @@ TU [munpf] BEGIN(UDPTABLE); break; - /* Translate these to checks if we already have or are - * outside the declaration region. */ - case K_timeunit: - if (have_timeunit_decl) rc = K_timeunit_check; - break; - case K_timeprecision: - if (have_timeprec_decl) rc = K_timeprecision_check; - break; - default: yylval.text = 0; break; diff --git a/main.cc b/main.cc index e3ee2a56a..cb087239e 100644 --- a/main.cc +++ b/main.cc @@ -1085,7 +1085,6 @@ int main(int argc, char*argv[]) if (flag_tmp) disable_concatz_generation = strcmp(flag_tmp,"true")==0; /* Parse the input. Make the pform. */ - pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); int rc = 0; for (unsigned idx = 0; idx < source_files.size(); idx += 1) { rc += pform_parse(source_files[idx]); diff --git a/parse.y b/parse.y index 1a06fa83f..a48b84ef1 100644 --- a/parse.y +++ b/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -35,9 +35,6 @@ class PSpecPath; extern void lex_end_table(); -bool have_timeunit_decl = false; -bool have_timeprec_decl = false; - static list* param_active_range = 0; static bool param_active_signed = false; static ivl_variable_type_t param_active_type = IVL_VT_LOGIC; @@ -532,8 +529,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %token K_tagged K_this K_throughout K_timeprecision K_timeunit K_type %token K_typedef K_union K_unique K_var K_virtual K_void K_wait_order %token K_wildcard K_with K_within - /* Fake tokens that are passed once we have an initial token. */ -%token K_timeprecision_check K_timeunit_check /* The new tokens from 1800-2009. */ %token K_accept_on K_checker K_endchecker K_eventually K_global K_implies @@ -692,7 +687,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %left UNARY_PREC -/* to resolve dangling else ambiguity. */ + /* to resolve dangling else ambiguity. */ %nonassoc less_than_K_else %nonassoc K_else @@ -700,12 +695,22 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %nonassoc '(' %nonassoc K_exclude + /* to resolve timeunits declaration/redeclaration ambiguity */ +%precedence no_timeunits_declaration +%precedence one_timeunits_declaration +%precedence K_timeunit K_timeprecision + %% /* IEEE1800-2005: A.1.2 */ /* source_text ::= [ timeunits_declaration ] { description } */ -source_text : description_list | ; +source_text + : timeunits_declaration_opt + { pform_set_scope_timescale(yyloc); } + description_list + | /* empty */ + ; assertion_item /* IEEE1800-2012: A.6.10 */ : concurrent_assertion_item @@ -1137,11 +1142,7 @@ data_type_or_implicit_or_void } ; - /* NOTE 1: We pull the "timeunits_declaration" into the description - here in order to be a little more flexible with where timeunits - statements may go. This may be a bad idea, but it is legacy now. */ - - /* NOTE 2: The "module" rule of the description combines the + /* NOTE: The "module" rule of the description combines the module_declaration, program_declaration, and interface_declaration rules from the standard description. */ @@ -1726,17 +1727,18 @@ open_range_list /* IEEE1800-2005 A.2.11 */ package_declaration /* IEEE1800-2005 A.1.2 */ : K_package lifetime_opt IDENTIFIER ';' - { pform_start_package_declaration(@1, $3, $2); - } + { pform_start_package_declaration(@1, $3, $2); } + timeunits_declaration_opt + { pform_set_scope_timescale(@1); } package_item_list_opt K_endpackage endlabel_opt { pform_end_package_declaration(@1); // If an end label is present make sure it match the package name. - if ($8) { - if (strcmp($3,$8) != 0) { - yyerror(@8, "error: End label doesn't match package name"); + if ($10) { + if (strcmp($3,$10) != 0) { + yyerror(@10, "error: End label doesn't match package name"); } - delete[]$8; + delete[]$10; } delete[]$3; } @@ -2230,20 +2232,23 @@ tf_port_list /* IEEE1800-2005: A.2.7 */ } ; - /* NOTE: Icarus Verilog is a little more generous with the - timeunits declarations by allowing them to happen in multiple - places in the file. So the rule is adjusted to be invoked by the - "description" rule. This theoretically allows files to be - concatenated together and still compile. */ timeunits_declaration /* IEEE1800-2005: A.1.2 */ : K_timeunit TIME_LITERAL ';' - { pform_set_timeunit($2, false, false); } + { pform_set_timeunit($2); } | K_timeunit TIME_LITERAL '/' TIME_LITERAL ';' - { pform_set_timeunit($2, false, false); - pform_set_timeprecision($4, false, false); + { pform_set_timeunit($2); + pform_set_timeprecision($4); } | K_timeprecision TIME_LITERAL ';' - { pform_set_timeprecision($2, false, false); } + { pform_set_timeprecision($2); } + ; + + /* Allow zero, one, or two declarations. The second declaration might + be a repeat declaration, but the pform functions take care of that. */ +timeunits_declaration_opt + : /* empty */ %prec no_timeunits_declaration + | timeunits_declaration %prec one_timeunits_declaration + | timeunits_declaration timeunits_declaration ; value_range /* IEEE1800-2005: A.8.3 */ @@ -4409,47 +4414,6 @@ cont_assign_list { $$ = $1; } ; - /* We allow zero, one or two unique declarations. */ -local_timeunit_prec_decl_opt - : /* Empty */ - | K_timeunit TIME_LITERAL '/' TIME_LITERAL ';' - { pform_set_timeunit($2, true, false); - have_timeunit_decl = true; - pform_set_timeprecision($4, true, false); - have_timeprec_decl = true; - } - | local_timeunit_prec_decl - | local_timeunit_prec_decl local_timeunit_prec_decl2 - ; - - /* By setting the appropriate have_time???_decl we allow only - one declaration of each type in this module. */ -local_timeunit_prec_decl - : K_timeunit TIME_LITERAL ';' - { pform_set_timeunit($2, true, false); - have_timeunit_decl = true; - } - | K_timeprecision TIME_LITERAL ';' - { pform_set_timeprecision($2, true, false); - have_timeprec_decl = true; - } - ; -local_timeunit_prec_decl2 - : K_timeunit TIME_LITERAL ';' - { pform_set_timeunit($2, true, false); - have_timeunit_decl = true; - } - | K_timeprecision TIME_LITERAL ';' - { pform_set_timeprecision($2, true, false); - have_timeprec_decl = true; - } - /* As the second item this form is always a check. */ - | K_timeunit TIME_LITERAL '/' TIME_LITERAL ';' - { pform_set_timeunit($2, true, true); - pform_set_timeprecision($4, true, true); - } - ; - /* This is the global structure of a module. A module is a start section, with optional ports, then an optional list of module items, and finally an end marker. */ @@ -4462,11 +4426,8 @@ module module_port_list_opt module_attribute_foreign ';' { pform_module_set_ports($8); } - local_timeunit_prec_decl_opt - { have_timeunit_decl = true; // Every thing past here is - have_timeprec_decl = true; // a check! - pform_check_timeunit_prec(); - } + timeunits_declaration_opt + { pform_set_scope_timescale(@2); } module_item_list_opt module_end { Module::UCDriveType ucd; @@ -4503,8 +4464,6 @@ module } } pform_endmodule($4, in_celldefine, ucd); - have_timeunit_decl = false; // We will allow decls again. - have_timeprec_decl = false; } endlabel_opt { // Last step: check any closing name. This is done late so @@ -4896,6 +4855,8 @@ module_item | attribute_list_opt assertion_item + | timeunits_declaration + | class_declaration | task_declaration @@ -5019,14 +4980,6 @@ module_item | KK_attribute '(' error ')' ';' { yyerror(@1, "error: Malformed $attribute parameter list."); } - | K_timeunit_check TIME_LITERAL ';' - { pform_set_timeunit($2, true, true); } - | K_timeunit_check TIME_LITERAL '/' TIME_LITERAL ';' - { pform_set_timeunit($2, true, true); - pform_set_timeprecision($4, true, true); - } - | K_timeprecision_check TIME_LITERAL ';' - { pform_set_timeprecision($2, true, true); } ; module_item_list diff --git a/parse_misc.h b/parse_misc.h index ddee21bf7..d02902013 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -1,7 +1,7 @@ #ifndef IVL_parse_misc_H #define IVL_parse_misc_H /* - * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -71,12 +71,6 @@ extern unsigned long based_size; extern bool in_celldefine; enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 }; extern UCDriveType uc_drive; -/* - * Flags to control if we are declaring or checking a timeunit or - * timeprecision statement. - */ -extern bool have_timeunit_decl; -extern bool have_timeprec_decl; /* * The parser signals back to the lexor that the next identifier diff --git a/pform.cc b/pform.cc index 1be0e2b46..f071d1fbf 100644 --- a/pform.cc +++ b/pform.cc @@ -73,6 +73,7 @@ vector pform_units; static bool is_compilation_unit(LexicalScope*scope) { // A compilation unit is the only scope that doesn't have a parent. + assert(scope); return scope->parent_scope() == 0; } @@ -355,30 +356,27 @@ static PModport*pform_cur_modport = 0; static NetNet::Type pform_default_nettype = NetNet::WIRE; /* - * These variables track the current time scale, as well as where the - * timescale was set. This supports warnings about tangled timescales. + * These variables track the time scale set by the most recent `timescale + * directive. Time scales set by SystemVerilog timeunit and timeprecision + * declarations are stored directly in the current lexical scope. */ static int pform_time_unit; static int pform_time_prec; -/* These two flags check the initial timeprecision and timeunit - * declaration inside a module. - */ -static bool tp_decl_flag = false; -static bool tu_decl_flag = false; - /* - * Flags used to set time_from_timescale based on timeunit and - * timeprecision. + * These variables track where the most recent `timescale directive + * occurred. This allows us to warn about time scales that are inherited + * from another file. */ -static bool tu_global_flag = false; -static bool tp_global_flag = false; -static bool tu_local_flag = false; -static bool tp_local_flag = false; - static char*pform_timescale_file = 0; static unsigned pform_timescale_line; +/* + * These variables track whether we can accept new timeunits declarations. + */ +bool allow_timeunit_decl = true; +bool allow_timeprec_decl = true; + static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno) { obj->set_lineno(lineno); @@ -426,17 +424,57 @@ static PScopeExtra* find_nearest_scopex(LexicalScope*scope) } /* - * Set the local time unit/precision to the global value. + * Set the local time unit/precision. This version is used for setting + * the time scale for design elements (modules, packages, etc.) and is + * called after any initial timeunit and timeprecision declarations + * have been parsed. */ -static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc) +void pform_set_scope_timescale(const struct vlltype&loc) { - scope->time_unit = pform_time_unit; - scope->time_precision = pform_time_prec; - /* If we have a timescale file then the time information is from - * a timescale directive. */ - scope->time_from_timescale = pform_timescale_file != 0; + PScopeExtra*scope = dynamic_cast(lexical_scope); + assert(scope); - if (warn_timescale && is_compilation_unit(lexical_scope) && pform_timescale_file + PScopeExtra*parent = find_nearest_scopex(scope->parent_scope()); + + bool used_global_timescale = false; + if (scope->time_unit_is_default) { + if (is_compilation_unit(scope)) { + scope->time_unit = def_ts_units; + } else if (!is_compilation_unit(parent)) { + scope->time_unit = parent->time_unit; + scope->time_unit_is_default = parent->time_unit_is_default; + } else if (pform_timescale_file != 0) { + scope->time_unit = pform_time_unit; + scope->time_unit_is_default = false; + used_global_timescale = true; + } else /* parent is compilation unit */ { + scope->time_unit = parent->time_unit; + scope->time_unit_is_default = parent->time_unit_is_default; + } + } + if (scope->time_prec_is_default) { + if (is_compilation_unit(scope)) { + scope->time_precision = def_ts_prec; + } else if (!is_compilation_unit(parent)) { + scope->time_precision = parent->time_precision; + scope->time_prec_is_default = parent->time_prec_is_default; + } else if (pform_timescale_file != 0) { + scope->time_precision = pform_time_prec; + scope->time_prec_is_default = false; + used_global_timescale = true; + } else { + scope->time_precision = parent->time_precision; + scope->time_prec_is_default = parent->time_prec_is_default; + } + } + + if (gn_system_verilog() && (scope->time_unit < scope->time_precision)) { + VLerror("error: a timeprecision is missing or is too large!"); + } else { + assert(scope->time_unit >= scope->time_precision); + } + + if (warn_timescale && used_global_timescale && (strcmp(pform_timescale_file, loc.text) != 0)) { cerr << loc.get_fileline() << ": warning: " @@ -445,6 +483,22 @@ static void pform_set_scope_timescale(PScope*scope, const struct vlltype&loc) cerr << pform_timescale_file << ":" << pform_timescale_line << ": ...: The inherited timescale is here." << endl; } + + allow_timeunit_decl = false; + allow_timeprec_decl = false; +} + +/* + * Set the local time unit/precision. This version is used for setting + * the time scale for subsidiary items (classes, subroutines, etc.), + * which simply inherit their time scale from their parent scope. + */ +static void pform_set_scope_timescale(PScope*scope, const PScope*parent) +{ + scope->time_unit = parent->time_unit; + scope->time_precision = parent->time_precision; + scope->time_unit_is_default = parent->time_unit_is_default; + scope->time_prec_is_default = parent->time_prec_is_default; } PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, @@ -454,12 +508,12 @@ PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name, class_scope->default_lifetime = find_lifetime(lifetime); FILE_NAME(class_scope, loc); - pform_set_scope_timescale(class_scope, loc); - PScopeExtra*scopex = find_nearest_scopex(lexical_scope); assert(scopex); assert(!pform_cur_generate); + pform_set_scope_timescale(class_scope, scopex); + if (scopex->classes.find(name) != scopex->classes.end()) { cerr << class_scope->get_fileline() << ": error: duplicate " "definition for class '" << name << "' in '" @@ -480,7 +534,8 @@ PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name, pkg_scope->default_lifetime = find_lifetime(lifetime); FILE_NAME(pkg_scope, loc); - pform_set_scope_timescale(pkg_scope, loc); + allow_timeunit_decl = true; + allow_timeprec_decl = true; lexical_scope = pkg_scope; return pkg_scope; @@ -498,8 +553,6 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, task->default_lifetime = default_lifetime; FILE_NAME(task, loc); - pform_set_scope_timescale(task, loc); - PScopeExtra*scopex = find_nearest_scopex(lexical_scope); assert(scopex); if (is_compilation_unit(scopex) && !gn_system_verilog()) { @@ -508,6 +561,8 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, error_count += 1; } + pform_set_scope_timescale(task, scopex); + if (pform_cur_generate) { // Check if the task is already in the dictionary. if (pform_cur_generate->tasks.find(task->pscope_name()) != @@ -547,8 +602,6 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, func->default_lifetime = default_lifetime; FILE_NAME(func, loc); - pform_set_scope_timescale(func, loc); - PScopeExtra*scopex = find_nearest_scopex(lexical_scope); assert(scopex); if (is_compilation_unit(scopex) && !gn_system_verilog()) { @@ -557,6 +610,8 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, error_count += 1; } + pform_set_scope_timescale(func, scopex); + if (pform_cur_generate) { // Check if the function is already in the dictionary. if (pform_cur_generate->funcs.find(func->pscope_name()) != @@ -907,64 +962,23 @@ static void pform_declare_implicit_nets(PExpr*expr) /* * The lexor calls this function to set the active timescale when it * detects a `timescale directive. The function saves the directive - * values (for use by modules) and if warnings are enabled checks to - * see if some modules have no timescale. + * values (for use by subsequent design elements) and if warnings are + * enabled checks to see if some design elements have no timescale. */ void pform_set_timescale(int unit, int prec, const char*file, unsigned lineno) { - bool first_flag = true; - assert(unit >= prec); pform_time_unit = unit; pform_time_prec = prec; - /* A `timescale clears the timeunit/timeprecision state. */ - tu_global_flag = false; - tp_global_flag = false; if (pform_timescale_file) { free(pform_timescale_file); - first_flag = false; } if (file) pform_timescale_file = strdup(file); else pform_timescale_file = 0; pform_timescale_line = lineno; - - if (!warn_timescale || !first_flag || !file) return; - - /* Look to see if we have any modules without a timescale. */ - bool have_no_ts = false; - map::iterator mod; - for (mod = pform_modules.begin(); mod != pform_modules.end(); ++ mod ) { - const Module*mp = (*mod).second; - if (mp->time_from_timescale || - mp->timescale_warn_done) continue; - have_no_ts = true; - break; - } - - /* If we do then print a message for the new ones. */ - if (have_no_ts) { - cerr << file << ":" << lineno << ": warning: " - << "Some modules have no timescale. This may cause" - << endl; - cerr << file << ":" << lineno << ": : " - << "confusing timing results. Affected modules are:" - << endl; - - for (mod = pform_modules.begin() - ; mod != pform_modules.end() ; ++ mod ) { - Module*mp = (*mod).second; - if (mp->time_from_timescale || - mp->timescale_warn_done) continue; - mp->timescale_warn_done = true; - - cerr << file << ":" << lineno << ": : " - << " -- module " << (*mod).first - << " declared here: " << mp->get_fileline() << endl; - } - } } bool get_time_unit(const char*cp, int &unit) @@ -1084,70 +1098,62 @@ static bool get_time_unit_prec(const char*cp, int &res, bool is_unit) return true; } -void pform_set_timeunit(const char*txt, bool in_module, bool only_check) +void pform_set_timeunit(const char*txt) { int val; if (get_time_unit_prec(txt, val, true)) return; - if (in_module) { - if (!only_check) { - pform_cur_module.front()->time_unit = val; - tu_decl_flag = true; - tu_local_flag = true; - } else if (!tu_decl_flag) { - VLerror(yylloc, "error: repeat timeunit found and the " - "initial module timeunit is missing."); - return; - } else if (pform_cur_module.front()->time_unit != val) { - VLerror(yylloc, "error: repeat timeunit does not match " - "the initial module timeunit " - "declaration."); - return; - } + PScopeExtra*scope = dynamic_cast(lexical_scope); + assert(scope); + if (allow_timeunit_decl) { + scope->time_unit = val; + scope->time_unit_is_local = true; + scope->time_unit_is_default = false; + allow_timeunit_decl = false; + } else if (!scope->time_unit_is_local) { + VLerror(yylloc, "error: repeat timeunit found and the initial " + "timeunit for this scope is missing."); + } else if (scope->time_unit != val) { + VLerror(yylloc, "error: repeat timeunit does not match the " + "initial timeunit for this scope."); } else { - /* Skip a global timeunit when `timescale is defined. */ - if (pform_timescale_file) return; - tu_global_flag = true; - pform_time_unit = val; + // This is a redeclaration, so don't allow any new declarations + allow_timeprec_decl = false; } } int pform_get_timeunit() { - if (pform_cur_module.empty()) - return pform_time_unit; - else - return pform_cur_module.front()->time_unit; + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + assert(scopex); + return scopex->time_unit; } -void pform_set_timeprecision(const char*txt, bool in_module, bool only_check) +void pform_set_timeprecision(const char*txt) { int val; if (get_time_unit_prec(txt, val, false)) return; - if (in_module) { - if (!only_check) { - pform_cur_module.front()->time_precision = val; - tp_decl_flag = true; - tp_local_flag = true; - } else if (!tp_decl_flag) { - VLerror(yylloc, "error: repeat timeprecision found and the " - "initial module timeprecision is missing."); - return; - } else if (pform_cur_module.front()->time_precision != val) { - VLerror(yylloc, "error: repeat timeprecision does not match " - "the initial module timeprecision " - "declaration."); - return; - } + PScopeExtra*scope = dynamic_cast(lexical_scope); + assert(scope); + + if (allow_timeprec_decl) { + scope->time_precision = val; + scope->time_prec_is_local = true; + scope->time_prec_is_default = false; + allow_timeprec_decl = false; + } else if (!scope->time_prec_is_local) { + VLerror(yylloc, "error: repeat timeprecision found and the initial " + "timeprecision for this scope is missing."); + } else if (scope->time_precision != val) { + VLerror(yylloc, "error: repeat timeprecision does not match the " + "initial timeprecision for this scope."); } else { - /* Skip a global timeprecision when `timescale is defined. */ - if (pform_timescale_file) return; - pform_time_prec = val; - tp_global_flag=true; + // This is a redeclaration, so don't allow any new declarations + allow_timeunit_decl = false; } } @@ -1252,14 +1258,13 @@ void pform_startmodule(const struct vlltype&loc, const char*name, FILE_NAME(cur_module, loc); - pform_set_scope_timescale(cur_module, loc); - tu_local_flag = tu_global_flag; - tp_local_flag = tp_global_flag; - cur_module->library_flag = pform_library_flag; pform_cur_module.push_front(cur_module); + allow_timeunit_decl = true; + allow_timeprec_decl = true; + lexical_scope = cur_module; /* The generate scheme numbering starts with *1*, not @@ -1269,21 +1274,6 @@ void pform_startmodule(const struct vlltype&loc, const char*name, pform_bind_attributes(cur_module->attributes, attr); } -/* - * In SystemVerilog we can have separate timeunit and timeprecision - * declarations. We need to have the values worked out by time this - * task is called. - */ -void pform_check_timeunit_prec() -{ - assert(! pform_cur_module.empty()); - if (gn_system_verilog() && - (pform_cur_module.front()->time_unit < pform_cur_module.front()->time_precision)) { - VLerror("error: a timeprecision is missing or is too large!"); - } else assert(pform_cur_module.front()->time_unit >= - pform_cur_module.front()->time_precision); -} - /* * This function is called by the parser to make a simple port * reference. This is a name without a .X(...), so the internal name @@ -1327,8 +1317,6 @@ void pform_endmodule(const char*name, bool inside_celldefine, Module*cur_module = pform_cur_module.front(); pform_cur_module.pop_front(); - cur_module->time_from_timescale = (tu_local_flag && tp_local_flag) - || (pform_timescale_file != 0); perm_string mod_name = cur_module->mod_name(); assert(strcmp(name, mod_name) == 0); cur_module->is_cell = inside_celldefine; @@ -1358,11 +1346,6 @@ void pform_endmodule(const char*name, bool inside_celldefine, // The current lexical scope should be this module by now. ivl_assert(*cur_module, lexical_scope == cur_module); pform_pop_scope(); - - tp_decl_flag = false; - tu_decl_flag = false; - tu_local_flag = false; - tp_local_flag = false; } static void pform_add_genvar(const struct vlltype&li, const perm_string&name, @@ -3691,12 +3674,18 @@ int pform_parse(const char*path) sprintf(unit_name, "$unit#%u", ++nunits); else sprintf(unit_name, "$unit"); + PPackage*unit = new PPackage(lex_strings.make(unit_name), 0); unit->default_lifetime = LexicalScope::STATIC; - unit->time_unit = def_ts_units; - unit->time_precision = def_ts_prec; - unit->time_from_timescale = false; + unit->set_file(filename_strings.make(path)); + unit->set_lineno(1); pform_units.push_back(unit); + + pform_set_timescale(def_ts_units, def_ts_prec, 0, 0); + + allow_timeunit_decl = true; + allow_timeprec_decl = true; + lexical_scope = unit; } reset_lexor(); diff --git a/pform.h b/pform.h index 8666386eb..b53325404 100644 --- a/pform.h +++ b/pform.h @@ -1,7 +1,7 @@ #ifndef IVL_pform_H #define IVL_pform_H /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -165,8 +165,8 @@ extern void pform_startmodule(const struct vlltype&loc, const char*name, bool program_block, bool is_interface, LexicalScope::lifetime_t lifetime, list*attr); -extern void pform_check_timeunit_prec(); extern void pform_module_set_ports(vector*); +extern void pform_set_scope_timescale(const struct vlltype&loc); /* These functions are used when we have a complete port definition, either in an ansi style or non-ansi style declaration. In this case, we have @@ -567,8 +567,7 @@ extern void parm_to_defparam_list(const string¶m); */ extern bool get_time_unit(const char*cp, int &unit); extern int pform_get_timeunit(); -extern void pform_set_timeunit(const char*txt, bool in_module, bool only_check); -extern void pform_set_timeprecision(const char*txt, bool in_module, - bool only_check); +extern void pform_set_timeunit(const char*txt); +extern void pform_set_timeprecision(const char*txt); #endif /* IVL_pform_H */ From 479af09cc39e4a8478982483fa0f428c5fe7b33f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 5 Nov 2017 22:28:21 +0000 Subject: [PATCH 049/138] Fix trailing whitespace. --- pform.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pform.cc b/pform.cc index f071d1fbf..029e6cb32 100644 --- a/pform.cc +++ b/pform.cc @@ -3696,7 +3696,7 @@ int pform_parse(const char*path) if (vl_input != stdin) { if (ivlpp_string) pclose(vl_input); - else + else fclose(vl_input); } From f83e01847a093dc4561ad8700aa1173dfc262356 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 6 Nov 2017 00:37:56 +0000 Subject: [PATCH 050/138] Fix a couple of minor bugs in the timescale parsing rework. --- parse.y | 9 +++++---- pform.cc | 18 +++++++----------- pform.h | 9 +++++++-- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/parse.y b/parse.y index a48b84ef1..cc9ef27ec 100644 --- a/parse.y +++ b/parse.y @@ -2234,13 +2234,14 @@ tf_port_list /* IEEE1800-2005: A.2.7 */ timeunits_declaration /* IEEE1800-2005: A.1.2 */ : K_timeunit TIME_LITERAL ';' - { pform_set_timeunit($2); } + { pform_set_timeunit($2, allow_timeunit_decl); } | K_timeunit TIME_LITERAL '/' TIME_LITERAL ';' - { pform_set_timeunit($2); - pform_set_timeprecision($4); + { bool initial_decl = allow_timeunit_decl && allow_timeprec_decl; + pform_set_timeunit($2, initial_decl); + pform_set_timeprec($4, initial_decl); } | K_timeprecision TIME_LITERAL ';' - { pform_set_timeprecision($2); } + { pform_set_timeprec($2, allow_timeprec_decl); } ; /* Allow zero, one, or two declarations. The second declaration might diff --git a/pform.cc b/pform.cc index 029e6cb32..c1a08a29a 100644 --- a/pform.cc +++ b/pform.cc @@ -469,7 +469,9 @@ void pform_set_scope_timescale(const struct vlltype&loc) } if (gn_system_verilog() && (scope->time_unit < scope->time_precision)) { - VLerror("error: a timeprecision is missing or is too large!"); + if (scope->time_unit_is_local || scope->time_prec_is_local) { + VLerror("error: a timeprecision is missing or is too large!"); + } } else { assert(scope->time_unit >= scope->time_precision); } @@ -1098,7 +1100,7 @@ static bool get_time_unit_prec(const char*cp, int &res, bool is_unit) return true; } -void pform_set_timeunit(const char*txt) +void pform_set_timeunit(const char*txt, bool initial_decl) { int val; @@ -1107,7 +1109,7 @@ void pform_set_timeunit(const char*txt) PScopeExtra*scope = dynamic_cast(lexical_scope); assert(scope); - if (allow_timeunit_decl) { + if (initial_decl) { scope->time_unit = val; scope->time_unit_is_local = true; scope->time_unit_is_default = false; @@ -1118,9 +1120,6 @@ void pform_set_timeunit(const char*txt) } else if (scope->time_unit != val) { VLerror(yylloc, "error: repeat timeunit does not match the " "initial timeunit for this scope."); - } else { - // This is a redeclaration, so don't allow any new declarations - allow_timeprec_decl = false; } } @@ -1131,7 +1130,7 @@ int pform_get_timeunit() return scopex->time_unit; } -void pform_set_timeprecision(const char*txt) +void pform_set_timeprec(const char*txt, bool initial_decl) { int val; @@ -1140,7 +1139,7 @@ void pform_set_timeprecision(const char*txt) PScopeExtra*scope = dynamic_cast(lexical_scope); assert(scope); - if (allow_timeprec_decl) { + if (initial_decl) { scope->time_precision = val; scope->time_prec_is_local = true; scope->time_prec_is_default = false; @@ -1151,9 +1150,6 @@ void pform_set_timeprecision(const char*txt) } else if (scope->time_precision != val) { VLerror(yylloc, "error: repeat timeprecision does not match the " "initial timeprecision for this scope."); - } else { - // This is a redeclaration, so don't allow any new declarations - allow_timeunit_decl = false; } } diff --git a/pform.h b/pform.h index b53325404..7157f7c75 100644 --- a/pform.h +++ b/pform.h @@ -567,7 +567,12 @@ extern void parm_to_defparam_list(const string¶m); */ extern bool get_time_unit(const char*cp, int &unit); extern int pform_get_timeunit(); -extern void pform_set_timeunit(const char*txt); -extern void pform_set_timeprecision(const char*txt); +extern void pform_set_timeunit(const char*txt, bool initial_decl); +extern void pform_set_timeprec(const char*txt, bool initial_decl); +/* + * Flags to determine whether this is an initial declaration. + */ +extern bool allow_timeunit_decl; +extern bool allow_timeprec_decl; #endif /* IVL_pform_H */ From af1ea13c479a6db549228bd1ab4437400bee2a48 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 6 Nov 2017 21:03:03 +0000 Subject: [PATCH 051/138] Don't check for macro redefinition if the warning is disabled. And reword the comment to be a bit less dictatorial. --- ivlpp/lexor.lex | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index b8ccb6296..a74a8c357 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -860,16 +860,17 @@ void define_macro(const char* name, const char* value, int keyword, int argc) struct define_t* def; struct define_t* prev; - /* Verilog spec has a very nasty system of macros jumping from - * file to file, resulting in a global macro scope. We abosolutely - * MUST track macro redefinitions and warn user about them. + /* Verilog has a very nasty system of macros jumping from + * file to file, resulting in a global macro scope. Here + * we optionally warn about any redefinitions. */ - - prev = def_lookup(name); - if (prev && warn_redef) { - emit_pathline(istack); - fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n", - name, prev->value, value); + if (warn_redef) { + prev = def_lookup(name); + if (prev) { + emit_pathline(istack); + fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n", + name, prev->value, value); + } } def = malloc(sizeof(struct define_t)); From c622d372f90f721b2750f74d042c597d17744958 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 7 Nov 2017 18:48:48 +0000 Subject: [PATCH 052/138] Fix for GitHub issue #169: nets can get given wrong scope in VPI. In vvp, the __vpiSignal object holds a pointer to the scope containing the signal. This was getting set to the current scope when the net was finally resolved, rather than to the scope where the net was declared. --- vvp/vpi_priv.h | 7 +++++-- vvp/vpi_real.cc | 16 ++++++++++++++-- vvp/vpi_signal.cc | 31 +++++++++++++++++++++---------- vvp/words.cc | 6 +++--- 4 files changed, 43 insertions(+), 17 deletions(-) diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index c26e6da50..9fa811e3f 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -376,7 +376,8 @@ extern vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec); extern vpiHandle vpip_make_var4(const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*net); -extern vpiHandle vpip_make_net4(const char*name, int msb, int lsb, +extern vpiHandle vpip_make_net4(__vpiScope*scope, + const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*node); /* @@ -543,7 +544,9 @@ struct __vpiRealVar : public __vpiHandle { }; extern __vpiScope* vpip_scope(__vpiRealVar*sig); -extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire); +extern vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net); +extern vpiHandle vpip_make_real_net(__vpiScope*scope, + const char*name, vvp_net_t*net); class __vpiBaseVar : public __vpiHandle { diff --git a/vvp/vpi_real.cc b/vvp/vpi_real.cc index 54ad3caf6..e51ee3219 100644 --- a/vvp/vpi_real.cc +++ b/vvp/vpi_real.cc @@ -178,7 +178,8 @@ vpiHandle __vpiRealVar::vpi_handle(int code) vpiHandle __vpiRealVar::vpi_iterate(int code) { return real_var_iterate(code, this); } -vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire) +static vpiHandle vpip_make_real_(__vpiScope*scope, const char*name, + vvp_net_t*net, bool is_wire) { struct __vpiRealVar*obj = new __vpiRealVar; @@ -187,11 +188,22 @@ vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net, bool is_wire) obj->is_wire = is_wire; obj->net = net; - obj->within.scope = vpip_peek_current_scope(); + obj->within.scope = scope; return obj; } +vpiHandle vpip_make_real_var(const char*name, vvp_net_t*net) +{ + return vpip_make_real_(vpip_peek_current_scope(), name, net, false); +} + +vpiHandle vpip_make_real_net(__vpiScope*scope, + const char*name, vvp_net_t*net) +{ + return vpip_make_real_(scope, name, net, true); +} + #ifdef CHECK_WITH_VALGRIND void real_delete(vpiHandle item) { diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 9cac4c796..5e63e77af 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -132,9 +132,19 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind return res; } -static vpiHandle fill_in_net4(struct __vpiSignal*obj, - const char*name, int msb, int lsb, - bool signed_flag, vvp_net_t*node); +static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope, + const char*name, int msb, int lsb, + bool signed_flag, vvp_net_t*node); + +static vpiHandle fill_in_var4(struct __vpiSignal*obj, + const char*name, int msb, int lsb, + bool signed_flag, vvp_net_t*node) +{ + // Variable declarations are always resolved immediately, + // so we can assume they belong in the current scope. + return fill_in_net4(obj, vpip_peek_current_scope(), + name, msb, lsb, signed_flag, node); +} /* * The standard formatting/conversion routines. @@ -972,7 +982,7 @@ struct signal_longint : public __vpiSignal { vpiHandle vpip_make_int4(const char*name, int msb, int lsb, vvp_net_t*vec) { __vpiSignal*obj = new signal_integer; - return fill_in_net4(obj, name, msb, lsb, true, vec); + return fill_in_var4(obj, name, msb, lsb, true, vec); } /* @@ -1011,7 +1021,7 @@ vpiHandle vpip_make_int2(const char*name, int msb, int lsb, bool signed_flag, } } - return fill_in_net4(obj, name, msb, lsb, signed_flag, vec); + return fill_in_var4(obj, name, msb, lsb, signed_flag, vec); } /* @@ -1021,7 +1031,7 @@ vpiHandle vpip_make_var4(const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*vec) { __vpiSignal*obj = new signal_reg; - return fill_in_net4(obj, name, msb, lsb, signed_flag, vec); + return fill_in_var4(obj, name, msb, lsb, signed_flag, vec); } #ifdef CHECK_WITH_VALGRIND @@ -1116,7 +1126,7 @@ void signal_pool_delete() * The name is the PLI name for the object. If it is an array it is * []. */ -static vpiHandle fill_in_net4(struct __vpiSignal*obj, +static vpiHandle fill_in_net4(struct __vpiSignal*obj, __vpiScope*scope, const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*node) { @@ -1130,18 +1140,19 @@ static vpiHandle fill_in_net4(struct __vpiSignal*obj, // Place this object within a scope. If this object is // attached to an array, then this value will be replaced with // the handle to the parent. - obj->within.scope = vpip_peek_current_scope(); + obj->within.scope = scope; count_vpi_nets += 1; return obj; } -vpiHandle vpip_make_net4(const char*name, int msb, int lsb, +vpiHandle vpip_make_net4(__vpiScope*scope, + const char*name, int msb, int lsb, bool signed_flag, vvp_net_t*node) { struct __vpiSignal*obj = new signal_net; - return fill_in_net4(obj, name, msb, lsb, signed_flag, node); + return fill_in_net4(obj, scope, name, msb, lsb, signed_flag, node); } static int PV_get_base(struct __vpiPV*rfp) diff --git a/vvp/words.cc b/vvp/words.cc index 0a89f0b8d..fcafa939a 100644 --- a/vvp/words.cc +++ b/vvp/words.cc @@ -48,7 +48,7 @@ static void __compile_var_real(char*label, char*name, define_functor_symbol(label, net); - vpiHandle obj = vpip_make_real_var(name, net, false); + vpiHandle obj = vpip_make_real_var(name, net); compile_vpi_symbol(label, obj); if (name) { @@ -350,7 +350,7 @@ static void do_compile_net(vvp_net_t*node, vvp_array_t array, vpiHandle obj = 0; if (! local_flag) { /* Make the vpiHandle for the reg. */ - obj = vpip_make_net4(name, msb, lsb, signed_flag, node); + obj = vpip_make_net4(scope, name, msb, lsb, signed_flag, node); /* This attaches the label to the vpiHandle */ compile_vpi_symbol(my_label, obj); } @@ -481,7 +481,7 @@ static void __compile_real_net2(vvp_net_t*node, vvp_array_t array, vpiHandle obj = 0; if (!local_flag) { - obj = vpip_make_real_var(name, node, true); + obj = vpip_make_real_net(scope, name, node); compile_vpi_symbol(my_label, obj); } #ifdef CHECK_WITH_VALGRIND From 02daffc97e34fb86eb18226fc9dbe7c0d598fa03 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 19:50:42 +0000 Subject: [PATCH 053/138] Add option to only warn about macro redefinitions that change the text. A common use case (prior to the introduction of localparam) was to use macros to define constant values, and to put global constant values in an include file that gets included by each source file. This will generate a lot of spurious warnings if we warn about all redefinitions. Make this new option the default for -Wall. --- driver/iverilog.man.in | 12 ++++++++---- driver/main.c | 34 ++++++++++++++++++++++------------ ivlpp/globals.h | 3 ++- ivlpp/lexor.lex | 4 ++-- ivlpp/main.c | 20 +++++++++++++------- 5 files changed, 47 insertions(+), 26 deletions(-) diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 3861690d2..56ba6d201 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,4 +1,4 @@ -.TH iverilog 1 "Oct 14th, 2017" "" "Version %M.%n%E" +.TH iverilog 1 "Nov 8th, 2017" "" "Version %M.%n%E" .SH NAME iverilog - Icarus Verilog compiler @@ -316,8 +316,9 @@ after a \fB\-Wall\fP argument to suppress isolated warning types. .TP 8 .B all -This enables the anachronisms, implicit, macro-redefinition, portbind, -select\-range, timescale, and sensitivity\-entire\-array warning categories. +This enables the anachronisms, implicit, macro-replacement, portbind, +select\-range, timescale, and sensitivity\-entire\-array warning +categories. .TP 8 .B anachronisms @@ -331,8 +332,11 @@ example, if a scalar wire X is used but not declared in the Verilog source, this will print a warning at its first use. .TP 8 -.B macro-redefinition +.B macro-redefinition\fI | \fPmacro-replacement This enables preprocessor warnings when a macro is being redefined. +The first variant prints a warning any time a macro is redefined. +The second variant only prints a warning if the macro text changes. +Use \fBno-macro-redefinition\fP to turn off all warnings of this type. .TP 8 .B portbind diff --git a/driver/main.c b/driver/main.c index d12c40fe1..b723d7ff3 100644 --- a/driver/main.c +++ b/driver/main.c @@ -350,7 +350,8 @@ static void build_preprocess_command(int e_flag) ivlpp_dir, sep, verbose_flag ? " -v" : "", e_flag ? "" : " -L", - strchr(warning_flags, 'r') ? " -Wredef " : "", + strchr(warning_flags, 'r') ? " -Wredef-all " : + strchr(warning_flags, 'R') ? " -Wredef-chg " : "", defines_path, source_path, compiled_defines_path, e_flag ? "" : " | "); @@ -520,14 +521,11 @@ static void process_warning_switch(const char*name) process_warning_switch("anachronisms"); process_warning_switch("implicit"); process_warning_switch("implicit-dimensions"); + process_warning_switch("macro-replacement"); process_warning_switch("portbind"); process_warning_switch("select-range"); process_warning_switch("timescale"); process_warning_switch("sensitivity-entire-array"); - process_warning_switch("macro-redefinition"); - } else if (strcmp(name,"macro-redefinition") == 0) { - if (! strchr(warning_flags, 'r')) - strcat(warning_flags, "r"); } else if (strcmp(name,"anachronisms") == 0) { if (! strchr(warning_flags, 'n')) strcat(warning_flags, "n"); @@ -540,6 +538,12 @@ static void process_warning_switch(const char*name) } else if (strcmp(name,"implicit-dimensions") == 0) { if (! strchr(warning_flags, 'd')) strcat(warning_flags, "d"); + } else if (strcmp(name,"macro-redefinition") == 0) { + if (! strchr(warning_flags, 'r')) + strcat(warning_flags, "r"); + } else if (strcmp(name,"macro-replacement") == 0) { + if (! strchr(warning_flags, 'R')) + strcat(warning_flags, "R"); } else if (strcmp(name,"portbind") == 0) { if (! strchr(warning_flags, 'p')) strcat(warning_flags, "p"); @@ -566,12 +570,6 @@ static void process_warning_switch(const char*name) cp[0] = cp[1]; cp += 1; } - } else if (strcmp(name,"no-macro-redefinition") == 0) { - char*cp = strchr(warning_flags, 'r'); - if (cp) while (*cp) { - cp[0] = cp[1]; - cp += 1; - } } else if (strcmp(name,"no-floating-nets") == 0) { char*cp = strchr(warning_flags, 'f'); if (cp) while (*cp) { @@ -590,6 +588,17 @@ static void process_warning_switch(const char*name) cp[0] = cp[1]; cp += 1; } + } else if (strcmp(name,"no-macro-redefinition") == 0) { + char*cp = strchr(warning_flags, 'r'); + if (cp) while (*cp) { + cp[0] = cp[1]; + cp += 1; + } + cp = strchr(warning_flags, 'R'); + if (cp) while (*cp) { + cp[0] = cp[1]; + cp += 1; + } } else if (strcmp(name,"no-portbind") == 0) { char*cp = strchr(warning_flags, 'p'); if (cp) while (*cp) { @@ -1322,7 +1331,8 @@ int main(int argc, char **argv) files. */ fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n", ivlpp_dir, sep, - strchr(warning_flags, 'r') ? "-Wredef" : "", + strchr(warning_flags, 'r') ? "-Wredef-all" : + strchr(warning_flags, 'R') ? "-Wredef-chg" : "", defines_path, compiled_defines_path ); diff --git a/ivlpp/globals.h b/ivlpp/globals.h index 1c4cee43d..a1f77e95e 100644 --- a/ivlpp/globals.h +++ b/ivlpp/globals.h @@ -1,7 +1,7 @@ #ifndef IVL_globals_H #define IVL_globals_H /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -54,6 +54,7 @@ extern char dep_mode; extern int verbose_flag; extern int warn_redef; +extern int warn_redef_all; /* This is the entry to the lexer. */ extern int yylex(void); diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index a74a8c357..5ab3e55de 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1,7 +1,7 @@ %option prefix="yy" %{ /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -866,7 +866,7 @@ void define_macro(const char* name, const char* value, int keyword, int argc) */ if (warn_redef) { prev = def_lookup(name); - if (prev) { + if (prev && (warn_redef_all || (strcmp(prev->value, value) != 0))) { emit_pathline(istack); fprintf(stderr, "warning: redefinition of macro %s from value '%s' to '%s'\n", name, prev->value, value); diff --git a/ivlpp/main.c b/ivlpp/main.c index b4909b647..19ef09bde 100644 --- a/ivlpp/main.c +++ b/ivlpp/main.c @@ -1,5 +1,5 @@ const char COPYRIGHT[] = - "Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com)"; + "Copyright (c) 1999-2017 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 @@ -100,6 +100,7 @@ FILE *depend_file = NULL; /* Should we warn about macro redefinitions? */ int warn_redef = 0; +int warn_redef_all = 0; static int flist_read_flags(const char*path) { @@ -339,11 +340,14 @@ int main(int argc, char*argv[]) break; } - case 'W': { - if (strcmp(optarg, "redef")==0) - warn_redef = 1; - break; - } + case 'W': + if (strcmp(optarg, "redef-all") == 0) { + warn_redef_all = 1; + warn_redef = 1; + } else if (strcmp(optarg, "redef-chg") == 0) { + warn_redef = 1; + } + break; case 'v': fprintf(stderr, "Icarus Verilog Preprocessor version " @@ -376,7 +380,9 @@ int main(int argc, char*argv[]) " -P - Read precompiled defines from \n" " -v - Verbose\n" " -V - Print version information and quit\n" - " -W - Enable extra ivlpp warning category (e.g. redef)\n", + " -W - Enable extra ivlpp warning category:\n" + " o redef-all - all macro redefinitions\n" + " o redef-chg - macro definition changes\n", argv[0]); return flag_errors; } From c0845d8bea17eb101f63301b95bae9f4cb178e93 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 20:07:38 +0000 Subject: [PATCH 054/138] Fix assertion failure when using -Wmacro-redefinition, -y, and -D. Predefined macros get stored in the precompiled macro file that gets read back in when processing library files. This means the predefined macros get processed twice. We need to skip the check in this case. --- ivlpp/lexor.lex | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 5ab3e55de..626c7071c 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -863,8 +863,13 @@ void define_macro(const char* name, const char* value, int keyword, int argc) /* Verilog has a very nasty system of macros jumping from * file to file, resulting in a global macro scope. Here * we optionally warn about any redefinitions. + * + * If istack is empty, we are processing a configuration + * or precompiled macro file, so don't want to check for + * redefinitions - when a precompiled macro file is used, + * it will contain copies of any predefined macros. */ - if (warn_redef) { + if (warn_redef && istack) { prev = def_lookup(name); if (prev && (warn_redef_all || (strcmp(prev->value, value) != 0))) { emit_pathline(istack); From 0f2ce7da45d31570be06218bea14d0dc58de02d0 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 20:20:04 +0000 Subject: [PATCH 055/138] Fix for GitHub issue #172: don't use %precedence in parser. Older versions of bison don't support this. Use %nonassoc instead. --- parse.y | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/parse.y b/parse.y index cc9ef27ec..bf7847ec1 100644 --- a/parse.y +++ b/parse.y @@ -696,9 +696,9 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %nonassoc K_exclude /* to resolve timeunits declaration/redeclaration ambiguity */ -%precedence no_timeunits_declaration -%precedence one_timeunits_declaration -%precedence K_timeunit K_timeprecision +%nonassoc no_timeunits_declaration +%nonassoc one_timeunits_declaration +%nonassoc K_timeunit K_timeprecision %% From ad83a135e51f8eeeba4bf51225a13cab6459e021 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 20:35:18 +0000 Subject: [PATCH 056/138] Fix assertion failure in vvp wide functor. If the functor output is read before any values have propagated to the functor inputs, the internal storage won't have been initialised. --- vvp/vvp_net.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 4138b1699..4b53978fa 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -3421,7 +3421,8 @@ unsigned vvp_wide_fun_core::port_count() const vvp_vector4_t& vvp_wide_fun_core::value(unsigned idx) { assert(idx < nports_); - assert(port_values_); + if (port_values_ == 0) + port_values_ = new vvp_vector4_t [nports_]; return port_values_[idx]; } From d1487c10f1ad265085b571d099e85a407ff6e63f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 8 Nov 2017 21:23:22 +0000 Subject: [PATCH 057/138] Fix shadow warning when using older versions of gcc. --- net_scope.cc | 4 ++-- netlist.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net_scope.cc b/net_scope.cc index d1c386fef..b9873786e 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -112,10 +112,10 @@ void Definitions::add_class(netclass_t*net_class) * in question. */ -NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*unit, +NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_unit, bool nest, bool program, bool interface, bool compilation_unit) : type_(t), name_(n), nested_module_(nest), program_block_(program), - is_interface_(interface), is_unit_(compilation_unit), unit_(unit), up_(up) + is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up) { events_ = 0; lcounter_ = 0; diff --git a/netlist.h b/netlist.h index 35ac3cab8..09856c198 100644 --- a/netlist.h +++ b/netlist.h @@ -931,7 +931,7 @@ class NetScope : public Definitions, public Attrib { and attach it to the given parent. If no compilation unit is specified, the parent's compilation unit is used. The name is expected to have been permallocated. */ - NetScope(NetScope*up, const hname_t&name, TYPE t, NetScope*unit=0, + NetScope(NetScope*up, const hname_t&name, TYPE t, NetScope*in_unit=0, bool nest=false, bool program=false, bool interface=false, bool compilation_unit=false); ~NetScope(); From f03033e612af3434b75bef80c4e81134e342a3eb Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 16 Nov 2017 19:03:34 -0800 Subject: [PATCH 058/138] Update flex destroy routines to work for version 2.6 and greater --- driver/cflexor.lex | 4 ++-- ivlpp/lexor.lex | 2 +- lexor.lex | 2 +- tgt-pcb/fp.lex | 7 +++++-- vhdlpp/lexor.lex | 11 ++++++++++- vpi/sdf_lexor.lex | 4 ++-- vpi/sys_readmem_lex.lex | 4 ++-- vpi/table_mod_lexor.lex | 4 ++-- vvp/lexor.lex | 4 ++-- 9 files changed, 27 insertions(+), 15 deletions(-) diff --git a/driver/cflexor.lex b/driver/cflexor.lex index 3f3e46e80..c6e3eb860 100644 --- a/driver/cflexor.lex +++ b/driver/cflexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -252,7 +252,7 @@ void destroy_lexor(void) { # 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 626c7071c..8a4355264 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -2119,7 +2119,7 @@ void destroy_lexor(void) { # 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/lexor.lex b/lexor.lex index 70fc1fda9..50d8c6ab9 100644 --- a/lexor.lex +++ b/lexor.lex @@ -1628,7 +1628,7 @@ 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/tgt-pcb/fp.lex b/tgt-pcb/fp.lex index af3292252..3536f51ae 100644 --- a/tgt-pcb/fp.lex +++ b/tgt-pcb/fp.lex @@ -6,7 +6,7 @@ %{ /* - * Copyright (C) 2011-2013 Stephen Williams (steve@icarus.com) + * Copyright (C) 2011-2017 Stephen Williams (steve@icarus.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -79,11 +79,14 @@ void init_fp_lexor(FILE*fd) yyrestart(fd); } +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ void destroy_fp_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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index 8dd8d823a..fdafcb058 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -6,7 +6,7 @@ %{ /* - * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2017 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 @@ -748,7 +748,16 @@ yyscan_t prepare_lexor(FILE*fd) return scanner; } +/* + * Modern version of flex (>=2.5.9) can clean up the scanner data. + */ void destroy_lexor(yyscan_t scanner) { +# ifdef FLEX_SCANNER +# if YY_FLEX_MAJOR_VERSION >= 2 && YY_FLEX_MINOR_VERSION >= 5 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(scanner); +# endif +# endif +# endif } diff --git a/vpi/sdf_lexor.lex b/vpi/sdf_lexor.lex index 0b8c7767e..9f05dd230 100644 --- a/vpi/sdf_lexor.lex +++ b/vpi/sdf_lexor.lex @@ -5,7 +5,7 @@ %{ /* - * Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2017 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 @@ -217,7 +217,7 @@ static void destroy_sdf_lexor(void) { # 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/vpi/sys_readmem_lex.lex b/vpi/sys_readmem_lex.lex index 22e5b0e80..c7f4c53ef 100644 --- a/vpi/sys_readmem_lex.lex +++ b/vpi/sys_readmem_lex.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 1999-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -199,7 +199,7 @@ void destroy_readmem_lexor(void) { # 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/vpi/table_mod_lexor.lex b/vpi/table_mod_lexor.lex index bd518ee7e..36031821b 100644 --- a/vpi/table_mod_lexor.lex +++ b/vpi/table_mod_lexor.lex @@ -6,7 +6,7 @@ %{ /* - * Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -154,7 +154,7 @@ void destroy_tblmod_lexor(void) { # 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif diff --git a/vvp/lexor.lex b/vvp/lexor.lex index b048ee612..3969c296d 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -333,7 +333,7 @@ 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 +# if YY_FLEX_MINOR_VERSION > 5 || defined(YY_FLEX_SUBMINOR_VERSION) && YY_FLEX_SUBMINOR_VERSION >= 9 yylex_destroy(); # endif # endif From 21418c6a41284440040f861ef009f2fbd3c4f96b Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 16 Nov 2017 19:40:09 -0800 Subject: [PATCH 059/138] Fix a couple memory leaks in $sdf_annotate() --- vpi/sys_sdf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 5d69ff623..9d3cd2b7b 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2017 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 @@ -289,7 +289,10 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) FILE *sdf_fd; char *fname = get_filename(callh, name, vpi_scan(argv)); - if (fname == 0) return 0; + if (fname == 0) { + vpi_free_object(argv); + return 0; + } sdf_fd = fopen(fname, "r"); if (sdf_fd == 0) { @@ -297,6 +300,8 @@ static PLI_INT32 sys_sdf_annotate_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) (int)vpi_get(vpiLineNo, callh)); vpi_printf("Unable to open SDF file \"%s\"." " Skipping this annotation.\n", fname); + vpi_free_object(argv); + free(fname); return 0; } From d23b046203b4ad5de0459662a70d72e72ce589ff Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 17 Nov 2017 13:07:18 -0800 Subject: [PATCH 060/138] Update the enumeration methods to set their width test attributes correctly --- elab_expr.cc | 21 ++++++++++- eval_tree.cc | 99 ++++------------------------------------------------ 2 files changed, 26 insertions(+), 94 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 1ff7b7b67..019381481 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -3141,6 +3141,25 @@ unsigned PEIdent::test_width_method_(Design*des, NetScope*scope, width_mode_t&) } } + // Look for the enumeration attributes. + if (const netenum_t*netenum = net->enumeration()) { + if (member_name == "num") { + expr_type_ = IVL_VT_BOOL; + expr_width_ = 32; + min_width_ = 32; + signed_flag_= true; + return 32; + } + if ((member_name == "first") || (member_name == "last") || + (member_name == "next") || (member_name == "prev")) { + expr_type_ = netenum->base_type(); + expr_width_ = netenum->packed_width();; + min_width_ = expr_width_; + signed_flag_ = netenum->get_signed(); + return expr_width_; + } + } + return 0; } diff --git a/eval_tree.cc b/eval_tree.cc index 1c709f5f2..1da857035 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -570,11 +570,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0; verinum::V res = eq_res; - unsigned top = lv.len(); - if (rv.len() < top) - top = rv.len(); - for (unsigned idx = 0 ; idx < top ; idx += 1) { + assert(lv.len() == rv.len()); + + for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) { bool x_bit_present = false; @@ -611,60 +610,6 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r } } - if (res != verinum::Vx) { - verinum::V lpad = verinum::V0; - verinum::V rpad = verinum::V0; - - if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1) - lpad = verinum::V1; - if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1) - rpad = verinum::V1; - - for (unsigned idx = top ; idx < lv.len() ; idx += 1) - switch (lv.get(idx)) { - - case verinum::Vx: - case verinum::Vz: - res = verinum::Vx; - break; - - case verinum::V0: - if (res != verinum::Vx && rpad != verinum::V0) - res = ne_res; - break; - - case verinum::V1: - if (res != verinum::Vx && rpad != verinum::V1) - res = ne_res; - break; - - default: - break; - } - - for (unsigned idx = top ; idx < rv.len() ; idx += 1) - switch (rv.get(idx)) { - - case verinum::Vx: - case verinum::Vz: - res = verinum::Vx; - break; - - case verinum::V0: - if (res != verinum::Vx && lpad != verinum::V0) - res = ne_res; - break; - - case verinum::V1: - if (res != verinum::Vx && lpad != verinum::V1) - res = ne_res; - break; - - default: - break; - } - } - NetEConst*result = new NetEConst(verinum(res, 1)); ivl_assert(*this, result); return result; @@ -681,46 +626,14 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr verinum::V res = verinum::V1; - // Find the smallest argument length. - unsigned cnt = lv.len(); - if (cnt > rv.len()) cnt = rv.len(); + assert(lv.len() == rv.len()); - // Check the common bits. - for (unsigned idx = 0 ; idx < cnt ; idx += 1) + for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) if (lv.get(idx) != rv.get(idx)) { res = verinum::V0; break; } - bool is_signed = lv.has_sign() && rv.has_sign(); - - // If the left value is longer check it against the pad bit. - if (res == verinum::V1) { - verinum::V pad = verinum::V0; - if (is_signed) - pad = rv.get(rv.len()-1); - - for (unsigned idx = cnt ; idx < lv.len() ; idx += 1) - if (lv.get(idx) != pad) { - res = verinum::V0; - break; - } - } - - // If the right value is longer check it against the pad bit. - if (res == verinum::V1) { - verinum::V pad = verinum::V0; - if (is_signed) - pad = lv.get(lv.len()-1); - - for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) { - if (rv.get(idx) != pad) { - res = verinum::V0; - break; - } - } - } - if (ne_flag) { if (res == verinum::V0) res = verinum::V1; else res = verinum::V0; From 3fc9ad2db0754a777f5a8e01d07c73333d19c3d5 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 17 Nov 2017 19:32:09 -0800 Subject: [PATCH 061/138] =?UTF-8?q?Add=20support=20for=20the=20wild=20comp?= =?UTF-8?q?are=20operators=20=3D=3D=3F=20and=20!=3D=3F?= --- design_dump.cc | 18 ++++++++-- elab_expr.cc | 14 ++++++++ eval_tree.cc | 63 +++++++++++++++++++++++++++++++++-- expr_synth.cc | 13 +++++++- ivl_target.h | 6 ++-- lexor.lex | 2 ++ netlist.h | 3 ++ netmisc.cc | 2 ++ parse.y | 14 ++++++-- t-dll-api.cc | 6 ++++ t-dll.cc | 6 ++++ tgt-stub/stub.c | 10 +++++- tgt-vlog95/expr.c | 14 +++++++- tgt-vlog95/logic_lpm.c | 32 +++++++++++++++--- tgt-vvp/draw_net_input.c | 4 ++- tgt-vvp/eval_real.c | 4 ++- tgt-vvp/eval_vec4.c | 20 +++++++---- tgt-vvp/vvp_scope.c | 14 +++++++- vvp/README.txt | 4 ++- vvp/arith.cc | 72 +++++++++++++++++++++++++++++++++++++++- vvp/arith.h | 20 ++++++++++- vvp/codes.h | 4 ++- vvp/compile.cc | 66 +++++++++++++++++++++++++++--------- vvp/compile.h | 6 +++- vvp/lexor.lex | 2 ++ vvp/opcodes.txt | 16 +++++++-- vvp/parse.y | 14 ++++++-- vvp/vthread.cc | 67 ++++++++++++++++++++++++++++++++++++- 28 files changed, 465 insertions(+), 51 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index d42f61485..590ec1e07 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -187,9 +187,15 @@ ostream& operator << (ostream&fd, NetCaseCmp::kind_t that) case NetCaseCmp::NEQ: fd << "!=="; break; - case NetCaseCmp::XEQ: + case NetCaseCmp::WEQ: fd << "==?"; break; + case NetCaseCmp::WNE: + fd << "!=?"; + break; + case NetCaseCmp::XEQ: + fd << "==x?"; + break; case NetCaseCmp::ZEQ: fd << "==z?"; break; @@ -1631,11 +1637,14 @@ void NetEBinary::dump(ostream&o) const case 'A': o << "~&"; break; + case 'e': + o << "=="; + break; case 'E': o << "==="; break; - case 'e': - o << "=="; + case 'w': + o << "==?"; break; case 'G': o << ">="; @@ -1652,6 +1661,9 @@ void NetEBinary::dump(ostream&o) const case 'N': o << "!=="; break; + case 'W': + o << "!=?"; + break; case 'o': o << "||"; break; diff --git a/elab_expr.cc b/elab_expr.cc index 019381481..6699823f6 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -329,10 +329,12 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode) case '>': // > Should be handled by PEBComp case 'e': // == Should be handled by PEBComp case 'E': // === Should be handled by PEBComp + case 'w': // ==? Should be handled by PEBComp case 'L': // <= Should be handled by PEBComp case 'G': // >= Should be handled by PEBComp case 'n': // != Should be handled by PEBComp case 'N': // !== Should be handled by PEBComp + case 'W': // !=? Should be handled by PEBComp case 'p': // ** should be handled by PEBPower ivl_assert(*this, 0); default: @@ -668,6 +670,18 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope, return 0; } break; + case 'w': /* ==? */ + case 'W': /* !=? */ + if ((lp->expr_type() != IVL_VT_BOOL && lp->expr_type() != IVL_VT_LOGIC) || + (rp->expr_type() != IVL_VT_BOOL && rp->expr_type() != IVL_VT_LOGIC)) { + cerr << get_fileline() << ": error: " + << human_readable_op(op_) + << " operator may only have INTEGRAL operands." + << endl; + des->errors += 1; + return 0; + } + break; default: break; } diff --git a/eval_tree.cc b/eval_tree.cc index 1da857035..7536bd56b 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -571,7 +571,8 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag, const NetExpr*le, const NetExpr*r verinum::V res = eq_res; - assert(lv.len() == rv.len()); + // The two expressions should already be padded to the same size. + ivl_assert(*this, lv.len() == rv.len()); for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) { @@ -626,7 +627,8 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr verinum::V res = verinum::V1; - assert(lv.len() == rv.len()); + // The two expressions should already be padded to the same size. + ivl_assert(*this, lv.len() == rv.len()); for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) if (lv.get(idx) != rv.get(idx)) { @@ -644,6 +646,55 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr return result; } +NetEConst* NetEBComp::eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const +{ + const NetEConst*lc = dynamic_cast(le); + const NetEConst*rc = dynamic_cast(re); + if (lc == 0 || rc == 0) return 0; + + const verinum&lv = lc->value(); + const verinum&rv = rc->value(); + + const verinum::V eq_res = ne_flag ? verinum::V0 : verinum::V1; + const verinum::V ne_res = ne_flag ? verinum::V1 : verinum::V0; + + verinum::V res = eq_res; + + // The two expressions should already be padded to the same size. + ivl_assert(*this, lv.len() == rv.len()); + + for (unsigned idx = 0 ; idx < lv.len() ; idx += 1) { + // An X or Z in the R-value matches any L-value. + switch (rv.get(idx)) { + case verinum::Vx: + case verinum::Vz: + continue; + default: + break; + } + + // An X or Z in the L-value that is not matches by an R-value X/Z returns undefined. + switch (lv.get(idx)) { + case verinum::Vx: + case verinum::Vz: + res = verinum::Vx; + continue; + default: + break; + } + + // A hard (0/1) mismatch gives a not-equal result. + if (rv.get(idx) != lv.get(idx)) { + res = ne_res; + break; + } + } + + NetEConst*result = new NetEConst(verinum(res, 1)); + ivl_assert(*this, result); + return result; +} + NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const { NetEConst*res = 0; @@ -657,6 +708,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const res = eval_eqeq_(false, l, r); break; + case 'w': // Wild equality (==?) + res = eval_weqeq_(false, l, r); + break; + case 'G': // >= res = eval_gteq_(l, r); break; @@ -673,6 +728,10 @@ NetEConst* NetEBComp::eval_arguments_(const NetExpr*l, const NetExpr*r) const res = eval_eqeq_(true, l, r); break; + case 'W': // Wild not-equal (!=?) + res = eval_weqeq_(true, l, r); + break; + case '<': // Less than res = eval_less_(l, r); break; diff --git a/expr_synth.cc b/expr_synth.cc index cb8ba87f0..6f8ca29b9 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -274,7 +274,18 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) if (op_ == 'E' || op_ == 'N') { NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(), - width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ); + width, op_=='E' ? NetCaseCmp::EEQ : NetCaseCmp::NEQ); + gate->set_line(*this); + connect(gate->pin(0), osig->pin(0)); + connect(gate->pin(1), lsig->pin(0)); + connect(gate->pin(2), rsig->pin(0)); + des->add_node(gate); + return osig; + } + + if (op_ == 'w' || op_ == 'W') { + NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(), + width, op_=='w' ? NetCaseCmp::WEQ : NetCaseCmp::WNE); gate->set_line(*this); connect(gate->pin(0), osig->pin(0)); connect(gate->pin(1), lsig->pin(0)); diff --git a/ivl_target.h b/ivl_target.h index 42dbe167b..f23c3fb58 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1,7 +1,7 @@ #ifndef IVL_ivl_target_H #define IVL_ivl_target_H /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -306,8 +306,10 @@ typedef enum ivl_lpm_type_e { IVL_LPM_CONCAT = 16, IVL_LPM_CONCATZ = 36, /* Transparent concat */ IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */ - IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */ + IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (casex) */ IVL_LPM_CMP_EQZ= 38, /* casez EQ */ + IVL_LPM_CMP_WEQ= 41, + IVL_LPM_CMP_WNE= 42, IVL_LPM_CMP_EQ = 10, IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GT = 2, diff --git a/lexor.lex b/lexor.lex index 50d8c6ab9..37c3e0207 100644 --- a/lexor.lex +++ b/lexor.lex @@ -188,6 +188,8 @@ TU [munpf] "!=" { return K_NE; } "===" { return K_CEQ; } "!==" { return K_CNE; } +"==?" { return K_WEQ; } +"!=?" { return K_WNE; } "||" { return K_LOR; } "&&" { return K_LAND; } "&&&" { return K_TAND; } diff --git a/netlist.h b/netlist.h index 09856c198..4ba553407 100644 --- a/netlist.h +++ b/netlist.h @@ -2365,6 +2365,8 @@ class NetCaseCmp : public NetNode { enum kind_t { EEQ, // === NEQ, // !== + WEQ, // ==? + WNE, // !=? XEQ, // casex guard tests ZEQ // casez guard tests }; @@ -4137,6 +4139,7 @@ class NetEBComp : public NetEBinary { NetEConst*eval_gt_(const NetExpr*le, const NetExpr*re) const; NetEConst*eval_gteq_(const NetExpr*le, const NetExpr*re) const; NetEConst*eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const; + NetEConst*eval_weqeq_(bool ne_flag, const NetExpr*le, const NetExpr*re) const; }; /* diff --git a/netmisc.cc b/netmisc.cc index 1adf66658..59da76061 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1260,6 +1260,8 @@ const char *human_readable_op(const char op, bool unary) if (unary) type = "~|"; // NOR else type = "!=="; // Case inequality break; + case 'w': type = "==?"; break; // Wild equality + case 'W': type = "!=?"; break; // Wild inequality case 'l': type = "<<(<)"; break; // Left shifts case 'r': type = ">>"; break; // Logical right shift diff --git a/parse.y b/parse.y index bf7847ec1..206b6fbb9 100644 --- a/parse.y +++ b/parse.y @@ -465,7 +465,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %token BASED_NUMBER DEC_NUMBER UNBASED_NUMBER %token REALTIME %token K_PLUS_EQ K_MINUS_EQ K_INCR K_DECR -%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LP K_LS K_RS K_RSS K_SG +%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE K_LP K_LS K_RS K_RSS K_SG /* K_CONTRIBUTE is <+, the contribution assign. */ %token K_CONTRIBUTE %token K_PO_POS K_PO_NEG K_POW @@ -678,7 +678,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %left '|' %left '^' K_NXOR K_NOR %left '&' K_NAND -%left K_EQ K_NE K_CEQ K_CNE +%left K_EQ K_NE K_CEQ K_CNE K_WEQ K_WNE %left K_GE K_LE '<' '>' %left K_LS K_RS K_RSS %left '+' '-' @@ -3284,6 +3284,11 @@ expression FILE_NAME(tmp, @2); $$ = tmp; } + | expression K_WEQ attribute_list_opt expression + { PEBinary*tmp = new PEBComp('w', $1, $4); + FILE_NAME(tmp, @2); + $$ = tmp; + } | expression K_LE attribute_list_opt expression { PEBinary*tmp = new PEBComp('L', $1, $4); FILE_NAME(tmp, @2); @@ -3304,6 +3309,11 @@ expression FILE_NAME(tmp, @2); $$ = tmp; } + | expression K_WNE attribute_list_opt expression + { PEBinary*tmp = new PEBComp('W', $1, $4); + FILE_NAME(tmp, @2); + $$ = tmp; + } | expression K_LOR attribute_list_opt expression { PEBinary*tmp = new PEBLogic('o', $1, $4); FILE_NAME(tmp, @2); diff --git a/t-dll-api.cc b/t-dll-api.cc index c07e18366..9c8283ab3 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1235,6 +1235,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: case IVL_LPM_MULT: @@ -1390,6 +1392,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net) case IVL_LPM_CMP_EQX: case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: case IVL_LPM_MULT: @@ -1540,6 +1544,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: case IVL_LPM_MULT: diff --git a/t-dll.cc b/t-dll.cc index 39f1f892c..29e874154 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1244,6 +1244,12 @@ void dll_target::net_case_cmp(const NetCaseCmp*net) case NetCaseCmp::NEQ: obj->type = IVL_LPM_CMP_NEE; break; + case NetCaseCmp::WEQ: + obj->type = IVL_LPM_CMP_WEQ; + break; + case NetCaseCmp::WNE: + obj->type = IVL_LPM_CMP_WNE; + break; case NetCaseCmp::XEQ: obj->type = IVL_LPM_CMP_EQX; break; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index ea71358be..15767349a 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -394,6 +394,12 @@ static void show_lpm_cmp_eeq(ivl_lpm_t net) case IVL_LPM_CMP_NEE: str = "NEE"; break; + case IVL_LPM_CMP_WEQ: + str = "WEQ"; + break; + case IVL_LPM_CMP_WNE: + str = "WNE"; + break; default: assert(0); break; @@ -1043,6 +1049,8 @@ static void show_lpm(ivl_lpm_t net) case IVL_LPM_CMP_EQX: case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: show_lpm_cmp_eeq(net); break; diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index f516a7a9e..b47f6f4d4 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -44,8 +44,10 @@ static expr_sign_t expr_get_binary_sign_type(ivl_expr_t expr) switch (ivl_expr_opcode(expr)) { case 'E': case 'e': + case 'w': case 'N': case 'n': + case 'W': case '<': case 'L': case '>': @@ -417,8 +419,10 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, case 'p': oper = "**"; break; case 'E': oper = "==="; break; case 'e': oper = "=="; break; + case 'w': oper = "==?"; break; case 'N': oper = "!=="; break; case 'n': oper = "!="; break; + case 'W': oper = "!=?"; break; case '<': oper = "<"; break; case 'L': oper = "<="; break; case '>': oper = ">"; break; @@ -465,6 +469,14 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, fprintf(vlog_out, " %s ", oper); emit_expr(scope, oper2, wid, 0, can_skip_unsigned, is_full_prec); break; + case 'w': + case 'W': + fprintf(stderr, "%s:%u: vlog95 error: The wild equality operators " + "cannot be converted.\n", + ivl_expr_file(expr), + ivl_expr_lineno(expr)); + vlog_errors += 1; + case 'E': case 'e': case 'N': diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 3754c82c9..024325090 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2016 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -398,6 +398,8 @@ static ivl_nexus_t get_lpm_output(ivl_scope_t scope, ivl_lpm_t lpm) case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: case IVL_LPM_CONCAT: case IVL_LPM_CONCATZ: case IVL_LPM_DIVIDE: @@ -1194,19 +1196,19 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm, fprintf(vlog_out, ")"); break; case IVL_LPM_CMP_EQX: -// HERE: Need to heck that this is not a real nexus. +// HERE: Need to check that this is not a real nexus. fprintf(vlog_out, "("); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0); fprintf(vlog_out, " ==? "); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0); fprintf(vlog_out, ")"); - fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal " + fprintf(stderr, "%s:%u: vlog95 error: Compare wildcard equal (caseX) " "operator is not supported.\n", ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); vlog_errors += 1; break; case IVL_LPM_CMP_EQZ: -// HERE: Need to heck that this is not a real nexus. +// HERE: Need to check that this is not a real nexus. fprintf(vlog_out, "("); emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0); fprintf(vlog_out, " == "); @@ -1245,6 +1247,28 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm, emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0); fprintf(vlog_out, ")"); break; + case IVL_LPM_CMP_WEQ: + fprintf(vlog_out, "("); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0); + fprintf(vlog_out, " ==? "); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0); + fprintf(vlog_out, ")"); + fprintf(stderr, "%s:%u: vlog95 error: Wild equality " + "operator is not supported.\n", + ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); + vlog_errors += 1; + break; + case IVL_LPM_CMP_WNE: + fprintf(vlog_out, "("); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 0), 0, 0); + fprintf(vlog_out, " !=? "); + emit_nexus_as_ca(scope, ivl_lpm_data(lpm, 1), 0, 0); + fprintf(vlog_out, ")"); + fprintf(stderr, "%s:%u: vlog95 error: Wild inequality " + "operator is not supported.\n", + ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); + vlog_errors += 1; + break; /* A concat-Z should never be generated, but report it as an * error if one is generated. */ case IVL_LPM_CONCATZ: diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index aa43b2203..86ec41657 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -398,6 +398,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) case IVL_LPM_CONCATZ: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: case IVL_LPM_CMP_EQX: case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: diff --git a/tgt-vvp/eval_real.c b/tgt-vvp/eval_real.c index a3c4d69c6..d7f1cfb4b 100644 --- a/tgt-vvp/eval_real.c +++ b/tgt-vvp/eval_real.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2017 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 @@ -57,6 +57,8 @@ static void draw_binary_real(ivl_expr_t expr) switch (ivl_expr_opcode(expr)) { case 'E': case 'N': + case 'w': + case 'W': case 'l': case 'r': case 'R': diff --git a/tgt-vvp/eval_vec4.c b/tgt-vvp/eval_vec4.c index 2afd1fbbc..c4516029e 100644 --- a/tgt-vvp/eval_vec4.c +++ b/tgt-vvp/eval_vec4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2013-2017 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 @@ -385,8 +385,7 @@ static void draw_binary_vec4_compare(ivl_expr_t expr) fprintf(vvp_out, " %%flag_get/vec4 4;\n"); break; case 'n': /* != */ - fprintf(vvp_out, " %%cmp/e;\n"); - fprintf(vvp_out, " %%flag_inv 4;\n"); + fprintf(vvp_out, " %%cmp/ne;\n"); fprintf(vvp_out, " %%flag_get/vec4 4;\n"); break; case 'E': /* === */ @@ -394,10 +393,17 @@ static void draw_binary_vec4_compare(ivl_expr_t expr) fprintf(vvp_out, " %%flag_get/vec4 6;\n"); break; case 'N': /* !== */ - fprintf(vvp_out, " %%cmp/e;\n"); - fprintf(vvp_out, " %%flag_inv 6;\n"); + fprintf(vvp_out, " %%cmp/ne;\n"); fprintf(vvp_out, " %%flag_get/vec4 6;\n"); break; + case 'w': /* ==? */ + fprintf(vvp_out, " %%cmp/we;\n"); + fprintf(vvp_out, " %%flag_get/vec4 4;\n"); + break; + case 'W': /* !=? */ + fprintf(vvp_out, " %%cmp/wne;\n"); + fprintf(vvp_out, " %%flag_get/vec4 4;\n"); + break; default: assert(0); } @@ -689,8 +695,10 @@ static void draw_binary_vec4(ivl_expr_t expr) case 'e': /* == */ case 'E': /* === */ - case 'n': /* !== */ + case 'n': /* != */ case 'N': /* !== */ + case 'w': /* ==? */ + case 'W': /* !=? */ draw_binary_vec4_compare(expr); break; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 6486d72cb..b272c36fa 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -1521,6 +1521,16 @@ static void draw_lpm_cmp(ivl_lpm_t net) type = "nee"; signed_string = ""; break; + case IVL_LPM_CMP_WEQ: + assert(dtc != IVL_VT_REAL); /* Should never get here! */ + type = "weq"; + signed_string = ""; + break; + case IVL_LPM_CMP_WNE: + assert(dtc != IVL_VT_REAL); /* Should never get here! */ + type = "wne"; + signed_string = ""; + break; default: assert(0); } @@ -2143,6 +2153,8 @@ static void draw_lpm_in_scope(ivl_lpm_t net) case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_NEE: + case IVL_LPM_CMP_WEQ: + case IVL_LPM_CMP_WNE: draw_lpm_cmp(net); return; diff --git a/vvp/README.txt b/vvp/README.txt index a6bfe2c01..dea23ae1a 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) * */ @@ -684,6 +684,8 @@ similar: