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:
parent
d2a900d187
commit
04be3a6323
4
cprop.cc
4
cprop.cc
|
|
@ -823,6 +823,10 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||||
|
|
||||||
/* If the select input is constant, then replace with a BUFZ */
|
/* If the select input is constant, then replace with a BUFZ */
|
||||||
bool flag = obj->pin_Sel().nexus()->drivers_constant();
|
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;
|
verinum::V sel_val = flag? obj->pin_Sel().nexus()->driven_value() : verinum::Vx;
|
||||||
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
|
if ((sel_val != verinum::Vz) && (sel_val != verinum::Vx)) {
|
||||||
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
|
NetBUFZ*tmp = new NetBUFZ(obj->scope(), obj->name(), obj->width());
|
||||||
|
|
|
||||||
19
net_link.cc
19
net_link.cc
|
|
@ -261,6 +261,25 @@ verinum::V Nexus::get_init() const
|
||||||
return verinum::Vz;
|
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
|
bool Nexus::drivers_present() const
|
||||||
{
|
{
|
||||||
assert(list_);
|
assert(list_);
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,11 @@ class Nexus {
|
||||||
|
|
||||||
NetNet* pick_any_net();
|
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
|
/* This method returns true if there are any drivers
|
||||||
(including variables) attached to this nexus. */
|
(including variables) attached to this nexus. */
|
||||||
bool drivers_present() const;
|
bool drivers_present() const;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue