Merge pull request #613 from larsclausen/param-no-default

Support parameters without default value
This commit is contained in:
Stephen Williams 2022-02-13 15:40:00 -08:00 committed by GitHub
commit 3f048f266a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 142 additions and 10 deletions

View File

@ -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<perm_string,param_expr_t*>::const_iterator cur =
parameters.begin(); cur != parameters.end(); cur++) {
if (cur->second->expr == 0)
return false;
}
return true;
}

View File

@ -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<PGate*> gates_;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

13
parse.y
View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

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