From 246a0d3ce8dd97dd29fe75052e87c74f7a338083 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 22 May 2022 16:38:42 +0200 Subject: [PATCH 1/5] Allow inputs to be variables in SystemVerilog SystemVerilog allows input ports to be variables. If something is connected to the input port it will be converted to an unresolved wire. This is handled the same as having a continuous assignment on a SystemVerilog varibale. Signed-off-by: Lars-Peter Clausen --- elab_sig.cc | 6 ++++-- elaborate.cc | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index 9f762c5ad..6f778f669 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -144,10 +144,12 @@ static void sig_check_port_type(Design*des, NetScope*scope, return; /* If the signal is an input and is also declared as a - reg, then report an error. */ + reg, then report an error. In SystemVerilog a input + is allowed to be a register. It will get converted + to a unresolved wire when the port is connected. */ if (sig->port_type() == NetNet::PINPUT && - sig->type() == NetNet::REG) { + sig->type() == NetNet::REG && !gn_var_can_be_uwire()) { cerr << wire->get_fileline() << ": error: Port `" << wire->basename() << "` of module `" << scope->module_name() diff --git a/elaborate.cc b/elaborate.cc index 6357d6f14..6a38d8b16 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1533,6 +1533,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const delete tmp_expr; if (!sig->get_lineno()) sig->set_line(*this); + if (ptype == NetNet::PINPUT && gn_var_can_be_uwire()) { + for (unsigned int i = 0; i < prts.size(); i++) { + if (prts[i]->type() == NetNet::REG) + prts[i]->type(NetNet::UNRESOLVED_WIRE); + } + } + if (need_bufz_for_input_port(prts)) { NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(), sig->vector_width(), true); From 8b0346d7b5ca492ac4ab8712cd3caae5c631ef30 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 9 Mar 2022 10:11:50 +0100 Subject: [PATCH 2/5] Recover from parser errors in all variable declarations Currently the parser can recover from `integer` or `time` variable declarations, but not for variables of other types. Refector the parser rules so that it can recover for all variable types as well as events. Signed-off-by: Lars-Peter Clausen --- parse.y | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/parse.y b/parse.y index f56ebbb27..539bec1b5 100644 --- a/parse.y +++ b/parse.y @@ -2628,13 +2628,12 @@ block_item_decl /* Recover from errors that happen within variable lists. Use the trailing semi-colon to resync the parser. */ - | K_integer error ';' - { yyerror(@1, "error: syntax error in integer variable list."); + | data_type error ';' + { yyerror(@1, "error: syntax error in variable list."); yyerrok; } - - | K_time error ';' - { yyerror(@1, "error: syntax error in time variable list."); + | K_event error ';' + { yyerror(@1, "error: syntax error in event variable list."); yyerrok; } From 134e7d6f08b340f99862af2c43747ca047d0bf7f Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 9 Mar 2022 10:15:27 +0100 Subject: [PATCH 3/5] Refactor variable lifetime parser rules Refactor the variable lifetime parser rules so that instead of having too rules, one with lifetime and one without, there is a single rule where the lifetime is an optional element. This helps to avoid a combinatorial explosion of parser rules once we add `var` support. Signed-off-by: Lars-Peter Clausen --- parse.y | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/parse.y b/parse.y index 539bec1b5..add5f89fc 100644 --- a/parse.y +++ b/parse.y @@ -2511,7 +2511,7 @@ variable_dimension /* IEEE1800-2005: A.2.5 */ } ; -variable_lifetime +variable_lifetime_opt : lifetime { if (pform_requires_sv(@1, "Overriding default variable lifetime") && $1 != pform_peek_scope()->default_lifetime) { @@ -2520,6 +2520,7 @@ variable_lifetime } var_lifetime = $1; } + | ; /* Verilog-2001 supports attribute lists, which can be attached to a @@ -2592,21 +2593,13 @@ block_item_decl /* variable declarations. Note that data_type can be 0 if we are recovering from an error. */ - : data_type list_of_variable_decl_assignments ';' - { if ($1) pform_make_var(@1, $2, $1, attributes_in_context); - } - - | variable_lifetime data_type list_of_variable_decl_assignments ';' + : variable_lifetime_opt data_type list_of_variable_decl_assignments ';' { if ($2) pform_make_var(@2, $3, $2, attributes_in_context); var_lifetime = LexicalScope::INHERITED; } /* The extra `reg` is not valid (System)Verilog, this is a iverilog extension. */ - | K_reg data_type list_of_variable_decl_assignments ';' - { if ($2) pform_make_var(@2, $3, $2, attributes_in_context); - } - - | variable_lifetime K_reg data_type list_of_variable_decl_assignments ';' + | variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';' { if ($3) pform_make_var(@3, $4, $3, attributes_in_context); var_lifetime = LexicalScope::INHERITED; } @@ -2628,7 +2621,7 @@ block_item_decl /* Recover from errors that happen within variable lists. Use the trailing semi-colon to resync the parser. */ - | data_type error ';' + | variable_lifetime_opt data_type error ';' { yyerror(@1, "error: syntax error in variable list."); yyerrok; } From d753e6a5d0167e0c020dc43e29118b2be3ab3e3c Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Wed, 5 Jan 2022 10:35:37 +0100 Subject: [PATCH 4/5] Add SystemVerilog `var` keyword support SystemVerilog adds the `var` keyword that can be used to declare a signal as a variable. In contexts where a signal is always a variable it is purely optional and it makes no difference whether it is specified or not. This is in * for loop variable declarations * task and function port declarations For variable declarations as block items when `var` is used it is possible to omit the explicit data type and use a implicit data type instead. E.g. all of the following are valid. ``` var x; var signed y; var [1:0] z; ``` For module input and output ports the `var` keyword can be used in place of the net type. It can be combined with either an implicit or explicit data type. E.g. ``` input var x output var [1:0] y ``` inout ports can not be variables and will be reported as an error. Signed-off-by: Lars-Peter Clausen --- parse.y | 112 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 41 deletions(-) diff --git a/parse.y b/parse.y index add5f89fc..1295aaa94 100644 --- a/parse.y +++ b/parse.y @@ -682,7 +682,7 @@ static void current_function_set_statement(const YYLTYPE&loc, std::vector variable_dimension %type dimensions_opt dimensions -%type net_type net_type_opt +%type net_type net_type_opt net_type_or_var net_type_or_var_opt %type gatetype switchtype %type port_direction port_direction_opt %type integer_vector_type @@ -1173,6 +1173,14 @@ data_declaration /* IEEE1800-2005: A.2.1.3 */ } pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type, $1); } + | attribute_list_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';' + { data_type_t*data_type = $3; + if (data_type == 0) { + data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); + FILE_NAME(data_type, @2); + } + pform_make_var(@2, $4, data_type, $1); + } | attribute_list_opt K_event event_variable_list ';' { if ($3) pform_make_events(@2, $3); } @@ -1638,7 +1646,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ // statement in a synthetic named block. We can name the block // after the variable that we are creating, that identifier is // safe in the controlling scope. - | K_for '(' data_type IDENTIFIER '=' expression ';' expression ';' for_step ')' + | K_for '(' K_var_opt data_type IDENTIFIER '=' expression ';' expression ';' for_step ')' { static unsigned for_counter = 0; char for_block_name [64]; snprintf(for_block_name, sizeof for_block_name, "$ivl_for_loop%u", for_counter); @@ -1648,18 +1656,18 @@ loop_statement /* IEEE1800-2005: A.6.8 */ listassign_list; decl_assignment_t*tmp_assign = new decl_assignment_t; - tmp_assign->name = lex_strings.make($4); + tmp_assign->name = lex_strings.make($5); assign_list.push_back(tmp_assign); - pform_make_var(@4, &assign_list, $3); + pform_make_var(@5, &assign_list, $4); } statement_or_null { pform_name_t tmp_hident; - tmp_hident.push_back(name_component_t(lex_strings.make($4))); + tmp_hident.push_back(name_component_t(lex_strings.make($5))); - PEIdent*tmp_ident = pform_new_ident(@4, tmp_hident); - FILE_NAME(tmp_ident, @4); + PEIdent*tmp_ident = pform_new_ident(@5, tmp_hident); + FILE_NAME(tmp_ident, @5); - PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13); + PForStatement*tmp_for = new PForStatement(tmp_ident, $7, $9, $11, $14); FILE_NAME(tmp_for, @1); pform_pop_scope(); @@ -1669,7 +1677,7 @@ loop_statement /* IEEE1800-2005: A.6.8 */ current_block_stack.pop(); tmp_blk->set_statement(tmp_for_list); $$ = tmp_blk; - delete[]$4; + delete[]$5; } | K_forever statement_or_null @@ -2318,8 +2326,8 @@ task_declaration /* IEEE1800-2005: A.2.7 */ tf_port_declaration /* IEEE1800-2005: A.2.7 */ - : port_direction data_type_or_implicit list_of_port_identifiers ';' - { $$ = pform_make_task_ports(@1, $1, $2, $3, true); + : port_direction K_var_opt data_type_or_implicit list_of_port_identifiers ';' + { $$ = pform_make_task_ports(@1, $1, $3, $4, true); } ; @@ -2334,25 +2342,25 @@ tf_port_declaration /* IEEE1800-2005: A.2.7 */ tf_port_item /* IEEE1800-2005: A.2.7 */ - : port_direction_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 tf_port_item_expr_opt { std::vector*tmp; NetNet::PortType use_port_type = $1; - if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0))) + if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($3 == 0))) use_port_type = port_declaration_context.port_type; - list* port_list = make_port_list($3, $4, 0); + list* port_list = make_port_list($4, $5, 0); if (use_port_type == NetNet::PIMPLICIT) { yyerror(@1, "error: missing task/function port direction."); use_port_type = NetNet::PINPUT; // for error recovery } - if (($2 == 0) && ($1==NetNet::PIMPLICIT)) { + if (($3 == 0) && ($1==NetNet::PIMPLICIT)) { // Detect special case this is an undecorated // identifier and we need to get the declaration from // left context. - if ($4 != 0) { - yyerror(@4, "internal error: How can there be an unpacked range here?\n"); + if ($5 != 0) { + yyerror(@5, "internal error: How can there be an unpacked range here?\n"); } - tmp = pform_make_task_ports(@3, use_port_type, + tmp = pform_make_task_ports(@4, use_port_type, port_declaration_context.data_type, port_list); @@ -2361,25 +2369,25 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ // indicate the type. Save the type for any right // context that may come later. port_declaration_context.port_type = use_port_type; - if ($2 == 0) { - $2 = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME($2, @3); + if ($3 == 0) { + $3 = new vector_type_t(IVL_VT_LOGIC, false, 0); + FILE_NAME($3, @4); } - port_declaration_context.data_type = $2; - tmp = pform_make_task_ports(@3, use_port_type, $2, port_list); + port_declaration_context.data_type = $3; + tmp = pform_make_task_ports(@3, use_port_type, $3, port_list); } $$ = tmp; - if ($5) { + if ($6) { assert(tmp->size()==1); - tmp->front().defe = $5; + tmp->front().defe = $6; } } /* Rules to match error cases... */ - | port_direction_opt data_type_or_implicit IDENTIFIER error - { yyerror(@3, "error: Error in task/function port item after port name %s.", $3); + | port_direction_opt K_var_opt data_type_or_implicit IDENTIFIER error + { yyerror(@3, "error: Error in task/function port item after port name %s.", $4); yyerrok; $$ = 0; } @@ -2593,7 +2601,17 @@ block_item_decl /* variable declarations. Note that data_type can be 0 if we are recovering from an error. */ - : variable_lifetime_opt data_type list_of_variable_decl_assignments ';' + : K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';' + { data_type_t*data_type = $3; + if (data_type == 0) { + data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); + FILE_NAME(data_type, @1); + } + pform_make_var(@1, $4, data_type, attributes_in_context); + var_lifetime = LexicalScope::INHERITED; + } + + | variable_lifetime_opt data_type list_of_variable_decl_assignments ';' { if ($2) pform_make_var(@2, $3, $2, attributes_in_context); var_lifetime = LexicalScope::INHERITED; } @@ -2621,6 +2639,10 @@ block_item_decl /* Recover from errors that happen within variable lists. Use the trailing semi-colon to resync the parser. */ + | K_var variable_lifetime_opt data_type_or_implicit error ';' + { yyerror(@1, "error: syntax error in variable list."); + yyerrok; + } | variable_lifetime_opt data_type error ';' { yyerror(@1, "error: syntax error in variable list."); yyerrok; @@ -4377,7 +4399,7 @@ list_of_port_declarations ; port_declaration - : attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt + : attribute_list_opt K_input net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt { Module::port_t*ptmp; perm_string name = lex_strings.make($5); data_type_t*use_type = $4; @@ -4405,7 +4427,7 @@ port_declaration delete[]$4; $$ = ptmp; } - | attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER '=' expression + | attribute_list_opt K_input net_type_or_var_opt data_type_or_implicit IDENTIFIER '=' expression { pform_requires_sv(@6, "Default port value"); Module::port_t*ptmp; perm_string name = lex_strings.make($5); @@ -4449,7 +4471,7 @@ port_declaration delete[]$4; $$ = ptmp; } - | attribute_list_opt K_output net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt + | attribute_list_opt K_output net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt { Module::port_t*ptmp; perm_string name = lex_strings.make($5); data_type_t*use_dtype = $4; @@ -4493,7 +4515,7 @@ port_declaration delete[]$4; $$ = ptmp; } - | attribute_list_opt K_output net_type_opt data_type_or_implicit IDENTIFIER '=' expression + | attribute_list_opt K_output net_type_or_var_opt data_type_or_implicit IDENTIFIER '=' expression { Module::port_t*ptmp; perm_string name = lex_strings.make($5); NetNet::Type use_type = $3; @@ -4513,13 +4535,6 @@ port_declaration } ; - - -net_type_opt - : net_type { $$ = $1; } - | { $$ = NetNet::IMPLICIT; } - ; - /* * The signed_opt rule will return "true" if K_signed is present, * for "false" otherwise. This rule corresponds to the declaration @@ -4856,7 +4871,7 @@ module_item input wire signed [h:l] ; This creates the wire and sets the port type all at once. */ - | attribute_list_opt port_direction net_type data_type_or_implicit list_of_port_identifiers ';' + | attribute_list_opt port_direction net_type_or_var data_type_or_implicit list_of_port_identifiers ';' { pform_module_define_port(@2, $5, $2, $3, $4, $1); } | attribute_list_opt port_direction K_wreal list_of_port_identifiers ';' @@ -4915,7 +4930,7 @@ module_item pform_module_define_port(@2, $4, NetNet::POUTPUT, use_type, $3, $1); } - | attribute_list_opt port_direction net_type data_type_or_implicit error ';' + | attribute_list_opt port_direction net_type_or_var data_type_or_implicit error ';' { yyerror(@2, "error: Invalid variable list in port declaration."); if ($1) delete $1; if ($4) delete $4; @@ -5378,6 +5393,20 @@ net_type | K_uwire { $$ = NetNet::UNRESOLVED_WIRE; } ; +net_type_opt + : net_type { $$ = $1; } + | { $$ = NetNet::IMPLICIT; } + ; + +net_type_or_var + : net_type { $$ = $1; } + | K_var { $$ = NetNet::REG; } + +net_type_or_var_opt + : net_type_opt { $$ = $1; } + | K_var { $$ = NetNet::REG; } + ; + /* The param_type rule is just the data_type_or_implicit rule wrapped with an assignment to para_data_type with the figured data type. This is used by parameter_assign, which is found to the right of @@ -7016,3 +7045,4 @@ unique_priority K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } ; K_static_opt : K_static { $$ = true; } | { $$ = false; } ; K_virtual_opt : K_virtual { $$ = true; } | { $$ = false; } ; +K_var_opt : K_var | ; From 9ffe627b32970f4f3ec5929fe3a5a0c948763578 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 10 Sep 2022 16:31:37 +0200 Subject: [PATCH 5/5] Add regression tests for `var` keyword Check that the var keyword is supported in the following contexts * Module ports (both ANSI and non-ANSI) * Module variable declarations * Package variable declarations * Task and function ports * block variable declarations * for loop variable declarations Also check that it is an error to use the var keyword in a for loop without an explicit data type, as that is not allowed by the standard. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_var_block.v | 50 +++++++++++++++ ivtest/ivltests/sv_var_for.v | 17 ++++++ ivtest/ivltests/sv_var_for_fail.v | 13 ++++ ivtest/ivltests/sv_var_function.v | 41 +++++++++++++ ivtest/ivltests/sv_var_module.v | 50 +++++++++++++++ ivtest/ivltests/sv_var_module_inout1.v | 11 ++++ ivtest/ivltests/sv_var_module_inout2.v | 10 +++ ivtest/ivltests/sv_var_module_input1.v | 61 +++++++++++++++++++ ivtest/ivltests/sv_var_module_input2.v | 60 ++++++++++++++++++ ivtest/ivltests/sv_var_module_output1.v | 81 +++++++++++++++++++++++++ ivtest/ivltests/sv_var_module_output2.v | 80 ++++++++++++++++++++++++ ivtest/ivltests/sv_var_package.v | 53 ++++++++++++++++ ivtest/ivltests/sv_var_task.v | 48 +++++++++++++++ ivtest/regress-sv.list | 13 ++++ ivtest/regress-vlog95.list | 11 ++++ 15 files changed, 599 insertions(+) create mode 100644 ivtest/ivltests/sv_var_block.v create mode 100644 ivtest/ivltests/sv_var_for.v create mode 100644 ivtest/ivltests/sv_var_for_fail.v create mode 100644 ivtest/ivltests/sv_var_function.v create mode 100644 ivtest/ivltests/sv_var_module.v create mode 100644 ivtest/ivltests/sv_var_module_inout1.v create mode 100644 ivtest/ivltests/sv_var_module_inout2.v create mode 100644 ivtest/ivltests/sv_var_module_input1.v create mode 100644 ivtest/ivltests/sv_var_module_input2.v create mode 100644 ivtest/ivltests/sv_var_module_output1.v create mode 100644 ivtest/ivltests/sv_var_module_output2.v create mode 100644 ivtest/ivltests/sv_var_package.v create mode 100644 ivtest/ivltests/sv_var_task.v diff --git a/ivtest/ivltests/sv_var_block.v b/ivtest/ivltests/sv_var_block.v new file mode 100644 index 000000000..e5a6590cb --- /dev/null +++ b/ivtest/ivltests/sv_var_block.v @@ -0,0 +1,50 @@ +// Check that the var keyword is supported for variable declarations in blocks + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module test; + + bit failed = 1'b0; + + initial begin + var x; + var [7:0] y; + var signed [8:0] z; + var logic [9:0] w; + + x = 1'b1; + y = 8'd10; + z = -8'sd1; + w = 8'd20; + + `check(x, 1'b1) + `check(y, 10) + `check(z, -1) + `check(w, 20) + + // var should default to logic and allow x state + x = 1'bx; + y = 8'hxx; + z = 8'hxx; + w = 8'hxx; + + `check(x, 1'bx) + `check(y, 8'hxx) + `check(z, 8'hxx) + `check(w, 8'hxx) + + `check($bits(x), 1) + `check($bits(y), 8) + `check($bits(z), 9) + `check($bits(w), 10) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_for.v b/ivtest/ivltests/sv_var_for.v new file mode 100644 index 000000000..f676125b0 --- /dev/null +++ b/ivtest/ivltests/sv_var_for.v @@ -0,0 +1,17 @@ +// Check that var keyword is supported in for loop variable declarations + +module test; + + initial begin + int j; + for (var int i = 0; i < 10; i++) begin + j = i; + end + if (j == 9) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_for_fail.v b/ivtest/ivltests/sv_var_for_fail.v new file mode 100644 index 000000000..827613d5c --- /dev/null +++ b/ivtest/ivltests/sv_var_for_fail.v @@ -0,0 +1,13 @@ +// Check that it is an error to not declare the data type in for loops, even +// when using var + +module test; + + initial begin + // The data type is not optional in a for loop, even when using var + for (var [7:0] i = 0; i < 10; i++) begin + end + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_var_function.v b/ivtest/ivltests/sv_var_function.v new file mode 100644 index 000000000..829454ca7 --- /dev/null +++ b/ivtest/ivltests/sv_var_function.v @@ -0,0 +1,41 @@ +// Check that the var keyword is supported for function ports + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + return 1'b1; \ + end \ + return 1'b0; + +module test; + + function bit f1 (var int x); + `check(x, 10) + endfunction + + function bit f2 (input var int x); + `check(x, 20) + endfunction + + function bit f3 (var [7:0] x); + `check(x, 30) + endfunction + + function bit f4 (input var [7:0] x); + `check(x, 40) + endfunction + + initial begin + bit failed; + + failed = f1(10); + failed |= f2(20); + failed |= f3(30); + failed |= f4(40); + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module.v b/ivtest/ivltests/sv_var_module.v new file mode 100644 index 000000000..0b63786dd --- /dev/null +++ b/ivtest/ivltests/sv_var_module.v @@ -0,0 +1,50 @@ +// Check that the var keyword is supported for variable declarations in modules + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module test; + + var x; + var [7:0] y; + var signed [8:0] z; + var logic [9:0] w; + + bit failed = 1'b0; + + initial begin + x = 1'b1; + y = 8'd10; + z = -8'sd1; + w = 8'd20; + + `check(x, 1'b1) + `check(y, 10) + `check(z, -1) + `check(w, 20) + + // var should default to logic and allow x state + x = 1'bx; + y = 8'hxx; + z = 8'hxx; + w = 8'hxx; + + `check(x, 1'bx) + `check(y, 8'hxx) + `check(z, 8'hxx) + `check(w, 8'hxx) + + `check($bits(x), 1) + `check($bits(y), 8) + `check($bits(z), 9) + `check($bits(w), 10) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_inout1.v b/ivtest/ivltests/sv_var_module_inout1.v new file mode 100644 index 000000000..4e07e8178 --- /dev/null +++ b/ivtest/ivltests/sv_var_module_inout1.v @@ -0,0 +1,11 @@ +// Check that using the var keyword for module ANSI inout ports results in an error + +module test #( + inout var x +); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_inout2.v b/ivtest/ivltests/sv_var_module_inout2.v new file mode 100644 index 000000000..cb0f68026 --- /dev/null +++ b/ivtest/ivltests/sv_var_module_inout2.v @@ -0,0 +1,10 @@ +// Check that using the var keyword for module non-ANSI inout ports results in an error + +module test; + inout var x; + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_input1.v b/ivtest/ivltests/sv_var_module_input1.v new file mode 100644 index 000000000..d23a9dca0 --- /dev/null +++ b/ivtest/ivltests/sv_var_module_input1.v @@ -0,0 +1,61 @@ +// Check that the var keyword is supported for module ANSI input ports + +bit failed = 1'b0; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module M #( + parameter VAL_X = 0, + parameter VAL_Y = 0, + parameter VAL_Z = 0, + parameter VAL_W = 0 +) ( + input var x, + input var [7:0] y, + input var signed [7:0] z, + input var logic [7:0] w +); + + initial begin + `check(x, VAL_X) + `check(y, VAL_Y) + `check(z, VAL_Z) + `check(w, VAL_W) + end + +endmodule + +module test; + + M #( + .VAL_X (1'b1), + .VAL_Y (8'd10), + .VAL_Z (-8'sd1), + .VAL_W (8'd20) + ) i_m1 ( + .x (1'b1), + .y (8'd10), + .z (-8'sd1), + .w (8'd20) + ); + + // When unconnected it should default to x, rather z + M #( + .VAL_X (1'bx), + .VAL_Y (8'hx), + .VAL_Z (8'hx), + .VAL_W (8'hx) + ) i_m2 (); + + initial begin + #1 + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_input2.v b/ivtest/ivltests/sv_var_module_input2.v new file mode 100644 index 000000000..5ec7702fc --- /dev/null +++ b/ivtest/ivltests/sv_var_module_input2.v @@ -0,0 +1,60 @@ +// Check that the var keyword is supported for module non-ANSI input ports + +bit failed = 1'b0; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module M(x, y, z, w); + parameter VAL_X = 0; + parameter VAL_Y = 0; + parameter VAL_Z = 0; + parameter VAL_W = 0; + + input var x; + input var [7:0] y; + input var signed [7:0] z; + input var logic [7:0] w; + + initial begin + `check(x, VAL_X) + `check(y, VAL_Y) + `check(z, VAL_Z) + `check(w, VAL_W) + end + +endmodule + +module test; + + M #( + .VAL_X (1'b1), + .VAL_Y (8'd10), + .VAL_Z (-8'sd1), + .VAL_W (8'd20) + ) i_m1 ( + .x (1'b1), + .y (8'd10), + .z (-8'sd1), + .w (8'd20) + ); + + // When unconnected it should default to x, rather z + M #( + .VAL_X (1'bx), + .VAL_Y (8'hx), + .VAL_Z (8'hx), + .VAL_W (8'hx) + ) i_m2 (); + + initial begin + #1 + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_output1.v b/ivtest/ivltests/sv_var_module_output1.v new file mode 100644 index 000000000..1e64aff13 --- /dev/null +++ b/ivtest/ivltests/sv_var_module_output1.v @@ -0,0 +1,81 @@ +// Check that the var keyword is supported for module ANSI output ports + +bit failed = 1'b0; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module M #( + parameter VAL_X = 0, + parameter VAL_Y = 0, + parameter VAL_Z = 0, + parameter VAL_W = 0 +) ( + output var x, + output var [7:0] y, + output var signed [7:0] z, + output var logic [7:0] w +); + + assign x = VAL_X; + assign y = VAL_Y; + assign z = VAL_Z; + assign w = VAL_W; + +endmodule + +module test; + + logic x1; + logic x2; + logic [7:0] y1; + logic [7:0] y2; + logic signed [7:0] z1; + logic signed [7:0] z2; + logic [7:0] w1; + logic [7:0] w2; + + M #( + .VAL_X (1'b1), + .VAL_Y (10), + .VAL_Z (-1), + .VAL_W (20) + ) i_m1 ( + .x (x1), + .y (y1), + .z (z1), + .w (w1) + ); + + // The type for var should default to logic, check that the value can be X + M #( + .VAL_X (1'bx), + .VAL_Y (8'hxx), + .VAL_Z (8'hxx), + .VAL_W (8'hxx) + ) i_m2 ( + .x (x2), + .y (y2), + .z (z2), + .w (w2) + ); + + initial begin + `check(x1, 1'b1) + `check(y1, 10) + `check(z1, -1) + `check(w1, 20) + `check(x2, 1'bx) + `check(y2, 8'hxx) + `check(z2, 8'hxx) + `check(w2, 8'hxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_module_output2.v b/ivtest/ivltests/sv_var_module_output2.v new file mode 100644 index 000000000..ca7962c9d --- /dev/null +++ b/ivtest/ivltests/sv_var_module_output2.v @@ -0,0 +1,80 @@ +// Check that the var keyword is supported for module non-ANSI output ports + +bit failed = 1'b0; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module M(x, y, z, w); + parameter VAL_X = 0; + parameter VAL_Y = 0; + parameter VAL_Z = 0; + parameter VAL_W = 0; + + output var x; + output var [7:0] y; + output var signed [7:0] z; + output var logic [7:0] w; + + assign x = VAL_X; + assign y = VAL_Y; + assign z = VAL_Z; + assign w = VAL_W; + +endmodule + +module test; + + logic x1; + logic x2; + logic [7:0] y1; + logic [7:0] y2; + logic signed [7:0] z1; + logic signed [7:0] z2; + logic [7:0] w1; + logic [7:0] w2; + + M #( + .VAL_X (1'b1), + .VAL_Y (10), + .VAL_Z (-1), + .VAL_W (20) + ) i_m1 ( + .x (x1), + .y (y1), + .z (z1), + .w (w1) + ); + + // The type for var should default to logic, check that the value can be X + M #( + .VAL_X (1'bx), + .VAL_Y (8'hxx), + .VAL_Z (8'hxx), + .VAL_W (8'hxx) + ) i_m2 ( + .x (x2), + .y (y2), + .z (z2), + .w (w2) + ); + + initial begin + `check(x1, 1'b1) + `check(y1, 10) + `check(z1, -1) + `check(w1, 20) + `check(x2, 1'bx) + `check(y2, 8'hxx) + `check(z2, 8'hxx) + `check(w2, 8'hxx) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_package.v b/ivtest/ivltests/sv_var_package.v new file mode 100644 index 000000000..4030a9c7f --- /dev/null +++ b/ivtest/ivltests/sv_var_package.v @@ -0,0 +1,53 @@ +// Check that the var keyword is supported for variable declarations in packages + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +package P; + var x; + var [7:0] y; + var signed [8:0] z; + var logic [9:0] w; +endpackage + +module test; + import P::*; + + bit failed = 1'b0; + + initial begin + x = 1'b1; + y = 8'd10; + z = -8'sd1; + w = 8'd20; + + `check(x, 1'b1) + `check(y, 10) + `check(z, -1) + `check(w, 20) + + // var should default to logic and allow x state + x = 1'bx; + y = 8'hxx; + z = 8'hxx; + w = 8'hxx; + + `check(x, 1'bx) + `check(y, 8'hxx) + `check(z, 8'hxx) + `check(w, 8'hxx) + + `check($bits(x), 1) + `check($bits(y), 8) + `check($bits(z), 9) + `check($bits(w), 10) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_var_task.v b/ivtest/ivltests/sv_var_task.v new file mode 100644 index 000000000..70ee3fb7f --- /dev/null +++ b/ivtest/ivltests/sv_var_task.v @@ -0,0 +1,48 @@ +// Check that the var keyword is supported for task ports + +bit failed = 1'b0; + +`define check(val, exp) \ + if (val !== exp) begin \ + $display("FAILED(%0d). '%s' expected %b, got %b", `__LINE__, `"val`", val, exp); \ + failed = 1'b1; \ + end + +module test; + + task t1 (var int x); + `check(x, 10) + endtask + + task t2 (input var int x, output var int y); + `check(x, 20) + y = x; + endtask + + task t3 (var [7:0] x); + `check(x, 30) + endtask + + task t4 (input var [7:0] x, output var [7:0] y); + `check(x, 40) + y = x; + endtask + + initial begin + int o1; + logic [7:0] o2; + + t1(10); + t2(20, o1); + t3(30); + t4(40, o2); + + `check(o1, 20) + `check(o2, 40) + + if (!failed) begin + $display("PASSED"); + end + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index d21ffab1b..c01b065bb 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -694,8 +694,21 @@ sv_uwire1 normal,-g2009 ivltests sv_uwire2 normal,-g2009 ivltests sv_uwire3 normal,-g2009 ivltests sv_uwire4 normal,-g2009 ivltests +sv_var_block normal,-g2005-sv ivltests +sv_var_for normal,-g2005-sv ivltests +sv_var_for_fail CE,-g2005-sv ivltests +sv_var_function normal,-g2005-sv ivltests sv_var_init1 normal,-g2009 ivltests sv_var_init2 normal,-g2009 ivltests +sv_var_module normal,-g2005-sv ivltests +sv_var_module_inout1 CE,-g2005-sv ivltests +sv_var_module_inout2 CE,-g2005-sv ivltests +sv_var_module_input1 normal,-g2005-sv ivltests +sv_var_module_input2 normal,-g2005-sv ivltests +sv_var_module_output1 normal,-g2005-sv ivltests +sv_var_module_output2 normal,-g2005-sv ivltests +sv_var_package normal,-g2005-sv ivltests +sv_var_task normal,-g2005-sv ivltests sv_wildcard_import1 normal,-g2009 ivltests sv_wildcard_import2 normal,-g2009 ivltests sv_wildcard_import3 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index 76d24a9ee..0f0b72526 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -942,6 +942,17 @@ sv_port_default10 normal,-g2009,-pallowsigned=1 ivltests sv_port_default11 normal,-g2009,-pallowsigned=1 ivltests sv_root_func normal,-g2009,-pallowsigned=1 ivltests gold=sv_root_func.gold sv_root_task normal,-g2009,-pallowsigned=1 ivltests gold=sv_root_task.gold +sv_var_block normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_for normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_function normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_module normal,-g2005-sv,-pallowsigned=1 ivltests +# Inputs can not be reg in Verilog 95, so the translated code will fail +sv_var_module_input1 TE,-g2005-sv,-pallowsigned=1 ivltests +sv_var_module_input2 TE,-g2005-sv,-pallowsigned=1 ivltests +sv_var_module_output1 normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_module_output2 normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_package normal,-g2005-sv,-pallowsigned=1 ivltests +sv_var_task normal,-g2005-sv,-pallowsigned=1 ivltests test_dispwided normal,-pallowsigned=1 ivltests gold=test_dispwided.gold test_inc_dec normal,-g2009,-pallowsigned=1 ivltests test_enumsystem normal,-g2009,-pallowsigned=1,ivltests/enumsystem.vhd ivltests