36 typedef std::map<RTLIL::SigBit, std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>>>
drivers_t;
60 std::map<RTLIL::SigBit, int> &
cache;
65 std::vector<RTLIL::SigBit> vec =
sigmap(sig).to_sigbit_vector();
84 sigmap(sigmap), drivers(drivers),
satgen(&
ez, &sigmap)
92 for (
int i = 8*
sizeof(
int); val; i = i >> 1)
102 if (
sat_pi.count(bit) != 0)
124 ez.assume(
ez.IFF(
ez.XOR(sat_a, sat_b), sat_pi[bit]));
126 for (
size_t i = 0; i < idx_bits; i++)
127 if ((idx & (1 << i)) == 0)
137 if (sigdone.count(out) != 0)
142 std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv =
drivers.at(out);
143 if (
ez_cells.count(drv.first) == 0) {
152 for (
auto &bit : drv.second)
162 std::set<RTLIL::SigBit> pi_set, sigdone;
165 pi.insert(pi.end(), pi_set.begin(), pi_set.end());
171 log(
"[%2d%%] Analyzing input cone for signal %s:\n", prec,
log_signal(output));
173 std::vector<RTLIL::SigBit> pi;
177 log(
" Found %d input signals and %d cells.\n",
int(pi.size()),
int(
ez_cells.size()));
187 std::set<int> unused_pi_idx;
189 for (
size_t i = 0; i < pi.size(); i++)
190 unused_pi_idx.insert(i);
194 std::vector<int> model_pi_idx;
195 std::vector<int> model_expr;
196 std::vector<bool> model;
198 for (
size_t i = 0; i < pi.size(); i++)
199 if (unused_pi_idx.count(i) != 0) {
200 model_pi_idx.push_back(i);
201 model_expr.push_back(
sat_pi.at(pi[i]));
204 if (!
ez.solve(model_expr, model,
ez.expression(
ezSAT::OpOr, model_expr),
ez.XOR(output_a, output_b),
ez.NOT(output_undef_a),
ez.NOT(output_undef_b)))
208 for (
size_t i = 0; i < model_pi_idx.size(); i++)
211 log(
" Found relevant input: %s\n",
log_signal(pi[model_pi_idx[i]]));
212 unused_pi_idx.erase(model_pi_idx[i]);
218 for (
size_t i = 0; i < pi.size(); i++)
219 if (unused_pi_idx.count(i) == 0)
220 reduced_inputs.push_back(pi[i]);
223 log(
" Reduced input cone contains %d inputs.\n",
int(reduced_inputs.size()));
231 std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> &
inv_pairs;
246 if (sigdepth.count(out) != 0)
247 return sigdepth.at(out);
250 std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv =
drivers.at(out);
251 if (celldone.count(drv.first) == 0) {
254 celldone.insert(drv.first);
256 int max_child_depth = 0;
257 for (
auto &bit : drv.second)
259 sigdepth[out] = max_child_depth + 1;
267 return sigdepth.at(out);
275 std::set<RTLIL::Cell*> celldone;
276 std::map<RTLIL::SigBit, int> sigdepth;
278 for (
auto &bit : bits) {
286 log_error(
"Solving for initial model failed!\n");
287 for (
size_t i = 0; i <
sat_out.size(); i++)
309 log(
" Constant value for this signal: %s\n",
log_signal(value));
312 for (
size_t i = 0; i < results.size(); i++) {
313 if (results[i].front().bit == value) {
319 if (result_idx == -1) {
320 result_idx = results.size();
321 results.push_back(std::vector<equiv_bit_t>());
327 results.back().push_back(bit);
335 results[result_idx].push_back(bit);
338 void analyze(std::vector<std::set<int>> &results, std::map<int, int> &results_map, std::vector<int> &bucket, std::string indent1, std::string indent2)
340 std::string indent = indent1 + indent2;
341 const char *indt = indent.c_str();
343 if (bucket.size() <= 1)
347 log(
"%s Trying to shatter bucket with %d signals.\n", indt,
int(bucket.size()));
350 std::vector<RTLIL::SigBit> bucket_sigbits;
351 for (
int idx : bucket)
353 log(
"%s Trying to shatter bucket with %d signals: %s\n", indt,
int(bucket.size()),
log_signal(bucket_sigbits));
356 std::vector<int> sat_set_list, sat_clr_list;
357 for (
int idx : bucket) {
362 std::vector<int> modelVars =
sat_out;
363 std::vector<bool> model;
365 modelVars.insert(modelVars.end(),
sat_def.begin(),
sat_def.end());
367 modelVars.insert(modelVars.end(),
sat_pi.begin(),
sat_pi.end());
375 sat_set_list.clear();
376 sat_clr_list.clear();
378 std::vector<int> sat_def_list;
380 for (
int idx : bucket)
394 int count_set = 0, count_clr = 0, count_undef = 0;
395 for (
int idx : bucket)
402 log(
"%s After %d iterations: %d set vs. %d clr vs %d undef\n", indt, iter_count, count_set, count_clr, count_undef);
406 for (
size_t i = 0; i <
pi_bits.size(); i++)
408 for (
int idx : bucket)
409 log(
"%s -> OUT %c == %s%s\n", indt, model[
sat_out.size() +
idx] ? model[
idx] ?
'1' :
'0' :
'x',
413 std::vector<int> buckets_a;
414 std::vector<int> buckets_b;
416 for (
int idx : bucket) {
418 buckets_a.push_back(
idx);
420 buckets_b.push_back(
idx);
422 analyze(results, results_map, buckets_a, indent1 +
".", indent2 +
" ");
423 analyze(results, results_map, buckets_b, indent1 +
"x", indent2 +
" ");
427 std::vector<int> undef_slaves;
429 for (
int idx : bucket) {
430 std::vector<int> sat_def_list;
431 for (
int idx2 : bucket)
433 sat_def_list.push_back(
sat_def[idx2]);
435 undef_slaves.push_back(idx);
438 if (undef_slaves.size() == bucket.size()) {
440 log(
"%s Complex undef overlap. None of the signals covers the others.\n", indt);
445 for (
int idx : undef_slaves)
449 log(
"%s Found %d equivialent signals:", indt,
int(bucket.size()));
450 for (
int idx : bucket)
456 for (
int idx : bucket) {
457 if (results_map.count(
idx) == 0)
459 if (result_idx == -1) {
460 result_idx = results_map.at(
idx);
463 int result_idx2 = results_map.at(
idx);
464 results[result_idx].insert(results[result_idx2].begin(), results[result_idx2].end());
465 for (
int idx2 : results[result_idx2])
466 results_map[idx2] = result_idx;
467 results[result_idx2].clear();
470 if (result_idx == -1) {
471 result_idx = results.size();
472 results.push_back(std::set<int>());
475 results[result_idx].insert(bucket.begin(), bucket.end());
479 void analyze(std::vector<std::vector<equiv_bit_t>> &results,
int perc)
481 std::vector<int> bucket;
482 for (
size_t i = 0; i <
sat_out.size(); i++)
485 std::vector<std::set<int>> results_buf;
486 std::map<int, int> results_map;
489 for (
auto &r : results_buf)
495 std::vector<RTLIL::SigBit> r_sigbits;
498 log(
" Found group of %d equivialent signals: %s\n",
int(r.size()),
log_signal(r_sigbits));
501 std::vector<int> undef_slaves;
504 std::vector<int> sat_def_list;
507 sat_def_list.push_back(
sat_def[idx2]);
509 undef_slaves.push_back(idx);
512 if (undef_slaves.size() == bucket.size()) {
514 log(
" Complex undef overlap. None of the signals covers the others.\n");
519 for (
int idx : undef_slaves)
522 std::vector<equiv_bit_t> result;
530 result.push_back(bit);
535 if (result.front().inverted)
536 for (
auto &bit : result)
537 bit.inverted = !bit.inverted;
539 for (
size_t i = 1; i < result.size(); i++) {
540 std::pair<RTLIL::SigBit, RTLIL::SigBit> p(result[0].bit, result[i].bit);
542 result.erase(result.begin() + i);
545 if (result.size() > 1)
546 results.push_back(result);
558 std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>>
inv_pairs;
566 if (needle == haystack)
571 std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv =
drivers.at(haystack);
573 if (celldone.count(drv.first))
575 celldone.insert(drv.first);
577 for (
auto &bit : drv.second)
585 std::set<RTLIL::Cell*> celldone;
592 log(
"%s Writing dump file `%s'.\n",
reduce_counter ?
" " :
"", filename.c_str());
604 int bits_full_total = 0;
605 std::vector<std::set<RTLIL::SigBit>> batches;
607 if (it.second->port_input) {
608 batches.push_back(
sigmap(it.second).to_sigbit_set());
609 bits_full_total += it.second->width;
613 std::set<RTLIL::SigBit> inputs, outputs;
614 for (
auto &port : it.second->connections()) {
615 std::vector<RTLIL::SigBit> bits =
sigmap(port.second).to_sigbit_vector();
617 outputs.insert(bits.begin(), bits.end());
619 inputs.insert(bits.begin(), bits.end());
621 std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> drv(it.second, inputs);
622 for (
auto &bit : outputs)
624 batches.push_back(outputs);
625 bits_full_total += outputs.size();
627 if (
inv_mode && it.second->type ==
"$_NOT_")
628 inv_pairs.insert(std::pair<RTLIL::SigBit, RTLIL::SigBit>(
sigmap(it.second->getPort(
"\\A")),
sigmap(it.second->getPort(
"\\Y"))));
632 int bits_full_count = 0;
633 std::map<std::vector<RTLIL::SigBit>, std::vector<RTLIL::SigBit>> buckets;
634 for (
auto &batch : batches)
636 for (
auto &bit : batch)
638 goto found_selected_wire;
639 bits_full_count += batch.size();
643 log(
" Finding reduced input cone for signal batch %s%c\n",
647 for (
auto &bit : batch) {
648 std::vector<RTLIL::SigBit> inputs;
649 infinder.
analyze(inputs, bit, 100 * bits_full_count / bits_full_total);
650 buckets[inputs].push_back(bit);
655 log(
" Sorted %d signal bits into %d buckets.\n", bits_count,
int(buckets.size()));
657 int bucket_count = 0;
658 std::vector<std::vector<equiv_bit_t>> equiv;
659 for (
auto &bucket : buckets)
663 if (bucket.second.size() == 1)
666 if (bucket.first.size() == 0) {
669 for (
size_t idx = 0;
idx < bucket.second.size();
idx++)
674 worker.
analyze(equiv, 100 * bucket_count / (buckets.size() + 1));
678 std::map<RTLIL::SigBit, int> bitusage;
684 log(
" Rewiring %d equivialent groups:\n",
int(equiv.size()));
685 int rewired_sigbits = 0;
686 for (
auto &grp : equiv)
691 for (
size_t i = 1; i < grp.size(); i++)
694 log(
" Skipping not-selected slave: %s\n",
log_signal(grp[i].bit));
698 if (grp[i].bit.wire->port_id == 0 && bitusage[grp[i].bit] <= 1) {
704 log(
" Skipping dependency of master: %s\n",
log_signal(grp[i].bit));
708 log(
" Connect slave%s: %s\n", grp[i].inverted ?
" using inverter" :
"",
log_signal(grp[i].bit));
714 sigmap(port.second).replace(grp[i].bit, dummy_wire, &port.second);
718 if (inv_sig.
size() == 0)
723 inv_cell->
setPort(
"\\A", grp[0].bit);
724 inv_cell->
setPort(
"\\Y", inv_sig);
739 log(
" Reached limit passed using -stop option. Skipping all further reductions.\n");
745 return rewired_sigbits;
755 log(
" freduce [options] [selection]\n");
757 log(
"This pass performs functional reduction in the circuit. I.e. if two nodes are\n");
758 log(
"equivialent, they are merged to one node and one of the redundant drivers is\n");
759 log(
"disconnected. A subsequent call to 'clean' will remove the redundant drivers.\n");
762 log(
" enable verbose or very verbose output\n");
765 log(
" enable explicit handling of inverted signals\n");
768 log(
" stop after <n> reduction operations. this is mostly used for\n");
769 log(
" debugging the freduce command itself.\n");
771 log(
" -dump <prefix>\n");
772 log(
" dump the design to <prefix>_<module>_<num>.il after each reduction\n");
773 log(
" operation. this is mostly used for debugging the freduce command.\n");
775 log(
"This pass is undef-aware, i.e. it considers don't-care values for detecting\n");
776 log(
"equivialent nodes.\n");
778 log(
"All selected wires are considered for rewiring. The selected cells cover the\n");
779 log(
"circuit that is analyzed.\n");
790 log_header(
"Executing FREDUCE pass (perform functional reduction).\n");
793 for (argidx = 1; argidx < args.size(); argidx++) {
794 if (args[argidx] ==
"-v") {
798 if (args[argidx] ==
"-vv") {
802 if (args[argidx] ==
"-inv") {
806 if (args[argidx] ==
"-stop" && argidx+1 < args.size()) {
810 if (args[argidx] ==
"-dump" && argidx+1 < args.size()) {
819 for (
auto &mod_it : design->
modules_) {
825 log(
"Rewired a total of %d signal bits.\n", bitcount);
const char * c_str() const
bool selected(T1 *module) const
void operator()(RTLIL::SigSpec &sig)
RTLIL::Wire * wire(RTLIL::IdString id)
bool operator<(const equiv_bit_t &other) const
std::string stringf(const char *fmt,...)
void sort(T *array, int size, LessThan lt)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
void rewrite_sigspecs(T functor)
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
static std::string idx(std::string str)
CountBitUsage(SigMap &sigmap, std::map< RTLIL::SigBit, int > &cache)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
std::vector< int > importSigSpec(RTLIL::SigSpec sig, int timestep=-1)
void log_error(const char *format,...)
FreduceWorker(RTLIL::Design *design, RTLIL::Module *module)
std::vector< int > importUndefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool inv_mode
bool cell_known(RTLIL::IdString type)
void connect(const RTLIL::SigSig &conn)
#define PRIVATE_NAMESPACE_BEGIN
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
#define log_assert(_assert_expr_)
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
#define PRIVATE_NAMESPACE_END
void setContext(SigMap *sigmap, std::string prefix=std::string())
static const char * id2cstr(const RTLIL::IdString &str)
#define USING_YOSYS_NAMESPACE
std::map< RTLIL::IdString, RTLIL::Module * > modules_
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
void log(const char *format,...)
bool find_bit_in_cone(std::set< RTLIL::Cell * > &celldone, RTLIL::SigBit needle, RTLIL::SigBit haystack)
bool find_bit_in_cone(RTLIL::SigBit needle, RTLIL::SigBit haystack)
bool importCell(RTLIL::Cell *cell, int timestep=-1)
std::map< RTLIL::IdString, RTLIL::SigSpec > connections_
std::string selected_active_module
std::map< RTLIL::SigBit, int > & cache
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
static void call(RTLIL::Design *design, std::string command)
std::pair< SigSpec, SigSpec > SigSig
std::set< std::pair< RTLIL::SigBit, RTLIL::SigBit > > inv_pairs
std::map< RTLIL::SigBit, std::pair< RTLIL::Cell *, std::set< RTLIL::SigBit > > > drivers_t