Support collapse of PartSelect::PV to concatenation
During elaboration, it is sometimes efficient to collapse a collections of PV drivers to a net to a single concatenation. This removes a bunch of resolutions and other nodes, and also is the only way that 2-value logic should work.
This commit is contained in:
parent
7d53ac342f
commit
098bbeea7c
|
|
@ -616,6 +616,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
|||
des->add_node(sub);
|
||||
sub->set_line(*this);
|
||||
connect(sub->pin(0), subsig->pin(0));
|
||||
collapse_partselect_pv_to_concat(des, sig);
|
||||
}
|
||||
sig = subsig;
|
||||
}
|
||||
|
|
|
|||
76
netmisc.cc
76
netmisc.cc
|
|
@ -791,3 +791,79 @@ uint64_t get_scaled_time_from_real(Design*des, NetScope*scope, NetECReal*val)
|
|||
|
||||
return delay;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function looks at the NetNet signal to see if there are any
|
||||
* NetPartSelect::PV nodes driving this signal. If so, See if they can
|
||||
* be collapsed into a single concatenation.
|
||||
*/
|
||||
void collapse_partselect_pv_to_concat(Design*des, NetNet*sig)
|
||||
{
|
||||
NetScope*scope = sig->scope();
|
||||
vector<NetPartSelect*> ps_map (sig->vector_width());
|
||||
|
||||
Nexus*nex = sig->pin(0).nexus();
|
||||
|
||||
for (Link*cur = nex->first_nlink(); cur ; cur = cur->next_nlink()) {
|
||||
NetPins*obj;
|
||||
unsigned obj_pin;
|
||||
cur->cur_link(obj, obj_pin);
|
||||
|
||||
// Look for NetPartSelect devices, where this signal is
|
||||
// connected to pin 1 of a NetPartSelect::PV.
|
||||
NetPartSelect*ps_obj = dynamic_cast<NetPartSelect*> (obj);
|
||||
if (ps_obj == 0)
|
||||
continue;
|
||||
if (ps_obj->dir() != NetPartSelect::PV)
|
||||
continue;
|
||||
if (obj_pin != 1)
|
||||
continue;
|
||||
|
||||
ivl_assert(*ps_obj, ps_obj->base() < ps_map.size());
|
||||
ivl_assert(*ps_obj, ps_obj->base()+ps_obj->width() <= ps_map.size());
|
||||
ps_map[ps_obj->base()] = ps_obj;
|
||||
}
|
||||
|
||||
// Check the collected NetPartSelect::PV objects to see if
|
||||
// they cover the vector.
|
||||
unsigned idx = 0;
|
||||
unsigned device_count = 0;
|
||||
while (idx < ps_map.size()) {
|
||||
NetPartSelect*ps_obj = ps_map[idx];
|
||||
if (ps_obj == 0)
|
||||
return;
|
||||
|
||||
idx += ps_obj->width();
|
||||
device_count += 1;
|
||||
}
|
||||
|
||||
ivl_assert(*sig, idx == ps_map.size());
|
||||
|
||||
// Ah HAH! The NetPartSelect::PV objects exactly cover the
|
||||
// target signal. We can replace all of them with a single
|
||||
// concatenation.
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << sig->get_fileline() << ": debug: "
|
||||
<< "Collapse " << device_count
|
||||
<< " NetPartSelect::PV devices into a concatenation." << endl;
|
||||
}
|
||||
|
||||
NetConcat*cat = new NetConcat(scope, scope->local_symbol(),
|
||||
ps_map.size(), device_count);
|
||||
des->add_node(cat);
|
||||
cat->set_line(*sig);
|
||||
|
||||
connect(cat->pin(0), sig->pin(0));
|
||||
|
||||
idx = 0;
|
||||
unsigned concat_position = 1;
|
||||
while (idx < ps_map.size()) {
|
||||
assert(ps_map[idx]);
|
||||
NetPartSelect*ps_obj = ps_map[idx];
|
||||
connect(cat->pin(concat_position), ps_obj->pin(0));
|
||||
concat_position += 1;
|
||||
idx += ps_obj->width();
|
||||
delete ps_obj;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue