Merge pull request #609 from larsclausen/sv-omit-param-keyword

Allow omitting `parameter` in module parameter port list
This commit is contained in:
Stephen Williams 2022-02-13 08:13:11 -08:00 committed by GitHub
commit 13aa782be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 186 additions and 89 deletions

View File

@ -0,0 +1,30 @@
// Check that all parameters in a parameter port list after a `localparam` get
// elaborated as localparams, until the next `parameter`. Check that this is the
// case even when the data type of the parameter is redefined.
module a #(
parameter A = 1, B = 2,
localparam C = 3, real D = 4,
parameter E = 5
);
initial begin
if (A == 10 && B == 20 && C == 3 && D == 4 && E == 50) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module b;
a #(
.A(10),
.B(20),
.D(40), // This will cause an error
.E(50)
) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the initial `parameter` keyword in a parameter
// port list in SystemVerilog. In Verilog this is not allowed and should result
// in an error.
module a #(A = 1);
initial begin
if (A == 10) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10)) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the initial `parameter` keyword in a parameter
// port list in SystemVerilog. In Verilog this is not allowed and should result
// in an error.
module a #(integer A = 1);
initial begin
if (A == 10) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10.1)) i_a();
endmodule

View File

@ -0,0 +1,17 @@
// Tests that it possible to omit the `parameter` keyword in a parameter port
// list before changing the parameter type in SystemVerilog. In Verilog this is
// not allowed and should result in an error.
module a #(parameter real A = 1.0, integer B = 2);
initial begin
if (A == 10.1 && B == 20) begin
$display("PASSED");
end else begin
$display("FAILED");
end
end
endmodule
module test;
a #(.A(10.1), .B(20)) i_a();
endmodule

View File

@ -0,0 +1,8 @@
// Check that implicit type in a parameter port list without `parameter`
// generates an error.
module test #([7:0] A = 1);
initial begin
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,8 @@
// Check that implicit type in a parameter port list without `parameter`
// generates an error.
module test #(signed A = 1);
initial begin
$display("FAILED");
end
endmodule

View File

@ -0,0 +1,8 @@
// Check that declaring changing the parameter type to an implicit type without
// the `parameter` keyword results in an error.
module test #(parameter real A = 1.0, signed B = 2);
initial begin
$display("FAILED");
end
endmodule

View File

@ -78,6 +78,9 @@ br_gh567 normal ivltests
check_constant_3 normal ivltests
function4 normal ivltests
parameter_in_generate1 normal ivltests
parameter_omit1 normal ivltests
parameter_omit2 normal ivltests
parameter_omit3 normal ivltests
pr1963962 normal ivltests gold=pr1963962-fsv.gold
pr3015421 CE ivltests gold=pr3015421-fsv.gold
resetall normal,-Wtimescale ivltests gold=resetall-fsv.gold

View File

@ -302,6 +302,7 @@ l_equiv_const normal,-g2005-sv ivltests
line_directive normal,-g2009,-I./ivltests ivltests gold=line_directive.gold
localparam_implicit normal,-g2005-sv ivltests
localparam_implicit2 CE,-g2005-sv ivltests
localparam_implicit3 CE,-g2005-sv ivltests
localparam_query normal,-g2005-sv ivltests
localparam_type2 normal,-g2009 ivltests
logical_short_circuit normal,-g2012 ivltests

View File

@ -696,6 +696,12 @@ 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_omit1 CE ivltests
parameter_omit2 CE ivltests
parameter_omit3 CE ivltests
parameter_omit_invalid1 CE ivltests
parameter_omit_invalid2 CE ivltests
parameter_omit_invalid3 CE ivltests
patch1268 normal ivltests
pca1 normal ivltests # Procedural Continuous Assignment in a mux
pic normal contrib pictest gold=pic.gold

135
parse.y
View File

@ -309,9 +309,8 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vector<Statement*
detected the case that there are no statements in the
task. If this is SystemVerilog, handle it as an
an empty block. */
if (!gn_system_verilog()) {
yyerror(loc, "error: Support for empty tasks requires SystemVerilog.");
}
pform_requires_sv(loc, "Task body with no statements");
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
current_task->set_statement(tmp);
@ -330,9 +329,7 @@ static void current_task_set_statement(const YYLTYPE&loc, std::vector<Statement*
return;
}
if (!gn_system_verilog()) {
yyerror(loc, "error: Task body with multiple statements requires SystemVerilog.");
}
pform_requires_sv(loc, "Task body with multiple statements");
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
@ -347,9 +344,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
detected the case that there are no statements in the
task. If this is SystemVerilog, handle it as an
an empty block. */
if (!gn_system_verilog()) {
yyerror(loc, "error: Support for empty functions requires SystemVerilog.");
}
pform_requires_sv(loc, "Function body with no statements");
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
current_function->set_statement(tmp);
@ -368,9 +364,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
return;
}
if (!gn_system_verilog()) {
yyerror(loc, "error: Function body with multiple statements requires SystemVerilog.");
}
pform_requires_sv(loc, "Function body with multiple statements");
PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, loc);
@ -659,7 +653,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <decl_assignment> variable_decl_assignment
%type <decl_assignments> list_of_variable_decl_assignments
%type <data_type> data_type data_type_or_implicit data_type_or_implicit_or_void
%type <data_type> data_type data_type_opt data_type_or_implicit data_type_or_implicit_or_void
%type <data_type> simple_type_or_string let_formal_type
%type <data_type> packed_array_data_type
%type <data_type> ps_type_identifier
@ -1269,6 +1263,11 @@ data_type /* IEEE1800-2005: A.2.2.1 */
}
;
/* Data type or nothing, but not implicit */
data_type_opt
: data_type { $$ = $1; }
| { $$ = 0; }
/* The data_type_or_implicit rule is a little more complex then the
rule documented in the IEEE format syntax in order to allow for
signaling the special case that the data_type is completely
@ -1285,7 +1284,7 @@ scalar_vector_opt /*IEEE1800-2005: optional support for packed array */
;
data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
: data_type
: data_type_opt
{ $$ = $1; }
| signing dimensions_opt
{ vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, $1, $2);
@ -1299,8 +1298,6 @@ data_type_or_implicit /* IEEE1800-2005: A.2.2.1 */
FILE_NAME(tmp, @2);
$$ = tmp;
}
|
{ $$ = 0; }
;
@ -1489,8 +1486,8 @@ function_declaration /* IEEE1800-2005: A.2.6 */
pform_set_this_class(@4, current_function);
pform_pop_scope();
current_function = 0;
if ($7==0 && !gn_system_verilog()) {
yyerror(@4, "error: Empty parenthesis syntax requires SystemVerilog.");
if ($7 == 0) {
pform_requires_sv(@4, "Empty parenthesis syntax");
}
}
label_opt
@ -2042,8 +2039,8 @@ port_direction /* IEEE1800-2005 A.1.3 */
| K_inout { $$ = NetNet::PINOUT; }
| K_ref
{ $$ = NetNet::PREF;
if (!gn_system_verilog()) {
yyerror(@1, "error: Reference ports (ref) require SystemVerilog.");
if (!pform_requires_sv(@1, "Reference port (ref)")) {
$$ = NetNet::PINPUT;
}
}
@ -2265,11 +2262,10 @@ stream_operator
streaming_concatenation /* IEEE1800-2005: A.8.1 */
: '{' stream_operator '{' stream_expression_list '}' '}'
{ /* streaming concatenation is a SystemVerilog thing. */
if (gn_system_verilog()) {
if (pform_requires_sv(@2, "Streaming concatenation")) {
yyerror(@2, "sorry: Streaming concatenation not supported.");
$$ = 0;
} else {
yyerror(@2, "error: Streaming concatenation requires SystemVerilog");
$$ = 0;
}
}
@ -2294,8 +2290,8 @@ task_declaration /* IEEE1800-2005: A.2.7 */
pform_set_this_class(@3, current_task);
pform_pop_scope();
current_task = 0;
if ($7 && $7->size() > 1 && !gn_system_verilog()) {
yyerror(@7, "error: Task body with multiple statements requires SystemVerilog.");
if ($7 && $7->size() > 1) {
pform_requires_sv(@7, "Task body with multiple statements");
}
delete $7;
}
@ -2452,10 +2448,8 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
}
if ($4 != 0) {
if (gn_system_verilog()) {
if (pform_requires_sv(@4, "Task/function port with unpacked dimensions")) {
pform_set_reg_idx(name, $4);
} else {
yyerror(@4, "error: Task/function port with unpacked dimensions requires SystemVerilog.");
}
}
@ -2479,10 +2473,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
tf_port_item_expr_opt
: '=' expression
{ if (! gn_system_verilog()) {
yyerror(@1, "error: Task/function default arguments require "
"SystemVerilog.");
}
{ pform_requires_sv(@$, "Task/function default argument");
$$ = $2;
}
| { $$ = 0; }
@ -2582,9 +2573,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
| '[' ']'
{ std::list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (0,0);
if (!gn_system_verilog()) {
yyerror("error: Dynamic array declaration require SystemVerilog.");
}
pform_requires_sv(@$, "Dynamic array declaration");
tmp->push_back(index);
$$ = tmp;
}
@ -2592,9 +2581,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
{ // SystemVerilog queue
list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (new PENull,0);
if (!gn_system_verilog()) {
yyerror("error: Queue declaration require SystemVerilog.");
}
pform_requires_sv(@$, "Queue declaration");
tmp->push_back(index);
$$ = tmp;
}
@ -2602,9 +2589,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
{ // SystemVerilog queue with a max size
list<pform_range_t> *tmp = new std::list<pform_range_t>;
pform_range_t index (new PENull,$4);
if (!gn_system_verilog()) {
yyerror("error: Queue declarations require SystemVerilog.");
}
pform_requires_sv(@$, "Queue declaration");
tmp->push_back(index);
$$ = tmp;
}
@ -2612,10 +2597,8 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
variable_lifetime
: lifetime
{ if (!gn_system_verilog()) {
yyerror(@1, "error: overriding the default variable lifetime "
"requires SystemVerilog.");
} else if ($1 != pform_peek_scope()->default_lifetime) {
{ if (pform_requires_sv(@1, "Overriding default variable lifetime") &&
$1 != pform_peek_scope()->default_lifetime) {
yyerror(@1, "sorry: overriding the default variable lifetime "
"is not yet supported.");
}
@ -3913,9 +3896,7 @@ expr_primary
FILE_NAME(tmp, @1);
delete[]$1;
$$ = tmp;
if (!gn_system_verilog()) {
yyerror(@1, "error: Empty function argument list requires SystemVerilog.");
}
pform_requires_sv(@1, "Empty function argument list");
}
| implicit_class_handle
@ -4158,24 +4139,22 @@ expr_primary
| expr_primary '\'' '(' expression ')'
{ PExpr*base = $4;
if (gn_system_verilog()) {
if (pform_requires_sv(@1, "Size cast")) {
PECastSize*tmp = new PECastSize($1, base);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
yyerror(@1, "error: Size cast requires SystemVerilog.");
$$ = base;
}
}
| simple_type_or_string '\'' '(' expression ')'
{ PExpr*base = $4;
if (gn_system_verilog()) {
if (pform_requires_sv(@1, "Type cast")) {
PECastType*tmp = new PECastType($1, base);
FILE_NAME(tmp, @1);
$$ = tmp;
} else {
yyerror(@1, "error: Type cast requires SystemVerilog.");
$$ = base;
}
}
@ -4409,12 +4388,9 @@ hierarchy_identifier
$$ = tmp;
}
| hierarchy_identifier '[' '$' ']'
{ pform_name_t * tmp = $1;
{ pform_requires_sv(@3, "Last element expression ($)");
pform_name_t * tmp = $1;
name_component_t&tail = tmp->back();
if (! gn_system_verilog()) {
yyerror(@3, "error: Last element expression ($) "
"requires SystemVerilog. Try enabling SystemVerilog.");
}
index_component_t itmp;
itmp.sel = index_component_t::SEL_BIT_LAST;
itmp.msb = 0;
@ -4585,9 +4561,7 @@ port_declaration
$$ = ptmp;
}
| attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression
{ if (!gn_system_verilog()) {
yyerror("error: Default port values require SystemVerilog.");
}
{ pform_requires_sv(@6, "Default port value");
Module::port_t*ptmp;
perm_string name = lex_strings.make($5);
data_type_t*use_type = $4;
@ -4935,17 +4909,29 @@ module_parameter_port_list_opt
module_parameter
: parameter param_type parameter_assign
| localparam param_type parameter_assign
{ if (!gn_system_verilog()) {
yyerror(@1, "error: Local parameters in module parameter "
"port lists requires SystemVerilog.");
}
}
{ pform_requires_sv(@1, "Local parameter in module parameter port list");
}
;
module_parameter_port_list
: module_parameter
| data_type_opt
{ param_data_type = $1;
param_is_local = false;
}
parameter_assign
{ pform_requires_sv(@3, "Omitting initial `parameter` in parameter port "
"list");
}
| module_parameter_port_list ',' module_parameter
| module_parameter_port_list ',' parameter_assign
| module_parameter_port_list ',' data_type_opt
{ if ($3) {
pform_requires_sv(@3, "Omitting `parameter`/`localparam` before "
"data type in parameter port list");
param_data_type = $3;
}
}
parameter_assign
;
module_item
@ -5379,10 +5365,7 @@ module_item
| K_function error K_endfunction label_opt
{ yyerror(@1, "error: I give up on this function definition.");
if ($4) {
if (!gn_system_verilog()) {
yyerror(@4, "error: Function end names require "
"SystemVerilog.");
}
pform_requires_sv(@4, "Function end label");
delete[]$4;
}
yyerrok;
@ -6514,10 +6497,7 @@ statement_item /* This is roughly statement_item in the LRM */
block_item_decls_opt
{ if (!$2) {
if ($4) {
if (! gn_system_verilog()) {
yyerror("error: Variable declaration in unnamed block "
"requires SystemVerilog.");
}
pform_requires_sv(@4, "Variable declaration in unnamed block");
} else {
/* If there are no declarations in the scope then just delete it. */
pform_pop_scope();
@ -6560,10 +6540,7 @@ statement_item /* This is roughly statement_item in the LRM */
{
if (!$2) {
if ($4) {
if (! gn_system_verilog()) {
yyerror("error: Variable declaration in unnamed block "
"requires SystemVerilog.");
}
pform_requires_sv(@4, "Variable declaration in unnamed block");
} else {
/* If there are no declarations in the scope then just delete it. */
pform_pop_scope();
@ -6847,9 +6824,7 @@ statement_item /* This is roughly statement_item in the LRM */
| hierarchy_identifier K_with '{' constraint_block_item_list_opt '}' ';'
{ /* ....randomize with { <constraints> } */
if ($1 && peek_tail_name(*$1) == "randomize") {
if (!gn_system_verilog())
yyerror(@2, "error: Randomize with constraint requires SystemVerilog.");
else
if (pform_requires_sv(@2, "Randomize with constraint"))
yyerror(@2, "sorry: Randomize with constraint not supported.");
} else {
yyerror(@2, "error: Constraint block can only be applied to randomize method.");

View File

@ -57,6 +57,7 @@ extern YYLTYPE yylloc;
*/
extern int VLlex();
extern void VLerror(const char*msg);
extern void VLerror(const YYLTYPE&loc, va_list ap);
extern void VLerror(const YYLTYPE&loc, const char*msg, ...) __attribute__((format(printf,2,3)));
#define yywarn VLwarn
extern void VLwarn(const char*msg);

View File

@ -1334,10 +1334,9 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1;
}
if (lifetime != LexicalScope::INHERITED && !gn_system_verilog()) {
cerr << loc << ": error: Default subroutine lifetimes "
"require SystemVerilog." << endl;
error_count += 1;
if (lifetime != LexicalScope::INHERITED) {
pform_requires_sv(loc, "Default subroutine lifetime");
}
if (gn_system_verilog() && ! pform_cur_module.empty()) {
@ -3138,11 +3137,7 @@ PAssign* pform_compressed_assign_from_inc_dec(const struct vlltype&loc, PExpr*ex
PExpr* pform_genvar_inc_dec(const struct vlltype&loc, const char*name, bool inc_flag)
{
if (!gn_system_verilog()) {
cerr << loc << ": error: Increment/decrement operators "
"require SystemVerilog." << endl;
error_count += 1;
}
pform_requires_sv(loc, "Increment/decrement operator");
PExpr*lval = new PEIdent(lex_strings.make(name));
PExpr*rval = new PENumber(new verinum(1));
@ -3760,6 +3755,15 @@ void pform_add_modport_port(const struct vlltype&loc,
pform_cur_modport->simple_ports[name] = make_pair(port_type, expr);
}
bool pform_requires_sv(const struct vlltype&loc, const char *feature)
{
if (gn_system_verilog())
return true;
VLerror(loc, "error: %s requires SystemVerilog.", feature);
return false;
}
FILE*vl_input = 0;
extern void reset_lexor();

View File

@ -612,4 +612,6 @@ extern bool allow_timeprec_decl;
void pform_put_enum_type_in_scope(enum_type_t*enum_set);
bool pform_requires_sv(const struct vlltype&loc, const char *feature);
#endif /* IVL_pform_H */