Correctly handle unpacked array typedefs for ports
If the type of a port is an array type it currently always gets evaluated in the scope where the port is declared. But if the type is a typedef it might be declared in a different scope and must be evaluated in that scope. E.g. the following will declare an array port with 10 entries and an element type of a 5 bit vector, while it should declare one with 4 entries and an element type of a 2 bit vector. ``` localparam A = 2; localparam B = 4; typedef [A-1:0] T[B]; module test ( T x ); localparam A = 5; localparam B = 10; endmodule ``` This is in part due to array types being given special handling. This was necessary before because each base type required slightly different handling and so the base type had to be extracted from the array type. This has now been consolidated and all data types are treated the same. The only exception is the vector type which still needs special handling to support separate definition of port direction and type. As a result it is possible to remove the special handling of the array type. This solves the problem of evaluating the type in the wrong scope. Some special handling needs to be retained though to be able to differentiate between array dimensions that are part of a type and array dimensions that are part of port declaration. This is again necessary to correctly support separate definition of port direction and type. E.g. in the example below port `x` and `y` get treated slightly differently, even though the resulting signals will be identical. ``` typedef logic [7:0] T[1:0]; ... input T x; input [7:0] y[1:0]; ``` Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
fd69d4e09c
commit
2385b32cb3
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.
|
||||
|
|
|
|||
14
elab_sig.cc
14
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,10 +1147,10 @@ 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
|
||||
|
|
|
|||
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