From f831d7d76f2c316cf7a2e60f8b44045a2f3b8c23 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Oct 2022 12:46:22 +0200 Subject: [PATCH 1/5] Add `ivl_type_packed_width()` API The C++ API for `ivl_type_t` has a method to query the total width of a packed type. This is currently not exported to the C API and the tgt-vvp backend implements similar functionality by querying the individual dimensions of a type. Export the `packed_width()` method to the C API. This allows to remove the custom implementation from the tgt-vvp backend. Signed-off-by: Lars-Peter Clausen --- ivl.def | 1 + ivl_target.h | 4 ++++ t-dll-api.cc | 5 +++++ tgt-vvp/eval_object.c | 4 ++-- tgt-vvp/stmt_assign.c | 25 +++++-------------------- tgt-vvp/vvp_priv.h | 5 ----- tgt-vvp/vvp_process.c | 4 ++-- 7 files changed, 19 insertions(+), 29 deletions(-) diff --git a/ivl.def b/ivl.def index 7c781eed4..81d9ae853 100644 --- a/ivl.def +++ b/ivl.def @@ -328,6 +328,7 @@ ivl_type_name ivl_type_packed_dimensions ivl_type_packed_lsb ivl_type_packed_msb +ivl_type_packed_width ivl_type_prop_name ivl_type_prop_type ivl_type_properties diff --git a/ivl_target.h b/ivl_target.h index 6afde3c27..fdbb9a8f6 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -2348,6 +2348,9 @@ extern unsigned ivl_switch_lineno(ivl_switch_t net); * Return the type of the element of an array. This is only valid * for array types. * + * ivl_type_packed_width + * Returns the total width of all packed dimensions. + * * ivl_type_signed * Return TRUE if the type represents a signed packed vector or * signed atomic type, and FALSE otherwise. @@ -2361,6 +2364,7 @@ extern ivl_type_t ivl_type_element(ivl_type_t net); extern unsigned ivl_type_packed_dimensions(ivl_type_t net); extern int ivl_type_packed_lsb(ivl_type_t net, unsigned dim); extern int ivl_type_packed_msb(ivl_type_t net, unsigned dim); +extern unsigned ivl_type_packed_width(ivl_type_t net); extern int ivl_type_signed(ivl_type_t net); extern const char* ivl_type_name(ivl_type_t net); extern int ivl_type_properties(ivl_type_t net); diff --git a/t-dll-api.cc b/t-dll-api.cc index c25ab938d..2b074722e 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -3202,6 +3202,11 @@ extern "C" ivl_type_t ivl_type_element(ivl_type_t net) return 0; } +extern "C" unsigned ivl_type_packed_width(ivl_type_t net) +{ + return net->packed_width(); +} + extern "C" unsigned ivl_type_packed_dimensions(ivl_type_t net) { assert(net); diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index c38b432bd..a825d6045 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -28,7 +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)) { - wid = width_of_packed_type(element_type); + wid = ivl_type_packed_width(element_type); signed_char = ivl_type_signed(element_type) ? "s" : ""; } else { // REAL or STRING objects are not packable. @@ -133,7 +133,7 @@ static int eval_darray_new(ivl_expr_t ex) switch (ivl_type_base(element_type)) { case IVL_VT_BOOL: case IVL_VT_LOGIC: - wid = width_of_packed_type(element_type); + wid = ivl_type_packed_width(element_type); for (idx = 0 ; idx < cnt ; idx += 1) { draw_eval_vec4(init_expr); fprintf(vvp_out, " %%parti/%c %u, %ld, 6;\n", diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 3095fe1a9..1d1817d52 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -897,21 +897,6 @@ static int show_stmt_assign_sig_string(ivl_statement_t net) return 0; } -unsigned width_of_packed_type(ivl_type_t net) -{ - unsigned idx; - unsigned width = 1; - for (idx = 0 ; idx < ivl_type_packed_dimensions(net) ; idx += 1) { - int lsb = ivl_type_packed_lsb(net,idx); - int msb = ivl_type_packed_msb(net,idx); - if (lsb <= msb) - width *= msb - lsb + 1; - else - width *= lsb - msb + 1; - } - return width; -} - /* * This function handles the special case that we assign an array * pattern to a dynamic array. Handle this by assigning each @@ -934,9 +919,9 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net) #if 0 unsigned element_width = 1; if (ivl_type_base(element_type) == IVL_VT_BOOL) - element_width = width_of_packed_type(element_type); + element_width = ivl_type_packed_width(element_type); else if (ivl_type_base(element_type) == IVL_VT_LOGIC) - element_width = width_of_packed_type(element_type); + element_width = ivl_type_packed_width(element_type); #endif // FIXME: At the moment we reallocate the array space. @@ -1094,7 +1079,7 @@ static int show_stmt_assign_queue_pattern(ivl_signal_t var, ivl_expr_t rval, fprintf(vvp_out, " %%ix/load 3, %u, 0;\n", idx); fprintf(vvp_out, " %%flag_set/imm 4, 0;\n"); fprintf(vvp_out, " %%store/qdar/v v%p_0, %d, %u;\n", var, max_idx, - width_of_packed_type(element_type)); + ivl_type_packed_width(element_type)); break; case IVL_VT_REAL: @@ -1181,7 +1166,7 @@ static int show_stmt_assign_sig_queue(ivl_statement_t net) index register 3. */ draw_eval_expr_into_integer(mux, 3); fprintf(vvp_out, " %%store/qdar/v v%p_0, %d, %u;\n", var, idx, - width_of_packed_type(element_type)); + ivl_type_packed_width(element_type)); } else if (ivl_expr_type(rval) == IVL_EX_ARRAY_PATTERN) { /* There is no l-value mux, but the r-value is an array @@ -1202,7 +1187,7 @@ static int show_stmt_assign_sig_queue(ivl_statement_t net) assert(ivl_type_base(element_type) == IVL_VT_BOOL || ivl_type_base(element_type) == IVL_VT_LOGIC); fprintf(vvp_out, " %%store/qobj/v v%p_0, %d, %u;\n", - var, idx, width_of_packed_type(element_type)); + var, idx, ivl_type_packed_width(element_type)); } } clr_word(idx); diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 09746855d..aadec5512 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -80,11 +80,6 @@ extern const char* vvp_signal_label(ivl_signal_t sig); extern unsigned width_of_nexus(ivl_nexus_t nex); extern ivl_variable_type_t data_type_of_nexus(ivl_nexus_t nex); -/* - * Calculate the width (in bits) of a packed type. - */ -extern unsigned width_of_packed_type(ivl_type_t net); - extern int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr); /* diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 385e54fba..11dd7a596 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1847,7 +1847,7 @@ static int show_insert_method(ivl_statement_t net) draw_eval_vec4(parm2); fprintf(vvp_out, " %%qinsert/v v%p_0, %d, %u;\n", var, idx, - width_of_packed_type(element_type)); + ivl_type_packed_width(element_type)); break; } return 0; @@ -1897,7 +1897,7 @@ static int show_push_frontback_method(ivl_statement_t net, bool is_front) draw_eval_vec4(parm1); fprintf(vvp_out, " %%store/%s/v v%p_0, %d, %u;\n", type_code, var, idx, - width_of_packed_type(element_type)); + ivl_type_packed_width(element_type)); break; } clr_word(idx); From d4765e33542690b6019cebe9efb4de20d1e23f13 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 8 Oct 2022 13:08:59 +0200 Subject: [PATCH 2/5] Don't implement `packed_width()` for dynamic array types The `netdarray_t` type implements the `packed_width()` method by returning the packed width of the element type. It is the only non-packed type that implements the method. This triggers an assert in the vlog95 backend for tasks with dynamic array typed parameters. And while the vlog95 backend does not support dynamic array types it should not result in a crash, just an error message. The only place that relies on the behavior that the packed width of the element type is returned is in the vvp backend where variable declarations are generated. Update that code to query the packed width of the element type instead and then remove the `packed_width()` implementation for the `netdarray_t` type. This fixes the assert in the vlog95 backend. But it is also nicer from an architectural perspective as this brings the type in line with the other types in terms of behavior. Signed-off-by: Lars-Peter Clausen --- netdarray.h | 3 --- tgt-vvp/vvp_scope.c | 10 ++++++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/netdarray.h b/netdarray.h index 890995ad1..326f07d4c 100644 --- a/netdarray.h +++ b/netdarray.h @@ -36,9 +36,6 @@ class netdarray_t : public netarray_t { // A dynamic array may have a type that is signed. inline bool get_signed() const { return element_type()->get_signed(); } - // Use the packed width to pass the element width - long packed_width() const { return element_type()->packed_width(); } - // This is the base_type() of the element of the array. We // need this in some cases in order to get the base type of // the element, and not the IVL_VT_DARRAY of the array itself. diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 140a2020e..58b94c9be 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -540,15 +540,21 @@ static void draw_reg_in_scope(ivl_signal_t sig) swapped ? first: last, swapped ? last : first, msb, lsb); } else if (ivl_signal_data_type(sig) == IVL_VT_DARRAY) { + ivl_type_t var_type = ivl_signal_net_type(sig); + ivl_type_t element_type = ivl_type_element(var_type); + fprintf(vvp_out, "v%p_0 .var/darray \"%s\", %u;%s\n", sig, vvp_mangle_name(ivl_signal_basename(sig)), - ivl_signal_width(sig), + ivl_type_packed_width(element_type), ivl_signal_local(sig)? " Local signal" : ""); } else if (ivl_signal_data_type(sig) == IVL_VT_QUEUE) { + ivl_type_t var_type = ivl_signal_net_type(sig); + ivl_type_t element_type = ivl_type_element(var_type); + fprintf(vvp_out, "v%p_0 .var/queue \"%s\", %u;%s\n", sig, vvp_mangle_name(ivl_signal_basename(sig)), - ivl_signal_width(sig), + ivl_type_packed_width(element_type), ivl_signal_local(sig)? " Local signal" : ""); } else if (ivl_signal_data_type(sig) == IVL_VT_STRING) { From 5fa1aecd4f37d98bccb079220343b71d81da3bed Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 17 Sep 2022 19:37:47 +0200 Subject: [PATCH 3/5] Improve type compatibility checking for dynamic arrays and queues SystemVerilog defines different levels of type compatibility. * Matching * Equivalent * Assignment compatible * Cast compatible At the moment the `nettype_t` has only one type compatibility test. It is used to check assignment compatibility when assigning to a dynamic array, queue or class. The current implementation rejects a few cases that should allowed and allows a few cases that should be rejected. Dynamic arrays and queues are assignment compatible if their element types are compatible. And two packed types are equivalent if they are both 2-state or 4-state, both signed or unsigned and have the same packed with. In the current implementation the sign is not considered and instead of checking if the packed width is the same it checks that the dimensions are identical. Signed-off-by: Lars-Peter Clausen --- netdarray.cc | 26 +++++++++++++++----------- netdarray.h | 1 + netparray.cc | 10 ++++++++++ netparray.h | 3 +++ netqueue.cc | 16 ---------------- netqueue.h | 1 - netstruct.cc | 13 +++++++++++++ netstruct.h | 4 ++++ nettypes.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- nettypes.h | 17 ++++++++++++----- netvector.cc | 21 ++++++--------------- netvector.h | 1 + 12 files changed, 113 insertions(+), 50 deletions(-) diff --git a/netdarray.cc b/netdarray.cc index 9456c5da3..0e45cabe8 100644 --- a/netdarray.cc +++ b/netdarray.cc @@ -37,18 +37,22 @@ ivl_variable_type_t netdarray_t::base_type(void) const return IVL_VT_DARRAY; } -bool netdarray_t::test_compatibility(ivl_type_t that) const +bool netdarray_t::test_equivalence(ivl_type_t that) const { - ivl_type_t elem_type = 0; - - if (const netdarray_t*that_da = dynamic_cast(that)) - elem_type = that_da->element_type(); - - if (const netqueue_t*that_q = dynamic_cast(that)) - elem_type = that_q->element_type(); - - if (elem_type == 0) + // Queues and dynamic arrays are not equivalent, so check for the base + // type to make sure both are either dynamic array or queue. + if (base_type() != that->base_type()) return false; - return element_type()->type_compatible(elem_type); + return test_compatibility(that); +} + +bool netdarray_t::test_compatibility(ivl_type_t that) const +{ + // This will match both queues and dynamic arrays + const netdarray_t *that_da = dynamic_cast(that); + if (!that_da) + return false; + + return element_type()->type_equivalent(that_da->element_type()); } diff --git a/netdarray.h b/netdarray.h index 326f07d4c..8fc466e3b 100644 --- a/netdarray.h +++ b/netdarray.h @@ -49,6 +49,7 @@ class netdarray_t : public netarray_t { private: bool test_compatibility(ivl_type_t that) const; + bool test_equivalence(ivl_type_t that) const; }; #endif /* IVL_netdarray_H */ diff --git a/netparray.cc b/netparray.cc index 0c0181c0c..3e6e81050 100644 --- a/netparray.cc +++ b/netparray.cc @@ -68,6 +68,16 @@ vector netparray_t::slice_dimensions() const return res; } +bool netparray_t::test_compatibility(ivl_type_t that) const +{ + return packed_type_compatible(that); +} + +bool netparray_t::test_equivalence(ivl_type_t that) const +{ + return packed_types_equivalent(this, that); +} + netuarray_t::~netuarray_t() { } diff --git a/netparray.h b/netparray.h index 6be2da4d0..2e51bf80d 100644 --- a/netparray.h +++ b/netparray.h @@ -68,6 +68,9 @@ class netparray_t : public netsarray_t { long packed_width(void) const; std::vector slice_dimensions() const; + private: + bool test_compatibility(ivl_type_t that) const; + bool test_equivalence(ivl_type_t that) const; }; inline netparray_t::netparray_t(const std::vector&pd, diff --git a/netqueue.cc b/netqueue.cc index 01e4fd082..f04bc4f36 100644 --- a/netqueue.cc +++ b/netqueue.cc @@ -35,19 +35,3 @@ ivl_variable_type_t netqueue_t::base_type() const { return IVL_VT_QUEUE; } - -bool netqueue_t::test_compatibility(ivl_type_t that) const -{ - ivl_type_t elem_type = 0; - - if (const netqueue_t*that_q = dynamic_cast(that)) - elem_type = that_q->element_type(); - - if (const netdarray_t*that_da = dynamic_cast(that)) - elem_type = that_da->element_type(); - - if (elem_type == 0) - return false; - - return element_type()->type_compatible(elem_type); -} diff --git a/netqueue.h b/netqueue.h index 1e04e4535..826893390 100644 --- a/netqueue.h +++ b/netqueue.h @@ -43,7 +43,6 @@ class netqueue_t : public netdarray_t { std::ostream& debug_dump(std::ostream&) const; private: - bool test_compatibility(ivl_type_t that) const; long max_idx_; }; diff --git a/netstruct.cc b/netstruct.cc index e56b333a7..011a6540b 100644 --- a/netstruct.cc +++ b/netstruct.cc @@ -134,3 +134,16 @@ ivl_variable_type_t netstruct_t::base_type() const return IVL_VT_BOOL; } + +bool netstruct_t::test_compatibility(ivl_type_t that) const +{ + return packed_type_compatible(that); +} + +bool netstruct_t::test_equivalence(ivl_type_t that) const +{ + if (!packed_) + return this == that; + + return packed_types_equivalent(this, that); +} diff --git a/netstruct.h b/netstruct.h index 211796f06..b2ae1f96f 100644 --- a/netstruct.h +++ b/netstruct.h @@ -75,6 +75,10 @@ class netstruct_t : public LineInfo, public ivl_type_s { // IVL_VT_NO_TYPE if the record is not packed. ivl_variable_type_t base_type() const; + private: + bool test_compatibility(ivl_type_t that) const; + bool test_equivalence(ivl_type_t that) const; + private: bool union_; bool packed_; diff --git a/nettypes.cc b/nettypes.cc index d669bd9fe..ad2fe5860 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -18,6 +18,7 @@ */ # include "nettypes.h" +# include "netenum.h" # include # include @@ -69,9 +70,22 @@ bool ivl_type_s::type_compatible(ivl_type_t that) const return test_compatibility(that); } -bool ivl_type_s::test_compatibility(const ivl_type_s* /*that*/) const +bool ivl_type_s::test_compatibility(ivl_type_t that) const { - return false; + return test_equivalence(that); +} + +bool ivl_type_s::type_equivalent(ivl_type_t that) const +{ + if (this == that) + return true; + + return test_equivalence(that); +} + +bool ivl_type_s::test_equivalence(ivl_type_t) const +{ + return false; } netarray_t::~netarray_t() @@ -166,3 +180,35 @@ bool prefix_to_slice(const std::vector&dims, return true; } +bool packed_types_equivalent(ivl_type_t a, ivl_type_t b) +{ + if (!a->packed() || !b->packed()) + return false; + + if (a->base_type() != b->base_type()) + return false; + + if (a->packed_width() != b->packed_width()) + return false; + + if (a->get_signed() != b->get_signed()) + return false; + + // Special case, even though enums are packed they are not equivalent, + // they are only assignment compatible to other packed types + if (dynamic_cast(b)) + return false; + + return true; +} + +bool packed_type_compatible(ivl_type_t type) +{ + if (type->packed()) + return true; + + if (type->base_type() == IVL_VT_REAL) + return true; + + return false; +} diff --git a/nettypes.h b/nettypes.h index 0c26678dc..dc95eef46 100644 --- a/nettypes.h +++ b/nettypes.h @@ -47,17 +47,20 @@ class ivl_type_s { virtual bool get_signed() const; virtual bool get_scalar() const; - // Return true if "that" type is compatible with this - // type. Compatible means the types are essentially the same. + // Return true if "that" type is assignment compatible with this + // type. bool type_compatible(ivl_type_t that) const; + // Return true if "that" type is equivalent with this type as defined by + // the standard + bool type_equivalent(ivl_type_t that) const; virtual std::ostream& debug_dump(std::ostream&) const; private: - // The "type_compatible" method uses this virtual method to - // invoke type-specific tests of compatibility. This should - // only be called by the type_compatible method above. + // The "type_compatible" and "type_equivalent" methods uses this virtual + // method to invoke type-specific tests of compatibility. virtual bool test_compatibility(ivl_type_t that) const; + virtual bool test_equivalence(ivl_type_t that) const; }; /* @@ -162,4 +165,8 @@ extern bool prefix_to_slice(const std::vector&dims, const std::list&prefix, long sb, long&loff, unsigned long&lwid); + +extern bool packed_types_equivalent(ivl_type_t a, ivl_type_t b); +extern bool packed_type_compatible(ivl_type_t type); + #endif /* IVL_nettypes_H */ diff --git a/netvector.cc b/netvector.cc index f43dd839e..bc8d83d49 100644 --- a/netvector.cc +++ b/netvector.cc @@ -89,19 +89,10 @@ vector netvector_t::slice_dimensions() const bool netvector_t::test_compatibility(ivl_type_t that) const { - const netvector_t*that_st = dynamic_cast(that); - if (that_st == 0) - return false; - - if (type_ != that_st->type_) - return false; - if (packed_dims_.size() != that_st->packed_dims_.size()) - return false; - - for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) { - if (packed_dims_[idx] != that_st->packed_dims_[idx]) - return false; - } - - return true; + return packed_type_compatible(that); +} + +bool netvector_t::test_equivalence(const ivl_type_t that) const +{ + return packed_types_equivalent(this, that); } diff --git a/netvector.h b/netvector.h index 55a482ec8..1bf919cec 100644 --- a/netvector.h +++ b/netvector.h @@ -86,6 +86,7 @@ class netvector_t : public ivl_type_s { private: bool test_compatibility(ivl_type_t that) const; + bool test_equivalence(ivl_type_t that) const; private: std::vector packed_dims_; From e897e3ab5fe14ba1b4de3aa71d157846de833bdb Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 19 Sep 2022 13:05:34 +0200 Subject: [PATCH 4/5] Avoid confusing type compatibility error messages Icarus allows to pass a value of the element type as an argument to the dynamic new operator. To allow this the type compatibility check for dynamic arrays allows both the dynamic array type itself and also the element type. This currently leads to a confusing error message if neither type matches. The error message will say that the passed value is not compatible with the element type. E.g. ``` real d1[]; int d2[]; d1 = d2; ``` results in ``` error: the type of the variable 'd2' doesn't match the context type. : variable type=dynamic array of netvector_t:bool signed[31:0] : context type=real ``` This is slightly confusing. Change the way the error message is reported so that the context type is the type of the dynamic array and not the element. With the change the above results in ``` error: the type of the variable 'd2' doesn't match the context type. : variable type=dynamic array of netvector_t:bool signed[31:0] : context type=dynamic array of real ``` Signed-off-by: Lars-Peter Clausen --- elab_expr.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index c643f1466..9772b3f07 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -4377,6 +4377,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, << "Found net " << net->name() << " for expr " << *this << endl; } + ivl_type_t check_type = ntype; if (const netdarray_t*array_type = dynamic_cast (ntype)) { if (array_type->type_compatible(net->net_type())) { NetESignal*tmp = new NetESignal(net); @@ -4386,10 +4387,10 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, // Icarus allows a dynamic array to be initialised with a // single elementary value, so try that next. - ntype = array_type->element_type(); + check_type = array_type->element_type(); } - if (! ntype->type_compatible(net->net_type())) { + if (! check_type->type_compatible(net->net_type())) { cerr << get_fileline() << ": error: the type of the variable '" << path_ << "' doesn't match the context type." << endl; From 78963493805bac95cc88388963e738ed6ad1d36d Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Oct 2022 17:40:02 +0200 Subject: [PATCH 5/5] Add regression tests for dynamic array/queue type compatibility Check for various dynamic array and queue types that their type compatibility is handled correctly. Signed-off-by: Lars-Peter Clausen --- ivtest/ivltests/sv_darray_assign1.v | 28 +++++++++++++++ ivtest/ivltests/sv_darray_assign2.v | 44 +++++++++++++++++++++++ ivtest/ivltests/sv_darray_assign_fail1.v | 15 ++++++++ ivtest/ivltests/sv_darray_assign_fail2.v | 15 ++++++++ ivtest/ivltests/sv_darray_assign_fail3.v | 14 ++++++++ ivtest/ivltests/sv_darray_assign_fail4.v | 17 +++++++++ ivtest/ivltests/sv_darray_assign_fail5.v | 14 ++++++++ ivtest/ivltests/sv_darray_assign_fail6.v | 14 ++++++++ ivtest/ivltests/sv_queue_assign1.v | 27 ++++++++++++++ ivtest/ivltests/sv_queue_assign2.v | 45 ++++++++++++++++++++++++ ivtest/ivltests/sv_queue_assign_fail1.v | 14 ++++++++ ivtest/ivltests/sv_queue_assign_fail2.v | 14 ++++++++ ivtest/ivltests/sv_queue_assign_fail3.v | 14 ++++++++ ivtest/ivltests/sv_queue_assign_fail4.v | 17 +++++++++ ivtest/ivltests/sv_queue_assign_fail5.v | 14 ++++++++ ivtest/ivltests/sv_queue_assign_fail6.v | 14 ++++++++ ivtest/regress-sv.list | 16 +++++++++ ivtest/regress-vlog95.list | 4 +++ 18 files changed, 340 insertions(+) create mode 100644 ivtest/ivltests/sv_darray_assign1.v create mode 100644 ivtest/ivltests/sv_darray_assign2.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail1.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail2.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail3.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail4.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail5.v create mode 100644 ivtest/ivltests/sv_darray_assign_fail6.v create mode 100644 ivtest/ivltests/sv_queue_assign1.v create mode 100644 ivtest/ivltests/sv_queue_assign2.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail1.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail2.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail3.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail4.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail5.v create mode 100644 ivtest/ivltests/sv_queue_assign_fail6.v diff --git a/ivtest/ivltests/sv_darray_assign1.v b/ivtest/ivltests/sv_darray_assign1.v new file mode 100644 index 000000000..b31e24214 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign1.v @@ -0,0 +1,28 @@ +// Check that dynamic arrays with compatible packed base types can be assigned +// to each other. Even if the element types are not identical. + +module test; + + typedef bit [31:0] T1; + typedef bit [31:0] T2[]; + + // For two packed types to be compatible they need to have the same packed + // width, both be 2-state or 4-state and both be either signed or unsigned. + bit [32:1] d1[]; + bit [7:0][3:0] d2[]; + int unsigned d3[]; + T1 d4[]; + T2 d5; + + initial begin + d1 = new[1]; + d2 = d1; + d3 = d2; + d4 = d3; + d5 = d4; + d1 = d5; + + $display("PASSED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign2.v b/ivtest/ivltests/sv_darray_assign2.v new file mode 100644 index 000000000..f3e7a78e4 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign2.v @@ -0,0 +1,44 @@ +// Check that dynamic arrays with compatible packed base types can be passed as +// task arguments. Even it the element types are not identical. + +module test; + + typedef logic [31:0] T[]; + + task t1(logic [31:0] d[]); + d[0] = 1; + endtask + + task t2(logic [7:0][3:0] d[]); + d[0] = 1; + endtask + + task t3([31:0] d[]); + d[0] = 1; + endtask + + task t4(T d); + d[0] = 1; + endtask + + // For two packed types to be compatible they need to have the same packed + // width, both be 2-state or 4-state and both be either signed or unsigned. + logic [31:0] d1[]; + logic [7:0][3:0] d2[]; + + initial begin + d1 = new[1]; + d2 = new[1]; + t1(d1); + t1(d2); + t2(d1); + t2(d2); + t3(d1); + t3(d2); + t4(d1); + t4(d2); + + $display("PASSED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail1.v b/ivtest/ivltests/sv_darray_assign_fail1.v new file mode 100644 index 000000000..33699b1b1 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail1.v @@ -0,0 +1,15 @@ +// Check that it is not possible to assign a dynamic array with a 2-state +// element type to a dynamic array with 4-state element type. Even if they are +// otherwise identical. + +module test; + + logic [31:0] d1[]; + bit [31:0] d2[]; + + initial begin + d1 = d2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail2.v b/ivtest/ivltests/sv_darray_assign_fail2.v new file mode 100644 index 000000000..cda58dfb3 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail2.v @@ -0,0 +1,15 @@ +// Check that it is not possible to assign a dynamic array with a signed element +// type to a dynamic array with a unsigned element type. Even if they are +// otherwise identical. + +module test; + + logic [31:0] d1[]; + logic signed [31:0] d2[]; + + initial begin + d1 = d2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail3.v b/ivtest/ivltests/sv_darray_assign_fail3.v new file mode 100644 index 000000000..e5ac046cf --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail3.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a dynamic array with different +// element type width. + +module test; + + int d1[]; + shortint d2[]; + + initial begin + d1 = d2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail4.v b/ivtest/ivltests/sv_darray_assign_fail4.v new file mode 100644 index 000000000..85961bac2 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail4.v @@ -0,0 +1,17 @@ +// Check that it is not possible to assign a dynamic array with an enum +// element type to a dynamic array with a packed type. Even if the enum base +// type is the same as the packed type. + +module test; + + enum logic [31:0] { + A + } d1[]; + logic [31:0] d2[]; + + initial begin + d1 = d2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail5.v b/ivtest/ivltests/sv_darray_assign_fail5.v new file mode 100644 index 000000000..a1538d0b6 --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail5.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a dynamic array with a real +// element type to a dynamic array with an int element type. + +module test; + + int d1[]; + real d2[]; + + initial begin + d1 = d2; + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_darray_assign_fail6.v b/ivtest/ivltests/sv_darray_assign_fail6.v new file mode 100644 index 000000000..8692e42da --- /dev/null +++ b/ivtest/ivltests/sv_darray_assign_fail6.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a dynamic array with an int +// element type to a dynamic array with a real element type. + +module test; + + real d1[]; + int d2[]; + + initial begin + d1 = d2; + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign1.v b/ivtest/ivltests/sv_queue_assign1.v new file mode 100644 index 000000000..fe0bb48df --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign1.v @@ -0,0 +1,27 @@ +// Check that queues with compatible packed base types can be assigned to each +// other. Even if the element types are not identical. + +module test; + + typedef bit [31:0] T1; + typedef bit [31:0] T2[$]; + + // For two packed types to be compatible they need to have the same packed + // width, both be 2-state or 4-state and both be either signed or unsigned. + bit [32:1] q1[$]; + bit [7:0][3:0] q2[$]; + int unsigned q3[$]; + T1 q4[$]; + T2 q5; + + initial begin + q2 = q1; + q3 = q2; + q4 = q3; + q5 = q4; + q1 = q5; + + $display("PASSED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign2.v b/ivtest/ivltests/sv_queue_assign2.v new file mode 100644 index 000000000..472bc165e --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign2.v @@ -0,0 +1,45 @@ +// Check that queues with compatible packed base types can be passed as task +// arguments. Even it the element types are not identical. + +module test; + + typedef logic [31:0] T[$]; + + task t1(logic [31:0] q[$]); + q[0] = 1; + endtask + + task t2(logic [7:0][3:0] q[$]); + q[0] = 1; + endtask + + task t3([31:0] q[$]); + q[0] = 1; + endtask + + task t4(T q); + q[0] = 1; + endtask + + // For two packed types to be compatible they need to have the same packed + // width, both be 2-state or 4-state and both be either signed or unsigned. + logic [31:0] q1[$]; + logic [7:0][3:0] q2[$]; + + initial begin + q1.push_back(1); + q2.push_back(2); + + t1(q1); + t1(q2); + t2(q1); + t2(q2); + t3(q1); + t3(q2); + t4(q1); + t4(q2); + + $display("PASSED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail1.v b/ivtest/ivltests/sv_queue_assign_fail1.v new file mode 100644 index 000000000..d43f6afbe --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail1.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a queue with a 2-state element type +// to a queue with 4-state element type. Even if they are otherwise identical. + +module test; + + logic [31:0] q1[$]; + bit [31:0] q2[$]; + + initial begin + q1 = q2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail2.v b/ivtest/ivltests/sv_queue_assign_fail2.v new file mode 100644 index 000000000..cab584703 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail2.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a queue with a signed element type to +// a queue with a unsigned element type. Even if they are otherwise identical. + +module test; + + logic [31:0] q1[$]; + logic signed [31:0] q2[$]; + + initial begin + q1 = q2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail3.v b/ivtest/ivltests/sv_queue_assign_fail3.v new file mode 100644 index 000000000..3d820f376 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail3.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a queue to another queue with a +// different element width. + +module test; + + int q1[$]; + shortint q2[$]; + + initial begin + q1 = q2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail4.v b/ivtest/ivltests/sv_queue_assign_fail4.v new file mode 100644 index 000000000..5df7c9ed9 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail4.v @@ -0,0 +1,17 @@ +// Check that it is not possible to assign a queue with an enum element type to +// a queue with a packed type. Even if the enum base type is the same as the +// packed type. + +module test; + + enum logic [31:0] { + A + } q1[$]; + logic [31:0] q2[$]; + + initial begin + q1 = q2; + $dispaly("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail5.v b/ivtest/ivltests/sv_queue_assign_fail5.v new file mode 100644 index 000000000..7a5b1f425 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail5.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a queue with a real element type to a +// queue with an int element type. + +module test; + + int q1[$]; + real q2[$]; + + initial begin + q1 = q2; + $display("FAILED"); + end + +endmodule diff --git a/ivtest/ivltests/sv_queue_assign_fail6.v b/ivtest/ivltests/sv_queue_assign_fail6.v new file mode 100644 index 000000000..358533117 --- /dev/null +++ b/ivtest/ivltests/sv_queue_assign_fail6.v @@ -0,0 +1,14 @@ +// Check that it is not possible to assign a queue with an int element type to a +// queue with a real element type. + +module test; + + real q1[$]; + int q2[$]; + + initial begin + q1 = q2; + $display("FAILED"); + end + +endmodule diff --git a/ivtest/regress-sv.list b/ivtest/regress-sv.list index 9e133585b..a879003d8 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -553,6 +553,14 @@ sv_darray_args2 normal,-g2009 ivltests sv_darray_args2b normal,-g2009 ivltests sv_darray_args3 normal,-g2009 ivltests sv_darray_args4 normal,-g2009 ivltests +sv_darray_assign1 normal,-g2009 ivltests +sv_darray_assign2 normal,-g2009 ivltests +sv_darray_assign_fail1 CE,-g2009 ivltests +sv_darray_assign_fail2 CE,-g2009 ivltests +sv_darray_assign_fail3 CE,-g2009 ivltests +sv_darray_assign_fail4 CE,-g2009 ivltests +sv_darray_assign_fail5 CE,-g2009 ivltests +sv_darray_assign_fail6 CE,-g2009 ivltests sv_darray_copy_empty1 normal,-g2009 ivltests sv_darray_copy_empty2 normal,-g2009 ivltests sv_darray_copy_empty3 normal,-g2009 ivltests @@ -621,6 +629,14 @@ sv_ps_function3 normal,-g2009 ivltests sv_queue1 normal,-g2009 ivltests sv_queue2 normal,-g2009 ivltests sv_queue3 normal,-g2009 ivltests +sv_queue_assign1 normal,-g2009 ivltests +sv_queue_assign2 normal,-g2009 ivltests +sv_queue_assign_fail1 CE,-g2009 ivltests +sv_queue_assign_fail2 CE,-g2009 ivltests +sv_queue_assign_fail3 CE,-g2009 ivltests +sv_queue_assign_fail4 CE,-g2009 ivltests +sv_queue_assign_fail5 CE,-g2009 ivltests +sv_queue_assign_fail6 CE,-g2009 ivltests sv_queue_copy_empty1 normal,-g2009 ivltests sv_queue_copy_empty2 normal,-g2009 ivltests sv_queue_function1 normal,-g2009 ivltests diff --git a/ivtest/regress-vlog95.list b/ivtest/regress-vlog95.list index a42d24955..5601081fc 100644 --- a/ivtest/regress-vlog95.list +++ b/ivtest/regress-vlog95.list @@ -345,6 +345,8 @@ sv_darray_args2 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args2b CE,-g2009,-pallowsigned=1 ivltests sv_darray_args3 CE,-g2009,-pallowsigned=1 ivltests sv_darray_args4 CE,-g2009,-pallowsigned=1 ivltests # Also string +sv_darray_assign1 CE,-g2009 ivltests +sv_darray_assign2 CE,-g2009 ivltests sv_darray_copy_empty1 CE,-g2009 ivltests sv_darray_copy_empty2 CE,-g2009 ivltests sv_darray_copy_empty3 CE,-g2009 ivltests @@ -486,6 +488,8 @@ pr3390385b CE,-g2009 ivltests # ++ pr3390385c CE,-g2009 ivltests # ++ pr3390385d CE,-g2009 ivltests # ++ pr3462145 CE,-g2009 ivltests # ++ +sv_queue_assign1 CE,-g2009 ivltests # queue +sv_queue_assign2 CE,-g2009 ivltests # queue sv_queue_copy_empty1 CE,-g2009 ivltests # queue sv_queue_copy_empty2 CE,-g2009 ivltests # queue sv_queue_function1 CE,-g2009,-pallowsigned=1 ivltests # queue