Skip to content
Browse files

Support uwire resolved writes to non-overlapping parts

The individual bits of an unresolved wire may be assigned in
different continuous assignments without generating an error.
  • Loading branch information...
1 parent 764b38b commit 5d35ad8a0d2908c79133a2de3c2ab43dd47653c5 @steveicarus committed Jan 28, 2012
Showing with 34 additions and 8 deletions.
  1. +8 −7 elab_net.cc
  2. +1 −1 elab_sig.cc
  3. +20 −0 netlist.cc
  4. +5 −0 netlist.h
View
15 elab_net.cc
@@ -453,13 +453,6 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
sig->type(NetNet::UNRESOLVED_WIRE);
}
- if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->pin(0).is_linked()) {
- cerr << get_fileline() << ": error: Unresolved net/uwire "
- << sig->name() << " cannot have multiple drivers." << endl;
- des->errors += 1;
- return 0;
- }
-
/* Don't allow registers as assign l-values. */
if (sig->type() == NetNet::REG) {
cerr << get_fileline() << ": error: reg " << sig->name()
@@ -591,6 +584,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
unsigned subnet_wid = midx-lidx+1;
+ /* Check if the l-value bits are double-driven. */
+ if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_part_lref(midx,lidx)) {
+ cerr << get_fileline() << ": error: Unresolved net/uwire "
+ << sig->name() << " cannot have multiple drivers." << endl;
+ des->errors += 1;
+ return 0;
+ }
+
if (sig->pin_count() > 1) {
if (widx < 0 || widx >= (long) sig->pin_count()) {
cerr << get_fileline() << ": warning: ignoring out of "
View
2 elab_sig.cc
@@ -794,7 +794,7 @@ static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
struct_member_t*curp = *cur;
long use_msb = 0;
long use_lsb = 0;
- if (! curp->range->empty()) {
+ if (curp->range.get() && ! curp->range->empty()) {
ivl_assert(*curp, curp->range->size() == 2);
PExpr*msb_pex = curp->range->front();
PExpr*lsb_pex = curp->range->back();
View
20 netlist.cc
@@ -856,6 +856,26 @@ unsigned NetNet::peek_eref() const
return eref_count_;
}
+/*
+ * Test each of the bits in the range, and set them. If any bits are
+ * already set then return true.
+ */
+bool NetNet::test_part_lref(unsigned msb, unsigned lsb)
+{
+ if (lref_mask_.size() == 0)
+ lref_mask_.resize(vector_width());
+
+ bool rc = false;
+ for (unsigned idx = lsb ; idx <= msb ; idx += 1) {
+ if (lref_mask_[idx])
+ rc = true;
+ else
+ lref_mask_[idx] = true;
+ }
+
+ return rc;
+}
+
void NetNet::incr_lref()
{
lref_count_ += 1;
View
5 netlist.h
@@ -660,6 +660,7 @@ class NetNet : public NetObj {
void incr_lref();
void decr_lref();
unsigned peek_lref() const { return lref_count_; }
+ bool test_part_lref(unsigned msb, unsigned lsb);
unsigned get_refs() const;
@@ -691,6 +692,10 @@ class NetNet : public NetObj {
unsigned eref_count_;
unsigned lref_count_;
+ // When the signal is an unresolved wire, we need more detail
+ // which bits are assigned. This mask is true for each bit
+ // that is known to be driven.
+ std::vector<bool> lref_mask_;
vector<class NetDelaySrc*> delay_paths_;
};

0 comments on commit 5d35ad8

Please sign in to comment.
Something went wrong with that request. Please try again.