Merge pull request #781 from larsclausen/darray-type-compat
Improve type compatibility checking for dynamic arrays and queues
This commit is contained in:
commit
10a39e59a1
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
1
ivl.def
1
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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
26
netdarray.cc
26
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<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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
10
netparray.cc
10
netparray.cc
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
16
netqueue.cc
16
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<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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
13
netstruct.cc
13
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
50
nettypes.cc
50
nettypes.cc
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
17
nettypes.h
17
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<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 */
|
||||
|
|
|
|||
21
netvector.cc
21
netvector.cc
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue