Fix GitHub issue #316 - isolate modpath delays from multi-driven nets.

When module ports are collapsed, we can't tell which of the nexus drivers
are associated with a given module port and should be routed through an
associated modpath delay. Work round this by inserting a transparent
buffer or tran_vp if an output or inout port has a modpath delay. The
target code generator can elide this once it has handled the modpath
delays.
This commit is contained in:
Martin Whitaker 2020-05-07 22:51:38 +01:00
parent 58eb202376
commit e19109e58f
1 changed files with 47 additions and 4 deletions

View File

@ -1119,6 +1119,37 @@ static void convert_net(Design*des, const LineInfo *line,
des->errors += 1;
}
static void isolate_and_connect(Design*des, NetScope*scope, const PGModule*mod,
NetNet*port, NetNet*sig, NetNet::PortType ptype)
{
switch (ptype) {
case NetNet::POUTPUT:
{
NetBUFZ*tmp = new NetBUFZ(scope, scope->local_symbol(),
sig->vector_width(), true);
tmp->set_line(*mod);
des->add_node(tmp);
connect(tmp->pin(1), port->pin(0));
connect(tmp->pin(0), sig->pin(0));
}
break;
case NetNet::PINOUT:
{
NetTran*tmp = new NetTran(scope, scope->local_symbol(),
sig->vector_width(),
sig->vector_width(), 0);
tmp->set_line(*mod);
des->add_node(tmp);
connect(tmp->pin(1), port->pin(0));
connect(tmp->pin(0), sig->pin(0));
}
break;
default:
ivl_assert(*mod, 0);
break;
}
}
/*
* Instantiate a module by recursively elaborating it. Set the path of
* the recursive elaboration so that signal names get properly
@ -1815,8 +1846,15 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// The simplest case, there are no
// parts/concatenations on the inside of the
// module, so the port and sig need simply be
// connected directly.
connect(prts[0]->pin(0), sig->pin(0));
// connected directly. But don't collapse ports
// that are a delay path destination, to avoid
// the delay being applied to other drivers of
// the external signal.
if (prts[0]->delay_paths() > 0) {
isolate_and_connect(des, scope, this, prts[0], sig, ptype);
} else {
connect(prts[0]->pin(0), sig->pin(0));
}
} else if (sig->vector_width()==prts_vector_width/instance.size()
&& prts.size()/instance.size() == 1) {
@ -1832,8 +1870,13 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// The signal width is exactly the width of a
// single instance of the port. In this case,
// connect the sig to all the ports identically.
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1)
connect(prts[ldx]->pin(0), sig->pin(0));
for (unsigned ldx = 0 ; ldx < prts.size() ; ldx += 1) {
if (prts[ldx]->delay_paths() > 0) {
isolate_and_connect(des, scope, this, prts[ldx], sig, ptype);
} else {
connect(prts[ldx]->pin(0), sig->pin(0));
}
}
} else switch (ptype) {
case NetNet::POUTPUT: