3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-12 20:18:20 +00:00

opt_ffinv: Use ModIndex instead of ModWalker.

This avoids using out-of-data index information.
This commit is contained in:
Marcelina Kościelnicka 2022-05-17 01:52:55 +02:00
parent 2864f2826a
commit 98c7804b89

View file

@ -30,7 +30,7 @@ struct OptFfInvWorker
{ {
int count = 0; int count = 0;
RTLIL::Module *module; RTLIL::Module *module;
ModWalker walker; ModIndex index;
FfInitVals initvals; FfInitVals initvals;
// Case 1: // Case 1:
@ -38,44 +38,45 @@ struct OptFfInvWorker
// - ... which has no other users // - ... which has no other users
// - all users of FF are LUTs // - all users of FF are LUTs
bool push_d_inv(FfData &ff) { bool push_d_inv(FfData &ff) {
pool<SigBit> dummy; if (index.query_is_input(ff.sig_d))
if (walker.get_inputs(dummy, ff.sig_d))
return false; return false;
if (walker.get_outputs(dummy, ff.sig_d)) if (index.query_is_output(ff.sig_d))
return false; return false;
pool<ModWalker::PortBit> d_drivers; auto d_ports = index.query_ports(ff.sig_d);
walker.get_drivers(d_drivers, ff.sig_d); if (d_ports.size() != 2)
if (d_drivers.size() != 1)
return false; return false;
Cell *d_inv = nullptr; Cell *d_inv = nullptr;
for (auto &driver: d_drivers) { for (auto &port: d_ports) {
if (driver.cell->type.in(ID($not), ID($_NOT_))) { if (port.cell == ff.cell && port.port == ID::D)
continue;
if (port.port != ID::Y)
return false;
if (port.cell->type.in(ID($not), ID($_NOT_))) {
// OK // OK
} else if (driver.cell->type.in(ID($lut))) { } else if (port.cell->type.in(ID($lut))) {
if (driver.cell->getParam(ID::WIDTH) != 1) if (port.cell->getParam(ID::WIDTH) != 1)
return false; return false;
if (driver.cell->getParam(ID::LUT).as_int() != 1) if (port.cell->getParam(ID::LUT).as_int() != 1)
return false; return false;
} else { } else {
return false; return false;
} }
d_inv = driver.cell; log_assert(d_inv == nullptr);
d_inv = port.cell;
} }
pool<ModWalker::PortBit> d_consumers;
walker.get_consumers(d_consumers, ff.sig_d);
if (d_consumers.size() != 1)
return false;
if (walker.get_outputs(dummy, ff.sig_q)) if (index.query_is_output(ff.sig_q))
return false; return false;
auto q_ports = index.query_ports(ff.sig_q);
pool<Cell *> q_luts; pool<Cell *> q_luts;
pool<ModWalker::PortBit> q_consumers; for (auto &port: q_ports) {
walker.get_consumers(q_consumers, ff.sig_q); if (port.cell == ff.cell && port.port == ID::Q)
for (auto &consumer: q_consumers) { continue;
if (!consumer.cell->type.in(ID($not), ID($_NOT_), ID($lut))) if (port.port != ID::A)
return false; return false;
q_luts.insert(consumer.cell); if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut)))
return false;
q_luts.insert(port.cell);
} }
ff.flip_rst_bits({0}); ff.flip_rst_bits({0});
@ -86,7 +87,7 @@ struct OptFfInvWorker
int flip_mask = 0; int flip_mask = 0;
SigSpec sig_a = lut->getPort(ID::A); SigSpec sig_a = lut->getPort(ID::A);
for (int i = 0; i < GetSize(sig_a); i++) { for (int i = 0; i < GetSize(sig_a); i++) {
if (walker.sigmap(sig_a[i]) == walker.sigmap(ff.sig_q)) { if (index.sigmap(sig_a[i]) == index.sigmap(ff.sig_q)) {
flip_mask |= 1 << i; flip_mask |= 1 << i;
} }
} }
@ -118,47 +119,49 @@ struct OptFfInvWorker
// - FF has one user // - FF has one user
// - ... which is an inverter // - ... which is an inverter
bool push_q_inv(FfData &ff) { bool push_q_inv(FfData &ff) {
pool<SigBit> dummy; if (index.query_is_input(ff.sig_d))
if (walker.get_inputs(dummy, ff.sig_d))
return false; return false;
if (walker.get_outputs(dummy, ff.sig_d)) if (index.query_is_output(ff.sig_d))
return false; return false;
Cell *d_lut = nullptr; Cell *d_lut = nullptr;
pool<ModWalker::PortBit> d_drivers; auto d_ports = index.query_ports(ff.sig_d);
walker.get_drivers(d_drivers, ff.sig_d); if (d_ports.size() != 2)
if (d_drivers.size() != 1)
return false; return false;
for (auto &driver: d_drivers) { for (auto &port: d_ports) {
if (!driver.cell->type.in(ID($not), ID($_NOT_), ID($lut))) if (port.cell == ff.cell && port.port == ID::D)
continue;
if (port.port != ID::Y)
return false; return false;
d_lut = driver.cell; if (!port.cell->type.in(ID($not), ID($_NOT_), ID($lut)))
return false;
log_assert(d_lut == nullptr);
d_lut = port.cell;
} }
pool<ModWalker::PortBit> d_consumers;
walker.get_consumers(d_consumers, ff.sig_d);
if (d_consumers.size() != 1)
return false;
if (walker.get_outputs(dummy, ff.sig_q)) if (index.query_is_output(ff.sig_q))
return false; return false;
pool<ModWalker::PortBit> q_consumers; auto q_ports = index.query_ports(ff.sig_q);
walker.get_consumers(q_consumers, ff.sig_q); if (q_ports.size() != 2)
if (q_consumers.size() != 1)
return false; return false;
Cell *q_inv = nullptr; Cell *q_inv = nullptr;
for (auto &consumer: q_consumers) { for (auto &port: q_ports) {
if (consumer.cell->type.in(ID($not), ID($_NOT_))) { if (port.cell == ff.cell && port.port == ID::Q)
continue;
if (port.port != ID::A)
return false;
if (port.cell->type.in(ID($not), ID($_NOT_))) {
// OK // OK
} else if (consumer.cell->type.in(ID($lut))) { } else if (port.cell->type.in(ID($lut))) {
if (consumer.cell->getParam(ID::WIDTH) != 1) if (port.cell->getParam(ID::WIDTH) != 1)
return false; return false;
if (consumer.cell->getParam(ID::LUT).as_int() != 1) if (port.cell->getParam(ID::LUT).as_int() != 1)
return false; return false;
} else { } else {
return false; return false;
} }
q_inv = consumer.cell; log_assert(q_inv == nullptr);
q_inv = port.cell;
} }
ff.flip_rst_bits({0}); ff.flip_rst_bits({0});
@ -190,7 +193,7 @@ struct OptFfInvWorker
} }
OptFfInvWorker(RTLIL::Module *module) : OptFfInvWorker(RTLIL::Module *module) :
module(module), walker(module->design, module), initvals(&walker.sigmap, module) module(module), index(module), initvals(&index.sigmap, module)
{ {
log("Discovering LUTs.\n"); log("Discovering LUTs.\n");