diff options
Diffstat (limited to 'passes')
-rw-r--r-- | passes/hierarchy/hierarchy.cc | 2 | ||||
-rw-r--r-- | passes/opt/wreduce.cc | 29 | ||||
-rw-r--r-- | passes/pmgen/Makefile.inc | 4 | ||||
-rw-r--r-- | passes/pmgen/README.md | 4 | ||||
-rw-r--r-- | passes/pmgen/pmgen.py | 12 | ||||
-rw-r--r-- | passes/sat/Makefile.inc | 1 | ||||
-rw-r--r-- | passes/sat/async2sync.cc | 53 | ||||
-rw-r--r-- | passes/sat/supercover.cc | 92 | ||||
-rw-r--r-- | passes/techmap/dfflibmap.cc | 4 | ||||
-rw-r--r-- | passes/techmap/flowmap.cc | 4 |
10 files changed, 185 insertions, 20 deletions
diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index 2d8edebb5..88c339e8c 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -910,7 +910,7 @@ struct HierarchyPass : public Pass { if (m == nullptr) continue; - if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty()) { + if (m->get_bool_attribute("\\blackbox") && !cell->parameters.empty() && m->get_bool_attribute("\\dynports")) { IdString new_m_name = m->derive(design, cell->parameters, true); if (new_m_name.empty()) continue; diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 09983bc67..1f7222e49 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -53,6 +53,7 @@ struct WreduceWorker std::set<Cell*, IdString::compare_ptr_by_name<Cell>> work_queue_cells; std::set<SigBit> work_queue_bits; pool<SigBit> keep_bits; + dict<SigBit, State> init_bits; WreduceWorker(WreduceConfig *config, Module *module) : config(config), module(module), mi(module) { } @@ -141,6 +142,7 @@ struct WreduceWorker SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); + Const initval; int width_before = GetSize(sig_q); @@ -150,16 +152,24 @@ struct WreduceWorker bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; bool sign_ext = !zero_ext; + for (int i = 0; i < GetSize(sig_q); i++) { + SigBit bit = sig_q[i]; + if (init_bits.count(bit)) + initval.bits.push_back(init_bits.at(bit)); + else + initval.bits.push_back(State::Sx); + } + for (int i = GetSize(sig_q)-1; i >= 0; i--) { - if (zero_ext && sig_d[i] == State::S0) { + if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { module->connect(sig_q[i], State::S0); sig_d.remove(i); sig_q.remove(i); continue; } - if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1]) { + if (sign_ext && i > 0 && sig_d[i] == sig_d[i-1] && initval[i] == initval[i-1]) { module->connect(sig_q[i], sig_q[i-1]); sig_d.remove(i); sig_q.remove(i); @@ -167,7 +177,7 @@ struct WreduceWorker } auto info = mi.query(sig_q[i]); - if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { + if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { sig_d.remove(i); sig_q.remove(i); zero_ext = false; @@ -183,10 +193,11 @@ struct WreduceWorker if (GetSize(sig_q) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + module->remove(cell); return; } - log("Removed top %d bits (of %d) from mux cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, + log("Removed top %d bits (of %d) from FF cell %s.%s (%s).\n", width_before - GetSize(sig_q), width_before, log_id(module), log_id(cell), log_id(cell->type)); for (auto bit : sig_d) @@ -376,10 +387,18 @@ struct WreduceWorker void run() { - for (auto w : module->wires()) + for (auto w : module->wires()) { if (w->get_bool_attribute("\\keep")) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); + if (w->attributes.count("\\init")) { + Const initval = w->attributes.at("\\init"); + SigSpec initsig = mi.sigmap(w); + int width = std::min(GetSize(initval), GetSize(initsig)); + for (int i = 0; i < width; i++) + init_bits[initsig[i]] = initval[i]; + } + } for (auto c : module->selected_cells()) work_queue_cells.insert(c); diff --git a/passes/pmgen/Makefile.inc b/passes/pmgen/Makefile.inc index 33baaca30..e0609d9ba 100644 --- a/passes/pmgen/Makefile.inc +++ b/passes/pmgen/Makefile.inc @@ -4,5 +4,5 @@ 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/ice40_dsp.pmg passes/pmgen/pmgen.py - $(P) cd passes/pmgen && python3 pmgen.py ice40_dsp +passes/pmgen/ice40_dsp_pm.h: passes/pmgen/pmgen.py passes/pmgen/ice40_dsp.pmg + $(P) mkdir -p passes/pmgen && python3 $^ $@ diff --git a/passes/pmgen/README.md b/passes/pmgen/README.md index a1007dc62..223b43059 100644 --- a/passes/pmgen/README.md +++ b/passes/pmgen/README.md @@ -16,7 +16,7 @@ API of Generated Matcher ======================== When `pmgen.py` reads a `foobar.pmg` file, it writes `foobar_pm.h` containing -a class `foobar_pm`. That class is instanciated with an RTLIL module and a +a class `foobar_pm`. That class is instantiated with an RTLIL module and a list of cells from that module: foobar_pm pm(module, module->selected_cells()); @@ -142,7 +142,7 @@ The `select` lines are evaluated once for each cell when the matcher is initialized. A `match` block will only consider cells for which all `select` expressions evaluated to `true`. Note that the state variable corresponding to the match (in the example `mul`) is the only state variable that may be used -`select` lines. +in `select` lines. Index lines are using the `index <type> expr1 === expr2` syntax. `expr1` is evaluated during matcher initialization and the same restrictions apply as for diff --git a/passes/pmgen/pmgen.py b/passes/pmgen/pmgen.py index e688a4567..d9747b065 100644 --- a/passes/pmgen/pmgen.py +++ b/passes/pmgen/pmgen.py @@ -6,7 +6,11 @@ import pprint pp = pprint.PrettyPrinter(indent=4) -prefix = sys.argv[1] +pmgfile = sys.argv[1] +assert pmgfile.endswith(".pmg") +prefix = pmgfile[0:-4] +prefix = prefix.split('/')[-1] +outfile = sys.argv[2] state_types = dict() udata_types = dict() @@ -73,7 +77,7 @@ def rewrite_cpp(s): return "".join(t) -with open("%s.pmg" % prefix, "r") as f: +with open(pmgfile, "r") as f: while True: line = f.readline() if line == "": break @@ -82,7 +86,7 @@ with open("%s.pmg" % prefix, "r") as f: cmd = line.split() if len(cmd) == 0 or cmd[0].startswith("//"): continue cmd = cmd[0] - + 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 @@ -176,7 +180,7 @@ with open("%s.pmg" % prefix, "r") as f: blocks.append(block) -with open("%s_pm.h" % prefix, "w") as f: +with open(outfile, "w") as f: print("// Generated by pmgen.py from {}.pgm".format(prefix), file=f) print("", file=f) diff --git a/passes/sat/Makefile.inc b/passes/sat/Makefile.inc index 8ab0280c0..6cb1ea644 100644 --- a/passes/sat/Makefile.inc +++ b/passes/sat/Makefile.inc @@ -8,4 +8,5 @@ OBJS += passes/sat/expose.o OBJS += passes/sat/assertpmux.o OBJS += passes/sat/clk2fflogic.o OBJS += passes/sat/async2sync.o +OBJS += passes/sat/supercover.o diff --git a/passes/sat/async2sync.cc b/passes/sat/async2sync.cc index c92db7118..d045d0dcb 100644 --- a/passes/sat/async2sync.cc +++ b/passes/sat/async2sync.cc @@ -39,7 +39,7 @@ struct Async2syncPass : public Pass { log("reset value in the next cycle regardless of the data-in value at the time of\n"); log("the clock edge.\n"); log("\n"); - log("Currently only $adff cells are supported by this pass.\n"); + log("Currently only $adff and $dffsr cells are supported by this pass.\n"); log("\n"); } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE @@ -84,7 +84,7 @@ struct Async2syncPass : public Pass { bool arst_pol = cell->parameters["\\ARST_POLARITY"].as_bool(); Const arst_val = cell->parameters["\\ARST_VALUE"]; - SigSpec sig_clk = cell->getPort("\\CLK"); + // SigSpec sig_clk = cell->getPort("\\CLK"); SigSpec sig_arst = cell->getPort("\\ARST"); SigSpec sig_d = cell->getPort("\\D"); SigSpec sig_q = cell->getPort("\\Q"); @@ -120,6 +120,55 @@ struct Async2syncPass : public Pass { cell->type = "$dff"; continue; } + + if (cell->type.in("$dffsr")) + { + // bool clk_pol = cell->parameters["\\CLK_POLARITY"].as_bool(); + bool set_pol = cell->parameters["\\SET_POLARITY"].as_bool(); + bool clr_pol = cell->parameters["\\CLR_POLARITY"].as_bool(); + + // SigSpec sig_clk = cell->getPort("\\CLK"); + SigSpec sig_set = cell->getPort("\\SET"); + SigSpec sig_clr = cell->getPort("\\CLR"); + SigSpec sig_d = cell->getPort("\\D"); + SigSpec sig_q = cell->getPort("\\Q"); + + log("Replacing %s.%s (%s): SET=%s, CLR=%s, D=%s, Q=%s\n", + log_id(module), log_id(cell), log_id(cell->type), + log_signal(sig_set), log_signal(sig_clr), log_signal(sig_d), log_signal(sig_q)); + + Const init_val; + for (int i = 0; i < GetSize(sig_q); i++) { + SigBit bit = sigmap(sig_q[i]); + init_val.bits.push_back(initbits.count(bit) ? initbits.at(bit) : State::Sx); + del_initbits.insert(bit); + } + + Wire *new_d = module->addWire(NEW_ID, GetSize(sig_d)); + Wire *new_q = module->addWire(NEW_ID, GetSize(sig_q)); + new_q->attributes["\\init"] = init_val; + + if (!set_pol) + sig_set = module->Not(NEW_ID, sig_set); + + if (clr_pol) + sig_clr = module->Not(NEW_ID, sig_clr); + + SigSpec tmp = module->Or(NEW_ID, sig_d, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, new_d); + + tmp = module->Or(NEW_ID, new_q, sig_set); + module->addAnd(NEW_ID, tmp, sig_clr, sig_q); + + cell->setPort("\\D", new_d); + cell->setPort("\\Q", new_q); + cell->unsetPort("\\SET"); + cell->unsetPort("\\CLR"); + cell->unsetParam("\\SET_POLARITY"); + cell->unsetParam("\\CLR_POLARITY"); + cell->type = "$dff"; + continue; + } } for (auto wire : module->wires()) diff --git a/passes/sat/supercover.cc b/passes/sat/supercover.cc new file mode 100644 index 000000000..ba44f02d8 --- /dev/null +++ b/passes/sat/supercover.cc @@ -0,0 +1,92 @@ +/* + * 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 + +struct SupercoverPass : public Pass { + SupercoverPass() : Pass("supercover", "add hi/lo cover cells for each wire bit") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" supercover [options] [selection]\n"); + log("\n"); + log("This command adds two cover cells for each bit of each selected wire, one\n"); + log("checking for a hi signal level and one checking for lo level.\n"); + log("\n"); + } + void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE + { + // bool flag_noinit = false; + + log_header(design, "Executing SUPERCOVER pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-noinit") { + // flag_noinit = true; + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + SigMap sigmap(module); + pool<SigBit> handled_bits; + + int cnt_wire = 0, cnt_bits = 0; + log("Adding cover cells to module %s.\n", log_id(module)); + for (auto wire : module->selected_wires()) + { + bool counted_wire = false; + std::string src = wire->get_src_attribute(); + + for (auto bit : sigmap(SigSpec(wire))) + { + if (bit.wire == nullptr) + continue; + + if (handled_bits.count(bit)) + continue; + + SigSpec inv = module->Not(NEW_ID, bit); + module->addCover(NEW_ID, bit, State::S1, src); + module->addCover(NEW_ID, inv, State::S1, src); + + handled_bits.insert(bit); + if (!counted_wire) { + counted_wire = false; + cnt_wire++; + } + cnt_bits++; + } + } + log(" added cover cells to %d wires, %d bits.\n", cnt_wire, cnt_bits); + } + } +} SupercoverPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index b0528d473..274177a68 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -660,8 +660,8 @@ struct DfflibmapPass : public Pass { map_adff_to_dff("$_DFF_PP0_", "$_DFF_P_"); map_adff_to_dff("$_DFF_PP1_", "$_DFF_P_"); - log(" final dff cell mappings:\n"); - logmap_all(); + log(" final dff cell mappings:\n"); + logmap_all(); for (auto &it : design->modules_) if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc index ddbd7bf5d..0b7931e48 100644 --- a/passes/techmap/flowmap.cc +++ b/passes/techmap/flowmap.cc @@ -132,9 +132,9 @@ static void dump_dot_graph(string filename, pool<RTLIL::SigBit> nodes, dict<RTLIL::SigBit, pool<RTLIL::SigBit>> edges, pool<RTLIL::SigBit> inputs, pool<RTLIL::SigBit> outputs, std::function<GraphStyle(RTLIL::SigBit)> node_style = - [](RTLIL::SigBit) { return GraphStyle{}; }, + [](RTLIL::SigBit) { return GraphStyle{}; }, std::function<GraphStyle(RTLIL::SigBit, RTLIL::SigBit)> edge_style = - [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, + [](RTLIL::SigBit, RTLIL::SigBit) { return GraphStyle{}; }, string name = "") { FILE *f = fopen(filename.c_str(), "w"); |