diff --git a/elab_expr.cc b/elab_expr.cc index 530f47b7e..41ac7bec6 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; 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/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 ffb5691b9..e423c2a86 100644 --- a/ivtest/regress-sv.list +++ b/ivtest/regress-sv.list @@ -557,6 +557,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 @@ -628,6 +636,14 @@ sv_ps_var1 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 0fdd10572..97ad90d58 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 @@ -488,6 +490,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 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 890995ad1..8fc466e3b 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. @@ -52,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_; 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); 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) {