Add BUFZ to input ports when necessary.
When driving an input port to a module, watch out for the case where the net is also driven within the instance. If this is the case, take pains to make sure what goes on in the instance doesn't leak out through the input port. Add a BUFZ (continuous assignment) to isolate the context from internal driving.
This commit is contained in:
parent
d84771428a
commit
893aae2ca4
28
elaborate.cc
28
elaborate.cc
|
|
@ -944,6 +944,17 @@ NetNet*PGModule::resize_net_to_port_(Design*des, NetScope*scope,
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool need_bufz_for_input_port(const svector<NetNet*>&prts)
|
||||||
|
{
|
||||||
|
if (prts[0]->port_type() != NetNet::PINPUT)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (prts[0]->pin(0).nexus()->drivers_present())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Instantiate a module by recursively elaborating it. Set the path of
|
* Instantiate a module by recursively elaborating it. Set the path of
|
||||||
* the recursive elaboration so that signal names get properly
|
* the recursive elaboration so that signal names get properly
|
||||||
|
|
@ -1162,7 +1173,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
width. We use that, then, to decide how to hook
|
width. We use that, then, to decide how to hook
|
||||||
it up.
|
it up.
|
||||||
|
|
||||||
NOTE that this also handles the case that the
|
v NOTE that this also handles the case that the
|
||||||
port is actually empty on the inside. We assume
|
port is actually empty on the inside. We assume
|
||||||
in that case that the port is input. */
|
in that case that the port is input. */
|
||||||
|
|
||||||
|
|
@ -1176,6 +1187,21 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (need_bufz_for_input_port(prts)) {
|
||||||
|
NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(),
|
||||||
|
sig->vector_width());
|
||||||
|
des->add_node(tmp);
|
||||||
|
connect(tmp->pin(1), sig->pin(0));
|
||||||
|
|
||||||
|
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
|
||||||
|
NetNet::WIRE, sig->vector_width());
|
||||||
|
tmp2->local_flag(true);
|
||||||
|
tmp2->set_line(*this);
|
||||||
|
tmp2->data_type(sig->data_type());
|
||||||
|
connect(tmp->pin(0), tmp2->pin(0));
|
||||||
|
sig = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
} else if (prts[0]->port_type() == NetNet::PINOUT) {
|
} else if (prts[0]->port_type() == NetNet::PINOUT) {
|
||||||
|
|
||||||
/* Inout to/from module. This is a more
|
/* Inout to/from module. This is a more
|
||||||
|
|
|
||||||
35
net_link.cc
35
net_link.cc
|
|
@ -247,6 +247,41 @@ verinum::V Nexus::get_init() const
|
||||||
return verinum::Vz;
|
return verinum::Vz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Nexus::drivers_present() const
|
||||||
|
{
|
||||||
|
assert(list_);
|
||||||
|
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||||
|
if (cur->get_dir() == Link::OUTPUT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (cur->get_dir() == Link::INPUT)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Must be PASSIVE, so if it is some kind of net, see if
|
||||||
|
// it is the sort that might drive the nexus.
|
||||||
|
const NetObj*obj;
|
||||||
|
unsigned pin;
|
||||||
|
cur->cur_link(obj, pin);
|
||||||
|
if (const NetNet*net = dynamic_cast<const NetNet*>(obj))
|
||||||
|
switch (net->type()) {
|
||||||
|
case NetNet::SUPPLY0:
|
||||||
|
case NetNet::SUPPLY1:
|
||||||
|
case NetNet::TRI0:
|
||||||
|
case NetNet::TRI1:
|
||||||
|
case NetNet::WAND:
|
||||||
|
case NetNet::WOR:
|
||||||
|
case NetNet::TRIAND:
|
||||||
|
case NetNet::TRIOR:
|
||||||
|
case NetNet::REG:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
void Nexus::drivers_delays(NetExpr*rise, NetExpr*fall, NetExpr*decay)
|
||||||
{
|
{
|
||||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,10 @@ class Nexus {
|
||||||
|
|
||||||
NetNet* pick_any_net();
|
NetNet* pick_any_net();
|
||||||
|
|
||||||
|
/* This method returns true if there are any drivers
|
||||||
|
(including variables) attached to this nexus. */
|
||||||
|
bool drivers_present() const;
|
||||||
|
|
||||||
/* This method returns true if all the possible drivers of
|
/* This method returns true if all the possible drivers of
|
||||||
this nexus are constant. It will also return true if there
|
this nexus are constant. It will also return true if there
|
||||||
are no drivers at all. */
|
are no drivers at all. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue