Support dynamic arrays and queues of packed arrays

Currently only dynamic arrays and queues of atom2 and vector types are
supported. Add support for packed arrays. Since these three types are
essentially handled the same internally supporting this only requires to
allow to elaborate a packed array base type.

Factor out type elaboration into a helper function that can be shared
between the elaboration of the base type of a dynamic array or queue and
the type for other signals. This gives consistent behavior and will also
make it easier to support additional base types for dynamic arrays or
queues.

Note that it is not yet possible to index elements of packed array dynamic
arrays or queues. But neither is it possible to do a bit select for vector
or atom2 type dynamic arrays or queues yet. Supporting this needs some
additional work.

There is one test that declares a queue of a struct type, but doesn't use
it since it is not supported. With this change a error will generated when
trying to declare a queue of a struct. So update that test to not declare
the variable so it does not fail.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
Lars-Peter Clausen 2022-03-04 09:12:50 +01:00
parent 61a088fa78
commit 5cc825f45d
5 changed files with 78 additions and 95 deletions

View File

@ -111,7 +111,6 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netclass.o netdarray.o \
netenum.o netparray.o netqueue.o netscalar.o netstruct.o netvector.o \
make_ivl_type.o \
net_event.o net_expr.o net_func.o \
net_func_eval.o net_link.o net_modulo.o \
net_nex_input.o net_nex_output.o net_proc.o net_scope.o net_tran.o \

View File

@ -130,6 +130,13 @@ class PWire : public PNamedItem {
private: // not implemented
PWire(const PWire&);
PWire& operator= (const PWire&);
ivl_type_t elaborate_type(Design*des, NetScope*scope,
const std::vector<netrange_t>&packed_dimensions) const;
ivl_type_t elaborate_darray_type(Design*des, NetScope*scope,
const char *darray_type,
const std::vector<netrange_t>&packed_dimensions)
const;
};
#endif /* IVL_PWire_H */

View File

@ -934,6 +934,64 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
return true;
}
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
const std::vector<netrange_t>&packed_dimensions) const
{
if (dynamic_cast<struct_type_t*>(set_data_type_) ||
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_)) {
ivl_type_t use_type = set_data_type_->elaborate_type(des, scope);
ivl_assert(*this, packed_dimensions.empty());
return use_type;
}
// Fallback method. Create vector type.
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
use_data_type == IVL_VT_BOOL ||
use_data_type == IVL_VT_REAL);
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
vec->set_signed(get_signed());
vec->set_isint(get_isint());
return vec;
}
ivl_type_t PWire::elaborate_darray_type(Design*des, NetScope*scope,
const char *darray_type,
const std::vector<netrange_t>&packed_dimensions)
const
{
ivl_type_t type = elaborate_type(des, scope, packed_dimensions);
if (dynamic_cast<const netvector_t*>(type) ||
dynamic_cast<const netparray_t*>(type) ||
dynamic_cast<const netreal_t*>(type) ||
dynamic_cast<const netstring_t*>(type))
return type;
cerr << get_fileline() << ": Sorry: "
<< darray_type << " of type `" << *type
<< "` is not yet supported." << endl;
des->errors++;
// Return something to recover
return new netvector_t(IVL_VT_LOGIC);
}
/*
* Elaborate a source wire. The "wire" is the declaration of wires,
@ -1100,19 +1158,21 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
// dimensions, then turn this into a dynamic array and
// put all the packed dimensions there.
if (use_lidx==0 && use_ridx==0) {
ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions,
get_signed());
ivl_type_t base_type = elaborate_darray_type(des, scope,
"Dynamic array",
packed_dimensions);
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netdarray_t(vec);
netdarray = new netdarray_t(base_type);
continue;
}
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:max_idx].
if (dynamic_cast<PENull*>(use_lidx)) {
ivl_type_t vec = make_ivl_type(data_type_, packed_dimensions,
get_signed());
ivl_type_t base_type = elaborate_darray_type(des, scope,
"Queue",
packed_dimensions);
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
long max_idx;
@ -1144,7 +1204,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
}
} else max_idx = -1;
netdarray = new netqueue_t(vec, max_idx);
netdarray = new netqueue_t(base_type, max_idx);
continue;
}
@ -1227,13 +1287,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
ivl_assert(*this, unpacked_dimensions.empty());
sig = new NetNet(scope, name_, wtype, netdarray);
} else if (dynamic_cast<struct_type_t*>(set_data_type_) ||
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_)) {
} else {
ivl_type_t use_type = elaborate_type(des, scope,
packed_dimensions);
ivl_type_t use_type = set_data_type_->elaborate_type(des, scope);
if (debug_elaborate) {
cerr << get_fileline() << ": debug: Create signal "
<< wtype << " " << *set_data_type_
@ -1241,41 +1298,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " in scope " << scope_path(scope) << endl;
}
ivl_assert(*this, packed_dimensions.empty());
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else {
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Create vector signal " << wtype
<< " data_type=" << data_type_;
if (!packed_dimensions.empty()) {
cerr << " " << packed_dimensions;
}
cerr << " " << name_ << unpacked_dimensions;
cerr << " in scope " << scope_path(scope) << endl;
}
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_fileline() << ": PWire::elaborate_sig: "
<< "Signal " << name_
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
use_data_type == IVL_VT_BOOL ||
use_data_type == IVL_VT_REAL);
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
vec->set_signed(get_signed());
vec->set_isint(get_isint());
packed_dimensions.clear();
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
}
if (wtype == NetNet::WIRE) sig->devirtualize_pins();

View File

@ -43,7 +43,8 @@ module unp_array_typedef();
real_unparray real_unparr;
int_darray int_darr;
int_unparray int_unparr;
word_darray word_darr;
// TODO at the moment dynamic arrays of struct are not supported
// word_darray word_darr;
word_unparray word_unparr;
initial begin

View File

@ -1,47 +0,0 @@
/*
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
# include "nettypes.h"
# include "netscalar.h"
# include "netvector.h"
ivl_type_t make_ivl_type(ivl_variable_type_t vt,
const std::vector<netrange_t>&packed_dimensions,
bool signed_flag, bool isint_flag)
{
netvector_t*vec;
if (packed_dimensions.size() > 0) {
vec = new netvector_t(packed_dimensions, vt);
vec->set_signed(signed_flag);
return vec;
}
switch (vt) {
case IVL_VT_REAL:
return &netreal_t::type_real;
case IVL_VT_STRING:
return &netstring_t::type_string;
default:
vec = new netvector_t(packed_dimensions, vt);
vec->set_signed(signed_flag);
vec->set_isint(isint_flag);
return vec;
}
}