Merge pull request #772 from larsclausen/uarray-port-typedef

Correctly handle unpacked array typedefs for ports
This commit is contained in:
Stephen Williams 2022-10-03 19:39:01 -07:00 committed by GitHub
commit 7c52d239db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 106 additions and 67 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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