Merge pull request #781 from larsclausen/darray-type-compat

Improve type compatibility checking for dynamic arrays and queues
This commit is contained in:
Stephen Williams 2022-10-14 08:15:50 -07:00 committed by GitHub
commit 10a39e59a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 483 additions and 86 deletions

View File

@ -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<const netdarray_t*> (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;

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (const netqueue_t*that_q = dynamic_cast<const netqueue_t*>(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<const netdarray_t*>(that);
if (!that_da)
return false;
return element_type()->type_equivalent(that_da->element_type());
}

View File

@ -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 */

View File

@ -68,6 +68,16 @@ vector<netrange_t> 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()
{
}

View File

@ -68,6 +68,9 @@ class netparray_t : public netsarray_t {
long packed_width(void) const;
std::vector<netrange_t> 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<netrange_t>&pd,

View File

@ -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<const netqueue_t*>(that))
elem_type = that_q->element_type();
if (const netdarray_t*that_da = dynamic_cast<const netdarray_t*>(that))
elem_type = that_da->element_type();
if (elem_type == 0)
return false;
return element_type()->type_compatible(elem_type);
}

View File

@ -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_;
};

View File

@ -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);
}

View File

@ -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_;

View File

@ -18,6 +18,7 @@
*/
# include "nettypes.h"
# include "netenum.h"
# include <iostream>
# include <cassert>
@ -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<netrange_t>&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<const netenum_t*>(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;
}

View File

@ -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<netrange_t>&dims,
const std::list<long>&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 */

View File

@ -89,19 +89,10 @@ vector<netrange_t> netvector_t::slice_dimensions() const
bool netvector_t::test_compatibility(ivl_type_t that) const
{
const netvector_t*that_st = dynamic_cast<const netvector_t*>(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);
}

View File

@ -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<netrange_t> packed_dims_;

View File

@ -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);

View File

@ -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",

View File

@ -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);

View File

@ -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);
/*

View File

@ -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);

View File

@ -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) {