Do not cprop through ternaries if the selector is an l-value.

It turns out that it is possible for an otherwise constant net
mux to be non-constant if there is a force that can drive the
net. This can be detected as an l-value reference to an otherwise
constant selector.
(cherry picked from commit abc4eb9d52)
This commit is contained in:
Stephen Williams 2009-10-05 19:46:47 -07:00
parent d2a900d187
commit 04be3a6323
3 changed files with 28 additions and 0 deletions

View File

@ -823,6 +823,10 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
/* If the select input is constant, then replace with a BUFZ */
bool flag = obj->pin_Sel().nexus()->drivers_constant();
/* Note that this cannot be constant if there are assignments
to this nexus. (Assignments include "force" to nets.) */
flag &= !obj->pin_Sel().nexus()->assign_lval();
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());

View File

@ -261,6 +261,25 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
bool Nexus::assign_lval() const
{
assert(list_);
for (Link*cur = list_ ; cur ; cur = cur->next_) {
const NetPins*obj;
unsigned pin;
cur->cur_link(obj, pin);
const NetNet*net = dynamic_cast<const NetNet*> (obj);
if (net == 0)
continue;
if (net->peek_lref())
return true;
}
return false;
}
bool Nexus::drivers_present() const
{
assert(list_);

View File

@ -347,6 +347,11 @@ class Nexus {
NetNet* pick_any_net();
/* This method returns true if there are any assignments that
use this nexus as an l-value. This can be true if the nexus
is a variable, but also if this is a net with a force. */
bool assign_lval() const;
/* This method returns true if there are any drivers
(including variables) attached to this nexus. */
bool drivers_present() const;