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);
|
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. */
|
/* Don't allow registers as assign l-values. */
|
||||||
if (sig->type() == NetNet::REG) {
|
if (sig->type() == NetNet::REG) {
|
||||||
cerr << get_fileline() << ": error: reg " << sig->name()
|
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;
|
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 (sig->pin_count() > 1) {
|
||||||
if (widx < 0 || widx >= (long) sig->pin_count()) {
|
if (widx < 0 || widx >= (long) sig->pin_count()) {
|
||||||
cerr << get_fileline() << ": warning: ignoring out of "
|
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;
|
struct_member_t*curp = *cur;
|
||||||
long use_msb = 0;
|
long use_msb = 0;
|
||||||
long use_lsb = 0;
|
long use_lsb = 0;
|
||||||
if (! curp->range->empty()) {
|
if (curp->range.get() && ! curp->range->empty()) {
|
||||||
ivl_assert(*curp, curp->range->size() == 2);
|
ivl_assert(*curp, curp->range->size() == 2);
|
||||||
PExpr*msb_pex = curp->range->front();
|
PExpr*msb_pex = curp->range->front();
|
||||||
PExpr*lsb_pex = curp->range->back();
|
PExpr*lsb_pex = curp->range->back();
|
||||||
|
|
|
||||||
20
netlist.cc
20
netlist.cc
|
|
@ -856,6 +856,26 @@ unsigned NetNet::peek_eref() const
|
||||||
return eref_count_;
|
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()
|
void NetNet::incr_lref()
|
||||||
{
|
{
|
||||||
lref_count_ += 1;
|
lref_count_ += 1;
|
||||||
|
|
|
||||||
|
|
@ -660,6 +660,7 @@ class NetNet : public NetObj {
|
||||||
void incr_lref();
|
void incr_lref();
|
||||||
void decr_lref();
|
void decr_lref();
|
||||||
unsigned peek_lref() const { return lref_count_; }
|
unsigned peek_lref() const { return lref_count_; }
|
||||||
|
bool test_part_lref(unsigned msb, unsigned lsb);
|
||||||
|
|
||||||
unsigned get_refs() const;
|
unsigned get_refs() const;
|
||||||
|
|
||||||
|
|
@ -691,6 +692,10 @@ class NetNet : public NetObj {
|
||||||
|
|
||||||
unsigned eref_count_;
|
unsigned eref_count_;
|
||||||
unsigned lref_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_;
|
vector<class NetDelaySrc*> delay_paths_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue