From 3daa2982acb28c2da76cc90e1ebc386d3fcf78a7 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 3 Jan 2022 21:24:23 +0100 Subject: [PATCH 1/2] Add support for `const` variables SystemVerilog allows to declare const variables. These variables are read-only and can not be assigned a value after their declaration. It is only possible to assign an initial value as an initializer. E.g. ``` const int x = 10; x = 20; // Error ``` The LRM requires that for variable declarations with static storage the initializer is a constant expression with the extension that other const variables are also allowed. const variables with automatic storage can be initialized by any expression. Checking if an expression contains only const variables requires a bit more work to implement. So for now be more lenient that what the standard requires and allow arbitrary expressions to initialize const variables even for those with static storage. Signed-off-by: Lars-Peter Clausen --- PExpr.h | 12 ++++++++---- PWire.h | 6 ++++++ Statement.cc | 9 +++++---- Statement.h | 7 +++++-- elab_lval.cc | 19 ++++++++++++++----- elab_net.cc | 6 ++++++ elab_sig.cc | 2 ++ elaborate.cc | 2 +- netlist.h | 6 ++++++ parse.y | 50 ++++++++++++++++++++++++++++---------------------- pform.cc | 16 ++++++++++------ pform.h | 9 ++++++--- 12 files changed, 97 insertions(+), 47 deletions(-) diff --git a/PExpr.h b/PExpr.h index b91e9bdcf2..8958ed62ae 100644 --- a/PExpr.h +++ b/PExpr.h @@ -172,7 +172,8 @@ class PExpr : public LineInfo { virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const; + bool is_force, + bool is_init = false) const; // This method returns true if the expression represents a // structural net that can have multiple drivers. This is @@ -262,7 +263,8 @@ class PEConcat : public PExpr { virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const; + bool is_force, + bool is_init = false) const; virtual bool is_collapsible_net(Design*des, NetScope*scope, NetNet::PortType port_type) const; private: @@ -361,7 +363,8 @@ class PEIdent : public PExpr { virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const; + bool is_force, + bool is_init = false) const; virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, ivl_type_t type, unsigned flags) const; @@ -647,7 +650,8 @@ class PENumber : public PExpr { virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const; + bool is_force, + bool is_init = false) const; private: verinum*const value_; diff --git a/PWire.h b/PWire.h index 4d8820eeea..8b47fc214a 100644 --- a/PWire.h +++ b/PWire.h @@ -68,6 +68,9 @@ class PWire : public PNamedItem { NetNet::PortType get_port_type() const; bool set_port_type(NetNet::PortType); + void set_const(bool is_const) { is_const_ = is_const; }; + bool get_const() const { return is_const_; }; + void set_signed(bool flag); bool get_signed() const; @@ -100,6 +103,9 @@ class PWire : public PNamedItem { NetNet::PortType port_type_; bool signed_; + // Whether the wire is variable declared with the const keyword. + bool is_const_ = false; + // These members hold expressions for the bit width of the // wire. If they do not exist, the wire is 1 bit wide. If they // do exist, they represent the packed dimensions of the diff --git a/Statement.cc b/Statement.cc index d75b802da5..7799eca738 100644 --- a/Statement.cc +++ b/Statement.cc @@ -29,8 +29,9 @@ Statement::~Statement() { } -PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant) -: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant) +PAssign_::PAssign_(PExpr*lval__, PExpr*ex, bool is_constant, bool is_init) +: event_(0), count_(0), lval_(lval__), rval_(ex), is_constant_(is_constant), + is_init_(is_init) { delay_ = 0; } @@ -73,8 +74,8 @@ PAssign::PAssign(PExpr*lval__, PExpr*cnt, PEventStatement*d, PExpr*ex) { } -PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant) -: PAssign_(lval__, ex, is_constant), op_(0) +PAssign::PAssign(PExpr*lval__, PExpr*ex, bool is_constant, bool is_init) +: PAssign_(lval__, ex, is_constant, is_init), op_(0) { } diff --git a/Statement.h b/Statement.h index 7d8efa6bfa..d9b7f0faf2 100644 --- a/Statement.h +++ b/Statement.h @@ -95,7 +95,8 @@ class Statement : virtual public LineInfo { */ class PAssign_ : public Statement { public: - explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant); + explicit PAssign_(PExpr*lval, PExpr*ex, bool is_constant, + bool is_init = false); explicit PAssign_(PExpr*lval, PExpr*de, PExpr*ex); explicit PAssign_(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); virtual ~PAssign_() =0; @@ -122,6 +123,8 @@ class PAssign_ : public Statement { PExpr* lval_; PExpr* rval_; bool is_constant_; + // Whether the assignment is a variable initializer expression + bool is_init_ = false; }; class PAssign : public PAssign_ { @@ -135,7 +138,7 @@ class PAssign : public PAssign_ { explicit PAssign(PExpr*lval, char op, PExpr*ex); explicit PAssign(PExpr*lval, PExpr*de, PExpr*ex); explicit PAssign(PExpr*lval, PExpr*cnt, PEventStatement*de, PExpr*ex); - explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant); + explicit PAssign(PExpr*lval, PExpr*ex, bool is_constant, bool is_init); ~PAssign(); virtual void dump(std::ostream&out, unsigned ind) const; diff --git a/elab_lval.cc b/elab_lval.cc index 1ac35d9165..10d24a1e02 100644 --- a/elab_lval.cc +++ b/elab_lval.cc @@ -76,7 +76,7 @@ using namespace std; * is to try to make a net elaboration, and see if the result is * suitable for assignment. */ -NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const +NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool, bool) const { cerr << get_fileline() << ": Assignment l-value too complex." << endl; return 0; @@ -98,7 +98,8 @@ NetAssign_* PExpr::elaborate_lval(Design*, NetScope*, bool, bool) const NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const + bool is_force, + bool is_init) const { if (repeat_) { cerr << get_fileline() << ": error: Repeat concatenations make " @@ -119,7 +120,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, } NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, - is_cassign, is_force); + is_cassign, is_force, is_init); /* If the l-value doesn't elaborate, the error was already detected and printed. We just skip it and let @@ -157,7 +158,8 @@ NetAssign_* PEConcat::elaborate_lval(Design*des, NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope, bool is_cassign, - bool is_force) const + bool is_force, + bool is_init) const { if (debug_elaborate) { @@ -213,6 +215,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, << endl; } + if (reg->get_const() && !is_init) { + cerr << get_fileline() << ": error: Assignment to const signal `" + << reg->name() << "` is not allowed." << endl; + des->errors++; + return nullptr; + } + return elaborate_lval_var_(des, scope, is_force, is_cassign, reg, sr.type, member_path); } @@ -1535,7 +1544,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope, return false; } -NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool, bool) const +NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool, bool, bool) const { cerr << get_fileline() << ": error: Constant values not allowed " << "in l-value expressions." << endl; diff --git a/elab_net.cc b/elab_net.cc index 9d30e5642d..9635bf0e86 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -556,6 +556,12 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, << endl; } + if (sig->get_const()) { + cerr << get_fileline() << ": error: Continuous assignment to const" + << " signal `" << sig->name() << "` is not allowed." << endl; + des->errors++; + return nullptr; + } // If this is SystemVerilog and the variable is not yet // assigned by anything, then convert it to an unresolved diff --git a/elab_sig.cc b/elab_sig.cc index 7337250c4b..a855d99485 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1204,5 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const for (unsigned idx = 0 ; idx < nattrib ; idx += 1) sig->attribute(attrib_list[idx].key, attrib_list[idx].val); + sig->set_const(is_const_); + return sig; } diff --git a/elaborate.cc b/elaborate.cc index b99ba90c7a..1e387f8e9d 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2378,7 +2378,7 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const << "lval_ expr type = " << typeid(*lval_).name() << endl; } - return lval_->elaborate_lval(des, scope, false, false); + return lval_->elaborate_lval(des, scope, false, false, is_init_); } NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope, diff --git a/netlist.h b/netlist.h index 4efd478d8f..8ea80ddf87 100644 --- a/netlist.h +++ b/netlist.h @@ -702,6 +702,9 @@ class NetNet : public NetObj, public PortType { signed. Otherwise, it is unsigned. */ bool get_signed() const; + void set_const(bool is_const) { is_const_ = is_const; } + bool get_const() const { return is_const_; } + bool get_scalar() const; inline const ivl_type_s* net_type(void) const { return net_type_; } @@ -808,6 +811,9 @@ class NetNet : public NetObj, public PortType { netuarray_t *array_type_ = nullptr; ivl_discipline_t discipline_; + // Whether the net is variable declared with the const keyword. + bool is_const_ = false; + std::vector unpacked_dims_; // These are the widths of the various slice depths. There is diff --git a/parse.y b/parse.y index c0d4fc32f8..92e8c73ef8 100644 --- a/parse.y +++ b/parse.y @@ -639,7 +639,7 @@ Module::port_t *module_declare_port(const YYLTYPE&loc, char *id, %type number pos_neg_number %type signing unsigned_signed_opt signed_unsigned_opt %type import_export -%type K_genvar_opt K_static_opt K_virtual_opt +%type K_genvar_opt K_static_opt K_virtual_opt K_const_opt %type udp_reg_opt edge_operator %type drive_strength drive_strength_opt dr_strength0 dr_strength1 %type udp_input_sym udp_output_sym @@ -1231,21 +1231,22 @@ constraint_set /* IEEE1800-2005 A.1.9 */ ; data_declaration /* IEEE1800-2005: A.2.1.3 */ - : attribute_list_opt data_type list_of_variable_decl_assignments ';' - { data_type_t*data_type = $2; - if (data_type == 0) { + : attribute_list_opt K_const_opt data_type list_of_variable_decl_assignments ';' + { data_type_t *data_type = $3; + if (!data_type) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @2); + FILE_NAME(data_type, @3); } - pform_makewire(@2, 0, str_strength, $3, NetNet::IMPLICIT_REG, data_type, $1); + pform_makewire(@3, 0, str_strength, $4, NetNet::IMPLICIT_REG, data_type, + $1, $2); } - | attribute_list_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';' - { data_type_t*data_type = $3; - if (data_type == 0) { + | attribute_list_opt K_const_opt K_var data_type_or_implicit list_of_variable_decl_assignments ';' + { data_type_t *data_type = $4; + if (!data_type) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @2); + FILE_NAME(data_type, @3); } - pform_make_var(@2, $4, data_type, $1); + pform_make_var(@3, $5, data_type, $1, $2); } | attribute_list_opt K_event event_variable_list ';' { if ($3) pform_make_events(@2, $3); @@ -2731,24 +2732,24 @@ block_item_decl /* variable declarations. Note that data_type can be 0 if we are recovering from an error. */ - : K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';' - { data_type_t*data_type = $3; - if (data_type == 0) { + : K_const_opt K_var variable_lifetime_opt data_type_or_implicit list_of_variable_decl_assignments ';' + { data_type_t *data_type = $4; + if (!data_type) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); - FILE_NAME(data_type, @1); + FILE_NAME(data_type, @2); } - pform_make_var(@1, $4, data_type, attributes_in_context); + pform_make_var(@2, $5, 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); + | K_const_opt variable_lifetime_opt data_type list_of_variable_decl_assignments ';' + { if ($3) pform_make_var(@3, $4, $3, attributes_in_context, $1); var_lifetime = LexicalScope::INHERITED; } /* The extra `reg` is not valid (System)Verilog, this is a iverilog extension. */ - | variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';' - { if ($3) pform_make_var(@3, $4, $3, attributes_in_context); + | K_const_opt variable_lifetime_opt K_reg data_type list_of_variable_decl_assignments ';' + { if ($4) pform_make_var(@4, $5, $4, attributes_in_context, $1); var_lifetime = LexicalScope::INHERITED; } @@ -2769,11 +2770,11 @@ 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 ';' + | K_const_opt 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 ';' + | K_const_opt variable_lifetime_opt data_type error ';' { yyerror(@1, "error: Syntax error in variable list."); yyerrok; } @@ -7308,6 +7309,11 @@ unique_priority presence is significant. This is a fairly common pattern so collect those rules here. */ +K_const_opt + : K_const { $$ = true; } + | { $$ = false; } + ; + K_genvar_opt : K_genvar { $$ = true; } | { $$ = false; } diff --git a/pform.cc b/pform.cc index 3957019ed1..61da7ad750 100644 --- a/pform.cc +++ b/pform.cc @@ -951,11 +951,13 @@ PCallTask* pform_make_call_task(const struct vlltype&loc, void pform_make_var(const struct vlltype&loc, std::list*assign_list, - data_type_t*data_type, std::list*attr) + data_type_t*data_type, std::list*attr, + bool is_const) { static const struct str_pair_t str = { IVL_DR_STRONG, IVL_DR_STRONG }; - pform_makewire(loc, 0, str, assign_list, NetNet::REG, data_type, attr); + pform_makewire(loc, 0, str, assign_list, NetNet::REG, data_type, attr, + is_const); } void pform_make_foreach_declarations(const struct vlltype&loc, @@ -2494,7 +2496,7 @@ void pform_make_var_init(const struct vlltype&li, PEIdent*lval = new PEIdent(name); FILE_NAME(lval, li); - PAssign*ass = new PAssign(lval, expr, !gn_system_verilog()); + PAssign*ass = new PAssign(lval, expr, !gn_system_verilog(), true); FILE_NAME(ass, li); lexical_scope->var_inits.push_back(ass); @@ -2646,7 +2648,8 @@ void pform_makewire(const struct vlltype&li, std::list*assign_list, NetNet::Type type, data_type_t*data_type, - list*attr) + list*attr, + bool is_const) { if (is_compilation_unit(lexical_scope) && !gn_system_verilog()) { VLerror(li, "error: Variable declarations must be contained within a module."); @@ -2662,7 +2665,7 @@ void pform_makewire(const struct vlltype&li, wires->push_back(wire); } - pform_set_data_type(li, data_type, wires, type, attr); + pform_set_data_type(li, data_type, wires, type, attr, is_const); while (! assign_list->empty()) { decl_assignment_t*first = assign_list->front(); @@ -3224,7 +3227,7 @@ void pform_set_port_type(const struct vlltype&li, */ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, std::vector *wires, NetNet::Type net_type, - list*attr) + list*attr, bool is_const) { if (data_type == 0) { VLerror(li, "internal error: data_type==0."); @@ -3245,6 +3248,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, ivl_assert(li, rc); wire->set_data_type(data_type); + wire->set_const(is_const); pform_bind_attributes(wire->attributes, attr, true); } diff --git a/pform.h b/pform.h index 7eeb936217..92d3edfb2b 100644 --- a/pform.h +++ b/pform.h @@ -350,12 +350,14 @@ extern void pform_makewire(const struct vlltype&li, std::list*assign_list, NetNet::Type type, data_type_t*data_type, - std::list*attr = 0); + std::list*attr = 0, + bool is_const = false); extern void pform_make_var(const struct vlltype&loc, std::list*assign_list, data_type_t*data_type, - std::list*attr = 0); + std::list*attr = 0, + bool is_const = false); extern void pform_make_var_init(const struct vlltype&li, perm_string name, PExpr*expr); @@ -374,7 +376,8 @@ extern void pform_set_data_type(const struct vlltype&li, data_type_t *data_type, std::vector *wires, NetNet::Type net_type, - std::list*attr); + std::list*attr, + bool is_const = false); extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list*names, NetNet::Type net_type, std::list*attr); From f092820599bb9983f14e909586fa65092b014870 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 23 Jul 2023 14:38:08 -0700 Subject: [PATCH 2/2] Add regression tests for const variables Check that const variables are supported and they can not be overridden by type of assignment. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_const1.v | 18 +++++++++++++++++ ivtest/ivltests/sv_const2.v | 29 ++++++++++++++++++++++++++++ ivtest/ivltests/sv_const3.v | 17 ++++++++++++++++ ivtest/ivltests/sv_const4.v | 18 +++++++++++++++++ ivtest/ivltests/sv_const5.v | 20 +++++++++++++++++++ ivtest/ivltests/sv_const_fail1.v | 13 +++++++++++++ ivtest/ivltests/sv_const_fail2.v | 12 ++++++++++++ ivtest/ivltests/sv_const_fail3.v | 12 ++++++++++++ ivtest/ivltests/sv_const_fail4.v | 12 ++++++++++++ ivtest/ivltests/sv_const_fail5.v | 12 ++++++++++++ ivtest/ivltests/sv_const_fail6.v | 16 +++++++++++++++ ivtest/ivltests/sv_const_fail7.v | 21 ++++++++++++++++++++ ivtest/ivltests/sv_const_fail8.v | 21 ++++++++++++++++++++ ivtest/regress-vvp.list | 13 +++++++++++++ ivtest/vvp_tests/sv_const1.json | 5 +++++ ivtest/vvp_tests/sv_const2.json | 5 +++++ ivtest/vvp_tests/sv_const3.json | 5 +++++ ivtest/vvp_tests/sv_const4.json | 5 +++++ ivtest/vvp_tests/sv_const5.json | 5 +++++ ivtest/vvp_tests/sv_const_fail1.json | 5 +++++ ivtest/vvp_tests/sv_const_fail2.json | 5 +++++ ivtest/vvp_tests/sv_const_fail3.json | 5 +++++ ivtest/vvp_tests/sv_const_fail4.json | 5 +++++ ivtest/vvp_tests/sv_const_fail5.json | 5 +++++ ivtest/vvp_tests/sv_const_fail6.json | 5 +++++ ivtest/vvp_tests/sv_const_fail7.json | 5 +++++ ivtest/vvp_tests/sv_const_fail8.json | 5 +++++ 27 files changed, 299 insertions(+) create mode 100644 ivtest/ivltests/sv_const1.v create mode 100644 ivtest/ivltests/sv_const2.v create mode 100644 ivtest/ivltests/sv_const3.v create mode 100644 ivtest/ivltests/sv_const4.v create mode 100644 ivtest/ivltests/sv_const5.v create mode 100644 ivtest/ivltests/sv_const_fail1.v create mode 100644 ivtest/ivltests/sv_const_fail2.v create mode 100644 ivtest/ivltests/sv_const_fail3.v create mode 100644 ivtest/ivltests/sv_const_fail4.v create mode 100644 ivtest/ivltests/sv_const_fail5.v create mode 100644 ivtest/ivltests/sv_const_fail6.v create mode 100644 ivtest/ivltests/sv_const_fail7.v create mode 100644 ivtest/ivltests/sv_const_fail8.v create mode 100644 ivtest/vvp_tests/sv_const1.json create mode 100644 ivtest/vvp_tests/sv_const2.json create mode 100644 ivtest/vvp_tests/sv_const3.json create mode 100644 ivtest/vvp_tests/sv_const4.json create mode 100644 ivtest/vvp_tests/sv_const5.json create mode 100644 ivtest/vvp_tests/sv_const_fail1.json create mode 100644 ivtest/vvp_tests/sv_const_fail2.json create mode 100644 ivtest/vvp_tests/sv_const_fail3.json create mode 100644 ivtest/vvp_tests/sv_const_fail4.json create mode 100644 ivtest/vvp_tests/sv_const_fail5.json create mode 100644 ivtest/vvp_tests/sv_const_fail6.json create mode 100644 ivtest/vvp_tests/sv_const_fail7.json create mode 100644 ivtest/vvp_tests/sv_const_fail8.json diff --git a/ivtest/ivltests/sv_const1.v b/ivtest/ivltests/sv_const1.v new file mode 100644 index 0000000000..085e5672ac --- /dev/null +++ b/ivtest/ivltests/sv_const1.v @@ -0,0 +1,18 @@ +// Check that const variables in module scope are supported. + +module test; + + const integer x = 10; + + // The initializer expression is allowed to reference other const variables. + const integer y = 20 + x; + + initial begin + if (x === 10 && y === 30) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_const2.v b/ivtest/ivltests/sv_const2.v new file mode 100644 index 0000000000..ac668b9093 --- /dev/null +++ b/ivtest/ivltests/sv_const2.v @@ -0,0 +1,29 @@ +// Check that const variables are supported in function and task scope. + +module test; + + function automatic integer f(integer x); + // Automatic const variables can have a non-const initializer epxression + const integer y = 2 * x; + return y; + endfunction + + task automatic t(input integer x, output integer y); + // Automatic const variables can have a non-const initializer epxression + const integer z = 2 * x; + y = z; + endtask + + initial begin + integer y; + + t(15, y); + + if (f(10) === 20 && y === 30) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_const3.v b/ivtest/ivltests/sv_const3.v new file mode 100644 index 0000000000..1f0a6a82bc --- /dev/null +++ b/ivtest/ivltests/sv_const3.v @@ -0,0 +1,17 @@ +// Check that const variables in block scope are supported. + +module test; + + initial begin + const static integer x = 10; + // The initializer expression is allowed to reference other const variables. + const static integer y = 20 + x; + + if (x === 10 && y === 30) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_const4.v b/ivtest/ivltests/sv_const4.v new file mode 100644 index 0000000000..3d0af22917 --- /dev/null +++ b/ivtest/ivltests/sv_const4.v @@ -0,0 +1,18 @@ +// Check that const variables are supported in the unit scope. + +const integer x = 10; + +// The initializer expression is allowed to reference other const variables. +const integer y = 20 + x; + +module test; + + initial begin + if (x === 10 && y === 30) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_const5.v b/ivtest/ivltests/sv_const5.v new file mode 100644 index 0000000000..e08bdfbc12 --- /dev/null +++ b/ivtest/ivltests/sv_const5.v @@ -0,0 +1,20 @@ +// Check that const variables are supported in a package scope. + +package P; + const integer x = 10; + + // The initializer expression is allowed to reference other const variables. + const integer y = 20 + x; +endpackage + +module test; + + initial begin + if (P::x === 10 && P::y === 30) begin + $display("PASSED"); + end else begin + $display("FAILED"); + end + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail1.v b/ivtest/ivltests/sv_const_fail1.v new file mode 100644 index 0000000000..f654272729 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail1.v @@ -0,0 +1,13 @@ +// Check that continuous assignment to a const variable fails. + +module test; + + const integer x = 10; + + assign x = 20; // Error: Assignment to const variable + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail2.v b/ivtest/ivltests/sv_const_fail2.v new file mode 100644 index 0000000000..2d0b2d6382 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail2.v @@ -0,0 +1,12 @@ +// Check that blocking assignment to a const variable fails. + +module test; + + const integer x = 10; + + initial begin + x = 20; // Error: Assignment to const variable + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail3.v b/ivtest/ivltests/sv_const_fail3.v new file mode 100644 index 0000000000..41546994fa --- /dev/null +++ b/ivtest/ivltests/sv_const_fail3.v @@ -0,0 +1,12 @@ +// Check that non-blocking assignment to a const variable fails. + +module test; + + const integer x = 10; + + initial begin + x <= 20; // Error: Assignment to const variable + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail4.v b/ivtest/ivltests/sv_const_fail4.v new file mode 100644 index 0000000000..56b24a8744 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail4.v @@ -0,0 +1,12 @@ +// Check that force assignment to a const variable fails. + +module test; + + const integer x = 10; + + initial begin + force x = 20; // Error: Assignment to const variable + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail5.v b/ivtest/ivltests/sv_const_fail5.v new file mode 100644 index 0000000000..58a856ea18 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail5.v @@ -0,0 +1,12 @@ +// Check that procedural continuous assignment to a const variable fails. + +module test; + + const integer x = 10; + + initial begin + assign x = 20; // Error: Assignment to const variable + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail6.v b/ivtest/ivltests/sv_const_fail6.v new file mode 100644 index 0000000000..34dd551e23 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail6.v @@ -0,0 +1,16 @@ +// Check that binding a const variable to a task output port fails. + +module test; + + const integer x = 10; + + task t(output integer x); + x = 20; + endtask + + initial begin + t(x); + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail7.v b/ivtest/ivltests/sv_const_fail7.v new file mode 100644 index 0000000000..8cad8fa795 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail7.v @@ -0,0 +1,21 @@ +// Check that binding a const variable to a module output port fails. + +module M( + output integer x +); + assign x = 20; +endmodule + +module test; + + const integer x = 10; + + M i_m ( + .x (x) + ); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_const_fail8.v b/ivtest/ivltests/sv_const_fail8.v new file mode 100644 index 0000000000..af9cfa3e65 --- /dev/null +++ b/ivtest/ivltests/sv_const_fail8.v @@ -0,0 +1,21 @@ +// Check that binding a const variable to a module inout port fails. + +module M( + inout integer x +); + assign x = 20; +endmodule + +module test; + + const integer x = 10; + + M i_m ( + .x (x) + ); + + initial begin + $display("FAILED"); + end + +endmodule diff --git a/ivtest/regress-vvp.list b/ivtest/regress-vvp.list index 05fd8b6d4c..11f9dc682c 100644 --- a/ivtest/regress-vvp.list +++ b/ivtest/regress-vvp.list @@ -60,6 +60,19 @@ sv_array_assign_fail1 vvp_tests/sv_array_assign_fail1.json sv_array_assign_fail2 vvp_tests/sv_array_assign_fail2.json sv_array_cassign6 vvp_tests/sv_array_cassign6.json sv_array_cassign7 vvp_tests/sv_array_cassign7.json +sv_const1 vvp_tests/sv_const1.json +sv_const2 vvp_tests/sv_const2.json +sv_const3 vvp_tests/sv_const3.json +sv_const4 vvp_tests/sv_const4.json +sv_const5 vvp_tests/sv_const5.json +sv_const_fail1 vvp_tests/sv_const_fail1.json +sv_const_fail2 vvp_tests/sv_const_fail2.json +sv_const_fail3 vvp_tests/sv_const_fail3.json +sv_const_fail4 vvp_tests/sv_const_fail4.json +sv_const_fail5 vvp_tests/sv_const_fail5.json +sv_const_fail6 vvp_tests/sv_const_fail6.json +sv_const_fail7 vvp_tests/sv_const_fail7.json +sv_const_fail8 vvp_tests/sv_const_fail8.json sv_foreach9 vvp_tests/sv_foreach9.json sv_foreach10 vvp_tests/sv_foreach10.json sv_module_port1 vvp_tests/sv_module_port1.json diff --git a/ivtest/vvp_tests/sv_const1.json b/ivtest/vvp_tests/sv_const1.json new file mode 100644 index 0000000000..80a6a307bb --- /dev/null +++ b/ivtest/vvp_tests/sv_const1.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_const1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const2.json b/ivtest/vvp_tests/sv_const2.json new file mode 100644 index 0000000000..39efe30738 --- /dev/null +++ b/ivtest/vvp_tests/sv_const2.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_const2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const3.json b/ivtest/vvp_tests/sv_const3.json new file mode 100644 index 0000000000..c151c363b9 --- /dev/null +++ b/ivtest/vvp_tests/sv_const3.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_const3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const4.json b/ivtest/vvp_tests/sv_const4.json new file mode 100644 index 0000000000..7cc53be8b7 --- /dev/null +++ b/ivtest/vvp_tests/sv_const4.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_const4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const5.json b/ivtest/vvp_tests/sv_const5.json new file mode 100644 index 0000000000..d3da84c817 --- /dev/null +++ b/ivtest/vvp_tests/sv_const5.json @@ -0,0 +1,5 @@ +{ + "type" : "normal", + "source" : "sv_const5.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail1.json b/ivtest/vvp_tests/sv_const_fail1.json new file mode 100644 index 0000000000..5fb0d364a3 --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail1.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail1.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail2.json b/ivtest/vvp_tests/sv_const_fail2.json new file mode 100644 index 0000000000..39c51cc427 --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail2.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail2.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail3.json b/ivtest/vvp_tests/sv_const_fail3.json new file mode 100644 index 0000000000..19353d4edd --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail3.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail3.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail4.json b/ivtest/vvp_tests/sv_const_fail4.json new file mode 100644 index 0000000000..50c209472c --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail4.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail4.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail5.json b/ivtest/vvp_tests/sv_const_fail5.json new file mode 100644 index 0000000000..1278627cdb --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail5.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail5.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail6.json b/ivtest/vvp_tests/sv_const_fail6.json new file mode 100644 index 0000000000..f8eaa2d355 --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail6.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail6.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail7.json b/ivtest/vvp_tests/sv_const_fail7.json new file mode 100644 index 0000000000..542ae9d9ac --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail7.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail7.v", + "iverilog-args" : [ "-g2005-sv" ] +} diff --git a/ivtest/vvp_tests/sv_const_fail8.json b/ivtest/vvp_tests/sv_const_fail8.json new file mode 100644 index 0000000000..3835ef9f9c --- /dev/null +++ b/ivtest/vvp_tests/sv_const_fail8.json @@ -0,0 +1,5 @@ +{ + "type" : "CE", + "source" : "sv_const_fail8.v", + "iverilog-args" : [ "-g2005-sv" ] +}