Some rework to allow for nested packed types.

This also simplifies the NetNet set of contructors and generalizes
the types that are supported, especially packed types.
This commit is contained in:
Stephen Williams 2012-09-29 15:13:45 -07:00
parent 4e76912331
commit 914ebeca4a
21 changed files with 247 additions and 172 deletions

View File

@ -108,7 +108,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
net_design.o netdarray.o \
netenum.o netstruct.o netvector.o net_event.o net_expr.o net_func.o \
netenum.o netparray.o netstruct.o netvector.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 \
net_udp.o pad_to_width.o parse.o parse_misc.o pform.o pform_analog.o \

View File

@ -249,8 +249,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
<< unpacked_dims_ << " unpacked dims=" << unpacked_dimensions();
if (!packed_dims_.empty())
o << " packed dims=" << packed_dims_;
o << " pin_count=" << pin_count();
if (local_flag_)
o << " (local)";
@ -1107,7 +1105,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
if (result_sig_) {
o << setw(ind+2) << "" << "Return signal: ";
if (result_sig_->get_signed()) o << "+";
o << result_sig_->name() << result_sig_->packed_dims() << endl;
o << result_sig_->name() << endl;
}
o << setw(ind+2) << "" << "Arguments: ";
if (port_count() == 0) o << "<none>";
@ -1129,7 +1127,7 @@ void NetFuncDef::dump(ostream&o, unsigned ind) const
break;
}
if (port(idx)->get_signed()) o << "+";
o << port(idx)->name() << port(idx)->packed_dims() << endl;
o << port(idx)->name() << endl;
}
if (statement_)
statement_->dump(o, ind+2);
@ -1548,7 +1546,8 @@ void NetESignal::dump(ostream&o) const
o << "+";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << sig()->packed_dims();
vector<netrange_t>tmp = net_->net_type()->slice_dimensions();
o << tmp;
}
void NetETernary::dump(ostream&o) const

View File

@ -1481,7 +1481,7 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
perm_string method_name,
unsigned long&off)
{
netstruct_t*type = net->struct_type();
const netstruct_t*type = net->struct_type();
ivl_assert(*li, type);
if (! type->packed()) {
@ -3555,7 +3555,7 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<netrange_t>&packed = net->sig()->packed_dims();
const vector<netrange_t>&packed = net->sig()->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
@ -3784,7 +3784,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
long msv = msc->value().as_long();
const list<netrange_t>& sig_packed = net->sig()->packed_dims();
const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
if (prefix_indices.size()+2 <= sig_packed.size()) {
// Special case: this is a slice of a multi-dimensional
// packed array. For example:
@ -3877,7 +3877,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
return res;
}
const list<netrange_t>& sig_packed = net->sig()->packed_dims();
const vector<netrange_t>& sig_packed = net->sig()->packed_dims();
if (prefix_indices.size()+2 <= sig_packed.size()) {
// Special case: this is a slice of a multi-dimensional
// packed array. For example:

View File

@ -507,7 +507,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
const list<netrange_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
// Part selects cannot select slices. So there must be enough
// prefix_indices to get all the way to the final dimension.
@ -596,7 +596,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
long lsv = base_c->value().as_long();
long offset = 0;
// Get the signal range.
const list<netrange_t>&packed = reg->packed_dims();
const vector<netrange_t>&packed = reg->packed_dims();
ivl_assert(*this, packed.size() == prefix_indices.size()+1);
// We want the last range, which is where we work.
@ -680,7 +680,7 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
NetNet*reg = lv->sig();
ivl_assert(*this, reg);
netstruct_t*struct_type = reg->struct_type();
const netstruct_t*struct_type = reg->struct_type();
ivl_assert(*this, struct_type);
if (debug_elaborate) {

View File

@ -430,11 +430,18 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
remove the member and store it into method_name, and retry
the search with "a.b". */
if (sig == 0 && path_.size() >= 2) {
if (debug_elaborate) {
cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: "
"Symbol not found, try again with path_prefix=" << path_prefix
<< " and method_name=" << path_tail.name << endl;
}
method_name = path_tail.name;
symbol_search(this, des, scope, path_prefix, sig, par, eve);
// Whoops, not a struct signal, so give up on this avenue.
if (sig && sig->struct_type() == 0) {
cerr << get_fileline() << ": XXXXX: sig=" << sig->name()
<< " is found, but not a struct with member " << method_name << endl;
method_name = perm_string();
sig = 0;
}
@ -474,7 +481,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
list<long> unpacked_indices_const;
netstruct_t*struct_type = 0;
const netstruct_t*struct_type = 0;
if ((struct_type = sig->struct_type()) && !method_name.nil()) {
// Detect the variable is a structure and there was a

View File

@ -522,7 +522,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1;
}
list<netrange_t> packed;
vector<netrange_t> packed;
packed.push_back(netrange_t(mnum, lnum));
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
ret_vec->set_signed(return_type_.type == PTF_REG_S);
@ -823,7 +823,7 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
}
static bool evaluate_ranges(Design*des, NetScope*scope,
list<netrange_t>&llist,
vector<netrange_t>&llist,
const list<pform_range_t>&rlist)
{
bool bad_msb = false, bad_lsb = false;
@ -874,7 +874,7 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
; cur != struct_type->members->end() ; ++ cur) {
list<netrange_t>packed_dimensions;
vector<netrange_t>packed_dimensions;
struct_member_t*curp = *cur;
if (curp->range.get() && ! curp->range->empty()) {
@ -900,20 +900,6 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
return res;
}
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
list<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
netparray_t*res = new netparray_t(packed_dimensions);
//res->set_line(*data_type);
return res;
}
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
data_type_t*pform_type)
{
@ -929,13 +915,29 @@ static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
return 0;
}
bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
parray_type_t*data_type)
{
vector<netrange_t>packed_dimensions;
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
ivl_assert(*data_type, !bad_range);
ivl_type_s*element_type = elaborate_type(des, scope, data_type->base_type);
netparray_t*res = new netparray_t(packed_dimensions, element_type);
//res->set_line(*data_type);
return res;
}
bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
{
if (lef.size() != rig.size())
return false;
list<netrange_t>::const_iterator lcur = lef.begin();
list<netrange_t>::const_iterator rcur = rig.begin();
vector<netrange_t>::const_iterator lcur = lef.begin();
vector<netrange_t>::const_iterator rcur = rig.begin();
while (lcur != lef.end()) {
if (lcur->get_msb() != rcur->get_msb())
return false;
@ -970,7 +972,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
unsigned wid = 1;
list<netrange_t>packed_dimensions;
vector<netrange_t>packed_dimensions;
des->errors += error_cnt_;
@ -1011,7 +1013,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (port_set_ || net_set_) {
bool bad_range = false;
list<netrange_t> plist, nlist;
vector<netrange_t> plist, nlist;
/* If they exist get the port definition MSB and LSB */
if (port_set_ && !port_.empty()) {
bad_range |= evaluate_ranges(des, scope, plist, port_);
@ -1222,7 +1224,8 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " and packed_width=" << use_enum->packed_width() << endl;
}
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum);
ivl_assert(*this, packed_dimensions.empty());
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_enum);
} else if (netarray) {
@ -1256,14 +1259,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< " in scope " << scope_path(scope) << endl;
}
ivl_type_s*base_type = elaborate_type(des, scope, parray_type->base_type);
#if 0
cerr << get_fileline() << ": sorry: Packed array of "
<< typeid(*parray_type->base_type).name()
<< " not supported." << endl;
des->errors += 1;
#endif
sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type);
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
} else {
@ -1293,7 +1289,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (is_implicit_scalar) vec->set_scalar(true);
else vec->set_scalar(get_scalar());
packed_dimensions.clear();
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, vec);
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, vec);
}

View File

@ -998,8 +998,9 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
ivl_assert(*this, dir != NetNet::NOT_A_PORT);
ivl_assert(*this, dir != NetNet::PIMPLICIT);
netvector_t*tmp_type = new netvector_t(IVL_VT_LOGIC, port_wid-1, 0);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, port_wid);
NetNet::WIRE, tmp_type);
tmp->local_flag(true);
tmp->set_line(*this);
@ -1417,6 +1418,12 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
<< "too complicated for elaboration." << endl;
continue;
}
if (debug_elaborate) {
cerr << get_fileline() << ": debug: "
<< "Elaborating INPUT port expression: " << *tmp_expr << endl;
}
sig = tmp_expr->synthesize(des, scope, tmp_expr);
if (sig == 0) {
cerr << pins[idx]->get_fileline()

View File

@ -21,6 +21,8 @@
# include "compiler.h"
# include <cassert>
using namespace std;
netenum_t::netenum_t(ivl_variable_type_t btype, bool signed_flag,
long msb, long lsb, size_t name_count)
: base_type_(btype), signed_flag_(signed_flag), msb_(msb), lsb_(lsb),
@ -45,6 +47,14 @@ long netenum_t::packed_width() const
return lsb_ - msb_ + 1;
}
vector<netrange_t> netenum_t::slice_dimensions() const
{
vector<netrange_t> tmp (1);
tmp[0] = netrange_t(msb_, lsb_);
return tmp;
}
bool netenum_t::insert_name(size_t name_idx, perm_string name, const verinum&val)
{
std::pair<std::map<perm_string,verinum>::iterator, bool> res;

View File

@ -38,6 +38,7 @@ class netenum_t : public LineInfo, public ivl_type_s {
ivl_variable_type_t base_type() const;
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
bool get_signed() const;
// The size() is the number of enumeration literals.

View File

@ -29,6 +29,7 @@
# include "netmisc.h"
# include "netdarray.h"
# include "netenum.h"
# include "netparray.h"
# include "netstruct.h"
# include "netvector.h"
# include "ivl_assert.h"
@ -464,44 +465,6 @@ PortType::Enum PortType::merged( Enum lhs, Enum rhs )
return PINOUT;
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1),
type_(t), port_type_(NOT_A_PORT),
local_flag_(false),
net_type_(0), discipline_(0),
eref_count_(0), lref_count_(0),
port_index_(-1)
{
assert(s);
assert(npins>0);
// Synthesize a single range to describe this canonical vector.
packed_dims_.push_back(netrange_t(npins-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
switch (t) {
case REG:
case INTEGER:
case IMPLICIT_REG:
dir = Link::OUTPUT;
break;
case SUPPLY0:
dir = Link::OUTPUT;
break;
case SUPPLY1:
dir = Link::OUTPUT;
break;
default:
break;
}
pin(0).set_dir(dir);
s->add_signal(this);
}
void NetNet::initialize_dir_(Link::DIR dir)
{
if (pins_are_virtual()) {
@ -544,47 +507,35 @@ template <class T> static unsigned calculate_count(T*type)
void NetNet::calculate_slice_widths_from_packed_dims_(void)
{
netvector_t*vec = dynamic_cast<netvector_t*> (net_type_);
ivl_assert(*this, vec==0 || packed_dims_.empty());
ivl_assert(*this, net_type_);
slice_dims_ = net_type_->slice_dimensions();
const std::list<netrange_t>&use_packed = vec? vec->packed_dims() : packed_dims_;
if (use_packed.empty()) {
slice_wids_.clear();
// Special case: There are no actual packed dimensions, so
// build up a fake dimension of "1".
if (slice_dims_.size() == 0) {
slice_wids_.resize(1);
slice_wids_[0] = net_type_->packed_width();
return;
}
slice_wids_.resize(use_packed.size());
slice_wids_.resize(slice_dims_.size());
slice_wids_[0] = netrange_width(use_packed);
list<netrange_t>::const_iterator cur = use_packed.begin();
ivl_assert(*this, slice_wids_.size() >= 1);
slice_wids_[0] = netrange_width(slice_dims_);
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
}
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
const list<netrange_t>&packed,
const list<netrange_t>&unpacked,
ivl_type_s*use_net_type)
const list<netrange_t>&unpacked, ivl_type_s*use_net_type)
: NetObj(s, n, calculate_count(unpacked)),
type_(t), port_type_(NOT_A_PORT),
local_flag_(false), net_type_(use_net_type),
discipline_(0), unpacked_dims_(unpacked.size()),
eref_count_(0), lref_count_(0)
{
packed_dims_ = packed;
// Special case: This is an enum, so it is its own packed vector.
if (netenum_t*et = dynamic_cast<netenum_t*>(use_net_type)) {
ivl_assert(*this, packed_dims_.empty());
packed_dims_.push_back(netrange_t(calculate_count(et)-1, 0));
}
// Special case: netstruct types are like another packed
// dimension.
if (netstruct_t*st = dynamic_cast<netstruct_t*>(use_net_type)) {
packed_dims_.push_back(netrange_t(calculate_count(st)-1, 0));
}
calculate_slice_widths_from_packed_dims_();
size_t idx = 0;
for (list<netrange_t>::const_iterator cur = unpacked.begin()
@ -633,7 +584,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
discipline_(0),
eref_count_(0), lref_count_(0)
{
packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
//XXXX packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
calculate_slice_widths_from_packed_dims_();
Link::DIR dir = Link::PASSIVE;
@ -792,16 +743,6 @@ void NetNet::set_module_port_index(unsigned idx)
assert( port_index_ >= 0 );
}
const std::list<netrange_t>& NetNet::packed_dims() const
{
if (netvector_t*vec = dynamic_cast<netvector_t*> (net_type_)) {
ivl_assert(*this, packed_dims_.empty());
return vec->packed_dims();
}
return packed_dims_;
}
ivl_variable_type_t NetNet::data_type() const
{
if (net_type_==0)
@ -839,9 +780,26 @@ netenum_t*NetNet::enumeration(void) const
return dynamic_cast<netenum_t*> (net_type_);
}
netstruct_t*NetNet::struct_type(void) const
const netstruct_t*NetNet::struct_type(void) const
{
return dynamic_cast<netstruct_t*> (net_type_);
const ivl_type_s*cur_type = net_type_;
while (cur_type) {
if (const netdarray_t*da = dynamic_cast<const netdarray_t*> (cur_type)) {
cur_type = da->element_type();
continue;
}
if (const netparray_t*da = dynamic_cast<const netparray_t*> (cur_type)) {
cur_type = da->element_type();
continue;
}
if (const netstruct_t*st = dynamic_cast<const netstruct_t*> (cur_type))
return st;
else
return 0;
}
assert(0);
return 0;
}
netdarray_t* NetNet::darray_type(void) const
@ -894,7 +852,7 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
{
ivl_assert(*this, indices.size()+1 == packed_dims().size());
list<netrange_t>::const_iterator pcur = packed_dims().end();
vector<netrange_t>::const_iterator pcur = packed_dims().end();
-- pcur;
long acc_off;
@ -2486,14 +2444,14 @@ NetNet* NetESignal::sig()
*/
long NetESignal::lsi() const
{
const list<netrange_t>&packed = net_->packed_dims();
const vector<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
return packed.back().get_lsb();
}
long NetESignal::msi() const
{
const list<netrange_t>&packed = net_->packed_dims();
const vector<netrange_t>&packed = net_->packed_dims();
ivl_assert(*this, packed.size() == 1);
return packed.back().get_msb();
}

View File

@ -597,21 +597,15 @@ class NetNet : public NetObj, public PortType {
typedef PortType::Enum PortType;
public:
// The width in this case is a shorthand for ms=width-1 and
// ls=0. Only one pin is created, the width is of the vector
// that passed through.
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
// This form supports an array of vectors. The [ms:ls] define
// the base vector, and the [s0:e0] define the array
// dimensions. If s0==e0, then this is not an array after
// all.
// This form is the more generic form of the constructor. For
// now, the unpacked type is not burried into an ivl_type_s object.
explicit NetNet(NetScope*s, perm_string n, Type t,
const std::list<netrange_t>&packed,
const std::list<netrange_t>&unpacked,
ivl_type_s*type =0);
// This form builds a NetNet from its record/enum definition.
// This form builds a NetNet from its record/enum/darray
// definition. They should probably be replaced with a single
// version that takes an ivl_type_s* base.
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
explicit NetNet(NetScope*s, perm_string n, Type t, netdarray_t*type);
explicit NetNet(NetScope*s, perm_string n, Type t, netvector_t*type);
@ -643,7 +637,7 @@ class NetNet : public NetObj, public PortType {
inline const ivl_type_s* net_type(void) const { return net_type_; }
netenum_t*enumeration(void) const;
netstruct_t*struct_type(void) const;
const netstruct_t*struct_type(void) const;
netdarray_t*darray_type(void) const;
/* Attach a discipline to the net. */
@ -653,8 +647,9 @@ class NetNet : public NetObj, public PortType {
/* This method returns a reference to the packed dimensions
for the vector. These are arranged as a list where the
first range in the list (front) is the left-most range in
the verilog declaration. */
const std::list<netrange_t>& packed_dims() const;
the verilog declaration. These packed dims are compressed
to represent the dimensions of all the subtypes. */
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
const std::vector<netrange_t>& unpacked_dims() const { return unpacked_dims_; }
@ -694,7 +689,7 @@ class NetNet : public NetObj, public PortType {
/* This methor returns 0 for scalars, but vectors and other
PACKED arrays have packed dimensions. */
inline size_t packed_dimensions() const { return packed_dims_.size(); }
inline size_t packed_dimensions() const { return slice_dims_.size(); }
// This is the number of array elements.
unsigned unpacked_count() const;
@ -733,7 +728,6 @@ class NetNet : public NetObj, public PortType {
ivl_type_s*net_type_;
ivl_discipline_t discipline_;
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> unpacked_dims_;
// These are the widths of the various slice depths. There is
@ -742,6 +736,7 @@ class NetNet : public NetObj, public PortType {
//
// For example: slice_wids_[0] is vector_width().
void calculate_slice_widths_from_packed_dims_(void);
std::vector<netrange_t> slice_dims_;
std::vector<unsigned long> slice_wids_;
unsigned eref_count_;
@ -756,7 +751,6 @@ class NetNet : public NetObj, public PortType {
int port_index_;
};
extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&rlist);
/*
* This object type is used to contain a logical scope within a

View File

@ -353,7 +353,7 @@ NetExpr *normalize_variable_base(NetExpr *base,
NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
const NetNet*reg)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size()+1 == packed_dims.size());
// Get the canonical offset of the slice within which we are
@ -369,7 +369,7 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
const NetNet*reg,
unsigned long wid, bool is_up)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size()+1 == packed_dims.size());
// Get the canonical offset of the slice within which we are
@ -384,10 +384,10 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
const NetNet*reg, unsigned long&lwid)
{
const list<netrange_t>&packed_dims = reg->packed_dims();
const vector<netrange_t>&packed_dims = reg->packed_dims();
ivl_assert(*base, indices.size() < packed_dims.size());
list<netrange_t>::const_iterator pcur = packed_dims.end();
vector<netrange_t>::const_iterator pcur = packed_dims.end();
for (size_t idx = indices.size() ; idx < packed_dims.size(); idx += 1) {
-- pcur;
}
@ -1182,8 +1182,8 @@ NetExpr*collapse_array_exprs(Design*des, NetScope*scope,
return *exprs.begin();
}
const std::list<netrange_t>&pdims = net->packed_dims();
std::list<netrange_t>::const_iterator pcur = pdims.begin();
const std::vector<netrange_t>&pdims = net->packed_dims();
std::vector<netrange_t>::const_iterator pcur = pdims.begin();
list<NetExpr*>::iterator ecur = exprs.begin();
NetExpr* base = 0;

58
netparray.cc Normal file
View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2012 Picture Elements, Inc.
* 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 "netparray.h"
using namespace std;
/*
* The packed width of a packed array is the packed width of the
* element times the dimension width of the array itself.
*/
long netparray_t::packed_width(void) const
{
long cur_width = element_type_->packed_width();
for (vector<netrange_t>::const_iterator cur = packed_dims_.begin()
; cur != packed_dims_.end() ; ++cur) {
cur_width *= cur->width();
}
return cur_width;
}
vector<netrange_t> netparray_t::slice_dimensions() const
{
vector<netrange_t> elem_dims = element_type_->slice_dimensions();
vector<netrange_t> res (packed_dims_.size() + elem_dims.size());
for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1)
res[idx] = packed_dims_[0];
for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1)
res[idx+packed_dims_.size()] = elem_dims[idx];
return res;
}
ivl_variable_type_t netparray_t::base_type() const
{
return element_type_->base_type();
}

View File

@ -20,29 +20,40 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
# include "LineInfo.h"
# include "nettypes.h"
# include <vector>
/*
* Packed arrays.
*/
class netparray_t : public ivl_type_s, public LineInfo {
class netparray_t : public ivl_type_s {
public:
explicit netparray_t(const std::list<netrange_t>&packed);
explicit netparray_t(const std::vector<netrange_t>&packed,
ivl_type_t etype);
~netparray_t();
inline const std::list<netrange_t>& packed_dimensions() const
public:
// Virtual methods from the ivl_type_s type...
long packed_width(void) const;
std::vector<netrange_t> slice_dimensions() const;
ivl_variable_type_t base_type() const;
public:
inline const ivl_type_s* element_type() const { return element_type_; }
inline const std::vector<netrange_t>& packed_dimensions() const
{ return packed_dims_; }
private:
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> packed_dims_;
ivl_type_t element_type_;
};
inline netparray_t::netparray_t(const std::list<netrange_t>&packed)
: packed_dims_(packed)
inline netparray_t::netparray_t(const std::vector<netrange_t>&packed,
ivl_type_t etype)
: packed_dims_(packed), element_type_(etype)
{
}

View File

@ -67,6 +67,13 @@ long netstruct_t::packed_width(void) const
return res;
}
vector<netrange_t> netstruct_t::slice_dimensions() const
{
vector<netrange_t> tmp;
tmp .push_back(netrange_t(packed_width()-1, 0));
return tmp;
}
ivl_variable_type_t netstruct_t::base_type() const
{
if (! packed_)

View File

@ -20,7 +20,7 @@
*/
# include "LineInfo.h"
# include <vector>
# include <vector>
# include "ivl_target.h"
# include "nettypes.h"
@ -30,7 +30,7 @@ class netstruct_t : public LineInfo, public ivl_type_s {
struct member_t {
perm_string name;
ivl_variable_type_t type;
list<netrange_t> packed_dims;
std::vector<netrange_t> packed_dims;
long width() const;
ivl_variable_type_t data_type() const { return type; };
// We need to keep the individual element sign information.
@ -54,6 +54,7 @@ class netstruct_t : public LineInfo, public ivl_type_s {
// Return the width (in bits) of the packed record, or -1 if
// the record is not packed.
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
// Return the base type of the packed record, or
// IVL_VT_NO_TYPE if the record is not packed.

View File

@ -31,6 +31,11 @@ long ivl_type_s::packed_width(void) const
return 1;
}
vector<netrange_t> ivl_type_s::slice_dimensions() const
{
return vector<netrange_t>();
}
ivl_variable_type_t ivl_type_s::base_type() const
{
return IVL_VT_NO_TYPE;
@ -41,10 +46,10 @@ bool ivl_type_s::get_signed() const
return false;
}
unsigned long netrange_width(const list<netrange_t>&packed)
unsigned long netrange_width(const vector<netrange_t>&packed)
{
unsigned wid = 1;
for (list<netrange_t>::const_iterator cur = packed.begin()
for (vector<netrange_t>::const_iterator cur = packed.begin()
; cur != packed.end() ; ++cur) {
unsigned use_wid = cur->width();
wid *= use_wid;
@ -59,14 +64,14 @@ unsigned long netrange_width(const list<netrange_t>&packed)
* and width of the resulting slice. In this case, the "sb" argument
* is an extra index of the prefix.
*/
bool prefix_to_slice(const std::list<netrange_t>&dims,
bool prefix_to_slice(const std::vector<netrange_t>&dims,
const std::list<long>&prefix, long sb,
long&loff, unsigned long&lwid)
{
assert(prefix.size() < dims.size());
size_t acc_wid = 1;
list<netrange_t>::const_iterator pcur = dims.end();
vector<netrange_t>::const_iterator pcur = dims.end();
for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) {
-- pcur;
acc_wid *= pcur->width();

View File

@ -20,10 +20,13 @@
*/
# include "ivl_target.h"
# include <list>
# include <climits>
# include <ostream>
# include <cassert>
# include <list>
# include <vector>
# include <climits>
# include <ostream>
# include <cassert>
class netrange_t;
/*
* This is a fully abstract type that is a type that can be attached
@ -33,6 +36,7 @@ class ivl_type_s {
public:
virtual ~ivl_type_s() =0;
virtual long packed_width(void) const;
virtual std::vector<netrange_t> slice_dimensions() const;
// Some types have a base variable type.
virtual ivl_variable_type_t base_type() const;
@ -78,14 +82,17 @@ class netrange_t {
long lsb_;
};
extern unsigned long netrange_width(const std::list<netrange_t>&dims);
extern std::ostream&operator << (std::ostream&out, const std::list<netrange_t>&rlist);
extern std::ostream&operator << (std::ostream&out, const std::vector<netrange_t>&rlist);
extern unsigned long netrange_width(const std::vector<netrange_t>&dims);
/*
* Take as input a list of packed dimensions and a list of prefix
* indices, and calculate the offset/width of the resulting slice into
* the packed array.
*/
extern bool prefix_to_slice(const std::list<netrange_t>&dims,
extern bool prefix_to_slice(const std::vector<netrange_t>&dims,
const std::list<long>&prefix, long sb,
long&loff, unsigned long&lwid);

View File

@ -19,6 +19,8 @@
# include "netvector.h"
using namespace std;
netvector_t::netvector_t(ivl_variable_type_t type, long msb, long lsb)
: type_(type), signed_(false)
{
@ -43,3 +45,8 @@ long netvector_t::packed_width() const
{
return netrange_width(packed_dims_);
}
vector<netrange_t> netvector_t::slice_dimensions() const
{
return packed_dims_;
}

View File

@ -26,6 +26,12 @@
class netvector_t : public ivl_type_s {
public:
explicit netvector_t(const std::vector<netrange_t>&packed,
ivl_variable_type_t type);
// This is a variant of the vector form. Some code processes
// the list of packed ranges as a list, but we will store them
// as a vector in this constructor.
explicit netvector_t(const std::list<netrange_t>&packed,
ivl_variable_type_t type);
@ -51,27 +57,28 @@ class netvector_t : public ivl_type_s {
inline bool get_scalar(void) const { return is_scalar_; }
ivl_variable_type_t base_type() const;
const std::list<netrange_t>&packed_dims() const;
const std::vector<netrange_t>&packed_dims() const;
long packed_width() const;
std::vector<netrange_t> slice_dimensions() const;
std::ostream& debug_dump(std::ostream&) const;
private:
std::list<netrange_t> packed_dims_;
std::vector<netrange_t> packed_dims_;
ivl_variable_type_t type_;
bool signed_ : 1;
bool isint_ : 1; // original type of integer
bool is_scalar_ : 1;
};
inline netvector_t::netvector_t(const std::list<netrange_t>&packed,
inline netvector_t::netvector_t(const std::vector<netrange_t>&packed,
ivl_variable_type_t type)
: packed_dims_(packed), type_(type), signed_(false)
{
}
inline const std::list<netrange_t>& netvector_t::packed_dims() const
inline const std::vector<netrange_t>& netvector_t::packed_dims() const
{
return packed_dims_;
}

View File

@ -2374,7 +2374,7 @@ void dll_target::signal(const NetNet*net)
ivl_signal_t object. */
{ size_t idx = 0;
list<netrange_t>::const_iterator cur;
vector<netrange_t>::const_iterator cur;
obj->packed_dims.resize(net->packed_dims().size());
for (cur = net->packed_dims().begin(), idx = 0
; cur != net->packed_dims().end() ; ++cur, idx += 1) {