42 if (cells.count(cell) == 0)
47 std::set<RTLIL::SigBit> new_sig_a_bits;
52 if (cell->
type ==
"$reduce_and") {
53 new_sig_a_bits.
clear();
60 if (cell->
type ==
"$reduce_or") {
61 new_sig_a_bits.clear();
67 if (bit.wire ==
NULL) {
68 new_sig_a_bits.insert(bit);
72 bool imported_children =
false;
73 for (
auto child_cell : drivers.
find(bit)) {
74 if (child_cell->type == cell->
type) {
76 if (child_cell->getPort(
"\\Y")[0] == bit) {
77 std::set<RTLIL::SigBit> child_sig_a_bits =
assign_map(child_cell->getPort(
"\\A")).to_sigbit_set();
78 new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end());
81 imported_children =
true;
84 if (!imported_children)
85 new_sig_a_bits.insert(bit);
90 if (new_sig_a != sig_a || sig_a.
size() != cell->
getPort(
"\\A").
size()) {
96 cell->
setPort(
"\\A", new_sig_a);
108 std::set<RTLIL::SigSpec> handled_sig;
110 handled_sig.insert(sig_a);
111 for (
int i = 0; i < sig_s.size(); i++)
114 if (handled_sig.count(this_b) > 0)
118 for (
int j = i+1; j < sig_s.size(); j++) {
120 if (this_b == that_b)
121 this_s.
append(sig_s.extract(j, 1));
124 if (this_s.
size() > 1)
127 reduce_or_cell->
setPort(
"\\A", this_s);
134 reduce_or_cell->
setPort(
"\\Y", this_s);
137 new_sig_b.append(this_b);
138 new_sig_s.append(this_s);
139 handled_sig.insert(this_b);
142 if (new_sig_s.size() != sig_s.size()) {
148 if (new_sig_s.size() == 0)
156 cell->
setPort(
"\\B", new_sig_b);
157 cell->
setPort(
"\\S", new_sig_s);
158 if (new_sig_s.size() > 1) {
169 std::vector<RTLIL::SigBit> sig_a =
assign_map(cell->
getPort(
"\\A")).to_sigbit_vector();
170 std::vector<RTLIL::SigBit> sig_b =
assign_map(cell->
getPort(
"\\B")).to_sigbit_vector();
171 std::vector<RTLIL::SigBit> sig_y =
assign_map(cell->
getPort(
"\\Y")).to_sigbit_vector();
173 std::vector<RTLIL::SigBit> new_sig_y;
176 std::vector<std::vector<RTLIL::SigBit>> consolidated_in_tuples;
177 std::map<std::vector<RTLIL::SigBit>,
RTLIL::SigBit> consolidated_in_tuples_map;
179 for (
int i = 0; i < int(sig_y.size()); i++)
181 std::vector<RTLIL::SigBit> in_tuple;
182 bool all_tuple_bits_same =
true;
184 in_tuple.push_back(sig_a.at(i));
185 for (
int j = i; j < int(sig_b.size()); j += int(sig_a.size())) {
186 if (sig_b.at(j) != sig_a.at(i))
187 all_tuple_bits_same =
false;
188 in_tuple.push_back(sig_b.at(j));
191 if (all_tuple_bits_same)
193 old_sig_conn.first.append_bit(sig_y.at(i));
194 old_sig_conn.second.append_bit(sig_a.at(i));
196 else if (consolidated_in_tuples_map.count(in_tuple))
198 old_sig_conn.first.append_bit(sig_y.at(i));
199 old_sig_conn.second.append_bit(consolidated_in_tuples_map.at(in_tuple));
203 consolidated_in_tuples_map[in_tuple] = sig_y.at(i);
204 consolidated_in_tuples.push_back(in_tuple);
205 new_sig_y.push_back(sig_y.at(i));
209 if (new_sig_y.size() != sig_y.size())
216 for (
auto &in_tuple : consolidated_in_tuples) {
218 new_a.
append(in_tuple.at(0));
223 for (
int i = 1; i <= cell->
getPort(
"\\S").
size(); i++)
224 for (
auto &in_tuple : consolidated_in_tuples) {
226 new_b.
append(in_tuple.at(i));
231 cell->
setPort(
"\\Y", new_sig_y);
246 design(design), module(module),
assign_map(module)
248 log(
" Optimizing cells in module %s.\n", module->
name.
c_str());
254 for (
auto &cell_it : module->
cells_) {
256 if (cell->
type ==
"$mem")
258 if (cell->
type ==
"$memwr")
261 for (
auto &cell_it : module->
cells_) {
267 bool keep_expanding_mem_wren_sigs =
true;
268 while (keep_expanding_mem_wren_sigs) {
269 keep_expanding_mem_wren_sigs =
false;
270 for (
auto &cell_it : module->
cells_) {
275 keep_expanding_mem_wren_sigs =
true;
289 const char *type_list[] = {
"$reduce_or",
"$reduce_and" };
290 for (
auto type : type_list)
293 std::set<RTLIL::Cell*> cells;
295 for (
auto &cell_it : module->
cells_) {
297 if (cell->
type != type || !design->
selected(module, cell))
303 while (cells.size() > 0) {
311 std::vector<RTLIL::Cell*> cells;
313 for (
auto &it : module->
cells_)
314 if ((it.second->type ==
"$mux" || it.second->type ==
"$pmux") && design->
selected(module, it.second))
315 cells.push_back(it.second);
317 for (
auto cell : cells)
336 log(
" opt_reduce [options] [selection]\n");
338 log(
"This pass performs two interlinked optimizations:\n");
340 log(
"1. it consolidates trees of large AND gates or OR gates and eliminates\n");
341 log(
"duplicated inputs.\n");
343 log(
"2. it identifies duplicated inputs to MUXes and replaces them with a single\n");
344 log(
"input with the original control signals OR'ed together.\n");
347 log(
" perform fine-grain optimizations\n");
350 log(
" alias for -fine\n");
355 bool do_fine =
false;
357 log_header(
"Executing OPT_REDUCE pass (consolidate $*mux and $reduce_* inputs).\n");
360 for (argidx = 1; argidx < args.size(); argidx++) {
361 if (args[argidx] ==
"-fine") {
365 if (args[argidx] ==
"-full") {
374 for (
auto &mod_it : design->
modules_) {
375 if (!design->
selected(mod_it.second))
387 log(
"Performed a total of %d changes.\n", total_count);
const char * c_str() const
bool selected(T1 *module) const
OptReduceWorker(RTLIL::Design *design, RTLIL::Module *module, bool do_fine)
RTLIL::Cell * addCell(RTLIL::IdString name, RTLIL::IdString type)
void log_header(const char *format,...)
std::set< RTLIL::SigBit > to_sigbit_set() const
const char * log_signal(const RTLIL::SigSpec &sig, bool autoint)
void opt_mux(RTLIL::Cell *cell)
void setPort(RTLIL::IdString portname, RTLIL::SigSpec signal)
std::map< RTLIL::IdString, RTLIL::Const > parameters
bool check_any(RTLIL::SigSpec sig)
void connect(const RTLIL::SigSig &conn)
#define PRIVATE_NAMESPACE_BEGIN
const RTLIL::SigSpec & getPort(RTLIL::IdString portname) const
RTLIL::Wire * addWire(RTLIL::IdString name, int width=1)
void opt_reduce(std::set< RTLIL::Cell * > &cells, SigSet< RTLIL::Cell * > &drivers, RTLIL::Cell *cell)
#define PRIVATE_NAMESPACE_END
bool check_all(RTLIL::SigSpec sig)
void opt_mux_bits(RTLIL::Cell *cell)
void add(RTLIL::SigSpec sig)
#define USING_YOSYS_NAMESPACE
std::map< RTLIL::IdString, RTLIL::Module * > modules_
std::map< RTLIL::IdString, RTLIL::Cell * > cells_
void remove(const std::set< RTLIL::Wire * > &wires)
virtual void execute(std::vector< std::string > args, RTLIL::Design *design)
void log(const char *format,...)
RTLIL::SigSpec extract(const RTLIL::SigSpec &pattern, const RTLIL::SigSpec *other=NULL) const
void scratchpad_set_bool(std::string varname, bool value)
void append(const RTLIL::SigSpec &signal)
void add(RTLIL::SigSpec from, RTLIL::SigSpec to)
void extra_args(std::vector< std::string > args, size_t argidx, RTLIL::Design *design, bool select=true)
std::pair< SigSpec, SigSpec > SigSig
void find(RTLIL::SigSpec sig, std::set< T > &result)
void insert(RTLIL::SigSpec sig, T data)
OptReducePass OptReducePass