Support struct members that are packed arrays.
This commit is contained in:
parent
9b816f6478
commit
78b0b49a4e
|
|
@ -106,7 +106,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
|||
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
|
||||
elab_scope.o elab_sig.o elab_sig_analog.o emit.o eval.o eval_attrib.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o netlist.o netmisc.o net_analog.o net_assign.o net_design.o \
|
||||
load_module.o netlist.o netmisc.o nettypes.o net_analog.o net_assign.o \
|
||||
net_design.o \
|
||||
netenum.o netstruct.o net_event.o net_expr.o net_func.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 \
|
||||
|
|
|
|||
|
|
@ -187,9 +187,9 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
|||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
ostream&operator<<(ostream&out, const list<NetNet::range_t>&rlist)
|
||||
ostream&operator<<(ostream&out, const list<netrange_t>&rlist)
|
||||
{
|
||||
for (list<NetNet::range_t>::const_iterator cur = rlist.begin()
|
||||
for (list<netrange_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
out << "[" << cur->msb << ":" << cur->lsb << "]";
|
||||
}
|
||||
|
|
|
|||
61
elab_expr.cc
61
elab_expr.cc
|
|
@ -1442,24 +1442,59 @@ static const netstruct_t::member_t*get_struct_member(const LineInfo*li,
|
|||
|
||||
return type->packed_member(method_name, off);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the tail name (method_name argument) is a member name and
|
||||
* the net is a struct. If that turns out to be the case, and the
|
||||
* struct is packed, then return a NetExpr that selects the member out
|
||||
* of the variable.
|
||||
*/
|
||||
static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
Design*des, NetScope*,
|
||||
NetNet*net, perm_string method_name)
|
||||
Design*des, NetScope*scope,
|
||||
NetNet*net, const name_component_t&comp)
|
||||
{
|
||||
unsigned long off;
|
||||
const netstruct_t::member_t*mem = get_struct_member(li, des, 0, net,
|
||||
method_name, off);
|
||||
comp.name, off);
|
||||
if (mem == 0) return 0;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": debug: Found struct member " <<mem->name
|
||||
cerr << li->get_fileline() << ": debug: Found struct member " << mem->name
|
||||
<< " At offset " << off << endl;
|
||||
}
|
||||
|
||||
unsigned use_width = mem->width();
|
||||
|
||||
if ( ! comp.index.empty() ) {
|
||||
// Evaluate all but the last index expression, into prefix_indices.
|
||||
list<long>prefix_indices;
|
||||
bool rc = evaluate_index_prefix(des, scope, prefix_indices, comp.index);
|
||||
ivl_assert(*li, rc);
|
||||
|
||||
// Evaluate the last index expression into a constant long.
|
||||
NetExpr*texpr = elab_and_eval(des, scope, comp.index.back().msb, -1, true);
|
||||
long tmp;
|
||||
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
|
||||
cerr << li->get_fileline() << ": error: "
|
||||
"Array index expressions must be constant here." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
// Now use the prefix_to_slice function to calculate the
|
||||
// offset and width of the addressed slice of the member.
|
||||
long loff;
|
||||
unsigned long lwid;
|
||||
prefix_to_slice(mem->packed_dims, prefix_indices, tmp, loff, lwid);
|
||||
|
||||
off += loff;
|
||||
use_width = lwid;
|
||||
}
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
NetEConst*base = make_const_val(off);
|
||||
NetESelect*sel = new NetESelect(sig, base, mem->width());
|
||||
NetESelect*sel = new NetESelect(sig, base, use_width);
|
||||
return sel;
|
||||
}
|
||||
|
||||
|
|
@ -2350,7 +2385,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
// really a method attached to an object.
|
||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
perm_string method_name = peek_tail_name(use_path);
|
||||
name_component_t member_comp = use_path.back();
|
||||
use_path.pop_back();
|
||||
|
||||
found_in = symbol_search(this, des, scope, use_path,
|
||||
|
|
@ -2372,7 +2407,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
return check_for_enum_methods(this, des, scope,
|
||||
netenum,
|
||||
use_path, method_name,
|
||||
use_path, member_comp.name,
|
||||
expr, expr_wid, NULL, 0);
|
||||
}
|
||||
|
||||
|
|
@ -2382,7 +2417,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
|||
ivl_assert(*this, use_path.back().index.empty());
|
||||
|
||||
return check_for_struct_members(this, des, scope,
|
||||
net, method_name);
|
||||
net, member_comp);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3279,11 +3314,11 @@ 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<NetNet::range_t>&packed = net->sig()->packed_dims();
|
||||
const list<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.
|
||||
const NetNet::range_t&rng = packed.back();
|
||||
const netrange_t&rng = packed.back();
|
||||
if (rng.msb < rng.lsb) {
|
||||
offset = -wid + 1;
|
||||
}
|
||||
|
|
@ -3494,7 +3529,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
|
||||
long msv = msc->value().as_long();
|
||||
|
||||
const list<NetNet::range_t>& sig_packed = net->sig()->packed_dims();
|
||||
const list<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:
|
||||
|
|
@ -3561,7 +3596,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
|||
return res;
|
||||
}
|
||||
|
||||
const list<NetNet::range_t>& sig_packed = net->sig()->packed_dims();
|
||||
const list<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:
|
||||
|
|
|
|||
61
elab_lval.cc
61
elab_lval.cc
|
|
@ -455,7 +455,7 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
const list<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.
|
||||
|
|
@ -544,11 +544,11 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
long lsv = base_c->value().as_long();
|
||||
long offset = 0;
|
||||
// Get the signal range.
|
||||
const list<NetNet::range_t>&packed = reg->packed_dims();
|
||||
const list<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.
|
||||
const NetNet::range_t&rng = packed.back();
|
||||
const netrange_t&rng = packed.back();
|
||||
if (((rng.msb < rng.lsb) &&
|
||||
use_sel == index_component_t::SEL_IDX_UP) ||
|
||||
((rng.msb > rng.lsb) &&
|
||||
|
|
@ -621,8 +621,7 @@ bool PEIdent::elaborate_lval_net_idx_(Design*des,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
|
||||
NetScope*,
|
||||
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
const perm_string&member_name) const
|
||||
{
|
||||
|
|
@ -649,7 +648,57 @@ bool PEIdent::elaborate_lval_net_packed_member_(Design*des,
|
|||
return false;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(off)), member->width());
|
||||
unsigned long use_width = member->width();
|
||||
|
||||
// We are processing the tail of a string of names. For
|
||||
// example, the verilog may be "a.b.c", so we are processing
|
||||
// "c" at this point. Of course, "c" is the name of the member
|
||||
// we are working on and "a.b" is the name of reg.
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (name_tail.index.size() > member->packed_dims.size()) {
|
||||
cerr << get_fileline() << ": error: Too make index expressions for member." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the index component type. At this point, we only
|
||||
// support bit select or none.
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
ivl_assert(*this, use_sel == index_component_t::SEL_NONE || use_sel == index_component_t::SEL_BIT);
|
||||
|
||||
if (name_tail.index.size() > 0) {
|
||||
// Evaluate all but the last index expression, into prefix_indices.
|
||||
list<long>prefix_indices;
|
||||
bool rc = evaluate_index_prefix(des, scope, prefix_indices, name_tail.index);
|
||||
ivl_assert(*this, rc);
|
||||
|
||||
// Evaluate the last index expression into a constant long.
|
||||
NetExpr*texpr = elab_and_eval(des, scope, name_tail.index.back().msb, -1, true);
|
||||
long tmp;
|
||||
if (texpr == 0 || !eval_as_long(tmp, texpr)) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Array index expressions must be constant here." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
// Now use the prefix_to_slice function to calculate the
|
||||
// offset and width of the addressed slice of the member.
|
||||
long loff;
|
||||
unsigned long lwid;
|
||||
prefix_to_slice(member->packed_dims, prefix_indices, tmp, loff, lwid);
|
||||
|
||||
off += loff;
|
||||
use_width = lwid;
|
||||
}
|
||||
|
||||
lv->set_part(new NetEConst(verinum(off)), use_width);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
102
elab_sig.cc
102
elab_sig.cc
|
|
@ -514,8 +514,8 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|||
des->errors += 1;
|
||||
}
|
||||
|
||||
list<NetNet::range_t> packed;
|
||||
packed.push_back(NetNet::range_t(mnum, lnum));
|
||||
list<netrange_t> packed;
|
||||
packed.push_back(netrange_t(mnum, lnum));
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, packed);
|
||||
ret_sig->set_scalar(false);
|
||||
|
||||
|
|
@ -813,61 +813,15 @@ void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
|||
statement_->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
|
||||
struct_type_t*struct_type)
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(struct_type->packed_flag);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
|
||||
; cur != struct_type->members->end() ; ++ cur) {
|
||||
|
||||
struct_member_t*curp = *cur;
|
||||
long use_msb = 0;
|
||||
long use_lsb = 0;
|
||||
if (curp->range.get() && ! curp->range->empty()) {
|
||||
ivl_assert(*curp, curp->range->size() == 1);
|
||||
pform_range_t&rangep = curp->range->front();
|
||||
PExpr*msb_pex = rangep.first;
|
||||
PExpr*lsb_pex = rangep.second;
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, msb_pex, -2, true);
|
||||
ivl_assert(*curp, tmp);
|
||||
bool rc = eval_as_long(use_msb, tmp);
|
||||
ivl_assert(*curp, rc);
|
||||
|
||||
tmp = elab_and_eval(des, scope, lsb_pex, -2, true);
|
||||
ivl_assert(*curp, tmp);
|
||||
rc = eval_as_long(use_lsb, tmp);
|
||||
ivl_assert(*curp, rc);
|
||||
}
|
||||
|
||||
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
||||
; name != curp->names->end() ; ++ name) {
|
||||
decl_assignment_t*namep = *name;
|
||||
|
||||
netstruct_t::member_t memb;
|
||||
memb.name = namep->name;
|
||||
memb.type = curp->type;
|
||||
memb.msb = use_msb;
|
||||
memb.lsb = use_lsb;
|
||||
res->append_member(memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
list<NetNet::range_t>&llist,
|
||||
list<netrange_t>&llist,
|
||||
const list<pform_range_t>&rlist)
|
||||
{
|
||||
bool bad_msb = false, bad_lsb = false;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
||||
; cur != rlist.end() ; ++cur) {
|
||||
NetNet::range_t lrng;
|
||||
netrange_t lrng;
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
||||
if (! eval_as_long(lrng.msb, texpr)) {
|
||||
|
|
@ -901,13 +855,49 @@ static bool evaluate_ranges(Design*des, NetScope*scope,
|
|||
return bad_msb | bad_lsb;
|
||||
}
|
||||
|
||||
bool test_ranges_eeq(const list<NetNet::range_t>&lef, const list<NetNet::range_t>&rig)
|
||||
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
|
||||
struct_type_t*struct_type)
|
||||
{
|
||||
netstruct_t*res = new netstruct_t;
|
||||
|
||||
res->packed(struct_type->packed_flag);
|
||||
|
||||
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
|
||||
; cur != struct_type->members->end() ; ++ cur) {
|
||||
|
||||
list<netrange_t>packed_dimensions;
|
||||
|
||||
struct_member_t*curp = *cur;
|
||||
if (curp->range.get() && ! curp->range->empty()) {
|
||||
bool bad_range;
|
||||
bad_range = evaluate_ranges(des, scope, packed_dimensions, *curp->range);
|
||||
ivl_assert(*curp, !bad_range);
|
||||
} else {
|
||||
packed_dimensions.push_back(netrange_t(0,0));
|
||||
}
|
||||
|
||||
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
||||
; name != curp->names->end() ; ++ name) {
|
||||
decl_assignment_t*namep = *name;
|
||||
|
||||
netstruct_t::member_t memb;
|
||||
memb.name = namep->name;
|
||||
memb.type = curp->type;
|
||||
memb.packed_dims = packed_dimensions;
|
||||
res->append_member(memb);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
|
||||
{
|
||||
if (lef.size() != rig.size())
|
||||
return false;
|
||||
|
||||
list<NetNet::range_t>::const_iterator lcur = lef.begin();
|
||||
list<NetNet::range_t>::const_iterator rcur = rig.begin();
|
||||
list<netrange_t>::const_iterator lcur = lef.begin();
|
||||
list<netrange_t>::const_iterator rcur = rig.begin();
|
||||
while (lcur != lef.end()) {
|
||||
if (lcur->msb != rcur->msb)
|
||||
return false;
|
||||
|
|
@ -942,7 +932,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
unsigned wid = 1;
|
||||
list<NetNet::range_t>packed_dimensions;
|
||||
list<netrange_t>packed_dimensions;
|
||||
|
||||
des->errors += error_cnt_;
|
||||
|
||||
|
|
@ -983,7 +973,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
|
||||
if (port_set_ || net_set_) {
|
||||
bool bad_range = false;
|
||||
list<NetNet::range_t> plist, nlist;
|
||||
list<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_);
|
||||
|
|
@ -1049,7 +1039,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
|
||||
packed_dimensions = nlist;
|
||||
wid = NetNet::vector_width(packed_dimensions);
|
||||
wid = netrange_width(packed_dimensions);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
77
netlist.cc
77
netlist.cc
|
|
@ -458,7 +458,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
|||
assert(npins>0);
|
||||
|
||||
// Synthesize a single range to describe this canonical vector.
|
||||
packed_dims_.push_back(NetNet::range_t(npins-1, 0));
|
||||
packed_dims_.push_back(netrange_t(npins-1, 0));
|
||||
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
|
|
@ -496,7 +496,7 @@ void NetNet::initialize_dir_(Link::DIR dir)
|
|||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
const list<NetNet::range_t>&packed)
|
||||
const list<netrange_t>&packed)
|
||||
: NetObj(s, n, 1), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
isint_(false), is_scalar_(false), local_flag_(false),
|
||||
|
|
@ -544,7 +544,7 @@ static unsigned calculate_count(long s, long e)
|
|||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
const list<NetNet::range_t>&packed, long array_s, long array_e)
|
||||
const list<netrange_t>&packed, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
type_(t), port_type_(NOT_A_PORT),
|
||||
data_type_(IVL_VT_NO_TYPE), signed_(false), isint_(false),
|
||||
|
|
@ -605,7 +605,7 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, netstruct_t*ty)
|
|||
dimensions_(0), s0_(0), e0_(0),
|
||||
eref_count_(0), lref_count_(0)
|
||||
{
|
||||
packed_dims_.push_back(range_t(calculate_count(ty)-1, 0));
|
||||
packed_dims_.push_back(netrange_t(calculate_count(ty)-1, 0));
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
switch (t) {
|
||||
|
|
@ -764,27 +764,11 @@ void NetNet::set_discipline(ivl_discipline_t dis)
|
|||
discipline_ = dis;
|
||||
}
|
||||
|
||||
unsigned long NetNet::vector_width(const list<NetNet::range_t>&packed)
|
||||
{
|
||||
unsigned wid = 1;
|
||||
for (list<NetNet::range_t>::const_iterator cur = packed.begin()
|
||||
; cur != packed.end() ; ++cur) {
|
||||
unsigned use_wid;
|
||||
if (cur->msb >= cur->lsb)
|
||||
use_wid = cur->msb - cur->lsb + 1;
|
||||
else
|
||||
use_wid = cur->lsb - cur->msb + 1;
|
||||
wid *= use_wid;
|
||||
}
|
||||
|
||||
return wid;
|
||||
}
|
||||
|
||||
bool NetNet::sb_is_valid(const list<long>&indices, long sb) const
|
||||
{
|
||||
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
|
||||
assert(packed_dims_.size() == 1);
|
||||
const range_t&rng = packed_dims_.back();
|
||||
const netrange_t&rng = packed_dims_.back();
|
||||
if (rng.msb >= rng.lsb)
|
||||
return (sb <= rng.msb) && (sb >= rng.lsb);
|
||||
else
|
||||
|
|
@ -795,7 +779,7 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
|
|||
{
|
||||
ivl_assert(*this, indices.size()+1 == packed_dims_.size());
|
||||
|
||||
list<range_t>::const_iterator pcur = packed_dims_.end();
|
||||
list<netrange_t>::const_iterator pcur = packed_dims_.end();
|
||||
-- pcur;
|
||||
|
||||
long acc_off;
|
||||
|
|
@ -832,50 +816,7 @@ long NetNet::sb_to_idx(const list<long>&indices, long sb) const
|
|||
bool NetNet::sb_to_slice(const list<long>&indices, long sb, long&loff, unsigned long&lwid) const
|
||||
{
|
||||
ivl_assert(*this, indices.size() < packed_dims_.size());
|
||||
|
||||
size_t acc_wid = 1;
|
||||
list<range_t>::const_iterator pcur = packed_dims_.end();
|
||||
for (size_t idx = indices.size()+1 ; idx < packed_dims_.size() ; idx += 1) {
|
||||
-- pcur;
|
||||
acc_wid *= pcur->width();
|
||||
}
|
||||
|
||||
lwid = acc_wid;
|
||||
|
||||
-- pcur;
|
||||
if (sb < pcur->msb && sb < pcur->lsb)
|
||||
return false;
|
||||
if (sb > pcur->msb && sb > pcur->lsb)
|
||||
return false;
|
||||
|
||||
long acc_off = 0;
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
acc_off += (sb - pcur->lsb) * acc_wid;
|
||||
else
|
||||
acc_off += (sb - pcur->msb) * acc_wid;
|
||||
|
||||
if (indices.size() == 0) {
|
||||
loff = acc_off;
|
||||
return true;
|
||||
}
|
||||
|
||||
lwid *= pcur->width();
|
||||
|
||||
list<long>::const_iterator icur = indices.end();
|
||||
do {
|
||||
-- pcur;
|
||||
-- icur;
|
||||
acc_wid *= pcur->width();
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
acc_off += (*icur - pcur->lsb) * acc_wid;
|
||||
else
|
||||
acc_off += (*icur - pcur->msb) * acc_wid;
|
||||
|
||||
} while (icur != indices.begin());
|
||||
|
||||
loff = acc_off;
|
||||
|
||||
return true;
|
||||
return prefix_to_slice(packed_dims_, indices, sb, loff, lwid);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2461,14 +2402,14 @@ NetNet* NetESignal::sig()
|
|||
*/
|
||||
long NetESignal::lsi() const
|
||||
{
|
||||
const list<NetNet::range_t>&packed = net_->packed_dims();
|
||||
const list<netrange_t>&packed = net_->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
return packed.back().lsb;
|
||||
}
|
||||
|
||||
long NetESignal::msi() const
|
||||
{
|
||||
const list<NetNet::range_t>&packed = net_->packed_dims();
|
||||
const list<netrange_t>&packed = net_->packed_dims();
|
||||
ivl_assert(*this, packed.size() == 1);
|
||||
return packed.back().msb;
|
||||
}
|
||||
|
|
|
|||
33
netlist.h
33
netlist.h
|
|
@ -35,6 +35,7 @@
|
|||
# include "ivl_target_priv.h"
|
||||
# include "pform_types.h"
|
||||
# include "config.h"
|
||||
# include "nettypes.h"
|
||||
# include "verinum.h"
|
||||
# include "verireal.h"
|
||||
# include "StringHeap.h"
|
||||
|
|
@ -563,21 +564,6 @@ class NetNet : public NetObj {
|
|||
|
||||
enum PortType { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
|
||||
struct range_t {
|
||||
inline range_t() : msb(0), lsb(0) { }
|
||||
inline range_t(long m, long l) : msb(m), lsb(l) { }
|
||||
inline range_t(const range_t&that)
|
||||
: msb(that.msb), lsb(that.lsb) { }
|
||||
inline range_t& operator = (const range_t&that)
|
||||
{ msb = that.msb; lsb = that.lsb; return *this; }
|
||||
|
||||
long msb;
|
||||
long lsb;
|
||||
|
||||
inline unsigned long width()const
|
||||
{ if (msb >= lsb) return msb-lsb+1; else return lsb-msb+1; }
|
||||
};
|
||||
|
||||
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
|
||||
|
|
@ -589,9 +575,9 @@ class NetNet : public NetObj {
|
|||
// dimensions. If s0==e0, then this is not an array after
|
||||
// all.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
const std::list<range_t>&packed);
|
||||
const std::list<netrange_t>&packed);
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
const std::list<range_t>&packed, long s0, long e0);
|
||||
const std::list<netrange_t>&packed, long s0, long e0);
|
||||
|
||||
// This form builds a NetNet from its record definition.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, netstruct_t*type);
|
||||
|
|
@ -633,14 +619,11 @@ class NetNet : public NetObj {
|
|||
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<range_t>& packed_dims() const { return packed_dims_; }
|
||||
const std::list<netrange_t>& packed_dims() const { return packed_dims_; }
|
||||
|
||||
/* The vector_width returns the bit width of the packed array,
|
||||
vector or scaler that is this NetNet object. The static
|
||||
method is also a convenient way to convert a range list to
|
||||
a vector width. */
|
||||
static unsigned long vector_width(const std::list<NetNet::range_t>&);
|
||||
unsigned long vector_width() const { return vector_width(packed_dims_); }
|
||||
vector or scaler that is this NetNet object. */
|
||||
unsigned long vector_width() const { return netrange_width(packed_dims_); }
|
||||
|
||||
/* Given a prefix of indices, figure out how wide the
|
||||
resulting slice would be. This is a generalization of the
|
||||
|
|
@ -722,7 +705,7 @@ class NetNet : public NetObj {
|
|||
netstruct_t*struct_type_;
|
||||
ivl_discipline_t discipline_;
|
||||
|
||||
std::list<range_t> packed_dims_;
|
||||
std::list<netrange_t> packed_dims_;
|
||||
const unsigned dimensions_;
|
||||
long s0_, e0_;
|
||||
|
||||
|
|
@ -736,7 +719,7 @@ class NetNet : public NetObj {
|
|||
vector<class NetDelaySrc*> delay_paths_;
|
||||
};
|
||||
|
||||
extern std::ostream&operator << (std::ostream&out, const std::list<NetNet::range_t>&rlist);
|
||||
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
|
||||
|
|
|
|||
16
netmisc.cc
16
netmisc.cc
|
|
@ -320,24 +320,24 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb,
|
|||
* vector. For now, we assert that there is only one set of dimensions.
|
||||
*/
|
||||
NetExpr *normalize_variable_base(NetExpr *base,
|
||||
const list<NetNet::range_t>&dims,
|
||||
const list<netrange_t>&dims,
|
||||
unsigned long wid, bool is_up)
|
||||
{
|
||||
ivl_assert(*base, dims.size() == 1);
|
||||
const NetNet::range_t&rng = dims.back();
|
||||
const netrange_t&rng = dims.back();
|
||||
return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up);
|
||||
}
|
||||
|
||||
NetExpr *normalize_variable_bit_base(const list<long>&indices, NetExpr*base,
|
||||
const NetNet*reg)
|
||||
{
|
||||
const list<NetNet::range_t>&packed_dims = reg->packed_dims();
|
||||
const list<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
|
||||
// addressing. We need that address as a slice offset to
|
||||
// calculate the proper complete address
|
||||
const NetNet::range_t&rng = packed_dims.back();
|
||||
const netrange_t&rng = packed_dims.back();
|
||||
long slice_off = reg->sb_to_idx(indices, rng.lsb);
|
||||
|
||||
return normalize_variable_base(base, rng.msb, rng.lsb, 1, true, slice_off);
|
||||
|
|
@ -347,13 +347,13 @@ NetExpr *normalize_variable_part_base(const list<long>&indices, NetExpr*base,
|
|||
const NetNet*reg,
|
||||
unsigned long wid, bool is_up)
|
||||
{
|
||||
const list<NetNet::range_t>&packed_dims = reg->packed_dims();
|
||||
const list<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
|
||||
// addressing. We need that address as a slice offset to
|
||||
// calculate the proper complete address
|
||||
const NetNet::range_t&rng = packed_dims.back();
|
||||
const netrange_t&rng = packed_dims.back();
|
||||
long slice_off = reg->sb_to_idx(indices, rng.lsb);
|
||||
|
||||
return normalize_variable_base(base, rng.msb, rng.lsb, wid, is_up, slice_off);
|
||||
|
|
@ -362,10 +362,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<NetNet::range_t>&packed_dims = reg->packed_dims();
|
||||
const list<netrange_t>&packed_dims = reg->packed_dims();
|
||||
ivl_assert(*base, indices.size() < packed_dims.size());
|
||||
|
||||
list<NetNet::range_t>::const_iterator pcur = packed_dims.end();
|
||||
list<netrange_t>::const_iterator pcur = packed_dims.end();
|
||||
for (size_t idx = indices.size() ; idx < packed_dims.size(); idx += 1) {
|
||||
-- pcur;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ extern NetExpr*normalize_variable_base(NetExpr *base, long msb, long lsb,
|
|||
unsigned long wid, bool is_up,
|
||||
long slice_off =0);
|
||||
extern NetExpr*normalize_variable_base(NetExpr *base,
|
||||
const list<NetNet::range_t>&dims,
|
||||
const list<netrange_t>&dims,
|
||||
unsigned long wid, bool is_up);
|
||||
|
||||
/*
|
||||
|
|
|
|||
11
netstruct.h
11
netstruct.h
|
|
@ -22,6 +22,7 @@
|
|||
# include "LineInfo.h"
|
||||
# include <vector>
|
||||
# include "ivl_target.h"
|
||||
# include "nettypes.h"
|
||||
|
||||
class netstruct_t : public LineInfo {
|
||||
|
||||
|
|
@ -29,8 +30,7 @@ class netstruct_t : public LineInfo {
|
|||
struct member_t {
|
||||
perm_string name;
|
||||
ivl_variable_type_t type;
|
||||
long msb;
|
||||
long lsb;
|
||||
list<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.
|
||||
|
|
@ -63,11 +63,6 @@ class netstruct_t : public LineInfo {
|
|||
inline bool netstruct_t::packed(void) const { return packed_; }
|
||||
|
||||
inline long netstruct_t::member_t::width() const
|
||||
{
|
||||
if (msb >= lsb)
|
||||
return msb - lsb + 1;
|
||||
else
|
||||
return lsb - msb + 1;
|
||||
}
|
||||
{ return netrange_width(packed_dims); }
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2012 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include "nettypes.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
unsigned long netrange_width(const list<netrange_t>&packed)
|
||||
{
|
||||
unsigned wid = 1;
|
||||
for (list<netrange_t>::const_iterator cur = packed.begin()
|
||||
; cur != packed.end() ; ++cur) {
|
||||
unsigned use_wid;
|
||||
if (cur->msb >= cur->lsb)
|
||||
use_wid = cur->msb - cur->lsb + 1;
|
||||
else
|
||||
use_wid = cur->lsb - cur->msb + 1;
|
||||
wid *= use_wid;
|
||||
}
|
||||
|
||||
return wid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a netrange_t list (which represent packed dimensions) and a
|
||||
* prefix of calculated index values, calculate the canonical offset
|
||||
* 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,
|
||||
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();
|
||||
for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) {
|
||||
-- pcur;
|
||||
acc_wid *= pcur->width();
|
||||
}
|
||||
|
||||
lwid = acc_wid;
|
||||
|
||||
-- pcur;
|
||||
if (sb < pcur->msb && sb < pcur->lsb)
|
||||
return false;
|
||||
if (sb > pcur->msb && sb > pcur->lsb)
|
||||
return false;
|
||||
|
||||
long acc_off = 0;
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
acc_off += (sb - pcur->lsb) * acc_wid;
|
||||
else
|
||||
acc_off += (sb - pcur->msb) * acc_wid;
|
||||
|
||||
if (prefix.size() == 0) {
|
||||
loff = acc_off;
|
||||
return true;
|
||||
}
|
||||
|
||||
lwid *= pcur->width();
|
||||
|
||||
list<long>::const_iterator icur = prefix.end();
|
||||
do {
|
||||
-- pcur;
|
||||
-- icur;
|
||||
acc_wid *= pcur->width();
|
||||
if (pcur->msb >= pcur->lsb)
|
||||
acc_off += (*icur - pcur->lsb) * acc_wid;
|
||||
else
|
||||
acc_off += (*icur - pcur->msb) * acc_wid;
|
||||
|
||||
} while (icur != prefix.begin());
|
||||
|
||||
loff = acc_off;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef __nettypes_H
|
||||
#define __nettypes_H
|
||||
/*
|
||||
* Copyright (c) 2012 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
# include <list>
|
||||
|
||||
class netrange_t {
|
||||
|
||||
public:
|
||||
inline netrange_t() : msb(0), lsb(0) { }
|
||||
inline netrange_t(long m, long l) : msb(m), lsb(l) { }
|
||||
|
||||
inline netrange_t(const netrange_t&that)
|
||||
: msb(that.msb), lsb(that.lsb) { }
|
||||
|
||||
inline netrange_t& operator = (const netrange_t&that)
|
||||
{ msb = that.msb; lsb = that.lsb; return *this; }
|
||||
|
||||
public:
|
||||
long msb;
|
||||
long lsb;
|
||||
|
||||
inline unsigned long width()const
|
||||
{ if (msb >= lsb) return msb-lsb+1; else return lsb-msb+1; }
|
||||
};
|
||||
|
||||
extern unsigned long netrange_width(const std::list<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,
|
||||
const std::list<long>&prefix, long sb,
|
||||
long&loff, unsigned long&lwid);
|
||||
|
||||
#endif
|
||||
2
t-dll.cc
2
t-dll.cc
|
|
@ -2387,7 +2387,7 @@ void dll_target::signal(const NetNet*net)
|
|||
ivl_signal_t object. */
|
||||
|
||||
{ size_t idx = 0;
|
||||
list<NetNet::range_t>::const_iterator cur;
|
||||
list<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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue