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:
parent
2864f2826a
commit
98c7804b89
|
@ -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");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue