diff --git a/link_const.cc b/link_const.cc index 9b01c75b3..0e8c7e39d 100644 --- a/link_const.cc +++ b/link_const.cc @@ -232,3 +232,58 @@ verinum Nexus::driven_vector() const return val; } + +/* + * Calculate a vector that represent all the bits of the vector, with + * each driven bit set to true, otherwise false. + */ +vector Nexus::driven_mask(void) const +{ + vector 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 (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(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; +} diff --git a/netlist.h b/netlist.h index 13b61e0a4..1f5d4e9be 100644 --- a/netlist.h +++ b/netlist.h @@ -386,6 +386,11 @@ class Nexus { verinum::V driven_value() 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 driven_mask(void)const; + /* The code generator sets an ivl_nexus_t to attach code generation details to the nexus. */ ivl_nexus_t t_cookie() const { return t_cookie_; } diff --git a/synth2.cc b/synth2.cc index c028817af..169c216eb 100644 --- a/synth2.cc +++ b/synth2.cc @@ -621,6 +621,10 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, << "MISSING TEST FOR CORRECTNESS OF THE BLEND!" << endl; } + vectormask = 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)); }