yosys-master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
freduce.cc
Go to the documentation of this file.
1 /*
2  * yosys -- Yosys Open SYnthesis Suite
3  *
4  * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 #include "kernel/register.h"
21 #include "kernel/celltypes.h"
22 #include "kernel/consteval.h"
23 #include "kernel/sigtools.h"
24 #include "kernel/log.h"
25 #include "kernel/satgen.h"
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <algorithm>
30 
33 
34 bool inv_mode;
36 typedef std::map<RTLIL::SigBit, std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>>> drivers_t;
37 std::string dump_prefix;
38 
40 {
41  int depth;
42  bool inverted;
45 
46  bool operator<(const equiv_bit_t &other) const {
47  if (depth != other.depth)
48  return depth < other.depth;
49  if (inverted != other.inverted)
50  return inverted < other.inverted;
51  if (drv != other.drv)
52  return drv < other.drv;
53  return bit < other.bit;
54  }
55 };
56 
58 {
60  std::map<RTLIL::SigBit, int> &cache;
61 
62  CountBitUsage(SigMap &sigmap, std::map<RTLIL::SigBit, int> &cache) : sigmap(sigmap), cache(cache) { }
63 
65  std::vector<RTLIL::SigBit> vec = sigmap(sig).to_sigbit_vector();
66  for (auto &bit : vec)
67  cache[bit]++;
68  }
69 };
70 
72 {
75 
77  std::set<RTLIL::Cell*> ez_cells;
79 
80  std::map<RTLIL::SigBit, int> sat_pi;
81  std::vector<int> sat_pi_uniq_bitvec;
82 
84  sigmap(sigmap), drivers(drivers), satgen(&ez, &sigmap)
85  {
86  satgen.model_undef = true;
87  }
88 
89  int get_bits(int val)
90  {
91  int bits = 0;
92  for (int i = 8*sizeof(int); val; i = i >> 1)
93  if (val >> (i-1)) {
94  bits += i;
95  val = val >> i;
96  }
97  return bits;
98  }
99 
101  {
102  if (sat_pi.count(bit) != 0)
103  return;
104 
105  satgen.setContext(&sigmap, "A");
106  int sat_a = satgen.importSigSpec(bit).front();
107  ez.assume(ez.NOT(satgen.importUndefSigSpec(bit).front()));
108 
109  satgen.setContext(&sigmap, "B");
110  int sat_b = satgen.importSigSpec(bit).front();
111  ez.assume(ez.NOT(satgen.importUndefSigSpec(bit).front()));
112 
113  int idx = sat_pi.size();
114  size_t idx_bits = get_bits(idx);
115 
116  if (sat_pi_uniq_bitvec.size() != idx_bits) {
117  sat_pi_uniq_bitvec.push_back(ez.frozen_literal(stringf("uniq_%d", int(idx_bits)-1)));
118  for (auto &it : sat_pi)
119  ez.assume(ez.OR(ez.NOT(it.second), ez.NOT(sat_pi_uniq_bitvec.back())));
120  }
121  log_assert(sat_pi_uniq_bitvec.size() == idx_bits);
122 
123  sat_pi[bit] = ez.frozen_literal(stringf("p, falsei_%s", log_signal(bit)));
124  ez.assume(ez.IFF(ez.XOR(sat_a, sat_b), sat_pi[bit]));
125 
126  for (size_t i = 0; i < idx_bits; i++)
127  if ((idx & (1 << i)) == 0)
128  ez.assume(ez.OR(ez.NOT(sat_pi[bit]), ez.NOT(sat_pi_uniq_bitvec[i])));
129  else
130  ez.assume(ez.OR(ez.NOT(sat_pi[bit]), sat_pi_uniq_bitvec[i]));
131  }
132 
133  void register_cone_worker(std::set<RTLIL::SigBit> &pi, std::set<RTLIL::SigBit> &sigdone, RTLIL::SigBit out)
134  {
135  if (out.wire == NULL)
136  return;
137  if (sigdone.count(out) != 0)
138  return;
139  sigdone.insert(out);
140 
141  if (drivers.count(out) != 0) {
142  std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv = drivers.at(out);
143  if (ez_cells.count(drv.first) == 0) {
144  satgen.setContext(&sigmap, "A");
145  if (!satgen.importCell(drv.first))
146  log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(drv.first->name), RTLIL::id2cstr(drv.first->type));
147  satgen.setContext(&sigmap, "B");
148  if (!satgen.importCell(drv.first))
149  log_abort();
150  ez_cells.insert(drv.first);
151  }
152  for (auto &bit : drv.second)
153  register_cone_worker(pi, sigdone, bit);
154  } else {
155  register_pi_bit(out);
156  pi.insert(out);
157  }
158  }
159 
160  void register_cone(std::vector<RTLIL::SigBit> &pi, RTLIL::SigBit out)
161  {
162  std::set<RTLIL::SigBit> pi_set, sigdone;
163  register_cone_worker(pi_set, sigdone, out);
164  pi.clear();
165  pi.insert(pi.end(), pi_set.begin(), pi_set.end());
166  }
167 
168  void analyze(std::vector<RTLIL::SigBit> &reduced_inputs, RTLIL::SigBit output, int prec)
169  {
170  if (verbose_level >= 1)
171  log("[%2d%%] Analyzing input cone for signal %s:\n", prec, log_signal(output));
172 
173  std::vector<RTLIL::SigBit> pi;
174  register_cone(pi, output);
175 
176  if (verbose_level >= 1)
177  log(" Found %d input signals and %d cells.\n", int(pi.size()), int(ez_cells.size()));
178 
179  satgen.setContext(&sigmap, "A");
180  int output_a = satgen.importSigSpec(output).front();
181  int output_undef_a = satgen.importUndefSigSpec(output).front();
182 
183  satgen.setContext(&sigmap, "B");
184  int output_b = satgen.importSigSpec(output).front();
185  int output_undef_b = satgen.importUndefSigSpec(output).front();
186 
187  std::set<int> unused_pi_idx;
188 
189  for (size_t i = 0; i < pi.size(); i++)
190  unused_pi_idx.insert(i);
191 
192  while (1)
193  {
194  std::vector<int> model_pi_idx;
195  std::vector<int> model_expr;
196  std::vector<bool> model;
197 
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]));
202  }
203 
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)))
205  break;
206 
207  int found_count = 0;
208  for (size_t i = 0; i < model_pi_idx.size(); i++)
209  if (model[i]) {
210  if (verbose_level >= 2)
211  log(" Found relevant input: %s\n", log_signal(pi[model_pi_idx[i]]));
212  unused_pi_idx.erase(model_pi_idx[i]);
213  found_count++;
214  }
215  log_assert(found_count == 1);
216  }
217 
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]);
221 
222  if (verbose_level >= 1)
223  log(" Reduced input cone contains %d inputs.\n", int(reduced_inputs.size()));
224  }
225 };
226 
228 {
231  std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> &inv_pairs;
232 
235 
236  std::vector<int> sat_pi, sat_out, sat_def;
237  std::vector<RTLIL::SigBit> out_bits, pi_bits;
238  std::vector<bool> out_inverted;
239  std::vector<int> out_depth;
241 
242  int register_cone_worker(std::set<RTLIL::Cell*> &celldone, std::map<RTLIL::SigBit, int> &sigdepth, RTLIL::SigBit out)
243  {
244  if (out.wire == NULL)
245  return 0;
246  if (sigdepth.count(out) != 0)
247  return sigdepth.at(out);
248 
249  if (drivers.count(out) != 0) {
250  std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv = drivers.at(out);
251  if (celldone.count(drv.first) == 0) {
252  if (!satgen.importCell(drv.first))
253  log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(drv.first->name), RTLIL::id2cstr(drv.first->type));
254  celldone.insert(drv.first);
255  }
256  int max_child_depth = 0;
257  for (auto &bit : drv.second)
258  max_child_depth = std::max(register_cone_worker(celldone, sigdepth, bit), max_child_depth);
259  sigdepth[out] = max_child_depth + 1;
260  } else {
261  pi_bits.push_back(out);
262  sat_pi.push_back(satgen.importSigSpec(out).front());
263  ez.assume(ez.NOT(satgen.importUndefSigSpec(out).front()));
264  sigdepth[out] = 0;
265  }
266 
267  return sigdepth.at(out);
268  }
269 
270  PerformReduction(SigMap &sigmap, drivers_t &drivers, std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> &inv_pairs, std::vector<RTLIL::SigBit> &bits, int cone_size) :
271  sigmap(sigmap), drivers(drivers), inv_pairs(inv_pairs), satgen(&ez, &sigmap), out_bits(bits), cone_size(cone_size)
272  {
273  satgen.model_undef = true;
274 
275  std::set<RTLIL::Cell*> celldone;
276  std::map<RTLIL::SigBit, int> sigdepth;
277 
278  for (auto &bit : bits) {
279  out_depth.push_back(register_cone_worker(celldone, sigdepth, bit));
280  sat_out.push_back(satgen.importSigSpec(bit).front());
281  sat_def.push_back(ez.NOT(satgen.importUndefSigSpec(bit).front()));
282  }
283 
284  if (inv_mode && cone_size > 0) {
285  if (!ez.solve(sat_out, out_inverted, ez.expression(ezSAT::OpAnd, sat_def)))
286  log_error("Solving for initial model failed!\n");
287  for (size_t i = 0; i < sat_out.size(); i++)
288  if (out_inverted.at(i))
289  sat_out[i] = ez.NOT(sat_out[i]);
290  } else
291  out_inverted = std::vector<bool>(sat_out.size(), false);
292  }
293 
294  void analyze_const(std::vector<std::vector<equiv_bit_t>> &results, int idx)
295  {
296  if (verbose_level == 1)
297  log(" Finding const value for %s.\n", log_signal(out_bits[idx]));
298 
299  bool can_be_set = ez.solve(ez.AND(sat_out[idx], sat_def[idx]));
300  bool can_be_clr = ez.solve(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
301  log_assert(!can_be_set || !can_be_clr);
302 
304  if (can_be_set)
305  value = RTLIL::State::S1;
306  if (can_be_clr)
307  value = RTLIL::State::S0;
308  if (verbose_level == 1)
309  log(" Constant value for this signal: %s\n", log_signal(value));
310 
311  int result_idx = -1;
312  for (size_t i = 0; i < results.size(); i++) {
313  if (results[i].front().bit == value) {
314  result_idx = i;
315  break;
316  }
317  }
318 
319  if (result_idx == -1) {
320  result_idx = results.size();
321  results.push_back(std::vector<equiv_bit_t>());
322  equiv_bit_t bit;
323  bit.depth = 0;
324  bit.inverted = false;
325  bit.drv = NULL;
326  bit.bit = value;
327  results.back().push_back(bit);
328  }
329 
330  equiv_bit_t bit;
331  bit.depth = 1;
332  bit.inverted = false;
333  bit.drv = drivers.count(out_bits[idx]) ? drivers.at(out_bits[idx]).first : NULL;
334  bit.bit = out_bits[idx];
335  results[result_idx].push_back(bit);
336  }
337 
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)
339  {
340  std::string indent = indent1 + indent2;
341  const char *indt = indent.c_str();
342 
343  if (bucket.size() <= 1)
344  return;
345 
346  if (verbose_level == 1)
347  log("%s Trying to shatter bucket with %d signals.\n", indt, int(bucket.size()));
348 
349  if (verbose_level > 1) {
350  std::vector<RTLIL::SigBit> bucket_sigbits;
351  for (int idx : bucket)
352  bucket_sigbits.push_back(out_bits[idx]);
353  log("%s Trying to shatter bucket with %d signals: %s\n", indt, int(bucket.size()), log_signal(bucket_sigbits));
354  }
355 
356  std::vector<int> sat_set_list, sat_clr_list;
357  for (int idx : bucket) {
358  sat_set_list.push_back(ez.AND(sat_out[idx], sat_def[idx]));
359  sat_clr_list.push_back(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
360  }
361 
362  std::vector<int> modelVars = sat_out;
363  std::vector<bool> model;
364 
365  modelVars.insert(modelVars.end(), sat_def.begin(), sat_def.end());
366  if (verbose_level >= 2)
367  modelVars.insert(modelVars.end(), sat_pi.begin(), sat_pi.end());
368 
369  if (ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_set_list), ez.expression(ezSAT::OpOr, sat_clr_list)))
370  {
371  int iter_count = 1;
372 
373  while (1)
374  {
375  sat_set_list.clear();
376  sat_clr_list.clear();
377 
378  std::vector<int> sat_def_list;
379 
380  for (int idx : bucket)
381  if (!model[sat_out.size() + idx]) {
382  sat_set_list.push_back(ez.AND(sat_out[idx], sat_def[idx]));
383  sat_clr_list.push_back(ez.AND(ez.NOT(sat_out[idx]), sat_def[idx]));
384  } else {
385  sat_def_list.push_back(sat_def[idx]);
386  }
387 
388  if (!ez.solve(modelVars, model, ez.expression(ezSAT::OpOr, sat_set_list), ez.expression(ezSAT::OpOr, sat_clr_list), ez.expression(ezSAT::OpAnd, sat_def_list)))
389  break;
390  iter_count++;
391  }
392 
393  if (verbose_level >= 1) {
394  int count_set = 0, count_clr = 0, count_undef = 0;
395  for (int idx : bucket)
396  if (!model[sat_out.size() + idx])
397  count_undef++;
398  else if (model[idx])
399  count_set++;
400  else
401  count_clr++;
402  log("%s After %d iterations: %d set vs. %d clr vs %d undef\n", indt, iter_count, count_set, count_clr, count_undef);
403  }
404 
405  if (verbose_level >= 2) {
406  for (size_t i = 0; i < pi_bits.size(); i++)
407  log("%s -> PI %c == %s\n", indt, model[2*sat_out.size() + i] ? '1' : '0', log_signal(pi_bits[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',
410  out_inverted.at(idx) ? "~" : "", log_signal(out_bits[idx]));
411  }
412 
413  std::vector<int> buckets_a;
414  std::vector<int> buckets_b;
415 
416  for (int idx : bucket) {
417  if (!model[sat_out.size() + idx] || model[idx])
418  buckets_a.push_back(idx);
419  if (!model[sat_out.size() + idx] || !model[idx])
420  buckets_b.push_back(idx);
421  }
422  analyze(results, results_map, buckets_a, indent1 + ".", indent2 + " ");
423  analyze(results, results_map, buckets_b, indent1 + "x", indent2 + " ");
424  }
425  else
426  {
427  std::vector<int> undef_slaves;
428 
429  for (int idx : bucket) {
430  std::vector<int> sat_def_list;
431  for (int idx2 : bucket)
432  if (idx != idx2)
433  sat_def_list.push_back(sat_def[idx2]);
434  if (ez.solve(ez.NOT(sat_def[idx]), ez.expression(ezSAT::OpOr, sat_def_list)))
435  undef_slaves.push_back(idx);
436  }
437 
438  if (undef_slaves.size() == bucket.size()) {
439  if (verbose_level >= 1)
440  log("%s Complex undef overlap. None of the signals covers the others.\n", indt);
441  // FIXME: We could try to further shatter a group with complex undef overlaps
442  return;
443  }
444 
445  for (int idx : undef_slaves)
446  out_depth[idx] = std::numeric_limits<int>::max();
447 
448  if (verbose_level >= 1) {
449  log("%s Found %d equivialent signals:", indt, int(bucket.size()));
450  for (int idx : bucket)
451  log("%s%s%s", idx == bucket.front() ? " " : ", ", out_inverted[idx] ? "~" : "", log_signal(out_bits[idx]));
452  log("\n");
453  }
454 
455  int result_idx = -1;
456  for (int idx : bucket) {
457  if (results_map.count(idx) == 0)
458  continue;
459  if (result_idx == -1) {
460  result_idx = results_map.at(idx);
461  continue;
462  }
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();
468  }
469 
470  if (result_idx == -1) {
471  result_idx = results.size();
472  results.push_back(std::set<int>());
473  }
474 
475  results[result_idx].insert(bucket.begin(), bucket.end());
476  }
477  }
478 
479  void analyze(std::vector<std::vector<equiv_bit_t>> &results, int perc)
480  {
481  std::vector<int> bucket;
482  for (size_t i = 0; i < sat_out.size(); i++)
483  bucket.push_back(i);
484 
485  std::vector<std::set<int>> results_buf;
486  std::map<int, int> results_map;
487  analyze(results_buf, results_map, bucket, stringf("[%2d%%] %d ", perc, cone_size), "");
488 
489  for (auto &r : results_buf)
490  {
491  if (r.size() <= 1)
492  continue;
493 
494  if (verbose_level >= 1) {
495  std::vector<RTLIL::SigBit> r_sigbits;
496  for (int idx : r)
497  r_sigbits.push_back(out_bits[idx]);
498  log(" Found group of %d equivialent signals: %s\n", int(r.size()), log_signal(r_sigbits));
499  }
500 
501  std::vector<int> undef_slaves;
502 
503  for (int idx : r) {
504  std::vector<int> sat_def_list;
505  for (int idx2 : r)
506  if (idx != idx2)
507  sat_def_list.push_back(sat_def[idx2]);
508  if (ez.solve(ez.NOT(sat_def[idx]), ez.expression(ezSAT::OpOr, sat_def_list)))
509  undef_slaves.push_back(idx);
510  }
511 
512  if (undef_slaves.size() == bucket.size()) {
513  if (verbose_level >= 1)
514  log(" Complex undef overlap. None of the signals covers the others.\n");
515  // FIXME: We could try to further shatter a group with complex undef overlaps
516  return;
517  }
518 
519  for (int idx : undef_slaves)
520  out_depth[idx] = std::numeric_limits<int>::max();
521 
522  std::vector<equiv_bit_t> result;
523 
524  for (int idx : r) {
525  equiv_bit_t bit;
526  bit.depth = out_depth[idx];
527  bit.inverted = out_inverted[idx];
528  bit.drv = drivers.count(out_bits[idx]) ? drivers.at(out_bits[idx]).first : NULL;
529  bit.bit = out_bits[idx];
530  result.push_back(bit);
531  }
532 
533  std::sort(result.begin(), result.end());
534 
535  if (result.front().inverted)
536  for (auto &bit : result)
537  bit.inverted = !bit.inverted;
538 
539  for (size_t i = 1; i < result.size(); i++) {
540  std::pair<RTLIL::SigBit, RTLIL::SigBit> p(result[0].bit, result[i].bit);
541  if (inv_pairs.count(p) != 0)
542  result.erase(result.begin() + i);
543  }
544 
545  if (result.size() > 1)
546  results.push_back(result);
547  }
548  }
549 };
550 
552 {
555 
558  std::set<std::pair<RTLIL::SigBit, RTLIL::SigBit>> inv_pairs;
559 
560  FreduceWorker(RTLIL::Design *design, RTLIL::Module *module) : design(design), module(module), sigmap(module)
561  {
562  }
563 
564  bool find_bit_in_cone(std::set<RTLIL::Cell*> &celldone, RTLIL::SigBit needle, RTLIL::SigBit haystack)
565  {
566  if (needle == haystack)
567  return true;
568  if (haystack.wire == NULL || needle.wire == NULL || drivers.count(haystack) == 0)
569  return false;
570 
571  std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> &drv = drivers.at(haystack);
572 
573  if (celldone.count(drv.first))
574  return false;
575  celldone.insert(drv.first);
576 
577  for (auto &bit : drv.second)
578  if (find_bit_in_cone(celldone, needle, bit))
579  return true;
580  return false;
581  }
582 
584  {
585  std::set<RTLIL::Cell*> celldone;
586  return find_bit_in_cone(celldone, needle, haystack);
587  }
588 
589  void dump()
590  {
591  std::string filename = stringf("%s_%s_%05d.il", dump_prefix.c_str(), RTLIL::id2cstr(module->name), reduce_counter);
592  log("%s Writing dump file `%s'.\n", reduce_counter ? " " : "", filename.c_str());
593  Pass::call(design, stringf("dump -outfile %s %s", filename.c_str(), design->selected_active_module.empty() ? module->name.c_str() : ""));
594  }
595 
596  int run()
597  {
598  log("Running functional reduction on module %s:\n", RTLIL::id2cstr(module->name));
599 
600  CellTypes ct;
601  ct.setup_internals();
602  ct.setup_stdcells();
603 
604  int bits_full_total = 0;
605  std::vector<std::set<RTLIL::SigBit>> batches;
606  for (auto &it : module->wires_)
607  if (it.second->port_input) {
608  batches.push_back(sigmap(it.second).to_sigbit_set());
609  bits_full_total += it.second->width;
610  }
611  for (auto &it : module->cells_) {
612  if (ct.cell_known(it.second->type)) {
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();
616  if (ct.cell_output(it.second->type, port.first))
617  outputs.insert(bits.begin(), bits.end());
618  else
619  inputs.insert(bits.begin(), bits.end());
620  }
621  std::pair<RTLIL::Cell*, std::set<RTLIL::SigBit>> drv(it.second, inputs);
622  for (auto &bit : outputs)
623  drivers[bit] = drv;
624  batches.push_back(outputs);
625  bits_full_total += outputs.size();
626  }
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"))));
629  }
630 
631  int bits_count = 0;
632  int bits_full_count = 0;
633  std::map<std::vector<RTLIL::SigBit>, std::vector<RTLIL::SigBit>> buckets;
634  for (auto &batch : batches)
635  {
636  for (auto &bit : batch)
637  if (bit.wire != NULL && design->selected(module, bit.wire))
638  goto found_selected_wire;
639  bits_full_count += batch.size();
640  continue;
641 
642  found_selected_wire:
643  log(" Finding reduced input cone for signal batch %s%c\n",
644  log_signal(batch), verbose_level ? ':' : '.');
645 
646  FindReducedInputs infinder(sigmap, drivers);
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);
651  bits_full_count++;
652  bits_count++;
653  }
654  }
655  log(" Sorted %d signal bits into %d buckets.\n", bits_count, int(buckets.size()));
656 
657  int bucket_count = 0;
658  std::vector<std::vector<equiv_bit_t>> equiv;
659  for (auto &bucket : buckets)
660  {
661  bucket_count++;
662 
663  if (bucket.second.size() == 1)
664  continue;
665 
666  if (bucket.first.size() == 0) {
667  log(" Finding const values for bucket %s%c\n", log_signal(bucket.second), verbose_level ? ':' : '.');
668  PerformReduction worker(sigmap, drivers, inv_pairs, bucket.second, bucket.first.size());
669  for (size_t idx = 0; idx < bucket.second.size(); idx++)
670  worker.analyze_const(equiv, idx);
671  } else {
672  log(" Trying to shatter bucket %s%c\n", log_signal(bucket.second), verbose_level ? ':' : '.');
673  PerformReduction worker(sigmap, drivers, inv_pairs, bucket.second, bucket.first.size());
674  worker.analyze(equiv, 100 * bucket_count / (buckets.size() + 1));
675  }
676  }
677 
678  std::map<RTLIL::SigBit, int> bitusage;
680 
681  if (!dump_prefix.empty())
682  dump();
683 
684  log(" Rewiring %d equivialent groups:\n", int(equiv.size()));
685  int rewired_sigbits = 0;
686  for (auto &grp : equiv)
687  {
688  log(" [%05d] Using as master for group: %s\n", ++reduce_counter, log_signal(grp.front().bit));
689 
690  RTLIL::SigSpec inv_sig;
691  for (size_t i = 1; i < grp.size(); i++)
692  {
693  if (!design->selected(module, grp[i].bit.wire)) {
694  log(" Skipping not-selected slave: %s\n", log_signal(grp[i].bit));
695  continue;
696  }
697 
698  if (grp[i].bit.wire->port_id == 0 && bitusage[grp[i].bit] <= 1) {
699  log(" Skipping unused slave: %s\n", log_signal(grp[i].bit));
700  continue;
701  }
702 
703  if (find_bit_in_cone(grp[i].bit, grp.front().bit)) {
704  log(" Skipping dependency of master: %s\n", log_signal(grp[i].bit));
705  continue;
706  }
707 
708  log(" Connect slave%s: %s\n", grp[i].inverted ? " using inverter" : "", log_signal(grp[i].bit));
709 
710  RTLIL::Cell *drv = drivers.at(grp[i].bit).first;
711  RTLIL::Wire *dummy_wire = module->addWire(NEW_ID);
712  for (auto &port : drv->connections_)
713  if (ct.cell_output(drv->type, port.first))
714  sigmap(port.second).replace(grp[i].bit, dummy_wire, &port.second);
715 
716  if (grp[i].inverted)
717  {
718  if (inv_sig.size() == 0)
719  {
720  inv_sig = module->addWire(NEW_ID);
721 
722  RTLIL::Cell *inv_cell = module->addCell(NEW_ID, "$_NOT_");
723  inv_cell->setPort("\\A", grp[0].bit);
724  inv_cell->setPort("\\Y", inv_sig);
725  }
726 
727  module->connect(RTLIL::SigSig(grp[i].bit, inv_sig));
728  }
729  else
730  module->connect(RTLIL::SigSig(grp[i].bit, grp[0].bit));
731 
732  rewired_sigbits++;
733  }
734 
735  if (!dump_prefix.empty())
736  dump();
737 
739  log(" Reached limit passed using -stop option. Skipping all further reductions.\n");
740  break;
741  }
742  }
743 
744  log(" Rewired a total of %d signal bits in module %s.\n", rewired_sigbits, RTLIL::id2cstr(module->name));
745  return rewired_sigbits;
746  }
747 };
748 
749 struct FreducePass : public Pass {
750  FreducePass() : Pass("freduce", "perform functional reduction") { }
751  virtual void help()
752  {
753  // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
754  log("\n");
755  log(" freduce [options] [selection]\n");
756  log("\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");
760  log("\n");
761  log(" -v, -vv\n");
762  log(" enable verbose or very verbose output\n");
763  log("\n");
764  log(" -inv\n");
765  log(" enable explicit handling of inverted signals\n");
766  log("\n");
767  log(" -stop <n>\n");
768  log(" stop after <n> reduction operations. this is mostly used for\n");
769  log(" debugging the freduce command itself.\n");
770  log("\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");
774  log("\n");
775  log("This pass is undef-aware, i.e. it considers don't-care values for detecting\n");
776  log("equivialent nodes.\n");
777  log("\n");
778  log("All selected wires are considered for rewiring. The selected cells cover the\n");
779  log("circuit that is analyzed.\n");
780  log("\n");
781  }
782  virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
783  {
784  reduce_counter = 0;
785  reduce_stop_at = 0;
786  verbose_level = 0;
787  inv_mode = false;
788  dump_prefix = std::string();
789 
790  log_header("Executing FREDUCE pass (perform functional reduction).\n");
791 
792  size_t argidx;
793  for (argidx = 1; argidx < args.size(); argidx++) {
794  if (args[argidx] == "-v") {
795  verbose_level = 1;
796  continue;
797  }
798  if (args[argidx] == "-vv") {
799  verbose_level = 2;
800  continue;
801  }
802  if (args[argidx] == "-inv") {
803  inv_mode = true;
804  continue;
805  }
806  if (args[argidx] == "-stop" && argidx+1 < args.size()) {
807  reduce_stop_at = atoi(args[++argidx].c_str());
808  continue;
809  }
810  if (args[argidx] == "-dump" && argidx+1 < args.size()) {
811  dump_prefix = args[++argidx];
812  continue;
813  }
814  break;
815  }
816  extra_args(args, argidx, design);
817 
818  int bitcount = 0;
819  for (auto &mod_it : design->modules_) {
820  RTLIL::Module *module = mod_it.second;
821  if (design->selected(module))
822  bitcount += FreduceWorker(design, module).run();
823  }
824 
825  log("Rewired a total of %d signal bits.\n", bitcount);
826  }
827 } FreducePass;
828 
const char * c_str() const
Definition: rtlil.h:178
FindReducedInputs(SigMap &sigmap, drivers_t &drivers)
Definition: freduce.cc:83
bool selected(T1 *module) const
Definition: rtlil.h:551
void operator()(RTLIL::SigSpec &sig)
Definition: freduce.cc:64
RTLIL::Wire * wire
Definition: rtlil.h:907
ezDefaultSAT ez
Definition: freduce.cc:76
RTLIL::Wire * wire(RTLIL::IdString id)
Definition: rtlil.h:637
FreducePass FreducePass
std::set< std::pair< RTLIL::SigBit, RTLIL::SigBit > > & inv_pairs
Definition: freduce.cc:231
bool operator<(const equiv_bit_t &other) const
Definition: freduce.cc:46
void setup_stdcells()
Definition: celltypes.h:132
std::string stringf(const char *fmt,...)
Definition: yosys.cc:58
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:57
int register_cone_worker(std::set< RTLIL::Cell * > &celldone, std::map< RTLIL::SigBit, int > &sigdepth, RTLIL::SigBit out)
Definition: freduce.cc:242
RTLIL::SigBit bit
Definition: freduce.cc:44
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
Definition: rtlil.cc:1353
void analyze(std::vector< std::vector< equiv_bit_t >> &results, int perc)
Definition: freduce.cc:479
void log_header(const char *format,...)
Definition: log.cc:188
int reduce_counter
Definition: freduce.cc:35
CellTypes ct
Definition: opt_clean.cc:33
SigMap sigmap
Definition: freduce.cc:556
std::map< RTLIL::IdString, RTLIL::Wire * > wires_
Definition: rtlil.h:595
void rewrite_sigspecs(T functor)
Definition: rtlil.h:1166
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
Definition: log.cc:269
static std::string idx(std::string str)
Definition: test_autotb.cc:57
bool inverted
Definition: freduce.cc:42
CountBitUsage(SigMap &sigmap, std::map< RTLIL::SigBit, int > &cache)
Definition: freduce.cc:62
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
Definition: rtlil.cc:1789
std::vector< int > importSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:78
void log_error(const char *format,...)
Definition: log.cc:204
RTLIL::Module * module
Definition: abc.cc:94
RTLIL::IdString type
Definition: rtlil.h:854
int size() const
Definition: rtlil.h:1019
#define log_abort()
Definition: log.h:84
bool model_undef
Definition: satgen.h:43
void analyze_const(std::vector< std::vector< equiv_bit_t >> &results, int idx)
Definition: freduce.cc:294
SigMap & sigmap
Definition: freduce.cc:229
void analyze(std::vector< RTLIL::SigBit > &reduced_inputs, RTLIL::SigBit output, int prec)
Definition: freduce.cc:168
int get_bits(int val)
Definition: freduce.cc:89
drivers_t & drivers
Definition: freduce.cc:74
RTLIL::Design * design
Definition: freduce.cc:553
FreduceWorker(RTLIL::Design *design, RTLIL::Module *module)
Definition: freduce.cc:560
std::set< RTLIL::Cell * > ez_cells
Definition: freduce.cc:77
std::vector< int > importUndefSigSpec(RTLIL::SigSpec sig, int timestep=-1)
Definition: satgen.h:92
void register_pi_bit(RTLIL::SigBit bit)
Definition: freduce.cc:100
YOSYS_NAMESPACE_BEGIN typedef ezMiniSAT ezDefaultSAT
Definition: satgen.h:32
USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN bool inv_mode
Definition: freduce.cc:34
bool cell_known(RTLIL::IdString type)
Definition: celltypes.h:188
void connect(const RTLIL::SigSig &conn)
Definition: rtlil.cc:1278
#define PRIVATE_NAMESPACE_BEGIN
Definition: yosys.h:97
std::string dump_prefix
Definition: freduce.cc:37
bool cell_output(RTLIL::IdString type, RTLIL::IdString port)
Definition: celltypes.h:193
RTLIL::Module * module
Definition: freduce.cc:554
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
Definition: freduce.cc:782
void register_cone(std::vector< RTLIL::SigBit > &pi, RTLIL::SigBit out)
Definition: freduce.cc:160
std::vector< RTLIL::SigBit > pi_bits
Definition: freduce.cc:237
#define log_assert(_assert_expr_)
Definition: log.h:85
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
Definition: rtlil.cc:1331
RTLIL::IdString name
Definition: rtlil.h:599
int depth
Definition: freduce.cc:41
#define NEW_ID
Definition: yosys.h:166
std::vector< bool > out_inverted
Definition: freduce.cc:238
int verbose_level
Definition: freduce.cc:35
#define PRIVATE_NAMESPACE_END
Definition: yosys.h:98
Definition: satgen.h:34
void setContext(SigMap *sigmap, std::string prefix=std::string())
Definition: satgen.h:50
Definition: register.h:27
static const char * id2cstr(const RTLIL::IdString &str)
Definition: rtlil.h:267
#define USING_YOSYS_NAMESPACE
Definition: yosys.h:102
ezDefaultSAT ez
Definition: freduce.cc:233
std::map< RTLIL::IdString, RTLIL::Module * > modules_
Definition: rtlil.h:507
virtual void help()
Definition: freduce.cc:751
std::map< RTLIL::SigBit, int > sat_pi
Definition: freduce.cc:80
#define NULL
PerformReduction(SigMap &sigmap, drivers_t &drivers, std::set< std::pair< RTLIL::SigBit, RTLIL::SigBit >> &inv_pairs, std::vector< RTLIL::SigBit > &bits, int cone_size)
Definition: freduce.cc:270
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
Definition: rtlil.h:596
drivers_t & drivers
Definition: freduce.cc:230
std::vector< int > sat_def
Definition: freduce.cc:236
void log(const char *format,...)
Definition: log.cc:180
std::vector< int > sat_pi_uniq_bitvec
Definition: freduce.cc:81
bool find_bit_in_cone(std::set< RTLIL::Cell * > &celldone, RTLIL::SigBit needle, RTLIL::SigBit haystack)
Definition: freduce.cc:564
std::vector< int > sat_out
Definition: freduce.cc:236
void setup_internals()
Definition: celltypes.h:83
bool find_bit_in_cone(RTLIL::SigBit needle, RTLIL::SigBit haystack)
Definition: freduce.cc:583
bool importCell(RTLIL::Cell *cell, int timestep=-1)
Definition: satgen.h:203
std::map< RTLIL::IdString, RTLIL::SigSpec > connections_
Definition: rtlil.h:855
std::string selected_active_module
Definition: rtlil.h:511
std::vector< int > out_depth
Definition: freduce.cc:239
std::map< RTLIL::SigBit, int > & cache
Definition: freduce.cc:60
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
Definition: register.cc:128
static void call(RTLIL::Design *design, std::string command)
Definition: register.cc:146
std::pair< SigSpec, SigSpec > SigSig
Definition: rtlil.h:71
int reduce_stop_at
Definition: freduce.cc:35
void analyze(std::vector< std::set< int >> &results, std::map< int, int > &results_map, std::vector< int > &bucket, std::string indent1, std::string indent2)
Definition: freduce.cc:338
RTLIL::Cell * drv
Definition: freduce.cc:43
std::vector< RTLIL::SigBit > out_bits
Definition: freduce.cc:237
std::set< std::pair< RTLIL::SigBit, RTLIL::SigBit > > inv_pairs
Definition: freduce.cc:558
void dump()
Definition: freduce.cc:589
std::map< RTLIL::SigBit, std::pair< RTLIL::Cell *, std::set< RTLIL::SigBit > > > drivers_t
Definition: freduce.cc:36
drivers_t drivers
Definition: freduce.cc:557
std::vector< int > sat_pi
Definition: freduce.cc:236
SigMap & sigmap
Definition: freduce.cc:73
void register_cone_worker(std::set< RTLIL::SigBit > &pi, std::set< RTLIL::SigBit > &sigdone, RTLIL::SigBit out)
Definition: freduce.cc:133
SigMap & sigmap
Definition: freduce.cc:59