Correctly handle separate port type declaration for atom2 types

When using non-ANSI style port declarations it is possible to declare the
port direction and the data type for the port in separate statements. E.g.

```
input x;
reg x;
```

When using packed array dimensions they must match for both declarations.
E.g.

```
input [3:0] x;
reg [3:0] x;
```

But this only applies to vector types, i.e. the packed dimension is
explicitly declared. It does not apply to the atom2 types which have an
implicit packed dimension.

The current implementation requires that even for atom2 types the implicit
dimension needs to be explicitly declared in the port direction. E.g. the
following will result in a elaboration error complaining about a packed
dimension mismatch.

```
module test;
  output x;
  byte x;
endmodule
```

Currently atom2_type_t's are deconstructed into base type, range and
signdness in the parser. That data is then passed to the signal
elaboration, which will then construct a netvector_t from it. This makes it
impossible to e.g. differentiate between `bit signed [31:0]` and `int`
during elaboration.

Instead of breaking the data type apart pass it as the data_type_t of the
signal and use the elaborate_type() method in the signal elaboration to
generate the netvector_t.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-03-12 22:40:14 +01:00
parent d480c4d7d0
commit de9e3b791b
2 changed files with 5 additions and 41 deletions

View File

@ -941,7 +941,8 @@ ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
dynamic_cast<enum_type_t*>(set_data_type_) ||
dynamic_cast<string_type_t*>(set_data_type_) ||
dynamic_cast<class_type_t*>(set_data_type_) ||
dynamic_cast<parray_type_t*>(set_data_type_)) {
dynamic_cast<parray_type_t*>(set_data_type_) ||
dynamic_cast<atom2_type_t*>(set_data_type_)) {
ivl_type_t use_type = set_data_type_->elaborate_type(des, scope);
ivl_assert(*this, packed_dimensions.empty());
return use_type;

View File

@ -2601,11 +2601,6 @@ void pform_module_define_port(const struct vlltype&li,
data_type = vec_type->base_type;
signed_flag = vec_type->signed_flag;
prange = vec_type->pdims.get();
} else if (atom2_type_t*atype = dynamic_cast<atom2_type_t*>(vtype)) {
data_type = IVL_VT_BOOL;
signed_flag = atype->signed_flag;
prange = make_range_from_width(atype->type_code);
} else if (real_type_t*rtype = dynamic_cast<real_type_t*>(vtype)) {
data_type = IVL_VT_REAL;
signed_flag = true;
@ -2959,11 +2954,8 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
vtype = uarray->base_type;
}
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag,
range_tmp, ports);
if (dynamic_cast<atom2_type_t*> (vtype)) {
ret = do_make_task_ports(loc, pt, IVL_VT_BOOL, vtype, ports);
}
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
@ -3431,30 +3423,6 @@ void pform_set_port_type(const struct vlltype&li,
delete attr;
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name)
{
PWire*cur = pform_get_wire_in_scope(name);
assert(cur);
cur->set_signed(signed_flag);
pform_range_t rng;
rng.first = new PENumber(new verinum(width-1, integer_width));
rng.second = new PENumber(new verinum((uint64_t)0, integer_width));
list<pform_range_t>rlist;
rlist.push_back(rng);
cur->set_range(rlist, SR_NET);
}
static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list<perm_string>*names)
{
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
perm_string txt = *cur;
pform_set_integer_2atom(width, signed_flag, txt);
}
}
/*
* This function detects the derived class for the given type and
* dispatches the type to the proper subtype function.
@ -3471,12 +3439,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list<pe
if (uarray_type)
data_type = uarray_type->base_type;
if (atom2_type_t*atom2_type = dynamic_cast<atom2_type_t*> (data_type)) {
pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names);
vt = IVL_VT_BOOL;
}
else if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (data_type)) {
if (net_type==NetNet::REG && vec_type->integer_flag)
net_type=NetNet::INTEGER;