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/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)