diff --git a/cprop.cc b/cprop.cc index 6f39cf9e6..0b705368b 100644 --- a/cprop.cc +++ b/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 */ 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()); diff --git a/net_link.cc b/net_link.cc index 59ab08087..2b092eb61 100644 --- a/net_link.cc +++ b/net_link.cc @@ -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 (obj); + if (net == 0) + continue; + + if (net->peek_lref()) + return true; + } + + return false; +} + bool Nexus::drivers_present() const { assert(list_); diff --git a/netlist.h b/netlist.h index 40efe0b47..e17230b3d 100644 --- a/netlist.h +++ b/netlist.h @@ -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;