{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
- log(" opt [selection]\n");
+ log(" opt [-mux_undef] [-mux_bool] [selection]\n");
log("\n");
log("This pass calls all the other opt_* passes in a useful order. This performs\n");
log("a series of trivial optimizations and cleanups. This pass executes the other\n");
log(" opt_share\n");
log(" opt_rmdff\n");
log(" opt_clean\n");
- log(" opt_const\n");
+ log(" opt_const [-mux_undef] [-mux_bool]\n");
log(" while [changed design]\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
+ std::string opt_const_args;
+
log_header("Executing OPT pass (performing simple optimizations).\n");
log_push();
- extra_args(args, 1, design);
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-mux_undef") {
+ opt_const_args += " -mux_undef";
+ continue;
+ }
+ if (args[argidx] == "-mux_bool") {
+ opt_const_args += " -mux_bool";
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
log_header("Optimizing in-memory representation of design.\n");
design->optimize();
Pass::call(design, "opt_share");
Pass::call(design, "opt_rmdff");
Pass::call(design, "opt_clean");
- Pass::call(design, "opt_const");
+ Pass::call(design, "opt_const" + opt_const_args);
if (OPT_DID_SOMETHING == false)
break;
log_header("Rerunning OPT passes. (Maybe there is more to do..)\n");
did_something = true;
}
-void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef)
+void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool consume_x, bool mux_undef, bool mux_bool)
{
if (!design->selected(module))
return;
}
}
+ if (mux_bool && cell->type == "$mux" && cell->connections["\\A"] == RTLIL::SigSpec(0, 1) && cell->connections["\\B"] == RTLIL::SigSpec(1, 1)) {
+ replace_cell(module, cell, "mux_bool", "\\Y", cell->connections["\\S"]);
+ goto next_cell;
+ }
+
+ if (mux_bool && cell->type == "$mux" && cell->connections["\\A"] == RTLIL::SigSpec(1, 1) && cell->connections["\\B"] == RTLIL::SigSpec(0, 1)) {
+ cell->connections["\\A"] = cell->connections["\\S"];
+ cell->connections.erase("\\B");
+ cell->connections.erase("\\S");
+ cell->parameters["\\A_WIDTH"] = cell->parameters["\\WIDTH"];
+ cell->parameters["\\Y_WIDTH"] = cell->parameters["\\WIDTH"];
+ cell->parameters["\\A_SIGNED"] = 0;
+ cell->parameters.erase("\\WIDTH");
+ cell->type = "$not";
+ did_something = true;
+ goto next_cell;
+ }
+
if (mux_undef && (cell->type == "$mux" || cell->type == "$pmux")) {
RTLIL::SigSpec new_a, new_b, new_s;
int width = cell->connections.at("\\A").width;
log(" -mux_undef\n");
log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n");
log("\n");
+ log(" -mux_bool\n");
+ log(" replace $mux cells with inverters or buffers when possible\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
bool mux_undef = false;
+ bool mux_bool = false;
log_header("Executing OPT_CONST pass (perform const folding).\n");
log_push();
mux_undef = true;
continue;
}
+ if (args[argidx] == "-mux_bool") {
+ mux_bool = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
do {
do {
did_something = false;
- replace_const_cells(design, mod_it.second, false, mux_undef);
+ replace_const_cells(design, mod_it.second, false, mux_undef, mux_bool);
} while (did_something);
- replace_const_cells(design, mod_it.second, true, mux_undef);
+ replace_const_cells(design, mod_it.second, true, mux_undef, mux_bool);
} while (did_something);
log_pop();