diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/cmds/qwp.cc | 2 | ||||
-rw-r--r-- | passes/opt/opt_clean.cc | 123 | ||||
-rw-r--r-- | passes/opt/opt_expr.cc | 13 | ||||
-rw-r--r-- | passes/opt/wreduce.cc | 36 | ||||
-rw-r--r-- | passes/pmgen/.gitignore | 1 | ||||
-rw-r--r-- | passes/pmgen/Makefile.inc | 17 | ||||
-rw-r--r-- | passes/pmgen/README.md | 24 | ||||
-rw-r--r-- | passes/pmgen/ice40_dsp.cc | 117 | ||||
-rw-r--r-- | passes/pmgen/ice40_dsp.pmg | 2 | ||||
-rw-r--r-- | passes/pmgen/peepopt.cc | 68 | ||||
-rw-r--r-- | passes/pmgen/peepopt_muldiv.pmg | 36 | ||||
-rw-r--r-- | passes/pmgen/peepopt_shiftmul.pmg | 87 | ||||
-rw-r--r-- | passes/pmgen/pmgen.py | 263 | ||||
-rw-r--r-- | passes/sat/expose.cc | 2 | ||||
-rw-r--r-- | passes/sat/sat.cc | 1 | ||||
-rw-r--r-- | passes/techmap/abc.cc | 29 | ||||
-rw-r--r-- | passes/techmap/dffinit.cc | 3 | ||||
-rw-r--r-- | passes/techmap/shregmap.cc | 12 |
18 files changed, 614 insertions, 222 deletions
diff --git a/passes/cmds/qwp.cc b/passes/cmds/qwp.cc index 1c64a7b77..adbe89e31 100644 --- a/passes/cmds/qwp.cc +++ b/passes/cmds/qwp.cc @@ -291,7 +291,7 @@ struct QwpWorker // gaussian elimination for (int i = 0; i < N; i++) { - if (config.verbose && ((i+1) % (N/15)) == 0) + if (config.verbose && N > 15 && ((i+1) % (N/15)) == 0) log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N); // find best row diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index fcb662b59..618d32550 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -272,6 +272,10 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } + SigPool raw_used_signals_noaliases; + for (auto &it : module->connections_) + raw_used_signals_noaliases.add(it.second); + module->connections_.clear(); SigPool used_signals; @@ -281,6 +285,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos for (auto &it2 : cell->connections_) { assign_map.apply(it2.second); used_signals.add(it2.second); + raw_used_signals_noaliases.add(it2.second); if (!ct_all.cell_output(cell->type, it2.first)) used_signals_nodrivers.add(it2.second); } @@ -301,53 +306,63 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - std::vector<RTLIL::Wire*> maybe_del_wires; + pool<RTLIL::Wire*> del_wires_queue; for (auto wire : module->wires()) { - if ((!purge_mode && check_public_name(wire->name)) || wire->port_id != 0 || wire->get_bool_attribute("\\keep") || wire->attributes.count("\\init")) { - RTLIL::SigSpec s1 = RTLIL::SigSpec(wire), s2 = s1; - assign_map.apply(s2); - if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) { - maybe_del_wires.push_back(wire); - } else { - log_assert(GetSize(s1) == GetSize(s2)); - Const initval; - if (wire->attributes.count("\\init")) - initval = wire->attributes.at("\\init"); - if (GetSize(initval) != GetSize(wire)) - initval.bits.resize(GetSize(wire), State::Sx); - RTLIL::SigSig new_conn; - for (int i = 0; i < GetSize(s1); i++) - if (s1[i] != s2[i]) { - if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { - s2[i] = initval[i]; - initval[i] = State::Sx; - } - new_conn.first.append_bit(s1[i]); - new_conn.second.append_bit(s2[i]); + SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); + log_assert(GetSize(s1) == GetSize(s2)); + + Const initval; + if (wire->attributes.count("\\init")) + initval = wire->attributes.at("\\init"); + if (GetSize(initval) != GetSize(wire)) + initval.bits.resize(GetSize(wire), State::Sx); + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + + bool delete_this_wire = false; + if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) { + /* do not delete anything with "keep" or module ports or initialized wires */ + } else + if (!purge_mode && check_public_name(wire->name)) { + /* do not get rid of public names unless in purge mode */ + } else { + if (!raw_used_signals_noaliases.check_any(s1)) + delete_this_wire = true; + if (!used_signals_nodrivers.check_any(s2)) + delete_this_wire = true; + } + + if (delete_this_wire) { + del_wires_queue.insert(wire); + } else { + RTLIL::SigSig new_conn; + for (int i = 0; i < GetSize(s1); i++) + if (s1[i] != s2[i]) { + if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { + s2[i] = initval[i]; + initval[i] = State::Sx; } - if (new_conn.first.size() > 0) { - if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); - else - wire->attributes.at("\\init") = initval; - used_signals.add(new_conn.first); - used_signals.add(new_conn.second); - module->connect(new_conn); + new_conn.first.append_bit(s1[i]); + new_conn.second.append_bit(s2[i]); } + if (new_conn.first.size() > 0) { + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + else + wire->attributes.at("\\init") = initval; + used_signals.add(new_conn.first); + used_signals.add(new_conn.second); + module->connect(new_conn); } - } else { - if (!used_signals.check_any(RTLIL::SigSpec(wire))) - maybe_del_wires.push_back(wire); } - RTLIL::SigSpec sig = assign_map(RTLIL::SigSpec(wire)); - if (!used_signals_nodrivers.check_any(sig)) { + if (!used_signals_nodrivers.check_all(s2)) { std::string unused_bits; - for (int i = 0; i < GetSize(sig); i++) { - if (sig[i].wire == NULL) + for (int i = 0; i < GetSize(s2); i++) { + if (s2[i].wire == NULL) continue; - if (!used_signals_nodrivers.check(sig[i])) { + if (!used_signals_nodrivers.check(s2[i])) { if (!unused_bits.empty()) unused_bits += " "; unused_bits += stringf("%d", i); @@ -362,24 +377,19 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } + int del_temp_wires_count = 0; + for (auto wire : del_wires_queue) { + if (ys_debug() || (check_public_name(wire->name) && verbose)) + log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); + else + del_temp_wires_count++; + } - pool<RTLIL::Wire*> del_wires; - - int del_wires_count = 0; - for (auto wire : maybe_del_wires) - if (!used_signals.check_any(RTLIL::SigSpec(wire))) { - if (check_public_name(wire->name) && verbose) { - log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); - } - del_wires.insert(wire); - del_wires_count++; - } - - module->remove(del_wires); - count_rm_wires += del_wires.size(); + module->remove(del_wires_queue); + count_rm_wires += GetSize(del_wires_queue); - if (verbose && del_wires_count > 0) - log_debug(" removed %d unused temporary wires.\n", del_wires_count); + if (verbose && del_temp_wires_count) + log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count); } bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) @@ -526,6 +536,9 @@ struct OptCleanPass : public Pass { ct_all.setup(design); + count_rm_cells = 0; + count_rm_wires = 0; + for (auto module : design->selected_whole_modules_warn()) { if (module->has_processes_warn()) continue; @@ -591,7 +604,7 @@ struct CleanPass : public Pass { for (auto module : design->selected_whole_modules()) { if (module->has_processes()) continue; - rmunused_module(module, purge_mode, false, false); + rmunused_module(module, purge_mode, ys_debug(), false); } log_suppressed(); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b445afdc8..512ef0cbf 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -61,7 +61,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } if (wire->port_input) driven_signals.add(sigmap(wire)); - if (wire->port_output) + if (wire->port_output || wire->get_bool_attribute("\\keep")) used_signals.add(sigmap(wire)); all_signals.add(sigmap(wire)); } @@ -88,7 +88,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } } - log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val)); + log_debug("Setting undriven signal in %s to constant: %s = %s\n", log_id(module), log_signal(sig), log_signal(val)); module->connect(sig, val); did_something = true; } @@ -104,10 +104,15 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) if (SigBit(initval[i]) == sig[i]) initval[i] = State::Sx; } - if (initval.is_fully_undef()) + if (initval.is_fully_undef()) { + log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); wire->attributes.erase("\\init"); - else + did_something = true; + } else if (initval != wire->attributes.at("\\init")) { + log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); wire->attributes["\\init"] = initval; + did_something = true; + } } } } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 41de8aad1..58c6e4b4b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -531,6 +531,42 @@ struct WreducePass : public Pass { module->connect(sig, Const(0, GetSize(sig))); } } + + if (c->type.in("$div", "$mod", "$pow")) + { + SigSpec A = c->getPort("\\A"); + int original_a_width = GetSize(A); + if (c->getParam("\\A_SIGNED").as_bool()) { + while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0) + A.remove(GetSize(A)-1, 1); + } else { + while (GetSize(A) > 0 && A[GetSize(A)-1] == State::S0) + A.remove(GetSize(A)-1, 1); + } + if (original_a_width != GetSize(A)) { + log("Removed top %d bits (of %d) from port A of cell %s.%s (%s).\n", + original_a_width-GetSize(A), original_a_width, log_id(module), log_id(c), log_id(c->type)); + c->setPort("\\A", A); + c->setParam("\\A_WIDTH", GetSize(A)); + } + + SigSpec B = c->getPort("\\B"); + int original_b_width = GetSize(B); + if (c->getParam("\\B_SIGNED").as_bool()) { + while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0) + B.remove(GetSize(B)-1, 1); + } else { + while (GetSize(B) > 0 && B[GetSize(B)-1] == State::S0) + B.remove(GetSize(B)-1, 1); + } + if (original_b_width != GetSize(B)) { + log("Removed top %d bits (of %d) from port B of cell %s.%s (%s).\n", + original_b_width-GetSize(B), original_b_width, log_id(module), log_id(c), log_id(c->type)); + c->setPort("\\B", B); + c->setParam("\\B_WIDTH", GetSize(B)); + } + } + if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) { IdString memid = c->getParam("\\MEMID").decode_string(); RTLIL::Memory *mem = module->memories.at(memid); diff --git a/passes/pmgen/.gitignore b/passes/pmgen/.gitignore index c9263057e..0ad36ea2c 100644 --- a/passes/pmgen/.gitignore +++ b/passes/pmgen/.gitignore @@ -1 +1,2 @@ /ice40_dsp_pm.h +/peepopt_pm.h diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index e0609d9ba..7911132db 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -1,8 +1,23 @@ OBJS += passes/pmgen/ice40_dsp.o +OBJS += passes/pmgen/peepopt.o + +# -------------------------------------- passes/pmgen/ice40_dsp.o: passes/pmgen/ice40_dsp_pm.h EXTRA_OBJS += passes/pmgen/ice40_dsp_pm.h .SECONDARY: passes/pmgen/ice40_dsp_pm.h passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg - $(P) mkdir -p passes/pmgen && python3 $^ $@ + $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p ice40_dsp $(filter-out $<,$^) + +# -------------------------------------- + +passes/pmgen/peepopt.o: passes/pmgen/peepopt_pm.h +EXTRA_OBJS += passes/pmgen/peepopt_pm.h +.SECONDARY: passes/pmgen/peepopt_pm.h + +PEEPOPT_PATTERN = passes/pmgen/peepopt_shiftmul.pmg +PEEPOPT_PATTERN += passes/pmgen/peepopt_muldiv.pmg + +passes/pmgen/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) + $(P) mkdir -p passes/pmgen && python3 $< -o $@ -p peepopt $(filter-out $<,$^) diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index 320e95a77..2f0b1fd5a 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -29,19 +29,25 @@ up in any future matches: pm.blacklist(some_cell); -The `.run(callback_function)` method searches for all matches and calls the -callback function for each found match: +The `.run_<pattern_name>(callback_function)` method searches for all matches +for the pattern`<pattern_name>` and calls the callback function for each found +match: - pm.run([&](){ + pm.run_foobar([&](){ log("found matching 'foo' cell: %s\n", log_id(pm.st.foo)); log(" with 'bar' cell: %s\n", log_id(pm.st.bar)); }); The `.pmg` file declares matcher state variables that are accessible via the -`.st.<state_name>` members. (The `.st` member is of type `foobar_pm::state_t`.) +`.st_<pattern_name>.<state_name>` members. (The `.st_<pattern_name>` member is +of type `foobar_pm::state_<pattern_name>_t`.) Similarly the `.pmg` file declares user data variables that become members of -`.ud`, a struct of type `foobar_pm::udata_t`. +`.ud_<pattern_name>`, a struct of type `foobar_pm::udata_<pattern_name>_t`. + +There are four versions of the `run_<pattern_name>()` method: Without callback, +callback without arguments, callback with reference to `pm`, and callback with +reference to `pm.st_<pattern_name>`. The .pmg File Format @@ -52,6 +58,12 @@ lines consist of whitespace-separated tokens. Lines in `.pmg` files starting with `//` are comments. +Declaring a pattern +------------------- + +A `.pmg` file contains one or more patterns. Each pattern starts with a line +with the `pattern` keyword followed by the name of the pattern. + Declaring state variables ------------------------- @@ -66,7 +78,7 @@ State variables are automatically managed by the generated backtracking algorith and saved and restored as needed. They are automatically initialized to the default constructed value of their type -when `.run(callback_function)` is called. +when `.run_<pattern_name>(callback_function)` is called. Declaring udata variables ------------------------- diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 3a054a463..39d033a04 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -19,47 +19,50 @@ #include "kernel/yosys.h" #include "kernel/sigtools.h" -#include "passes/pmgen/ice40_dsp_pm.h" USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +#include "passes/pmgen/ice40_dsp_pm.h" + void create_ice40_dsp(ice40_dsp_pm &pm) { + auto &st = pm.st_ice40_dsp; + #if 0 log("\n"); - log("ffA: %s\n", log_id(pm.st.ffA, "--")); - log("ffB: %s\n", log_id(pm.st.ffB, "--")); - log("mul: %s\n", log_id(pm.st.mul, "--")); - log("ffY: %s\n", log_id(pm.st.ffY, "--")); - log("addAB: %s\n", log_id(pm.st.addAB, "--")); - log("muxAB: %s\n", log_id(pm.st.muxAB, "--")); - log("ffS: %s\n", log_id(pm.st.ffS, "--")); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("mul: %s\n", log_id(st.mul, "--")); + log("ffY: %s\n", log_id(st.ffY, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); + log("muxAB: %s\n", log_id(st.muxAB, "--")); + log("ffS: %s\n", log_id(st.ffS, "--")); #endif - log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(pm.st.mul)); + log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); - if (GetSize(pm.st.sigA) > 16) { - log(" input A (%s) is too large (%d > 16).\n", log_signal(pm.st.sigA), GetSize(pm.st.sigA)); + if (GetSize(st.sigA) > 16) { + log(" input A (%s) is too large (%d > 16).\n", log_signal(st.sigA), GetSize(st.sigA)); return; } - if (GetSize(pm.st.sigB) > 16) { - log(" input B (%s) is too large (%d > 16).\n", log_signal(pm.st.sigB), GetSize(pm.st.sigB)); + if (GetSize(st.sigB) > 16) { + log(" input B (%s) is too large (%d > 16).\n", log_signal(st.sigB), GetSize(st.sigB)); return; } - if (GetSize(pm.st.sigS) > 32) { - log(" accumulator (%s) is too large (%d > 32).\n", log_signal(pm.st.sigS), GetSize(pm.st.sigS)); + if (GetSize(st.sigS) > 32) { + log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS)); return; } - if (GetSize(pm.st.sigY) > 32) { - log(" output (%s) is too large (%d > 32).\n", log_signal(pm.st.sigY), GetSize(pm.st.sigY)); + if (GetSize(st.sigY) > 32) { + log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY)); return; } - bool mul_signed = pm.st.mul->getParam("\\A_SIGNED").as_bool(); + bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool(); if (mul_signed) { log(" inference of signed iCE40 DSP arithmetic is currently not supported.\n"); @@ -69,21 +72,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log(" replacing $mul with SB_MAC16 cell.\n"); Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); - pm.module->swap_names(cell, pm.st.mul); + pm.module->swap_names(cell, st.mul); // SB_MAC16 Input Interface - SigSpec A = pm.st.sigA; + SigSpec A = st.sigA; A.extend_u0(16, mul_signed); - SigSpec B = pm.st.sigB; + SigSpec B = st.sigB; B.extend_u0(16, mul_signed); SigSpec CD; - if (pm.st.muxA) - CD = pm.st.muxA->getPort("\\B"); - if (pm.st.muxB) - CD = pm.st.muxB->getPort("\\A"); + if (st.muxA) + CD = st.muxA->getPort("\\B"); + if (st.muxB) + CD = st.muxB->getPort("\\A"); CD.extend_u0(32, mul_signed); cell->setPort("\\A", A); @@ -91,8 +94,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\C", CD.extract(0, 16)); cell->setPort("\\D", CD.extract(16, 16)); - cell->setParam("\\A_REG", pm.st.ffA ? State::S1 : State::S0); - cell->setParam("\\B_REG", pm.st.ffB ? State::S1 : State::S0); + cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0); + cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0); cell->setPort("\\AHOLD", State::S0); cell->setPort("\\BHOLD", State::S0); @@ -102,25 +105,25 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\IRSTTOP", State::S0); cell->setPort("\\IRSTBOT", State::S0); - if (pm.st.clock_vld) + if (st.clock_vld) { - cell->setPort("\\CLK", pm.st.clock); + cell->setPort("\\CLK", st.clock); cell->setPort("\\CE", State::S1); - cell->setParam("\\NEG_TRIGGER", pm.st.clock_pol ? State::S0 : State::S1); + cell->setParam("\\NEG_TRIGGER", st.clock_pol ? State::S0 : State::S1); - log(" clock: %s (%s)", log_signal(pm.st.clock), pm.st.clock_pol ? "posedge" : "negedge"); + log(" clock: %s (%s)", log_signal(st.clock), st.clock_pol ? "posedge" : "negedge"); - if (pm.st.ffA) - log(" ffA:%s", log_id(pm.st.ffA)); + if (st.ffA) + log(" ffA:%s", log_id(st.ffA)); - if (pm.st.ffB) - log(" ffB:%s", log_id(pm.st.ffB)); + if (st.ffB) + log(" ffB:%s", log_id(st.ffB)); - if (pm.st.ffY) - log(" ffY:%s", log_id(pm.st.ffY)); + if (st.ffY) + log(" ffY:%s", log_id(st.ffY)); - if (pm.st.ffS) - log(" ffS:%s", log_id(pm.st.ffS)); + if (st.ffS) + log(" ffS:%s", log_id(st.ffS)); log("\n"); } @@ -144,16 +147,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm) // SB_MAC16 Output Interface - SigSpec O = pm.st.ffS ? pm.st.sigS : pm.st.sigY; + SigSpec O = st.ffS ? st.sigS : st.sigY; if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); cell->setPort("\\O", O); - if (pm.st.addAB) { - log(" accumulator %s (%s)\n", log_id(pm.st.addAB), log_id(pm.st.addAB->type)); - cell->setPort("\\ADDSUBTOP", pm.st.addAB->type == "$add" ? State::S0 : State::S1); - cell->setPort("\\ADDSUBBOT", pm.st.addAB->type == "$add" ? State::S0 : State::S1); + if (st.addAB) { + log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1); + cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1); } else { cell->setPort("\\ADDSUBTOP", State::S0); cell->setPort("\\ADDSUBBOT", State::S0); @@ -166,10 +169,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\OHOLDBOT", State::S0); SigSpec acc_reset = State::S0; - if (pm.st.muxA) - acc_reset = pm.st.muxA->getPort("\\S"); - if (pm.st.muxB) - acc_reset = pm.module->Not(NEW_ID, pm.st.muxB->getPort("\\S")); + if (st.muxA) + acc_reset = st.muxA->getPort("\\S"); + if (st.muxB) + acc_reset = pm.module->Not(NEW_ID, st.muxB->getPort("\\S")); cell->setPort("\\OLOADTOP", acc_reset); cell->setPort("\\OLOADBOT", acc_reset); @@ -179,17 +182,17 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\C_REG", State::S0); cell->setParam("\\D_REG", State::S0); - cell->setParam("\\TOP_8x8_MULT_REG", pm.st.ffY ? State::S1 : State::S0); - cell->setParam("\\BOT_8x8_MULT_REG", pm.st.ffY ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG1", pm.st.ffY ? State::S1 : State::S0); + cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); + cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); + cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0); cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0); - cell->setParam("\\TOPOUTPUT_SELECT", Const(pm.st.ffS ? 1 : 3, 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(pm.st.ffS ? 1 : 3, 2)); + cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2)); cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2)); cell->setParam("\\BOTADDSUB_UPPERINPUT", State::S0); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); @@ -198,9 +201,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0); cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0); - pm.autoremove(pm.st.mul); - pm.autoremove(pm.st.ffY); - pm.autoremove(pm.st.ffS); + pm.autoremove(st.mul); + pm.autoremove(st.ffY); + pm.autoremove(st.ffS); } struct Ice40DspPass : public Pass { @@ -230,7 +233,7 @@ struct Ice40DspPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) - ice40_dsp_pm(module, module->selected_cells()).run(create_ice40_dsp); + ice40_dsp_pm(module, module->selected_cells()).run_ice40_dsp(create_ice40_dsp); } } Ice40DspPass; diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 96c62e313..1f3590d4e 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -1,3 +1,5 @@ +pattern ice40_dsp + state <SigBit> clock state <bool> clock_pol clock_vld state <SigSpec> sigA sigB sigY sigS diff --git a/passes/pmgen/peepopt.cc b/passes/pmgen/peepopt.cc new file mode 100644 index 000000000..e7f95cf85 --- /dev/null +++ b/passes/pmgen/peepopt.cc @@ -0,0 +1,68 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +bool did_something; + +#include "passes/pmgen/peepopt_pm.h" + +struct PeepoptPass : public Pass { + PeepoptPass() : Pass("peepopt", "collection of peephole optimizers") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" peepopt [options] [selection]\n"); + log("\n"); + log("This pass applies a collection of peephole optimizers to the current design.\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing PEEPOPT pass (run peephole optimizers).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-singleton") { + // singleton_mode = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) { + did_something = true; + while (did_something) { + did_something = false; + peepopt_pm pm(module, module->selected_cells()); + pm.run_shiftmul(); + pm.run_muldiv(); + } + } + } +} PeepoptPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/pmgen/peepopt_muldiv.pmg b/passes/pmgen/peepopt_muldiv.pmg new file mode 100644 index 000000000..06c275834 --- /dev/null +++ b/passes/pmgen/peepopt_muldiv.pmg @@ -0,0 +1,36 @@ +pattern muldiv + +state <SigSpec> t x y + +match mul + select mul->type == $mul + select GetSize(port(mul, \A)) + GetSize(port(mul, \B)) <= GetSize(port(mul, \Y)) +endmatch + +code t x y + t = port(mul, \Y); + x = port(mul, \A); + y = port(mul, \B); + branch; + std::swap(x, y); +endcode + +match div + select div->type.in($div) + index <SigSpec> port(div, \A) === t + index <SigSpec> port(div, \B) === x +endmatch + +code + SigSpec div_y = port(div, \Y); + SigSpec val_y = y; + + if (GetSize(div_y) != GetSize(val_y)) + val_y.extend_u0(GetSize(div_y), param(div, \A_SIGNED).as_bool()); + + did_something = true; + log("muldiv pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + module->connect(div_y, val_y); + autoremove(div); + reject; +endcode diff --git a/passes/pmgen/peepopt_shiftmul.pmg b/passes/pmgen/peepopt_shiftmul.pmg new file mode 100644 index 000000000..fe861b728 --- /dev/null +++ b/passes/pmgen/peepopt_shiftmul.pmg @@ -0,0 +1,87 @@ +pattern shiftmul + +state <SigSpec> shamt + +match shift + select shift->type.in($shift, $shiftx, $shr) +endmatch + +code shamt + shamt = port(shift, \B); + if (shamt.empty()) + reject; + if (shamt[GetSize(shamt)-1] == State::S0) { + do { + shamt.remove(GetSize(shamt)-1); + if (shamt.empty()) + reject; + } while (shamt[GetSize(shamt)-1] == State::S0); + } else + if (shift->type.in($shift, $shiftx) && param(shift, \B_SIGNED).as_bool()) { + reject; + } + if (GetSize(shamt) > 20) + reject; +endcode + +match mul + select mul->type.in($mul) + select port(mul, \A).is_fully_const() || port(mul, \B).is_fully_const() + index <SigSpec> port(mul, \Y) === shamt +endmatch + +code + IdString const_factor_port = port(mul, \A).is_fully_const() ? \A : \B; + IdString const_factor_signed = const_factor_port == \A ? \A_SIGNED : \B_SIGNED; + Const const_factor_cnst = port(mul, const_factor_port).as_const(); + int const_factor = const_factor_cnst.as_int(); + + if (GetSize(const_factor_cnst) == 0) + reject; + + if (const_factor_cnst.bits[GetSize(const_factor_cnst)-1] != State::S0 && + param(mul, const_factor_signed).as_bool()) + reject; + + if (GetSize(const_factor_cnst) > 20) + reject; + + if (GetSize(port(shift, \Y)) > const_factor) + reject; + + did_something = true; + log("shiftmul pattern in %s: shift=%s, mul=%s\n", log_id(module), log_id(shift), log_id(mul)); + + int new_const_factor_log2 = ceil_log2(const_factor); + int new_const_factor = 1 << new_const_factor_log2; + + SigSpec padding(State::Sx, new_const_factor-const_factor); + SigSpec old_a = port(shift, \A), new_a; + int trunc = 0; + + if (GetSize(old_a) % const_factor != 0) { + trunc = const_factor - GetSize(old_a) % const_factor; + old_a.append(SigSpec(State::Sx, trunc)); + } + + for (int i = 0; i*const_factor < GetSize(old_a); i++) { + SigSpec slice = old_a.extract(i*const_factor, const_factor); + new_a.append(slice); + new_a.append(padding); + } + + if (trunc > 0) + new_a.remove(GetSize(new_a)-trunc, trunc); + + SigSpec new_b = {port(mul, const_factor_port == \A ? \B : \A), SigSpec(State::S0, new_const_factor_log2)}; + if (param(shift, \B_SIGNED).as_bool()) + new_b.append(State::S0); + + shift->setPort(\A, new_a); + shift->setParam(\A_WIDTH, GetSize(new_a)); + shift->setPort(\B, new_b); + shift->setParam(\B_WIDTH, GetSize(new_b)); + + blacklist(shift); + reject; +endcode diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index d9747b065..81052afce 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -3,15 +3,42 @@ import re import sys import pprint +import getopt pp = pprint.PrettyPrinter(indent=4) -pmgfile = sys.argv[1] -assert pmgfile.endswith(".pmg") -prefix = pmgfile[0:-4] -prefix = prefix.split('/')[-1] -outfile = sys.argv[2] - +prefix = None +pmgfiles = list() +outfile = None +debug = False +genhdr = False + +opts, args = getopt.getopt(sys.argv[1:], "p:o:dg") + +for o, a in opts: + if o == "-p": + prefix = a + elif o == "-o": + outfile = a + elif o == "-d": + debug = True + elif o == "-g": + genhdr = True + +if outfile is None: + outfile = "/dev/stdout" + +for a in args: + assert a.endswith(".pmg") + if prefix is None and len(args) == 1: + prefix = a[0:-4] + prefix = prefix.split('/')[-1] + pmgfiles.append(a) + +assert prefix is not None + +current_pattern = None +patterns = dict() state_types = dict() udata_types = dict() blocks = list() @@ -77,7 +104,8 @@ def rewrite_cpp(s): return "".join(t) -with open(pmgfile, "r") as f: +def process_pmgfile(f): + global current_pattern while True: line = f.readline() if line == "": break @@ -87,14 +115,31 @@ with open(pmgfile, "r") as f: if len(cmd) == 0 or cmd[0].startswith("//"): continue cmd = cmd[0] + if cmd == "pattern": + if current_pattern is not None: + block = dict() + block["type"] = "final" + block["pattern"] = current_pattern + blocks.append(block) + line = line.split() + assert len(line) == 2 + assert line[1] not in patterns + current_pattern = line[1] + patterns[current_pattern] = len(blocks) + state_types[current_pattern] = dict() + udata_types[current_pattern] = dict() + continue + + assert current_pattern is not None + if cmd == "state": m = re.match(r"^state\s+<(.*?)>\s+(([A-Za-z_][A-Za-z_0-9]*\s+)*[A-Za-z_][A-Za-z_0-9]*)\s*$", line) assert m type_str = m.group(1) states_str = m.group(2) for s in re.split(r"\s+", states_str): - assert s not in state_types - state_types[s] = type_str + assert s not in state_types[current_pattern] + state_types[current_pattern][s] = type_str continue if cmd == "udata": @@ -103,19 +148,20 @@ with open(pmgfile, "r") as f: type_str = m.group(1) udatas_str = m.group(2) for s in re.split(r"\s+", udatas_str): - assert s not in udata_types - udata_types[s] = type_str + assert s not in udata_types[current_pattern] + udata_types[current_pattern][s] = type_str continue if cmd == "match": block = dict() block["type"] = "match" + block["pattern"] = current_pattern line = line.split() assert len(line) == 2 - assert line[1] not in state_types + assert line[1] not in state_types[current_pattern] block["cell"] = line[1] - state_types[line[1]] = "Cell*"; + state_types[current_pattern][line[1]] = "Cell*"; block["if"] = list() block["select"] = list() @@ -158,15 +204,18 @@ with open(pmgfile, "r") as f: assert False blocks.append(block) + continue if cmd == "code": block = dict() block["type"] = "code" + block["pattern"] = current_pattern + block["code"] = list() block["states"] = set() for s in line.split()[1:]: - assert s in state_types + assert s in state_types[current_pattern] block["states"].add(s) while True: @@ -179,18 +228,37 @@ with open(pmgfile, "r") as f: block["code"].append(rewrite_cpp(l.rstrip())) blocks.append(block) + continue -with open(outfile, "w") as f: - print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f) - print("", file=f) + assert False - print("#include \"kernel/yosys.h\"", file=f) - print("#include \"kernel/sigtools.h\"", file=f) - print("", file=f) +for fn in pmgfiles: + with open(fn, "r") as f: + process_pmgfile(f) + +if current_pattern is not None: + block = dict() + block["type"] = "final" + block["pattern"] = current_pattern + blocks.append(block) + +current_pattern = None + +if debug: + pp.pprint(blocks) - print("YOSYS_NAMESPACE_BEGIN", file=f) +with open(outfile, "w") as f: + for fn in pmgfiles: + print("// Generated by pmgen.py from {}".format(fn), file=f) print("", file=f) + if genhdr: + print("#include \"kernel/yosys.h\"", file=f) + print("#include \"kernel/sigtools.h\"", file=f) + print("", file=f) + print("YOSYS_NAMESPACE_BEGIN", file=f) + print("", file=f) + print("struct {}_pm {{".format(prefix), file=f) print(" Module *module;", file=f) print(" SigMap sigmap;", file=f) @@ -212,17 +280,19 @@ with open(outfile, "w") as f: print(" int rollback;", file=f) print("", file=f) - print(" struct state_t {", file=f) - for s, t in sorted(state_types.items()): - print(" {} {};".format(t, s), file=f) - print(" } st;", file=f) - print("", file=f) + for current_pattern in sorted(patterns.keys()): + print(" struct state_{}_t {{".format(current_pattern), file=f) + for s, t in sorted(state_types[current_pattern].items()): + print(" {} {};".format(t, s), file=f) + print(" }} st_{};".format(current_pattern), file=f) + print("", file=f) - print(" struct udata_t {", file=f) - for s, t in sorted(udata_types.items()): - print(" {} {};".format(t, s), file=f) - print(" } ud;", file=f) - print("", file=f) + print(" struct udata_{}_t {{".format(current_pattern), file=f) + for s, t in sorted(udata_types[current_pattern].items()): + print(" {} {};".format(t, s), file=f) + print(" }} ud_{};".format(current_pattern), file=f) + print("", file=f) + current_pattern = None for v, n in sorted(ids.items()): if n[0] == "\\": @@ -258,20 +328,24 @@ with open(outfile, "w") as f: print(" }", file=f) print("", file=f) - print(" void check_blacklist() {", file=f) - print(" if (!blacklist_dirty)", file=f) - print(" return;", file=f) - print(" blacklist_dirty = false;", file=f) - for index in range(len(blocks)): - block = blocks[index] - if block["type"] == "match": - print(" if (st.{} != nullptr && blacklist_cells.count(st.{})) {{".format(block["cell"], block["cell"]), file=f) - print(" rollback = {};".format(index+1), file=f) - print(" return;", file=f) - print(" }", file=f) - print(" rollback = 0;", file=f) - print(" }", file=f) - print("", file=f) + for current_pattern in sorted(patterns.keys()): + print(" void check_blacklist_{}() {{".format(current_pattern), file=f) + print(" if (!blacklist_dirty)", file=f) + print(" return;", file=f) + print(" blacklist_dirty = false;", file=f) + for index in range(len(blocks)): + block = blocks[index] + if block["pattern"] != current_pattern: + continue + if block["type"] == "match": + print(" if (st_{}.{} != nullptr && blacklist_cells.count(st_{}.{})) {{".format(current_pattern, block["cell"], current_pattern, block["cell"]), file=f) + print(" rollback = {};".format(index+1), file=f) + print(" return;", file=f) + print(" }", file=f) + print(" rollback = 0;", file=f) + print(" }", file=f) + print("", file=f) + current_pattern = None print(" SigSpec port(Cell *cell, IdString portname) {", file=f) print(" return sigmap(cell->getPort(portname));", file=f) @@ -294,11 +368,13 @@ with open(outfile, "w") as f: print(" {}_pm(Module *module, const vector<Cell*> &cells) :".format(prefix), file=f) print(" module(module), sigmap(module) {", file=f) - for s, t in sorted(udata_types.items()): - if t.endswith("*"): - print(" ud.{} = nullptr;".format(s), file=f) - else: - print(" ud.{} = {}();".format(s, t), file=f) + for current_pattern in sorted(patterns.keys()): + for s, t in sorted(udata_types[current_pattern].items()): + if t.endswith("*"): + print(" ud_{}.{} = nullptr;".format(current_pattern,s), file=f) + else: + print(" ud_{}.{} = {}();".format(current_pattern, s, t), file=f) + current_pattern = None print(" for (auto cell : module->cells()) {", file=f) print(" for (auto &conn : cell->connections())", file=f) print(" add_siguser(conn.second, cell);", file=f) @@ -328,34 +404,52 @@ with open(outfile, "w") as f: print(" }", file=f) print("", file=f) - print(" void run(std::function<void()> on_accept_f) {", file=f) - print(" on_accept = on_accept_f;", file=f) - print(" rollback = 0;", file=f) - print(" blacklist_dirty = false;", file=f) - for s, t in sorted(state_types.items()): - if t.endswith("*"): - print(" st.{} = nullptr;".format(s), file=f) - else: - print(" st.{} = {}();".format(s, t), file=f) - print(" block_0();", file=f) - print(" }", file=f) - print("", file=f) - - print(" void run(std::function<void({}_pm&)> on_accept_f) {{".format(prefix), file=f) - print(" run([&](){on_accept_f(*this);});", file=f) - print(" }", file=f) - print("", file=f) + for current_pattern in sorted(patterns.keys()): + print(" void run_{}(std::function<void()> on_accept_f) {{".format(current_pattern), file=f) + print(" on_accept = on_accept_f;", file=f) + print(" rollback = 0;", file=f) + print(" blacklist_dirty = false;", file=f) + for s, t in sorted(state_types[current_pattern].items()): + if t.endswith("*"): + print(" st_{}.{} = nullptr;".format(current_pattern, s), file=f) + else: + print(" st_{}.{} = {}();".format(current_pattern, s, t), file=f) + print(" block_{}();".format(patterns[current_pattern]), file=f) + print(" }", file=f) + print("", file=f) + print(" void run_{}(std::function<void({}_pm&)> on_accept_f) {{".format(current_pattern, prefix), file=f) + print(" run_{}([&](){{on_accept_f(*this);}});".format(current_pattern), file=f) + print(" }", file=f) + print("", file=f) + print(" void run_{}(std::function<void(state_{}_t&)> on_accept_f) {{".format(current_pattern, current_pattern), file=f) + print(" run_{}([&](){{on_accept_f(st_{});}});".format(current_pattern, current_pattern), file=f) + print(" }", file=f) + print("", file=f) + print(" void run_{}() {{".format(current_pattern), file=f) + print(" run_{}([](){{}});".format(current_pattern, current_pattern), file=f) + print(" }", file=f) + print("", file=f) + current_pattern = None for index in range(len(blocks)): block = blocks[index] print(" void block_{}() {{".format(index), file=f) + current_pattern = block["pattern"] + + if block["type"] == "final": + print(" on_accept();", file=f) + print(" check_blacklist_{}();".format(current_pattern), file=f) + print(" }", file=f) + if index+1 != len(blocks): + print("", file=f) + continue const_st = set() nonconst_st = set() restore_st = set() - for i in range(index): + for i in range(patterns[current_pattern], index): if blocks[i]["type"] == "code": for s in blocks[i]["states"]: const_st.add(s) @@ -378,27 +472,27 @@ with open(outfile, "w") as f: assert False for s in sorted(const_st): - t = state_types[s] + t = state_types[current_pattern][s] if t.endswith("*"): - print(" {} const &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) + print(" {} const &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) else: - print(" const {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) + print(" const {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) for s in sorted(nonconst_st): - t = state_types[s] - print(" {} &{} YS_ATTRIBUTE(unused) = st.{};".format(t, s, s), file=f) + t = state_types[current_pattern][s] + print(" {} &{} YS_ATTRIBUTE(unused) = st_{}.{};".format(t, s, current_pattern, s), file=f) if len(restore_st): print("", file=f) for s in sorted(restore_st): - t = state_types[s] + t = state_types[current_pattern][s] print(" {} backup_{} = {};".format(t, s, s), file=f) if block["type"] == "code": print("", file=f) print(" do {", file=f) - print("#define reject do { check_blacklist(); goto rollback_label; } while(0)", file=f) - print("#define accept do { on_accept(); check_blacklist(); if (rollback) goto rollback_label; } while(0)", file=f) + print("#define reject do {{ check_blacklist_{}(); goto rollback_label; }} while(0)".format(current_pattern), file=f) + print("#define accept do {{ on_accept(); check_blacklist_{}(); if (rollback) goto rollback_label; }} while(0)".format(current_pattern), file=f) print("#define branch do {{ block_{}(); if (rollback) goto rollback_label; }} while(0)".format(index+1), file=f) for line in block["code"]: @@ -417,11 +511,11 @@ with open(outfile, "w") as f: if len(restore_st) or len(nonconst_st): print("", file=f) for s in sorted(restore_st): - t = state_types[s] + t = state_types[current_pattern][s] print(" {} = backup_{};".format(s, s), file=f) for s in sorted(nonconst_st): if s not in restore_st: - t = state_types[s] + t = state_types[current_pattern][s] if t.endswith("*"): print(" {} = nullptr;".format(s), file=f) else: @@ -470,17 +564,12 @@ with open(outfile, "w") as f: else: assert False - + current_pattern = None print(" }", file=f) print("", file=f) - print(" void block_{}() {{".format(len(blocks)), file=f) - print(" on_accept();", file=f) - print(" check_blacklist();", file=f) - print(" }", file=f) print("};", file=f) - print("", file=f) - print("YOSYS_NAMESPACE_END", file=f) - -# pp.pprint(blocks) + if genhdr: + print("", file=f) + print("YOSYS_NAMESPACE_END", file=f) diff --git a/passes/sat/expose.cc b/passes/sat/expose.cc index 809345486..71ce1683d 100644 --- a/passes/sat/expose.cc +++ b/passes/sat/expose.cc @@ -508,7 +508,7 @@ struct ExposePass : public Pass { } for (auto &conn : module->connections_) - conn.first = out_to_in_map(sigmap(conn.first)); + conn.first = out_to_in_map(conn.first); } if (flag_cut) diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 695a03e15..cbba738f0 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -1169,6 +1169,7 @@ struct SatPass : public Pass { if (args[argidx] == "-tempinduct-def") { tempinduct = true; tempinduct_def = true; + enable_undef = true; continue; } if (args[argidx] == "-tempinduct-baseonly") { diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 547115459..5b19d84fb 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -330,20 +330,33 @@ void extract_cell(RTLIL::Cell *cell, bool keepff) std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullptr) { std::string abc_sname = abc_name.substr(1); - if (abc_sname.substr(0, 5) == "ys__n") { - bool inv = abc_sname.back() == 'v'; - if (inv) abc_sname.pop_back(); + bool isnew = false; + if (abc_sname.substr(0, 4) == "new_") + { + abc_sname.erase(0, 4); + isnew = true; + } + if (abc_sname.substr(0, 5) == "ys__n") + { abc_sname.erase(0, 5); - if (abc_sname.find_last_not_of("012345689") == std::string::npos) { + if (std::isdigit(abc_sname.at(0))) + { int sid = std::stoi(abc_sname); - for (auto sig : signal_list) { - if (sig.id == sid && sig.bit.wire != nullptr) { + size_t postfix_start = abc_sname.find_first_not_of("0123456789"); + std::string postfix = postfix_start != std::string::npos ? abc_sname.substr(postfix_start) : ""; + + if (sid < GetSize(signal_list)) + { + auto sig = signal_list.at(sid); + if (sig.bit.wire != nullptr) + { std::stringstream sstr; sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1); if (sig.bit.wire->width != 1) sstr << "[" << sig.bit.offset << "]"; - if (inv) - sstr << "_inv"; + if (isnew) + sstr << "_new"; + sstr << postfix; if (orig_wire != nullptr) *orig_wire = sig.bit.wire; return sstr.str(); diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc index 48390488e..0ad33dc0e 100644 --- a/passes/techmap/dffinit.cc +++ b/passes/techmap/dffinit.cc @@ -102,7 +102,8 @@ struct DffinitPass : public Pass { if (wire->attributes.count("\\init")) { Const value = wire->attributes.at("\\init"); for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) - init_bits[sigmap(SigBit(wire, i))] = value[i]; + if (value[i] != State::Sx) + init_bits[sigmap(SigBit(wire, i))] = value[i]; } if (wire->port_output) for (auto bit : sigmap(wire)) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a541b33be..75eedfbcc 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -178,7 +178,17 @@ struct ShregmapTechXilinx7 : ShregmapTech // Only map if $shiftx exclusively covers the shift register if (shiftx->type == "$shiftx") { - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + if (GetSize(taps) > shiftx->getParam("\\A_WIDTH").as_int()) + return false; + // Due to padding the most significant bits of A may be 1'bx, + // and if so, discount them + if (GetSize(taps) < shiftx->getParam("\\A_WIDTH").as_int()) { + const SigSpec A = shiftx->getPort("\\A"); + const int A_width = shiftx->getParam("\\A_WIDTH").as_int(); + for (int i = GetSize(taps); i < A_width; ++i) + if (A[i] != RTLIL::Sx) return false; + } + else if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } else if (shiftx->type == "$mux") { |