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:
parent
764b38bb3b
commit
5d35ad8a0d
15
elab_net.cc
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 "
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
20
netlist.cc
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;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue