Allow mixed procedural/continuous assignment for array words.

This is legal if the procedural and continuous assignments target
different words.

NOTE: This is not fully compliant with the standard, because vvp
does not know that the nets were originally declared as variables,
so initialises to 'bz instead of 'bx and does not handle release
correctly.
This commit is contained in:
Martin Whitaker 2024-02-03 17:55:32 +00:00
parent cd2d4e9287
commit 89bb86962f
3 changed files with 40 additions and 5 deletions

View File

@ -468,11 +468,15 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
if ((reg->type()==NetNet::UNRESOLVED_WIRE) && !is_force) {
ivl_assert(*this, reg->coerced_to_uwire());
cerr << get_fileline() << ": error: Cannot perform "
"procedural assignment to word in array '" << reg->name()
<< "' because it is also continuously assigned." << endl;
des->errors += 1;
return 0;
NetEConst*canon_const = dynamic_cast<NetEConst*>(canon_index);
if (!canon_const || reg->test_part_driven(reg->vector_width() - 1, 0,
canon_const->value().as_long())) {
cerr << get_fileline() << ": error: Cannot perform "
"procedural assignment to word in array '" << reg->name()
<< "' because it is also continuously assigned." << endl;
des->errors += 1;
return 0;
}
}
NetAssign_*lv = new NetAssign_(reg);

View File

@ -829,6 +829,30 @@ unsigned NetNet::peek_eref() const
return eref_count_;
}
/*
* Test each of the bits in the range. If any bits are set then return true.
*/
bool NetNet::test_part_driven(unsigned pmsb, unsigned plsb, int widx)
{
if (lref_mask_.empty())
return false;
// If indexing a word that doesn't exist, then pretend this is
// never driven.
if (widx < 0)
return false;
if (widx >= (int)pin_count())
return false;
unsigned word_base = vector_width() * widx;
for (unsigned idx = plsb ; idx <= pmsb ; idx += 1) {
if (lref_mask_[idx+word_base])
return true;
}
return false;
}
/*
* Test each of the bits in the range, and set them. If any bits are
* already set then return true.

View File

@ -793,6 +793,13 @@ class NetNet : public NetObj, public PortType {
// only useful for UNRESOLVED_WIRE objects. The msb and lsb
// are the part select of the signal, and the widx is the word
// index if this is an unpacked array.
bool test_part_driven(unsigned msb, unsigned lsb, int widx =0);
// Treating this node as a uwire, this function tests whether
// any bits in the canonical part are already driven and sets
// them if not. This is only useful for UNRESOLVED_WIRE objects.
// The msb and lsb are the part select of the signal, and the
// widx is the word index if this is an unpacked array.
bool test_and_set_part_driver(unsigned msb, unsigned lsb, int widx =0);
unsigned get_refs() const;