diff --git a/driver/iverilog.man b/driver/iverilog.man index 05245a5b9..a7a4f743e 100644 --- a/driver/iverilog.man +++ b/driver/iverilog.man @@ -66,6 +66,11 @@ other tools. .TP 8 .B -gverilog-ams\fI|-fP-gno-verilog-ams Enable or disable (default) support for Verilog-AMS. +Very little Verilog-AMS specific functionality is currently supported. +.TP 8 +.B -gsystem-verilog\fI|-fP-gno-system-verilog +Enable or disable (default) support for SystemVerilog. +Very little SystemVerilog specific functionality is currently supported. .TP 8 .B -gspecify\fI|\fP-gno-specify Enable or disable (default) specify block support. When enabled, diff --git a/driver/main.c b/driver/main.c index d53e3ab4c..b97decf7a 100644 --- a/driver/main.c +++ b/driver/main.c @@ -626,6 +626,9 @@ int process_generation(const char*name) else if (strcmp(name,"system-verilog") == 0) gen_system_verilog = "system-verilog"; + else if (strcmp(name,"no-system-verilog") == 0) + gen_verilog_ams = "no-system-verilog"; + else { fprintf(stderr, "Unknown/Unsupported Language generation " "%s\n\n", name); @@ -636,6 +639,7 @@ int process_generation(const char*name) "Other generation flags:\n" " specify | no-specify\n" " verilog-ams | no-verilog-ams\n" + " system-verilog | no-system-verilog\n" " std-include | no-std-include\n" " relative-include | no-relative-include\n" " xtypes | no-xtypes\n" diff --git a/elab_pexpr.cc b/elab_pexpr.cc index b7e243341..59849ee37 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -207,6 +207,14 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const name_component_t name_tail = path_.back(); oldpath.pop_back(); + if (path_.size() > 1) { + cerr << get_fileline() << ": error: parameter r-value expression " + "does not support hierarchical references `" << path_ + << "`." << endl; + des->errors += 1; + return 0; + } + NetScope*pscope = scope; if (path_.size() > 0) { list tmp = eval_scope_path(des, scope, oldpath); @@ -229,8 +237,9 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const ivl_assert(*this, pscope); } if (ex == 0) { - cerr << get_fileline() << ": error: identifier ``" << name_tail.name << - "'' is not a parameter in "<< scope_path(scope)<< "." << endl; + cerr << get_fileline() << ": error: identifier `" + << name_tail.name << "` is not a parameter in " + << scope_path(scope)<< "." << endl; des->errors += 1; return 0; } diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index a6e652c5e..875e40050 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1353,10 +1353,17 @@ static void do_expand(int use_args) struct include_stack_t*isp; int head = 0; int tail = 0; + const char *cp; + unsigned escapes = 0; + char *str_buf = 0; if (cur_macro->keyword) { fprintf(yyout, "%s", cur_macro->value); + if (do_expand_stringify_flag) { + do_expand_stringify_flag = 0; + fputc('"', yyout); + } return; } @@ -1385,6 +1392,43 @@ static void do_expand(int use_args) isp->ebs = 0; } + /* Escape some characters if we are making a string version. */ + for (cp = isp->str; (cp = strpbrk(cp, "\"\\")); cp += 1, escapes += 1); + if (escapes && isp->stringify_flag) { + unsigned idx = 0; + str_buf = (char *) malloc(strlen(isp->str)+3*escapes+1); + for (cp = isp->str; *cp; cp += 1) { + if (*cp == '"') { + str_buf[idx] = '\\'; + str_buf[idx+1] = '0'; + str_buf[idx+2] = '4'; + str_buf[idx+3] = '2'; + idx += 4; + continue; + } + if (*cp == '\\') { + str_buf[idx] = '\\'; + str_buf[idx+1] = '1'; + str_buf[idx+2] = '3'; + str_buf[idx+3] = '4'; + idx += 4; + continue; + } + str_buf[idx] = *cp; + idx += 1; + } + str_buf[idx] = 0; + idx += 1; + if (use_args) exp_buf_free += isp->ebs; + exp_buf_grow_to_fit(idx); + head = exp_buf_size - exp_buf_free; + exp_buf_free -= idx; + strcpy(&exp_buf[head], str_buf); + isp->str = &exp_buf[head]; + isp->ebs = idx; + free(str_buf); + } + isp->next = istack; istack->yybs = YY_CURRENT_BUFFER; istack = isp; @@ -1808,4 +1852,5 @@ void destroy_lexor() # endif # endif free(def_buf); + free(exp_buf); } diff --git a/netmisc.cc b/netmisc.cc index 4840ca0f2..183d9d47e 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -416,6 +416,7 @@ const char *human_readable_op(const char op, bool unary) case '-': type = "-"; break; case '*': type = "*"; break; case '/': type = "/"; break; + case '%': type = "%"; break; case '<': type = "<"; break; case '>': type = ">"; break; diff --git a/parse.y b/parse.y index 24ef79d2d..764d99ffc 100644 --- a/parse.y +++ b/parse.y @@ -80,6 +80,22 @@ static stack current_block_stack; const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL }; const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG }; +static list >* make_port_list(char*id, PExpr*expr) +{ + list >*tmp = new list >; + tmp->push_back(make_pair(lex_strings.make(id), expr)); + delete[]id; + return tmp; +} +static list >* make_port_list(list >*tmp, + char*id, PExpr*expr) +{ + tmp->push_back(make_pair(lex_strings.make(id), expr)); + delete[]id; + return tmp; +} + static list* list_from_identifier(char*id) { list*tmp = new list; @@ -146,6 +162,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) strdup. They can be put into lists with the texts type. */ char*text; list*perm_strings; + + list >*port_list; + pform_name_t*pform_name; ivl_discipline_t discipline; @@ -260,7 +279,9 @@ static PECallFunction*make_call_function(perm_string tn, PExpr*arg1, PExpr*arg2) %type udp_initial_expr_opt %type register_variable net_variable real_variable -%type register_variable_list net_variable_list real_variable_list list_of_identifiers +%type register_variable_list net_variable_list +%type real_variable_list list_of_identifiers +%type list_of_port_identifiers %type net_decl_assign net_decl_assigns @@ -1647,6 +1668,17 @@ list_of_identifiers { $$ = list_from_identifier($1, $3); } ; +list_of_port_identifiers + : IDENTIFIER + { $$ = make_port_list($1, 0); } + | IDENTIFIER '=' expression + { $$ = make_port_list($1, $3); } + | list_of_port_identifiers ',' IDENTIFIER + { $$ = make_port_list($1, $3, 0); } + | list_of_port_identifiers ',' IDENTIFIER '=' expression + { $$ = make_port_list($1, $3, $5); } + ; + /* The list_of_ports and list_of_port_declarations rules are the port list formats for module ports. The list_of_ports_opt rule is @@ -1991,9 +2023,20 @@ module_item SR_BOTH); } - | K_output var_type signed_opt range_opt list_of_identifiers ';' - { pform_makewire(@1, $4, $3, $5, $2, NetNet::POUTPUT, - IVL_VT_NO_TYPE, 0, SR_BOTH); + | K_output var_type signed_opt range_opt list_of_port_identifiers ';' + { list >::const_iterator pp; + list*tmp = new list; + for (pp = $5->begin(); pp != $5->end(); pp++) { + tmp->push_back((*pp).first); + } + pform_makewire(@1, $4, $3, tmp, $2, NetNet::POUTPUT, + IVL_VT_NO_TYPE, 0, SR_BOTH); + for (pp = $5->begin(); pp != $5->end(); pp++) { + if ((*pp).second) { + pform_make_reginit(@1, (*pp).first, (*pp).second); + } + } + delete $5; } /* var_type declaration (reg variables) cannot be input or output, diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 0773a4377..78202e521 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -696,16 +696,7 @@ static void real_value(vpiHandle ref, p_vpi_value vp) assert((ref->vpi_type->type_code == vpiConstant) || (ref->vpi_type->type_code == vpiParameter)); - switch (vp->format) { - case vpiObjTypeVal: - vp->format = vpiRealVal; - case vpiRealVal: - vp->value.real = rfp->value; - break; - default: - fprintf(stderr, "vvp error: unsupported format %d.\n", vp->format); - assert(0); - } + vpip_real_get_value(rfp->value, vp); } static const struct __vpirt vpip_real_rt = { diff --git a/vvp/vthread.cc b/vvp/vthread.cc index b11a2f034..438a1761c 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -984,7 +984,7 @@ bool of_ASSIGN_V0X1(vthread_t thr, vvp_code_t cp) if (off >= (long)sig->size()) return true; else if (off < 0 ) { // We fell off the LSB end. - if ((unsigned)-off > wid ) return true; + if ((unsigned)-off >= wid ) return true; // Trim the bits before the LSB wid += off; bit -= off; @@ -1021,7 +1021,7 @@ bool of_ASSIGN_V0X1D(vthread_t thr, vvp_code_t cp) if (off >= (long)sig->size()) return true; else if (off < 0 ) { // We fell off the LSB end. - if ((unsigned)-off > wid ) return true; + if ((unsigned)-off >= wid ) return true; // Trim the bits before the LSB wid += off; bit -= off; @@ -1060,7 +1060,7 @@ bool of_ASSIGN_V0X1E(vthread_t thr, vvp_code_t cp) return true; } else if (off < 0 ) { // We fell off the LSB end. - if ((unsigned)-off > wid ) { + if ((unsigned)-off >= wid ) { thr->event = 0; thr->ecount = 0; return true;