Sanity check to prevent bad code getting through synth2 blending
When conditional ports are blending (by allowing NetPartSelects be connected together to the outputs) make sure there isn't an accidental overlap of drivers that invalidates the process.
This commit is contained in:
parent
579b59b8eb
commit
ded1bd4949
|
|
@ -232,3 +232,58 @@ verinum Nexus::driven_vector() const
|
||||||
|
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate a vector that represent all the bits of the vector, with
|
||||||
|
* each driven bit set to true, otherwise false.
|
||||||
|
*/
|
||||||
|
vector<bool> Nexus::driven_mask(void) const
|
||||||
|
{
|
||||||
|
vector<bool> mask (vector_width());
|
||||||
|
|
||||||
|
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||||
|
|
||||||
|
Link::DIR link_dir = cur->get_dir();
|
||||||
|
if (link_dir==Link::PASSIVE)
|
||||||
|
continue;
|
||||||
|
if (link_dir==Link::INPUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const NetPins*obj = cur->get_obj();
|
||||||
|
|
||||||
|
// If the link is to a variable (REG or INTEGER) then
|
||||||
|
// the variable is driving all the bits. We have our
|
||||||
|
// complete answer, mark all the bits as driven and
|
||||||
|
// finish. Otherwise, we are not going to get new
|
||||||
|
// information from this node, move on.
|
||||||
|
if (const NetNet*sig = dynamic_cast<const NetNet*> (obj)) {
|
||||||
|
NetNet::Type sig_type = sig->type();
|
||||||
|
if (sig_type==NetNet::INTEGER || sig_type==NetNet::REG) {
|
||||||
|
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||||
|
mask[idx] = true;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
|
||||||
|
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
|
||||||
|
continue;
|
||||||
|
if (obj_ps && cur->get_pin()!=1)
|
||||||
|
continue;
|
||||||
|
if (obj_ps) {
|
||||||
|
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
|
||||||
|
size_t bit = idx + obj_ps->base();
|
||||||
|
ivl_assert(*obj, bit < mask.size());
|
||||||
|
mask[bit] = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||||
|
mask[idx] = true;
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,11 @@ class Nexus {
|
||||||
verinum::V driven_value() const;
|
verinum::V driven_value() const;
|
||||||
verinum driven_vector() const;
|
verinum driven_vector() const;
|
||||||
|
|
||||||
|
/* Return a mask of the bits of this vector that are
|
||||||
|
driven. This is usually all false or all true, but in
|
||||||
|
special cases it may be a blend. */
|
||||||
|
std::vector<bool> driven_mask(void)const;
|
||||||
|
|
||||||
/* The code generator sets an ivl_nexus_t to attach code
|
/* The code generator sets an ivl_nexus_t to attach code
|
||||||
generation details to the nexus. */
|
generation details to the nexus. */
|
||||||
ivl_nexus_t t_cookie() const { return t_cookie_; }
|
ivl_nexus_t t_cookie() const { return t_cookie_; }
|
||||||
|
|
|
||||||
|
|
@ -621,6 +621,10 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||||
<< "MISSING TEST FOR CORRECTNESS OF THE BLEND!"
|
<< "MISSING TEST FOR CORRECTNESS OF THE BLEND!"
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
vector<bool>mask = statement_input.pin(idx).nexus()->driven_mask();
|
||||||
|
for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) {
|
||||||
|
ivl_assert(*this, mask[bit]==false);
|
||||||
|
}
|
||||||
connect(nex_out.pin(idx), statement_input.pin(idx));
|
connect(nex_out.pin(idx), statement_input.pin(idx));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue