Merge pull request #772 from larsclausen/uarray-port-typedef
Correctly handle unpacked array typedefs for ports
This commit is contained in:
commit
7c52d239db
3
PWire.cc
3
PWire.cc
|
|
@ -33,8 +33,7 @@ PWire::PWire(perm_string n,
|
|||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false),
|
||||
port_set_(false), net_set_(false), is_scalar_(false),
|
||||
error_cnt_(0), uarray_type_(0), set_data_type_(0),
|
||||
discipline_(0)
|
||||
error_cnt_(0), set_data_type_(0), discipline_(0)
|
||||
{
|
||||
switch (rt) {
|
||||
case SR_PORT:
|
||||
|
|
|
|||
2
PWire.h
2
PWire.h
|
|
@ -77,7 +77,6 @@ class PWire : public PNamedItem {
|
|||
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
|
||||
|
||||
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
|
||||
void set_uarray_type(uarray_type_t*type) { uarray_type_ = type; }
|
||||
|
||||
void set_data_type(data_type_t*type);
|
||||
|
||||
|
|
@ -121,7 +120,6 @@ class PWire : public PNamedItem {
|
|||
// If this wire is actually a memory, these indices will give
|
||||
// me the size and address ranges of the memory.
|
||||
std::list<pform_range_t>unpacked_;
|
||||
uarray_type_t*uarray_type_;
|
||||
|
||||
// This is the complex type of the wire. the data_type_ may
|
||||
// modify how this is interpreted.
|
||||
|
|
|
|||
16
elab_sig.cc
16
elab_sig.cc
|
|
@ -1003,13 +1003,9 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
unsigned wid = 1;
|
||||
vector<netrange_t>packed_dimensions;
|
||||
|
||||
NetScope*array_type_scope = scope;
|
||||
if (uarray_type_ && !uarray_type_->name.nil())
|
||||
array_type_scope = array_type_scope->find_typedef_scope(des, uarray_type_);
|
||||
|
||||
NetScope*base_type_scope = array_type_scope;
|
||||
NetScope *type_scope = scope;
|
||||
if (set_data_type_ && !set_data_type_->name.nil())
|
||||
base_type_scope = base_type_scope->find_typedef_scope(des, set_data_type_);
|
||||
type_scope = type_scope->find_typedef_scope(des, set_data_type_);
|
||||
|
||||
des->errors += error_cnt_;
|
||||
|
||||
|
|
@ -1050,7 +1046,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
||||
<< "Evaluate ranges for net " << basename() << endl;
|
||||
}
|
||||
dimensions_ok &= evaluate_ranges(des, base_type_scope, this, nlist, net_);
|
||||
dimensions_ok &= evaluate_ranges(des, type_scope, this, nlist, net_);
|
||||
}
|
||||
assert(net_set_ || net_.empty());
|
||||
|
||||
|
|
@ -1151,15 +1147,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
wtype = NetNet::WIRE;
|
||||
}
|
||||
|
||||
ivl_type_t type = elaborate_type(des, array_type_scope, packed_dimensions);
|
||||
ivl_type_t type = elaborate_type(des, type_scope, packed_dimensions);
|
||||
// Create the type for the unpacked dimensions. If the
|
||||
// unpacked_dimensions are empty this will just return the base type.
|
||||
type = elaborate_array_type(des, array_type_scope, *this, type, unpacked_);
|
||||
type = elaborate_array_type(des, type_scope, *this, type, unpacked_);
|
||||
|
||||
list<netrange_t> unpacked_dimensions;
|
||||
// If this is an unpacked array extract the base type and unpacked
|
||||
// dimensions as these are separate properties of the NetNet.
|
||||
if (const netuarray_t *atype = dynamic_cast<const netuarray_t*>(type)) {
|
||||
while (const netuarray_t *atype = dynamic_cast<const netuarray_t*>(type)) {
|
||||
unpacked_dimensions.insert(unpacked_dimensions.begin(),
|
||||
atype->static_dimensions().begin(),
|
||||
atype->static_dimensions().end());
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
// Check that an array type identifier used for a module port is elaborated in
|
||||
// the correct scope.
|
||||
|
||||
localparam A = 2;
|
||||
localparam B = 4;
|
||||
|
||||
typedef logic [A-1:0] T[B];
|
||||
|
||||
module test (
|
||||
input T x
|
||||
);
|
||||
|
||||
localparam A = 5;
|
||||
localparam B = 10;
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
`define check(expr, val) \
|
||||
if (expr !== val) begin \
|
||||
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
initial begin
|
||||
`check($size(x, 1), 4);
|
||||
`check($size(x, 2), 2);
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Check that nested unpacked array types are supported.
|
||||
|
||||
module test;
|
||||
|
||||
localparam A = 3;
|
||||
localparam B = 5;
|
||||
localparam C = 2;
|
||||
localparam D = 7;
|
||||
|
||||
typedef logic [31:0] T1[A];
|
||||
typedef T1 T2[B][C];
|
||||
|
||||
T2 x[D];
|
||||
T2 y;
|
||||
|
||||
bit failed = 1'b0;
|
||||
|
||||
`define check(expr, val) \
|
||||
if (expr !== val) begin \
|
||||
$display("FAILED: %s, expected %0d, got %0d", `"expr`", val, expr); \
|
||||
failed = 1'b1; \
|
||||
end
|
||||
|
||||
initial begin
|
||||
`check($unpacked_dimensions(x), 4)
|
||||
`check($size(x, 1), A)
|
||||
`check($size(x, 2), B)
|
||||
`check($size(x, 3), C)
|
||||
`check($size(x, 4), D)
|
||||
|
||||
`check($unpacked_dimensions(y), 3)
|
||||
`check($size(y, 1), A)
|
||||
`check($size(y, 2), B)
|
||||
`check($size(y, 3), C)
|
||||
|
||||
`check($bits(T2), $bits(integer) * A * B * C)
|
||||
|
||||
if (!failed) begin
|
||||
$display("PASSED");
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
|
@ -368,6 +368,7 @@ module_nonansi_struct2 normal,-g2005-sv ivltests
|
|||
module_nonansi_struct_fail CE,-g2005-sv ivltests
|
||||
module_output_port_sv_var1 normal,-g2005-sv ivltests
|
||||
module_output_port_sv_var2 normal,-g2005-sv ivltests
|
||||
module_port_typedef_array1 normal,-g2005-sv ivltests
|
||||
named_begin normal,-g2009 ivltests
|
||||
named_begin_fail CE,-g2009 ivltests
|
||||
named_fork normal,-g2009 ivltests
|
||||
|
|
@ -673,6 +674,7 @@ sv_typedef_darray_base1 normal,-g2009 ivltests
|
|||
sv_typedef_darray_base2 normal,-g2009 ivltests
|
||||
sv_typedef_darray_base3 normal,-g2009 ivltests
|
||||
sv_typedef_darray_base4 normal,-g2009 ivltests
|
||||
sv_typedef_nested_array normal,-g2009 ivltests
|
||||
sv_typedef_queue_base1 normal,-g2009 ivltests
|
||||
sv_typedef_queue_base2 normal,-g2009 ivltests
|
||||
sv_typedef_queue_base3 normal,-g2009 ivltests
|
||||
|
|
|
|||
|
|
@ -225,6 +225,7 @@ br_ml20171017 CE ivltests
|
|||
genvar_scopes CE ivltests
|
||||
meminit2 CE ivltests
|
||||
memsynth4 CE,-S ivltests # Synthesized net array
|
||||
module_port_typedef_array1 CE,-g2005-sv ivltests # Module port array
|
||||
negative_genvar CE ivltests
|
||||
pr1565544 CE ivltests
|
||||
pr1657307 CE ivltests
|
||||
|
|
|
|||
33
parse.y
33
parse.y
|
|
@ -4350,7 +4350,8 @@ list_of_port_declarations
|
|||
pform_module_define_port(@3, name,
|
||||
port_declaration_context.port_type,
|
||||
port_declaration_context.port_net_type,
|
||||
port_declaration_context.data_type, 0);
|
||||
port_declaration_context.data_type,
|
||||
nullptr, nullptr);
|
||||
delete[]$3;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -4369,10 +4370,9 @@ port_declaration
|
|||
: attribute_list_opt K_input net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($5);
|
||||
data_type_t*use_type = $4;
|
||||
if ($6) use_type = new uarray_type_t(use_type, $6);
|
||||
ptmp = pform_module_port_reference(@2, name);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT, $3, use_type, $1);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT, $3, $4, $6, nullptr,
|
||||
$1);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
|
@ -4386,8 +4386,8 @@ port_declaration
|
|||
ptmp = pform_module_port_reference(@2, name);
|
||||
real_type_t*real_type = new real_type_t(real_type_t::REAL);
|
||||
FILE_NAME(real_type, @3);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT,
|
||||
NetNet::WIRE, real_type, $1);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT, NetNet::WIRE,
|
||||
real_type, nullptr, $1);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.port_net_type = NetNet::WIRE;
|
||||
port_declaration_context.data_type = real_type;
|
||||
|
|
@ -4401,7 +4401,8 @@ port_declaration
|
|||
data_type_t*use_type = $4;
|
||||
ptmp = pform_module_port_reference(@2, name);
|
||||
ptmp->default_value = $7;
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT, $3, use_type, $1);
|
||||
pform_module_define_port(@2, name, NetNet::PINPUT, $3, use_type,
|
||||
nullptr, $1);
|
||||
port_declaration_context.port_type = NetNet::PINPUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
|
@ -4412,7 +4413,8 @@ port_declaration
|
|||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($5);
|
||||
ptmp = pform_module_port_reference(@2, name);
|
||||
pform_module_define_port(@2, name, NetNet::PINOUT, $3, $4, $1);
|
||||
pform_module_define_port(@2, name, NetNet::PINOUT, $3, $4, nullptr,
|
||||
$1);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.port_net_type = $3;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
|
@ -4430,8 +4432,8 @@ port_declaration
|
|||
ptmp = pform_module_port_reference(@2, name);
|
||||
real_type_t*real_type = new real_type_t(real_type_t::REAL);
|
||||
FILE_NAME(real_type, @3);
|
||||
pform_module_define_port(@2, name, NetNet::PINOUT,
|
||||
NetNet::WIRE, real_type, $1);
|
||||
pform_module_define_port(@2, name, NetNet::PINOUT, NetNet::WIRE,
|
||||
real_type, nullptr, $1);
|
||||
port_declaration_context.port_type = NetNet::PINOUT;
|
||||
port_declaration_context.port_net_type = NetNet::WIRE;
|
||||
port_declaration_context.data_type = real_type;
|
||||
|
|
@ -4441,8 +4443,6 @@ port_declaration
|
|||
| attribute_list_opt K_output net_type_or_var_opt data_type_or_implicit IDENTIFIER dimensions_opt
|
||||
{ Module::port_t*ptmp;
|
||||
perm_string name = lex_strings.make($5);
|
||||
data_type_t*use_dtype = $4;
|
||||
if ($6) use_dtype = new uarray_type_t(use_dtype, $6);
|
||||
NetNet::Type use_type = $3;
|
||||
if (use_type == NetNet::IMPLICIT) {
|
||||
if (vector_type_t*dtype = dynamic_cast<vector_type_t*> ($4)) {
|
||||
|
|
@ -4460,7 +4460,7 @@ port_declaration
|
|||
}
|
||||
}
|
||||
ptmp = pform_module_port_reference(@2, name);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, use_dtype, $1);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $6, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = use_type;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
|
@ -4474,8 +4474,8 @@ port_declaration
|
|||
ptmp = pform_module_port_reference(@2, name);
|
||||
real_type_t*real_type = new real_type_t(real_type_t::REAL);
|
||||
FILE_NAME(real_type, @3);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT,
|
||||
NetNet::WIRE, real_type, $1);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT, NetNet::WIRE,
|
||||
real_type, nullptr, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = NetNet::WIRE;
|
||||
port_declaration_context.data_type = real_type;
|
||||
|
|
@ -4490,7 +4490,8 @@ port_declaration
|
|||
use_type = NetNet::IMPLICIT_REG;
|
||||
}
|
||||
ptmp = pform_module_port_reference(@2, name);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $1);
|
||||
pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4,
|
||||
nullptr, $1);
|
||||
port_declaration_context.port_type = NetNet::POUTPUT;
|
||||
port_declaration_context.port_net_type = use_type;
|
||||
port_declaration_context.data_type = $4;
|
||||
|
|
|
|||
40
pform.cc
40
pform.cc
|
|
@ -2591,21 +2591,12 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::PortType port_kind,
|
||||
NetNet::Type type,
|
||||
data_type_t*vtype,
|
||||
list<pform_range_t>*urange,
|
||||
list<named_pexpr_t>*attr,
|
||||
bool keep_attr)
|
||||
{
|
||||
pform_check_net_data_type(li, type, vtype);
|
||||
|
||||
// Unpacked dimensions
|
||||
list<pform_range_t>*urange = 0;
|
||||
|
||||
// If this is an unpacked array, then split out the parts that
|
||||
// we can send to the PWire object that we create.
|
||||
if (uarray_type_t*uarr_type = dynamic_cast<uarray_type_t*> (vtype)) {
|
||||
urange = uarr_type->dims.get();
|
||||
vtype = uarr_type->base_type;
|
||||
}
|
||||
|
||||
PWire *cur = pform_get_or_make_wire(li, name, type, port_kind, SR_BOTH);
|
||||
|
||||
vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype);
|
||||
|
|
@ -2616,6 +2607,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
|
||||
if (urange) {
|
||||
cur->set_unpacked_idx(*urange);
|
||||
delete urange;
|
||||
}
|
||||
|
||||
pform_bind_attributes(cur->attributes, attr, keep_attr);
|
||||
|
|
@ -2632,13 +2624,9 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
; cur != ports->end() ; ++ cur ) {
|
||||
|
||||
data_type_t*use_type = vtype;
|
||||
if (cur->udims)
|
||||
use_type = new uarray_type_t(vtype, cur->udims);
|
||||
|
||||
pform_module_define_port(li, cur->name, port_kind, type, use_type,
|
||||
attr, true);
|
||||
if (cur->udims)
|
||||
delete use_type;
|
||||
cur->udims, attr, true);
|
||||
|
||||
if (cur->expr)
|
||||
pform_make_var_init(li, cur->name, cur->expr);
|
||||
|
|
@ -2820,12 +2808,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
bool allow_implicit)
|
||||
{
|
||||
vector<pform_tf_port_t>*ret = NULL;
|
||||
std::list<pform_range_t>*unpacked_dims = NULL;
|
||||
|
||||
if (uarray_type_t*uarray = dynamic_cast<uarray_type_t*> (vtype)) {
|
||||
unpacked_dims = uarray->dims.get();
|
||||
vtype = uarray->base_type;
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
ret = pform_make_task_ports_vec(loc, pt, vec_type, ports,
|
||||
|
|
@ -2834,14 +2816,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
ret = do_make_task_ports(loc, pt, vtype, ports);
|
||||
}
|
||||
|
||||
if (unpacked_dims) {
|
||||
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||
; cur != ports->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(cur->name);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete ports;
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -3213,10 +3187,6 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type,
|
|||
assert(0);
|
||||
}
|
||||
|
||||
uarray_type_t*uarray_type = dynamic_cast<uarray_type_t*> (data_type);
|
||||
if (uarray_type)
|
||||
data_type = uarray_type->base_type;
|
||||
|
||||
vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type);
|
||||
|
||||
for (std::vector<PWire*>::iterator it= wires->begin();
|
||||
|
|
@ -3230,10 +3200,6 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type,
|
|||
bool rc = wire->set_wire_type(net_type);
|
||||
ivl_assert(li, rc);
|
||||
|
||||
if (uarray_type) {
|
||||
wire->set_unpacked_idx(*uarray_type->dims.get());
|
||||
wire->set_uarray_type(uarray_type);
|
||||
}
|
||||
wire->set_data_type(data_type);
|
||||
|
||||
pform_bind_attributes(wire->attributes, attr, true);
|
||||
|
|
|
|||
1
pform.h
1
pform.h
|
|
@ -154,6 +154,7 @@ extern void pform_module_define_port(const struct vlltype&li,
|
|||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
data_type_t*vtype,
|
||||
std::list<pform_range_t>*urange,
|
||||
std::list<named_pexpr_t>*attr,
|
||||
bool keep_attr =false);
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
|
|
|
|||
Loading…
Reference in New Issue