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.
This commit is contained in:
Stephen Williams 2012-01-28 10:20:09 -08:00
parent 764b38bb3b
commit 5d35ad8a0d
4 changed files with 34 additions and 8 deletions

View File

@ -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 File

@ -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 File

@ -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 File

@ -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_;
};