diff --git a/Module.cc b/Module.cc index 923f5b1db..75e1c0f8d 100644 --- a/Module.cc +++ b/Module.cc @@ -139,3 +139,19 @@ PNamedItem::SymbolType Module::symbol_type() const return MODULE; } + +bool Module::can_be_toplevel() const +{ + // Don't choose library modules. + if (library_flag) + return false; + + // Don't choose modules with parameters without default value + for (std::map::const_iterator cur = + parameters.begin(); cur != parameters.end(); cur++) { + if (cur->second->expr == 0) + return false; + } + + return true; +} diff --git a/Module.h b/Module.h index 3abcff0d1..3630d4b1c 100644 --- a/Module.h +++ b/Module.h @@ -166,6 +166,8 @@ class Module : public PScopeExtra, public PNamedItem { SymbolType symbol_type() const; + bool can_be_toplevel() const; + private: void dump_specparams_(std::ostream&out, unsigned indent) const; std::list gates_; diff --git a/ivtest/ivltests/parameter_no_default.v b/ivtest/ivltests/parameter_no_default.v new file mode 100644 index 000000000..88e4dbb1a --- /dev/null +++ b/ivtest/ivltests/parameter_no_default.v @@ -0,0 +1,20 @@ +// SystemVerilog allows parameters without default values in the parameter port +// list. Check that this is supported. The test should fail in Verilog mode. + +module a #( + parameter A +); + +initial begin + if (A == 1) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end +end + +endmodule + +module test; + a #(.A(1)) i_a(); +endmodule diff --git a/ivtest/ivltests/parameter_no_default_fail1.v b/ivtest/ivltests/parameter_no_default_fail1.v new file mode 100644 index 000000000..975c510cc --- /dev/null +++ b/ivtest/ivltests/parameter_no_default_fail1.v @@ -0,0 +1,16 @@ +// Check that not providing a value during module instantiation for a parameter +// without a default value generates an error. + +module a #( + parameter A +); + +initial begin + $display("FAILED"); +end + +endmodule + +module test; + a i_a(); +endmodule diff --git a/ivtest/ivltests/parameter_no_default_fail2.v b/ivtest/ivltests/parameter_no_default_fail2.v new file mode 100644 index 000000000..8bb164045 --- /dev/null +++ b/ivtest/ivltests/parameter_no_default_fail2.v @@ -0,0 +1,16 @@ +// Check that parameters without default values outside the parameter port list +// generate an error. + +module a; + +parameter A; + +initial begin + $display("FAILED"); +end + +endmodule + +module test; + a #(.A(10)) i_a(); +endmodule diff --git a/ivtest/ivltests/parameter_no_default_toplvl.v b/ivtest/ivltests/parameter_no_default_toplvl.v new file mode 100644 index 000000000..417d97094 --- /dev/null +++ b/ivtest/ivltests/parameter_no_default_toplvl.v @@ -0,0 +1,14 @@ +// Check that modules with undefined parameters do not get picked as top-level +// modules. + +module a #( + parameter A +); + initial $display("FAILED"); +endmodule + +module b #( + parameter B = 1 +); + initial $display("PASSED"); +endmodule diff --git a/ivtest/regress-fsv.list b/ivtest/regress-fsv.list index a25e451c6..2b847a618 100644 --- a/ivtest/regress-fsv.list +++ b/ivtest/regress-fsv.list @@ -78,6 +78,7 @@ br_gh567 normal ivltests check_constant_3 normal ivltests function4 normal ivltests parameter_in_generate1 normal ivltests +parameter_no_default normal ivltests parameter_omit1 normal ivltests parameter_omit2 normal ivltests parameter_omit3 normal ivltests diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 4f4a5d78c..945873c52 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -317,6 +317,10 @@ packeda normal,-g2009 ivltests packeda2 normal,-g2009 ivltests parameter_in_generate2 CE,-g2005-sv ivltests parameter_invalid_override CE,-g2005-sv ivltests gold=parameter_invalid_override.gold +parameter_no_default CE,-g2005-sv ivltests +parameter_no_default_fail1 CE ivltests +parameter_no_default_fail2 CE ivltests +parameter_no_default_toplvl normal,-g2005-sv ivltests parameter_type2 normal,-g2009 ivltests parpkg_test normal,-g2009 ivltests parpkg_test2 normal,-g2009 ivltests diff --git a/ivtest/regress-vlg.list b/ivtest/regress-vlg.list index d8352af04..127c60b07 100644 --- a/ivtest/regress-vlg.list +++ b/ivtest/regress-vlg.list @@ -696,6 +696,7 @@ param_test4 normal ivltests param_times normal ivltests # param has multiplication. parameter_type normal ivltests gold=parameter_type.gold parameter_in_generate1 CE ivltests +parameter_no_default CE ivltests parameter_omit1 CE ivltests parameter_omit2 CE ivltests parameter_omit3 CE ivltests diff --git a/main.cc b/main.cc index ecedbb414..0c20b15cc 100644 --- a/main.cc +++ b/main.cc @@ -1187,8 +1187,7 @@ int main(int argc, char*argv[]) for (mod = pform_modules.begin() ; mod != pform_modules.end() ; ++ mod ) { - /* Don't choose library modules. */ - if ((*mod).second->library_flag) + if (!(*mod).second->can_be_toplevel()) continue; /* Don't choose modules instantiated in other diff --git a/net_design.cc b/net_design.cc index 12c8b14c6..8112f2039 100644 --- a/net_design.cc +++ b/net_design.cc @@ -827,9 +827,19 @@ void NetScope::evaluate_parameter_(Design*des, param_ref_t cur) } // If the parameter has already been evaluated, quietly return. - if (cur->second.val_expr == 0) + if (cur->second.val != 0) return; + if (cur->second.val_expr == 0) { + cerr << this->get_fileline() << ": error: " + << "Missing value for parameter `" + << cur->first << "`." << endl; + des->errors += 1; + + cur->second.val = new NetEConst(verinum(verinum::Vx)); + return; + } + // Guess the varaiable type of the parameter. If the parameter has no // given type, then guess the type from the expression and use that to // evaluate. diff --git a/parse.y b/parse.y index 9b98ca4f6..0129b515e 100644 --- a/parse.y +++ b/parse.y @@ -4901,7 +4901,11 @@ module_port_list_opt that the port declarations may use them. */ module_parameter_port_list_opt : - | '#' '(' module_parameter_port_list ')' + | '#' '(' + { pform_start_parameter_port_list(); } + module_parameter_port_list + { pform_end_parameter_port_list(); } + ')' ; module_parameter @@ -5580,7 +5584,12 @@ parameter_assign_list ; parameter_assign - : IDENTIFIER '=' expression parameter_value_ranges_opt + : IDENTIFIER parameter_value_ranges_opt + { pform_set_parameter(@1, lex_strings.make($1), param_is_local, + param_data_type, 0, $2); + delete[]$1; + } + | IDENTIFIER '=' expression parameter_value_ranges_opt { PExpr*tmp = $3; pform_set_parameter(@1, lex_strings.make($1), param_is_local, param_data_type, tmp, $4); diff --git a/pform.cc b/pform.cc index 4ab111ea0..dd171773c 100644 --- a/pform.cc +++ b/pform.cc @@ -386,6 +386,9 @@ static unsigned pform_timescale_line; bool allow_timeunit_decl = true; bool allow_timeprec_decl = true; +// Track whether the current parameter declaration is in a parameter port list +static bool pform_in_parameter_port_list = false; + static inline void FILE_NAME(LineInfo*obj, const char*file, unsigned lineno) { obj->set_lineno(lineno); @@ -1378,6 +1381,16 @@ void pform_startmodule(const struct vlltype&loc, const char*name, pform_bind_attributes(cur_module->attributes, attr); } +void pform_start_parameter_port_list() +{ + pform_in_parameter_port_list = true; +} + +void pform_end_parameter_port_list() +{ + pform_in_parameter_port_list = false; +} + /* * This function is called by the parser to make a simple port * reference. This is a name without a .X(...), so the internal name @@ -3228,6 +3241,17 @@ void pform_set_parameter(const struct vlltype&loc, return; } + if (expr == 0) { + if (is_local) { + VLerror(loc, "error: localparam must have a value."); + } else if (!pform_in_parameter_port_list) { + VLerror(loc, "error: parameter declared outside parameter " + "port list must have a default value."); + } else { + pform_requires_sv(loc, "parameter without default value"); + } + } + bool overridable = !is_local; if (scope == pform_cur_generate && !is_local) { @@ -3240,7 +3264,6 @@ void pform_set_parameter(const struct vlltype&loc, overridable = false; } - assert(expr); Module::param_expr_t*parm = new Module::param_expr_t(); FILE_NAME(parm, loc); diff --git a/pform.h b/pform.h index b1b5e7a1d..52199eaad 100644 --- a/pform.h +++ b/pform.h @@ -614,4 +614,7 @@ void pform_put_enum_type_in_scope(enum_type_t*enum_set); bool pform_requires_sv(const struct vlltype&loc, const char *feature); +void pform_start_parameter_port_list(); +void pform_end_parameter_port_list(); + #endif /* IVL_pform_H */ diff --git a/pform_dump.cc b/pform_dump.cc index 2aa8c8ecc..9367ce0d3 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1485,11 +1485,9 @@ void LexicalScope::dump_parameters_(ostream&out, unsigned indent) const cur->second->data_type->debug_dump(out); else out << "(nil type)"; - out << " " << (*cur).first << " = "; if ((*cur).second->expr) - out << *(*cur).second->expr; - else - out << "/* ERROR */"; + out << " " << (*cur).first << " = " + << *(*cur).second->expr; for (LexicalScope::range_t*tmp = (*cur).second->range ; tmp ; tmp = tmp->next) { if (tmp->exclude_flag)