From 32d1f385f88b89575f55b249b74955759706b1b0 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 4 Mar 2022 10:41:39 +0100 Subject: [PATCH 1/5] tgt-vvp: Allow dynamic array new for vectors with multiple packed dimensions In the vvp all vector signals are in canonical form. This means a single dimension and the lsb starts at 0. This means that there is no need to restrict new operations for dynamic arrays of vectors to vectors with 0 or 1 packed dimensions. Multiple packed dimensions will work just fine. All that is needed is the total packed width for the signal. Signed-off-by: Lars-Peter Clausen --- tgt-vvp/eval_object.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index 0da8caa62..c38b432bd 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -28,18 +28,7 @@ void darray_new(ivl_type_t element_type, unsigned size_reg) ivl_variable_type_t type = ivl_type_base(element_type); if ((type == IVL_VT_BOOL) || (type == IVL_VT_LOGIC)) { - // bool objects are vectorable, but for now only support - // a single dimensions. - assert(ivl_type_packed_dimensions(element_type) <= 1); - if (ivl_type_packed_dimensions(element_type) == 1) { - int msb, lsb; - msb = ivl_type_packed_msb(element_type, 0); - lsb = ivl_type_packed_lsb(element_type, 0); - wid = msb>=lsb ? msb - lsb : lsb - msb; - wid += 1; - } else { - wid = 1; - } + wid = width_of_packed_type(element_type); signed_char = ivl_type_signed(element_type) ? "s" : ""; } else { // REAL or STRING objects are not packable. From 61a088fa78c9b87309c51b05e72bbf60d301f214 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Jan 2022 22:42:20 +0100 Subject: [PATCH 2/5] Use elaborate_type() infrastructure to elaborate signal types Each data_type_t has a elaborate_type() method that returns the corresponding ivl_data_t for that type. Make use of that in PWire::elaborate_sig(). This removes duplicated code and ensures consistent behavior between the different places where types are elaborated. This will also make it easier to add new data type that are going to be elaborated this way. Signed-off-by: Lars-Peter Clausen --- elab_sig.cc | 86 +++++++---------------------------------------------- 1 file changed, 10 insertions(+), 76 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index 47edb73d8..a84583a39 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -1213,52 +1213,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const NetNet*sig = 0; - if (class_type_t*class_type = dynamic_cast(set_data_type_)) { - // If this is a class variable, then the class type - // should already have been elaborated. All we need to - // do right now is locate the netclass_t object for the - // class, and use that to build the net. - - ivl_assert(*this, class_type->save_elaborated_type); - netclass_t*use_type = class_type->save_elaborated_type; - - sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); - - } else if (struct_type_t*struct_type = dynamic_cast(set_data_type_)) { - // If this is a struct type, then build the net with the - // struct type. - ivl_type_s*tmp_type = struct_type->elaborate_type(des, scope); - netstruct_t*use_type = dynamic_cast(tmp_type); - if (debug_elaborate) { - cerr << get_fileline() << ": debug: Create signal " << wtype; - if (use_type->packed()) - cerr << " " << use_type->packed_width() << " bit packed struct "; - else - cerr << " struct <> "; - cerr << name_; - cerr << " in scope " << scope_path(scope) << endl; - } - - sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); - - } else if (enum_type_t*enum_type = dynamic_cast(set_data_type_)) { - list::const_iterator sample_name = enum_type->names->begin(); - const netenum_t*use_enum = base_type_scope->find_enumeration_for_name(des, sample_name->name); - - if (debug_elaborate) { - cerr << get_fileline() << ": PWire::elaborate_sig: " - << "Create signal " << wtype - << " enumeration " - << name_ << " in scope " << scope_path(scope) - << " with packed_dimensions=" << packed_dimensions - << " and packed_width=" << use_enum->packed_width() << endl; - } - - ivl_assert(*this, packed_dimensions.empty()); - sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum); - - - } else if (netdarray) { + if (netdarray) { if (debug_elaborate) { cerr << get_fileline() << ": PWire::elaborate_sig: " @@ -1272,43 +1227,22 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const ivl_assert(*this, unpacked_dimensions.empty()); sig = new NetNet(scope, name_, wtype, netdarray); - } else if (dynamic_cast(set_data_type_)) { + } else if (dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_)) { - // Signal declared as: string foo; + ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); if (debug_elaborate) { - cerr << get_fileline() << ": " << __func__ << ": " - << "Create signal " << wtype - << " string " - << name_ << " in scope " << scope_path(scope) - << endl; - } - - sig = new NetNet(scope, name_, wtype, unpacked_dimensions, - &netstring_t::type_string); - - } else if (parray_type_t*parray_type = dynamic_cast(set_data_type_)) { - // The pform gives us a parray_type_t for packed arrays - // that show up in type definitions. This can be handled - // a lot like packed dimensions from other means. - - // The trick here is that the parray type has an - // arbitrary sub-type, and not just a scalar bit... - ivl_type_t tmp_type = parray_type->elaborate_type(des, scope); - const netparray_t*use_type = dynamic_cast(tmp_type); - // Should not be getting packed dimensions other than - // through the parray type declaration. - ivl_assert(*this, packed_dimensions.empty()); - - if (debug_elaborate) { - cerr << get_fileline() << ": debug: Create signal " << wtype - << " parray=" << use_type->static_dimensions() + cerr << get_fileline() << ": debug: Create signal " + << wtype << " " << *set_data_type_ << " " << name_ << unpacked_dimensions << " in scope " << scope_path(scope) << endl; } + ivl_assert(*this, packed_dimensions.empty()); sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); - - } else { if (debug_elaborate) { cerr << get_fileline() << ": PWire::elaborate_sig: " From 5cc825f45d9bae1e47f36bc523c9560c35eb3b1d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Fri, 4 Mar 2022 09:12:50 +0100 Subject: [PATCH 3/5] Support dynamic arrays and queues of packed arrays Currently only dynamic arrays and queues of atom2 and vector types are supported. Add support for packed arrays. Since these three types are essentially handled the same internally supporting this only requires to allow to elaborate a packed array base type. Factor out type elaboration into a helper function that can be shared between the elaboration of the base type of a dynamic array or queue and the type for other signals. This gives consistent behavior and will also make it easier to support additional base types for dynamic arrays or queues. Note that it is not yet possible to index elements of packed array dynamic arrays or queues. But neither is it possible to do a bit select for vector or atom2 type dynamic arrays or queues yet. Supporting this needs some additional work. There is one test that declares a queue of a struct type, but doesn't use it since it is not supported. With this change a error will generated when trying to declare a queue of a struct. So update that test to not declare the variable so it does not fail. Signed-off-by: Lars-Peter Clausen --- Makefile.in | 1 - PWire.h | 7 ++ elab_sig.cc | 115 +++++++++++++++++----------- ivtest/ivltests/unp_array_typedef.v | 3 +- make_ivl_type.cc | 47 ------------ 5 files changed, 78 insertions(+), 95 deletions(-) delete mode 100644 make_ivl_type.cc diff --git a/Makefile.in b/Makefile.in index 3f0c00377..68e54b744 100644 --- a/Makefile.in +++ b/Makefile.in @@ -111,7 +111,6 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \ load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \ net_design.o netclass.o netdarray.o \ netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \ - make_ivl_type.o \ net_event.o net_expr.o net_func.o \ net_func_eval.o net_link.o net_modulo.o \ net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \ diff --git a/PWire.h b/PWire.h index f4b792538..dbf27dffd 100644 --- a/PWire.h +++ b/PWire.h @@ -130,6 +130,13 @@ class PWire : public PNamedItem { private: // not implemented PWire(const PWire&); PWire& operator= (const PWire&); + + ivl_type_t elaborate_type(Design*des, NetScope*scope, + const std::vector&packed_dimensions) const; + ivl_type_t elaborate_darray_type(Design*des, NetScope*scope, + const char *darray_type, + const std::vector&packed_dimensions) + const; }; #endif /* IVL_PWire_H */ diff --git a/elab_sig.cc b/elab_sig.cc index a84583a39..66275b46b 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -934,6 +934,64 @@ bool test_ranges_eeq(const vector&lef, const vector&rig) return true; } +ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope, + const std::vector&packed_dimensions) const +{ + if (dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_) || + dynamic_cast(set_data_type_)) { + ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); + ivl_assert(*this, packed_dimensions.empty()); + return use_type; + } + + // Fallback method. Create vector type. + + ivl_variable_type_t use_data_type = data_type_; + if (use_data_type == IVL_VT_NO_TYPE) { + use_data_type = IVL_VT_LOGIC; + if (debug_elaborate) { + cerr << get_fileline() << ": PWire::elaborate_sig: " + << "Signal " << name_ + << " in scope " << scope_path(scope) + << " defaults to data type " << use_data_type << endl; + } + } + + ivl_assert(*this, use_data_type == IVL_VT_LOGIC || + use_data_type == IVL_VT_BOOL || + use_data_type == IVL_VT_REAL); + + netvector_t*vec = new netvector_t(packed_dimensions, use_data_type); + vec->set_signed(get_signed()); + vec->set_isint(get_isint()); + + return vec; +} + +ivl_type_t PWire::elaborate_darray_type(Design*des, NetScope*scope, + const char *darray_type, + const std::vector&packed_dimensions) + const +{ + ivl_type_t type = elaborate_type(des, scope, packed_dimensions); + + if (dynamic_cast(type) || + dynamic_cast(type) || + dynamic_cast(type) || + dynamic_cast(type)) + return type; + + cerr << get_fileline() << ": Sorry: " + << darray_type << " of type `" << *type + << "` is not yet supported." << endl; + des->errors++; + + // Return something to recover + return new netvector_t(IVL_VT_LOGIC); +} /* * Elaborate a source wire. The "wire" is the declaration of wires, @@ -1100,19 +1158,21 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const // dimensions, then turn this into a dynamic array and // put all the packed dimensions there. if (use_lidx==0 && use_ridx==0) { - ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions, - get_signed()); + ivl_type_t base_type = elaborate_darray_type(des, scope, + "Dynamic array", + packed_dimensions); packed_dimensions.clear(); ivl_assert(*this, netdarray==0); - netdarray = new netdarray_t(vec); + netdarray = new netdarray_t(base_type); continue; } // Special case: Detect the mark for a QUEUE // declaration, which is the dimensions [null:max_idx]. if (dynamic_cast(use_lidx)) { - ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions, - get_signed()); + ivl_type_t base_type = elaborate_darray_type(des, scope, + "Queue", + packed_dimensions); packed_dimensions.clear(); ivl_assert(*this, netdarray==0); long max_idx; @@ -1144,7 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const } } } else max_idx = -1; - netdarray = new netqueue_t(vec, max_idx); + netdarray = new netqueue_t(base_type, max_idx); continue; } @@ -1227,13 +1287,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const ivl_assert(*this, unpacked_dimensions.empty()); sig = new NetNet(scope, name_, wtype, netdarray); - } else if (dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_) || - dynamic_cast(set_data_type_)) { + } else { + ivl_type_t use_type = elaborate_type(des, scope, + packed_dimensions); - ivl_type_t use_type = set_data_type_->elaborate_type(des, scope); if (debug_elaborate) { cerr << get_fileline() << ": debug: Create signal " << wtype << " " << *set_data_type_ @@ -1241,41 +1298,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const << " in scope " << scope_path(scope) << endl; } - ivl_assert(*this, packed_dimensions.empty()); sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type); - } else { - if (debug_elaborate) { - cerr << get_fileline() << ": PWire::elaborate_sig: " - << "Create vector signal " << wtype - << " data_type=" << data_type_; - if (!packed_dimensions.empty()) { - cerr << " " << packed_dimensions; - } - cerr << " " << name_ << unpacked_dimensions; - cerr << " in scope " << scope_path(scope) << endl; - } - - ivl_variable_type_t use_data_type = data_type_; - if (use_data_type == IVL_VT_NO_TYPE) { - use_data_type = IVL_VT_LOGIC; - if (debug_elaborate) { - cerr << get_fileline() << ": PWire::elaborate_sig: " - << "Signal " << name_ - << " in scope " << scope_path(scope) - << " defaults to data type " << use_data_type << endl; - } - } - - ivl_assert(*this, use_data_type == IVL_VT_LOGIC || - use_data_type == IVL_VT_BOOL || - use_data_type == IVL_VT_REAL); - - netvector_t*vec = new netvector_t(packed_dimensions, use_data_type); - vec->set_signed(get_signed()); - vec->set_isint(get_isint()); - packed_dimensions.clear(); - sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec); - } if (wtype == NetNet::WIRE) sig->devirtualize_pins(); diff --git a/ivtest/ivltests/unp_array_typedef.v b/ivtest/ivltests/unp_array_typedef.v index bbb0377a5..73c3c3311 100644 --- a/ivtest/ivltests/unp_array_typedef.v +++ b/ivtest/ivltests/unp_array_typedef.v @@ -43,7 +43,8 @@ module unp_array_typedef(); real_unparray real_unparr; int_darray int_darr; int_unparray int_unparr; - word_darray word_darr; + // TODO at the moment dynamic arrays of struct are not supported + // word_darray word_darr; word_unparray word_unparr; initial begin diff --git a/make_ivl_type.cc b/make_ivl_type.cc deleted file mode 100644 index 963a5eace..000000000 --- a/make_ivl_type.cc +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) - * - * This source code is free software; you can redistribute it - * and/or modify it in source code form under the terms of the GNU - * General Public License as published by the Free Software - * Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -# include "nettypes.h" -# include "netscalar.h" -# include "netvector.h" - -ivl_type_t make_ivl_type(ivl_variable_type_t vt, - const std::vector&packed_dimensions, - bool signed_flag, bool isint_flag) -{ - netvector_t*vec; - - if (packed_dimensions.size() > 0) { - vec = new netvector_t(packed_dimensions, vt); - vec->set_signed(signed_flag); - return vec; - } - - switch (vt) { - case IVL_VT_REAL: - return &netreal_t::type_real; - case IVL_VT_STRING: - return &netstring_t::type_string; - default: - vec = new netvector_t(packed_dimensions, vt); - vec->set_signed(signed_flag); - vec->set_isint(isint_flag); - return vec; - } -} From babfacee9adc29a23374da00f910a2975ca74337 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 12 Mar 2022 13:35:41 +0100 Subject: [PATCH 4/5] Add regression test for dynamic arrays of packed arrays Check that it is possible to declare a dynamic array of a packed array type. The test is identical to the tests for the other supported dynamic array types. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_darray7.v | 54 ++++++++++++++++++++++++++++++++++++ ivtest/regress-sv.list | 1 + ivtest/regress-vlog95.list | 1 + 3 files changed, 56 insertions(+) create mode 100644 ivtest/ivltests/sv_darray7.v diff --git a/ivtest/ivltests/sv_darray7.v b/ivtest/ivltests/sv_darray7.v new file mode 100644 index 000000000..d62cf0732 --- /dev/null +++ b/ivtest/ivltests/sv_darray7.v @@ -0,0 +1,54 @@ +// Check that dynamic arrays of packed array types are supported + +module main; + + typedef reg [3:0] T1; + typedef T1 [7:0] T2; + + T2 foo[]; + int idx; + + initial begin + if (foo.size() != 0) begin + $display("FAILED -- foo.size()=%0d, s.b. 0", foo.size()); + $finish; + end + + foo = new[10]; + if (foo.size() != 10) begin + $display("FAILED -- foo.size()=%0d, s.b. 10", foo.size()); + $finish; + end + + for (idx = 0 ; idx < foo.size() ; idx += 1) begin + foo[idx] = idx; + end + + $display("foo[7] = %d", foo[7]); + if (foo[7] != 7) begin + $display("FAILED -- foo[7] = %0d (s.b. 7)", foo[7]); + $finish; + end + + $display("foo[9] = %d", foo[9]); + if (foo[9] != 9) begin + $display("FAILED -- foo[9] = %0d (s.b. 9)", foo[9]); + $finish; + end + + for (idx = 0 ; idx < 2*foo.size() ; idx += 1) begin + if (foo[idx%10] != (idx%10)) begin + $display("FAILED -- foo[%0d%%10] = %0d", idx, foo[idx%10]); + $finish; + end + end + + foo.delete(); + if (foo.size() != 0) begin + $display("FAILED -- foo.size()=%0d (after delete: s.b. 0)", foo.size()); + $finish; + end + + $display("PASSED"); + end +endmodule // main diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index ee99c29f7..d845c44e1 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -452,6 +452,7 @@ sv_darray4 normal,-g2009 ivltests sv_darray5 normal,-g2009 ivltests sv_darray5b normal,-g2009 ivltests sv_darray6 normal,-g2009 ivltests +sv_darray7 normal,-g2009 ivltests sv_darray_args1 normal,-g2009 ivltests sv_darray_args2 normal,-g2009 ivltests sv_darray_args2b normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index a03185273..aa574bc63 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -312,6 +312,7 @@ sv_darray4 CE,-g2009,-pallowsigned=1 ivltests sv_darray5 CE,-g2009,-pallowsigned=1 ivltests sv_darray5b CE,-g2009,-pallowsigned=1 ivltests sv_darray6 CE,-g2009,-pallowsigned=1 ivltests # Also string +sv_darray7 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args1 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args2 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args2b CE,-g2009,-pallowsigned=1 ivltests From 1a10abeae7e806eaa19f5b681a314a425c09bdf8 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 12 Mar 2022 12:55:20 +0100 Subject: [PATCH 5/5] Add regression tests for queue of packed arrays Check that queues of packed arrays are supported. These tests are identical to the existing queue tests for other data type, just that the data type is a packed array. Signed-off-by: Lars-Peter Clausen --- ivtest/gold/sv_queue_parray.gold | 16 ++ ivtest/gold/sv_queue_parray_bounded.gold | 9 + ivtest/gold/sv_queue_parray_fail.gold | 10 ++ ivtest/ivltests/sv_queue_parray.v | 195 ++++++++++++++++++++++ ivtest/ivltests/sv_queue_parray_bounded.v | 80 +++++++++ ivtest/ivltests/sv_queue_parray_fail.v | 19 +++ ivtest/regress-sv.list | 3 + ivtest/regress-vlog95.list | 3 + 8 files changed, 335 insertions(+) create mode 100644 ivtest/gold/sv_queue_parray.gold create mode 100644 ivtest/gold/sv_queue_parray_bounded.gold create mode 100644 ivtest/gold/sv_queue_parray_fail.gold create mode 100644 ivtest/ivltests/sv_queue_parray.v create mode 100644 ivtest/ivltests/sv_queue_parray_bounded.v create mode 100644 ivtest/ivltests/sv_queue_parray_fail.v diff --git a/ivtest/gold/sv_queue_parray.gold b/ivtest/gold/sv_queue_parray.gold new file mode 100644 index 000000000..7cedbd4c8 --- /dev/null +++ b/ivtest/gold/sv_queue_parray.gold @@ -0,0 +1,16 @@ +./ivltests/sv_queue_parray.v:35: Warning: skipping delete(0) on empty queue. +./ivltests/sv_queue_parray.v:39: Warning: pop_front() on empty queue. +./ivltests/sv_queue_parray.v:45: Warning: pop_back() on empty queue. +./ivltests/sv_queue_parray.v:56: Warning: skipping out of range delete(3) on queue of size 3. +./ivltests/sv_queue_parray.v:57: Warning: skipping queue delete() with negative index. +./ivltests/sv_queue_parray.v:58: Warning: skipping queue delete() with undefined index. +./ivltests/sv_queue_parray.v:132: Warning: cannot assign to a negative queue index (-1). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:133: Warning: cannot assign to an undefined queue index. 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:134: Warning: assigning to queue[4] is outside of size (3). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:137: Warning: cannot assign to a negative queue index (-1). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:139: Warning: cannot assign to an undefined queue index. 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:141: Warning: assigning to queue[4] is outside of size (3). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:153: Warning: cannot insert at a negative queue index (-1). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:154: Warning: cannot insert at an undefined queue index. 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray.v:155: Warning: inserting to queue[5] is outside of size (4). 40'b0000000000000000000000000000000000001010 was not added. +PASSED diff --git a/ivtest/gold/sv_queue_parray_bounded.gold b/ivtest/gold/sv_queue_parray_bounded.gold new file mode 100644 index 000000000..9de22b87d --- /dev/null +++ b/ivtest/gold/sv_queue_parray_bounded.gold @@ -0,0 +1,9 @@ +./ivltests/sv_queue_parray_bounded.v:61: Warning: Array pattern assignment has more elements (4) than bounded queue 'q_tst' supports (3). + Only using first 3 elements. +./ivltests/sv_queue_parray_bounded.v:38: Warning: push_back(40'b0000000000000000000000000000000001100100) skipped for already full bounded queue [3]. +./ivltests/sv_queue_parray_bounded.v:45: Warning: push_front(40'b0000000000000000000000000000000000000101) removed 40'b0000000000000000000000000000000000000011 from already full bounded queue [3]. +./ivltests/sv_queue_parray_bounded.v:46: Warning: assigning to queue[3] is outside bound (3). 40'b0000000000000000000000000000000000000011 was not added. +./ivltests/sv_queue_parray_bounded.v:53: Warning: inserting to queue[3] is outside bound (3). 40'b0000000000000000000000000000000000001010 was not added. +./ivltests/sv_queue_parray_bounded.v:54: Warning: insert(1, 40'b0000000000000000000000000000000000000010) removed 40'b0000000000000000000000000000000000000010 from already full bounded queue [3]. +./ivltests/sv_queue_parray_bounded.v:69: Warning: queue is bounded to have at most 3 elements, source has 4 elements. +PASSED diff --git a/ivtest/gold/sv_queue_parray_fail.gold b/ivtest/gold/sv_queue_parray_fail.gold new file mode 100644 index 000000000..8bf76072b --- /dev/null +++ b/ivtest/gold/sv_queue_parray_fail.gold @@ -0,0 +1,10 @@ +./ivltests/sv_queue_parray_fail.v:7: error: queue 'q_vec1' bound must be positive (-1)! +./ivltests/sv_queue_parray_fail.v:8: error: queue 'q_vec2' bound is undefined! +./ivltests/sv_queue_parray_fail.v:9: error: A reference to a wire or reg (`bound') is not allowed in a constant expression. +./ivltests/sv_queue_parray_fail.v:9: error: queue 'q_vec3' bound must be a constant! +./ivltests/sv_queue_parray_fail.v:12: error: size() method takes no arguments +./ivltests/sv_queue_parray_fail.v:13: error: pop_front() method takes no arguments +./ivltests/sv_queue_parray_fail.v:14: error: pop_back() method takes no arguments +./ivltests/sv_queue_parray_fail.v:15: error: push_front() method requires a single argument. +./ivltests/sv_queue_parray_fail.v:16: error: push_back() method requires a single argument. +9 error(s) during elaboration. diff --git a/ivtest/ivltests/sv_queue_parray.v b/ivtest/ivltests/sv_queue_parray.v new file mode 100644 index 000000000..a581a5910 --- /dev/null +++ b/ivtest/ivltests/sv_queue_parray.v @@ -0,0 +1,195 @@ +module top; + typedef reg [4:0] T1; + typedef T1 [7:0] T2; + + T2 q_tst [$]; + T2 q_tmp [$]; + T2 elem; + integer idx; + bit passed; + + task automatic check_size(integer size, + string fname, + integer lineno); + if (q_tst.size !== size) begin + $display("%s:%0d: Failed: queue size != %0d (%0d)", + fname, lineno, size, q_tst.size); + passed = 1'b0; + end + endtask + + task automatic check_idx_value(integer idx, + T2 expected, + string fname, + integer lineno); + if (q_tst[idx] != expected) begin + $display("%s:%0d: Failed: element [%0d] != %0d (%0d)", + fname, lineno, idx, expected, q_tst[idx]); + passed = 1'b0; + end + endtask + + initial begin + passed = 1'b1; + + q_tst.delete(0); // Warning: skip delete on an empty queue + check_size(0, `__FILE__, `__LINE__); + check_idx_value(0, 0, `__FILE__, `__LINE__); + + elem = q_tst.pop_front(); // Warning: cannot pop_front() an empty queue + if (elem !== 'X) begin + $display("Failed: pop_front() != 'X (%0d)", elem); + passed = 1'b0; + end + + elem = q_tst.pop_back(); // Warning: cannot pop_back() an empty queue + if (elem !== 'X) begin + $display("Failed: pop_back() != 'X (%0d)", elem); + passed = 1'b0; + end + + q_tst.push_back(2); + q_tst.push_front(1); + q_tst.push_back(3); + q_tst.push_back(100); + q_tst.delete(3); // Should $ work here? + q_tst.delete(3); // Warning: skip an out of range delete() + q_tst.delete(-1); // Warning: skip delete with negative index + q_tst.delete('X); // Warning: skip delete with undefined index + + check_size(3, `__FILE__, `__LINE__); + + if (q_tst[0] !== 1) begin + $display("Failed: element [0] != 1 (%0d)", q_tst[0]); + passed = 1'b0; + end + + if (q_tst[1] !== 2) begin + $display("Failed: element [1] != 2 (%0d)", q_tst[1]); + passed = 1'b0; + end + + if (q_tst[2] !== 3) begin + $display("Failed: element [2] != 3 (%0d)", q_tst[2]); + passed = 1'b0; + end + + if (q_tst[3] !== 'X) begin + $display("Failed: element [3] != 'X (%0d)", q_tst[3]); + passed = 1'b0; + end + + if (q_tst[-1] !== 'X) begin + $display("Failed: element [-1] != 'X (%0d)", q_tst[-1]); + passed = 1'b0; + end + + if (q_tst['X] !== 'X) begin + $display("Failed: element ['X] != 'X (%0d)", q_tst['X]); + passed = 1'b0; + end + + check_idx_value(-1, 0.0, `__FILE__, `__LINE__); + check_idx_value('X, 0.0, `__FILE__, `__LINE__); + + elem = q_tst.pop_front(); + if (elem !== 1) begin + $display("Failed: element pop_front() != 1 (%0d)", elem); + passed = 1'b0; + end + + elem = q_tst.pop_back(); + if (elem !== 3) begin + $display("Failed: element pop_back() != 3 (%0d)", elem); + passed = 1'b0; + end + + check_size(1, `__FILE__, `__LINE__); + + if ((q_tst[0] !== q_tst[$]) || (q_tst[0] !== 2)) begin + $display("Failed: q_tst[0](%0d) != q_tst[$](%0d) != 2", + q_tst[0], q_tst[$]); + passed = 1'b0; + end + + q_tst.delete(); + + check_size(0, `__FILE__, `__LINE__); + + q_tst.push_front(5); + q_tst.push_front(100); + q_tst.push_back(100); + elem = q_tst.pop_back; + elem = q_tst.pop_front; + + check_size(1, `__FILE__, `__LINE__); + check_idx_value(0, 5, `__FILE__, `__LINE__); + + q_tst[0] = 1; + q_tst[1] = 3; + q_tst[1] = 2; + q_tst[2] = 3; + q_tst[-1] = 10; // Warning: will not be added (negative index) + q_tst['X] = 10; // Warning: will not be added (undefined index) + q_tst[4] = 10; // Warning: will not be added (out of range index) + + idx = -1; + q_tst[idx] = 10; // Warning: will not be added (negative index) + idx = 3'b0x1; + q_tst[idx] = 10; // Warning: will not be added (undefined index) + idx = 4; + q_tst[idx] = 10; // Warning: will not be added (out of range index) + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 1, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 3, `__FILE__, `__LINE__); + + q_tst.delete(); + q_tst[0] = 2; + q_tst.insert(1, 4); + q_tst.insert(0, 1); + q_tst.insert(2, 3); + q_tst.insert(-1, 10); // Warning: will not be added (negative index) + q_tst.insert('X, 10); // Warning: will not be added (undefined index) + q_tst.insert(5, 10); // Warning: will not be added (out of range index) + + check_size(4, `__FILE__, `__LINE__); + check_idx_value(0, 1, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 3, `__FILE__, `__LINE__); + check_idx_value(3, 4, `__FILE__, `__LINE__); + + q_tst = '{3, 2, 1}; + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 3, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 1, `__FILE__, `__LINE__); + + q_tmp = '{1, 2}; + q_tst = q_tmp; + q_tmp[0] = 3; + q_tmp[2] = 1; + + check_size(2, `__FILE__, `__LINE__); + check_idx_value(0, 1.0, `__FILE__, `__LINE__); + check_idx_value(1, 2.0, `__FILE__, `__LINE__); + + q_tst[2] = 3; + check_size(3, `__FILE__, `__LINE__); + check_idx_value(2, 3, `__FILE__, `__LINE__); + + q_tst = {1, 2}; + check_size(2, `__FILE__, `__LINE__); + check_idx_value(0, 1, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + + q_tst = '{}; + + check_size(0, `__FILE__, `__LINE__); + + if (passed) $display("PASSED"); + + end +endmodule : top diff --git a/ivtest/ivltests/sv_queue_parray_bounded.v b/ivtest/ivltests/sv_queue_parray_bounded.v new file mode 100644 index 000000000..a2ba3751b --- /dev/null +++ b/ivtest/ivltests/sv_queue_parray_bounded.v @@ -0,0 +1,80 @@ +module top; + typedef reg [4:0] T1; + typedef T1 [7:0] T2; + + T2 q_tst [$:2]; + T2 q_tmp [$]; + bit passed; + + task automatic check_size(integer size, + string fname, + integer lineno); + if (q_tst.size !== size) begin + $display("%s:%0d: Failed: queue size != %0d (%0d)", + fname, lineno, size, q_tst.size); + passed = 1'b0; + end + endtask + + task automatic check_idx_value(integer idx, + T2 expected, + string fname, + integer lineno); + if (q_tst[idx] != expected) begin + $display("%s:%0d: Failed: element [%0d] != %0d (%0d)", + fname, lineno, idx, expected, q_tst[idx]); + passed = 1'b0; + end + endtask + + initial begin + passed = 1'b1; + + check_size(0, `__FILE__, `__LINE__); + + q_tst.push_back(2); + q_tst.push_front(1); + q_tst.push_back(3); + q_tst.push_back(100); // Warning: item not added. + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 1, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 3, `__FILE__, `__LINE__); + + q_tst.push_front(5); // Warning: back item removed. + q_tst[3] = 3; // Warning: item not added. + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 5, `__FILE__, `__LINE__); + check_idx_value(1, 1, `__FILE__, `__LINE__); + check_idx_value(2, 2, `__FILE__, `__LINE__); + + q_tst.insert(3, 10); // Warning: item not added. + q_tst.insert(1, 2); // Warning: back item removed. + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 5, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 1, `__FILE__, `__LINE__); + + q_tst = '{1, 2, 3, 4}; // Warning: items not added. + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 1, `__FILE__, `__LINE__); + check_idx_value(1, 2, `__FILE__, `__LINE__); + check_idx_value(2, 3, `__FILE__, `__LINE__); + + q_tmp = '{4, 3, 2, 1}; + q_tst = q_tmp; // Warning not all items copied + q_tmp[0] = 5; + + check_size(3, `__FILE__, `__LINE__); + check_idx_value(0, 4, `__FILE__, `__LINE__); + check_idx_value(1, 3, `__FILE__, `__LINE__); + check_idx_value(2, 2, `__FILE__, `__LINE__); + + if (passed) $display("PASSED"); + + end +endmodule : top diff --git a/ivtest/ivltests/sv_queue_parray_fail.v b/ivtest/ivltests/sv_queue_parray_fail.v new file mode 100644 index 000000000..2d5c046d1 --- /dev/null +++ b/ivtest/ivltests/sv_queue_parray_fail.v @@ -0,0 +1,19 @@ +module top; + typedef reg [4:0] T1; + typedef T1 [7:0] T2; + + int bound = 2; + T2 q_vec [$]; + T2 q_vec1 [$:-1]; + T2 q_vec2 [$:'X]; + T2 q_vec3 [$:bound]; + + initial begin + $display(q_vec.size(1)); + $display(q_vec.pop_front(1)); + $display(q_vec.pop_back(1)); + q_vec.push_front(1, 2); + q_vec.push_back(1, 2); + $display("FAILED"); + end +endmodule : top diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index d845c44e1..3bec48dc5 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -514,6 +514,9 @@ sv_port_default14 CE,-g2009 ivltests sv_queue1 normal,-g2009 ivltests sv_queue2 normal,-g2009 ivltests sv_queue3 normal,-g2009 ivltests +sv_queue_parray normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray.gold +sv_queue_parray_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_parray_bounded.gold +sv_queue_parray_fail CE,-g2009 ivltests gold=sv_queue_parray_fail.gold sv_queue_real normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real.gold sv_queue_real_bounded normal,-g2009,-pfileline=1 ivltests gold=sv_queue_real_bounded.gold sv_queue_real_fail CE,-g2009 ivltests gold=sv_queue_real_fail.gold diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index aa574bc63..210253f2e 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -588,6 +588,9 @@ sv_queue_string_fail CE,-g2009 ivltests sv_queue_vec CE,-g2009,-pallowsigned=1 ivltests sv_queue_vec_bounded CE,-g2009,-pallowsigned=1 ivltests sv_queue_vec_fail CE,-g2009,-pallowsigned=1 ivltests +sv_queue_parray CE,-g2009, ivltests +sv_queue_parray_bounded CE,-g2009, ivltests +sv_queue_parray_fail CE,-g2009, ivltests test_forgen CE,-g2009,ivltests/forgen.vhd ivltests test_gxor CE,-g2009,-pallowsigned=1,ivltests/gxor.vhd ivltests test_varray1 CE,-g2009,-pallowsigned=1,ivltests/varray1.vhd ivltests