mirror of
https://github.com/YosysHQ/yosys
synced 2025-07-28 15:07:58 +00:00
Refactor common parts of SAT-using optimizations into a helper.
This also aligns the functionality: - in all cases, the onehot attribute is used to create appropriate constraints (previously, opt_dff didn't do it at all, and share created one-hot constraints based on $pmux presence alone, which is unsound) - in all cases, shift and mul/div/pow cells are now skipped when importing the SAT problem (previously only memory_share did this) — this avoids creating clauses for hard cells that are unlikely to help with proving the UNSATness needed for optimization
This commit is contained in:
parent
d8fcf1ab25
commit
d25b9088c8
7 changed files with 224 additions and 153 deletions
|
@ -21,7 +21,8 @@
|
|||
#include "kernel/log.h"
|
||||
#include "kernel/register.h"
|
||||
#include "kernel/rtlil.h"
|
||||
#include "kernel/satgen.h"
|
||||
#include "kernel/qcsat.h"
|
||||
#include "kernel/modtools.h"
|
||||
#include "kernel/sigtools.h"
|
||||
#include "kernel/ffinit.h"
|
||||
#include "kernel/ff.h"
|
||||
|
@ -51,26 +52,23 @@ struct OptDffWorker
|
|||
FfInitVals initvals;
|
||||
dict<SigBit, int> bitusers;
|
||||
dict<SigBit, cell_int_t> bit2mux;
|
||||
dict<SigBit, RTLIL::Cell*> bit2driver;
|
||||
|
||||
typedef std::map<RTLIL::SigBit, bool> pattern_t;
|
||||
typedef std::set<pattern_t> patterns_t;
|
||||
typedef std::pair<RTLIL::SigBit, bool> ctrl_t;
|
||||
typedef std::set<ctrl_t> ctrls_t;
|
||||
|
||||
ezSatPtr ez;
|
||||
SatGen satgen;
|
||||
pool<Cell*> sat_cells;
|
||||
ModWalker modwalker;
|
||||
QuickConeSat qcsat;
|
||||
|
||||
// Used as a queue.
|
||||
std::vector<Cell *> dff_cells;
|
||||
|
||||
OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod), ez(), satgen(ez.get(), &sigmap) {
|
||||
// Gathering three kinds of information here for every sigmapped SigBit:
|
||||
OptDffWorker(const OptDffOptions &opt, Module *mod) : opt(opt), module(mod), sigmap(mod), initvals(&sigmap, mod), modwalker(module->design, module), qcsat(modwalker) {
|
||||
// Gathering two kinds of information here for every sigmapped SigBit:
|
||||
//
|
||||
// - bitusers: how many users it has (muxes will only be merged into FFs if this is 1, making the FF the only user)
|
||||
// - bit2mux: the mux cell and bit index that drives it, if any
|
||||
// - bit2driver: the cell driving it, if any
|
||||
|
||||
for (auto wire : module->wires())
|
||||
{
|
||||
|
@ -88,10 +86,6 @@ struct OptDffWorker
|
|||
|
||||
for (auto conn : cell->connections()) {
|
||||
bool is_output = cell->output(conn.first);
|
||||
if (is_output) {
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bit2driver[bit] = cell;
|
||||
}
|
||||
if (!is_output || !cell->known()) {
|
||||
for (auto bit : sigmap(conn.second))
|
||||
bitusers[bit]++;
|
||||
|
@ -104,20 +98,6 @@ struct OptDffWorker
|
|||
|
||||
}
|
||||
|
||||
std::function<void(Cell*)> sat_import_cell = [&](Cell *c) {
|
||||
if (!sat_cells.insert(c).second)
|
||||
return;
|
||||
if (!satgen.importCell(c))
|
||||
return;
|
||||
for (auto &conn : c->connections()) {
|
||||
if (!c->input(conn.first))
|
||||
continue;
|
||||
for (auto bit : sigmap(conn.second))
|
||||
if (bit2driver.count(bit))
|
||||
sat_import_cell(bit2driver.at(bit));
|
||||
}
|
||||
};
|
||||
|
||||
State combine_const(State a, State b) {
|
||||
if (a == State::Sx && !opt.keepdc)
|
||||
return b;
|
||||
|
@ -594,19 +574,19 @@ struct OptDffWorker
|
|||
if (!opt.sat)
|
||||
continue;
|
||||
// For each register bit, try to prove that it cannot change from the initial value. If so, remove it
|
||||
if (!bit2driver.count(ff.sig_d[i]))
|
||||
if (!modwalker.has_drivers(ff.sig_d.extract(i)))
|
||||
continue;
|
||||
if (val != State::S0 && val != State::S1)
|
||||
continue;
|
||||
|
||||
sat_import_cell(bit2driver.at(ff.sig_d[i]));
|
||||
int init_sat_pi = qcsat.importSigBit(val);
|
||||
int q_sat_pi = qcsat.importSigBit(ff.sig_q[i]);
|
||||
int d_sat_pi = qcsat.importSigBit(ff.sig_d[i]);
|
||||
|
||||
int init_sat_pi = satgen.importSigSpec(val).front();
|
||||
int q_sat_pi = satgen.importSigBit(ff.sig_q[i]);
|
||||
int d_sat_pi = satgen.importSigBit(ff.sig_d[i]);
|
||||
qcsat.prepare();
|
||||
|
||||
// Try to find out whether the register bit can change under some circumstances
|
||||
bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi)));
|
||||
bool counter_example_found = qcsat.ez->solve(qcsat.ez->IFF(q_sat_pi, init_sat_pi), qcsat.ez->NOT(qcsat.ez->IFF(d_sat_pi, init_sat_pi)));
|
||||
|
||||
// If the register bit cannot change, we can replace it with a constant
|
||||
if (counter_example_found)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue