Merge pull request #764 from larsclausen/module-port-list-default

Support default port values in port declarations lists
This commit is contained in:
Stephen Williams 2022-09-14 09:25:33 -07:00 committed by GitHub
commit fa0217af87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 133 additions and 85 deletions

View File

@ -0,0 +1,22 @@
// Check that it is an error to specify a default value for inout port
// declarations.
module M (
inout [31:0] x, y = 1 // inout ports do not support default values
);
initial begin
$display("FAILED");
end
endmodule
module test;
wire [31:0] x, y;
M i_m (
.x(x),
.y(y)
);
endmodule

View File

@ -0,0 +1,31 @@
// Check that it is possible to specify a default port value for each port in a
// input port declaration list.
module M (
input [31:0] x = 1, y = 2
);
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d): %s, expected %0h got %0h", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end
reg failed = 1'b0;
initial begin
`check(x, 1)
`check(y, 2)
if (!failed) begin
$display("PASSED");
end
end
endmodule
module test;
M i_m ();
endmodule

View File

@ -0,0 +1,31 @@
// Check that it is possible to specify a default port value for each port in a
// output port declaration list.
module M (
output [31:0] x = 1, y = 2
);
`define check(val, exp) \
if (val !== exp) begin \
$display("FAILED(%0d): %s, expected %0h got %0h", `__LINE__, `"val`", exp, val); \
failed = 1'b1; \
end
reg failed = 1'b0;
initial begin
`check(x, 1)
`check(y, 2)
if (!failed) begin
$display("PASSED");
end
end
endmodule
module test;
M i_m ();
endmodule

View File

@ -78,6 +78,7 @@ br_gh567 normal ivltests
check_constant_3 normal ivltests
function4 normal ivltests
module_inout_port_type normal ivltests
module_input_port_list_def normal,-g2005-sv ivltests
module_input_port_type normal ivltests
parameter_in_generate1 normal ivltests
parameter_no_default normal ivltests

View File

@ -651,7 +651,9 @@ mixed_width_case normal ivltests
modparam normal ivltests top # Override parameter via passed down value
module3.12A normal ivltests main
module3.12B normal ivltests
module_inout_port_list_def CE ivltests # inout ports do not support default values
module_inout_port_type CE ivltests
module_input_port_list_def CE ivltests # input ports only support default values in SV
module_input_port_type CE ivltests
module_nonansi_integer1 normal ivltests
module_nonansi_integer2 normal ivltests
@ -659,6 +661,7 @@ module_nonansi_time1 normal ivltests
module_nonansi_time2 normal ivltests
module_nonansi_vec1 normal ivltests
module_nonansi_vec2 normal ivltests
module_output_port_list_def normal ivltests
module_output_port_var1 normal ivltests
module_output_port_var2 normal ivltests
module_port_range_mismatch CE ivltests

130
parse.y
View File

@ -602,7 +602,6 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <perm_strings> udp_port_list
%type <wires> udp_port_decl udp_port_decls
%type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt
%type <wire> net_variable
%type <wires> net_variable_list
@ -621,7 +620,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations module_attribute_foreign
%type <value_range> parameter_value_range parameter_value_ranges
%type <value_range> parameter_value_ranges_opt
%type <expr> tf_port_item_expr_opt value_range_expression
%type <expr> value_range_expression
%type <named_pexprs> enum_name_list enum_name
%type <data_type> enum_data_type enum_base_type
@ -648,8 +647,8 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector<Statem
%type <pform_name> hierarchy_identifier implicit_class_handle class_hierarchy_identifier
%type <expr> assignment_pattern expression expr_mintypmax
%type <expr> expr_primary_or_typename expr_primary
%type <expr> class_new dynamic_array_new let_default_opt
%type <expr> var_decl_initializer_opt
%type <expr> class_new dynamic_array_new
%type <expr> var_decl_initializer_opt initializer_opt
%type <expr> inc_or_dec_expression inside_expression lpvalue
%type <expr> branch_probe_expression streaming_concatenation
%type <expr> delay_value delay_value_simple
@ -1778,11 +1777,15 @@ list_of_variable_decl_assignments /* IEEE1800-2005 A.2.3 */
}
;
var_decl_initializer_opt
initializer_opt
: '=' expression { $$ = $2; }
| { $$ = nullptr; }
;
var_decl_initializer_opt
: initializer_opt
| '=' class_new { $$ = $2; }
| '=' dynamic_array_new { $$ = $2; }
| { $$ = 0; }
;
variable_decl_assignment /* IEEE1800-2005 A.2.3 */
@ -2342,7 +2345,7 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */
tf_port_item /* IEEE1800-2005: A.2.7 */
: port_direction_opt K_var_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt
: port_direction_opt K_var_opt data_type_or_implicit IDENTIFIER dimensions_opt initializer_opt
{ std::vector<pform_tf_port_t>*tmp;
NetNet::PortType use_port_type = $1;
if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($3 == 0)))
@ -2379,6 +2382,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
$$ = tmp;
if ($6) {
pform_requires_sv(@6, "Task/function default argument");
assert(tmp->size()==1);
tmp->front().defe = $6;
}
@ -2393,16 +2397,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
}
;
/* This rule matches the [ = <expression> ] part of the tf_port_item rules. */
tf_port_item_expr_opt
: '=' expression
{ pform_requires_sv(@$, "Task/function default argument");
$$ = $2;
}
| { $$ = 0; }
;
tf_port_list /* IEEE1800-2005: A.2.7 */
: { port_declaration_context.port_type = gn_system_verilog() ? NetNet::PINPUT : NetNet::PIMPLICIT;
port_declaration_context.data_type = 0;
@ -2572,21 +2566,13 @@ attribute_list
attribute
: IDENTIFIER
: IDENTIFIER initializer_opt
{ named_pexpr_t*tmp = new named_pexpr_t;
tmp->name = lex_strings.make($1);
tmp->parm = 0;
tmp->parm = $2;
delete[]$1;
$$ = tmp;
}
| IDENTIFIER '=' expression
{ PExpr*tmp = $3;
named_pexpr_t*tmp2 = new named_pexpr_t;
tmp2->name = lex_strings.make($1);
tmp2->parm = tmp;
delete[]$1;
$$ = tmp2;
}
;
@ -2786,42 +2772,22 @@ pos_neg_number
;
enum_name
: IDENTIFIER
: IDENTIFIER initializer_opt
{ perm_string name = lex_strings.make($1);
delete[]$1;
$$ = make_named_number(name);
$$ = make_named_number(name, $2);
}
| IDENTIFIER '[' pos_neg_number ']'
| IDENTIFIER '[' pos_neg_number ']' initializer_opt
{ perm_string name = lex_strings.make($1);
long count = check_enum_seq_value(@1, $3, false);
$$ = make_named_numbers(name, 0, count-1, $5);
delete[]$1;
$$ = make_named_numbers(name, 0, count-1);
delete $3;
}
| IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']'
| IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' initializer_opt
{ perm_string name = lex_strings.make($1);
$$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true),
check_enum_seq_value(@1, $5, true));
delete[]$1;
delete $3;
delete $5;
}
| IDENTIFIER '=' expression
{ perm_string name = lex_strings.make($1);
delete[]$1;
$$ = make_named_number(name, $3);
}
| IDENTIFIER '[' pos_neg_number ']' '=' expression
{ perm_string name = lex_strings.make($1);
long count = check_enum_seq_value(@1, $3, false);
$$ = make_named_numbers(name, 0, count-1, $6);
delete[]$1;
delete $3;
}
| IDENTIFIER '[' pos_neg_number ':' pos_neg_number ']' '=' expression
{ perm_string name = lex_strings.make($1);
$$ = make_named_numbers(name, check_enum_seq_value(@1, $3, true),
check_enum_seq_value(@1, $5, true), $8);
check_enum_seq_value(@1, $5, true), $7);
delete[]$1;
delete $3;
delete $5;
@ -4327,14 +4293,10 @@ list_of_port_identifiers
;
list_of_variable_port_identifiers
: IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $2, 0); }
| IDENTIFIER dimensions_opt '=' expression
{ $$ = make_port_list($1, $2, $4); }
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt
{ $$ = make_port_list($1, $3, $4, 0); }
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt '=' expression
{ $$ = make_port_list($1, $3, $4, $6); }
: IDENTIFIER dimensions_opt initializer_opt
{ $$ = make_port_list($1, $2, $3); }
| list_of_variable_port_identifiers ',' IDENTIFIER dimensions_opt initializer_opt
{ $$ = make_port_list($1, $3, $4, $5); }
;
@ -4380,13 +4342,29 @@ list_of_port_declarations
tmp->push_back($3);
$$ = tmp;
}
| list_of_port_declarations ',' IDENTIFIER
| list_of_port_declarations ',' IDENTIFIER initializer_opt
{ Module::port_t*ptmp;
perm_string name = lex_strings.make($3);
ptmp = pform_module_port_reference(@3, name);
std::vector<Module::port_t*>*tmp = $1;
tmp->push_back(ptmp);
if ($4) {
switch (port_declaration_context.port_type) {
case NetNet::PINOUT:
yyerror(@4, "error: Default port value not allowed for inout ports.");
break;
case NetNet::PINPUT:
pform_requires_sv(@4, "Default port value");
ptmp->default_value = $4;
break;
case NetNet::POUTPUT:
pform_make_var_init(@3, name, $4);
break;
default:
break;
}
}
/* Get the port declaration details, the port type
and what not, from context data stored by the
last port_declaration rule. */
@ -4534,7 +4512,7 @@ port_declaration
}
ptmp = pform_module_port_reference(@2, name);
pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $1);
port_declaration_context.port_type = NetNet::PINOUT;
port_declaration_context.port_type = NetNet::POUTPUT;
port_declaration_context.port_net_type = use_type;
port_declaration_context.data_type = $4;
@ -5260,19 +5238,12 @@ let_port_list
// FIXME: What about the attributes?
let_port_item
: attribute_list_opt let_formal_type IDENTIFIER dimensions_opt let_default_opt
: attribute_list_opt let_formal_type IDENTIFIER dimensions_opt initializer_opt
{ perm_string tmp3 = lex_strings.make($3);
$$ = pform_make_let_port($2, tmp3, $4, $5);
}
;
let_default_opt
: '=' expression
{ $$ = $2; }
|
{ $$ = 0; }
;
let_formal_type
: data_type_or_implicit
{ $$ = $1; }
@ -5446,15 +5417,9 @@ parameter_assign_list
;
parameter_assign
: IDENTIFIER parameter_value_ranges_opt
: IDENTIFIER initializer_opt 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);
param_data_type, $2, $3);
delete[]$1;
}
;
@ -6986,11 +6951,6 @@ udp_port_list
udp_reg_opt: K_reg { $$ = true; } | { $$ = false; };
udp_initial_expr_opt
: '=' expression { $$ = $2; }
| { $$ = 0; }
;
udp_input_declaration_list
: K_input IDENTIFIER
{ std::list<perm_string>*tmp = new std::list<perm_string>;
@ -7027,7 +6987,7 @@ udp_primitive
names and declarations are all in the parameter list. */
| K_primitive IDENTIFIER
'(' K_output udp_reg_opt IDENTIFIER udp_initial_expr_opt ','
'(' K_output udp_reg_opt IDENTIFIER initializer_opt ','
udp_input_declaration_list ')' ';'
udp_body
K_endprimitive label_opt