Permalink
Browse files

Support struct members that are packed arrays.

  • Loading branch information...
steveicarus committed Mar 26, 2012
1 parent 9b816f6 commit 78b0b49a4eed6a3c26f58acea8318ec6ebb4d02f
Showing with 335 additions and 190 deletions.
  1. +2 −1 Makefile.in
  2. +2 −2 design_dump.cc
  3. +48 −13 elab_expr.cc
  4. +55 −6 elab_lval.cc
  5. +46 −56 elab_sig.cc
  6. +9 −68 netlist.cc
  7. +8 −25 netlist.h
  8. +8 −8 netmisc.cc
  9. +1 −1 netmisc.h
  10. +3 −8 netstruct.h
  11. +96 −0 nettypes.cc
  12. +55 −0 nettypes.h
  13. +1 −1 t-dll.cc
  14. +1 −1 t-dll.h
View
@@ -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 \
View
@@ -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 << "]";
}
View
@@ -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:
View
@@ -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;
}
View
@@ -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);
}
Oops, something went wrong.

0 comments on commit 78b0b49

Please sign in to comment.