From 3aa4484a3cd9a2e82fddd499cde575eaf8c565cc Mon Sep 17 00:00:00 2001 From: Henner Zeller Date: Fri, 20 Jul 2018 23:41:18 -0700 Subject: Consistent use of 'override' for virtual methods in derived classes. o Not all derived methods were marked 'override', but it is a great feature of C++11 that we should make use of. o While at it: touched header files got a -*- c++ -*- for emacs to provide support for that language. o use YS_OVERRIDE for all override keywords (though we should probably use the plain keyword going forward now that C++11 is established) --- passes/opt/opt.cc | 4 ++-- passes/opt/opt_clean.cc | 8 ++++---- passes/opt/opt_demorgan.cc | 4 ++-- passes/opt/opt_expr.cc | 4 ++-- passes/opt/opt_merge.cc | 4 ++-- passes/opt/opt_muxtree.cc | 4 ++-- passes/opt/opt_reduce.cc | 4 ++-- passes/opt/opt_rmdff.cc | 4 ++-- passes/opt/rmports.cc | 4 ++-- passes/opt/share.cc | 4 ++-- passes/opt/wreduce.cc | 4 ++-- 11 files changed, 24 insertions(+), 24 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index 021c1a03f..a4aca2fee 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -27,7 +27,7 @@ PRIVATE_NAMESPACE_BEGIN struct OptPass : public Pass { OptPass() : Pass("opt", "perform simple optimizations") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -63,7 +63,7 @@ struct OptPass : public Pass { log("\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { std::string opt_clean_args; std::string opt_expr_args; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 25d462ada..c3b13acaf 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -442,7 +442,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool struct OptCleanPass : public Pass { OptCleanPass() : Pass("opt_clean", "remove unused cells and wires") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -459,7 +459,7 @@ struct OptCleanPass : public Pass { log(" also remove internal nets if they have a public name\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool purge_mode = false; @@ -505,7 +505,7 @@ struct OptCleanPass : public Pass { struct CleanPass : public Pass { CleanPass() : Pass("clean", "remove unused cells and wires") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -520,7 +520,7 @@ struct CleanPass : public Pass { log("in -purge mode between the commands.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool purge_mode = false; diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index f2af1cb93..1699a6454 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -169,7 +169,7 @@ void demorgan_worker( struct OptDemorganPass : public Pass { OptDemorganPass() : Pass("opt_demorgan", "Optimize reductions with DeMorgan equivalents") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -179,7 +179,7 @@ struct OptDemorganPass : public Pass { log("overall gate count of the circuit\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_DEMORGAN pass (push inverters through $reduce_* cells).\n"); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index a54a5c6b8..0ba233c62 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1470,7 +1470,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons struct OptExprPass : public Pass { OptExprPass() : Pass("opt_expr", "perform const folding and simple expression rewriting") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1504,7 +1504,7 @@ struct OptExprPass : public Pass { log(" replaced by 'a'. the -keepdc option disables all such optimizations.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool mux_undef = false; bool mux_bool = false; diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 2aeb514e4..eedf88904 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -341,7 +341,7 @@ struct OptMergeWorker struct OptMergePass : public Pass { OptMergePass() : Pass("opt_merge", "consolidate identical cells") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -357,7 +357,7 @@ struct OptMergePass : public Pass { log(" Operate on all cell types, not just built-in types.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_MERGE pass (detect identical cells).\n"); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index f5ddc2af9..87c7ce9b2 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -449,7 +449,7 @@ struct OptMuxtreeWorker struct OptMuxtreePass : public Pass { OptMuxtreePass() : Pass("opt_muxtree", "eliminate dead trees in multiplexer trees") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -462,7 +462,7 @@ struct OptMuxtreePass : public Pass { log("This pass only operates on completely selected modules without processes.\n"); log("\n"); } - virtual void execute(vector args, RTLIL::Design *design) + void execute(vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_MUXTREE pass (detect dead branches in mux trees).\n"); extra_args(args, 1, design); diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index eb9d02ad5..d99f1ca6a 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -329,7 +329,7 @@ struct OptReduceWorker struct OptReducePass : public Pass { OptReducePass() : Pass("opt_reduce", "simplify large MUXes and AND/OR gates") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -350,7 +350,7 @@ struct OptReducePass : public Pass { log(" alias for -fine\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { bool do_fine = false; diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index b5edb357b..5880254c1 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -399,7 +399,7 @@ delete_dff: struct OptRmdffPass : public Pass { OptRmdffPass() : Pass("opt_rmdff", "remove DFFs with constant inputs") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -409,7 +409,7 @@ struct OptRmdffPass : public Pass { log("a constant driver.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { int total_count = 0, total_initdrv = 0; log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n"); diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc index 756be7473..fc1596ebf 100644 --- a/passes/opt/rmports.cc +++ b/passes/opt/rmports.cc @@ -28,7 +28,7 @@ PRIVATE_NAMESPACE_BEGIN struct RmportsPassPass : public Pass { RmportsPassPass() : Pass("rmports", "remove module ports with no connections") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -39,7 +39,7 @@ struct RmportsPassPass : public Pass { log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing RMPORTS pass (remove ports with no connections).\n"); diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 22914eaa7..b80280829 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -1421,7 +1421,7 @@ struct ShareWorker struct SharePass : public Pass { SharePass() : Pass("share", "perform sat-based resource sharing") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -1453,7 +1453,7 @@ struct SharePass : public Pass { log(" Only perform the first N merges, then stop. This is useful for debugging.\n"); log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { ShareWorkerConfig config; diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 07503fbb3..0164f58d6 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -353,7 +353,7 @@ struct WreduceWorker struct WreducePass : public Pass { WreducePass() : Pass("wreduce", "reduce the word size of operations if possible") { } - virtual void help() + void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); @@ -373,7 +373,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); } - virtual void execute(std::vector args, Design *design) + void execute(std::vector args, Design *design) YS_OVERRIDE { WreduceConfig config; bool opt_memx = false; -- cgit v1.2.3 From ab97eddee9b0ea0a772660731fe4c3270d2564e5 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 20 Nov 2018 17:56:47 +0100 Subject: Add iteration limit to "opt_muxtree" Signed-off-by: Clifford Wolf --- passes/opt/opt_muxtree.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 87c7ce9b2..375697dc8 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -36,6 +36,7 @@ struct OptMuxtreeWorker RTLIL::Module *module; SigMap assign_map; int removed_count; + int glob_abort_cnt = 100000; struct bitinfo_t { bool seen_non_mux; @@ -293,6 +294,9 @@ struct OptMuxtreeWorker void eval_mux_port(knowledge_t &knowledge, int mux_idx, int port_idx, bool do_replace_known, bool do_enable_ports, int abort_count) { + if (glob_abort_cnt == 0) + return; + muxinfo_t &muxinfo = mux2info[mux_idx]; if (do_enable_ports) @@ -315,7 +319,7 @@ struct OptMuxtreeWorker knowledge.visited_muxes[m] = true; parent_muxes.push_back(m); } - for (int m : parent_muxes) + for (int m : parent_muxes) { if (root_enable_muxes.at(m)) continue; else if (root_muxes.at(m)) { @@ -327,6 +331,9 @@ struct OptMuxtreeWorker eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1); } else eval_mux(knowledge, m, do_replace_known, do_enable_ports, abort_count); + if (glob_abort_cnt == 0) + return; + } for (int m : parent_muxes) knowledge.visited_muxes[m] = false; @@ -390,6 +397,12 @@ struct OptMuxtreeWorker void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports, int abort_count) { + if (glob_abort_cnt == 0) { + log(" Giving up (too many iterations)\n"); + return; + } + glob_abort_cnt--; + muxinfo_t &muxinfo = mux2info[mux_idx]; // set input ports to constants if we find known active or inactive signals @@ -433,6 +446,9 @@ struct OptMuxtreeWorker if (knowledge.known_inactive.at(portinfo.ctrl_sig)) continue; eval_mux_port(knowledge, mux_idx, port_idx, do_replace_known, do_enable_ports, abort_count); + + if (glob_abort_cnt == 0) + return; } } -- cgit v1.2.3 From 9e072ec21f9985126e1cfeb04fa7f2bc963790b3 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 00:23:22 +0000 Subject: opt_lut: new pass, to combine LUTs for tighter packing. --- passes/opt/Makefile.inc | 1 + passes/opt/opt_lut.cpp | 274 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 passes/opt/opt_lut.cpp (limited to 'passes/opt') diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 0d01e9d35..0f596b1f4 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -6,6 +6,7 @@ OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_rmdff.o OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_expr.o +OBJS += passes/opt/opt_lut.o ifneq ($(SMALL),1) OBJS += passes/opt/share.o diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp new file mode 100644 index 000000000..4d6d491f7 --- /dev/null +++ b/passes/opt/opt_lut.cpp @@ -0,0 +1,274 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2018 whitequark + * + * 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" +#include "kernel/modtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +static bool evaluate_lut(SigMap &sigmap, RTLIL::Cell *lut, dict inputs) +{ + SigSpec lut_input = sigmap(lut->getPort("\\A")); + int lut_width = lut->getParam("\\WIDTH").as_int(); + Const lut_table = lut->getParam("\\LUT"); + int lut_index = 0; + + for (int i = 0; i < lut_width; i++) + { + SigBit input = sigmap(lut_input[i]); + if (inputs.count(input)) + { + lut_index |= inputs[input] << i; + } + else + { + lut_index |= SigSpec(lut_input[i]).as_bool() << i; + } + } + + return lut_table.extract(lut_index).as_int(); +} + +static void run_lut_opts(Module *module) +{ + ModIndex index(module); + SigMap sigmap(module); + + log("Discovering LUTs.\n"); + + pool luts; + dict luts_arity; + for (auto cell : module->selected_cells()) + { + if (cell->type == "$lut") + { + int lut_width = cell->getParam("\\WIDTH").as_int(); + SigSpec lut_input = cell->getPort("\\A"); + int lut_arity = 0; + + for (auto &bit : lut_input) + { + if (bit.wire) + lut_arity++; + } + + log("Found $lut cell %s.%s with WIDTH=%d implementing %d-LUT.\n", log_id(module), log_id(cell), lut_width, lut_arity); + luts.insert(cell); + luts_arity[cell] = lut_arity; + } + } + + log("\n"); + log("Combining LUTs.\n"); + + pool worklist = luts; + while (worklist.size()) + { + auto lutA = worklist.pop(); + SigSpec lutA_input = sigmap(lutA->getPort("\\A")); + SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); + int lutA_width = lutA->getParam("\\WIDTH").as_int(); + int lutA_arity = luts_arity[lutA]; + + auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); + if (lutA_output_ports.size() != 2) + continue; + + for (auto port : lutA_output_ports) + { + if (port.cell == lutA) + continue; + + if (luts.count(port.cell)) + { + auto lutB = port.cell; + SigSpec lutB_input = sigmap(lutB->getPort("\\A")); + SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); + int lutB_width = lutB->getParam("\\WIDTH").as_int(); + int lutB_arity = luts_arity[lutB]; + + log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + + pool lutA_inputs; + pool lutB_inputs; + for (auto &bit : lutA_input) + { + if (bit.wire) + lutA_inputs.insert(sigmap(bit)); + } + for (auto &bit : lutB_input) + { + if(bit.wire) + lutB_inputs.insert(sigmap(bit)); + } + + pool common_inputs; + for (auto &bit : lutA_inputs) + { + if (lutB_inputs.count(bit)) + common_inputs.insert(bit); + } + + int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); + log(" Cell A is a %d-LUT. Cell B is a %d-LUT. Cells share %zu input(s) and can be merged into one %d-LUT.\n", lutA_arity, lutB_arity, common_inputs.size(), lutM_arity); + + int combine = -1; + if (combine == -1) + { + if (lutM_arity > lutA_width) + { + log(" Not combining LUTs into cell A (combined LUT too wide).\n"); + } + else if (lutB->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); + } + else combine = 0; + } + if (combine == -1) + { + if (lutM_arity > lutB_width) + { + log(" Not combining LUTs into cell B (combined LUT too wide).\n"); + } + else if (lutA->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + } + else combine = 1; + } + + RTLIL::Cell *lutM, *lutR; + pool lutM_inputs, lutR_inputs; + if (combine == 0) + { + log(" Combining LUTs into cell A.\n"); + lutM = lutA; + lutM_inputs = lutA_inputs; + lutR = lutB; + lutR_inputs = lutB_inputs; + } + else if (combine == 1) + { + log(" Combining LUTs into cell B.\n"); + lutM = lutB; + lutM_inputs = lutB_inputs; + lutR = lutA; + lutR_inputs = lutA_inputs; + } + else + { + log(" Cannot combine LUTs.\n"); + continue; + } + + pool lutR_unique; + for (auto &bit : lutR_inputs) + { + if (!common_inputs.count(bit) && bit != lutA_output) + lutR_unique.insert(bit); + } + + int lutM_width = lutM->getParam("\\WIDTH").as_int(); + SigSpec lutM_input = sigmap(lutM->getPort("\\A")); + std::vector lutM_new_inputs; + for (int i = 0; i < lutM_width; i++) + { + if ((!lutM_input[i].wire || sigmap(lutM_input[i]) == lutA_output) && lutR_unique.size()) + { + SigBit new_input = lutR_unique.pop(); + log(" Connecting input %d as %s.\n", i, log_signal(new_input)); + lutM_new_inputs.push_back(new_input); + } + else if (sigmap(lutM_input[i]) == lutA_output) + { + log(" Disconnecting input %d.\n", i); + lutM_new_inputs.push_back(SigBit()); + } + else + { + log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); + lutM_new_inputs.push_back(lutM_input[i]); + } + } + log_assert(lutR_unique.size() == 0); + + RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width); + for (int eval = 0; eval < 1 << lutM_width; eval++) + { + dict eval_inputs; + for (size_t i = 0; i < lutM_new_inputs.size(); i++) + { + eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; + } + eval_inputs[lutA_output] = evaluate_lut(sigmap, lutA, eval_inputs); + lutM_new_table[eval] = (RTLIL::State) evaluate_lut(sigmap, lutB, eval_inputs); + } + + log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); + log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); + + lutM->setParam("\\LUT", lutM_new_table); + lutM->setPort("\\A", lutM_new_inputs); + lutM->setPort("\\Y", lutB_output); + + luts_arity[lutM] = lutM_arity; + luts.erase(lutR); + luts_arity.erase(lutR); + lutR->module->remove(lutR); + + worklist.insert(lutM); + worklist.erase(lutR); + } + } + } +} + +struct OptLutPass : public Pass { + OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } + void help() YS_OVERRIDE + { + log("\n"); + log(" opt_lut [options] [selection]\n"); + log("\n"); + log("This pass combines cascaded $lut cells with unused inputs.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + // if (args[argidx] == "-???") { + // continue; + // } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + run_lut_opts(module); + } +} OptLutPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From e54c7e951c5659ae6ebb4dfe9c42adfe0498dc4b Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 12:26:41 +0000 Subject: opt_lut: refactor to use a worker. NFC. --- passes/opt/opt_lut.cpp | 347 +++++++++++++++++++++++++------------------------ 1 file changed, 177 insertions(+), 170 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp index 4d6d491f7..f33b23cf4 100644 --- a/passes/opt/opt_lut.cpp +++ b/passes/opt/opt_lut.cpp @@ -24,223 +24,228 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -static bool evaluate_lut(SigMap &sigmap, RTLIL::Cell *lut, dict inputs) +struct OptLutWorker { - SigSpec lut_input = sigmap(lut->getPort("\\A")); - int lut_width = lut->getParam("\\WIDTH").as_int(); - Const lut_table = lut->getParam("\\LUT"); - int lut_index = 0; + RTLIL::Module *module; + ModIndex index; + SigMap sigmap; - for (int i = 0; i < lut_width; i++) + bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { - SigBit input = sigmap(lut_input[i]); - if (inputs.count(input)) - { - lut_index |= inputs[input] << i; - } - else - { - lut_index |= SigSpec(lut_input[i]).as_bool() << i; - } - } - - return lut_table.extract(lut_index).as_int(); -} - -static void run_lut_opts(Module *module) -{ - ModIndex index(module); - SigMap sigmap(module); - - log("Discovering LUTs.\n"); + SigSpec lut_input = sigmap(lut->getPort("\\A")); + int lut_width = lut->getParam("\\WIDTH").as_int(); + Const lut_table = lut->getParam("\\LUT"); + int lut_index = 0; - pool luts; - dict luts_arity; - for (auto cell : module->selected_cells()) - { - if (cell->type == "$lut") + for (int i = 0; i < lut_width; i++) { - int lut_width = cell->getParam("\\WIDTH").as_int(); - SigSpec lut_input = cell->getPort("\\A"); - int lut_arity = 0; - - for (auto &bit : lut_input) + SigBit input = sigmap(lut_input[i]); + if (inputs.count(input)) { - if (bit.wire) - lut_arity++; + lut_index |= inputs[input] << i; + } + else + { + lut_index |= SigSpec(lut_input[i]).as_bool() << i; } - - log("Found $lut cell %s.%s with WIDTH=%d implementing %d-LUT.\n", log_id(module), log_id(cell), lut_width, lut_arity); - luts.insert(cell); - luts_arity[cell] = lut_arity; } - } - log("\n"); - log("Combining LUTs.\n"); + return lut_table.extract(lut_index).as_int(); + } - pool worklist = luts; - while (worklist.size()) + OptLutWorker(RTLIL::Module *module) : + module(module), index(module), sigmap(module) { - auto lutA = worklist.pop(); - SigSpec lutA_input = sigmap(lutA->getPort("\\A")); - SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); - int lutA_width = lutA->getParam("\\WIDTH").as_int(); - int lutA_arity = luts_arity[lutA]; - - auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); - if (lutA_output_ports.size() != 2) - continue; + pool luts; + dict luts_arity; - for (auto port : lutA_output_ports) + log("Discovering LUTs.\n"); + for (auto cell : module->selected_cells()) { - if (port.cell == lutA) - continue; - - if (luts.count(port.cell)) + if (cell->type == "$lut") { - auto lutB = port.cell; - SigSpec lutB_input = sigmap(lutB->getPort("\\A")); - SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); - int lutB_width = lutB->getParam("\\WIDTH").as_int(); - int lutB_arity = luts_arity[lutB]; - - log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + int lut_width = cell->getParam("\\WIDTH").as_int(); + SigSpec lut_input = cell->getPort("\\A"); + int lut_arity = 0; - pool lutA_inputs; - pool lutB_inputs; - for (auto &bit : lutA_input) + for (auto &bit : lut_input) { if (bit.wire) - lutA_inputs.insert(sigmap(bit)); - } - for (auto &bit : lutB_input) - { - if(bit.wire) - lutB_inputs.insert(sigmap(bit)); + lut_arity++; } - pool common_inputs; - for (auto &bit : lutA_inputs) - { - if (lutB_inputs.count(bit)) - common_inputs.insert(bit); - } + log("Found $lut cell %s.%s with WIDTH=%d implementing %d-LUT.\n", log_id(module), log_id(cell), lut_width, lut_arity); + luts.insert(cell); + luts_arity[cell] = lut_arity; + } + } - int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); - log(" Cell A is a %d-LUT. Cell B is a %d-LUT. Cells share %zu input(s) and can be merged into one %d-LUT.\n", lutA_arity, lutB_arity, common_inputs.size(), lutM_arity); + log("\n"); + log("Combining LUTs.\n"); + + pool worklist = luts; + while (worklist.size()) + { + auto lutA = worklist.pop(); + SigSpec lutA_input = sigmap(lutA->getPort("\\A")); + SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); + int lutA_width = lutA->getParam("\\WIDTH").as_int(); + int lutA_arity = luts_arity[lutA]; + + auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); + if (lutA_output_ports.size() != 2) + continue; - int combine = -1; - if (combine == -1) + for (auto port : lutA_output_ports) + { + if (port.cell == lutA) + continue; + + if (luts.count(port.cell)) { - if (lutM_arity > lutA_width) - { - log(" Not combining LUTs into cell A (combined LUT too wide).\n"); - } - else if (lutB->get_bool_attribute("\\lut_keep")) + auto lutB = port.cell; + SigSpec lutB_input = sigmap(lutB->getPort("\\A")); + SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); + int lutB_width = lutB->getParam("\\WIDTH").as_int(); + int lutB_arity = luts_arity[lutB]; + + log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + + pool lutA_inputs; + pool lutB_inputs; + for (auto &bit : lutA_input) { - log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); + if (bit.wire) + lutA_inputs.insert(sigmap(bit)); } - else combine = 0; - } - if (combine == -1) - { - if (lutM_arity > lutB_width) + for (auto &bit : lutB_input) { - log(" Not combining LUTs into cell B (combined LUT too wide).\n"); + if(bit.wire) + lutB_inputs.insert(sigmap(bit)); } - else if (lutA->get_bool_attribute("\\lut_keep")) + + pool common_inputs; + for (auto &bit : lutA_inputs) { - log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + if (lutB_inputs.count(bit)) + common_inputs.insert(bit); } - else combine = 1; - } - RTLIL::Cell *lutM, *lutR; - pool lutM_inputs, lutR_inputs; - if (combine == 0) - { - log(" Combining LUTs into cell A.\n"); - lutM = lutA; - lutM_inputs = lutA_inputs; - lutR = lutB; - lutR_inputs = lutB_inputs; - } - else if (combine == 1) - { - log(" Combining LUTs into cell B.\n"); - lutM = lutB; - lutM_inputs = lutB_inputs; - lutR = lutA; - lutR_inputs = lutA_inputs; - } - else - { - log(" Cannot combine LUTs.\n"); - continue; - } + int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); + log(" Cell A is a %d-LUT. Cell B is a %d-LUT. Cells share %zu input(s) and can be merged into one %d-LUT.\n", lutA_arity, lutB_arity, common_inputs.size(), lutM_arity); - pool lutR_unique; - for (auto &bit : lutR_inputs) - { - if (!common_inputs.count(bit) && bit != lutA_output) - lutR_unique.insert(bit); - } + int combine = -1; + if (combine == -1) + { + if (lutM_arity > lutA_width) + { + log(" Not combining LUTs into cell A (combined LUT too wide).\n"); + } + else if (lutB->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); + } + else combine = 0; + } + if (combine == -1) + { + if (lutM_arity > lutB_width) + { + log(" Not combining LUTs into cell B (combined LUT too wide).\n"); + } + else if (lutA->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + } + else combine = 1; + } - int lutM_width = lutM->getParam("\\WIDTH").as_int(); - SigSpec lutM_input = sigmap(lutM->getPort("\\A")); - std::vector lutM_new_inputs; - for (int i = 0; i < lutM_width; i++) - { - if ((!lutM_input[i].wire || sigmap(lutM_input[i]) == lutA_output) && lutR_unique.size()) + RTLIL::Cell *lutM, *lutR; + pool lutM_inputs, lutR_inputs; + if (combine == 0) { - SigBit new_input = lutR_unique.pop(); - log(" Connecting input %d as %s.\n", i, log_signal(new_input)); - lutM_new_inputs.push_back(new_input); + log(" Combining LUTs into cell A.\n"); + lutM = lutA; + lutM_inputs = lutA_inputs; + lutR = lutB; + lutR_inputs = lutB_inputs; } - else if (sigmap(lutM_input[i]) == lutA_output) + else if (combine == 1) { - log(" Disconnecting input %d.\n", i); - lutM_new_inputs.push_back(SigBit()); + log(" Combining LUTs into cell B.\n"); + lutM = lutB; + lutM_inputs = lutB_inputs; + lutR = lutA; + lutR_inputs = lutA_inputs; } else { - log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); - lutM_new_inputs.push_back(lutM_input[i]); + log(" Cannot combine LUTs.\n"); + continue; } - } - log_assert(lutR_unique.size() == 0); - RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width); - for (int eval = 0; eval < 1 << lutM_width; eval++) - { - dict eval_inputs; - for (size_t i = 0; i < lutM_new_inputs.size(); i++) + pool lutR_unique; + for (auto &bit : lutR_inputs) { - eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; + if (!common_inputs.count(bit) && bit != lutA_output) + lutR_unique.insert(bit); + } + + int lutM_width = lutM->getParam("\\WIDTH").as_int(); + SigSpec lutM_input = sigmap(lutM->getPort("\\A")); + std::vector lutM_new_inputs; + for (int i = 0; i < lutM_width; i++) + { + if ((!lutM_input[i].wire || sigmap(lutM_input[i]) == lutA_output) && lutR_unique.size()) + { + SigBit new_input = lutR_unique.pop(); + log(" Connecting input %d as %s.\n", i, log_signal(new_input)); + lutM_new_inputs.push_back(new_input); + } + else if (sigmap(lutM_input[i]) == lutA_output) + { + log(" Disconnecting input %d.\n", i); + lutM_new_inputs.push_back(SigBit()); + } + else + { + log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); + lutM_new_inputs.push_back(lutM_input[i]); + } + } + log_assert(lutR_unique.size() == 0); + + RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width); + for (int eval = 0; eval < 1 << lutM_width; eval++) + { + dict eval_inputs; + for (size_t i = 0; i < lutM_new_inputs.size(); i++) + { + eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; + } + eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); + lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - eval_inputs[lutA_output] = evaluate_lut(sigmap, lutA, eval_inputs); - lutM_new_table[eval] = (RTLIL::State) evaluate_lut(sigmap, lutB, eval_inputs); - } - log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); - log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); + log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); + log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); - lutM->setParam("\\LUT", lutM_new_table); - lutM->setPort("\\A", lutM_new_inputs); - lutM->setPort("\\Y", lutB_output); + lutM->setParam("\\LUT", lutM_new_table); + lutM->setPort("\\A", lutM_new_inputs); + lutM->setPort("\\Y", lutB_output); - luts_arity[lutM] = lutM_arity; - luts.erase(lutR); - luts_arity.erase(lutR); - lutR->module->remove(lutR); + luts_arity[lutM] = lutM_arity; + luts.erase(lutR); + luts_arity.erase(lutR); + lutR->module->remove(lutR); - worklist.insert(lutM); - worklist.erase(lutR); + worklist.insert(lutM); + worklist.erase(lutR); + } } } } -} +}; struct OptLutPass : public Pass { OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } @@ -267,7 +272,9 @@ struct OptLutPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) - run_lut_opts(module); + { + OptLutWorker worker(module); + } } } OptLutPass; -- cgit v1.2.3 From 59eea0183ffaa453f77c6d439a9df8c1087c0fe0 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 12:35:27 +0000 Subject: opt_lut: collect and display statistics. --- passes/opt/opt_lut.cpp | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp index f33b23cf4..b043f6c10 100644 --- a/passes/opt/opt_lut.cpp +++ b/passes/opt/opt_lut.cpp @@ -30,6 +30,11 @@ struct OptLutWorker ModIndex index; SigMap sigmap; + pool luts; + dict luts_arity; + + int combined_count = 0; + bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { SigSpec lut_input = sigmap(lut->getPort("\\A")); @@ -53,12 +58,27 @@ struct OptLutWorker return lut_table.extract(lut_index).as_int(); } + void show_stats_by_arity() + { + dict arity_counts; + int max_arity = 0; + for (auto lut_arity : luts_arity) + { + max_arity = max(max_arity, lut_arity.second); + arity_counts[lut_arity.second]++; + } + + log("Number of LUTs: %6zu\n", luts.size()); + for (int arity = 1; arity <= max_arity; arity++) + { + if (arity_counts[arity]) + log(" %d-LUT: %13d\n", arity, arity_counts[arity]); + } + } + OptLutWorker(RTLIL::Module *module) : module(module), index(module), sigmap(module) { - pool luts; - dict luts_arity; - log("Discovering LUTs.\n"); for (auto cell : module->selected_cells()) { @@ -79,10 +99,10 @@ struct OptLutWorker luts_arity[cell] = lut_arity; } } + show_stats_by_arity(); log("\n"); log("Combining LUTs.\n"); - pool worklist = luts; while (worklist.size()) { @@ -241,9 +261,12 @@ struct OptLutWorker worklist.insert(lutM); worklist.erase(lutR); + + combined_count++; } } } + show_stats_by_arity(); } }; @@ -271,10 +294,16 @@ struct OptLutPass : public Pass { } extra_args(args, argidx, design); + int total_count = 0; for (auto module : design->selected_modules()) { OptLutWorker worker(module); + total_count += worker.combined_count; } + if (total_count) + design->scratchpad_set_bool("opt.did_something", true); + log("\n"); + log("Combined %d LUTs.\n", total_count); } } OptLutPass; -- cgit v1.2.3 From e6034840702effa2ff0c2eee0cca046b5c097e86 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 13:14:44 +0000 Subject: opt_lut: always prefer to eliminate 1-LUTs. These are always either buffers or inverters, and keeping the larger LUT preserves more source-level information about the design. --- passes/opt/opt_lut.cpp | 60 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 19 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp index b043f6c10..0eb6b13e5 100644 --- a/passes/opt/opt_lut.cpp +++ b/passes/opt/opt_lut.cpp @@ -154,35 +154,57 @@ struct OptLutWorker int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); log(" Cell A is a %d-LUT. Cell B is a %d-LUT. Cells share %zu input(s) and can be merged into one %d-LUT.\n", lutA_arity, lutB_arity, common_inputs.size(), lutM_arity); - int combine = -1; - if (combine == -1) + const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; + int combine_mask = 0; + if (lutM_arity > lutA_width) { - if (lutM_arity > lutA_width) - { - log(" Not combining LUTs into cell A (combined LUT too wide).\n"); - } - else if (lutB->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); - } - else combine = 0; + log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); + } + else if (lutB->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); + } + else + { + combine_mask |= COMBINE_A; + } + if (lutM_arity > lutB_width) + { + log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); + } + else if (lutA->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + } + else + { + combine_mask |= COMBINE_B; } - if (combine == -1) + + int combine = combine_mask; + if (combine == COMBINE_EITHER) { - if (lutM_arity > lutB_width) + log(" Can combine into either cell.\n"); + if (lutA_arity == 1) { - log(" Not combining LUTs into cell B (combined LUT too wide).\n"); + log(" Cell A is a buffer or inverter, combining into cell B.\n"); + combine = COMBINE_B; } - else if (lutA->get_bool_attribute("\\lut_keep")) + else if (lutB_arity == 1) + { + log(" Cell B is a buffer or inverter, combining into cell A.\n"); + combine = COMBINE_A; + } + else { - log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + log(" Arbitrarily combining into cell A.\n"); + combine = COMBINE_A; } - else combine = 1; } RTLIL::Cell *lutM, *lutR; pool lutM_inputs, lutR_inputs; - if (combine == 0) + if (combine == COMBINE_A) { log(" Combining LUTs into cell A.\n"); lutM = lutA; @@ -190,7 +212,7 @@ struct OptLutWorker lutR = lutB; lutR_inputs = lutB_inputs; } - else if (combine == 1) + else if (combine == COMBINE_B) { log(" Combining LUTs into cell B.\n"); lutM = lutB; -- cgit v1.2.3 From 45cb6200af13469724de42656f2c1f0f61c8766a Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 15:26:40 +0000 Subject: opt_lut: add -dlogic, to avoid disturbing logic such as carry chains. --- passes/opt/opt_lut.cpp | 180 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 163 insertions(+), 17 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp index 0eb6b13e5..befe346a3 100644 --- a/passes/opt/opt_lut.cpp +++ b/passes/opt/opt_lut.cpp @@ -26,12 +26,15 @@ PRIVATE_NAMESPACE_BEGIN struct OptLutWorker { + dict> &dlogic; RTLIL::Module *module; ModIndex index; SigMap sigmap; pool luts; dict luts_arity; + dict> luts_dlogics; + dict> luts_dlogic_inputs; int combined_count = 0; @@ -61,23 +64,37 @@ struct OptLutWorker void show_stats_by_arity() { dict arity_counts; + dict dlogic_counts; int max_arity = 0; + for (auto lut_arity : luts_arity) { max_arity = max(max_arity, lut_arity.second); arity_counts[lut_arity.second]++; } - log("Number of LUTs: %6zu\n", luts.size()); + for (auto &lut_dlogics : luts_dlogics) + { + for (auto &lut_dlogic : lut_dlogics.second) + { + dlogic_counts[lut_dlogic->type]++; + } + } + + log("Number of LUTs: %8zu\n", luts.size()); for (int arity = 1; arity <= max_arity; arity++) { if (arity_counts[arity]) - log(" %d-LUT: %13d\n", arity, arity_counts[arity]); + log(" %d-LUT %16d\n", arity, arity_counts[arity]); + } + for (auto &dlogic_count : dlogic_counts) + { + log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second); } } - OptLutWorker(RTLIL::Module *module) : - module(module), index(module), sigmap(module) + OptLutWorker(dict> &dlogic, RTLIL::Module *module) : + dlogic(dlogic), module(module), index(module), sigmap(module) { log("Discovering LUTs.\n"); for (auto cell : module->selected_cells()) @@ -88,15 +105,84 @@ struct OptLutWorker SigSpec lut_input = cell->getPort("\\A"); int lut_arity = 0; - for (auto &bit : lut_input) + log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + luts.insert(cell); + + // First, find all dedicated logic we're connected to. This results in an overapproximation + // of such connections. + pool lut_all_dlogics; + for (int i = 0; i < lut_width; i++) + { + SigBit bit = lut_input[i]; + for (auto &port : index.query_ports(bit)) + { + if (dlogic.count(port.cell->type)) + { + auto &dlogic_map = dlogic[port.cell->type]; + if (dlogic_map.count(i)) + { + if (port.port == dlogic_map[i]) + { + lut_all_dlogics.insert(port.cell); + } + } + } + } + } + + // Second, make sure that the connection to dedicated logic is legal. If it is not legal, + // it means one of the two things: + // * The connection is spurious. I.e. this is dedicated logic that will be packed + // with some other LUT, and it just happens to be conected to this LUT as well. + // * The connection is illegal. + // In either of these cases, we don't need to concern ourselves with preserving the connection + // between this LUT and this dedicated logic cell. + pool lut_legal_dlogics; + pool lut_dlogic_inputs; + for (auto lut_dlogic : lut_all_dlogics) + { + auto &dlogic_map = dlogic[lut_dlogic->type]; + bool legal = true; + for (auto &dlogic_conn : dlogic_map) + { + if (lut_width <= dlogic_conn.first) + { + log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log(" LUT input A[%d] not present.\n", dlogic_conn.first); + legal = false; + break; + } + if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second))) + { + log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); + legal = false; + break; + } + } + + if (legal) + { + log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + lut_legal_dlogics.insert(lut_dlogic); + for (auto &dlogic_conn : dlogic_map) + lut_dlogic_inputs.insert(dlogic_conn.first); + } + } + + // Third, determine LUT arity. An n-wide LUT that has k constant inputs and m inputs shared with dedicated + // logic implements an (n-k-m)-ary function. + for (int i = 0; i < lut_width; i++) { - if (bit.wire) + SigBit bit = lut_input[i]; + if (bit.wire || lut_dlogic_inputs.count(i)) lut_arity++; } - log("Found $lut cell %s.%s with WIDTH=%d implementing %d-LUT.\n", log_id(module), log_id(cell), lut_width, lut_arity); - luts.insert(cell); + log(" Cell implements a %d-LUT.\n", lut_arity); luts_arity[cell] = lut_arity; + luts_dlogics[cell] = lut_legal_dlogics; + luts_dlogic_inputs[cell] = lut_dlogic_inputs; } } show_stats_by_arity(); @@ -111,12 +197,13 @@ struct OptLutWorker SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); int lutA_width = lutA->getParam("\\WIDTH").as_int(); int lutA_arity = luts_arity[lutA]; + pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); if (lutA_output_ports.size() != 2) continue; - for (auto port : lutA_output_ports) + for (auto &port : lutA_output_ports) { if (port.cell == lutA) continue; @@ -128,6 +215,7 @@ struct OptLutWorker SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); int lutB_width = lutB->getParam("\\WIDTH").as_int(); int lutB_arity = luts_arity[lutB]; + pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); @@ -140,7 +228,7 @@ struct OptLutWorker } for (auto &bit : lutB_input) { - if(bit.wire) + if (bit.wire) lutB_inputs.insert(sigmap(bit)); } @@ -152,7 +240,15 @@ struct OptLutWorker } int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); - log(" Cell A is a %d-LUT. Cell B is a %d-LUT. Cells share %zu input(s) and can be merged into one %d-LUT.\n", lutA_arity, lutB_arity, common_inputs.size(), lutM_arity); + if (lutA_dlogic_inputs.size()) + log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); + else + log(" Cell A is a %d-LUT. ", lutA_arity); + if (lutB_dlogic_inputs.size()) + log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); + else + log("Cell B is a %d-LUT.\n", lutB_arity); + log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; int combine_mask = 0; @@ -160,6 +256,10 @@ struct OptLutWorker { log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); } + else if (lutB_dlogic_inputs.size() > 0) + { + log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); + } else if (lutB->get_bool_attribute("\\lut_keep")) { log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); @@ -172,6 +272,10 @@ struct OptLutWorker { log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); } + else if (lutA_dlogic_inputs.size() > 0) + { + log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); + } else if (lutA->get_bool_attribute("\\lut_keep")) { log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); @@ -204,11 +308,13 @@ struct OptLutWorker RTLIL::Cell *lutM, *lutR; pool lutM_inputs, lutR_inputs; + pool lutM_dlogic_inputs; if (combine == COMBINE_A) { log(" Combining LUTs into cell A.\n"); lutM = lutA; lutM_inputs = lutA_inputs; + lutM_dlogic_inputs = lutA_dlogic_inputs; lutR = lutB; lutR_inputs = lutB_inputs; } @@ -217,6 +323,7 @@ struct OptLutWorker log(" Combining LUTs into cell B.\n"); lutM = lutB; lutM_inputs = lutB_inputs; + lutM_dlogic_inputs = lutB_dlogic_inputs; lutR = lutA; lutR_inputs = lutA_inputs; } @@ -238,7 +345,13 @@ struct OptLutWorker std::vector lutM_new_inputs; for (int i = 0; i < lutM_width; i++) { - if ((!lutM_input[i].wire || sigmap(lutM_input[i]) == lutA_output) && lutR_unique.size()) + bool input_unused = false; + if (sigmap(lutM_input[i]) == lutA_output) + input_unused = true; + if (!lutM_input[i].wire && !lutM_dlogic_inputs.count(i)) + input_unused = true; + + if (input_unused && lutR_unique.size()) { SigBit new_input = lutR_unique.pop(); log(" Connecting input %d as %s.\n", i, log_signal(new_input)); @@ -246,7 +359,7 @@ struct OptLutWorker } else if (sigmap(lutM_input[i]) == lutA_output) { - log(" Disconnecting input %d.\n", i); + log(" Disconnecting cascade input %d.\n", i); lutM_new_inputs.push_back(SigBit()); } else @@ -292,26 +405,59 @@ struct OptLutWorker } }; +static void split(std::vector &tokens, const std::string &text, char sep) +{ + size_t start = 0, end = 0; + while ((end = text.find(sep, start)) != std::string::npos) { + tokens.push_back(text.substr(start, end - start)); + start = end + 1; + } + tokens.push_back(text.substr(start)); +} + struct OptLutPass : public Pass { OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } void help() YS_OVERRIDE { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" opt_lut [options] [selection]\n"); log("\n"); log("This pass combines cascaded $lut cells with unused inputs.\n"); log("\n"); + log(" -dlogic :=[:=...]\n"); + log(" preserve connections to dedicated logic cell that has ports\n"); + log(" connected to LUT inputs . this includes\n"); + log(" the case where both LUT and dedicated logic input are connected to\n"); + log(" the same constant.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); + dict> dlogic; + size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // if (args[argidx] == "-???") { - // continue; - // } + if (args[argidx] == "-dlogic" && argidx+1 < args.size()) { + std::vector tokens; + split(tokens, args[++argidx], ':'); + if (tokens.size() < 2) + log_cmd_error("The -dlogic option requires at least one connection.\n"); + IdString type = "\\" + tokens[0]; + for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) { + std::vector conn_tokens; + split(conn_tokens, *it, '='); + if (conn_tokens.size() != 2) + log_cmd_error("Invalid format of -dlogic signal mapping.\n"); + IdString logic_port = "\\" + conn_tokens[0]; + int lut_input = atoi(conn_tokens[1].c_str()); + dlogic[type][lut_input] = logic_port; + } + continue; + } break; } extra_args(args, argidx, design); @@ -319,7 +465,7 @@ struct OptLutPass : public Pass { int total_count = 0; for (auto module : design->selected_modules()) { - OptLutWorker worker(module); + OptLutWorker worker(dlogic, module); total_count += worker.combined_count; } if (total_count) -- cgit v1.2.3 From 2d98db73e39f17865ae26cdd00cf7c112521649f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Dec 2018 18:03:58 +0100 Subject: Rename opt_lut.cpp to opt_lut.cc Signed-off-by: Clifford Wolf --- passes/opt/opt_lut.cc | 478 +++++++++++++++++++++++++++++++++++++++++++++++++ passes/opt/opt_lut.cpp | 478 ------------------------------------------------- 2 files changed, 478 insertions(+), 478 deletions(-) create mode 100644 passes/opt/opt_lut.cc delete mode 100644 passes/opt/opt_lut.cpp (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc new file mode 100644 index 000000000..befe346a3 --- /dev/null +++ b/passes/opt/opt_lut.cc @@ -0,0 +1,478 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2018 whitequark + * + * 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" +#include "kernel/modtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct OptLutWorker +{ + dict> &dlogic; + RTLIL::Module *module; + ModIndex index; + SigMap sigmap; + + pool luts; + dict luts_arity; + dict> luts_dlogics; + dict> luts_dlogic_inputs; + + int combined_count = 0; + + bool evaluate_lut(RTLIL::Cell *lut, dict inputs) + { + SigSpec lut_input = sigmap(lut->getPort("\\A")); + int lut_width = lut->getParam("\\WIDTH").as_int(); + Const lut_table = lut->getParam("\\LUT"); + int lut_index = 0; + + for (int i = 0; i < lut_width; i++) + { + SigBit input = sigmap(lut_input[i]); + if (inputs.count(input)) + { + lut_index |= inputs[input] << i; + } + else + { + lut_index |= SigSpec(lut_input[i]).as_bool() << i; + } + } + + return lut_table.extract(lut_index).as_int(); + } + + void show_stats_by_arity() + { + dict arity_counts; + dict dlogic_counts; + int max_arity = 0; + + for (auto lut_arity : luts_arity) + { + max_arity = max(max_arity, lut_arity.second); + arity_counts[lut_arity.second]++; + } + + for (auto &lut_dlogics : luts_dlogics) + { + for (auto &lut_dlogic : lut_dlogics.second) + { + dlogic_counts[lut_dlogic->type]++; + } + } + + log("Number of LUTs: %8zu\n", luts.size()); + for (int arity = 1; arity <= max_arity; arity++) + { + if (arity_counts[arity]) + log(" %d-LUT %16d\n", arity, arity_counts[arity]); + } + for (auto &dlogic_count : dlogic_counts) + { + log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second); + } + } + + OptLutWorker(dict> &dlogic, RTLIL::Module *module) : + dlogic(dlogic), module(module), index(module), sigmap(module) + { + log("Discovering LUTs.\n"); + for (auto cell : module->selected_cells()) + { + if (cell->type == "$lut") + { + int lut_width = cell->getParam("\\WIDTH").as_int(); + SigSpec lut_input = cell->getPort("\\A"); + int lut_arity = 0; + + log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + luts.insert(cell); + + // First, find all dedicated logic we're connected to. This results in an overapproximation + // of such connections. + pool lut_all_dlogics; + for (int i = 0; i < lut_width; i++) + { + SigBit bit = lut_input[i]; + for (auto &port : index.query_ports(bit)) + { + if (dlogic.count(port.cell->type)) + { + auto &dlogic_map = dlogic[port.cell->type]; + if (dlogic_map.count(i)) + { + if (port.port == dlogic_map[i]) + { + lut_all_dlogics.insert(port.cell); + } + } + } + } + } + + // Second, make sure that the connection to dedicated logic is legal. If it is not legal, + // it means one of the two things: + // * The connection is spurious. I.e. this is dedicated logic that will be packed + // with some other LUT, and it just happens to be conected to this LUT as well. + // * The connection is illegal. + // In either of these cases, we don't need to concern ourselves with preserving the connection + // between this LUT and this dedicated logic cell. + pool lut_legal_dlogics; + pool lut_dlogic_inputs; + for (auto lut_dlogic : lut_all_dlogics) + { + auto &dlogic_map = dlogic[lut_dlogic->type]; + bool legal = true; + for (auto &dlogic_conn : dlogic_map) + { + if (lut_width <= dlogic_conn.first) + { + log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log(" LUT input A[%d] not present.\n", dlogic_conn.first); + legal = false; + break; + } + if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second))) + { + log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); + legal = false; + break; + } + } + + if (legal) + { + log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + lut_legal_dlogics.insert(lut_dlogic); + for (auto &dlogic_conn : dlogic_map) + lut_dlogic_inputs.insert(dlogic_conn.first); + } + } + + // Third, determine LUT arity. An n-wide LUT that has k constant inputs and m inputs shared with dedicated + // logic implements an (n-k-m)-ary function. + for (int i = 0; i < lut_width; i++) + { + SigBit bit = lut_input[i]; + if (bit.wire || lut_dlogic_inputs.count(i)) + lut_arity++; + } + + log(" Cell implements a %d-LUT.\n", lut_arity); + luts_arity[cell] = lut_arity; + luts_dlogics[cell] = lut_legal_dlogics; + luts_dlogic_inputs[cell] = lut_dlogic_inputs; + } + } + show_stats_by_arity(); + + log("\n"); + log("Combining LUTs.\n"); + pool worklist = luts; + while (worklist.size()) + { + auto lutA = worklist.pop(); + SigSpec lutA_input = sigmap(lutA->getPort("\\A")); + SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); + int lutA_width = lutA->getParam("\\WIDTH").as_int(); + int lutA_arity = luts_arity[lutA]; + pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; + + auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); + if (lutA_output_ports.size() != 2) + continue; + + for (auto &port : lutA_output_ports) + { + if (port.cell == lutA) + continue; + + if (luts.count(port.cell)) + { + auto lutB = port.cell; + SigSpec lutB_input = sigmap(lutB->getPort("\\A")); + SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); + int lutB_width = lutB->getParam("\\WIDTH").as_int(); + int lutB_arity = luts_arity[lutB]; + pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; + + log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + + pool lutA_inputs; + pool lutB_inputs; + for (auto &bit : lutA_input) + { + if (bit.wire) + lutA_inputs.insert(sigmap(bit)); + } + for (auto &bit : lutB_input) + { + if (bit.wire) + lutB_inputs.insert(sigmap(bit)); + } + + pool common_inputs; + for (auto &bit : lutA_inputs) + { + if (lutB_inputs.count(bit)) + common_inputs.insert(bit); + } + + int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); + if (lutA_dlogic_inputs.size()) + log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); + else + log(" Cell A is a %d-LUT. ", lutA_arity); + if (lutB_dlogic_inputs.size()) + log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); + else + log("Cell B is a %d-LUT.\n", lutB_arity); + log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); + + const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; + int combine_mask = 0; + if (lutM_arity > lutA_width) + { + log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); + } + else if (lutB_dlogic_inputs.size() > 0) + { + log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); + } + else if (lutB->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); + } + else + { + combine_mask |= COMBINE_A; + } + if (lutM_arity > lutB_width) + { + log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); + } + else if (lutA_dlogic_inputs.size() > 0) + { + log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); + } + else if (lutA->get_bool_attribute("\\lut_keep")) + { + log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); + } + else + { + combine_mask |= COMBINE_B; + } + + int combine = combine_mask; + if (combine == COMBINE_EITHER) + { + log(" Can combine into either cell.\n"); + if (lutA_arity == 1) + { + log(" Cell A is a buffer or inverter, combining into cell B.\n"); + combine = COMBINE_B; + } + else if (lutB_arity == 1) + { + log(" Cell B is a buffer or inverter, combining into cell A.\n"); + combine = COMBINE_A; + } + else + { + log(" Arbitrarily combining into cell A.\n"); + combine = COMBINE_A; + } + } + + RTLIL::Cell *lutM, *lutR; + pool lutM_inputs, lutR_inputs; + pool lutM_dlogic_inputs; + if (combine == COMBINE_A) + { + log(" Combining LUTs into cell A.\n"); + lutM = lutA; + lutM_inputs = lutA_inputs; + lutM_dlogic_inputs = lutA_dlogic_inputs; + lutR = lutB; + lutR_inputs = lutB_inputs; + } + else if (combine == COMBINE_B) + { + log(" Combining LUTs into cell B.\n"); + lutM = lutB; + lutM_inputs = lutB_inputs; + lutM_dlogic_inputs = lutB_dlogic_inputs; + lutR = lutA; + lutR_inputs = lutA_inputs; + } + else + { + log(" Cannot combine LUTs.\n"); + continue; + } + + pool lutR_unique; + for (auto &bit : lutR_inputs) + { + if (!common_inputs.count(bit) && bit != lutA_output) + lutR_unique.insert(bit); + } + + int lutM_width = lutM->getParam("\\WIDTH").as_int(); + SigSpec lutM_input = sigmap(lutM->getPort("\\A")); + std::vector lutM_new_inputs; + for (int i = 0; i < lutM_width; i++) + { + bool input_unused = false; + if (sigmap(lutM_input[i]) == lutA_output) + input_unused = true; + if (!lutM_input[i].wire && !lutM_dlogic_inputs.count(i)) + input_unused = true; + + if (input_unused && lutR_unique.size()) + { + SigBit new_input = lutR_unique.pop(); + log(" Connecting input %d as %s.\n", i, log_signal(new_input)); + lutM_new_inputs.push_back(new_input); + } + else if (sigmap(lutM_input[i]) == lutA_output) + { + log(" Disconnecting cascade input %d.\n", i); + lutM_new_inputs.push_back(SigBit()); + } + else + { + log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); + lutM_new_inputs.push_back(lutM_input[i]); + } + } + log_assert(lutR_unique.size() == 0); + + RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width); + for (int eval = 0; eval < 1 << lutM_width; eval++) + { + dict eval_inputs; + for (size_t i = 0; i < lutM_new_inputs.size(); i++) + { + eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; + } + eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); + lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); + } + + log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); + log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); + + lutM->setParam("\\LUT", lutM_new_table); + lutM->setPort("\\A", lutM_new_inputs); + lutM->setPort("\\Y", lutB_output); + + luts_arity[lutM] = lutM_arity; + luts.erase(lutR); + luts_arity.erase(lutR); + lutR->module->remove(lutR); + + worklist.insert(lutM); + worklist.erase(lutR); + + combined_count++; + } + } + } + show_stats_by_arity(); + } +}; + +static void split(std::vector &tokens, const std::string &text, char sep) +{ + size_t start = 0, end = 0; + while ((end = text.find(sep, start)) != std::string::npos) { + tokens.push_back(text.substr(start, end - start)); + start = end + 1; + } + tokens.push_back(text.substr(start)); +} + +struct OptLutPass : public Pass { + OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" opt_lut [options] [selection]\n"); + log("\n"); + log("This pass combines cascaded $lut cells with unused inputs.\n"); + log("\n"); + log(" -dlogic :=[:=...]\n"); + log(" preserve connections to dedicated logic cell that has ports\n"); + log(" connected to LUT inputs . this includes\n"); + log(" the case where both LUT and dedicated logic input are connected to\n"); + log(" the same constant.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); + + dict> dlogic; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + if (args[argidx] == "-dlogic" && argidx+1 < args.size()) { + std::vector tokens; + split(tokens, args[++argidx], ':'); + if (tokens.size() < 2) + log_cmd_error("The -dlogic option requires at least one connection.\n"); + IdString type = "\\" + tokens[0]; + for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) { + std::vector conn_tokens; + split(conn_tokens, *it, '='); + if (conn_tokens.size() != 2) + log_cmd_error("Invalid format of -dlogic signal mapping.\n"); + IdString logic_port = "\\" + conn_tokens[0]; + int lut_input = atoi(conn_tokens[1].c_str()); + dlogic[type][lut_input] = logic_port; + } + continue; + } + break; + } + extra_args(args, argidx, design); + + int total_count = 0; + for (auto module : design->selected_modules()) + { + OptLutWorker worker(dlogic, module); + total_count += worker.combined_count; + } + if (total_count) + design->scratchpad_set_bool("opt.did_something", true); + log("\n"); + log("Combined %d LUTs.\n", total_count); + } +} OptLutPass; + +PRIVATE_NAMESPACE_END diff --git a/passes/opt/opt_lut.cpp b/passes/opt/opt_lut.cpp deleted file mode 100644 index befe346a3..000000000 --- a/passes/opt/opt_lut.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2018 whitequark - * - * 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" -#include "kernel/modtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct OptLutWorker -{ - dict> &dlogic; - RTLIL::Module *module; - ModIndex index; - SigMap sigmap; - - pool luts; - dict luts_arity; - dict> luts_dlogics; - dict> luts_dlogic_inputs; - - int combined_count = 0; - - bool evaluate_lut(RTLIL::Cell *lut, dict inputs) - { - SigSpec lut_input = sigmap(lut->getPort("\\A")); - int lut_width = lut->getParam("\\WIDTH").as_int(); - Const lut_table = lut->getParam("\\LUT"); - int lut_index = 0; - - for (int i = 0; i < lut_width; i++) - { - SigBit input = sigmap(lut_input[i]); - if (inputs.count(input)) - { - lut_index |= inputs[input] << i; - } - else - { - lut_index |= SigSpec(lut_input[i]).as_bool() << i; - } - } - - return lut_table.extract(lut_index).as_int(); - } - - void show_stats_by_arity() - { - dict arity_counts; - dict dlogic_counts; - int max_arity = 0; - - for (auto lut_arity : luts_arity) - { - max_arity = max(max_arity, lut_arity.second); - arity_counts[lut_arity.second]++; - } - - for (auto &lut_dlogics : luts_dlogics) - { - for (auto &lut_dlogic : lut_dlogics.second) - { - dlogic_counts[lut_dlogic->type]++; - } - } - - log("Number of LUTs: %8zu\n", luts.size()); - for (int arity = 1; arity <= max_arity; arity++) - { - if (arity_counts[arity]) - log(" %d-LUT %16d\n", arity, arity_counts[arity]); - } - for (auto &dlogic_count : dlogic_counts) - { - log(" with %-12s %4d\n", dlogic_count.first.c_str(), dlogic_count.second); - } - } - - OptLutWorker(dict> &dlogic, RTLIL::Module *module) : - dlogic(dlogic), module(module), index(module), sigmap(module) - { - log("Discovering LUTs.\n"); - for (auto cell : module->selected_cells()) - { - if (cell->type == "$lut") - { - int lut_width = cell->getParam("\\WIDTH").as_int(); - SigSpec lut_input = cell->getPort("\\A"); - int lut_arity = 0; - - log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); - luts.insert(cell); - - // First, find all dedicated logic we're connected to. This results in an overapproximation - // of such connections. - pool lut_all_dlogics; - for (int i = 0; i < lut_width; i++) - { - SigBit bit = lut_input[i]; - for (auto &port : index.query_ports(bit)) - { - if (dlogic.count(port.cell->type)) - { - auto &dlogic_map = dlogic[port.cell->type]; - if (dlogic_map.count(i)) - { - if (port.port == dlogic_map[i]) - { - lut_all_dlogics.insert(port.cell); - } - } - } - } - } - - // Second, make sure that the connection to dedicated logic is legal. If it is not legal, - // it means one of the two things: - // * The connection is spurious. I.e. this is dedicated logic that will be packed - // with some other LUT, and it just happens to be conected to this LUT as well. - // * The connection is illegal. - // In either of these cases, we don't need to concern ourselves with preserving the connection - // between this LUT and this dedicated logic cell. - pool lut_legal_dlogics; - pool lut_dlogic_inputs; - for (auto lut_dlogic : lut_all_dlogics) - { - auto &dlogic_map = dlogic[lut_dlogic->type]; - bool legal = true; - for (auto &dlogic_conn : dlogic_map) - { - if (lut_width <= dlogic_conn.first) - { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] not present.\n", dlogic_conn.first); - legal = false; - break; - } - if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second))) - { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); - legal = false; - break; - } - } - - if (legal) - { - log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - lut_legal_dlogics.insert(lut_dlogic); - for (auto &dlogic_conn : dlogic_map) - lut_dlogic_inputs.insert(dlogic_conn.first); - } - } - - // Third, determine LUT arity. An n-wide LUT that has k constant inputs and m inputs shared with dedicated - // logic implements an (n-k-m)-ary function. - for (int i = 0; i < lut_width; i++) - { - SigBit bit = lut_input[i]; - if (bit.wire || lut_dlogic_inputs.count(i)) - lut_arity++; - } - - log(" Cell implements a %d-LUT.\n", lut_arity); - luts_arity[cell] = lut_arity; - luts_dlogics[cell] = lut_legal_dlogics; - luts_dlogic_inputs[cell] = lut_dlogic_inputs; - } - } - show_stats_by_arity(); - - log("\n"); - log("Combining LUTs.\n"); - pool worklist = luts; - while (worklist.size()) - { - auto lutA = worklist.pop(); - SigSpec lutA_input = sigmap(lutA->getPort("\\A")); - SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); - int lutA_width = lutA->getParam("\\WIDTH").as_int(); - int lutA_arity = luts_arity[lutA]; - pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; - - auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); - if (lutA_output_ports.size() != 2) - continue; - - for (auto &port : lutA_output_ports) - { - if (port.cell == lutA) - continue; - - if (luts.count(port.cell)) - { - auto lutB = port.cell; - SigSpec lutB_input = sigmap(lutB->getPort("\\A")); - SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); - int lutB_width = lutB->getParam("\\WIDTH").as_int(); - int lutB_arity = luts_arity[lutB]; - pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; - - log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); - - pool lutA_inputs; - pool lutB_inputs; - for (auto &bit : lutA_input) - { - if (bit.wire) - lutA_inputs.insert(sigmap(bit)); - } - for (auto &bit : lutB_input) - { - if (bit.wire) - lutB_inputs.insert(sigmap(bit)); - } - - pool common_inputs; - for (auto &bit : lutA_inputs) - { - if (lutB_inputs.count(bit)) - common_inputs.insert(bit); - } - - int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); - if (lutA_dlogic_inputs.size()) - log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); - else - log(" Cell A is a %d-LUT. ", lutA_arity); - if (lutB_dlogic_inputs.size()) - log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); - else - log("Cell B is a %d-LUT.\n", lutB_arity); - log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); - - const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; - int combine_mask = 0; - if (lutM_arity > lutA_width) - { - log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); - } - else if (lutB_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); - } - else if (lutB->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); - } - else - { - combine_mask |= COMBINE_A; - } - if (lutM_arity > lutB_width) - { - log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); - } - else if (lutA_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); - } - else if (lutA->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); - } - else - { - combine_mask |= COMBINE_B; - } - - int combine = combine_mask; - if (combine == COMBINE_EITHER) - { - log(" Can combine into either cell.\n"); - if (lutA_arity == 1) - { - log(" Cell A is a buffer or inverter, combining into cell B.\n"); - combine = COMBINE_B; - } - else if (lutB_arity == 1) - { - log(" Cell B is a buffer or inverter, combining into cell A.\n"); - combine = COMBINE_A; - } - else - { - log(" Arbitrarily combining into cell A.\n"); - combine = COMBINE_A; - } - } - - RTLIL::Cell *lutM, *lutR; - pool lutM_inputs, lutR_inputs; - pool lutM_dlogic_inputs; - if (combine == COMBINE_A) - { - log(" Combining LUTs into cell A.\n"); - lutM = lutA; - lutM_inputs = lutA_inputs; - lutM_dlogic_inputs = lutA_dlogic_inputs; - lutR = lutB; - lutR_inputs = lutB_inputs; - } - else if (combine == COMBINE_B) - { - log(" Combining LUTs into cell B.\n"); - lutM = lutB; - lutM_inputs = lutB_inputs; - lutM_dlogic_inputs = lutB_dlogic_inputs; - lutR = lutA; - lutR_inputs = lutA_inputs; - } - else - { - log(" Cannot combine LUTs.\n"); - continue; - } - - pool lutR_unique; - for (auto &bit : lutR_inputs) - { - if (!common_inputs.count(bit) && bit != lutA_output) - lutR_unique.insert(bit); - } - - int lutM_width = lutM->getParam("\\WIDTH").as_int(); - SigSpec lutM_input = sigmap(lutM->getPort("\\A")); - std::vector lutM_new_inputs; - for (int i = 0; i < lutM_width; i++) - { - bool input_unused = false; - if (sigmap(lutM_input[i]) == lutA_output) - input_unused = true; - if (!lutM_input[i].wire && !lutM_dlogic_inputs.count(i)) - input_unused = true; - - if (input_unused && lutR_unique.size()) - { - SigBit new_input = lutR_unique.pop(); - log(" Connecting input %d as %s.\n", i, log_signal(new_input)); - lutM_new_inputs.push_back(new_input); - } - else if (sigmap(lutM_input[i]) == lutA_output) - { - log(" Disconnecting cascade input %d.\n", i); - lutM_new_inputs.push_back(SigBit()); - } - else - { - log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); - lutM_new_inputs.push_back(lutM_input[i]); - } - } - log_assert(lutR_unique.size() == 0); - - RTLIL::Const lutM_new_table(State::Sx, 1 << lutM_width); - for (int eval = 0; eval < 1 << lutM_width; eval++) - { - dict eval_inputs; - for (size_t i = 0; i < lutM_new_inputs.size(); i++) - { - eval_inputs[lutM_new_inputs[i]] = (eval >> i) & 1; - } - eval_inputs[lutA_output] = evaluate_lut(lutA, eval_inputs); - lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); - } - - log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); - log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); - - lutM->setParam("\\LUT", lutM_new_table); - lutM->setPort("\\A", lutM_new_inputs); - lutM->setPort("\\Y", lutB_output); - - luts_arity[lutM] = lutM_arity; - luts.erase(lutR); - luts_arity.erase(lutR); - lutR->module->remove(lutR); - - worklist.insert(lutM); - worklist.erase(lutR); - - combined_count++; - } - } - } - show_stats_by_arity(); - } -}; - -static void split(std::vector &tokens, const std::string &text, char sep) -{ - size_t start = 0, end = 0; - while ((end = text.find(sep, start)) != std::string::npos) { - tokens.push_back(text.substr(start, end - start)); - start = end + 1; - } - tokens.push_back(text.substr(start)); -} - -struct OptLutPass : public Pass { - OptLutPass() : Pass("opt_lut", "optimize LUT cells") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" opt_lut [options] [selection]\n"); - log("\n"); - log("This pass combines cascaded $lut cells with unused inputs.\n"); - log("\n"); - log(" -dlogic :=[:=...]\n"); - log(" preserve connections to dedicated logic cell that has ports\n"); - log(" connected to LUT inputs . this includes\n"); - log(" the case where both LUT and dedicated logic input are connected to\n"); - log(" the same constant.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); - - dict> dlogic; - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - if (args[argidx] == "-dlogic" && argidx+1 < args.size()) { - std::vector tokens; - split(tokens, args[++argidx], ':'); - if (tokens.size() < 2) - log_cmd_error("The -dlogic option requires at least one connection.\n"); - IdString type = "\\" + tokens[0]; - for (auto it = tokens.begin() + 1; it != tokens.end(); ++it) { - std::vector conn_tokens; - split(conn_tokens, *it, '='); - if (conn_tokens.size() != 2) - log_cmd_error("Invalid format of -dlogic signal mapping.\n"); - IdString logic_port = "\\" + conn_tokens[0]; - int lut_input = atoi(conn_tokens[1].c_str()); - dlogic[type][lut_input] = logic_port; - } - continue; - } - break; - } - extra_args(args, argidx, design); - - int total_count = 0; - for (auto module : design->selected_modules()) - { - OptLutWorker worker(dlogic, module); - total_count += worker.combined_count; - } - if (total_count) - design->scratchpad_set_bool("opt.did_something", true); - log("\n"); - log("Combined %d LUTs.\n", total_count); - } -} OptLutPass; - -PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 88217d0157a1dd11a8151542adaed5d0a1c90149 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 5 Dec 2018 19:12:02 +0000 Subject: opt_lut: simplify type conversion. NFC. --- passes/opt/opt_lut.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index befe346a3..3c4cb95bb 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -58,7 +58,7 @@ struct OptLutWorker } } - return lut_table.extract(lut_index).as_int(); + return lut_table.extract(lut_index).as_bool(); } void show_stats_by_arity() -- cgit v1.2.3 From 643f858acffcb40cce4686a5a039dc80c18b933d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 6 Dec 2018 07:29:21 +0100 Subject: Bugfix in opt_expr handling of a<0 and a>=0 Signed-off-by: Clifford Wolf --- passes/opt/opt_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 0ba233c62..610edc5e9 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1406,7 +1406,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { if (sigConst.is_fully_zero()) { - RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); + RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y"))); if (is_lt) { log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n", log_id(cell->type), log_id(cell)); -- cgit v1.2.3 From a8ab7228240fb227f4178ca02037cdcf897ee19e Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 16:31:15 +0000 Subject: opt_lut: add -limit option, for debugging misoptimizations. --- passes/opt/opt_lut.cc | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index befe346a3..ee3943f9c 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -93,7 +93,7 @@ struct OptLutWorker } } - OptLutWorker(dict> &dlogic, RTLIL::Module *module) : + OptLutWorker(dict> &dlogic, RTLIL::Module *module, int limit) : dlogic(dlogic), module(module), index(module), sigmap(module) { log("Discovering LUTs.\n"); @@ -192,6 +192,12 @@ struct OptLutWorker pool worklist = luts; while (worklist.size()) { + if (limit == 0) + { + log("Limit reached.\n"); + break; + } + auto lutA = worklist.pop(); SigSpec lutA_input = sigmap(lutA->getPort("\\A")); SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); @@ -398,6 +404,8 @@ struct OptLutWorker worklist.erase(lutR); combined_count++; + if (limit > 0) + limit--; } } } @@ -431,17 +439,22 @@ struct OptLutPass : public Pass { log(" the case where both LUT and dedicated logic input are connected to\n"); log(" the same constant.\n"); log("\n"); + log(" -limit N\n"); + log(" only perform the first N combines, then stop. useful for debugging.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_LUT pass (optimize LUTs).\n"); dict> dlogic; + int limit = -1; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-dlogic" && argidx+1 < args.size()) { + if (args[argidx] == "-dlogic" && argidx+1 < args.size()) + { std::vector tokens; split(tokens, args[++argidx], ':'); if (tokens.size() < 2) @@ -458,6 +471,11 @@ struct OptLutPass : public Pass { } continue; } + if (args[argidx] == "-limit" && argidx + 1 < args.size()) + { + limit = atoi(args[++argidx].c_str()); + continue; + } break; } extra_args(args, argidx, design); @@ -465,7 +483,7 @@ struct OptLutPass : public Pass { int total_count = 0; for (auto module : design->selected_modules()) { - OptLutWorker worker(dlogic, module); + OptLutWorker worker(dlogic, module, limit - total_count); total_count += worker.combined_count; } if (total_count) -- cgit v1.2.3 From 9eb03d458dcb2a3ba91a84739e764558b26e335c Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 17:04:41 +0000 Subject: opt_lut: show original truth table for both cells. --- passes/opt/opt_lut.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index ee3943f9c..4207fbdb9 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -388,8 +388,9 @@ struct OptLutWorker lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - log(" Old truth table: %s.\n", lutM->getParam("\\LUT").as_string().c_str()); - log(" New truth table: %s.\n", lutM_new_table.as_string().c_str()); + log(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); + log(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); + log(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); lutM->setParam("\\LUT", lutM_new_table); lutM->setPort("\\A", lutM_new_inputs); -- cgit v1.2.3 From 7ec740b7ad4ee4bc02e2564671e0153cdd08152f Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 17:13:52 +0000 Subject: opt_lut: leave intact LUTs with cascade feeding module outputs. --- passes/opt/opt_lut.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 4207fbdb9..ba2cc6ee7 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -225,6 +225,12 @@ struct OptLutWorker log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + if (index.query_is_output(lutA->getPort("\\Y"))) + { + log(" Not combining LUTs (cascade connection feeds module output).\n"); + continue; + } + pool lutA_inputs; pool lutB_inputs; for (auto &bit : lutA_input) -- cgit v1.2.3 From 0a840dd88334c382314db3aafc2f1da2a1969df2 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 31 Dec 2018 16:34:27 +0100 Subject: Fix handling of (* keep *) wires in wreduce Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 0164f58d6..8063b86a6 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -235,8 +235,11 @@ struct WreduceWorker } else { while (GetSize(sig) > 0) { - auto info = mi.query(sig[GetSize(sig)-1]); + auto bit = sig[GetSize(sig)-1]; + if (keep_bits.count(bit)) + break; + auto info = mi.query(bit); if (info->is_output || GetSize(info->ports) > 1) break; -- cgit v1.2.3 From 42c356c49c04a735fe27e672ff31452170f84b40 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 31 Dec 2018 23:53:23 +0000 Subject: opt_lut: eliminate LUTs evaluating to constants or inputs. --- passes/opt/opt_lut.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index be050c713..261af538f 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -187,6 +187,87 @@ struct OptLutWorker } show_stats_by_arity(); + log("\n"); + log("Eliminating LUTs.\n"); + for (auto lut : luts) + { + SigSpec lut_input = sigmap(lut->getPort("\\A")); + pool &lut_dlogic_inputs = luts_dlogic_inputs[lut]; + + vector lut_inputs; + for (auto &bit : lut_input) + { + if (bit.wire) + lut_inputs.push_back(sigmap(bit)); + } + + bool const0_match = true; + bool const1_match = true; + vector input_matches; + for (size_t i = 0; i < lut_inputs.size(); i++) + input_matches.push_back(true); + + for (int eval = 0; eval < 1 << lut_inputs.size(); eval++) + { + dict eval_inputs; + for (size_t i = 0; i < lut_inputs.size(); i++) + eval_inputs[lut_inputs[i]] = (eval >> i) & 1; + bool value = evaluate_lut(lut, eval_inputs); + if (value != 0) + const0_match = false; + if (value != 1) + const1_match = false; + for (size_t i = 0; i < lut_inputs.size(); i++) + { + if (value != eval_inputs[lut_inputs[i]]) + input_matches[i] = false; + } + } + + int input_match = -1; + for (size_t i = 0; i < lut_inputs.size(); i++) + if (input_matches[i]) + input_match = i; + + if (const0_match || const1_match || input_match != -1) + { + log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); + + SigBit value; + if (const0_match) + { + log(" Cell evaluates constant 0.\n"); + value = State::S0; + } + if (const1_match) + { + log(" Cell evaluates constant 1.\n"); + value = State::S1; + } + if (input_match != -1) { + log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match])); + value = lut_inputs[input_match]; + } + + if (lut_dlogic_inputs.size()) + { + log(" Not eliminating cell (connected to dedicated logic).\n"); + } + else + { + SigSpec lut_output = lut->getPort("\\Y"); + module->connect(lut_output, value); + + module->remove(lut); + luts.erase(lut); + luts_arity.erase(lut); + luts_dlogics.erase(lut); + luts_dlogic_inputs.erase(lut); + } + } + } + show_stats_by_arity(); + log("\n"); log("Combining LUTs.\n"); pool worklist = luts; -- cgit v1.2.3 From 8e53d2e0bf3584709cd320447ad5a89a80dcfd94 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 02:45:49 +0000 Subject: opt_expr: simplify any unsigned comparisons with all-0 and all-1. Before this commit, only unsigned comparisons with all-0 would be simplified. This commit also makes the code handling such comparisons to be more rigorous and not abort on unexpected input. --- passes/opt/opt_expr.cc | 86 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 17 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 610edc5e9..87597ce57 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1344,6 +1344,75 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } + // simplify comparisons + // currently, only replaces comparisons with an extreme of the signal range with a constant + // TODO: since, unlike the following optimization, this one does not assume that both inputs to the cell are constant, + // it is more robust; the following optimization should be folded into this one at some point + if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) + { + IdString cmp_type = cell->type; + SigSpec var_sig = cell->getPort("\\A"); + SigSpec const_sig = cell->getPort("\\B"); + int var_width = cell->parameters["\\A_WIDTH"].as_int(); + int const_width = cell->parameters["\\B_WIDTH"].as_int(); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + + if (!const_sig.is_fully_const()) + { + std::swap(var_sig, const_sig); + std::swap(var_width, const_width); + if (cmp_type == "$gt") + cmp_type = "$lt"; + else if (cmp_type == "$lt") + cmp_type = "$gt"; + else if (cmp_type == "$ge") + cmp_type = "$le"; + else if (cmp_type == "$le") + cmp_type = "$ge"; + } + + if (const_sig.is_fully_def() && const_sig.is_fully_const()) + { + const char *condition, *replacement; + SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y"))); + result_sig[0] = State::Sx; + + if (!is_signed) + { + if (const_sig.is_fully_zero() && cmp_type == "$lt") { + condition = "unsigned X<0"; + replacement = "constant 0"; + result_sig[0] = State::S0; + } + if (const_sig.is_fully_zero() && cmp_type == "$ge") { + condition = "unsigned X>=0"; + replacement = "constant 1"; + result_sig[0] = State::S1; + } + if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") { + condition = "unsigned X>~0"; + replacement = "constant 0"; + result_sig[0] = State::S0; + } + if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") { + condition = "unsigned X<=~0"; + replacement = "constant 1"; + result_sig[0] = State::S1; + } + } + + if (result_sig.is_fully_def()) + { + log("Replacing %s cell `%s' (implementing %s) with %s.\n", + log_id(cell->type), log_id(cell), condition, replacement); + module->connect(cell->getPort("\\Y"), result_sig); + module->remove(cell); + did_something = true; + goto next_cell; + } + } + } + // replace a<0 or a>=0 with the top bit of a if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) { @@ -1405,23 +1474,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } else if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { - if (sigConst.is_fully_zero()) { - RTLIL::SigSpec a_prime(RTLIL::State::S0, GetSize(cell->getPort("\\Y"))); - if (is_lt) { - log("Replacing %s cell `%s' (implementing unsigned X<0) with constant false.\n", - log_id(cell->type), log_id(cell)); - a_prime[0] = RTLIL::State::S0; - } else { - log("Replacing %s cell `%s' (implementing unsigned X>=0) with constant true.\n", - log_id(cell->type), log_id(cell)); - a_prime[0] = RTLIL::State::S1; - } - module->connect(cell->getPort("\\Y"), a_prime); - module->remove(cell); - did_something = true; - goto next_cell; - } - int const_bit_set = get_onehot_bit_index(sigConst); if (const_bit_set >= 0 && const_bit_set < width) { int bit_set = const_bit_set; -- cgit v1.2.3 From 9e9846a6ead700756fbd7a5e6c72ccb424006934 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 03:01:25 +0000 Subject: opt_expr: refactor simplification of signed X>=0 and X<0. NFCI. --- passes/opt/opt_expr.cc | 50 ++++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 24 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 87597ce57..989c949ce 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1373,38 +1373,59 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (const_sig.is_fully_def() && const_sig.is_fully_const()) { - const char *condition, *replacement; + std::string condition, replacement; SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y"))); - result_sig[0] = State::Sx; + bool replace = false; if (!is_signed) - { + { /* unsigned */ if (const_sig.is_fully_zero() && cmp_type == "$lt") { condition = "unsigned X<0"; replacement = "constant 0"; result_sig[0] = State::S0; + replace = true; } if (const_sig.is_fully_zero() && cmp_type == "$ge") { condition = "unsigned X>=0"; replacement = "constant 1"; result_sig[0] = State::S1; + replace = true; } if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") { condition = "unsigned X>~0"; replacement = "constant 0"; result_sig[0] = State::S0; + replace = true; } if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") { condition = "unsigned X<=~0"; replacement = "constant 1"; result_sig[0] = State::S1; + replace = true; + } + } + else + { /* signed */ + if (const_sig.is_fully_zero() && cmp_type == "$lt") + { + condition = "signed X<0"; + replacement = stringf("X[%d]", var_width - 1); + result_sig[0] = var_sig[var_width - 1]; + replace = true; + } + if (const_sig.is_fully_zero() && cmp_type == "$ge") + { + condition = "signed X>=0"; + replacement = stringf("X[%d]", var_width - 1); + module->addNot(NEW_ID, var_sig[var_width - 1], result_sig); + replace = true; } } - if (result_sig.is_fully_def()) + if (replace) { log("Replacing %s cell `%s' (implementing %s) with %s.\n", - log_id(cell->type), log_id(cell), condition, replacement); + log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); module->connect(cell->getPort("\\Y"), result_sig); module->remove(cell); did_something = true; @@ -1453,25 +1474,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } else log_abort(); - // replace a(signed) < 0 with the high bit of a - if (sigConst.is_fully_const() && sigConst.is_fully_zero() && var_signed == true) - { - RTLIL::SigSpec a_prime(RTLIL::State::S0, cell->parameters["\\Y_WIDTH"].as_int()); - a_prime[0] = sigVar[width - 1]; - if (is_lt) { - log("Replacing %s cell `%s' (implementing X<0) with X[%d]: %s\n", - log_id(cell->type), log_id(cell), width-1, log_signal(a_prime)); - module->connect(cell->getPort("\\Y"), a_prime); - module->remove(cell); - } else { - log("Replacing %s cell `%s' (implementing X>=0) with ~X[%d]: %s\n", - log_id(cell->type), log_id(cell), width-1, log_signal(a_prime)); - module->addNot(NEW_ID, a_prime, cell->getPort("\\Y")); - module->remove(cell); - } - did_something = true; - goto next_cell; - } else if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { int const_bit_set = get_onehot_bit_index(sigConst); -- cgit v1.2.3 From 4fd458290c3da4c3f372f2e1fdd99829a9462a38 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 04:31:20 +0000 Subject: opt_expr: refactor simplification of unsigned X=onehot. NFCI. --- passes/opt/opt_expr.cc | 68 +++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 989c949ce..9abbdc6ac 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1374,35 +1374,60 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (const_sig.is_fully_def() && const_sig.is_fully_const()) { std::string condition, replacement; - SigSpec result_sig(State::S0, GetSize(cell->getPort("\\Y"))); + SigSpec replace_sig(State::S0, GetSize(cell->getPort("\\Y"))); bool replace = false; + bool remove = false; if (!is_signed) { /* unsigned */ if (const_sig.is_fully_zero() && cmp_type == "$lt") { condition = "unsigned X<0"; replacement = "constant 0"; - result_sig[0] = State::S0; + replace_sig[0] = State::S0; replace = true; } if (const_sig.is_fully_zero() && cmp_type == "$ge") { condition = "unsigned X>=0"; replacement = "constant 1"; - result_sig[0] = State::S1; + replace_sig[0] = State::S1; replace = true; } if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") { condition = "unsigned X>~0"; replacement = "constant 0"; - result_sig[0] = State::S0; + replace_sig[0] = State::S0; replace = true; } if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") { condition = "unsigned X<=~0"; replacement = "constant 1"; - result_sig[0] = State::S1; + replace_sig[0] = State::S1; replace = true; } + + int const_bit_set = get_onehot_bit_index(const_sig); + if (const_bit_set >= 0 && const_bit_set < var_width) + { + RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_set); + for (int i = const_bit_set; i < var_width; i++) { + var_high_sig[i - const_bit_set] = var_sig[i]; + } + + if (cmp_type == "$lt") + { + condition = stringf("unsigned X<%s", log_signal(const_sig)); + replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_set); + module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y")); + remove = true; + } + if (cmp_type == "$ge") + { + condition = stringf("unsigned X>=%s", log_signal(const_sig)); + replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_set); + module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y")); + remove = true; + } + } } else { /* signed */ @@ -1410,23 +1435,24 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { condition = "signed X<0"; replacement = stringf("X[%d]", var_width - 1); - result_sig[0] = var_sig[var_width - 1]; + replace_sig[0] = var_sig[var_width - 1]; replace = true; } if (const_sig.is_fully_zero() && cmp_type == "$ge") { condition = "signed X>=0"; replacement = stringf("X[%d]", var_width - 1); - module->addNot(NEW_ID, var_sig[var_width - 1], result_sig); - replace = true; + module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort("\\Y")); + remove = true; } } - if (replace) + if (replace || remove) { log("Replacing %s cell `%s' (implementing %s) with %s.\n", log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); - module->connect(cell->getPort("\\Y"), result_sig); + if (replace) + module->connect(cell->getPort("\\Y"), replace_sig); module->remove(cell); did_something = true; goto next_cell; @@ -1477,26 +1503,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) { int const_bit_set = get_onehot_bit_index(sigConst); - if (const_bit_set >= 0 && const_bit_set < width) { - int bit_set = const_bit_set; - RTLIL::SigSpec a_prime(RTLIL::State::S0, width - bit_set); - for (int i = bit_set; i < width; i++) { - a_prime[i - bit_set] = sigVar[i]; - } - if (is_lt) { - log("Replacing %s cell `%s' (implementing unsigned X<%s) with !X[%d:%d]: %s.\n", - log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime)); - module->addLogicNot(NEW_ID, a_prime, cell->getPort("\\Y")); - } else { - log("Replacing %s cell `%s' (implementing unsigned X>=%s) with |X[%d:%d]: %s.\n", - log_id(cell->type), log_id(cell), log_signal(sigConst), width - 1, bit_set, log_signal(a_prime)); - module->addReduceOr(NEW_ID, a_prime, cell->getPort("\\Y")); - } - module->remove(cell); - did_something = true; - goto next_cell; - } - else if(const_bit_set >= width && const_bit_set >= 0){ + if(const_bit_set >= width && const_bit_set >= 0){ RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); if(is_lt){ a_prime[0] = RTLIL::State::S1; @@ -1509,7 +1516,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons module->remove(cell); did_something = true; goto next_cell; - } } } -- cgit v1.2.3 From f7363ac5086ccb8bdb97dcdbfed890c54e1ed153 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 08:40:01 +0000 Subject: opt_lut: count eliminated cells, and set opt.did_something for them. --- passes/opt/opt_lut.cc | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 261af538f..8c564b0ed 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -36,7 +36,7 @@ struct OptLutWorker dict> luts_dlogics; dict> luts_dlogic_inputs; - int combined_count = 0; + int eliminated_count = 0, combined_count = 0; bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { @@ -191,6 +191,12 @@ struct OptLutWorker log("Eliminating LUTs.\n"); for (auto lut : luts) { + if (limit == 0) + { + log("Limit reached.\n"); + break; + } + SigSpec lut_input = sigmap(lut->getPort("\\A")); pool &lut_dlogic_inputs = luts_dlogic_inputs[lut]; @@ -263,6 +269,10 @@ struct OptLutWorker luts_arity.erase(lut); luts_dlogics.erase(lut); luts_dlogic_inputs.erase(lut); + + eliminated_count++; + if (limit > 0) + limit--; } } } @@ -568,16 +578,20 @@ struct OptLutPass : public Pass { } extra_args(args, argidx, design); - int total_count = 0; + int eliminated_count = 0, combined_count = 0; for (auto module : design->selected_modules()) { - OptLutWorker worker(dlogic, module, limit - total_count); - total_count += worker.combined_count; + OptLutWorker worker(dlogic, module, limit - eliminated_count - combined_count); + eliminated_count += worker.eliminated_count; + combined_count += worker.combined_count; } - if (total_count) + if (eliminated_count) + design->scratchpad_set_bool("opt.did_something", true); + if (combined_count) design->scratchpad_set_bool("opt.did_something", true); log("\n"); - log("Combined %d LUTs.\n", total_count); + log("Eliminated %d LUTs.\n", eliminated_count); + log("Combined %d LUTs.\n", combined_count); } } OptLutPass; -- cgit v1.2.3 From 06143ab33f4064677586be2a2b0d763f0818e856 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 09:36:32 +0000 Subject: opt_lut: use a worklist, and revisit cells affected by elimination. --- passes/opt/opt_lut.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 8c564b0ed..a79a9a2da 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -189,7 +189,8 @@ struct OptLutWorker log("\n"); log("Eliminating LUTs.\n"); - for (auto lut : luts) + pool worklist = luts; + while (worklist.size()) { if (limit == 0) { @@ -197,6 +198,7 @@ struct OptLutWorker break; } + auto lut = worklist.pop(); SigSpec lut_input = sigmap(lut->getPort("\\A")); pool &lut_dlogic_inputs = luts_dlogic_inputs[lut]; @@ -262,8 +264,13 @@ struct OptLutWorker else { SigSpec lut_output = lut->getPort("\\Y"); - module->connect(lut_output, value); + for (auto &port : index.query_ports(lut_output)) + { + if (port.cell != lut && luts.count(port.cell)) + worklist.insert(port.cell); + } + module->connect(lut_output, value); module->remove(lut); luts.erase(lut); luts_arity.erase(lut); @@ -280,7 +287,7 @@ struct OptLutWorker log("\n"); log("Combining LUTs.\n"); - pool worklist = luts; + worklist = luts; while (worklist.size()) { if (limit == 0) -- cgit v1.2.3 From c55dfb83693c6707ecb1d7dce7824a61e87eb44d Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 10:21:58 +0000 Subject: opt_lut: reflect changes in sigmap. Otherwise, some LUTs will be missed during elimination. --- passes/opt/opt_lut.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index a79a9a2da..b9a1ce7a7 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -271,6 +271,8 @@ struct OptLutWorker } module->connect(lut_output, value); + sigmap.add(lut_output, value); + module->remove(lut); luts.erase(lut); luts_arity.erase(lut); -- cgit v1.2.3 From efa278e232d20ea080743801bd91d55ec62955cf Mon Sep 17 00:00:00 2001 From: whitequark Date: Fri, 7 Dec 2018 19:14:07 +0000 Subject: Fix typographical and grammatical errors and inconsistencies. The initial list of hits was generated with the codespell command below, and each hit was evaluated and fixed manually while taking context into consideration. DIRS="kernel/ frontends/ backends/ passes/ techlibs/" DIRS="${DIRS} libs/ezsat/ libs/subcircuit" codespell $DIRS -S *.o -L upto,iff,thru,synopsys,uint More hits were found by looking through comments and strings manually. --- passes/opt/opt_expr.cc | 2 +- passes/opt/opt_lut.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 610edc5e9..998c6507c 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1477,7 +1477,7 @@ struct OptExprPass : public Pass { log(" opt_expr [options] [selection]\n"); log("\n"); log("This pass performs const folding on internal cell types with constant inputs.\n"); - log("It also performs some simple expression rewritring.\n"); + log("It also performs some simple expression rewriting.\n"); log("\n"); log(" -mux_undef\n"); log(" remove 'undef' inputs from $mux, $pmux and $_MUX_ cells\n"); diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 261af538f..d1b8ab358 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -133,7 +133,7 @@ struct OptLutWorker // Second, make sure that the connection to dedicated logic is legal. If it is not legal, // it means one of the two things: // * The connection is spurious. I.e. this is dedicated logic that will be packed - // with some other LUT, and it just happens to be conected to this LUT as well. + // with some other LUT, and it just happens to be connected to this LUT as well. // * The connection is illegal. // In either of these cases, we don't need to concern ourselves with preserving the connection // between this LUT and this dedicated logic cell. -- cgit v1.2.3 From bf8db55ef36f6839827cd8bc69f673fd3fd43cca Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 05:04:28 +0000 Subject: opt_expr: improve simplification of comparisons with large constants. The idea behind this simplification is that a N-bit signal X being compared with an M-bit constant where M>N and the constant has Nth or higher bit set, it either always succeeds or always fails. However, the existing implementation only worked with one-hot signals for some reason. It also printed incorrect messages. This commit adjusts the simplification to have as much power as possible, and fixes other bugs. --- passes/opt/opt_expr.cc | 117 ++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 70 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 9abbdc6ac..76bcfd44f 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -259,6 +259,22 @@ bool is_one_or_minus_one(const Const &value, bool is_signed, bool &is_negative) return last_bit_one; } +int get_highest_hot_index(RTLIL::SigSpec signal) +{ + for (int i = GetSize(signal) - 1; i >= 0; i--) + { + if (signal[i] == RTLIL::State::S0) + continue; + + if (signal[i] == RTLIL::State::S1) + return i; + + break; + } + + return -1; +} + // if the signal has only one bit set, return the index of that bit. // otherwise return -1 int get_onehot_bit_index(RTLIL::SigSpec signal) @@ -1345,9 +1361,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } // simplify comparisons - // currently, only replaces comparisons with an extreme of the signal range with a constant - // TODO: since, unlike the following optimization, this one does not assume that both inputs to the cell are constant, - // it is more robust; the following optimization should be folded into this one at some point if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) { IdString cmp_type = cell->type; @@ -1405,29 +1418,53 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons replace = true; } - int const_bit_set = get_onehot_bit_index(const_sig); - if (const_bit_set >= 0 && const_bit_set < var_width) + int const_bit_hot = get_onehot_bit_index(const_sig); + if (const_bit_hot >= 0 && const_bit_hot < var_width) { - RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_set); - for (int i = const_bit_set; i < var_width; i++) { - var_high_sig[i - const_bit_set] = var_sig[i]; + RTLIL::SigSpec var_high_sig(RTLIL::State::S0, var_width - const_bit_hot); + for (int i = const_bit_hot; i < var_width; i++) { + var_high_sig[i - const_bit_hot] = var_sig[i]; } if (cmp_type == "$lt") { condition = stringf("unsigned X<%s", log_signal(const_sig)); - replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_set); + replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot); module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y")); remove = true; } if (cmp_type == "$ge") { condition = stringf("unsigned X>=%s", log_signal(const_sig)); - replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_set); + replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot); module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y")); remove = true; } } + + int const_bit_set = get_highest_hot_index(const_sig); + if(const_bit_set >= var_width) + { + string cmp_name; + if (cmp_type == "$lt" || cmp_type == "$le") + { + if (cmp_type == "$lt") cmp_name = "<"; + if (cmp_type == "$le") cmp_name = "<="; + condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); + replacement = "constant 1"; + replace_sig[0] = State::S1; + replace = true; + } + if (cmp_type == "$gt" || cmp_type == "$ge") + { + if (cmp_type == "$gt") cmp_name = ">"; + if (cmp_type == "$ge") cmp_name = ">="; + condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); + replacement = "constant 0"; + replace_sig[0] = State::S0; + replace = true; + } + } } else { /* signed */ @@ -1460,66 +1497,6 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - // replace a<0 or a>=0 with the top bit of a - if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) - { - //used to decide whether the signal needs to be negated - bool is_lt = false; - - //references the variable signal in the comparison - RTLIL::SigSpec sigVar; - - //references the constant signal in the comparison - RTLIL::SigSpec sigConst; - - // note that this signal must be constant for the optimization - // to take place, but it is not checked beforehand. - // If new passes are added, this signal must be checked for const-ness - - //width of the variable port - int width; - int const_width; - - bool var_signed; - - if (cell->type == "$lt" || cell->type == "$ge") { - is_lt = cell->type == "$lt" ? 1 : 0; - sigVar = cell->getPort("\\A"); - sigConst = cell->getPort("\\B"); - width = cell->parameters["\\A_WIDTH"].as_int(); - const_width = cell->parameters["\\B_WIDTH"].as_int(); - var_signed = cell->parameters["\\A_SIGNED"].as_bool(); - } else - if (cell->type == "$gt" || cell->type == "$le") { - is_lt = cell->type == "$gt" ? 1 : 0; - sigVar = cell->getPort("\\B"); - sigConst = cell->getPort("\\A"); - width = cell->parameters["\\B_WIDTH"].as_int(); - const_width = cell->parameters["\\A_WIDTH"].as_int(); - var_signed = cell->parameters["\\B_SIGNED"].as_bool(); - } else - log_abort(); - - if (sigConst.is_fully_const() && sigConst.is_fully_def() && var_signed == false) - { - int const_bit_set = get_onehot_bit_index(sigConst); - if(const_bit_set >= width && const_bit_set >= 0){ - RTLIL::SigSpec a_prime(RTLIL::State::S0, 1); - if(is_lt){ - a_prime[0] = RTLIL::State::S1; - log("Replacing %s cell `%s' (implementing unsigned X[%d:0] < %s[%d:0]) with constant 0.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); - } - else{ - log("Replacing %s cell `%s' (implementing unsigned X[%d:0]>= %s[%d:0]) with constant 1.\n", log_id(cell->type), log_id(cell), width-1, log_signal(sigConst),const_width-1); - } - module->connect(cell->getPort("\\Y"), a_prime); - module->remove(cell); - did_something = true; - goto next_cell; - } - } - } - next_cell:; #undef ACTION_DO #undef ACTION_DO_Y -- cgit v1.2.3 From 07af772a7279d656564fb23eee457e71cc0d657f Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 2 Jan 2019 14:09:53 +0000 Subject: flowmap: new techmap pass. --- passes/opt/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 0f596b1f4..c3e0a2a40 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -6,12 +6,12 @@ OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_rmdff.o OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_expr.o -OBJS += passes/opt/opt_lut.o ifneq ($(SMALL),1) OBJS += passes/opt/share.o OBJS += passes/opt/wreduce.o OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o +OBJS += passes/opt/opt_lut.o endif -- cgit v1.2.3 From 8a63fc51d31bca50c3d08130c3271a288af1cf4b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 7 Jan 2019 10:01:11 +0100 Subject: Bugfix in $memrd sharing Signed-off-by: Clifford Wolf --- passes/opt/share.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/share.cc b/passes/opt/share.cc index b80280829..c85c27427 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -710,8 +710,12 @@ struct ShareWorker RTLIL::Cell *supercell = module->addCell(NEW_ID, c1); RTLIL::SigSpec addr1 = c1->getPort("\\ADDR"); RTLIL::SigSpec addr2 = c2->getPort("\\ADDR"); - if (addr1 != addr2) - supercell->setPort("\\ADDR", module->Mux(NEW_ID, addr2, addr1, act)); + if (GetSize(addr1) < GetSize(addr2)) + addr1.extend_u0(GetSize(addr2)); + else + addr2.extend_u0(GetSize(addr1)); + supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); + supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1)); supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA"))); supercell_aux.insert(supercell); return supercell; -- cgit v1.2.3 From 246391200e3e0d47ee571d4d77dd0744dba0e164 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 20 Feb 2019 16:36:42 +0100 Subject: Add FF support to wreduce Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 8063b86a6..3aa916ec2 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -38,7 +38,8 @@ struct WreduceConfig "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", "$add", "$sub", "$mul", // "$div", "$mod", "$pow", - "$mux", "$pmux" + "$mux", "$pmux", + "$dff", "$adff" }); } }; @@ -134,6 +135,71 @@ struct WreduceWorker module->connect(sig_y.extract(n_kept, n_removed), sig_removed); } + void run_cell_dff(Cell *cell) + { + // Reduce size of FF if inputs are just sign/zero extended or output bit is not used + + SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); + SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); + + int width_before = GetSize(sig_q); + + if (width_before == 0) + return; + + bool zero_ext = sig_d[GetSize(sig_d)-1] == State::S0; + bool sign_ext = !zero_ext; + + for (int i = GetSize(sig_q)-1; i >= 0; i--) + { + if (zero_ext && sig_d[i] == State::S0) { + 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]) { + module->connect(sig_q[i], sig_q[i-1]); + sig_d.remove(i); + sig_q.remove(i); + continue; + } + + auto info = mi.query(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; + sign_ext = false; + continue; + } + + break; + } + + if (width_before == GetSize(sig_q)) + return; + + if (GetSize(sig_q) == 0) { + log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); + return; + } + + log("Removed top %d bits (of %d) from mux 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) + work_queue_bits.insert(bit); + + for (auto bit : sig_q) + work_queue_bits.insert(bit); + + cell->setPort("\\D", sig_d); + cell->setPort("\\Q", sig_q); + cell->fixup_parameters(); + } + void run_reduce_inport(Cell *cell, char port, int max_port_size, bool &port_signed, bool &did_something) { port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool(); @@ -176,6 +242,9 @@ struct WreduceWorker if (cell->type.in("$mux", "$pmux")) return run_cell_mux(cell); + if (cell->type.in("$dff", "$adff")) + return run_cell_dff(cell); + SigSpec sig = mi.sigmap(cell->getPort("\\Y")); if (sig.has_const()) -- cgit v1.2.3 From 2da4c9c8f0a849434f657ac4a56de11d35e1c41e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 21 Feb 2019 13:48:23 +0100 Subject: Fix opt_rmdff handling of $_DFFSR_???_ and $_DLATCHSR_???_, fixes #816 Signed-off-by: Clifford Wolf --- passes/opt/opt_rmdff.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 5880254c1..e8570f0eb 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -174,8 +174,6 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) cell->unsetParam("\\CLR_POLARITY"); cell->unsetPort("\\SET"); cell->unsetPort("\\CLR"); - - return true; } else { @@ -186,11 +184,12 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) cell->unsetParam("\\CLR_POLARITY"); cell->unsetPort("\\SET"); cell->unsetPort("\\CLR"); - - return true; } + + return true; } - else + + if (!hasreset) { IdString new_type; @@ -207,8 +206,10 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) cell->unsetPort("\\S"); cell->unsetPort("\\R"); - return did_something; + return true; } + + return did_something; } bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) -- cgit v1.2.3 From 25680f6a078bb32f157bd580705656496717bafb Mon Sep 17 00:00:00 2001 From: Keith Rothman <537074+litghost@users.noreply.github.com> Date: Fri, 22 Feb 2019 10:28:28 -0800 Subject: Fix WREDUCE on FF not fixing ARST_VALUE parameter. Adds test case that fails without code change. Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com> --- passes/opt/wreduce.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 3aa916ec2..c550b402e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -195,6 +195,19 @@ struct WreduceWorker for (auto bit : sig_q) work_queue_bits.insert(bit); + // Narrow ARST_VALUE parameter to new size. + // + // Note: This works because earlier loop only removes signals from + // the upper bits of the DFF. + if(cell->parameters.count("\\ARST_VALUE") > 0) { + RTLIL::Const old_arst_value = cell->parameters.at("\\ARST_VALUE"); + std::vector new_arst_value(GetSize(sig_q)); + for(int i = 0; i < GetSize(sig_q); ++i) { + new_arst_value[i] = old_arst_value[i]; + } + cell->parameters["\\ARST_VALUE"] = RTLIL::Const(new_arst_value); + } + cell->setPort("\\D", sig_d); cell->setPort("\\Q", sig_q); cell->fixup_parameters(); -- cgit v1.2.3 From cd722f26a5437e145c02c49b5736bd03b13927da Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 24 Feb 2019 20:34:23 +0100 Subject: Cleanups in ARST handling in wreduce Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index c550b402e..09983bc67 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -196,16 +196,10 @@ struct WreduceWorker work_queue_bits.insert(bit); // Narrow ARST_VALUE parameter to new size. - // - // Note: This works because earlier loop only removes signals from - // the upper bits of the DFF. - if(cell->parameters.count("\\ARST_VALUE") > 0) { - RTLIL::Const old_arst_value = cell->parameters.at("\\ARST_VALUE"); - std::vector new_arst_value(GetSize(sig_q)); - for(int i = 0; i < GetSize(sig_q); ++i) { - new_arst_value[i] = old_arst_value[i]; - } - cell->parameters["\\ARST_VALUE"] = RTLIL::Const(new_arst_value); + if (cell->parameters.count("\\ARST_VALUE")) { + Const arst_value = cell->getParam("\\ARST_VALUE"); + arst_value.bits.resize(GetSize(sig_q)); + cell->setParam("\\ARST_VALUE", arst_value); } cell->setPort("\\D", sig_d); -- cgit v1.2.3 From e847690bda520511735680bd4cb65b416edcdc3f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 28 Feb 2019 17:24:46 -0800 Subject: Fix multiple issues in wreduce FF handling, fixes #835 Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'passes/opt') 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> work_queue_cells; std::set work_queue_bits; pool keep_bits; + dict 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); -- cgit v1.2.3 From f806b95ed6a2f2c1a0e5c8884676fd384e510143 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Mar 2019 20:35:15 +0100 Subject: Improve handling of and-with-1 and or-with-0 in opt_expr, fixes #327 Signed-off-by: Clifford Wolf --- passes/opt/opt_expr.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 26a3ca7bc..a05db2a4f 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -155,6 +155,13 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ new_b.append_bit(it.first.second); } + if (cell->type.in("$and", "$or") && i == GRP_CONST_A) { + log(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); + module->connect(new_y, new_b); + module->connect(new_conn); + continue; + } + RTLIL::Cell *c = module->addCell(NEW_ID, cell->type); c->setPort("\\A", new_a); -- cgit v1.2.3 From 7cfd83c3415dd3d576539e00b91b6e283997fe52 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 22 Mar 2019 11:42:19 +0100 Subject: Trim init attributes when resizing FFs in "wreduce", fixes #887 Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1f7222e49..52245ce3e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -54,6 +54,7 @@ struct WreduceWorker std::set work_queue_bits; pool keep_bits; dict init_bits; + pool remove_init_bits; WreduceWorker(WreduceConfig *config, Module *module) : config(config), module(module), mi(module) { } @@ -164,6 +165,7 @@ struct WreduceWorker { if (zero_ext && sig_d[i] == State::S0 && (initval[i] == State::S0 || initval[i] == State::Sx)) { module->connect(sig_q[i], State::S0); + remove_init_bits.insert(sig_q[i]); sig_d.remove(i); sig_q.remove(i); continue; @@ -171,6 +173,7 @@ struct WreduceWorker 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]); + remove_init_bits.insert(sig_q[i]); sig_d.remove(i); sig_q.remove(i); continue; @@ -178,6 +181,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]))) { + remove_init_bits.insert(sig_q[i]); sig_d.remove(i); sig_q.remove(i); zero_ext = false; @@ -387,13 +391,16 @@ struct WreduceWorker void run() { + // create a copy as mi.sigmap will be updated as we process the module + SigMap init_attr_sigmap = mi.sigmap; + 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); + SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) init_bits[initsig[i]] = initval[i]; @@ -446,6 +453,24 @@ struct WreduceWorker module->connect(nw, SigSpec(w).extract(0, GetSize(nw))); module->swap_names(w, nw); } + + if (!remove_init_bits.empty()) { + for (auto w : module->wires()) { + if (w->attributes.count("\\init")) { + Const initval = w->attributes.at("\\init"); + Const new_initval(State::Sx, GetSize(w)); + SigSpec initsig = init_attr_sigmap(w); + int width = std::min(GetSize(initval), GetSize(initsig)); + for (int i = 0; i < width; i++) { + log_dump(initsig[i], remove_init_bits.count(initsig[i])); + if (!remove_init_bits.count(initsig[i])) + new_initval[i] = initval[i]; + } + w->attributes.at("\\init") = new_initval; + log_dump(w->name, initval, new_initval); + } + } + } } }; -- cgit v1.2.3 From 1bf8c2b823992569830cf0d248cb12bfccd5f384 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Apr 2019 14:03:05 +0200 Subject: Import initial pmux2shiftx from eddieh Signed-off-by: Clifford Wolf --- passes/opt/Makefile.inc | 1 + passes/opt/pmux2shiftx.cc | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 passes/opt/pmux2shiftx.cc (limited to 'passes/opt') diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index c3e0a2a40..337fee9e4 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -13,5 +13,6 @@ OBJS += passes/opt/wreduce.o OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o OBJS += passes/opt/opt_lut.o +OBJS += passes/opt/pmux2shiftx.o endif diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc new file mode 100644 index 000000000..6ffc27a4c --- /dev/null +++ b/passes/opt/pmux2shiftx.cc @@ -0,0 +1,81 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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 Pmux2ShiftxPass : public Pass { + Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" pmux2shiftx [selection]\n"); + log("\n"); + log("This pass transforms $pmux cells to $shiftx cells.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing PMUX2SHIFTX pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + for (auto cell : module->selected_cells()) + { + if (cell->type != "$pmux") + continue; + + // Create a new encoder, out of a $pmux, that takes + // the existing pmux's 'S' input and transforms it + // back into a binary value + RTLIL::SigSpec shiftx_a; + RTLIL::SigSpec pmux_s; + + int s_width = cell->getParam("\\S_WIDTH").as_int(); + if (!cell->getPort("\\A").is_fully_undef()) { + ++s_width; + shiftx_a.append(cell->getPort("\\A")); + pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); + } + const int clog2width = ceil(log2(s_width)); + + RTLIL::SigSpec pmux_b; + for (int i = s_width-1; i >= 0; i--) + pmux_b.append(RTLIL::Const(i, clog2width)); + shiftx_a.append(cell->getPort("\\B")); + pmux_s.append(cell->getPort("\\S")); + + RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); + module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); + module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); + module->remove(cell); + } + } +} Pmux2ShiftxPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 481f0015be48e7662f6fc55ca8bbb46c51829ccb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Apr 2019 18:10:12 +0200 Subject: Complete rewrite of pmux2shiftx Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 292 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 265 insertions(+), 27 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 6ffc27a4c..8ea70fe84 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -45,35 +45,273 @@ struct Pmux2ShiftxPass : public Pass { extra_args(args, argidx, design); for (auto module : design->selected_modules()) - for (auto cell : module->selected_cells()) { - if (cell->type != "$pmux") - continue; - - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - RTLIL::SigSpec shiftx_a; - RTLIL::SigSpec pmux_s; - - int s_width = cell->getParam("\\S_WIDTH").as_int(); - if (!cell->getPort("\\A").is_fully_undef()) { - ++s_width; - shiftx_a.append(cell->getPort("\\A")); - pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); + SigMap sigmap(module); + + dict> eqdb; + + for (auto cell : module->selected_cells()) + { + if (cell->type == "$eq") + { + dict bits; + + SigSpec A = sigmap(cell->getPort("\\A")); + SigSpec B = sigmap(cell->getPort("\\B")); + + int a_width = cell->getParam("\\A_WIDTH").as_int(); + int b_width = cell->getParam("\\B_WIDTH").as_int(); + + if (a_width < b_width) { + bool a_signed = cell->getParam("\\A_SIGNED").as_int(); + A.extend_u0(b_width, a_signed); + } + + if (b_width < a_width) { + bool b_signed = cell->getParam("\\B_SIGNED").as_int(); + B.extend_u0(a_width, b_signed); + } + + for (int i = 0; i < GetSize(A); i++) { + SigBit a_bit = A[i], b_bit = B[i]; + if (b_bit.wire && !a_bit.wire) { + std::swap(a_bit, b_bit); + } + if (!a_bit.wire || b_bit.wire) + goto next_cell; + if (bits.count(a_bit)) + goto next_cell; + bits[a_bit] = b_bit.data; + } + + if (GetSize(bits) > 20) + goto next_cell; + + bits.sort(); + pair entry; + + for (auto it : bits) { + entry.first.append_bit(it.first); + entry.second.bits.push_back(it.second); + } + + eqdb[sigmap(cell->getPort("\\Y")[0])] = entry; + goto next_cell; + } + + if (cell->type == "$logic_not") + { + dict bits; + + SigSpec A = sigmap(cell->getPort("\\A")); + + for (int i = 0; i < GetSize(A); i++) + bits[A[i]] = State::S0; + + bits.sort(); + pair entry; + + for (auto it : bits) { + entry.first.append_bit(it.first); + entry.second.bits.push_back(it.second); + } + + eqdb[sigmap(cell->getPort("\\Y")[0])] = entry; + goto next_cell; + } + next_cell:; + } + + for (auto cell : module->selected_cells()) + { + if (cell->type != "$pmux") + continue; + + string src = cell->get_src_attribute(); + int width = cell->getParam("\\WIDTH").as_int(); + int width_bits = ceil_log2(width); + int extwidth = width; + + while (extwidth & (extwidth-1)) + extwidth++; + + dict> seldb; + + SigSpec S = sigmap(cell->getPort("\\S")); + for (int i = 0; i < GetSize(S); i++) + { + if (!eqdb.count(S[i])) + continue; + + auto &entry = eqdb.at(S[i]); + seldb[entry.first].insert(i); + } + + if (seldb.empty()) + continue; + + log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); + + SigSpec updated_S = cell->getPort("\\S"); + SigSpec updated_B = cell->getPort("\\B"); + + #if 1 + for (auto &it : seldb) { + string msg = stringf("seldb: %s ->", log_signal(it.first)); + for (int i : it.second) + msg += stringf(" %d(%s)", i, log_signal(eqdb.at(S[i]).second)); + log(" %s\n", msg.c_str()); + } + #endif + + while (!seldb.empty()) + { + // pick the largest entry in seldb + SigSpec sig = seldb.begin()->first; + for (auto &it : seldb) { + if (GetSize(sig) < GetSize(it.first)) + sig = it.first; + else if (GetSize(seldb.at(sig)) < GetSize(it.second)) + sig = it.first; + } + + log(" checking ctrl signal %s\n", log_signal(sig)); + + // find the relevant choices + dict choices; + vector onescnt(GetSize(sig)); + for (int i : seldb.at(sig)) { + Const val = eqdb.at(S[i]).second; + choices[val] = i; + for (int k = 0; k < GetSize(val); k++) + if (val[k] == State::S1) + onescnt[k] |= 1; + else + onescnt[k] |= 2; + } + + // TBD: also find choices that are using signals that are subsets of the bits in "sig" + + // find the best permutation + vector> perm(GetSize(sig)); + for (int i = 0; i < GetSize(onescnt); i++) + perm[i] = make_pair(onescnt[i], i); + // TBD: this is not the best permutation + std::sort(perm.rbegin(), perm.rend()); + + // permutated sig + Const perm_xormask(State::S0, GetSize(sig)); + SigSpec perm_sig(State::S0, GetSize(sig)); + for (int i = 0; i < GetSize(sig); i++) { + if (perm[i].first == 1) + perm_xormask[i] = State::S1; + perm_sig[i] = sig[perm[i].second]; + } + + log(" best permutation: %s\n", log_signal(perm_sig)); + log(" best xor mask: %s\n", log_signal(perm_xormask)); + + // permutated choices + int min_choice = 1 << 30; + int max_choice = -1; + dict perm_choices; + + for (auto &it : choices) + { + Const &old_c = it.first; + Const new_c(State::S0, GetSize(old_c)); + + for (int i = 0; i < GetSize(old_c); i++) + new_c[i] = old_c[perm[i].second]; + + Const new_c_before_xor = new_c; + new_c = const_xor(new_c, perm_xormask, false, false, GetSize(new_c)); + + perm_choices[new_c] = it.second; + + min_choice = std::min(min_choice, new_c.as_int()); + max_choice = std::max(max_choice, new_c.as_int()); + + log(" %s -> %s -> %s\n", log_signal(old_c), log_signal(new_c_before_xor), log_signal(new_c)); + } + + log(" choices: %d\n", GetSize(choices)); + log(" min choice: %d\n", min_choice); + log(" max choice: %d\n", max_choice); + log(" range density: %d%%\n", 100*GetSize(choices)/(max_choice-min_choice+1)); + log(" absolute density: %d%%\n", 100*GetSize(choices)/(max_choice+1)); + + bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices)); + log(" full case: %s\n", full_case ? "true" : "false"); + + // use arithmetic offset if density is less than 30% + Const offset(State::S0, GetSize(sig)); + if (3*GetSize(choices) < max_choice && 3*GetSize(choices) >= (max_choice-min_choice)) + { + log(" using offset method.\n"); + + offset = Const(min_choice, GetSize(sig)); + min_choice -= offset.as_int(); + max_choice -= offset.as_int(); + + dict new_perm_choices; + for (auto &it : perm_choices) + new_perm_choices[const_sub(it.first, offset, false, false, GetSize(sig))] = it.second; + perm_choices.swap(new_perm_choices); + } + + // ignore cases with a absolute density of less than 30% + if (3*GetSize(choices) < max_choice) { + log(" insufficient density.\n"); + seldb.erase(sig); + continue; + } + + // creat cmp signal + SigSpec cmp = perm_sig; + if (perm_xormask.as_bool()) + cmp = module->Xor(NEW_ID, cmp, perm_xormask, false, src); + if (offset.as_bool()) + cmp = module->Sub(NEW_ID, cmp, offset, false, src); + + // create enable signal + SigBit en = State::S1; + if (!full_case) { + Const enable_mask(State::S0, max_choice+1); + for (auto &it : perm_choices) + enable_mask[it.first.as_int()] = State::S1; + en = module->addWire(NEW_ID); + module->addShift(NEW_ID, enable_mask, cmp, en, false, src); + } + + // create data signal + SigSpec data(State::Sx, (max_choice+1)*extwidth); + for (auto &it : perm_choices) { + int position = it.first.as_int()*extwidth; + int data_index = it.second; + data.replace(position, cell->getPort("\\B").extract(data_index*width, width)); + updated_S[data_index] = State::S0; + updated_B.replace(data_index*width, SigSpec(State::Sx, width)); + } + + // create shiftx cell + SigSpec shifted_cmp = {cmp, SigSpec(State::S0, width_bits)}; + SigSpec outsig = module->addWire(NEW_ID, width); + Cell *c = module->addShiftx(NEW_ID, data, shifted_cmp, outsig, false, src); + updated_S.append(en); + updated_B.append(outsig); + log(" created $shiftx cell %s.\n", log_id(c)); + + // remove this sig and continue with the next block + seldb.erase(sig); + } + + // update $pmux cell + cell->setPort("\\S", updated_S); + cell->setPort("\\B", updated_B); + cell->setParam("\\S_WIDTH", GetSize(updated_S)); } - const int clog2width = ceil(log2(s_width)); - - RTLIL::SigSpec pmux_b; - for (int i = s_width-1; i >= 0; i--) - pmux_b.append(RTLIL::Const(i, clog2width)); - shiftx_a.append(cell->getPort("\\B")); - pmux_s.append(cell->getPort("\\S")); - - RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); - module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); - module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); - module->remove(cell); } } } Pmux2ShiftxPass; -- cgit v1.2.3 From 177878cbb091f9339ee68a904f57f0283bdcfe10 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Apr 2019 20:20:08 +0200 Subject: Improve pmux2shift ctrl permutation finder Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 141 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 114 insertions(+), 27 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 8ea70fe84..daa73b0b8 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -29,17 +29,29 @@ struct Pmux2ShiftxPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" pmux2shiftx [selection]\n"); + log(" pmux2shiftx [options] [selection]\n"); log("\n"); log("This pass transforms $pmux cells to $shiftx cells.\n"); log("\n"); + log(" -density non_offset_percentage offset_percentage\n"); + log(" specifies the minimum density for non_offset- and for offset-mode\n"); + log(" default values are 30 (non-offset) and 50 (offset)\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { + int non_offset_percentage = 30; + int offset_percentage = 50; + log_header(design, "Executing PMUX2SHIFTX pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-density" && argidx+2 < args.size()) { + non_offset_percentage = atoi(args[++argidx].c_str()); + offset_percentage = atoi(args[++argidx].c_str()); + continue; + } break; } extra_args(args, argidx, design); @@ -180,34 +192,108 @@ struct Pmux2ShiftxPass : public Pass { // find the relevant choices dict choices; - vector onescnt(GetSize(sig)); for (int i : seldb.at(sig)) { Const val = eqdb.at(S[i]).second; choices[val] = i; - for (int k = 0; k < GetSize(val); k++) - if (val[k] == State::S1) - onescnt[k] |= 1; - else - onescnt[k] |= 2; } // TBD: also find choices that are using signals that are subsets of the bits in "sig" // find the best permutation - vector> perm(GetSize(sig)); - for (int i = 0; i < GetSize(onescnt); i++) - perm[i] = make_pair(onescnt[i], i); - // TBD: this is not the best permutation - std::sort(perm.rbegin(), perm.rend()); + vector perm_new_from_old(GetSize(sig)); + Const perm_xormask(State::S0, GetSize(sig)); + { + vector values(GetSize(choices)); + vector used_src_columns(GetSize(sig)); + vector> columns(GetSize(sig), vector(GetSize(values))); + + for (int i = 0; i < GetSize(choices); i++) { + Const val = choices.element(i)->first; + for (int k = 0; k < GetSize(val); k++) + if (val[k] == State::S1) + columns[k][i] = true; + } + + for (int dst_col = GetSize(sig)-1; dst_col >= 0; dst_col--) + { + int best_src_col = -1; + bool best_inv = false; + int best_maxval = 0; + int best_delta = 0; + + // find best src colum for this dst column + for (int src_col = 0; src_col < GetSize(sig); src_col++) + { + if (used_src_columns[src_col]) + continue; + + int this_maxval = 0; + int this_minval = 1 << 30; + + int this_inv_maxval = 0; + int this_inv_minval = 1 << 30; + + for (int i = 0; i < GetSize(values); i++) + { + int val = values[i]; + int inv_val = val; + + if (columns[src_col][i]) + val |= 1 << dst_col; + else + inv_val |= 1 << dst_col; + + this_maxval = std::max(this_maxval, val); + this_minval = std::min(this_minval, val); + + this_inv_maxval = std::max(this_inv_maxval, inv_val); + this_inv_minval = std::min(this_inv_minval, inv_val); + } + + int this_delta = this_maxval - this_minval; + int this_inv_delta = this_maxval - this_minval; + bool this_inv = false; + + if (this_delta != this_inv_delta) + this_inv = this_inv_delta < this_delta; + else if (this_maxval != this_inv_maxval) + this_inv = this_inv_maxval < this_maxval; + + if (this_inv) { + this_delta = this_inv_delta; + this_maxval = this_inv_maxval; + this_minval = this_inv_minval; + } + + bool this_is_better = false; + + if (best_src_col < 0) + this_is_better = true; + else if (this_delta != best_delta) + this_is_better = this_delta < best_delta; + else if (this_maxval != best_maxval) + this_is_better = this_maxval < best_maxval; + else + this_is_better = sig[best_src_col] < sig[src_col]; + + if (this_is_better) { + best_src_col = src_col; + best_inv = this_inv; + best_maxval = this_maxval; + best_delta = this_delta; + } + } + + used_src_columns[best_src_col] = true; + perm_new_from_old[dst_col] = best_src_col; + perm_xormask[dst_col] = best_inv ? State::S1 : State::S0; + } + } // permutated sig - Const perm_xormask(State::S0, GetSize(sig)); SigSpec perm_sig(State::S0, GetSize(sig)); - for (int i = 0; i < GetSize(sig); i++) { - if (perm[i].first == 1) - perm_xormask[i] = State::S1; - perm_sig[i] = sig[perm[i].second]; - } + for (int i = 0; i < GetSize(sig); i++) + perm_sig[i] = sig[perm_new_from_old[i]]; log(" best permutation: %s\n", log_signal(perm_sig)); log(" best xor mask: %s\n", log_signal(perm_xormask)); @@ -223,7 +309,7 @@ struct Pmux2ShiftxPass : public Pass { Const new_c(State::S0, GetSize(old_c)); for (int i = 0; i < GetSize(old_c); i++) - new_c[i] = old_c[perm[i].second]; + new_c[i] = old_c[perm_new_from_old[i]]; Const new_c_before_xor = new_c; new_c = const_xor(new_c, perm_xormask, false, false, GetSize(new_c)); @@ -236,18 +322,21 @@ struct Pmux2ShiftxPass : public Pass { log(" %s -> %s -> %s\n", log_signal(old_c), log_signal(new_c_before_xor), log_signal(new_c)); } + int range_density = 100*GetSize(choices) / (max_choice-min_choice+1); + int absolute_density = 100*GetSize(choices) / (max_choice+1); + log(" choices: %d\n", GetSize(choices)); log(" min choice: %d\n", min_choice); log(" max choice: %d\n", max_choice); - log(" range density: %d%%\n", 100*GetSize(choices)/(max_choice-min_choice+1)); - log(" absolute density: %d%%\n", 100*GetSize(choices)/(max_choice+1)); + log(" range density: %d%%\n", range_density); + log(" absolute density: %d%%\n", absolute_density); bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices)); log(" full case: %s\n", full_case ? "true" : "false"); - // use arithmetic offset if density is less than 30% + // check density percentages Const offset(State::S0, GetSize(sig)); - if (3*GetSize(choices) < max_choice && 3*GetSize(choices) >= (max_choice-min_choice)) + if (absolute_density < non_offset_percentage && range_density >= offset_percentage) { log(" using offset method.\n"); @@ -259,10 +348,8 @@ struct Pmux2ShiftxPass : public Pass { for (auto &it : perm_choices) new_perm_choices[const_sub(it.first, offset, false, false, GetSize(sig))] = it.second; perm_choices.swap(new_perm_choices); - } - - // ignore cases with a absolute density of less than 30% - if (3*GetSize(choices) < max_choice) { + } else + if (absolute_density < non_offset_percentage) { log(" insufficient density.\n"); seldb.erase(sig); continue; -- cgit v1.2.3 From 0070184ea9dea56d1dfd8268035bc01a3e340add Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 19 Apr 2019 23:37:11 +0200 Subject: Improvements in pmux2shiftx Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index daa73b0b8..d0f41cb07 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -149,6 +149,7 @@ struct Pmux2ShiftxPass : public Pass { dict> seldb; + SigSpec B = cell->getPort("\\B"); SigSpec S = sigmap(cell->getPort("\\S")); for (int i = 0; i < GetSize(S); i++) { @@ -168,15 +169,6 @@ struct Pmux2ShiftxPass : public Pass { SigSpec updated_S = cell->getPort("\\S"); SigSpec updated_B = cell->getPort("\\B"); - #if 1 - for (auto &it : seldb) { - string msg = stringf("seldb: %s ->", log_signal(it.first)); - for (int i : it.second) - msg += stringf(" %d(%s)", i, log_signal(eqdb.at(S[i]).second)); - log(" %s\n", msg.c_str()); - } - #endif - while (!seldb.empty()) { // pick the largest entry in seldb @@ -319,7 +311,8 @@ struct Pmux2ShiftxPass : public Pass { min_choice = std::min(min_choice, new_c.as_int()); max_choice = std::max(max_choice, new_c.as_int()); - log(" %s -> %s -> %s\n", log_signal(old_c), log_signal(new_c_before_xor), log_signal(new_c)); + log(" %3d: %s -> %s -> %s: %s\n", it.second, log_signal(old_c), log_signal(new_c_before_xor), + log_signal(new_c), log_signal(B.extract(it.second*width, width))); } int range_density = 100*GetSize(choices) / (max_choice-min_choice+1); @@ -338,9 +331,9 @@ struct Pmux2ShiftxPass : public Pass { Const offset(State::S0, GetSize(sig)); if (absolute_density < non_offset_percentage && range_density >= offset_percentage) { - log(" using offset method.\n"); - offset = Const(min_choice, GetSize(sig)); + log(" offset: %s\n", log_signal(offset)); + min_choice -= offset.as_int(); max_choice -= offset.as_int(); @@ -377,7 +370,7 @@ struct Pmux2ShiftxPass : public Pass { for (auto &it : perm_choices) { int position = it.first.as_int()*extwidth; int data_index = it.second; - data.replace(position, cell->getPort("\\B").extract(data_index*width, width)); + data.replace(position, B.extract(data_index*width, width)); updated_S[data_index] = State::S0; updated_B.replace(data_index*width, SigSpec(State::Sx, width)); } -- cgit v1.2.3 From 37728520a6d559a9f9a0082ddb3d596e8a634d97 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 01:15:48 +0200 Subject: Improvements in "pmux2shiftx" Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 64 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 12 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index d0f41cb07..e6a0bd06b 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -33,23 +33,41 @@ struct Pmux2ShiftxPass : public Pass { log("\n"); log("This pass transforms $pmux cells to $shiftx cells.\n"); log("\n"); - log(" -density non_offset_percentage offset_percentage\n"); + log(" -min_density \n"); log(" specifies the minimum density for non_offset- and for offset-mode\n"); log(" default values are 30 (non-offset) and 50 (offset)\n"); log("\n"); + log(" -min_choices \n"); + log(" specified the minimum number of choices for a control signal\n"); + log(" defaukt: 3\n"); + log("\n"); + log(" -allow_onehot\n"); + log(" by default, pmuxes with one-hot encoded control signals are not\n"); + log(" converted. this option disables that check.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - int non_offset_percentage = 30; - int offset_percentage = 50; + int min_non_offset_percentage = 30; + int min_offset_percentage = 50; + int min_choices = 3; + bool allow_onehot = false; log_header(design, "Executing PMUX2SHIFTX pass.\n"); size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-density" && argidx+2 < args.size()) { - non_offset_percentage = atoi(args[++argidx].c_str()); - offset_percentage = atoi(args[++argidx].c_str()); + if (args[argidx] == "-min_density" && argidx+2 < args.size()) { + min_non_offset_percentage = atoi(args[++argidx].c_str()); + min_offset_percentage = atoi(args[++argidx].c_str()); + continue; + } + if (args[argidx] == "-min_choices" && argidx+1 < args.size()) { + min_choices = atoi(args[++argidx].c_str()); + continue; + } + if (args[argidx] == "-allow_onehot") { + allow_onehot = true; continue; } break; @@ -163,8 +181,7 @@ struct Pmux2ShiftxPass : public Pass { if (seldb.empty()) continue; - log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); - log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); + bool printed_pmux_header = false; SigSpec updated_S = cell->getPort("\\S"); SigSpec updated_B = cell->getPort("\\B"); @@ -180,17 +197,40 @@ struct Pmux2ShiftxPass : public Pass { sig = it.first; } - log(" checking ctrl signal %s\n", log_signal(sig)); - // find the relevant choices + bool is_onehot = true; dict choices; for (int i : seldb.at(sig)) { Const val = eqdb.at(S[i]).second; + int onebits = 0; + for (auto b : val.bits) + if (b == State::S1) + onebits++; + if (onebits > 1) + is_onehot = false; choices[val] = i; } // TBD: also find choices that are using signals that are subsets of the bits in "sig" + if (is_onehot && !allow_onehot) { + seldb.erase(sig); + continue; + } + + if (GetSize(choices) < min_choices) { + seldb.erase(sig); + continue; + } + + if (!printed_pmux_header) { + printed_pmux_header = true; + log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); + } + + log(" checking ctrl signal %s\n", log_signal(sig)); + // find the best permutation vector perm_new_from_old(GetSize(sig)); Const perm_xormask(State::S0, GetSize(sig)); @@ -329,7 +369,7 @@ struct Pmux2ShiftxPass : public Pass { // check density percentages Const offset(State::S0, GetSize(sig)); - if (absolute_density < non_offset_percentage && range_density >= offset_percentage) + if (absolute_density < min_non_offset_percentage && range_density >= min_offset_percentage) { offset = Const(min_choice, GetSize(sig)); log(" offset: %s\n", log_signal(offset)); @@ -342,7 +382,7 @@ struct Pmux2ShiftxPass : public Pass { new_perm_choices[const_sub(it.first, offset, false, false, GetSize(sig))] = it.second; perm_choices.swap(new_perm_choices); } else - if (absolute_density < non_offset_percentage) { + if (absolute_density < min_non_offset_percentage) { log(" insufficient density.\n"); seldb.erase(sig); continue; -- cgit v1.2.3 From e06d158e8a3ae3626fbf82b3a8c6764f05111513 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 01:18:07 +0200 Subject: Fix some typos Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index e6a0bd06b..dbcdff3d8 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -39,7 +39,7 @@ struct Pmux2ShiftxPass : public Pass { log("\n"); log(" -min_choices \n"); log(" specified the minimum number of choices for a control signal\n"); - log(" defaukt: 3\n"); + log(" default: 3\n"); log("\n"); log(" -allow_onehot\n"); log(" by default, pmuxes with one-hot encoded control signals are not\n"); @@ -253,7 +253,7 @@ struct Pmux2ShiftxPass : public Pass { int best_maxval = 0; int best_delta = 0; - // find best src colum for this dst column + // find best src column for this dst column for (int src_col = 0; src_col < GetSize(sig); src_col++) { if (used_src_columns[src_col]) -- cgit v1.2.3 From b3a3e08e389c8d10fbd8e0dc8b48e1e559dedf5d Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 02:03:44 +0200 Subject: Improve "pmux2shiftx" Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index dbcdff3d8..4cd061c68 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -33,9 +33,9 @@ struct Pmux2ShiftxPass : public Pass { log("\n"); log("This pass transforms $pmux cells to $shiftx cells.\n"); log("\n"); - log(" -min_density \n"); - log(" specifies the minimum density for non_offset- and for offset-mode\n"); - log(" default values are 30 (non-offset) and 50 (offset)\n"); + log(" -min_density \n"); + log(" specifies the minimum density for the shifter\n"); + log(" default: 50\n"); log("\n"); log(" -min_choices \n"); log(" specified the minimum number of choices for a control signal\n"); @@ -48,8 +48,7 @@ struct Pmux2ShiftxPass : public Pass { } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { - int min_non_offset_percentage = 30; - int min_offset_percentage = 50; + int min_density = 50; int min_choices = 3; bool allow_onehot = false; @@ -57,9 +56,8 @@ struct Pmux2ShiftxPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - if (args[argidx] == "-min_density" && argidx+2 < args.size()) { - min_non_offset_percentage = atoi(args[++argidx].c_str()); - min_offset_percentage = atoi(args[++argidx].c_str()); + if (args[argidx] == "-min_density" && argidx+1 < args.size()) { + min_density = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-min_choices" && argidx+1 < args.size()) { @@ -369,7 +367,7 @@ struct Pmux2ShiftxPass : public Pass { // check density percentages Const offset(State::S0, GetSize(sig)); - if (absolute_density < min_non_offset_percentage && range_density >= min_offset_percentage) + if (absolute_density < min_density && range_density >= min_density) { offset = Const(min_choice, GetSize(sig)); log(" offset: %s\n", log_signal(offset)); @@ -382,7 +380,7 @@ struct Pmux2ShiftxPass : public Pass { new_perm_choices[const_sub(it.first, offset, false, false, GetSize(sig))] = it.second; perm_choices.swap(new_perm_choices); } else - if (absolute_density < min_non_offset_percentage) { + if (absolute_density < min_density) { log(" insufficient density.\n"); seldb.erase(sig); continue; -- cgit v1.2.3 From 97e9caa4fa1f874b693a9d948f48418f22babb6c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 17:52:16 +0200 Subject: Add "onehot" pass, improve "pmux2shiftx" onehot handling Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 417 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 404 insertions(+), 13 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 4cd061c68..5fd49a571 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -23,6 +23,172 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct OnehotDatabase +{ + Module *module; + const SigMap &sigmap; + bool verbose = false; + + pool init_ones; + dict> sig_sources_db; + dict sig_onehot_cache; + pool recursion_guard; + + OnehotDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) + { + } + + void initialize() + { + for (auto wire : module->wires()) + { + auto it = wire->attributes.find("\\init"); + if (it == wire->attributes.end()) + continue; + + auto &val = it->second; + int width = std::max(GetSize(wire), GetSize(val)); + + for (int i = 0; i < width; i++) + if (val[i] == State::S1) + init_ones.insert(sigmap(SigBit(wire, i))); + } + + for (auto cell : module->cells()) + { + vector inputs; + SigSpec output; + + if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff")) + { + output = cell->getPort("\\Q"); + if (cell->type == "$adff") + inputs.push_back(cell->getParam("\\ARST_VALUE")); + inputs.push_back(cell->getPort("\\D")); + } + + if (cell->type.in("$mux", "$pmux")) + { + output = cell->getPort("\\Y"); + inputs.push_back(cell->getPort("\\A")); + SigSpec B = cell->getPort("\\B"); + for (int i = 0; i < GetSize(B); i += GetSize(output)) + inputs.push_back(B.extract(i, GetSize(output))); + } + + if (!output.empty()) + { + output = sigmap(output); + auto &srcs = sig_sources_db[output]; + for (auto src : inputs) { + while (!src.empty() && src[GetSize(src)-1] == State::S0) + src.remove(GetSize(src)-1); + srcs.insert(sigmap(src)); + } + } + } + } + + void query_worker(const SigSpec &sig, bool &retval, bool &cache, int indent) + { + if (verbose) + log("%*s %s\n", indent, "", log_signal(sig)); + log_assert(retval); + + if (recursion_guard.count(sig)) { + if (verbose) + log("%*s - recursion\n", indent, ""); + cache = false; + return; + } + + auto it = sig_onehot_cache.find(sig); + if (it != sig_onehot_cache.end()) { + if (verbose) + log("%*s - cached (%s)\n", indent, "", it->second ? "true" : "false"); + if (!it->second) + retval = false; + return; + } + + bool found_init_ones = false; + for (auto bit : sig) { + if (init_ones.count(bit)) { + if (found_init_ones) { + if (verbose) + log("%*s - non-onehot init value\n", indent, ""); + retval = false; + break; + } + found_init_ones = true; + } + } + + if (retval) + { + if (sig.is_fully_const()) + { + bool found_ones = false; + for (auto bit : sig) { + if (bit == State::S1) { + if (found_ones) { + if (verbose) + log("%*s - non-onehot constant\n", indent, ""); + retval = false; + break; + } + found_ones = true; + } + } + } + else + { + auto srcs = sig_sources_db.find(sig); + if (srcs == sig_sources_db.end()) { + if (verbose) + log("%*s - no sources for non-const signal\n", indent, ""); + retval = false; + } else { + for (auto &src : srcs->second) { + bool child_cache = true; + recursion_guard.insert(sig); + query_worker(src, retval, child_cache, indent+4); + recursion_guard.erase(sig); + if (!child_cache) + cache = false; + if (!retval) + break; + } + } + } + } + + // it is always safe to cache a negative result + if (cache || !retval) + sig_onehot_cache[sig] = retval; + } + + bool query(const SigSpec &sig) + { + bool retval = true; + bool cache = true; + + if (verbose) + log("** ONEHOT QUERY START (%s)\n", log_signal(sig)); + + query_worker(sig, retval, cache, 3); + + if (verbose) + log("** ONEHOT QUERY RESULT = %s\n", retval ? "true" : "false"); + + // it is always safe to cache the root result of a query + if (!cache) + sig_onehot_cache[sig] = retval; + + return retval; + } +}; + struct Pmux2ShiftxPass : public Pass { Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } void help() YS_OVERRIDE @@ -33,6 +199,9 @@ struct Pmux2ShiftxPass : public Pass { log("\n"); log("This pass transforms $pmux cells to $shiftx cells.\n"); log("\n"); + log(" -v, -vv\n"); + log(" verbose output\n"); + log("\n"); log(" -min_density \n"); log(" specifies the minimum density for the shifter\n"); log(" default: 50\n"); @@ -41,9 +210,9 @@ struct Pmux2ShiftxPass : public Pass { log(" specified the minimum number of choices for a control signal\n"); log(" default: 3\n"); log("\n"); - log(" -allow_onehot\n"); - log(" by default, pmuxes with one-hot encoded control signals are not\n"); - log(" converted. this option disables that check.\n"); + log(" -onehot ignore|pmux|shiftx\n"); + log(" select strategy for one-hot encoded control signals\n"); + log(" default: pmux\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE @@ -51,6 +220,9 @@ struct Pmux2ShiftxPass : public Pass { int min_density = 50; int min_choices = 3; bool allow_onehot = false; + bool optimize_onehot = true; + bool verbose = false; + bool verbose_onehot = false; log_header(design, "Executing PMUX2SHIFTX pass.\n"); @@ -64,8 +236,31 @@ struct Pmux2ShiftxPass : public Pass { min_choices = atoi(args[++argidx].c_str()); continue; } - if (args[argidx] == "-allow_onehot") { + if (args[argidx] == "-onehot" && argidx+1 < args.size() && args[argidx+1] == "ignore") { + argidx++; + allow_onehot = false; + optimize_onehot = false; + continue; + } + if (args[argidx] == "-onehot" && argidx+1 < args.size() && args[argidx+1] == "pmux") { + argidx++; + allow_onehot = false; + optimize_onehot = true; + continue; + } + if (args[argidx] == "-onehot" && argidx+1 < args.size() && args[argidx+1] == "shiftx") { + argidx++; allow_onehot = true; + optimize_onehot = false; + continue; + } + if (args[argidx] == "-v") { + verbose = true; + continue; + } + if (args[argidx] == "-vv") { + verbose = true; + verbose_onehot = true; continue; } break; @@ -75,10 +270,15 @@ struct Pmux2ShiftxPass : public Pass { for (auto module : design->selected_modules()) { SigMap sigmap(module); + OnehotDatabase onehot_db(module, sigmap); + onehot_db.verbose = verbose_onehot; + + if (optimize_onehot) + onehot_db.initialize(); dict> eqdb; - for (auto cell : module->selected_cells()) + for (auto cell : module->cells()) { if (cell->type == "$eq") { @@ -181,6 +381,12 @@ struct Pmux2ShiftxPass : public Pass { bool printed_pmux_header = false; + if (verbose) { + printed_pmux_header = true; + log("Inspecting $pmux cell %s/%s.\n", log_id(module), log_id(cell)); + log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); + } + SigSpec updated_S = cell->getPort("\\S"); SigSpec updated_B = cell->getPort("\\B"); @@ -196,7 +402,7 @@ struct Pmux2ShiftxPass : public Pass { } // find the relevant choices - bool is_onehot = true; + bool is_onehot = GetSize(sig) > 2; dict choices; for (int i : seldb.at(sig)) { Const val = eqdb.at(S[i]).second; @@ -211,14 +417,17 @@ struct Pmux2ShiftxPass : public Pass { // TBD: also find choices that are using signals that are subsets of the bits in "sig" - if (is_onehot && !allow_onehot) { - seldb.erase(sig); - continue; - } + if (!verbose) + { + if (is_onehot && !allow_onehot && !optimize_onehot) { + seldb.erase(sig); + continue; + } - if (GetSize(choices) < min_choices) { - seldb.erase(sig); - continue; + if (GetSize(choices) < min_choices) { + seldb.erase(sig); + continue; + } } if (!printed_pmux_header) { @@ -229,6 +438,65 @@ struct Pmux2ShiftxPass : public Pass { log(" checking ctrl signal %s\n", log_signal(sig)); + auto print_choices = [&]() { + log(" table of choices:\n"); + for (auto &it : choices) + log(" %3d: %s: %s\n", it.second, log_signal(it.first), + log_signal(B.extract(it.second*width, width))); + }; + + if (verbose) + { + if (is_onehot && !allow_onehot && !optimize_onehot) { + print_choices(); + log(" ignoring one-hot encoding.\n"); + seldb.erase(sig); + continue; + } + + if (GetSize(choices) < min_choices) { + print_choices(); + log(" insufficient choices.\n"); + seldb.erase(sig); + continue; + } + } + + if (is_onehot && optimize_onehot) + { + print_choices(); + if (!onehot_db.query(sig)) + { + log(" failed to detect onehot driver. do not optimize.\n"); + } + else + { + log(" optimizing one-hot encoding.\n"); + for (auto &it : choices) + { + const Const &val = it.first; + int index = -1; + + for (int i = 0; i < GetSize(val); i++) + if (val[i] == State::S1) { + log_assert(index < 0); + index = i; + } + + if (index < 0) { + log(" %3d: zero encoding.\n", it.second); + continue; + } + + SigBit new_ctrl = sig[index]; + log(" %3d: new crtl signal is %s.\n", it.second, log_signal(new_ctrl)); + updated_S[it.second] = new_ctrl; + } + } + seldb.erase(sig); + continue; + } + // find the best permutation vector perm_new_from_old(GetSize(sig)); Const perm_xormask(State::S0, GetSize(sig)); @@ -434,4 +702,127 @@ struct Pmux2ShiftxPass : public Pass { } } Pmux2ShiftxPass; +struct OnehotPass : public Pass { + OnehotPass() : Pass("onehot", "optimize $eq cells for onehot signals") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" onehot [options] [selection]\n"); + log("\n"); + log("This pass optimizes $eq cells that compare one-hot signals against constants\n"); + log("\n"); + log(" -v, -vv\n"); + log(" verbose output\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + bool verbose = false; + bool verbose_onehot = false; + + log_header(design, "Executing ONEHOT pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-v") { + verbose = true; + continue; + } + if (args[argidx] == "-vv") { + verbose = true; + verbose_onehot = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + { + SigMap sigmap(module); + OnehotDatabase onehot_db(module, sigmap); + onehot_db.verbose = verbose_onehot; + onehot_db.initialize(); + + for (auto cell : module->selected_cells()) + { + if (cell->type != "$eq") + continue; + + SigSpec A = sigmap(cell->getPort("\\A")); + SigSpec B = sigmap(cell->getPort("\\B")); + + int a_width = cell->getParam("\\A_WIDTH").as_int(); + int b_width = cell->getParam("\\B_WIDTH").as_int(); + + if (a_width < b_width) { + bool a_signed = cell->getParam("\\A_SIGNED").as_int(); + A.extend_u0(b_width, a_signed); + } + + if (b_width < a_width) { + bool b_signed = cell->getParam("\\B_SIGNED").as_int(); + B.extend_u0(a_width, b_signed); + } + + if (A.is_fully_const()) + std::swap(A, B); + + if (!B.is_fully_const()) + continue; + + if (verbose) + log("Checking $eq(%s, %s) cell %s/%s.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + + if (!onehot_db.query(A)) { + if (verbose) + log(" onehot driver test on %s failed.\n", log_signal(A)); + continue; + } + + int index = -1; + bool not_onehot = false; + + for (int i = 0; i < GetSize(B); i++) { + if (B[i] != State::S1) + continue; + if (index >= 0) + not_onehot = true; + index = i; + } + + if (index < 0) { + if (verbose) + log(" not optimizing the zero pattern.\n"); + continue; + } + + SigSpec Y = cell->getPort("\\Y"); + + if (not_onehot) + { + if (verbose) + log(" replacing with constant 0 driver.\n"); + else + log("Replacing one-hot $eq(%s, %s) cell %s/%s with constant 0 driver.\n", log_signal(A), log_signal(B), log_id(module), log_id(cell)); + module->connect(Y, SigSpec(1, GetSize(Y))); + } + else + { + SigSpec sig = A[index]; + if (verbose) + log(" replacing with signal %s.\n", log_signal(sig)); + else + log("Replacing one-hot $eq(%s, %s) cell %s/%s with signal %s.\n",log_signal(A), log_signal(B), log_id(module), log_id(cell), log_signal(sig)); + sig.extend_u0(GetSize(Y)); + module->connect(Y, sig); + } + + module->remove(cell); + } + } + } +} OnehotPass; + PRIVATE_NAMESPACE_END -- cgit v1.2.3 From fc23af170768926e645b6c94c54b4c2e6e8d0808 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 18:13:37 +0200 Subject: Auto-initialize OnehotDatabase on-demand in pmux2shiftx.cc Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 5fd49a571..5f897b131 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -28,6 +28,7 @@ struct OnehotDatabase Module *module; const SigMap &sigmap; bool verbose = false; + bool initialized = false; pool init_ones; dict> sig_sources_db; @@ -40,6 +41,9 @@ struct OnehotDatabase void initialize() { + log_assert(!initialized); + initialized = true; + for (auto wire : module->wires()) { auto it = wire->attributes.find("\\init"); @@ -176,6 +180,9 @@ struct OnehotDatabase if (verbose) log("** ONEHOT QUERY START (%s)\n", log_signal(sig)); + if (!initialized) + initialize(); + query_worker(sig, retval, cache, 3); if (verbose) @@ -273,9 +280,6 @@ struct Pmux2ShiftxPass : public Pass { OnehotDatabase onehot_db(module, sigmap); onehot_db.verbose = verbose_onehot; - if (optimize_onehot) - onehot_db.initialize(); - dict> eqdb; for (auto cell : module->cells()) @@ -743,7 +747,6 @@ struct OnehotPass : public Pass { SigMap sigmap(module); OnehotDatabase onehot_db(module, sigmap); onehot_db.verbose = verbose_onehot; - onehot_db.initialize(); for (auto cell : module->selected_cells()) { -- cgit v1.2.3 From 0f0ada13f46fdc00a6f55f649647c177b4a150ff Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 15:26:20 +0200 Subject: Add full_pmux feature to pmux2shiftx Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 5f897b131..29870f510 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -369,6 +369,7 @@ struct Pmux2ShiftxPass : public Pass { dict> seldb; + SigSpec A = cell->getPort("\\A"); SigSpec B = cell->getPort("\\B"); SigSpec S = sigmap(cell->getPort("\\S")); for (int i = 0; i < GetSize(S); i++) @@ -419,6 +420,8 @@ struct Pmux2ShiftxPass : public Pass { choices[val] = i; } + bool full_pmux = GetSize(choices) == GetSize(S); + // TBD: also find choices that are using signals that are subsets of the bits in "sig" if (!verbose) @@ -634,7 +637,21 @@ struct Pmux2ShiftxPass : public Pass { log(" range density: %d%%\n", range_density); log(" absolute density: %d%%\n", absolute_density); - bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (max_choice+1 == GetSize(choices)); + if (full_pmux) { + int full_density = 100*GetSize(choices) / (1 << GetSize(sig)); + log(" full density: %d%%\n", full_density); + if (full_density < min_density) { + full_pmux = false; + } else { + min_choice = 0; + max_choice = (1 << GetSize(sig))-1; + log(" update to full case.\n"); + log(" new min choice: %d\n", min_choice); + log(" new max choice: %d\n", max_choice); + } + } + + bool full_case = (min_choice == 0) && (max_choice == (1 << GetSize(sig))-1) && (full_pmux || max_choice+1 == GetSize(choices)); log(" full case: %s\n", full_case ? "true" : "false"); // check density percentages @@ -677,6 +694,10 @@ struct Pmux2ShiftxPass : public Pass { // create data signal SigSpec data(State::Sx, (max_choice+1)*extwidth); + if (full_pmux) { + for (int i = 0; i <= max_choice; i++) + data.replace(i*extwidth, A); + } for (auto &it : perm_choices) { int position = it.first.as_int()*extwidth; int data_index = it.second; -- cgit v1.2.3 From e158ea20979165c1bac4c5c4027cf53255e57baa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 17:25:52 +0200 Subject: Add log_debug() framework Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 11 ++++--- passes/opt/opt_expr.cc | 79 +++++++++++++++++++++++++++-------------------- passes/opt/opt_merge.cc | 8 +++-- passes/opt/opt_muxtree.cc | 6 ++-- 4 files changed, 59 insertions(+), 45 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c3b13acaf..c38e9df5e 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -137,7 +137,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto cell : unused) { if (verbose) - log(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str()); + log_debug(" removing unused `%s' cell `%s'.\n", cell->type.c_str(), cell->name.c_str()); module->design->scratchpad_set_bool("opt.did_something", true); module->remove(cell); count_rm_cells++; @@ -326,7 +326,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos for (auto wire : maybe_del_wires) if (!used_signals.check_any(RTLIL::SigSpec(wire))) { if (check_public_name(wire->name) && verbose) { - log(" removing unused non-port wire %s.\n", wire->name.c_str()); + log_debug(" removing unused non-port wire %s.\n", wire->name.c_str()); } del_wires.insert(wire); del_wires_count++; @@ -336,7 +336,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos count_rm_wires += del_wires.size(); if (verbose && del_wires_count > 0) - log(" removed %d unused temporary wires.\n", del_wires_count); + log_debug(" removed %d unused temporary wires.\n", del_wires_count); } bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) @@ -399,7 +399,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) } if (verbose) - log(" removing redundant init attribute on %s.\n", log_id(wire)); + log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); wire->attributes.erase("\\init"); did_something = true; @@ -426,7 +426,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool } for (auto cell : delcells) { if (verbose) - log(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), + log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A"))); module->remove(cell); } @@ -551,6 +551,7 @@ struct CleanPass : public Pass { rmunused_module(module, purge_mode, false, false); } + log_suppressed(); if (count_rm_cells > 0 || count_rm_wires > 0) log("Removed %d unused cells and %d unused wires.\n", count_rm_cells, count_rm_wires); diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index a05db2a4f..af6d352af 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -67,7 +67,7 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) if (sig.size() == 0) continue; - log("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c)); + log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c)); module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width))); did_something = true; } @@ -78,7 +78,7 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::SigSpec Y = cell->getPort(out_port); out_val.extend_u0(Y.size(), false); - log("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n", + log_debug("Replacing %s cell `%s' (%s) in module `%s' with constant driver `%s = %s'.\n", cell->type.c_str(), cell->name.c_str(), info.c_str(), module->name.c_str(), log_signal(Y), log_signal(out_val)); // log_cell(cell); @@ -134,7 +134,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ if (GetSize(grouped_bits[i]) == GetSize(bits_y)) return false; - log("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n", + log_debug("Replacing %s cell `%s' in module `%s' with cells using grouped bits:\n", log_id(cell->type), log_id(cell), log_id(module)); for (int i = 0; i < GRP_N; i++) @@ -156,7 +156,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ } if (cell->type.in("$and", "$or") && i == GRP_CONST_A) { - log(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); + log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); module->connect(new_y, new_b); module->connect(new_conn); continue; @@ -180,10 +180,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ module->connect(new_conn); - log(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); + log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); if (b_name == "\\B") - log(", B=%s", log_signal(new_b)); - log("\n"); + log_debug(", B=%s", log_signal(new_b)); + log_debug("\n"); } cover_list("opt.opt_expr.fine.group", "$not", "$pos", "$and", "$or", "$xor", "$xnor", cell->type.str()); @@ -197,7 +197,7 @@ void handle_polarity_inv(Cell *cell, IdString port, IdString param, const SigMap { SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { - log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", + log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); @@ -226,7 +226,7 @@ void handle_clkpol_celltype_swap(Cell *cell, string type1, string type2, IdStrin if (cell->type.in(type1, type2)) { SigSpec sig = assign_map(cell->getPort(port)); if (invert_map.count(sig)) { - log("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", + log_debug("Inverting %s of %s cell `%s' in module `%s': %s -> %s\n", log_id(port), log_id(cell->type), log_id(cell), log_id(cell->module), log_signal(sig), log_signal(invert_map.at(sig))); cell->setPort(port, (invert_map.at(sig))); @@ -455,9 +455,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { if (cell->type == "$reduce_xnor") { cover("opt.opt_expr.reduce_xnor_not"); - log("Replacing %s cell `%s' in module `%s' with $not cell.\n", + log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n", log_id(cell->type), log_id(cell->name), log_id(module)); cell->type = "$not"; + did_something = true; } else { cover("opt.opt_expr.unary_buffer"); replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A")); @@ -488,7 +489,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (GetSize(new_sig_a) < GetSize(sig_a)) { cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str()); - log("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", + log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a)); cell->setPort("\\A", new_sig_a); cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a); @@ -511,7 +512,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (GetSize(new_sig_b) < GetSize(sig_b)) { cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str()); - log("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", + log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b)); cell->setPort("\\B", new_sig_b); cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b); @@ -537,7 +538,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) { cover("opt.opt_expr.fine.$reduce_and"); - log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", + log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); cell->setPort("\\A", sig_a = new_a); cell->parameters.at("\\A_WIDTH") = 1; @@ -563,7 +564,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a != RTLIL::State::Sm && RTLIL::SigSpec(new_a) != sig_a) { cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str()); - log("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", + log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); cell->setPort("\\A", sig_a = new_a); cell->parameters.at("\\A_WIDTH") = 1; @@ -589,7 +590,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_b != RTLIL::State::Sm && RTLIL::SigSpec(new_b) != sig_b) { cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str()); - log("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", + log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b)); cell->setPort("\\B", sig_b = new_b); cell->parameters.at("\\B_WIDTH") = 1; @@ -640,7 +641,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) { cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str()); - log("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); RTLIL::SigSpec tmp = cell->getPort("\\A"); cell->setPort("\\A", cell->getPort("\\B")); cell->setPort("\\B", tmp); @@ -750,7 +751,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons ACTION_DO("\\Y", cell->getPort("\\A")); if (input == State::S0 && !a.is_fully_undef()) { cover("opt.opt_expr.action_" S__LINE__); - log("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n", + log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); cell->setPort("\\A", SigSpec(State::Sx, GetSize(a))); did_something = true; @@ -822,7 +823,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons ACTION_DO("\\Y", cell->getPort("\\A")); } else { cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->type = "$not"; cell->parameters.erase("\\B_WIDTH"); cell->parameters.erase("\\B_SIGNED"); @@ -837,7 +838,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons (assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero())) { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), + log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), log_id(module), "$eq" ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool"; if (assign_map(cell->getPort("\\A")).is_fully_zero()) { @@ -876,7 +877,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str()); - log("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", + log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y)); module->connect(cell->getPort("\\Y"), sig_y); @@ -939,7 +940,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (identity_wrt_b) cover_list("opt.opt_expr.identwrt.b", "$add", "$sub", "$or", "$xor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$mul", "$div", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with identity for port %c.\n", + log_debug("Replacing %s cell `%s' in module `%s' with identity for port %c.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); if (!identity_wrt_a) { @@ -969,7 +970,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) { cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", cell->getPort("\\S")); cell->unsetPort("\\B"); cell->unsetPort("\\S"); @@ -988,7 +989,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) { cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { @@ -1008,7 +1009,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); - log("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); + log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\B", cell->getPort("\\S")); cell->unsetPort("\\S"); if (cell->type == "$mux") { @@ -1061,7 +1062,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (cell->getPort("\\S").size() != new_s.size()) { cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str()); - log("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", + log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", new_a); cell->setPort("\\B", new_b); @@ -1179,7 +1180,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover("opt.opt_expr.mul_shift.zero"); - log("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n", + log_debug("Replacing multiply-by-zero cell `%s' in module `%s' with zero-driver.\n", cell->name.c_str(), module->name.c_str()); module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(0, sig_y.size()))); @@ -1197,7 +1198,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons else cover("opt.opt_expr.mul_shift.unswapped"); - log("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n", + log_debug("Replacing multiply-by-%d cell `%s' in module `%s' with shift-by-%d.\n", a_val, cell->name.c_str(), module->name.c_str(), i); if (!swapped_ab) { @@ -1237,7 +1238,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover("opt.opt_expr.divmod_zero"); - log("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n", + log_debug("Replacing divide-by-zero cell `%s' in module `%s' with undef-driver.\n", cell->name.c_str(), module->name.c_str()); module->connect(RTLIL::SigSig(sig_y, RTLIL::SigSpec(State::Sx, sig_y.size()))); @@ -1254,7 +1255,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover("opt.opt_expr.div_shift"); - log("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n", + log_debug("Replacing divide-by-%d cell `%s' in module `%s' with shift-by-%d.\n", b_val, cell->name.c_str(), module->name.c_str(), i); std::vector new_b = RTLIL::SigSpec(i, 6); @@ -1272,7 +1273,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { cover("opt.opt_expr.mod_mask"); - log("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n", + log_debug("Replacing modulo-by-%d cell `%s' in module `%s' with bitmask.\n", b_val, cell->name.c_str(), module->name.c_str()); std::vector new_b = RTLIL::SigSpec(State::S1, i); @@ -1342,7 +1343,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons SigSpec y_sig = cell->getPort("\\Y"); Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig)); - log("Replacing cell `%s' in module `%s' with constant driver %s.\n", + log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n", log_id(cell), log_id(module), log_signal(y_value)); module->connect(y_sig, y_value); @@ -1354,7 +1355,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (redundant_bits) { - log("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", + log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", redundant_bits, log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", sig_a); @@ -1493,7 +1494,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (replace || remove) { - log("Replacing %s cell `%s' (implementing %s) with %s.\n", + log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n", log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); if (replace) module->connect(cell->getPort("\\Y"), replace_sig); @@ -1599,8 +1600,14 @@ struct OptExprPass : public Pass { for (auto module : design->selected_modules()) { - if (undriven) + log("Optimizing module %s.\n", log_id(module)); + + if (undriven) { + did_something = false; replace_undriven(design, module); + if (did_something) + design->scratchpad_set_bool("opt.did_something", true); + } do { do { @@ -1610,7 +1617,11 @@ struct OptExprPass : public Pass { design->scratchpad_set_bool("opt.did_something", true); } while (did_something); replace_const_cells(design, module, true, mux_undef, mux_bool, do_fine, keepdc, clkinv); + if (did_something) + design->scratchpad_set_bool("opt.did_something", true); } while (did_something); + + log_suppressed(); } log_pop(); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index eedf88904..7567d4657 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -315,17 +315,17 @@ struct OptMergeWorker { if (sharemap.count(cell) > 0) { did_something = true; - log(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str()); + log_debug(" Cell `%s' is identical to cell `%s'.\n", cell->name.c_str(), sharemap[cell]->name.c_str()); for (auto &it : cell->connections()) { if (cell->output(it.first)) { RTLIL::SigSpec other_sig = sharemap[cell]->getPort(it.first); - log(" Redirecting output %s: %s = %s\n", it.first.c_str(), + log_debug(" Redirecting output %s: %s = %s\n", it.first.c_str(), log_signal(it.second), log_signal(other_sig)); module->connect(RTLIL::SigSig(it.second, other_sig)); assign_map.add(it.second, other_sig); } } - log(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); + log_debug(" Removing %s cell `%s' from module `%s'.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); #ifdef USE_CELL_HASH_CACHE cell_hash_cache.erase(cell); #endif @@ -336,6 +336,8 @@ struct OptMergeWorker } } } + + log_suppressed(); } }; diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 375697dc8..dbebf21e0 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -181,14 +181,14 @@ struct OptMuxtreeWorker for (int mux_idx = 0; mux_idx < GetSize(root_muxes); mux_idx++) if (root_muxes.at(mux_idx)) { - log(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); + log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); } while (!root_mux_rerun.empty()) { int mux_idx = *root_mux_rerun.begin(); - log(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell)); + log_debug(" Root of a mux tree: %s (rerun as non-pure)\n", log_id(mux2info[mux_idx].cell)); log_assert(root_enable_muxes.at(mux_idx)); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); @@ -326,7 +326,7 @@ struct OptMuxtreeWorker if (abort_count == 0) { root_mux_rerun.insert(m); root_enable_muxes.at(m) = true; - log(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell)); + log_debug(" Removing pure flag from root mux %s.\n", log_id(mux2info[m].cell)); } else eval_mux(knowledge, m, false, do_enable_ports, abort_count - 1); } else -- cgit v1.2.3 From c84cdc711c6f78175c3ef236c3aa7640d7485b79 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Apr 2019 17:55:41 +0200 Subject: Remove some left-over log_dump() Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 52245ce3e..68e077cf9 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -462,12 +462,10 @@ struct WreduceWorker SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) { - log_dump(initsig[i], remove_init_bits.count(initsig[i])); if (!remove_init_bits.count(initsig[i])) new_initval[i] = initval[i]; } w->attributes.at("\\init") = new_initval; - log_dump(w->name, initval, new_initval); } } } -- cgit v1.2.3 From 634482380cfe5d6a1c801af0ce04e8048c5c9baf Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 10:03:18 +0200 Subject: Preserve $specify[23] cells Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c38e9df5e..3f38dd580 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -64,7 +64,7 @@ struct keep_cache_t bool query(Cell *cell) { - if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover")) + if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3")) return true; if (cell->has_keep_attr()) -- cgit v1.2.3 From 71c38d9de527e1a8b55ba295df459fbcf2a0fe47 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 23 Apr 2019 15:46:40 +0200 Subject: Add $specrule cells for $setup/$hold/$skew specify rules Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 3f38dd580..3e131d2af 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -64,7 +64,7 @@ struct keep_cache_t bool query(Cell *cell) { - if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3")) + if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule")) return true; if (cell->has_keep_attr()) -- cgit v1.2.3 From 754b1ee4b3ad8d1e1fab8eac88e0976e0355bc96 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 29 Apr 2019 08:38:38 +0200 Subject: Drive dangling wires with init attr with their init value, fixes #956 --- passes/opt/opt_clean.cc | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index c38e9df5e..5d95c4f1a 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -281,13 +281,26 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos 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]); } 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); -- cgit v1.2.3 From b515fd2d25851c90c9a0b08414c5ea5edeb916a0 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Apr 2019 11:25:15 +0200 Subject: Add peepopt_muldiv, fixes #930 Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 68e077cf9..bbb1f4c48 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -529,6 +529,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); -- cgit v1.2.3 From 9d117eba9d65cf978716f1c7d41e86466ca03fc6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Apr 2019 14:46:12 +0200 Subject: Add handling of init attributes in "opt_expr -undriven" Signed-off-by: Clifford Wolf --- passes/opt/opt_expr.cc | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index af6d352af..b445afdc8 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -39,6 +39,9 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) SigPool used_signals; SigPool all_signals; + dict> initbits; + pool revisit_initwires; + for (auto cell : module->cells()) for (auto &conn : cell->connections()) { if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) @@ -48,6 +51,14 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } for (auto wire : module->wires()) { + if (wire->attributes.count("\\init")) { + SigSpec sig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { + if (initval[i] == State::S0 || initval[i] == State::S1) + initbits[sig[i]] = make_pair(wire, initval[i]); + } + } if (wire->port_input) driven_signals.add(sigmap(wire)); if (wire->port_output) @@ -67,10 +78,38 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) if (sig.size() == 0) continue; - log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c)); - module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width))); + Const val(RTLIL::State::Sx, GetSize(sig)); + for (int i = 0; i < GetSize(sig); i++) { + SigBit bit = sigmap(sig[i]); + auto cursor = initbits.find(bit); + if (cursor != initbits.end()) { + revisit_initwires.insert(cursor->second.first); + val[i] = cursor->second.second; + } + } + + log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val)); + module->connect(sig, val); did_something = true; } + + if (!revisit_initwires.empty()) + { + SigMap sm2(module); + + for (auto wire : revisit_initwires) { + SigSpec sig = sm2(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { + if (SigBit(initval[i]) == sig[i]) + initval[i] = State::Sx; + } + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + else + wire->attributes["\\init"] = initval; + } + } } void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) -- cgit v1.2.3 From 32ff37bb5a8cec79e8cbcfac4075cc553fa9a394 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 30 Apr 2019 22:20:45 +0200 Subject: Fix segfault in wreduce Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 68e077cf9..41de8aad1 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -180,6 +180,8 @@ struct WreduceWorker } auto info = mi.query(sig_q[i]); + if (info == nullptr) + return; if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { remove_init_bits.insert(sig_q[i]); sig_d.remove(i); -- cgit v1.2.3 From a30b99e66e048530d74e9dfc5c103d5fac47c5bc Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 1 May 2019 09:29:34 +0200 Subject: Silently resolve completely unused cell-vs-const driver-driver conflicts Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5d95c4f1a..242680290 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -85,7 +85,14 @@ void rmunused_module_cells(Module *module, bool verbose) { SigMap sigmap(module); pool queue, unused; + pool used_raw_bits; dict> wire2driver; + dict> driver_driver_logs; + + for (auto &it : module->connections_) { + for (auto raw_bit : it.second) + used_raw_bits.insert(raw_bit); + } for (auto &it : module->cells_) { Cell *cell = it.second; @@ -96,11 +103,15 @@ void rmunused_module_cells(Module *module, bool verbose) continue; auto bit = sigmap(raw_bit); if (bit.wire == nullptr) - log_warning("Driver-driver conflict for %s between cell %s.%s and constant %s in %s: Resolved using constant.\n", - log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module)); + driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", + log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); if (bit.wire != nullptr) wire2driver[bit].insert(cell); } + if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it2.first)) + for (auto raw_bit : it2.second) + used_raw_bits.insert(raw_bit); } if (keep_cache.query(cell)) queue.insert(cell); @@ -114,9 +125,17 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto bit : sigmap(wire)) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); + for (auto raw_bit : SigSpec(wire)) + used_raw_bits.insert(raw_bit); } } + for (auto it : driver_driver_logs) { + if (used_raw_bits.count(it.first)) + for (auto msg : it.second) + log_warning("%s\n", msg.c_str()); + } + while (!queue.empty()) { pool bits; -- cgit v1.2.3 From f12e1155f1d77443ee9d876d5ba3d407b9447540 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 09:12:10 +0200 Subject: Improve unused-detection for opt_clean driver-driver conflict warning Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 50 ++++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 21 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 242680290..f287fdcff 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -97,21 +97,19 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it : module->cells_) { Cell *cell = it.second; for (auto &it2 : cell->connections()) { - if (!ct_all.cell_known(cell->type) || ct_all.cell_output(cell->type, it2.first)) - for (auto raw_bit : it2.second) { - if (raw_bit.wire == nullptr) - continue; - auto bit = sigmap(raw_bit); - if (bit.wire == nullptr) - driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " - "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", - log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); - if (bit.wire != nullptr) - wire2driver[bit].insert(cell); - } - if (!ct_all.cell_known(cell->type) || ct_all.cell_input(cell->type, it2.first)) - for (auto raw_bit : it2.second) - used_raw_bits.insert(raw_bit); + if (ct_all.cell_known(cell->type) && !ct_all.cell_output(cell->type, it2.first)) + continue; + for (auto raw_bit : it2.second) { + if (raw_bit.wire == nullptr) + continue; + auto bit = sigmap(raw_bit); + if (bit.wire == nullptr) + driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", + log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); + if (bit.wire != nullptr) + wire2driver[bit].insert(cell); + } } if (keep_cache.query(cell)) queue.insert(cell); @@ -130,12 +128,6 @@ void rmunused_module_cells(Module *module, bool verbose) } } - for (auto it : driver_driver_logs) { - if (used_raw_bits.count(it.first)) - for (auto msg : it.second) - log_warning("%s\n", msg.c_str()); - } - while (!queue.empty()) { pool bits; @@ -161,6 +153,22 @@ void rmunused_module_cells(Module *module, bool verbose) module->remove(cell); count_rm_cells++; } + + for (auto &it : module->cells_) { + Cell *cell = it.second; + for (auto &it2 : cell->connections()) { + if (ct_all.cell_known(cell->type) && !ct_all.cell_input(cell->type, it2.first)) + continue; + for (auto raw_bit : it2.second) + used_raw_bits.insert(raw_bit); + } + } + + for (auto it : driver_driver_logs) { + if (used_raw_bits.count(it.first)) + for (auto msg : it.second) + log_warning("%s\n", msg.c_str()); + } } int count_nontrivial_wire_attrs(RTLIL::Wire *w) -- cgit v1.2.3 From 5c2c0b4bb2ade51396da3acbcce0d5916fb1c7d6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 09:22:26 +0200 Subject: Further improve unused-detection for opt_clean driver-driver conflict warning Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index f287fdcff..fcb662b59 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -89,9 +89,12 @@ void rmunused_module_cells(Module *module, bool verbose) dict> wire2driver; dict> driver_driver_logs; + SigMap raw_sigmap; for (auto &it : module->connections_) { - for (auto raw_bit : it.second) - used_raw_bits.insert(raw_bit); + for (int i = 0; i < GetSize(it.second); i++) { + if (it.second[i].wire != nullptr) + raw_sigmap.add(it.first[i], it.second[i]); + } } for (auto &it : module->cells_) { @@ -104,7 +107,7 @@ void rmunused_module_cells(Module *module, bool verbose) continue; auto bit = sigmap(raw_bit); if (bit.wire == nullptr) - driver_driver_logs[raw_bit].push_back(stringf("Driver-driver conflict " + driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); if (bit.wire != nullptr) @@ -124,7 +127,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); for (auto raw_bit : SigSpec(wire)) - used_raw_bits.insert(raw_bit); + used_raw_bits.insert(raw_sigmap(raw_bit)); } } @@ -159,7 +162,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it2 : cell->connections()) { if (ct_all.cell_known(cell->type) && !ct_all.cell_input(cell->type, it2.first)) continue; - for (auto raw_bit : it2.second) + for (auto raw_bit : raw_sigmap(it2.second)) used_raw_bits.insert(raw_bit); } } -- cgit v1.2.3 From 42190207b4a5ae37240e58652d173c7164f025f7 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 3 May 2019 14:24:53 +0200 Subject: Improve opt_expr and opt_clean handling of (partially) undriven and/or unused wires, fixes #981 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 112 +++++++++++++++++++++++++++++++----------------- passes/opt/opt_expr.cc | 13 ++++-- 2 files changed, 81 insertions(+), 44 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5d95c4f1a..96118e906 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -274,50 +274,53 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos std::vector maybe_del_wires; for (auto wire : module->wires()) { + SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); + log_assert(GetSize(s1) == GetSize(s2)); + + bool maybe_del = false; 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]); + if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) + maybe_del = true; + } else { + if (!used_signals.check_any(s2)) + maybe_del = true; + } + + if (maybe_del) { + maybe_del_wires.push_back(wire); + } else { + 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; } - 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); @@ -336,14 +339,40 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos pool 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) { + for (auto wire : maybe_del_wires) { + SigSpec s1 = SigSpec(wire); + if (used_signals.check_any(s1)) { + SigSpec s2 = assign_map(s1); + 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]); + } + if (new_conn.first.size() > 0) { + if (initval.is_fully_undef()) + wire->attributes.erase("\\init"); + else + wire->attributes.at("\\init") = initval; + module->connect(new_conn); + } + } else { + if (ys_debug() || (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(); @@ -496,6 +525,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; @@ -561,7 +593,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; + } } } } -- cgit v1.2.3 From a01386c0e45b4eee5295db440740a1ab271396fe Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 4 May 2019 09:47:16 +0200 Subject: Improve opt_clean handling of unused wires Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 96118e906..9f6212526 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -242,6 +242,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; @@ -251,6 +255,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); } @@ -277,23 +282,30 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos 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 maybe_del = false; - if ((!purge_mode && check_public_name(wire->name)) || wire->port_id != 0 || wire->get_bool_attribute("\\keep") || wire->attributes.count("\\init")) { - if (!used_signals.check_any(s2) && wire->port_id == 0 && !wire->get_bool_attribute("\\keep")) - maybe_del = true; + 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 (!used_signals.check_any(s2)) + if (!raw_used_signals_noaliases.check_any(s1)) + maybe_del = true; + if (!used_signals_nodrivers.check_any(s2)) maybe_del = true; } if (maybe_del) { maybe_del_wires.push_back(wire); } else { - 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]) { @@ -341,7 +353,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos int del_wires_count = 0; for (auto wire : maybe_del_wires) { SigSpec s1 = SigSpec(wire); - if (used_signals.check_any(s1)) { + if (used_signals_nodrivers.check_any(s1)) { SigSpec s2 = assign_map(s1); Const initval; if (wire->attributes.count("\\init")) -- cgit v1.2.3 From ba6ce21a74425788b5a98e2e628c089841b47aa3 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 6 May 2019 12:45:22 +0200 Subject: Cleanups in opt_clean Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 63 +++++++++++++------------------------------------ 1 file changed, 16 insertions(+), 47 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 9f6212526..81432b175 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -276,7 +276,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - std::vector maybe_del_wires; + pool del_wires_queue; for (auto wire : module->wires()) { SigSpec s1 = SigSpec(wire), s2 = assign_map(s1); @@ -290,7 +290,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (initval.is_fully_undef()) wire->attributes.erase("\\init"); - bool maybe_del = false; + 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 @@ -298,13 +298,13 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos /* do not get rid of public names unless in purge mode */ } else { if (!raw_used_signals_noaliases.check_any(s1)) - maybe_del = true; + delete_this_wire = true; if (!used_signals_nodrivers.check_any(s2)) - maybe_del = true; + delete_this_wire = true; } - if (maybe_del) { - maybe_del_wires.push_back(wire); + if (delete_this_wire) { + del_wires_queue.insert(wire); } else { RTLIL::SigSig new_conn; for (int i = 0; i < GetSize(s1); i++) @@ -347,50 +347,19 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } - - pool del_wires; - - int del_wires_count = 0; - for (auto wire : maybe_del_wires) { - SigSpec s1 = SigSpec(wire); - if (used_signals_nodrivers.check_any(s1)) { - SigSpec s2 = assign_map(s1); - 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]); - } - if (new_conn.first.size() > 0) { - if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); - else - wire->attributes.at("\\init") = initval; - module->connect(new_conn); - } - } else { - if (ys_debug() || (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++; - } + 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++; } - 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) -- cgit v1.2.3 From a76189e7adb88a81b8c1a8910524323fe93a421c Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Tue, 7 May 2019 14:41:58 +0200 Subject: More opt_clean cleanups Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 62 ++++++++++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 249939876..6ca6ac820 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -320,22 +320,32 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (initval.is_fully_undef()) wire->attributes.erase("\\init"); - bool delete_this_wire = false; + if (GetSize(wire) == 0) { + // delete zero-width wires + goto delete_this_wire; + } else 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 */ + // 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; + // do not get rid of public names unless in purge mode + } else + if (!raw_used_signals_noaliases.check_any(s1)) { + // delete wires that aren't used by anything directly + goto delete_this_wire; + } else + if (!used_signals_nodrivers.check_any(s2)) { + // delete wires that aren't used by anything indirectly, even though other wires may alias it + goto delete_this_wire; } - if (delete_this_wire) { + if (0) + { + delete_this_wire: del_wires_queue.insert(wire); - } else { + } + else + { RTLIL::SigSig new_conn; for (int i = 0; i < GetSize(s1); i++) if (s1[i] != s2[i]) { @@ -355,25 +365,25 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos used_signals.add(new_conn.second); module->connect(new_conn); } - } - if (!used_signals_nodrivers.check_all(s2)) { - std::string unused_bits; - for (int i = 0; i < GetSize(s2); i++) { - if (s2[i].wire == NULL) - continue; - if (!used_signals_nodrivers.check(s2[i])) { - if (!unused_bits.empty()) - unused_bits += " "; - unused_bits += stringf("%d", i); + if (!used_signals_nodrivers.check_all(s2)) { + std::string unused_bits; + for (int i = 0; i < GetSize(s2); i++) { + if (s2[i].wire == NULL) + continue; + if (!used_signals_nodrivers.check(s2[i])) { + if (!unused_bits.empty()) + unused_bits += " "; + unused_bits += stringf("%d", i); + } } - } - if (unused_bits.empty() || wire->port_id != 0) + if (unused_bits.empty() || wire->port_id != 0) + wire->attributes.erase("\\unused_bits"); + else + wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); + } else { wire->attributes.erase("\\unused_bits"); - else - wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); - } else { - wire->attributes.erase("\\unused_bits"); + } } } -- cgit v1.2.3 From 8166a142dd251f9d9ba2d172737d757ac52aa772 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 12 May 2019 13:51:12 +0200 Subject: Fix handling of glob_abort_cnt in opt_muxtree, fixes #1002 Signed-off-by: Clifford Wolf --- passes/opt/opt_muxtree.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index dbebf21e0..6511e091b 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -184,6 +184,10 @@ struct OptMuxtreeWorker log_debug(" Root of a mux tree: %s%s\n", log_id(mux2info[mux_idx].cell), root_enable_muxes.at(mux_idx) ? " (pure)" : ""); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); + if (glob_abort_cnt == 0) { + log(" Giving up (too many iterations)\n"); + return; + } } while (!root_mux_rerun.empty()) { @@ -192,9 +196,14 @@ struct OptMuxtreeWorker log_assert(root_enable_muxes.at(mux_idx)); root_mux_rerun.erase(mux_idx); eval_root_mux(mux_idx); + if (glob_abort_cnt == 0) { + log(" Giving up (too many iterations)\n"); + return; + } } log(" Analyzing evaluation results.\n"); + log_assert(glob_abort_cnt > 0); for (auto &mi : mux2info) { @@ -397,10 +406,8 @@ struct OptMuxtreeWorker void eval_mux(knowledge_t &knowledge, int mux_idx, bool do_replace_known, bool do_enable_ports, int abort_count) { - if (glob_abort_cnt == 0) { - log(" Giving up (too many iterations)\n"); + if (glob_abort_cnt == 0) return; - } glob_abort_cnt--; muxinfo_t &muxinfo = mux2info[mux_idx]; @@ -454,6 +461,7 @@ struct OptMuxtreeWorker void eval_root_mux(int mux_idx) { + log_assert(glob_abort_cnt > 0); knowledge_t knowledge; knowledge.known_inactive.resize(GetSize(bit2info)); knowledge.known_active.resize(GetSize(bit2info)); -- cgit v1.2.3 From a21a84b3b45d252ff050d3ae7e738d157b0b2be8 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 15 May 2019 16:01:28 +0200 Subject: Improvements in opt_clean Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 6ca6ac820..bf8020169 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -232,7 +232,7 @@ bool check_public_name(RTLIL::IdString id) return true; } -void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) +bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbose) { SigPool register_signals; SigPool connected_signals; @@ -272,20 +272,17 @@ 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; + SigPool raw_used_signals; SigPool used_signals_nodrivers; for (auto &it : module->cells_) { RTLIL::Cell *cell = it.second; for (auto &it2 : cell->connections_) { assign_map.apply(it2.second); + raw_used_signals.add(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); } @@ -294,6 +291,7 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos RTLIL::Wire *wire = it.second; if (wire->port_id > 0) { RTLIL::SigSpec sig = RTLIL::SigSpec(wire); + raw_used_signals.add(sig); assign_map.apply(sig); used_signals.add(sig); if (!wire->port_input) @@ -330,11 +328,11 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos 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)) { + if (!raw_used_signals.check_any(s1)) { // delete wires that aren't used by anything directly goto delete_this_wire; } else - if (!used_signals_nodrivers.check_any(s2)) { + if (!used_signals.check_any(s2)) { // delete wires that aren't used by anything indirectly, even though other wires may alias it goto delete_this_wire; } @@ -400,6 +398,8 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (verbose && del_temp_wires_count) log_debug(" removed %d unused temporary wires.\n", del_temp_wires_count); + + return !del_wires_queue.empty(); } bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) @@ -497,10 +497,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool module->design->scratchpad_set_bool("opt.did_something", true); rmunused_module_cells(module, verbose); - rmunused_module_signals(module, purge_mode, verbose); + while (rmunused_module_signals(module, purge_mode, verbose)) { } if (rminit && rmunused_module_init(module, purge_mode, verbose)) - rmunused_module_signals(module, purge_mode, verbose); + while (rmunused_module_signals(module, purge_mode, verbose)) { } } struct OptCleanPass : public Pass { -- cgit v1.2.3 From c4b8575f4322f72dd1b35e2737966db731a26c17 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 20 May 2019 15:36:13 +0200 Subject: Add "wreduce -keepdc", fixes #1016 Signed-off-by: Clifford Wolf --- passes/opt/wreduce.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 58c6e4b4b..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -29,6 +29,7 @@ PRIVATE_NAMESPACE_BEGIN struct WreduceConfig { pool supported_cell_types; + bool keepdc = false; WreduceConfig() { @@ -82,7 +83,7 @@ struct WreduceWorker SigBit ref = sig_a[i]; for (int k = 0; k < GetSize(sig_s); k++) { - if (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx && ref != sig_b[k*GetSize(sig_a) + i]) + if ((config->keepdc || (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) goto no_match_ab; if (sig_b[k*GetSize(sig_a) + i] != Sx) ref = sig_b[k*GetSize(sig_a) + i]; @@ -495,6 +496,9 @@ struct WreducePass : public Pass { log(" Do not change the width of memory address ports. Use this options in\n"); log(" flows that use the 'memory_memx' pass.\n"); log("\n"); + log(" -keepdc\n"); + log(" Do not optimize explicit don't-care values.\n"); + log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE { @@ -509,6 +513,10 @@ struct WreducePass : public Pass { opt_memx = true; continue; } + if (args[argidx] == "-keepdc") { + config.keepdc = true; + continue; + } break; } extra_args(args, argidx, design); -- cgit v1.2.3 From e3f9ccf56d65ba72dfa625e9716d1182f36a381e Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 22 May 2019 13:56:56 +0200 Subject: Keep zero-width wires in opt_clean if and only if they are ports, fixes #1023 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index bf8020169..7011d4602 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -319,8 +319,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos wire->attributes.erase("\\init"); if (GetSize(wire) == 0) { - // delete zero-width wires - goto delete_this_wire; + // delete zero-width wires, unless they are module ports + if (wire->port_id == 0) + goto delete_this_wire; } else 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 -- cgit v1.2.3 From 50ed34a6d0fe1013fae0a14165fc4fce1d1a3685 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 May 2019 11:26:18 -0700 Subject: opt_rmdff to work on $dffe and $_DFFE_* --- passes/opt/opt_rmdff.cc | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index e8570f0eb..a4ed582cb 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -260,8 +260,8 @@ delete_dlatch: bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) { - RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r; - RTLIL::Const val_cp, val_rp, val_rv; + RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; + RTLIL::Const val_cp, val_rp, val_rv, val_ep; if (dff->type == "$_FF_") { sig_d = dff->getPort("\\D"); @@ -285,6 +285,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); } + else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" && + (dff->type[7] == 'N' || dff->type[7] == 'P') && + (dff->type[8] == 'N' || dff->type[8] == 'P')) { + sig_d = dff->getPort("\\D"); + sig_q = dff->getPort("\\Q"); + sig_c = dff->getPort("\\C"); + sig_e = dff->getPort("\\E"); + val_cp = RTLIL::Const(dff->type[6] == 'P', 1); + val_ep = RTLIL::Const(dff->type[7] == 'P', 1); + } else if (dff->type == "$ff") { sig_d = dff->getPort("\\D"); sig_q = dff->getPort("\\Q"); @@ -295,6 +305,14 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_c = dff->getPort("\\CLK"); val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); } + else if (dff->type == "$dffe") { + sig_e = dff->getPort("\\EN"); + sig_d = dff->getPort("\\D"); + sig_q = dff->getPort("\\Q"); + sig_c = dff->getPort("\\CLK"); + val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); + val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1); + } else if (dff->type == "$adff") { sig_d = dff->getPort("\\D"); sig_q = dff->getPort("\\Q"); @@ -320,6 +338,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } + if (sig_e.size()) { + if (!sig_e.is_fully_const()) + return false; + if (sig_e != val_ep) { + if (has_init) + mod->connect(sig_q, val_init); + goto delete_dff; + } + } + if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { std::set muxes; mux_drivers.find(sig_d, muxes); @@ -489,7 +517,8 @@ struct OptRmdffPass : public Pass { if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", - "$ff", "$dff", "$adff")) + "$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", + "$ff", "$dff", "$dffe", "$adff")) dff_list.push_back(cell->name); if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_")) -- cgit v1.2.3 From 5ac7e38d0aab1c73150accd9befbccc5398b8e42 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 23 May 2019 12:58:30 -0700 Subject: Fix spacing --- passes/opt/opt_rmdff.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a4ed582cb..3cb8e2b1e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -342,8 +342,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (!sig_e.is_fully_const()) return false; if (sig_e != val_ep) { - if (has_init) - mod->connect(sig_q, val_init); + if (has_init) + mod->connect(sig_q, val_init); goto delete_dff; } } -- cgit v1.2.3 From 357b1de6bc3dcddc9bc0870e20c68c21c869a323 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 16:15:22 -0700 Subject: Resolve @cliffordwolf review, set even if !has_init --- passes/opt/opt_rmdff.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 3cb8e2b1e..a36b279c2 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -342,8 +342,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) if (!sig_e.is_fully_const()) return false; if (sig_e != val_ep) { - if (has_init) - mod->connect(sig_q, val_init); + mod->connect(sig_q, val_init); goto delete_dff; } } -- cgit v1.2.3 From 0d66103cbb462e6be613cc1187fa7be4f5ee4701 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 16:33:10 -0700 Subject: Add comments --- passes/opt/opt_rmdff.cc | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index a36b279c2..abbf8b5d1 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -364,39 +364,60 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) } } + // If clock is driven by a constant and (i) no reset signal + // (ii) Q has no initial value + // (iii) initial value is same as reset value if (!sig_c.empty() && sig_c.is_fully_const() && (!sig_r.size() || !has_init || val_init == val_rv)) { if (val_rv.bits.size() == 0) val_rv = val_init; + // Q is permanently reset value or initial value mod->connect(sig_q, val_rv); goto delete_dff; } + // If D is fully undefined and reset signal present and (i) Q has no initial value + // (ii) initial value is same as reset value if (sig_d.is_fully_undef() && sig_r.size() && (!has_init || val_init == val_rv)) { + // Q is permanently reset value mod->connect(sig_q, val_rv); goto delete_dff; } + // If D is fully undefined and no reset signal and Q has an initial value if (sig_d.is_fully_undef() && !sig_r.size() && has_init) { + // Q is permanently initial value mod->connect(sig_q, val_init); goto delete_dff; } + // If D is fully constant and (i) no reset signal + // (ii) reset value is same as constant D + // and (a) has initial value + // (b) initial value same as constant D if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { + // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; } + // If D input is same as Q output and (i) no reset signal + // (ii) no initial signal + // (iii) initial value is same as reset value if (sig_d == sig_q && (sig_r.empty() || !has_init || val_init == val_rv)) { + // Q is permanently reset value or initial value if (sig_r.size()) mod->connect(sig_q, val_rv); - if (has_init) + else if (has_init) mod->connect(sig_q, val_init); goto delete_dff; } + // If reset signal is present, and is fully constant if (!sig_r.empty() && sig_r.is_fully_const()) { + // If reset value is permanently enable or if reset is undefined if (sig_r == val_rp || sig_r.is_fully_undef()) { + // Q is permanently reset value mod->connect(sig_q, val_rv); goto delete_dff; } -- cgit v1.2.3 From 822d0b7789fdfe94bfe11b96546af8430e5f3299 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 24 May 2019 18:30:51 -0700 Subject: opt_rmdff to optimise even in presence of enable signal, even removing --- passes/opt/opt_rmdff.cc | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index abbf8b5d1..d10cf508f 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -338,15 +338,6 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } - if (sig_e.size()) { - if (!sig_e.is_fully_const()) - return false; - if (sig_e != val_ep) { - mod->connect(sig_q, val_init); - goto delete_dff; - } - } - if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { std::set muxes; mux_drivers.find(sig_d, muxes); @@ -392,9 +383,11 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If D is fully constant and (i) no reset signal // (ii) reset value is same as constant D - // and (a) has initial value + // and (a) has no initial value // (b) initial value same as constant D - if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { + // and (1) has no enable signal + // (2) enable is always active + if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const()) && (!sig_e.size() || (sig_d.is_fully_undef() && !has_init))) { // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; @@ -415,7 +408,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If reset signal is present, and is fully constant if (!sig_r.empty() && sig_r.is_fully_const()) { - // If reset value is permanently enable or if reset is undefined + // If reset value is permanently active or if reset is undefined if (sig_r == val_rp || sig_r.is_fully_undef()) { // Q is permanently reset value mod->connect(sig_q, val_rv); @@ -437,6 +430,30 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\R"); } + // If enable signal is present, and is fully constant + if (!sig_e.empty() && sig_e.is_fully_const()) + { + // If enable value is permanently inactive + if (sig_e != val_ep) { + // Q is permanently initial value + mod->connect(sig_q, val_init); + goto delete_dff; + } + + log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); + + if (dff->type == "$dffe") { + dff->type = "$dff"; + dff->unsetPort("\\EN"); + dff->unsetParam("\\EN_POLARITY"); + return true; + } + + log_assert(dff->type.substr(0,7) == "$_DFFE_"); + dff->type = stringf("$_DFF_%c_", + dff->type[7]); + dff->unsetPort("\\E"); + } + return false; delete_dff: -- cgit v1.2.3 From d4fb6cac7c4c93f868e294dfc95936516813eeac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 25 May 2019 12:55:57 -0700 Subject: Revert enable check --- passes/opt/opt_rmdff.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index d10cf508f..2abffa2a9 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -385,9 +385,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // (ii) reset value is same as constant D // and (a) has no initial value // (b) initial value same as constant D - // and (1) has no enable signal - // (2) enable is always active - if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const()) && (!sig_e.size() || (sig_d.is_fully_undef() && !has_init))) { + if (sig_d.is_fully_const() && (!sig_r.size() || val_rv == sig_d.as_const()) && (!has_init || val_init == sig_d.as_const())) { // Q is permanently D mod->connect(sig_q, sig_d); goto delete_dff; -- cgit v1.2.3 From 9a468f81c412f8b63d25e739f28932815c6882fb Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 28 May 2019 08:48:21 +0200 Subject: Optimizing DFFs whose initial value prevents their value from changing This is a proof of concept implementation that invokes SAT solver via Pass::call method. --- passes/opt/opt_rmdff.cc | 58 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 2abffa2a9..72eac9111 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -30,6 +30,7 @@ SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; bool keepdc; +bool sat; void remove_init_attr(SigSpec sig) { @@ -258,7 +259,7 @@ delete_dlatch: return true; } -bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) +bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) { RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::Const val_cp, val_rp, val_rv, val_ep; @@ -452,6 +453,52 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\E"); } + if (sat && has_init) { + std::vector removed_sigbits; + + // for (auto &sigbit : sig_q.bits()) { + for (int position =0; position < GetSize(sig_d); position += 1) { + RTLIL::SigBit q_sigbit = sig_q[position]; + RTLIL::SigBit d_sigbit = sig_d[position]; + RTLIL::Const sigbit_init_val = val_init.extract(position); + + if ((!q_sigbit.wire) || (!d_sigbit.wire)) { + continue; + } + + char str[1024]; + sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", + log_id(d_sigbit.wire), + d_sigbit.offset, + sigbit_init_val.as_string().c_str(), + log_id(q_sigbit.wire), + q_sigbit.offset, + sigbit_init_val.as_string().c_str() + ); + log("Running: %s\n", str); + + log_flush(); + + pass->call(mod->design, str); + if (mod->design->scratchpad_get_bool("sat.success", false)) { + sprintf(str, "connect -set %s[%d] %s", + log_id(q_sigbit.wire), + q_sigbit.offset, + sigbit_init_val.as_string().c_str() + ); + log("Running: %s\n", str); + log_flush(); + pass->call(mod->design, str); + // mod->connect(q_sigbit, sigbit_init_val); + removed_sigbits.push_back(position); + } + } + + if (!removed_sigbits.empty()) { + return true; + } + } + return false; delete_dff: @@ -467,7 +514,7 @@ struct OptRmdffPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" opt_rmdff [-keepdc] [selection]\n"); + log(" opt_rmdff [-keepdc] [-sat] [selection]\n"); log("\n"); log("This pass identifies flip-flops with constant inputs and replaces them with\n"); log("a constant driver.\n"); @@ -479,6 +526,7 @@ struct OptRmdffPass : public Pass { log_header(design, "Executing OPT_RMDFF pass (remove dff with constant values).\n"); keepdc = false; + sat = false; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { @@ -486,6 +534,10 @@ struct OptRmdffPass : public Pass { keepdc = true; continue; } + if (args[argidx] == "-sat") { + sat = true; + continue; + } break; } extra_args(args, argidx, design); @@ -568,7 +620,7 @@ struct OptRmdffPass : public Pass { for (auto &id : dff_list) { if (module->cell(id) != nullptr && - handle_dff(module, module->cells_[id])) + handle_dff(module, module->cells_[id], this)) total_count++; } -- cgit v1.2.3 From 8a6f9977f659d350cca936b45cb8b441d5a67eeb Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 5 Jun 2019 09:14:12 +0200 Subject: Suppress driver-driver conflict warning for unknown cell types, fixes #1065 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 7011d4602..cfb0f788a 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -106,7 +106,7 @@ void rmunused_module_cells(Module *module, bool verbose) if (raw_bit.wire == nullptr) continue; auto bit = sigmap(raw_bit); - if (bit.wire == nullptr) + if (bit.wire == nullptr && ct_all.cell_known(cell->type)) driver_driver_logs[raw_sigmap(raw_bit)].push_back(stringf("Driver-driver conflict " "for %s between cell %s.%s and constant %s in %s: Resolved using constant.", log_signal(raw_bit), log_id(cell), log_id(it2.first), log_signal(bit), log_id(module))); -- cgit v1.2.3 From feb2ddb52bd7ca590596e22f73a5d3c153907391 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 5 Jun 2019 14:08:14 -0700 Subject: Fix typo in opt_rmdff --- passes/opt/opt_rmdff.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 2abffa2a9..eeb992a3e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -292,8 +292,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_q = dff->getPort("\\Q"); sig_c = dff->getPort("\\C"); sig_e = dff->getPort("\\E"); - val_cp = RTLIL::Const(dff->type[6] == 'P', 1); - val_ep = RTLIL::Const(dff->type[7] == 'P', 1); + val_cp = RTLIL::Const(dff->type[7] == 'P', 1); + val_ep = RTLIL::Const(dff->type[8] == 'P', 1); } else if (dff->type == "$ff") { sig_d = dff->getPort("\\D"); -- cgit v1.2.3 From 83450a94898321a239f67f92e05fb9a246f4dd6d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:15:13 -0700 Subject: Move muxpack from passes/techmap to passes/opt --- passes/opt/Makefile.inc | 1 + passes/opt/muxpack.cc | 256 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 passes/opt/muxpack.cc (limited to 'passes/opt') diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index 337fee9e4..ea3646330 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -14,5 +14,6 @@ OBJS += passes/opt/opt_demorgan.o OBJS += passes/opt/rmports.o OBJS += passes/opt/opt_lut.o OBJS += passes/opt/pmux2shiftx.o +OBJS += passes/opt/muxpack.o endif diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc new file mode 100644 index 000000000..9668b0d43 --- /dev/null +++ b/passes/opt/muxpack.cc @@ -0,0 +1,256 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * 2019 Eddie Hung + * + * 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 MuxpackWorker +{ + Module *module; + SigMap sigmap; + + int mux_count, pmux_count; + + pool remove_cells; + + dict sig_chain_next; + dict sig_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; + + void make_sig_chain_next_prev() + { + for (auto wire : module->wires()) + { + if (wire->port_output || wire->get_bool_attribute("\\keep")) { + for (auto bit : sigmap(wire)) { + sigbit_with_non_chain_users.insert(bit); + } + } + } + + for (auto cell : module->cells()) + { + if (cell->type.in("$mux") && !cell->get_bool_attribute("\\keep")) + { + SigSpec a_sig = sigmap(cell->getPort("\\A")); + SigSpec b_sig = sigmap(cell->getPort("\\B")); + SigSpec y_sig = sigmap(cell->getPort("\\Y")); + + if (sig_chain_next.count(a_sig)) + for (auto a_bit : a_sig.bits()) + sigbit_with_non_chain_users.insert(a_bit); + else + sig_chain_next[a_sig] = cell; + + if (sig_chain_next.count(b_sig)) + for (auto b_bit : b_sig.bits()) + sigbit_with_non_chain_users.insert(b_bit); + else + sig_chain_next[b_sig] = cell; + + sig_chain_prev[y_sig] = cell; + continue; + } + + for (auto conn : cell->connections()) + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) + sigbit_with_non_chain_users.insert(bit); + } + } + + void find_chain_start_cells() + { + for (auto it : sig_chain_next) + { + SigSpec next_sig; + + for (auto bit : it.first.bits()) + if (sigbit_with_non_chain_users.count(bit)) + goto start_cell; + + next_sig = it.second->getPort("\\A"); + if (sig_chain_prev.count(next_sig) == 0) { + next_sig = it.second->getPort("\\B"); + if (sig_chain_prev.count(next_sig) == 0) + next_sig = SigSpec(); + } + + if (!next_sig.empty()) + { + Cell *c1 = sig_chain_prev.at(next_sig); + Cell *c2 = it.second; + + if (c1->type != c2->type) + goto start_cell; + + if (c1->parameters != c2->parameters) + goto start_cell; + + continue; + } + + start_cell: + chain_start_cells.insert(it.second); + } + } + + vector create_chain(Cell *start_cell) + { + vector chain; + + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); + + SigSpec y_sig = sigmap(c->getPort("\\Y")); + + if (sig_chain_next.count(y_sig) == 0) + break; + + c = sig_chain_next.at(y_sig); + if (chain_start_cells.count(c) != 0) + break; + } + + return chain; + } + + void process_chain(vector &chain) + { + if (GetSize(chain) < 2) + return; + + int cursor = 0; + while (cursor < GetSize(chain)) + { + int cases = GetSize(chain) - cursor; + + Cell *first_cell = chain[cursor]; + dict taps_dict; + + if (cases < 2) { + cursor++; + continue; + } + + Cell *last_cell = chain[cursor+cases-1]; + + log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n", + log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases); + + mux_count += cases; + pmux_count += 1; + + first_cell->type = "$pmux"; + SigSpec b_sig = first_cell->getPort("\\B"); + SigSpec s_sig = first_cell->getPort("\\S"); + + for (int i = 1; i < cases; i++) { + Cell* prev_cell = chain[cursor+i-1]; + Cell* cursor_cell = chain[cursor+i]; + if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) { + b_sig.append(cursor_cell->getPort("\\B")); + s_sig.append(cursor_cell->getPort("\\S")); + } + else { + b_sig.append(cursor_cell->getPort("\\A")); + s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S"))); + } + remove_cells.insert(cursor_cell); + } + + first_cell->setPort("\\B", b_sig); + first_cell->setPort("\\S", s_sig); + first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); + first_cell->setPort("\\Y", last_cell->getPort("\\Y")); + + cursor += cases; + } + } + + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); + + remove_cells.clear(); + sig_chain_next.clear(); + sig_chain_prev.clear(); + chain_start_cells.clear(); + } + + MuxpackWorker(Module *module) : + module(module), sigmap(module), mux_count(0), pmux_count(0) + { + make_sig_chain_next_prev(); + find_chain_start_cells(); + + for (auto c : chain_start_cells) { + vector chain = create_chain(c); + process_chain(chain); + } + + cleanup(); + } +}; + +struct MuxpackPass : public Pass { + MuxpackPass() : Pass("muxpack", "$mux cell cascades to $pmux") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" muxpack [selection]\n"); + log("\n"); + log("This pass converts cascaded chains of $mux cells (e.g. those created by if-else\n"); + log("constructs) into $pmux cells.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) + { + break; + } + extra_args(args, argidx, design); + + int mux_count = 0; + int pmux_count = 0; + + for (auto module : design->selected_modules()) { + MuxpackWorker worker(module); + mux_count += worker.mux_count; + pmux_count += worker.pmux_count; + } + + log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count); + } +} MuxpackPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From d2172c6846f710e9a362708e3308dd302110deb2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:44:50 -0700 Subject: Non chain user check using next_sig --- passes/opt/muxpack.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 9668b0d43..963083107 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -84,19 +84,17 @@ struct MuxpackWorker { for (auto it : sig_chain_next) { - SigSpec next_sig; - - for (auto bit : it.first.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - next_sig = it.second->getPort("\\A"); + SigSpec next_sig = it.second->getPort("\\A"); if (sig_chain_prev.count(next_sig) == 0) { next_sig = it.second->getPort("\\B"); if (sig_chain_prev.count(next_sig) == 0) next_sig = SigSpec(); } + for (auto bit : next_sig.bits()) + if (sigbit_with_non_chain_users.count(bit)) + goto start_cell; + if (!next_sig.empty()) { Cell *c1 = sig_chain_prev.at(next_sig); -- cgit v1.2.3 From 978fda94f684185a7d583a3865b7a68459344e46 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:46:42 -0700 Subject: Fix spacing --- passes/opt/muxpack.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 963083107..cb13a45b0 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -43,9 +43,8 @@ struct MuxpackWorker for (auto wire : module->wires()) { if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) { + for (auto bit : sigmap(wire)) sigbit_with_non_chain_users.insert(bit); - } } } @@ -58,8 +57,8 @@ struct MuxpackWorker SigSpec y_sig = sigmap(cell->getPort("\\Y")); if (sig_chain_next.count(a_sig)) - for (auto a_bit : a_sig.bits()) - sigbit_with_non_chain_users.insert(a_bit); + for (auto a_bit : a_sig.bits()) + sigbit_with_non_chain_users.insert(a_bit); else sig_chain_next[a_sig] = cell; @@ -70,7 +69,7 @@ struct MuxpackWorker sig_chain_next[b_sig] = cell; sig_chain_prev[y_sig] = cell; - continue; + continue; } for (auto conn : cell->connections()) @@ -182,7 +181,7 @@ struct MuxpackWorker first_cell->setPort("\\B", b_sig); first_cell->setPort("\\S", s_sig); - first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); + first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); first_cell->setPort("\\Y", last_cell->getPort("\\Y")); cursor += cases; -- cgit v1.2.3 From dc7b8c4b942f9d9bc61a87a81291244d0b73843b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 12:56:34 -0700 Subject: More cleanup --- passes/opt/muxpack.cc | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index cb13a45b0..ae4b67db2 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -37,6 +37,7 @@ struct MuxpackWorker dict sig_chain_prev; pool sigbit_with_non_chain_users; pool chain_start_cells; + pool candidate_cells; void make_sig_chain_next_prev() { @@ -59,14 +60,18 @@ struct MuxpackWorker if (sig_chain_next.count(a_sig)) for (auto a_bit : a_sig.bits()) sigbit_with_non_chain_users.insert(a_bit); - else + else { sig_chain_next[a_sig] = cell; + candidate_cells.insert(cell); + } if (sig_chain_next.count(b_sig)) for (auto b_bit : b_sig.bits()) sigbit_with_non_chain_users.insert(b_bit); - else + else { sig_chain_next[b_sig] = cell; + candidate_cells.insert(cell); + } sig_chain_prev[y_sig] = cell; continue; @@ -81,35 +86,34 @@ struct MuxpackWorker void find_chain_start_cells() { - for (auto it : sig_chain_next) + for (auto cell : candidate_cells) { - SigSpec next_sig = it.second->getPort("\\A"); + SigSpec next_sig = cell->getPort("\\A"); if (sig_chain_prev.count(next_sig) == 0) { - next_sig = it.second->getPort("\\B"); + next_sig = cell->getPort("\\B"); if (sig_chain_prev.count(next_sig) == 0) - next_sig = SigSpec(); - } - - for (auto bit : next_sig.bits()) - if (sigbit_with_non_chain_users.count(bit)) goto start_cell; + } - if (!next_sig.empty()) { + for (auto bit : next_sig.bits()) + if (sigbit_with_non_chain_users.count(bit)) + goto start_cell; + Cell *c1 = sig_chain_prev.at(next_sig); - Cell *c2 = it.second; + Cell *c2 = cell; if (c1->type != c2->type) goto start_cell; if (c1->parameters != c2->parameters) goto start_cell; - - continue; } + continue; + start_cell: - chain_start_cells.insert(it.second); + chain_start_cells.insert(cell); } } @@ -197,6 +201,7 @@ struct MuxpackWorker sig_chain_next.clear(); sig_chain_prev.clear(); chain_start_cells.clear(); + candidate_cells.clear(); } MuxpackWorker(Module *module) : -- cgit v1.2.3 From ccdf989025e57da7dfd5ab609676ebe3cfb2c2d6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 13:51:22 -0700 Subject: Support cascading $pmux.A with $mux.A and $mux.B --- passes/opt/muxpack.cc | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ae4b67db2..f9e5c8f09 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -51,10 +51,12 @@ struct MuxpackWorker for (auto cell : module->cells()) { - if (cell->type.in("$mux") && !cell->get_bool_attribute("\\keep")) + if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep")) { SigSpec a_sig = sigmap(cell->getPort("\\A")); - SigSpec b_sig = sigmap(cell->getPort("\\B")); + SigSpec b_sig; + if (cell->type == "$mux") + b_sig = sigmap(cell->getPort("\\B")); SigSpec y_sig = sigmap(cell->getPort("\\Y")); if (sig_chain_next.count(a_sig)) @@ -65,12 +67,14 @@ struct MuxpackWorker candidate_cells.insert(cell); } - if (sig_chain_next.count(b_sig)) - for (auto b_bit : b_sig.bits()) - sigbit_with_non_chain_users.insert(b_bit); - else { - sig_chain_next[b_sig] = cell; - candidate_cells.insert(cell); + if (!b_sig.empty()) { + if (sig_chain_next.count(b_sig)) + for (auto b_bit : b_sig.bits()) + sigbit_with_non_chain_users.insert(b_bit); + else { + sig_chain_next[b_sig] = cell; + candidate_cells.insert(cell); + } } sig_chain_prev[y_sig] = cell; @@ -88,10 +92,16 @@ struct MuxpackWorker { for (auto cell : candidate_cells) { + log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); + SigSpec next_sig = cell->getPort("\\A"); if (sig_chain_prev.count(next_sig) == 0) { - next_sig = cell->getPort("\\B"); - if (sig_chain_prev.count(next_sig) == 0) + if (cell->type == "$mux") { + next_sig = cell->getPort("\\B"); + if (sig_chain_prev.count(next_sig) == 0) + goto start_cell; + } + else goto start_cell; } @@ -103,10 +113,7 @@ struct MuxpackWorker Cell *c1 = sig_chain_prev.at(next_sig); Cell *c2 = cell; - if (c1->type != c2->type) - goto start_cell; - - if (c1->parameters != c2->parameters) + if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) goto start_cell; } @@ -220,15 +227,16 @@ struct MuxpackWorker }; struct MuxpackPass : public Pass { - MuxpackPass() : Pass("muxpack", "$mux cell cascades to $pmux") { } + MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { } void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); log(" muxpack [selection]\n"); log("\n"); - log("This pass converts cascaded chains of $mux cells (e.g. those created by if-else\n"); - log("constructs) into $pmux cells.\n"); + log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n"); + log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n"); + log("into $pmux cells.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From 5c277c6325b78bfe18cf294b63ea69ff272e69c5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 6 Jun 2019 14:21:34 -0700 Subject: Fix and test for balanced case --- passes/opt/muxpack.cc | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index f9e5c8f09..8c4db4e4d 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -94,23 +94,27 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec next_sig = cell->getPort("\\A"); - if (sig_chain_prev.count(next_sig) == 0) { - if (cell->type == "$mux") { - next_sig = cell->getPort("\\B"); - if (sig_chain_prev.count(next_sig) == 0) - goto start_cell; - } - else + SigSpec a_sig = cell->getPort("\\A"); + if (cell->type == "$mux") { + SigSpec b_sig = cell->getPort("\\B"); + if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) + goto start_cell; + + if (!sig_chain_prev.count(a_sig)) + a_sig = b_sig; + } + else if (cell->type == "$pmux") { + if (!sig_chain_prev.count(a_sig)) goto start_cell; } + else log_abort(); { - for (auto bit : next_sig.bits()) + for (auto bit : a_sig.bits()) if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - Cell *c1 = sig_chain_prev.at(next_sig); + Cell *c1 = sig_chain_prev.at(a_sig); Cell *c2 = cell; if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) -- cgit v1.2.3 From 5ab59cd59ee90abc4b6991486854dbe4c3f4d0a4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:36:19 -0700 Subject: Resolve @cliffordwolf comment on sigmap --- passes/opt/muxpack.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 8c4db4e4d..b060389e3 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -94,9 +94,9 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec a_sig = cell->getPort("\\A"); + SigSpec a_sig = sigmap(cell->getPort("\\A")); if (cell->type == "$mux") { - SigSpec b_sig = cell->getPort("\\B"); + SigSpec b_sig = sigmap(cell->getPort("\\B")); if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) goto start_cell; -- cgit v1.2.3 From 887df8914c64220b9f306b7d21f199fa247224fd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 11:37:52 -0700 Subject: Resolve @cliffordwolf comment on redundant check --- passes/opt/muxpack.cc | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index b060389e3..15a646e2e 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -109,17 +109,9 @@ struct MuxpackWorker } else log_abort(); - { - for (auto bit : a_sig.bits()) - if (sigbit_with_non_chain_users.count(bit)) - goto start_cell; - - Cell *c1 = sig_chain_prev.at(a_sig); - Cell *c2 = cell; - - if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH")) + for (auto bit : a_sig.bits()) + if (sigbit_with_non_chain_users.count(bit)) goto start_cell; - } continue; -- cgit v1.2.3 From 9b408838f191bb0390b6edff55770cab8e8ca15d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 14:18:17 -0700 Subject: Add ExclusiveDatabase to check exclusive $eq/$logic_not cell results --- passes/opt/muxpack.cc | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 15a646e2e..0cf9e0e30 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -24,6 +24,58 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct ExclusiveDatabase +{ + Module *module; + const SigMap &sigmap; + + dict sig_cmp_prev; + dict> sig_exclusive; + + ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) + { + SigSpec a_port, b_port, y_port; + for (auto cell : module->cells()) { + if (cell->type == "$eq") { + a_port = sigmap(cell->getPort("\\A")); + b_port = sigmap(cell->getPort("\\B")); + if (!b_port.is_fully_const()) { + if (!a_port.is_fully_const()) + continue; + std::swap(a_port, b_port); + } + y_port = sigmap(cell->getPort("\\Y")); + } + else if (cell->type == "$logic_not") { + a_port = sigmap(cell->getPort("\\A")); + b_port = Const(RTLIL::S0, GetSize(a_port)); + y_port = sigmap(cell->getPort("\\Y")); + } + else continue; + + auto r = sig_exclusive[a_port].insert(b_port.as_const()); + if (!r.second) + continue; + sig_cmp_prev[y_port] = a_port; + } + } + + bool query(const SigSpec& sig1, const SigSpec& sig2) const + { + auto it = sig_cmp_prev.find(sig1); + if (it == sig_cmp_prev.end()) + return false; + + auto jt = sig_cmp_prev.find(sig2); + if (jt == sig_cmp_prev.end()) + return false; + + log("query = %s %s\n", log_signal(it->second), log_signal(jt->second)); + return it->second == jt->second; + } +}; + + struct MuxpackWorker { Module *module; @@ -39,6 +91,8 @@ struct MuxpackWorker pool chain_start_cells; pool candidate_cells; + ExclusiveDatabase excl_db; + void make_sig_chain_next_prev() { for (auto wire : module->wires()) @@ -90,6 +144,7 @@ struct MuxpackWorker void find_chain_start_cells() { + Cell* first_cell = nullptr; for (auto cell : candidate_cells) { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); @@ -102,6 +157,13 @@ struct MuxpackWorker if (!sig_chain_prev.count(a_sig)) a_sig = b_sig; + + if (first_cell) { + SigSpec s_sig = sigmap(cell->getPort("\\S")); + SigSpec prev_s_sig = sigmap(first_cell->getPort("\\S")); + if (!excl_db.query(prev_s_sig, s_sig)) + goto start_cell; + } } else if (cell->type == "$pmux") { if (!sig_chain_prev.count(a_sig)) @@ -117,6 +179,7 @@ struct MuxpackWorker start_cell: chain_start_cells.insert(cell); + first_cell = cell; } } @@ -208,7 +271,7 @@ struct MuxpackWorker } MuxpackWorker(Module *module) : - module(module), sigmap(module), mux_count(0), pmux_count(0) + module(module), sigmap(module), mux_count(0), pmux_count(0), excl_db(module, sigmap) { make_sig_chain_next_prev(); find_chain_start_cells(); -- cgit v1.2.3 From ba52d9b4716b287b0a469597b748f9859e897329 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:34:16 -0700 Subject: Extend ExclusiveDatabase to query SigSpec-s (for $pmux) --- passes/opt/muxpack.cc | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 0cf9e0e30..4b02df394 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,7 +29,7 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict sig_cmp_prev; + dict sig_cmp_prev; dict> sig_exclusive; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) @@ -62,16 +62,23 @@ struct ExclusiveDatabase bool query(const SigSpec& sig1, const SigSpec& sig2) const { - auto it = sig_cmp_prev.find(sig1); - if (it == sig_cmp_prev.end()) - return false; - - auto jt = sig_cmp_prev.find(sig2); - if (jt == sig_cmp_prev.end()) - return false; + // FIXME: O(N) + for (auto bit1 : sig1.bits()) { + auto it = sig_cmp_prev.find(bit1); + if (it == sig_cmp_prev.end()) + return false; + + for (auto bit2 : sig2.bits()) { + auto jt = sig_cmp_prev.find(bit2); + if (jt == sig_cmp_prev.end()) + return false; + + if (it->second != jt->second) + return false; + } + } - log("query = %s %s\n", log_signal(it->second), log_signal(jt->second)); - return it->second == jt->second; + return true; } }; @@ -144,7 +151,6 @@ struct MuxpackWorker void find_chain_start_cells() { - Cell* first_cell = nullptr; for (auto cell : candidate_cells) { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); @@ -157,13 +163,6 @@ struct MuxpackWorker if (!sig_chain_prev.count(a_sig)) a_sig = b_sig; - - if (first_cell) { - SigSpec s_sig = sigmap(cell->getPort("\\S")); - SigSpec prev_s_sig = sigmap(first_cell->getPort("\\S")); - if (!excl_db.query(prev_s_sig, s_sig)) - goto start_cell; - } } else if (cell->type == "$pmux") { if (!sig_chain_prev.count(a_sig)) @@ -175,11 +174,19 @@ struct MuxpackWorker if (sigbit_with_non_chain_users.count(bit)) goto start_cell; + { + Cell *prev_cell = sig_chain_prev.at(a_sig); + log_assert(prev_cell); + SigSpec s_sig = sigmap(cell->getPort("\\S")); + SigSpec next_s_sig = sigmap(prev_cell->getPort("\\S")); + if (!excl_db.query(s_sig, next_s_sig)) + goto start_cell; + } + continue; start_cell: chain_start_cells.insert(cell); - first_cell = cell; } } @@ -243,6 +250,7 @@ struct MuxpackWorker s_sig.append(cursor_cell->getPort("\\S")); } else { + log_assert(cursor_cell->type == "$mux"); b_sig.append(cursor_cell->getPort("\\A")); s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S"))); } -- cgit v1.2.3 From f705f6a0b5d19d38cf41ba5f782847de54110463 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 7 Jun 2019 15:39:12 -0700 Subject: Comment O(N) -> O(N^2) --- passes/opt/muxpack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 4b02df394..f01d5474d 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -62,7 +62,7 @@ struct ExclusiveDatabase bool query(const SigSpec& sig1, const SigSpec& sig2) const { - // FIXME: O(N) + // FIXME: O(N^2) for (auto bit1 : sig1.bits()) { auto it = sig_cmp_prev.find(bit1); if (it == sig_cmp_prev.end()) -- cgit v1.2.3 From 5b999ae68decef5646ef0ccac53463f22fe18d8f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 10 Jun 2019 10:32:19 -0700 Subject: Elaborate muxpack doc --- passes/opt/muxpack.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index f01d5474d..b6f3313bf 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -302,8 +302,12 @@ struct MuxpackPass : public Pass { log(" muxpack [selection]\n"); log("\n"); log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n"); - log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n"); - log("into $pmux cells.\n"); + log("constructs) and $mux cells (e.g. those created by if-else constructs) into\n"); + log("$pmux cells.\n"); + log("\n"); + log("This optimisation is conservative --- it will only pack $mux or $pmux cells with\n"); + log("other such cells if it can be certain that the select lines are mutually\n"); + log("exclusive.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From 9892df17efadd0eafe5217e812fb4cec2bfdf6e5 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Tue, 11 Jun 2019 11:47:13 +0200 Subject: Generate satgen instance instead of calling sat pass --- passes/opt/opt_rmdff.cc | 108 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 23 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 72eac9111..4b9fe5823 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -17,11 +17,14 @@ * */ +#include "kernel/log.h" #include "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/satgen.h" +#include "kernel/satgen_algo.h" #include "kernel/sigtools.h" -#include "kernel/log.h" -#include #include +#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -456,36 +459,95 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) if (sat && has_init) { std::vector removed_sigbits; + DriverMap drvmap(mod); + // for (auto &sigbit : sig_q.bits()) { - for (int position =0; position < GetSize(sig_d); position += 1) { + for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; - RTLIL::Const sigbit_init_val = val_init.extract(position); if ((!q_sigbit.wire) || (!d_sigbit.wire)) { continue; } + std::map sat_pi; + + ezSatPtr ez; + SatGen satgen(ez.get(), &drvmap.sigmap); + std::set ez_cells; + std::vector modelExpressions; + std::vector modelValues; + + log("Optimizing: %s\n", log_id(q_sigbit.wire)); + log(" Cells:"); + for (const auto &cell : drvmap.cell_cone(d_sigbit)) { + if (ez_cells.count(cell) == 0) { + log(" %s\n", log_id(cell)); + if (!satgen.importCell(cell)) + log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), + RTLIL::id2cstr(cell->type)); + ez_cells.insert(cell); + } + } + + RTLIL::Const sigbit_init_val = val_init.extract(position); + int reg_init = satgen.importSigSpec(sigbit_init_val).front(); + + int output_a = satgen.importSigSpec(d_sigbit).front(); + modelExpressions.push_back(output_a); + + log(" Wires:"); + for (const auto &sig : drvmap.cone_inputs(d_sigbit)) { + if (sat_pi.count(sig) == 0) { + sat_pi[sig] = satgen.importSigSpec(sig).front(); + modelExpressions.push_back(sat_pi[sig]); + + if (sig == q_sigbit) { + ez->assume(ez->IFF(sat_pi[sig], reg_init)); + } + + if (sig.wire) { + log(" %s\n", log_id(sig.wire)); + } + } + } + + bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, reg_init)); + // bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, ez->NOT(reg_init))); + if (ez->getSolverTimoutStatus()) + log("Timeout\n"); + + log("Success: %d\n", success); + + // satgen.signals_eq(big_lhs, big_rhs, timestep); + + // auto iterable = drvmap.cone(d_sigbit); + + // // for (const auto &sig : drvmap.cone(d_sigbit)) + // for(auto begin=iterable.begin(); begin != iterable.end(); ++begin) + // { + // if (drvmap.count(*begin)) { + // if (drvmap.at(*begin).first) + // log("Running: %s\n", log_id(drvmap.at(*begin).first)); + // } + + // if ((*begin).wire) { + // log("Running: %s\n", log_id((*begin).wire)); + // } + // } + + char str[1024]; - sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", - log_id(d_sigbit.wire), - d_sigbit.offset, - sigbit_init_val.as_string().c_str(), - log_id(q_sigbit.wire), - q_sigbit.offset, - sigbit_init_val.as_string().c_str() - ); - log("Running: %s\n", str); - - log_flush(); - - pass->call(mod->design, str); - if (mod->design->scratchpad_get_bool("sat.success", false)) { - sprintf(str, "connect -set %s[%d] %s", - log_id(q_sigbit.wire), - q_sigbit.offset, - sigbit_init_val.as_string().c_str() - ); + // sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", log_id(d_sigbit.wire), d_sigbit.offset, + // sigbit_init_val.as_string().c_str(), log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); + // log("Running: %s\n", str); + + // log_flush(); + + // pass->call(mod->design, str); + // if (mod->design->scratchpad_get_bool("sat.success", false)) { + if (success) { + sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); log("Running: %s\n", str); log_flush(); pass->call(mod->design, str); -- cgit v1.2.3 From d69989b8d27eea16d793600b1779661f31161c6c Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Wed, 12 Jun 2019 19:35:05 +0200 Subject: Rename satgen_algo.h -> algo.h, code cleanup and refactoring --- passes/opt/opt_rmdff.cc | 95 ++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 73 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 4b9fe5823..b5a5735e7 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -21,7 +21,7 @@ #include "kernel/register.h" #include "kernel/rtlil.h" #include "kernel/satgen.h" -#include "kernel/satgen_algo.h" +#include "kernel/algo.h" #include "kernel/sigtools.h" #include #include @@ -32,6 +32,7 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; +std::map netlists; bool keepdc; bool sat; @@ -459,9 +460,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) if (sat && has_init) { std::vector removed_sigbits; - DriverMap drvmap(mod); + if (!netlists.count(mod)) { + netlists.emplace(mod, Netlist(mod, comb_cells_filt())); + } + + Netlist &net = netlists.at(mod); - // for (auto &sigbit : sig_q.bits()) { for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; @@ -470,83 +474,27 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) continue; } - std::map sat_pi; - ezSatPtr ez; - SatGen satgen(ez.get(), &drvmap.sigmap); - std::set ez_cells; - std::vector modelExpressions; - std::vector modelValues; - - log("Optimizing: %s\n", log_id(q_sigbit.wire)); - log(" Cells:"); - for (const auto &cell : drvmap.cell_cone(d_sigbit)) { - if (ez_cells.count(cell) == 0) { - log(" %s\n", log_id(cell)); - if (!satgen.importCell(cell)) - log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), - RTLIL::id2cstr(cell->type)); - ez_cells.insert(cell); - } - } - - RTLIL::Const sigbit_init_val = val_init.extract(position); - int reg_init = satgen.importSigSpec(sigbit_init_val).front(); - - int output_a = satgen.importSigSpec(d_sigbit).front(); - modelExpressions.push_back(output_a); - - log(" Wires:"); - for (const auto &sig : drvmap.cone_inputs(d_sigbit)) { - if (sat_pi.count(sig) == 0) { - sat_pi[sig] = satgen.importSigSpec(sig).front(); - modelExpressions.push_back(sat_pi[sig]); - - if (sig == q_sigbit) { - ez->assume(ez->IFF(sat_pi[sig], reg_init)); - } + SatGen satgen(ez.get(), &net.sigmap); - if (sig.wire) { - log(" %s\n", log_id(sig.wire)); - } - } + for (const auto &cell : cell_cone(net, d_sigbit)) { + if (!satgen.importCell(cell)) + log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), + RTLIL::id2cstr(cell->type)); } - bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, reg_init)); - // bool success = ez->solve(modelExpressions, modelValues, ez->IFF(output_a, ez->NOT(reg_init))); - if (ez->getSolverTimoutStatus()) - log("Timeout\n"); - - log("Success: %d\n", success); - - // satgen.signals_eq(big_lhs, big_rhs, timestep); - - // auto iterable = drvmap.cone(d_sigbit); + RTLIL::Const sigbit_init_val = val_init.extract(position); + int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); - // // for (const auto &sig : drvmap.cone(d_sigbit)) - // for(auto begin=iterable.begin(); begin != iterable.end(); ++begin) - // { - // if (drvmap.count(*begin)) { - // if (drvmap.at(*begin).first) - // log("Running: %s\n", log_id(drvmap.at(*begin).first)); - // } + int q_sat_pi = satgen.importSigBit(q_sigbit); + int d_sat_pi = satgen.importSigBit(d_sigbit); - // if ((*begin).wire) { - // log("Running: %s\n", log_id((*begin).wire)); - // } - // } + // log("DFF: %s", log_id(net.sigbit_driver_map[q_sigbit])); + bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); char str[1024]; - // sprintf(str, "sat -ignore_unknown_cells -prove %s[%d] %s -set %s[%d] %s", log_id(d_sigbit.wire), d_sigbit.offset, - // sigbit_init_val.as_string().c_str(), log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); - // log("Running: %s\n", str); - - // log_flush(); - - // pass->call(mod->design, str); - // if (mod->design->scratchpad_get_bool("sat.success", false)) { - if (success) { + if (!counter_example_found) { sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); log("Running: %s\n", str); log_flush(); @@ -561,6 +509,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) } } + return false; delete_dff: @@ -603,9 +552,9 @@ struct OptRmdffPass : public Pass { break; } extra_args(args, argidx, design); + netlists.clear(); - for (auto module : design->selected_modules()) - { + for (auto module : design->selected_modules()) { pool driven_bits; dict init_bits; -- cgit v1.2.3 From 8665f48879526f8f3ed79629f28a8686ed78a8ad Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 13 Jun 2019 19:35:37 +0200 Subject: Implement disconnection of constant register bits --- passes/opt/opt_rmdff.cc | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index b5a5735e7..c5db344e8 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -33,6 +33,8 @@ SigMap assign_map, dff_init_map; SigSet mux_drivers; dict> init_attributes; std::map netlists; +std::map comb_filters; + bool keepdc; bool sat; @@ -263,7 +265,7 @@ delete_dlatch: return true; } -bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) +bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) { RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::Const val_cp, val_rp, val_rv, val_ep; @@ -461,7 +463,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) std::vector removed_sigbits; if (!netlists.count(mod)) { - netlists.emplace(mod, Netlist(mod, comb_cells_filt())); + netlists.emplace(mod, Netlist(mod)); + comb_filters.emplace(mod, comb_cells_filt()); } Netlist &net = netlists.at(mod); @@ -477,7 +480,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) ezSatPtr ez; SatGen satgen(ez.get(), &net.sigmap); - for (const auto &cell : cell_cone(net, d_sigbit)) { + for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { if (!satgen.importCell(cell)) log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); @@ -489,17 +492,25 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff, Pass *pass) int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); - // log("DFF: %s", log_id(net.sigbit_driver_map[q_sigbit])); - bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); - char str[1024]; + if (position == 14) { + counter_example_found = false; + } + if (!counter_example_found) { - sprintf(str, "connect -set %s[%d] %s", log_id(q_sigbit.wire), q_sigbit.offset, sigbit_init_val.as_string().c_str()); - log("Running: %s\n", str); - log_flush(); - pass->call(mod->design, str); - // mod->connect(q_sigbit, sigbit_init_val); + + RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); + RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); + + for (auto &conn : mod->connections_) + net.sigmap(conn.first).replace(driver_port, dummy_wire, &conn.first); + + remove_init_attr(driver_port); + driver_port = dummy_wire; + + mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); + removed_sigbits.push_back(position); } } @@ -553,6 +564,7 @@ struct OptRmdffPass : public Pass { } extra_args(args, argidx, design); netlists.clear(); + comb_filters.clear(); for (auto module : design->selected_modules()) { pool driven_bits; @@ -631,7 +643,7 @@ struct OptRmdffPass : public Pass { for (auto &id : dff_list) { if (module->cell(id) != nullptr && - handle_dff(module, module->cells_[id], this)) + handle_dff(module, module->cells_[id])) total_count++; } -- cgit v1.2.3 From 291b36afeb1075b7c6329d1e57594ed3e6b71581 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 11:35:45 +0200 Subject: Some cleanup, revert sat.cc --- passes/opt/opt_rmdff.cc | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index c5db344e8..41bbdcd57 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -460,15 +460,19 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) } if (sat && has_init) { - std::vector removed_sigbits; + bool removed_sigbits = false; + // Create netlist for the module if not already available if (!netlists.count(mod)) { netlists.emplace(mod, Netlist(mod)); comb_filters.emplace(mod, comb_cells_filt()); } + // Load netlist for the module from the pool Netlist &net = netlists.at(mod); + + // For each register bit, try to prove that it cannot change from the initial value. If so, remove it for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; @@ -480,6 +484,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) ezSatPtr ez; SatGen satgen(ez.get(), &net.sigmap); + // Create SAT instance only for the cells that influence the register bit combinatorially for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { if (!satgen.importCell(cell)) log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), @@ -492,12 +497,10 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); + // Try to find out whether the register bit can change under some circumstances bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); - if (position == 14) { - counter_example_found = false; - } - + // If the register bit cannot change, we can replace it with a constant if (!counter_example_found) { RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); @@ -511,11 +514,11 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); - removed_sigbits.push_back(position); + removed_sigbits = true; } } - if (!removed_sigbits.empty()) { + if (removed_sigbits) { return true; } } -- cgit v1.2.3 From 53695e6729e8ae603be7e7cd9bc8b29758d61a11 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 11:39:24 +0200 Subject: Prepare for situation when port of the signal cannot be found --- passes/opt/opt_rmdff.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 41bbdcd57..cf89ac096 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -503,7 +503,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) // If the register bit cannot change, we can replace it with a constant if (!counter_example_found) { - RTLIL::SigBit &driver_port = net.driver_port(q_sigbit); + RTLIL::SigSpec driver_port = net.driver_port(q_sigbit); RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); for (auto &conn : mod->connections_) -- cgit v1.2.3 From 8451cbea896d2b441b5c78eb2813790616d10b84 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 14 Jun 2019 12:14:02 +0200 Subject: Move netlist helper module to passes/opt for the time being --- passes/opt/netlist.h | 317 ++++++++++++++++++++++++++++++++++++++++++++++++ passes/opt/opt_rmdff.cc | 2 +- 2 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 passes/opt/netlist.h (limited to 'passes/opt') diff --git a/passes/opt/netlist.h b/passes/opt/netlist.h new file mode 100644 index 000000000..f029ad6ab --- /dev/null +++ b/passes/opt/netlist.h @@ -0,0 +1,317 @@ +/* -*- c++ -*- + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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. + * + */ + +#ifndef SATGEN_ALGO_H +#define SATGEN_ALGO_H + +#include "kernel/celltypes.h" +#include "kernel/rtlil.h" +#include "kernel/sigtools.h" +#include + +YOSYS_NAMESPACE_BEGIN + +CellTypes comb_cells_filt() +{ + CellTypes ct; + + ct.setup_internals(); + ct.setup_stdcells(); + + return ct; +} + +struct Netlist { + RTLIL::Module *module; + SigMap sigmap; + CellTypes ct; + dict sigbit_driver_map; + dict> cell_inputs_map; + + Netlist(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) { setup_netlist(module, ct); } + + Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module), ct(ct) { setup_netlist(module, ct); } + + RTLIL::Cell *driver_cell(RTLIL::SigBit sig) const + { + sig = sigmap(sig); + if (!sigbit_driver_map.count(sig)) { + return NULL; + } + + return sigbit_driver_map.at(sig); + } + + RTLIL::SigSpec driver_port(RTLIL::SigBit sig) + { + RTLIL::Cell *cell = driver_cell(sig); + + if (!cell) { + return RTLIL::SigSpec(); + } + + for (auto &port : cell->connections_) { + if (ct.cell_output(cell->type, port.first)) { + RTLIL::SigSpec port_sig = sigmap(port.second); + for (int i = 0; i < GetSize(port_sig); i++) { + if (port_sig[i] == sig) { + return port.second[i]; + } + } + } + } + + return RTLIL::SigSpec(); + } + + void setup_netlist(RTLIL::Module *module, const CellTypes &ct) + { + for (auto cell : module->cells()) { + if (ct.cell_known(cell->type)) { + std::set inputs, outputs; + for (auto &port : cell->connections()) { + std::vector bits = sigmap(port.second).to_sigbit_vector(); + if (ct.cell_output(cell->type, port.first)) + outputs.insert(bits.begin(), bits.end()); + else + inputs.insert(bits.begin(), bits.end()); + } + cell_inputs_map[cell] = inputs; + for (auto &bit : outputs) { + sigbit_driver_map[bit] = cell; + }; + } + } + } +}; + +namespace detail +{ +struct NetlistConeWireIter : public std::iterator { + using set_iter_t = std::set::iterator; + + const Netlist &net; + RTLIL::SigBit sig; + bool sentinel; + CellTypes *cell_filter; + + std::stack> dfs_path_stack; + std::set cells_visited; + + NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true), cell_filter(NULL) {} + + NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) + : net(net), sig(sig), sentinel(false), cell_filter(cell_filter) + { + } + + const RTLIL::SigBit &operator*() const { return sig; }; + bool operator!=(const NetlistConeWireIter &other) const + { + if (sentinel || other.sentinel) { + return sentinel != other.sentinel; + } else { + return sig != other.sig; + } + } + + bool operator==(const NetlistConeWireIter &other) const + { + if (sentinel || other.sentinel) { + return sentinel == other.sentinel; + } else { + return sig == other.sig; + } + } + + void next_sig_in_dag() + { + while (1) { + if (dfs_path_stack.empty()) { + sentinel = true; + return; + } + + auto &cell_inputs_iter = dfs_path_stack.top().first; + auto &cell_inputs_iter_guard = dfs_path_stack.top().second; + + cell_inputs_iter++; + if (cell_inputs_iter != cell_inputs_iter_guard) { + sig = *cell_inputs_iter; + return; + } else { + dfs_path_stack.pop(); + } + } + } + + NetlistConeWireIter &operator++() + { + RTLIL::Cell *cell = net.driver_cell(sig); + + if (!cell) { + next_sig_in_dag(); + return *this; + } + + if (cells_visited.count(cell)) { + next_sig_in_dag(); + return *this; + } + + if ((cell_filter) && (!cell_filter->cell_known(cell->type))) { + next_sig_in_dag(); + return *this; + } + + auto &inputs = net.cell_inputs_map.at(cell); + dfs_path_stack.push(std::make_pair(inputs.begin(), inputs.end())); + cells_visited.insert(cell); + sig = (*dfs_path_stack.top().first); + return *this; + } +}; + +struct NetlistConeWireIterable { + const Netlist &net; + RTLIL::SigBit sig; + CellTypes *cell_filter; + + NetlistConeWireIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) + { + } + + NetlistConeWireIter begin() { return NetlistConeWireIter(net, sig, cell_filter); } + NetlistConeWireIter end() { return NetlistConeWireIter(net); } +}; + +struct NetlistConeCellIter : public std::iterator { + const Netlist &net; + + NetlistConeWireIter sig_iter; + + NetlistConeCellIter(const Netlist &net) : net(net), sig_iter(net) {} + + NetlistConeCellIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig_iter(net, sig, cell_filter) + { + if ((!sig_iter.sentinel) && (!has_driver_cell(*sig_iter))) { + ++(*this); + } + } + + bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } + + RTLIL::Cell *operator*() const { return net.sigbit_driver_map.at(*sig_iter); }; + + bool operator!=(const NetlistConeCellIter &other) const { return sig_iter != other.sig_iter; } + bool operator==(const NetlistConeCellIter &other) const { return sig_iter == other.sig_iter; } + NetlistConeCellIter &operator++() + { + while (true) { + ++sig_iter; + if (sig_iter.sentinel) { + return *this; + } + + RTLIL::Cell* cell = net.driver_cell(*sig_iter); + + if (!cell) { + continue; + } + + if ((sig_iter.cell_filter) && (!sig_iter.cell_filter->cell_known(cell->type))) { + continue; + } + + if (!sig_iter.cells_visited.count(cell)) { + return *this; + } + } + } +}; + +struct NetlistConeCellIterable { + const Netlist &net; + RTLIL::SigBit sig; + CellTypes *cell_filter; + + NetlistConeCellIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) + { + } + + NetlistConeCellIter begin() { return NetlistConeCellIter(net, sig, cell_filter); } + NetlistConeCellIter end() { return NetlistConeCellIter(net); } +}; + +// struct NetlistConeInputsIter : public std::iterator { +// const Netlist &net; +// RTLIL::SigBit sig; + +// NetlistConeWireIter sig_iter; + +// bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } + +// NetlistConeInputsIter(const Netlist &net, RTLIL::SigBit sig = NULL) : net(net), sig(sig), sig_iter(net, sig) +// { +// if ((sig != NULL) && (has_driver_cell(sig_iter))) { +// ++(*this); +// } +// } + +// const RTLIL::SigBit &operator*() const { return sig_iter; }; +// bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } +// bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } +// NetlistConeInputsIter &operator++() +// { +// do { +// ++sig_iter; +// if (sig_iter->empty()) { +// return *this; +// } +// } while (has_driver_cell(sig_iter)); + +// return *this; +// } +// }; + +// struct NetlistConeInputsIterable { +// const Netlist &net; +// RTLIL::SigBit sig; + +// NetlistConeInputsIterable(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig) {} + +// NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, sig); } +// NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } +// }; +} // namespace detail + +detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) +{ + return detail::NetlistConeWireIterable(net, net.sigmap(sig), cell_filter = cell_filter); +} + +// detail::NetlistConeInputsIterable cone_inputs(RTLIL::SigBit sig) { return NetlistConeInputsIterable(this, &sig); } +detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) +{ + return detail::NetlistConeCellIterable(net, net.sigmap(sig), cell_filter); +} + +YOSYS_NAMESPACE_END + +#endif diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index f44e6e58c..0ab91ca9e 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -21,8 +21,8 @@ #include "kernel/register.h" #include "kernel/rtlil.h" #include "kernel/satgen.h" -#include "kernel/algo.h" #include "kernel/sigtools.h" +#include "netlist.h" #include #include -- cgit v1.2.3 From 2454ad99bf49afe752d6fd1c1567f59ee9e26736 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 20 Jun 2019 13:44:21 +0200 Subject: Refactor "opt_rmdff -sat" Signed-off-by: Clifford Wolf --- passes/opt/netlist.h | 317 ------------------------------------------------ passes/opt/opt_rmdff.cc | 88 +++++++------- 2 files changed, 46 insertions(+), 359 deletions(-) delete mode 100644 passes/opt/netlist.h (limited to 'passes/opt') diff --git a/passes/opt/netlist.h b/passes/opt/netlist.h deleted file mode 100644 index f029ad6ab..000000000 --- a/passes/opt/netlist.h +++ /dev/null @@ -1,317 +0,0 @@ -/* -*- c++ -*- - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * 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. - * - */ - -#ifndef SATGEN_ALGO_H -#define SATGEN_ALGO_H - -#include "kernel/celltypes.h" -#include "kernel/rtlil.h" -#include "kernel/sigtools.h" -#include - -YOSYS_NAMESPACE_BEGIN - -CellTypes comb_cells_filt() -{ - CellTypes ct; - - ct.setup_internals(); - ct.setup_stdcells(); - - return ct; -} - -struct Netlist { - RTLIL::Module *module; - SigMap sigmap; - CellTypes ct; - dict sigbit_driver_map; - dict> cell_inputs_map; - - Netlist(RTLIL::Module *module) : module(module), sigmap(module), ct(module->design) { setup_netlist(module, ct); } - - Netlist(RTLIL::Module *module, const CellTypes &ct) : module(module), sigmap(module), ct(ct) { setup_netlist(module, ct); } - - RTLIL::Cell *driver_cell(RTLIL::SigBit sig) const - { - sig = sigmap(sig); - if (!sigbit_driver_map.count(sig)) { - return NULL; - } - - return sigbit_driver_map.at(sig); - } - - RTLIL::SigSpec driver_port(RTLIL::SigBit sig) - { - RTLIL::Cell *cell = driver_cell(sig); - - if (!cell) { - return RTLIL::SigSpec(); - } - - for (auto &port : cell->connections_) { - if (ct.cell_output(cell->type, port.first)) { - RTLIL::SigSpec port_sig = sigmap(port.second); - for (int i = 0; i < GetSize(port_sig); i++) { - if (port_sig[i] == sig) { - return port.second[i]; - } - } - } - } - - return RTLIL::SigSpec(); - } - - void setup_netlist(RTLIL::Module *module, const CellTypes &ct) - { - for (auto cell : module->cells()) { - if (ct.cell_known(cell->type)) { - std::set inputs, outputs; - for (auto &port : cell->connections()) { - std::vector bits = sigmap(port.second).to_sigbit_vector(); - if (ct.cell_output(cell->type, port.first)) - outputs.insert(bits.begin(), bits.end()); - else - inputs.insert(bits.begin(), bits.end()); - } - cell_inputs_map[cell] = inputs; - for (auto &bit : outputs) { - sigbit_driver_map[bit] = cell; - }; - } - } - } -}; - -namespace detail -{ -struct NetlistConeWireIter : public std::iterator { - using set_iter_t = std::set::iterator; - - const Netlist &net; - RTLIL::SigBit sig; - bool sentinel; - CellTypes *cell_filter; - - std::stack> dfs_path_stack; - std::set cells_visited; - - NetlistConeWireIter(const Netlist &net) : net(net), sentinel(true), cell_filter(NULL) {} - - NetlistConeWireIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) - : net(net), sig(sig), sentinel(false), cell_filter(cell_filter) - { - } - - const RTLIL::SigBit &operator*() const { return sig; }; - bool operator!=(const NetlistConeWireIter &other) const - { - if (sentinel || other.sentinel) { - return sentinel != other.sentinel; - } else { - return sig != other.sig; - } - } - - bool operator==(const NetlistConeWireIter &other) const - { - if (sentinel || other.sentinel) { - return sentinel == other.sentinel; - } else { - return sig == other.sig; - } - } - - void next_sig_in_dag() - { - while (1) { - if (dfs_path_stack.empty()) { - sentinel = true; - return; - } - - auto &cell_inputs_iter = dfs_path_stack.top().first; - auto &cell_inputs_iter_guard = dfs_path_stack.top().second; - - cell_inputs_iter++; - if (cell_inputs_iter != cell_inputs_iter_guard) { - sig = *cell_inputs_iter; - return; - } else { - dfs_path_stack.pop(); - } - } - } - - NetlistConeWireIter &operator++() - { - RTLIL::Cell *cell = net.driver_cell(sig); - - if (!cell) { - next_sig_in_dag(); - return *this; - } - - if (cells_visited.count(cell)) { - next_sig_in_dag(); - return *this; - } - - if ((cell_filter) && (!cell_filter->cell_known(cell->type))) { - next_sig_in_dag(); - return *this; - } - - auto &inputs = net.cell_inputs_map.at(cell); - dfs_path_stack.push(std::make_pair(inputs.begin(), inputs.end())); - cells_visited.insert(cell); - sig = (*dfs_path_stack.top().first); - return *this; - } -}; - -struct NetlistConeWireIterable { - const Netlist &net; - RTLIL::SigBit sig; - CellTypes *cell_filter; - - NetlistConeWireIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) - { - } - - NetlistConeWireIter begin() { return NetlistConeWireIter(net, sig, cell_filter); } - NetlistConeWireIter end() { return NetlistConeWireIter(net); } -}; - -struct NetlistConeCellIter : public std::iterator { - const Netlist &net; - - NetlistConeWireIter sig_iter; - - NetlistConeCellIter(const Netlist &net) : net(net), sig_iter(net) {} - - NetlistConeCellIter(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig_iter(net, sig, cell_filter) - { - if ((!sig_iter.sentinel) && (!has_driver_cell(*sig_iter))) { - ++(*this); - } - } - - bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } - - RTLIL::Cell *operator*() const { return net.sigbit_driver_map.at(*sig_iter); }; - - bool operator!=(const NetlistConeCellIter &other) const { return sig_iter != other.sig_iter; } - bool operator==(const NetlistConeCellIter &other) const { return sig_iter == other.sig_iter; } - NetlistConeCellIter &operator++() - { - while (true) { - ++sig_iter; - if (sig_iter.sentinel) { - return *this; - } - - RTLIL::Cell* cell = net.driver_cell(*sig_iter); - - if (!cell) { - continue; - } - - if ((sig_iter.cell_filter) && (!sig_iter.cell_filter->cell_known(cell->type))) { - continue; - } - - if (!sig_iter.cells_visited.count(cell)) { - return *this; - } - } - } -}; - -struct NetlistConeCellIterable { - const Netlist &net; - RTLIL::SigBit sig; - CellTypes *cell_filter; - - NetlistConeCellIterable(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) : net(net), sig(sig), cell_filter(cell_filter) - { - } - - NetlistConeCellIter begin() { return NetlistConeCellIter(net, sig, cell_filter); } - NetlistConeCellIter end() { return NetlistConeCellIter(net); } -}; - -// struct NetlistConeInputsIter : public std::iterator { -// const Netlist &net; -// RTLIL::SigBit sig; - -// NetlistConeWireIter sig_iter; - -// bool has_driver_cell(const RTLIL::SigBit &s) { return net.sigbit_driver_map.count(s); } - -// NetlistConeInputsIter(const Netlist &net, RTLIL::SigBit sig = NULL) : net(net), sig(sig), sig_iter(net, sig) -// { -// if ((sig != NULL) && (has_driver_cell(sig_iter))) { -// ++(*this); -// } -// } - -// const RTLIL::SigBit &operator*() const { return sig_iter; }; -// bool operator!=(const NetlistConeInputsIter &other) const { return sig_iter != other.sig_iter; } -// bool operator==(const NetlistConeInputsIter &other) const { return sig_iter == other.sig_iter; } -// NetlistConeInputsIter &operator++() -// { -// do { -// ++sig_iter; -// if (sig_iter->empty()) { -// return *this; -// } -// } while (has_driver_cell(sig_iter)); - -// return *this; -// } -// }; - -// struct NetlistConeInputsIterable { -// const Netlist &net; -// RTLIL::SigBit sig; - -// NetlistConeInputsIterable(const Netlist &net, RTLIL::SigBit sig) : net(net), sig(sig) {} - -// NetlistConeInputsIter begin() { return NetlistConeInputsIter(net, sig); } -// NetlistConeInputsIter end() { return NetlistConeInputsIter(net); } -// }; -} // namespace detail - -detail::NetlistConeWireIterable cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) -{ - return detail::NetlistConeWireIterable(net, net.sigmap(sig), cell_filter = cell_filter); -} - -// detail::NetlistConeInputsIterable cone_inputs(RTLIL::SigBit sig) { return NetlistConeInputsIterable(this, &sig); } -detail::NetlistConeCellIterable cell_cone(const Netlist &net, RTLIL::SigBit sig, CellTypes *cell_filter = NULL) -{ - return detail::NetlistConeCellIterable(net, net.sigmap(sig), cell_filter); -} - -YOSYS_NAMESPACE_END - -#endif diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 0ab91ca9e..5fc28ae92 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -22,7 +22,6 @@ #include "kernel/rtlil.h" #include "kernel/satgen.h" #include "kernel/sigtools.h" -#include "netlist.h" #include #include @@ -31,9 +30,8 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map, dff_init_map; SigSet mux_drivers; +dict bit2driver; dict> init_attributes; -std::map netlists; -std::map comb_filters; bool keepdc; bool sat; @@ -459,41 +457,46 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) dff->unsetPort("\\E"); } - if (sat && has_init) { + if (sat && has_init && (!sig_r.size() || val_init == val_rv)) + { bool removed_sigbits = false; - // Create netlist for the module if not already available - if (!netlists.count(mod)) { - netlists.emplace(mod, Netlist(mod)); - comb_filters.emplace(mod, comb_cells_filt()); - } - - // Load netlist for the module from the pool - Netlist &net = netlists.at(mod); - + ezSatPtr ez; + SatGen satgen(ez.get(), &assign_map); + pool sat_cells; + + std::function sat_import_cell = [&](Cell *c) { + if (!sat_cells.insert(c).second) + return; + if (!satgen.importCell(c)) + return; + for (auto &conn : c->connections()) { + if (!c->input(conn.first)) + continue; + for (auto bit : assign_map(conn.second)) + if (bit2driver.count(bit)) + sat_import_cell(bit2driver.at(bit)); + } + }; // For each register bit, try to prove that it cannot change from the initial value. If so, remove it for (int position = 0; position < GetSize(sig_d); position += 1) { RTLIL::SigBit q_sigbit = sig_q[position]; RTLIL::SigBit d_sigbit = sig_d[position]; - if ((!q_sigbit.wire) || (!d_sigbit.wire)) { + if ((!q_sigbit.wire) || (!d_sigbit.wire)) continue; - } - ezSatPtr ez; - SatGen satgen(ez.get(), &net.sigmap); + if (!bit2driver.count(d_sigbit)) + continue; - // Create SAT instance only for the cells that influence the register bit combinatorially - for (const auto &cell : cell_cone(net, d_sigbit, &comb_filters.at(mod))) { - if (!satgen.importCell(cell)) - log_error("Can't create SAT model for cell %s (%s)!\n", RTLIL::id2cstr(cell->name), - RTLIL::id2cstr(cell->type)); - } + sat_import_cell(bit2driver.at(d_sigbit)); - RTLIL::Const sigbit_init_val = val_init.extract(position); - int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); + RTLIL::State sigbit_init_val = val_init[position]; + if (sigbit_init_val != State::S0 && sigbit_init_val != State::S1) + continue; + int init_sat_pi = satgen.importSigSpec(sigbit_init_val).front(); int q_sat_pi = satgen.importSigBit(q_sigbit); int d_sat_pi = satgen.importSigBit(d_sigbit); @@ -501,24 +504,21 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) bool counter_example_found = ez->solve(ez->IFF(q_sat_pi, init_sat_pi), ez->NOT(ez->IFF(d_sat_pi, init_sat_pi))); // If the register bit cannot change, we can replace it with a constant - if (!counter_example_found) { - - RTLIL::SigSpec driver_port = net.driver_port(q_sigbit); - RTLIL::Wire *dummy_wire = mod->addWire(NEW_ID, 1); - - for (auto &conn : mod->connections_) - net.sigmap(conn.first).replace(driver_port, dummy_wire, &conn.first); - - remove_init_attr(driver_port); - driver_port = dummy_wire; + if (!counter_example_found) + { + log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, + position, log_id(dff), log_id(dff->type), log_id(mod)); - mod->connect(RTLIL::SigSig(q_sigbit, sigbit_init_val)); + SigSpec tmp = dff->getPort("\\D"); + tmp[position] = sigbit_init_val; + dff->setPort("\\D", tmp); removed_sigbits = true; } } if (removed_sigbits) { + handle_dff(mod, dff); return true; } } @@ -566,8 +566,6 @@ struct OptRmdffPass : public Pass { break; } extra_args(args, argidx, design); - netlists.clear(); - comb_filters.clear(); for (auto module : design->selected_modules()) { pool driven_bits; @@ -576,6 +574,7 @@ struct OptRmdffPass : public Pass { assign_map.set(module); dff_init_map.set(module); mux_drivers.clear(); + bit2driver.clear(); init_attributes.clear(); for (auto wire : module->wires()) @@ -600,17 +599,21 @@ struct OptRmdffPass : public Pass { driven_bits.insert(bit); } } - mux_drivers.clear(); std::vector dff_list; std::vector dffsr_list; std::vector dlatch_list; for (auto cell : module->cells()) { - for (auto &conn : cell->connections()) - if (cell->output(conn.first) || !cell->known()) - for (auto bit : assign_map(conn.second)) + for (auto &conn : cell->connections()) { + bool is_output = cell->output(conn.first); + if (is_output || !cell->known()) + for (auto bit : assign_map(conn.second)) { + if (is_output) + bit2driver[bit] = cell; driven_bits.insert(bit); + } + } if (cell->type == "$mux" || cell->type == "$pmux") { if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) @@ -682,6 +685,7 @@ struct OptRmdffPass : public Pass { assign_map.clear(); mux_drivers.clear(); + bit2driver.clear(); init_attributes.clear(); if (total_count || total_initdrv) -- cgit v1.2.3 From 641b86d25f5baa898bf5fca3d1a8f2fd4f5954e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:45:31 -0700 Subject: Fix up ExclusiveDatabase with @cliffordwolf's help --- passes/opt/muxpack.cc | 69 +++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 35 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index b6f3313bf..ae4f7ba9c 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,54 +29,53 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict sig_cmp_prev; - dict> sig_exclusive; + dict> sig_cmp_prev; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) { - SigSpec a_port, b_port, y_port; + SigSpec const_sig, nonconst_sig, y_port; for (auto cell : module->cells()) { if (cell->type == "$eq") { - a_port = sigmap(cell->getPort("\\A")); - b_port = sigmap(cell->getPort("\\B")); - if (!b_port.is_fully_const()) { - if (!a_port.is_fully_const()) + nonconst_sig = sigmap(cell->getPort("\\A")); + const_sig = sigmap(cell->getPort("\\B")); + if (!const_sig.is_fully_const()) { + if (!nonconst_sig.is_fully_const()) continue; - std::swap(a_port, b_port); + std::swap(nonconst_sig, const_sig); } y_port = sigmap(cell->getPort("\\Y")); } else if (cell->type == "$logic_not") { - a_port = sigmap(cell->getPort("\\A")); - b_port = Const(RTLIL::S0, GetSize(a_port)); + nonconst_sig = sigmap(cell->getPort("\\A")); + const_sig = Const(RTLIL::S0, GetSize(nonconst_sig)); y_port = sigmap(cell->getPort("\\Y")); } else continue; - auto r = sig_exclusive[a_port].insert(b_port.as_const()); - if (!r.second) - continue; - sig_cmp_prev[y_port] = a_port; - } - } + log_assert(!nonconst_sig.empty()); + log_assert(!const_sig.empty()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + } + } - bool query(const SigSpec& sig1, const SigSpec& sig2) const - { - // FIXME: O(N^2) - for (auto bit1 : sig1.bits()) { - auto it = sig_cmp_prev.find(bit1); - if (it == sig_cmp_prev.end()) - return false; - - for (auto bit2 : sig2.bits()) { - auto jt = sig_cmp_prev.find(bit2); - if (jt == sig_cmp_prev.end()) - return false; - - if (it->second != jt->second) - return false; - } - } + bool query(const SigSpec &sig) const + { + SigSpec nonconst_sig; + pool const_values; + + for (auto bit : sig.bits()) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) + return false; + + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) + return false; + + if (!const_values.insert(it->second.second).second) + return false; + } return true; } @@ -178,8 +177,8 @@ struct MuxpackWorker Cell *prev_cell = sig_chain_prev.at(a_sig); log_assert(prev_cell); SigSpec s_sig = sigmap(cell->getPort("\\S")); - SigSpec next_s_sig = sigmap(prev_cell->getPort("\\S")); - if (!excl_db.query(s_sig, next_s_sig)) + s_sig.append(sigmap(prev_cell->getPort("\\S"))); + if (!excl_db.query(s_sig)) goto start_cell; } -- cgit v1.2.3 From d89d663c92853fcd7f9d75b392ec4133ba2f1d89 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:52:28 -0700 Subject: Add doc --- passes/opt/muxpack.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index ae4f7ba9c..c8b226c78 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -304,9 +304,9 @@ struct MuxpackPass : public Pass { log("constructs) and $mux cells (e.g. those created by if-else constructs) into\n"); log("$pmux cells.\n"); log("\n"); - log("This optimisation is conservative --- it will only pack $mux or $pmux cells with\n"); - log("other such cells if it can be certain that the select lines are mutually\n"); - log("exclusive.\n"); + log("This optimisation is conservative --- it will only pack $mux or $pmux cells\n"); + log("whose select lines are driven by '$eq' cells with other such cells if it can be\n"); + log("certain that their select inputs are mutually exclusive.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From 15535112b7b4caa1da75274397c5a3ba885a7349 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 11:52:51 -0700 Subject: Fix spacing --- passes/opt/muxpack.cc | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index c8b226c78..4468e8734 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -52,30 +52,30 @@ struct ExclusiveDatabase } else continue; - log_assert(!nonconst_sig.empty()); - log_assert(!const_sig.empty()); - sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); - } - } - - bool query(const SigSpec &sig) const - { - SigSpec nonconst_sig; - pool const_values; - - for (auto bit : sig.bits()) { - auto it = sig_cmp_prev.find(bit); - if (it == sig_cmp_prev.end()) - return false; - - if (nonconst_sig.empty()) - nonconst_sig = it->second.first; - else if (nonconst_sig != it->second.first) - return false; - - if (!const_values.insert(it->second.second).second) - return false; - } + log_assert(!nonconst_sig.empty()); + log_assert(!const_sig.empty()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + } + } + + bool query(const SigSpec &sig) const + { + SigSpec nonconst_sig; + pool const_values; + + for (auto bit : sig.bits()) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) + return false; + + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) + return false; + + if (!const_values.insert(it->second.second).second) + return false; + } return true; } -- cgit v1.2.3 From 545cfbbe0dcc36f18dce6429498f4d87112879e2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 21 Jun 2019 12:31:14 -0700 Subject: Cope with $reduce_or common in case --- passes/opt/muxpack.cc | 42 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 4468e8734..6697d6ca1 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -29,11 +29,13 @@ struct ExclusiveDatabase Module *module; const SigMap &sigmap; - dict> sig_cmp_prev; + dict>> sig_cmp_prev; ExclusiveDatabase(Module *module, const SigMap &sigmap) : module(module), sigmap(sigmap) { - SigSpec const_sig, nonconst_sig, y_port; + SigSpec const_sig, nonconst_sig; + SigBit y_port; + pool reduce_or; for (auto cell : module->cells()) { if (cell->type == "$eq") { nonconst_sig = sigmap(cell->getPort("\\A")); @@ -50,11 +52,40 @@ struct ExclusiveDatabase const_sig = Const(RTLIL::S0, GetSize(nonconst_sig)); y_port = sigmap(cell->getPort("\\Y")); } + else if (cell->type == "$reduce_or") { + reduce_or.insert(cell); + continue; + } else continue; log_assert(!nonconst_sig.empty()); log_assert(!const_sig.empty()); - sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,const_sig.as_const()); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::vector{const_sig.as_const()}); + } + + for (auto cell : reduce_or) { + nonconst_sig = SigSpec(); + std::vector values; + SigSpec a_port = sigmap(cell->getPort("\\A")); + for (auto bit : a_port) { + auto it = sig_cmp_prev.find(bit); + if (it == sig_cmp_prev.end()) { + nonconst_sig = SigSpec(); + break; + } + if (nonconst_sig.empty()) + nonconst_sig = it->second.first; + else if (nonconst_sig != it->second.first) { + nonconst_sig = SigSpec(); + break; + } + for (auto value : it->second.second) + values.push_back(value); + } + if (nonconst_sig.empty()) + continue; + y_port = sigmap(cell->getPort("\\Y")); + sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values)); } } @@ -73,8 +104,9 @@ struct ExclusiveDatabase else if (nonconst_sig != it->second.first) return false; - if (!const_values.insert(it->second.second).second) - return false; + for (auto value : it->second.second) + if (!const_values.insert(value).second) + return false; } return true; -- cgit v1.2.3 From 8e9ef891febb47f512710de591401539ad521634 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 11:00:44 +0200 Subject: Do not clean up buffer cells with "keep" attribute, closes #1128 Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index cfb0f788a..5f75288e2 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -480,7 +480,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool std::vector delcells; for (auto cell : module->cells()) - if (cell->type.in("$pos", "$_BUF_")) { + if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) { bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec y = cell->getPort("\\Y"); -- cgit v1.2.3 From 0b7d648c6a71594f8a17e78aef8f62b6f6448390 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 26 Jun 2019 17:54:17 +0200 Subject: Improve opt_clean handling of unused public wires Signed-off-by: Clifford Wolf --- passes/opt/opt_clean.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 5f75288e2..a8a8e0bc7 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -326,8 +326,8 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos 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 + if (!purge_mode && check_public_name(wire->name) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) { + // do not get rid of public names unless in purge mode or if the wire is entirely unused, not even aliased } else if (!raw_used_signals.check_any(s1)) { // delete wires that aren't used by anything directly -- cgit v1.2.3 From 7c14678ec0f4b16134d94a7419f59e7edb634cf6 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 27 Jun 2019 10:59:12 +0200 Subject: Add "pmux2shiftx -norange", fixes #1135 Signed-off-by: Clifford Wolf --- passes/opt/pmux2shiftx.cc | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 29870f510..65d8b8f32 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -221,6 +221,9 @@ struct Pmux2ShiftxPass : public Pass { log(" select strategy for one-hot encoded control signals\n"); log(" default: pmux\n"); log("\n"); + log(" -norange\n"); + log(" disable $sub inference for \"range decoders\"\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { @@ -230,6 +233,7 @@ struct Pmux2ShiftxPass : public Pass { bool optimize_onehot = true; bool verbose = false; bool verbose_onehot = false; + bool norange = false; log_header(design, "Executing PMUX2SHIFTX pass.\n"); @@ -270,6 +274,10 @@ struct Pmux2ShiftxPass : public Pass { verbose_onehot = true; continue; } + if (args[argidx] == "-norange") { + norange = true; + continue; + } break; } extra_args(args, argidx, design); @@ -559,7 +567,7 @@ struct Pmux2ShiftxPass : public Pass { int this_inv_delta = this_maxval - this_minval; bool this_inv = false; - if (this_delta != this_inv_delta) + if (!norange && this_delta != this_inv_delta) this_inv = this_inv_delta < this_delta; else if (this_maxval != this_inv_maxval) this_inv = this_inv_maxval < this_maxval; @@ -574,7 +582,7 @@ struct Pmux2ShiftxPass : public Pass { if (best_src_col < 0) this_is_better = true; - else if (this_delta != best_delta) + else if (!norange && this_delta != best_delta) this_is_better = this_delta < best_delta; else if (this_maxval != best_maxval) this_is_better = this_maxval < best_maxval; @@ -656,7 +664,7 @@ struct Pmux2ShiftxPass : public Pass { // check density percentages Const offset(State::S0, GetSize(sig)); - if (absolute_density < min_density && range_density >= min_density) + if (!norange && absolute_density < min_density && range_density >= min_density) { offset = Const(min_choice, GetSize(sig)); log(" offset: %s\n", log_signal(offset)); -- cgit v1.2.3 From 35fa7b30574244e4f99373f2a790f004b4a1dbbb Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 27 Jun 2019 22:02:12 +0200 Subject: Fix memory leak when one of multiple DFF cells is removed in opt_rmdff When there are multiple DFFs and one of them is removed, its reference lingers inside bit2driver dict. While invoking handle_dff() function for other DFFs, this broken reference is used isnside sat_import_cell() function. --- passes/opt/opt_rmdff.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 5fc28ae92..17e0d7cd4 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -530,6 +530,11 @@ delete_dff: log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); remove_init_attr(dff->getPort("\\Q")); mod->remove(dff); + + for (auto &entry : bit2driver) + if (entry.second == dff) + bit2driver.erase(entry.first); + return true; } -- cgit v1.2.3 From 3225bfb98403271bbe8a56418ccd027b42eabda1 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Thu, 27 Jun 2019 22:06:23 +0200 Subject: Add help for "-sat" option inside opt_rmdff. "opt" can pass "-sat" too --- passes/opt/opt.cc | 8 ++++++-- passes/opt/opt_rmdff.cc | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index a4aca2fee..e9a43e0f3 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -44,7 +44,7 @@ struct OptPass : public Pass { log(" opt_muxtree\n"); log(" opt_reduce [-fine] [-full]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_rmdff [-keepdc]\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" while \n"); @@ -54,7 +54,7 @@ struct OptPass : public Pass { log(" do\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); log(" opt_merge [-share_all]\n"); - log(" opt_rmdff [-keepdc]\n"); + log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" while \n"); log("\n"); @@ -112,6 +112,10 @@ struct OptPass : public Pass { opt_rmdff_args += " -keepdc"; continue; } + if (args[argidx] == "-sat") { + opt_rmdff_args += " -sat"; + continue; + } if (args[argidx] == "-share_all") { opt_merge_args += " -share_all"; continue; diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 17e0d7cd4..be6ac2d30 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -549,6 +549,10 @@ struct OptRmdffPass : public Pass { log("This pass identifies flip-flops with constant inputs and replaces them with\n"); log("a constant driver.\n"); log("\n"); + log(" -sat\n"); + log(" additionally invoke SAT solver to detect and remove flip-flops (with \n"); + log(" non-constant inputs) that can also be replaced with a constant driver\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { -- cgit v1.2.3 From 37b58f43242086de13fb2966d11b71efa29e7bfd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Jul 2019 19:15:07 -0700 Subject: Clarify 'wreduce -keepdc' doc --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..f749c8249 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values.\n"); + log(" Do not optimize explicit don't-care values on $mux cells.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE -- cgit v1.2.3 From 713337255e6ab57b0679d64539d5c87d036c067f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 9 Jul 2019 10:14:23 -0700 Subject: Revert "Add "synth -keepdc" option" --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index f749c8249..1fbc41082 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -497,7 +497,7 @@ struct WreducePass : public Pass { log(" flows that use the 'memory_memx' pass.\n"); log("\n"); log(" -keepdc\n"); - log(" Do not optimize explicit don't-care values on $mux cells.\n"); + log(" Do not optimize explicit don't-care values.\n"); log("\n"); } void execute(std::vector args, Design *design) YS_OVERRIDE -- cgit v1.2.3 From 2de7e92bb847edef65f418c9034709649f6c1185 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 13 Jul 2019 16:49:56 +0000 Subject: opt_lut: make less chatty. --- passes/opt/opt_lut.cc | 94 +++++++++++++++++++++------------------------------ 1 file changed, 38 insertions(+), 56 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 26855fd70..182f63d99 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -105,7 +105,7 @@ struct OptLutWorker SigSpec lut_input = cell->getPort("\\A"); int lut_arity = 0; - log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); + log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); luts.insert(cell); // First, find all dedicated logic we're connected to. This results in an overapproximation @@ -147,15 +147,15 @@ struct OptLutWorker { if (lut_width <= dlogic_conn.first) { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] not present.\n", dlogic_conn.first); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT input A[%d] not present.\n", dlogic_conn.first); legal = false; break; } if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second))) { - log(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); - log(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); + log_debug(" LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second))); legal = false; break; } @@ -163,7 +163,7 @@ struct OptLutWorker if (legal) { - log(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); + log_debug(" LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic)); lut_legal_dlogics.insert(lut_dlogic); for (auto &dlogic_conn : dlogic_map) lut_dlogic_inputs.insert(dlogic_conn.first); @@ -179,7 +179,7 @@ struct OptLutWorker lut_arity++; } - log(" Cell implements a %d-LUT.\n", lut_arity); + log_debug(" Cell implements a %d-LUT.\n", lut_arity); luts_arity[cell] = lut_arity; luts_dlogics[cell] = lut_legal_dlogics; luts_dlogic_inputs[cell] = lut_dlogic_inputs; @@ -239,28 +239,26 @@ struct OptLutWorker if (const0_match || const1_match || input_match != -1) { - log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); + log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut)); SigBit value; if (const0_match) { - log(" Cell evaluates constant 0.\n"); + log_debug(" Cell evaluates constant 0.\n"); value = State::S0; } if (const1_match) { - log(" Cell evaluates constant 1.\n"); + log_debug(" Cell evaluates constant 1.\n"); value = State::S1; } if (input_match != -1) { - log(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match])); + log_debug(" Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match])); value = lut_inputs[input_match]; } if (lut_dlogic_inputs.size()) - { - log(" Not eliminating cell (connected to dedicated logic).\n"); - } + log_debug(" Not eliminating cell (connected to dedicated logic).\n"); else { SigSpec lut_output = lut->getPort("\\Y"); @@ -323,11 +321,11 @@ struct OptLutWorker int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; - log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); + log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); if (index.query_is_output(lutA->getPort("\\Y"))) { - log(" Not combining LUTs (cascade connection feeds module output).\n"); + log_debug(" Not combining LUTs (cascade connection feeds module output).\n"); continue; } @@ -353,67 +351,51 @@ struct OptLutWorker int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); if (lutA_dlogic_inputs.size()) - log(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); + log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); else - log(" Cell A is a %d-LUT. ", lutA_arity); + log_debug(" Cell A is a %d-LUT. ", lutA_arity); if (lutB_dlogic_inputs.size()) - log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); + log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); else - log("Cell B is a %d-LUT.\n", lutB_arity); - log(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); + log_debug("Cell B is a %d-LUT.\n", lutB_arity); + log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; int combine_mask = 0; if (lutM_arity > lutA_width) - { - log(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); - } + log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); else if (lutB_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); - } + log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); else if (lutB->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); - } + log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); else - { combine_mask |= COMBINE_A; - } if (lutM_arity > lutB_width) - { - log(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); - } + log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); else if (lutA_dlogic_inputs.size() > 0) - { - log(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); - } + log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); else if (lutA->get_bool_attribute("\\lut_keep")) - { - log(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); - } + log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); else - { combine_mask |= COMBINE_B; - } int combine = combine_mask; if (combine == COMBINE_EITHER) { - log(" Can combine into either cell.\n"); + log_debug(" Can combine into either cell.\n"); if (lutA_arity == 1) { - log(" Cell A is a buffer or inverter, combining into cell B.\n"); + log_debug(" Cell A is a buffer or inverter, combining into cell B.\n"); combine = COMBINE_B; } else if (lutB_arity == 1) { - log(" Cell B is a buffer or inverter, combining into cell A.\n"); + log_debug(" Cell B is a buffer or inverter, combining into cell A.\n"); combine = COMBINE_A; } else { - log(" Arbitrarily combining into cell A.\n"); + log_debug(" Arbitrarily combining into cell A.\n"); combine = COMBINE_A; } } @@ -423,7 +405,7 @@ struct OptLutWorker pool lutM_dlogic_inputs; if (combine == COMBINE_A) { - log(" Combining LUTs into cell A.\n"); + log_debug(" Combining LUTs into cell A.\n"); lutM = lutA; lutM_inputs = lutA_inputs; lutM_dlogic_inputs = lutA_dlogic_inputs; @@ -432,7 +414,7 @@ struct OptLutWorker } else if (combine == COMBINE_B) { - log(" Combining LUTs into cell B.\n"); + log_debug(" Combining LUTs into cell B.\n"); lutM = lutB; lutM_inputs = lutB_inputs; lutM_dlogic_inputs = lutB_dlogic_inputs; @@ -441,7 +423,7 @@ struct OptLutWorker } else { - log(" Cannot combine LUTs.\n"); + log_debug(" Cannot combine LUTs.\n"); continue; } @@ -466,17 +448,17 @@ struct OptLutWorker if (input_unused && lutR_unique.size()) { SigBit new_input = lutR_unique.pop(); - log(" Connecting input %d as %s.\n", i, log_signal(new_input)); + log_debug(" Connecting input %d as %s.\n", i, log_signal(new_input)); lutM_new_inputs.push_back(new_input); } else if (sigmap(lutM_input[i]) == lutA_output) { - log(" Disconnecting cascade input %d.\n", i); + log_debug(" Disconnecting cascade input %d.\n", i); lutM_new_inputs.push_back(SigBit()); } else { - log(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); + log_debug(" Leaving input %d as %s.\n", i, log_signal(lutM_input[i])); lutM_new_inputs.push_back(lutM_input[i]); } } @@ -494,9 +476,9 @@ struct OptLutWorker lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - log(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); - log(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); - log(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); + log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); lutM->setParam("\\LUT", lutM_new_table); lutM->setPort("\\A", lutM_new_inputs); -- cgit v1.2.3 From fc0e36d1c02c22a578020aa1f2c90c86844fefe6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 12:50:21 -0700 Subject: wreduce for $sub --- passes/opt/wreduce.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1fbc41082..e8c2cb726 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -365,6 +365,29 @@ struct WreduceWorker } } + if (cell->type.in("$add", "$sub")) { + SigSpec A = cell->getPort("\\A"); + SigSpec B = cell->getPort("\\B"); + bool sub = cell->type == "$sub"; + + int i; + for (i = 0; i < GetSize(sig); i++) { + if (B[i] != S0 && (sub || A[i] != S0)) + break; + if (B[i] == S0) + module->connect(sig[i], A[i]); + else if (A[i] == S0) + module->connect(sig[i], B[i]); + else log_abort(); + } + if (i > 0) { + cell->setPort("\\A", A.extract(i, -1)); + cell->setPort("\\B", B.extract(i, -1)); + sig.remove(0, i); + bits_removed += i; + } + } + if (GetSize(sig) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->remove(cell); -- cgit v1.2.3 From bcd802718256efbacaf0a73f99347af40b61e464 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:11:48 -0700 Subject: Also optimise MSB of $sub --- passes/opt/wreduce.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index e8c2cb726..dff1c5370 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -342,9 +342,9 @@ struct WreduceWorker } } - if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor")) + if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub")) { - bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub"; int a_size = 0, b_size = 0; if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A")); @@ -352,7 +352,7 @@ struct WreduceWorker int max_y_size = max(a_size, b_size); - if (cell->type == "$add") + if (cell->type.in("$add", "$sub")) max_y_size++; if (cell->type == "$mul") -- cgit v1.2.3 From 31b0002e8c0e1b7a8ad054e02b1200c03461b581 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:20:45 -0700 Subject: Remove "top" from message --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index dff1c5370..23e14f7f5 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -395,7 +395,7 @@ struct WreduceWorker } if (bits_removed) { - log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", + log("Removed %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort("\\Y", sig); did_something = true; -- cgit v1.2.3 From 3a87dc35242598b6951fb70d4302ede60c2a96b2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:23:07 -0700 Subject: Wrap A and B in sigmap --- passes/opt/wreduce.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 23e14f7f5..294f0d57e 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -366,8 +366,8 @@ struct WreduceWorker } if (cell->type.in("$add", "$sub")) { - SigSpec A = cell->getPort("\\A"); - SigSpec B = cell->getPort("\\B"); + SigSpec A = mi.sigmap(cell->getPort("\\A")); + SigSpec B = mi.sigmap(cell->getPort("\\B")); bool sub = cell->type == "$sub"; int i; -- cgit v1.2.3 From cb0fd0521531a69632102f5fad8cdc9996ed4dee Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 13:58:50 -0700 Subject: Do not access beyond bounds --- passes/opt/wreduce.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 294f0d57e..908a85d5b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -372,7 +372,7 @@ struct WreduceWorker int i; for (i = 0; i < GetSize(sig); i++) { - if (B[i] != S0 && (sub || A[i] != S0)) + if (B.at(i, Sx) != S0 && (sub || A.at(i, Sx) != S0)) break; if (B[i] == S0) module->connect(sig[i], A[i]); -- cgit v1.2.3 From 09beeee38a5af767f70d24e86c976e43b1b27547 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 19 Jul 2019 14:40:57 -0700 Subject: Try and fix again --- passes/opt/wreduce.cc | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 908a85d5b..22af0bd8b 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -372,13 +372,12 @@ struct WreduceWorker int i; for (i = 0; i < GetSize(sig); i++) { - if (B.at(i, Sx) != S0 && (sub || A.at(i, Sx) != S0)) - break; - if (B[i] == S0) + if (B.at(i, Sx) == S0 && A.at(i, Sx) != Sx) module->connect(sig[i], A[i]); - else if (A[i] == S0) + else if (!sub && A.at(i, Sx) == S0 && B.at(i, Sx) != Sx) module->connect(sig[i], B[i]); - else log_abort(); + else + break; } if (i > 0) { cell->setPort("\\A", A.extract(i, -1)); -- cgit v1.2.3 From 07c4a7d4388cdacaa15512dd2f6f0f9e9fcb31f5 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Fri, 26 Jul 2019 11:36:48 +0200 Subject: Implement opt_share This pass identifies arithmetic operators that share an operand and whose results are used in mutually exclusive cases controlled by a multiplexer, and merges them together by multiplexing the other operands --- passes/opt/Makefile.inc | 2 +- passes/opt/opt_share.cc | 329 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 passes/opt/opt_share.cc (limited to 'passes/opt') diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index ea3646330..eb07e9452 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -4,6 +4,7 @@ OBJS += passes/opt/opt_merge.o OBJS += passes/opt/opt_muxtree.o OBJS += passes/opt/opt_reduce.o OBJS += passes/opt/opt_rmdff.o +OBJS += passes/opt/opt_share.o OBJS += passes/opt/opt_clean.o OBJS += passes/opt/opt_expr.o @@ -16,4 +17,3 @@ OBJS += passes/opt/opt_lut.o OBJS += passes/opt/pmux2shiftx.o OBJS += passes/opt/muxpack.o endif - diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc new file mode 100644 index 000000000..9f6f59b64 --- /dev/null +++ b/passes/opt/opt_share.cc @@ -0,0 +1,329 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * 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/log.h" +#include "kernel/register.h" +#include "kernel/rtlil.h" +#include "kernel/sigtools.h" +#include + +#include +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +SigMap assign_map; + +// Helper class that to track whether a SigSpec is signed and whether it is +// connected to the \\B port of the $sub cell, which makes its sign prefix +// negative. +struct ExtSigSpec { + RTLIL::SigSpec sig; + bool sign; + bool is_signed; + + ExtSigSpec() {} + + ExtSigSpec(RTLIL::SigSpec s, bool sign = false, bool is_signed = false) : sig(s), sign(sign), is_signed(is_signed) {} + + ExtSigSpec(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) + { + sign = (cell->type == "$sub") && (port_name == "\\B"); + sig = (*sigmap)(cell->getPort(port_name)); + + is_signed = false; + if (cell->hasParam(port_name.str() + "_SIGNED")) { + is_signed = cell->getParam(port_name.str() + "_SIGNED").as_bool(); + } + } + + bool empty() const { return sig.empty(); } + + bool operator<(const ExtSigSpec &other) const + { + if (sig != other.sig) + return sig < other.sig; + + if (sign != other.sign) + return sign < other.sign; + + return is_signed < other.is_signed; + } + + bool operator==(const RTLIL::SigSpec &other) const { return sign ? false : sig == other; } + bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig; } +}; + +void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &operators, int offset, int width, + const ExtSigSpec &operand) +{ + + std::vector muxed_operands; + int max_width = 0; + for (auto op : operators) { + for (auto &conn : op->connections()) { + if (op->output(conn.first)) + continue; + + if (conn.second != operand.sig) { + auto operand = ExtSigSpec(op, conn.first, &assign_map); + if (operand.sig.size() > max_width) { + max_width = operand.sig.size(); + } + + muxed_operands.push_back(operand); + } + } + } + + for (auto &operand : muxed_operands) { + operand.sig.extend_u0(max_width, operand.is_signed); + } + + auto shared_op = operators[0]; + + for (auto op : operators) { + if (op == shared_op) + continue; + module->remove(op); + } + + RTLIL::SigSpec mux_out = mux->getPort("\\Y"); + + if (muxed_operands[0].sign != muxed_operands[1].sign) { + muxed_operands[1] = ExtSigSpec(module->Neg(NEW_ID, muxed_operands[1].sig, muxed_operands[1].is_signed)); + } + + auto mux_to_oper = module->Mux(NEW_ID, muxed_operands[0].sig, muxed_operands[1].sig, mux->getPort("\\S")); + + shared_op->setPort("\\Y", mux_out.extract(offset, width)); + shared_op->setParam("\\Y_WIDTH", width); + + auto dummy = module->addWire(NEW_ID, width); + + mux_out.replace(offset, dummy); + mux->setPort("\\Y", mux_out); + + if (shared_op->getPort("\\A") == operand.sig) { + shared_op->setPort("\\B", mux_to_oper); + shared_op->setParam("\\B_WIDTH", max_width); + } else { + shared_op->setPort("\\A", mux_to_oper); + shared_op->setParam("\\A_WIDTH", max_width); + } +} + +typedef struct { + RTLIL::Cell *mux; + std::vector operators; + int offset; + int width; + ExtSigSpec shared_operand; +} shared_op_t; + +bool find_op_res_width(int offset, int &width, RTLIL::SigSpec porta, RTLIL::SigSpec portb, + const dict &op_outbit_to_outsig, const dict &op_outbit_user_cnt) +{ + + std::array op_outsigs{op_outbit_to_outsig.at(porta[offset]), op_outbit_to_outsig.at(portb[offset])}; + + width = 0; + bool multi_user = false; + + while (true) { + for (const auto &op_outsig : op_outsigs) + if (op_outbit_user_cnt.at(op_outsig[width]) > 1) + multi_user = true; + + ++offset; + ++width; + + if ((offset >= porta.size()) || (width >= op_outsigs[0].size()) || (width >= op_outsigs[1].size())) + break; + + if ((porta[offset] != op_outsigs[0][width]) || (portb[offset] != op_outsigs[1][width])) + break; + } + + if (multi_user) + return false; + + for (const auto &outsig : op_outsigs) + for (int i = width; i < outsig.size(); i++) + if (op_outbit_user_cnt.count(outsig[i])) + return false; + + return true; +} + +ExtSigSpec find_shared_operand(const std::vector &operators, const std::map> &operand_to_users) +{ + + std::set operators_set(operators.begin(), operators.end()); + ExtSigSpec oper; + + auto op_a = operators[0]; + for (auto &conn : op_a->connections()) { + if (op_a->output(conn.first)) + continue; + + oper = ExtSigSpec(op_a, conn.first, &assign_map); + auto bundle = operand_to_users.at(oper); + + if (std::includes(bundle.begin(), bundle.end(), operators_set.begin(), operators_set.end())) + break; + } + + return oper; +} + +dict find_op_outbit_user_cnt(RTLIL::Module *module, const dict &op_outbit_to_outsig) +{ + dict op_outbit_user_cnt; + + std::function update_op_outbit_user_cnt = [&](SigSpec sig) { + auto outsig = assign_map(sig); + for (auto outbit : outsig) + if (op_outbit_to_outsig.count(outbit)) + op_outbit_user_cnt[outbit]++; + }; + + for (auto cell : module->cells()) + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + update_op_outbit_user_cnt(conn.second); + + for (auto w : module->wires()) { + if (!w->port_output) + continue; + + update_op_outbit_user_cnt(w); + } + + return op_outbit_user_cnt; +} + +struct OptRmdffPass : public Pass { + OptRmdffPass() : Pass("opt_share", "merge arithmetic operators that share an operand") {} + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" opt_share [selection]\n"); + log("\n"); + log("This pass identifies arithmetic operators that share an operand and whose\n"); + log("results are used in mutually exclusive cases controlled by a multiplexer,\n"); + log("and merges them together by multiplexing the other operands.\n"); + log("\n"); + } + void execute(std::vector, RTLIL::Design *design) YS_OVERRIDE + { + + log_header(design, "Executing OPT_SHARE pass.\n"); + + for (auto module : design->selected_modules()) { + assign_map.clear(); + assign_map.set(module); + + std::map> operand_to_users; + dict outsig_to_operator; + dict op_outbit_to_outsig; + bool any_shared_operands = false; + + for (auto cell : module->cells()) { + if (!cell->type.in("$add", "$sub")) + continue; + + for (auto &conn : cell->connections()) { + if (cell->output(conn.first)) { + auto outsig = assign_map(conn.second); + for (auto outbit : outsig) + op_outbit_to_outsig[outbit] = outsig; + + outsig_to_operator[outsig] = cell; + } else { + auto op_insig = ExtSigSpec(cell, conn.first, &assign_map); + operand_to_users[op_insig].insert(cell); + if (operand_to_users[op_insig].size() > 1) + any_shared_operands = true; + } + } + } + + if (!any_shared_operands) + continue; + + // Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to + // how many points are operator output bits connected. + dict op_outbit_user_cnt = find_op_outbit_user_cnt(module, op_outbit_to_outsig); + std::vector shared_ops; + for (auto cell : module->cells()) { + if (!cell->type.in("$mux", "$_MUX_")) + continue; + + auto porta = assign_map(cell->getPort("\\A")); + auto portb = assign_map(cell->getPort("\\B")); + + // Look through the bits of the $mux inputs and see which of them are connected to the operator + // results. Operator results can be concatenated with other signals before led to the $mux. + for (int i = 0; i < porta.size(); ++i) { + std::array mux_inbits{porta[i], portb[i]}; + + // Are the results of an $add or $sub operators connected to both of this $mux inputs? + if (!op_outbit_to_outsig.count(mux_inbits[0]) or !op_outbit_to_outsig.count(mux_inbits[1])) + continue; + + std::vector operators; + for (const auto &b : mux_inbits) + operators.push_back(outsig_to_operator.at(op_outbit_to_outsig.at(b))); + + // Do these operators share an operand? + auto shared_operand = find_shared_operand(operators, operand_to_users); + if (shared_operand.empty()) + continue; + + // Some bits of the operator results might be unconnected. Calculate the number of conneted + // bits. + int width; + + if (find_op_res_width(i, width, porta, portb, op_outbit_to_outsig, op_outbit_user_cnt)) + shared_ops.push_back(shared_op_t{cell, operators, i, width, shared_operand}); + + i += width - 1; + } + } + + for (auto &shared : shared_ops) { + log(" Found arithmetic cells that share an operand and can be merged by moving the %s %s in front " + "of " + "them:\n", + log_id(shared.mux->type), log_id(shared.mux)); + for (auto op : shared.operators) + log(" %s\n", log_id(op)); + log("\n"); + + merge_operators(module, shared.mux, shared.operators, shared.offset, shared.width, shared.shared_operand); + } + } + } + +} OptRmdffPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From c075486c59155d16ed278922a3752366a95246ff Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Sun, 28 Jul 2019 16:03:54 +0200 Subject: Reimplement opt_share to work on $alu and $pmux --- passes/opt/opt_share.cc | 320 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 225 insertions(+), 95 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 9f6f59b64..e9a2f05f9 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -31,12 +31,21 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map; +struct InPort { + RTLIL::SigSpec sig; + RTLIL::Cell *pmux; + int port_id; + RTLIL::Cell *alu; + + InPort(RTLIL::SigSpec s, RTLIL::Cell *c, int p, RTLIL::Cell *a = NULL) : sig(s), pmux(c), port_id(p), alu(a) {} +}; + // Helper class that to track whether a SigSpec is signed and whether it is // connected to the \\B port of the $sub cell, which makes its sign prefix // negative. struct ExtSigSpec { RTLIL::SigSpec sig; - bool sign; + RTLIL::SigSpec sign; bool is_signed; ExtSigSpec() {} @@ -45,7 +54,7 @@ struct ExtSigSpec { ExtSigSpec(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) { - sign = (cell->type == "$sub") && (port_name == "\\B"); + sign = (port_name == "\\B") ? cell->getPort("\\BI") : RTLIL::Const(0, 1); sig = (*sigmap)(cell->getPort(port_name)); is_signed = false; @@ -67,23 +76,22 @@ struct ExtSigSpec { return is_signed < other.is_signed; } - bool operator==(const RTLIL::SigSpec &other) const { return sign ? false : sig == other; } + bool operator==(const RTLIL::SigSpec &other) const { return (sign != RTLIL::Const(0, 1)) ? false : sig == other; } bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig; } }; -void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &operators, int offset, int width, +void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &ports, int offset, int width, const ExtSigSpec &operand) { std::vector muxed_operands; int max_width = 0; - for (auto op : operators) { - for (auto &conn : op->connections()) { - if (op->output(conn.first)) - continue; + for (const auto& p : ports) { + auto op = p.alu; - if (conn.second != operand.sig) { - auto operand = ExtSigSpec(op, conn.first, &assign_map); + for (RTLIL::IdString port_name : {"\\A", "\\B"}) { + if (op->getPort(port_name) != operand.sig) { + auto operand = ExtSigSpec(op, port_name, &assign_map); if (operand.sig.size() > max_width) { max_width = operand.sig.size(); } @@ -97,29 +105,60 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< operand.sig.extend_u0(max_width, operand.is_signed); } - auto shared_op = operators[0]; + auto shared_op = ports[0].alu; - for (auto op : operators) { + for (const auto& p : ports) { + auto op = p.alu; if (op == shared_op) continue; module->remove(op); } - RTLIL::SigSpec mux_out = mux->getPort("\\Y"); + for (auto &muxed_op : muxed_operands) { + if (muxed_op.sign != muxed_operands[0].sign) { + muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed)); + } + } + + RTLIL::SigSpec mux_y = mux->getPort("\\Y"); + RTLIL::SigSpec mux_a = mux->getPort("\\A"); + RTLIL::SigSpec mux_b = mux->getPort("\\B"); + RTLIL::SigSpec mux_s = mux->getPort("\\S"); + + RTLIL::SigSpec alu_x = shared_op->getPort("\\X"); + RTLIL::SigSpec alu_co = shared_op->getPort("\\CO"); - if (muxed_operands[0].sign != muxed_operands[1].sign) { - muxed_operands[1] = ExtSigSpec(module->Neg(NEW_ID, muxed_operands[1].sig, muxed_operands[1].is_signed)); + RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); + RTLIL::SigSpec shared_pmux_b; + RTLIL::SigSpec shared_pmux_s; + + shared_op->setPort("\\Y", shared_op->getPort("\\Y").extract(0, width)); + + if (mux->type == "$pmux") { + shared_pmux_s = RTLIL::SigSpec(); + + for (const auto&p: ports) { + shared_pmux_s.append(mux_s[p.port_id]); + mux_b.replace(p.port_id * mux_a.size() + offset, shared_op->getPort("\\Y")); + } + } else { + shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)}; + mux_a.replace(offset, shared_op->getPort("\\Y")); + mux_b.replace(offset, shared_op->getPort("\\Y")); } - auto mux_to_oper = module->Mux(NEW_ID, muxed_operands[0].sig, muxed_operands[1].sig, mux->getPort("\\S")); + mux->setPort("\\Y", mux_y); + mux->setPort("\\S", mux_s); + mux->setPort("\\B", mux_b); - shared_op->setPort("\\Y", mux_out.extract(offset, width)); - shared_op->setParam("\\Y_WIDTH", width); + for (const auto &op : muxed_operands) + shared_pmux_b.append(op.sig); - auto dummy = module->addWire(NEW_ID, width); + auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s); - mux_out.replace(offset, dummy); - mux->setPort("\\Y", mux_out); + shared_op->setPort("\\X", alu_x.extract(0, width)); + shared_op->setPort("\\CO", alu_co.extract(0, width)); + shared_op->setParam("\\Y_WIDTH", width); if (shared_op->getPort("\\A") == operand.sig) { shared_op->setPort("\\B", mux_to_oper); @@ -128,81 +167,132 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< shared_op->setPort("\\A", mux_to_oper); shared_op->setParam("\\A_WIDTH", max_width); } + } typedef struct { RTLIL::Cell *mux; - std::vector operators; + std::vector ports; int offset; int width; ExtSigSpec shared_operand; } shared_op_t; -bool find_op_res_width(int offset, int &width, RTLIL::SigSpec porta, RTLIL::SigSpec portb, - const dict &op_outbit_to_outsig, const dict &op_outbit_user_cnt) + +template void remove_val(std::vector &v, const std::vector &vals) +{ + auto val_iter = vals.rbegin(); + for (auto i = v.rbegin(); i != v.rend(); ++i) + if ((val_iter != vals.rend()) && (*i == *val_iter)) { + v.erase(i.base() - 1); + ++val_iter; + } +} + +bool find_op_res_width(int offset, int &width, std::vector& ports, const dict &op_outbit_to_outsig) { - std::array op_outsigs{op_outbit_to_outsig.at(porta[offset]), op_outbit_to_outsig.at(portb[offset])}; + std::vector op_outsigs; + dict> op_outsig_span; + + std::transform(ports.begin(), ports.end(), std::back_inserter(op_outsigs), [&](InPort *p) { return op_outbit_to_outsig.at(p->sig[offset]); }); + + std::vector finished(ports.size(), false); width = 0; - bool multi_user = false; - while (true) { - for (const auto &op_outsig : op_outsigs) - if (op_outbit_user_cnt.at(op_outsig[width]) > 1) - multi_user = true; + std::function all_finished = [&] { return std::find(std::begin(finished), std::end(finished), false) == end(finished);}; + while (!all_finished()) + { ++offset; ++width; - if ((offset >= porta.size()) || (width >= op_outsigs[0].size()) || (width >= op_outsigs[1].size())) - break; + if (offset >= ports[0]->sig.size()) { + for (size_t i = 0; i < op_outsigs.size(); ++i) { + if (finished[i]) + continue; + + op_outsig_span[width].insert(ports[i]); + finished[i] = true; + } - if ((porta[offset] != op_outsigs[0][width]) || (portb[offset] != op_outsigs[1][width])) break; + } + + for (size_t i = 0; i < op_outsigs.size(); ++i) { + if (finished[i]) + continue; + + if ((width >= op_outsigs[i].size()) || (ports[i]->sig[offset] != op_outsigs[i][width])) { + op_outsig_span[width].insert(ports[i]); + finished[i] = true; + } + } } - if (multi_user) - return false; + for (auto w: op_outsig_span) { + if (w.second.size() > 1) { + width = w.first; + + ports.erase(std::remove_if(ports.begin(), ports.end(), [&](InPort *p) { return !w.second.count(p); }), ports.end()); - for (const auto &outsig : op_outsigs) - for (int i = width; i < outsig.size(); i++) - if (op_outbit_user_cnt.count(outsig[i])) - return false; + return true; + } + } - return true; + return false; } -ExtSigSpec find_shared_operand(const std::vector &operators, const std::map> &operand_to_users) +ExtSigSpec find_shared_operand(InPort* seed, std::vector &ports, const std::map> &operand_to_users) { + std::set alus_using_operand; + std::set alus_set; + for(const auto& p: ports) + alus_set.insert(p->alu); - std::set operators_set(operators.begin(), operators.end()); ExtSigSpec oper; - auto op_a = operators[0]; - for (auto &conn : op_a->connections()) { - if (op_a->output(conn.first)) + auto op_a = seed->alu; + + for (RTLIL::IdString port_name : {"\\A", "\\B"}) { + oper = ExtSigSpec(op_a, port_name, &assign_map); + auto operand_users = operand_to_users.at(oper); + + if (operand_users.size() == 1) continue; - oper = ExtSigSpec(op_a, conn.first, &assign_map); - auto bundle = operand_to_users.at(oper); + alus_using_operand.clear(); + std::set_intersection(operand_users.begin(), operand_users.end(), alus_set.begin(), alus_set.end(), + std::inserter(alus_using_operand, alus_using_operand.begin())); - if (std::includes(bundle.begin(), bundle.end(), operators_set.begin(), operators_set.end())) - break; + if (alus_using_operand.size() > 1) { + ports.erase(std::remove_if(ports.begin(), ports.end(), [&](InPort *p) { return !alus_using_operand.count(p->alu); }), + ports.end()); + return oper; + } } - return oper; + return ExtSigSpec(); } -dict find_op_outbit_user_cnt(RTLIL::Module *module, const dict &op_outbit_to_outsig) +void remove_multi_user_outbits(RTLIL::Module *module, dict &op_outbit_to_outsig) { dict op_outbit_user_cnt; std::function update_op_outbit_user_cnt = [&](SigSpec sig) { auto outsig = assign_map(sig); - for (auto outbit : outsig) - if (op_outbit_to_outsig.count(outbit)) - op_outbit_user_cnt[outbit]++; + for (auto outbit : outsig) { + if (!op_outbit_to_outsig.count(outbit)) + continue; + + if (++op_outbit_user_cnt[outbit] > 1) { + auto alu_outsig = op_outbit_to_outsig.at(outbit); + + for (auto outbit : alu_outsig) + op_outbit_to_outsig.erase(outbit); + } + } }; for (auto cell : module->cells()) @@ -216,8 +306,6 @@ dict find_op_outbit_user_cnt(RTLIL::Module *module, const di update_op_outbit_user_cnt(w); } - - return op_outbit_user_cnt; } struct OptRmdffPass : public Pass { @@ -246,24 +334,31 @@ struct OptRmdffPass : public Pass { dict outsig_to_operator; dict op_outbit_to_outsig; bool any_shared_operands = false; + std::vector op_insigs; for (auto cell : module->cells()) { - if (!cell->type.in("$add", "$sub")) + if (!cell->type.in("$alu")) continue; - for (auto &conn : cell->connections()) { - if (cell->output(conn.first)) { - auto outsig = assign_map(conn.second); - for (auto outbit : outsig) - op_outbit_to_outsig[outbit] = outsig; - - outsig_to_operator[outsig] = cell; - } else { - auto op_insig = ExtSigSpec(cell, conn.first, &assign_map); - operand_to_users[op_insig].insert(cell); - if (operand_to_users[op_insig].size() > 1) - any_shared_operands = true; - } + RTLIL::SigSpec sig_bi = cell->getPort("\\BI"); + RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); + + if ((!sig_bi.is_fully_const()) || (!sig_ci.is_fully_const()) || (sig_bi != sig_ci)) + continue; + + RTLIL::SigSpec sig_y = cell->getPort("\\A"); + + auto outsig = assign_map(cell->getPort("\\Y")); + outsig_to_operator[outsig] = cell; + for (auto outbit : outsig) + op_outbit_to_outsig[outbit] = outsig; + + for (RTLIL::IdString port_name : {"\\A", "\\B"}) { + auto op_insig = ExtSigSpec(cell, port_name, &assign_map); + op_insigs.push_back(op_insig); + operand_to_users[op_insig].insert(cell); + if (operand_to_users[op_insig].size() > 1) + any_shared_operands = true; } } @@ -272,42 +367,77 @@ struct OptRmdffPass : public Pass { // Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to // how many points are operator output bits connected. - dict op_outbit_user_cnt = find_op_outbit_user_cnt(module, op_outbit_to_outsig); + remove_multi_user_outbits(module, op_outbit_to_outsig); + std::vector shared_ops; for (auto cell : module->cells()) { - if (!cell->type.in("$mux", "$_MUX_")) + if (!cell->type.in("$mux", "$_MUX_", "$pmux")) continue; - auto porta = assign_map(cell->getPort("\\A")); - auto portb = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_a = cell->getPort("\\A"); + RTLIL::SigSpec sig_b = cell->getPort("\\B"); + RTLIL::SigSpec sig_s = cell->getPort("\\S"); + + std::vector ports; + + if (cell->type.in("$mux", "$_MUX_")) { + ports.push_back(InPort(assign_map(sig_a), cell, 0)); + ports.push_back(InPort(assign_map(sig_b), cell, 1)); + } else { + RTLIL::SigSpec sig_s = cell->getPort("\\S"); + for (int i = 0; i < sig_s.size(); i++) { + auto inp = sig_b.extract(i * sig_a.size(), sig_a.size()); + ports.push_back(InPort(assign_map(inp), cell, i)); + } + } // Look through the bits of the $mux inputs and see which of them are connected to the operator // results. Operator results can be concatenated with other signals before led to the $mux. - for (int i = 0; i < porta.size(); ++i) { - std::array mux_inbits{porta[i], portb[i]}; + for (int i = 0; i < sig_a.size(); ++i) { + std::vector alu_ports; + for (auto& p: ports) + if (op_outbit_to_outsig.count(p.sig[i])) { + p.alu = outsig_to_operator.at(op_outbit_to_outsig.at(p.sig[i])); + alu_ports.push_back(&p); + } + + int alu_port_width = 0; + + while (alu_ports.size() > 1) { + std::vector shared_ports(alu_ports); + + auto seed = alu_ports[0]; + alu_ports.erase(alu_ports.begin()); - // Are the results of an $add or $sub operators connected to both of this $mux inputs? - if (!op_outbit_to_outsig.count(mux_inbits[0]) or !op_outbit_to_outsig.count(mux_inbits[1])) - continue; + // Find ports whose $alu-s share an operand with $alu connected to the seed port + auto shared_operand = find_shared_operand(seed, shared_ports, operand_to_users); - std::vector operators; - for (const auto &b : mux_inbits) - operators.push_back(outsig_to_operator.at(op_outbit_to_outsig.at(b))); + if (shared_operand.empty()) + continue; - // Do these operators share an operand? - auto shared_operand = find_shared_operand(operators, operand_to_users); - if (shared_operand.empty()) - continue; + // Some bits of the operator results might be unconnected. Calculate the number of conneted + // bits. + if (!find_op_res_width(i, alu_port_width, shared_ports, op_outbit_to_outsig)) + break; - // Some bits of the operator results might be unconnected. Calculate the number of conneted - // bits. - int width; + if (shared_ports.size() < 2) + break; - if (find_op_res_width(i, width, porta, portb, op_outbit_to_outsig, op_outbit_user_cnt)) - shared_ops.push_back(shared_op_t{cell, operators, i, width, shared_operand}); + // Remember the combination for the merger + std::vector shared_p; + for (auto p: shared_ports) + shared_p.push_back(*p); - i += width - 1; + shared_ops.push_back(shared_op_t{cell, shared_p, i, alu_port_width, shared_operand}); + + // Remove merged ports from the list and try to find other mergers for the mux + remove_val(alu_ports, shared_ports); + } + + if (alu_port_width) + i += alu_port_width - 1; } + } for (auto &shared : shared_ops) { @@ -315,11 +445,11 @@ struct OptRmdffPass : public Pass { "of " "them:\n", log_id(shared.mux->type), log_id(shared.mux)); - for (auto op : shared.operators) - log(" %s\n", log_id(op)); + for (const auto& op : shared.ports) + log(" %s\n", log_id(op.alu)); log("\n"); - merge_operators(module, shared.mux, shared.operators, shared.offset, shared.width, shared.shared_operand); + merge_operators(module, shared.mux, shared.ports, shared.offset, shared.width, shared.shared_operand); } } } -- cgit v1.2.3 From 28b7053a01630def454e683f03953c74744da025 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Wed, 31 Jul 2019 11:49:48 +0200 Subject: Fix formatting for msys2 mingw build using GetSize --- passes/opt/opt_lut.cc | 8 ++++---- passes/opt/rmports.cc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 182f63d99..587ef878a 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -81,7 +81,7 @@ struct OptLutWorker } } - log("Number of LUTs: %8zu\n", luts.size()); + log("Number of LUTs: %8d\n", GetSize(luts)); for (int arity = 1; arity <= max_arity; arity++) { if (arity_counts[arity]) @@ -351,14 +351,14 @@ struct OptLutWorker int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size(); if (lutA_dlogic_inputs.size()) - log_debug(" Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size()); + log_debug(" Cell A is a %d-LUT with %d dedicated connections. ", lutA_arity, GetSize(lutA_dlogic_inputs)); else log_debug(" Cell A is a %d-LUT. ", lutA_arity); if (lutB_dlogic_inputs.size()) - log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size()); + log_debug("Cell B is a %d-LUT with %d dedicated connections.\n", lutB_arity, GetSize(lutB_dlogic_inputs)); else log_debug("Cell B is a %d-LUT.\n", lutB_arity); - log_debug(" Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity); + log_debug(" Cells share %d input(s) and can be merged into one %d-LUT.\n", GetSize(common_inputs), lutM_arity); const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B; int combine_mask = 0; diff --git a/passes/opt/rmports.cc b/passes/opt/rmports.cc index fc1596ebf..32363dd68 100644 --- a/passes/opt/rmports.cc +++ b/passes/opt/rmports.cc @@ -171,7 +171,7 @@ struct RmportsPassPass : public Pass { wire->port_output = false; wire->port_id = 0; } - log("Removed %zu unused ports.\n", unused_ports.size()); + log("Removed %d unused ports.\n", GetSize(unused_ports)); // Re-number all of the wires that DO have ports still on them for(size_t i=0; iports.size(); i++) -- cgit v1.2.3 From 280c4e7794543e99244aafffc62a2dd4454bcb06 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Sat, 3 Aug 2019 12:28:46 +0200 Subject: Fix spacing in opt_share tests, change wording in opt_share help --- passes/opt/opt_share.cc | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index e9a2f05f9..25b07cbbd 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -2,6 +2,7 @@ * yosys -- Yosys Open SYnthesis Suite * * Copyright (C) 2012 Clifford Wolf + * 2019 Bogdan Vukobratovic * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -308,17 +309,20 @@ void remove_multi_user_outbits(RTLIL::Module *module, dict, RTLIL::Design *design) YS_OVERRIDE @@ -454,6 +458,6 @@ struct OptRmdffPass : public Pass { } } -} OptRmdffPass; +} OptSharePass; PRIVATE_NAMESPACE_END -- cgit v1.2.3 From 6a796accc09bc2c8ef98c068185de13d3e01890a Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Sun, 4 Aug 2019 19:06:38 +0200 Subject: Support various binary operators in opt_share --- passes/opt/opt_share.cc | 586 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 392 insertions(+), 194 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 25b07cbbd..e8f44749a 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -32,37 +32,36 @@ PRIVATE_NAMESPACE_BEGIN SigMap assign_map; -struct InPort { +struct OpMuxConn { RTLIL::SigSpec sig; - RTLIL::Cell *pmux; - int port_id; - RTLIL::Cell *alu; + RTLIL::Cell *mux; + RTLIL::Cell *op; + int mux_port_id; + int mux_port_offset; + int op_outsig_offset; + + bool operator<(const OpMuxConn &other) const + { + if (mux != other.mux) + return mux < other.mux; + + if (mux_port_id != other.mux_port_id) + return mux_port_id < other.mux_port_id; - InPort(RTLIL::SigSpec s, RTLIL::Cell *c, int p, RTLIL::Cell *a = NULL) : sig(s), pmux(c), port_id(p), alu(a) {} + return mux_port_offset < other.mux_port_offset; + } }; -// Helper class that to track whether a SigSpec is signed and whether it is -// connected to the \\B port of the $sub cell, which makes its sign prefix -// negative. +// Helper class to track additiona information about a SigSpec, like whether it is signed and the semantics of the port it is connected to struct ExtSigSpec { RTLIL::SigSpec sig; RTLIL::SigSpec sign; bool is_signed; + RTLIL::IdString semantics; ExtSigSpec() {} - ExtSigSpec(RTLIL::SigSpec s, bool sign = false, bool is_signed = false) : sig(s), sign(sign), is_signed(is_signed) {} - - ExtSigSpec(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) - { - sign = (port_name == "\\B") ? cell->getPort("\\BI") : RTLIL::Const(0, 1); - sig = (*sigmap)(cell->getPort(port_name)); - - is_signed = false; - if (cell->hasParam(port_name.str() + "_SIGNED")) { - is_signed = cell->getParam(port_name.str() + "_SIGNED").as_bool(); - } - } + ExtSigSpec(RTLIL::SigSpec s, RTLIL::SigSpec sign = RTLIL::Const(0, 1), bool is_signed = false, RTLIL::IdString semantics = RTLIL::IdString()) : sig(s), sign(sign), is_signed(is_signed), semantics(semantics) {} bool empty() const { return sig.empty(); } @@ -74,42 +73,136 @@ struct ExtSigSpec { if (sign != other.sign) return sign < other.sign; - return is_signed < other.is_signed; + if (is_signed != other.is_signed) + return is_signed < other.is_signed; + + return semantics < other.semantics; } bool operator==(const RTLIL::SigSpec &other) const { return (sign != RTLIL::Const(0, 1)) ? false : sig == other; } - bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig; } + bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; } }; -void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &ports, int offset, int width, - const ExtSigSpec &operand) +#define BITWISE_OPS "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$and", "$or", "$xor", "$xnor" + +#define REDUCTION_OPS "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$reduce_nand" + +#define LOGICAL_OPS "$logic_and", "$logic_or" + +#define SHIFT_OPS "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx" + +#define RELATIONAL_OPS "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt" + +bool cell_supported(RTLIL::Cell *cell) +{ + + if (cell->type.in("$alu")) { + RTLIL::SigSpec sig_bi = cell->getPort("\\BI"); + RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); + + if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci) + return true; + } else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, "$add", "$sub", "$mul", "$div", "$mod", "$concat")) { + return true; + } + + return false; +} + +std::map mergeable_type_map{ + {"$sub", "$add"}, +}; + +bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) +{ + auto a_type = a->type; + if (mergeable_type_map.count(a_type.str())) + a_type = mergeable_type_map.at(a_type.str()); + + auto b_type = b->type; + if (mergeable_type_map.count(b_type.str())) + b_type = mergeable_type_map.at(b_type.str()); + + return a_type == b_type; +} + +RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name) +{ + if (cell->type.in("$lt", "$le", "$ge", "$gt", "$div", "$mod", "$concat", SHIFT_OPS) && port_name == "\\B") + return port_name; + + return ""; +} + +RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { + + if (cell->type == "$alu" && port_name == "\\B") + return cell->getPort("\\BI"); + else if (cell->type == "$sub" && port_name == "\\B") + return RTLIL::Const(1, 1); + + return RTLIL::Const(0, 1); +} + +bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name) +{ + if (cell->type.in(BITWISE_OPS, LOGICAL_OPS)) + return false; + + if (cell->hasParam(port_name.str() + "_SIGNED")) + return cell->getParam(port_name.str() + "_SIGNED").as_bool(); + + return false; + +} + +ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) +{ + auto sig = (*sigmap)(cell->getPort(port_name)); + + RTLIL::SigSpec sign = decode_port_sign(cell, port_name); + RTLIL::IdString semantics = decode_port_semantics(cell, port_name); + + bool is_signed = decode_port_signed(cell, port_name); + + return ExtSigSpec(sig, sign, is_signed, semantics); +} + +void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &ports, const ExtSigSpec &operand) { std::vector muxed_operands; int max_width = 0; for (const auto& p : ports) { - auto op = p.alu; + auto op = p.op; - for (RTLIL::IdString port_name : {"\\A", "\\B"}) { - if (op->getPort(port_name) != operand.sig) { - auto operand = ExtSigSpec(op, port_name, &assign_map); - if (operand.sig.size() > max_width) { - max_width = operand.sig.size(); - } + RTLIL::IdString muxed_port_name = "\\A"; + if (op->getPort("\\A") == operand.sig) { + muxed_port_name = "\\B"; + } - muxed_operands.push_back(operand); - } + auto operand = decode_port(op, muxed_port_name, &assign_map); + if (operand.sig.size() > max_width) { + max_width = operand.sig.size(); } + + muxed_operands.push_back(operand); } + auto shared_op = ports[0].op; + + if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; })) + if (max_width < shared_op->getParam("\\Y_WIDTH").as_int()) + max_width = shared_op->getParam("\\Y_WIDTH").as_int(); + + for (auto &operand : muxed_operands) { operand.sig.extend_u0(max_width, operand.is_signed); } - auto shared_op = ports[0].alu; for (const auto& p : ports) { - auto op = p.alu; + auto op = p.op; if (op == shared_op) continue; module->remove(op); @@ -126,40 +219,47 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< RTLIL::SigSpec mux_b = mux->getPort("\\B"); RTLIL::SigSpec mux_s = mux->getPort("\\S"); - RTLIL::SigSpec alu_x = shared_op->getPort("\\X"); - RTLIL::SigSpec alu_co = shared_op->getPort("\\CO"); - RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); RTLIL::SigSpec shared_pmux_b; RTLIL::SigSpec shared_pmux_s; - shared_op->setPort("\\Y", shared_op->getPort("\\Y").extract(0, width)); + int conn_width = ports[0].sig.size(); + int conn_offset = ports[0].mux_port_offset; + + shared_op->setPort("\\Y", shared_op->getPort("\\Y").extract(0, conn_width)); if (mux->type == "$pmux") { shared_pmux_s = RTLIL::SigSpec(); - for (const auto&p: ports) { - shared_pmux_s.append(mux_s[p.port_id]); - mux_b.replace(p.port_id * mux_a.size() + offset, shared_op->getPort("\\Y")); + for (const auto &p : ports) { + shared_pmux_s.append(mux_s[p.mux_port_id]); + mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort("\\Y")); } } else { shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)}; - mux_a.replace(offset, shared_op->getPort("\\Y")); - mux_b.replace(offset, shared_op->getPort("\\Y")); + mux_a.replace(conn_offset, shared_op->getPort("\\Y")); + mux_b.replace(conn_offset, shared_op->getPort("\\Y")); } + mux->setPort("\\A", mux_a); + mux->setPort("\\B", mux_b); mux->setPort("\\Y", mux_y); mux->setPort("\\S", mux_s); - mux->setPort("\\B", mux_b); for (const auto &op : muxed_operands) shared_pmux_b.append(op.sig); auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s); - shared_op->setPort("\\X", alu_x.extract(0, width)); - shared_op->setPort("\\CO", alu_co.extract(0, width)); - shared_op->setParam("\\Y_WIDTH", width); + if (shared_op->type.in("$alu")) { + RTLIL::SigSpec alu_x = shared_op->getPort("\\X"); + RTLIL::SigSpec alu_co = shared_op->getPort("\\CO"); + + shared_op->setPort("\\X", alu_x.extract(0, conn_width)); + shared_op->setPort("\\CO", alu_co.extract(0, conn_width)); + } + + shared_op->setParam("\\Y_WIDTH", conn_width); if (shared_op->getPort("\\A") == operand.sig) { shared_op->setPort("\\B", mux_to_oper); @@ -173,11 +273,9 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< typedef struct { RTLIL::Cell *mux; - std::vector ports; - int offset; - int width; + std::vector ports; ExtSigSpec shared_operand; -} shared_op_t; +} merged_op_t; template void remove_val(std::vector &v, const std::vector &vals) @@ -190,86 +288,60 @@ template void remove_val(std::vector &v, const std::vector &v } } -bool find_op_res_width(int offset, int &width, std::vector& ports, const dict &op_outbit_to_outsig) +void check_muxed_operands(std::vector &ports, const ExtSigSpec &shared_operand) { - std::vector op_outsigs; - dict> op_outsig_span; - - std::transform(ports.begin(), ports.end(), std::back_inserter(op_outsigs), [&](InPort *p) { return op_outbit_to_outsig.at(p->sig[offset]); }); - - std::vector finished(ports.size(), false); + auto it = ports.begin(); + ExtSigSpec seed; - width = 0; + while (it != ports.end()) { + auto p = *it; + auto op = p->op; - std::function all_finished = [&] { return std::find(std::begin(finished), std::end(finished), false) == end(finished);}; - - while (!all_finished()) - { - ++offset; - ++width; - - if (offset >= ports[0]->sig.size()) { - for (size_t i = 0; i < op_outsigs.size(); ++i) { - if (finished[i]) - continue; - - op_outsig_span[width].insert(ports[i]); - finished[i] = true; - } - - break; + RTLIL::IdString muxed_port_name = "\\A"; + if (op->getPort("\\A") == shared_operand.sig) { + muxed_port_name = "\\B"; } - for (size_t i = 0; i < op_outsigs.size(); ++i) { - if (finished[i]) - continue; + auto operand = decode_port(op, muxed_port_name, &assign_map); - if ((width >= op_outsigs[i].size()) || (ports[i]->sig[offset] != op_outsigs[i][width])) { - op_outsig_span[width].insert(ports[i]); - finished[i] = true; - } - } - } - - for (auto w: op_outsig_span) { - if (w.second.size() > 1) { - width = w.first; + if (seed.empty()) + seed = operand; - ports.erase(std::remove_if(ports.begin(), ports.end(), [&](InPort *p) { return !w.second.count(p); }), ports.end()); - - return true; + if (operand.is_signed != seed.is_signed) { + ports.erase(it); + } else { + ++it; } } - - return false; } -ExtSigSpec find_shared_operand(InPort* seed, std::vector &ports, const std::map> &operand_to_users) +ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vector &ports, const std::map> &operand_to_users) { - std::set alus_using_operand; - std::set alus_set; + std::set ops_using_operand; + std::set ops_set; for(const auto& p: ports) - alus_set.insert(p->alu); + ops_set.insert(p->op); ExtSigSpec oper; - auto op_a = seed->alu; + auto op_a = seed->op; for (RTLIL::IdString port_name : {"\\A", "\\B"}) { - oper = ExtSigSpec(op_a, port_name, &assign_map); + oper = decode_port(op_a, port_name, &assign_map); auto operand_users = operand_to_users.at(oper); if (operand_users.size() == 1) continue; - alus_using_operand.clear(); - std::set_intersection(operand_users.begin(), operand_users.end(), alus_set.begin(), alus_set.end(), - std::inserter(alus_using_operand, alus_using_operand.begin())); + ops_using_operand.clear(); + for (auto mux_ops: ops_set) + if (operand_users.count(mux_ops)) + ops_using_operand.insert(mux_ops); - if (alus_using_operand.size() > 1) { - ports.erase(std::remove_if(ports.begin(), ports.end(), [&](InPort *p) { return !alus_using_operand.count(p->alu); }), - ports.end()); + if (ops_using_operand.size() > 1) { + ports.erase(std::remove_if(ports.begin(), ports.end(), [&](const OpMuxConn *p) { return !ops_using_operand.count(p->op); }), + ports.end()); return oper; } } @@ -277,40 +349,135 @@ ExtSigSpec find_shared_operand(InPort* seed, std::vector &ports, const return ExtSigSpec(); } -void remove_multi_user_outbits(RTLIL::Module *module, dict &op_outbit_to_outsig) +dict find_valid_op_mux_conns(RTLIL::Module *module, dict &op_outbit_to_outsig, + dict outsig_to_operator, + dict &op_aux_to_outsig) { - dict op_outbit_user_cnt; + dict op_outsig_user_track; + dict op_mux_conn_map; - std::function update_op_outbit_user_cnt = [&](SigSpec sig) { - auto outsig = assign_map(sig); - for (auto outbit : outsig) { - if (!op_outbit_to_outsig.count(outbit)) - continue; + std::function remove_outsig = [&](RTLIL::SigSpec outsig) { + for (auto op_outbit : outsig) + op_outbit_to_outsig.erase(op_outbit); + + if (op_mux_conn_map.count(outsig)) + op_mux_conn_map.erase(outsig); + }; - if (++op_outbit_user_cnt[outbit] > 1) { - auto alu_outsig = op_outbit_to_outsig.at(outbit); + std::function remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) { + auto aux_outsig = op_aux_to_outsig.at(auxbit); + auto op = outsig_to_operator.at(aux_outsig); + auto op_outsig = assign_map(op->getPort("\\Y")); + remove_outsig(op_outsig); - for (auto outbit : alu_outsig) - op_outbit_to_outsig.erase(outbit); + for (auto aux_outbit : aux_outsig) + op_aux_to_outsig.erase(aux_outbit); + }; + + std::function + find_op_mux_conns = [&](RTLIL::Cell *mux) { + RTLIL::SigSpec sig; + int mux_port_size; + + if (mux->type.in("$mux", "$_MUX_")) { + mux_port_size = mux->getPort("\\A").size(); + sig = RTLIL::SigSpec{mux->getPort("\\B"), mux->getPort("\\A")}; + } else { + mux_port_size = mux->getPort("\\A").size(); + sig = mux->getPort("\\B"); + } + + auto mux_insig = assign_map(sig); + + for (int i = 0; i < mux_insig.size(); ++i) { + if (op_aux_to_outsig.count(mux_insig[i])) { + remove_outsig_from_aux_bit(mux_insig[i]); + continue; + } + + if (!op_outbit_to_outsig.count(mux_insig[i])) + continue; + + auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]); + + if (op_mux_conn_map.count(op_outsig)) { + remove_outsig(op_outsig); + continue; + } + + int mux_port_id = i / mux_port_size; + int mux_port_offset = i % mux_port_size; + + int op_outsig_offset; + for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset) + ; + + int j = op_outsig_offset; + do { + if (!op_outbit_to_outsig.count(mux_insig[i])) + break; + + if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig) + break; + + ++i; + ++j; + } while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size())); + + int op_conn_width = j - op_outsig_offset; + OpMuxConn inp = { + op_outsig.extract(op_outsig_offset, op_conn_width), + mux, + outsig_to_operator.at(op_outsig), + mux_port_id, + mux_port_offset, + op_outsig_offset, + }; + + op_mux_conn_map[op_outsig] = inp; + + --i; + } + }; + + std::function remove_connected_ops = [&](RTLIL::SigSpec sig) { + auto mux_insig = assign_map(sig); + for (auto outbit : mux_insig) { + if (op_aux_to_outsig.count(outbit)) { + remove_outsig_from_aux_bit(outbit); + continue; } + + if (!op_outbit_to_outsig.count(outbit)) + continue; + + remove_outsig(op_outbit_to_outsig.at(outbit)); } }; - for (auto cell : module->cells()) - for (auto &conn : cell->connections()) - if (cell->input(conn.first)) - update_op_outbit_user_cnt(conn.second); + for (auto cell : module->cells()) { + if (cell->type.in("$mux", "$_MUX_", "$pmux")) { + remove_connected_ops(cell->getPort("\\S")); + find_op_mux_conns(cell); + } else { + for (auto &conn : cell->connections()) + if (cell->input(conn.first)) + remove_connected_ops(conn.second); + } + } for (auto w : module->wires()) { if (!w->port_output) continue; - update_op_outbit_user_cnt(w); + remove_connected_ops(w); } + + return op_mux_conn_map; } struct OptSharePass : public Pass { - OptSharePass() : Pass("opt_share", "merge arithmetic operators that share an operand") {} + OptSharePass() : Pass("opt_share", "merge mutually exclusive cells of the same type that share an input signal") {} void help() YS_OVERRIDE { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -318,18 +485,19 @@ struct OptSharePass : public Pass { log(" opt_share [selection]\n"); log("\n"); - log("This pass identifies mutually exclusive $alu arithmetic cells that:\n"); - log(" (a) share an input operand\n"); + log("This pass identifies mutually exclusive cells of the same type that:\n"); + log(" (a) share an input signal\n"); log(" (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell allowing\n"); - log(" the $alu cell to be merged and the multiplexer to be moved from\n"); - log(" multiplexing its output to multiplexing the non-shared input operands.\n"); + log(" the cell to be merged and the multiplexer to be moved from\n"); + log(" multiplexing its output to multiplexing the non-shared input signals.\n"); log("\n"); } - void execute(std::vector, RTLIL::Design *design) YS_OVERRIDE + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing OPT_SHARE pass.\n"); + extra_args(args, 1, design); for (auto module : design->selected_modules()) { assign_map.clear(); assign_map.set(module); @@ -337,28 +505,30 @@ struct OptSharePass : public Pass { std::map> operand_to_users; dict outsig_to_operator; dict op_outbit_to_outsig; + dict op_aux_to_outsig; bool any_shared_operands = false; std::vector op_insigs; for (auto cell : module->cells()) { - if (!cell->type.in("$alu")) + if (!cell_supported(cell)) continue; - RTLIL::SigSpec sig_bi = cell->getPort("\\BI"); - RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); - - if ((!sig_bi.is_fully_const()) || (!sig_ci.is_fully_const()) || (sig_bi != sig_ci)) - continue; - - RTLIL::SigSpec sig_y = cell->getPort("\\A"); + if (cell->type == "$alu") { + for (RTLIL::IdString port_name : {"\\X", "\\CO"}) { + auto mux_insig = assign_map(cell->getPort(port_name)); + outsig_to_operator[mux_insig] = cell; + for (auto outbit : mux_insig) + op_aux_to_outsig[outbit] = mux_insig; + } + } - auto outsig = assign_map(cell->getPort("\\Y")); - outsig_to_operator[outsig] = cell; - for (auto outbit : outsig) - op_outbit_to_outsig[outbit] = outsig; + auto mux_insig = assign_map(cell->getPort("\\Y")); + outsig_to_operator[mux_insig] = cell; + for (auto outbit : mux_insig) + op_outbit_to_outsig[outbit] = mux_insig; for (RTLIL::IdString port_name : {"\\A", "\\B"}) { - auto op_insig = ExtSigSpec(cell, port_name, &assign_map); + auto op_insig = decode_port(cell, port_name, &assign_map); op_insigs.push_back(op_insig); operand_to_users[op_insig].insert(cell); if (operand_to_users[op_insig].size() > 1) @@ -371,89 +541,117 @@ struct OptSharePass : public Pass { // Operator outputs need to be exclusively connected to the $mux inputs in order to be mergeable. Hence we count to // how many points are operator output bits connected. - remove_multi_user_outbits(module, op_outbit_to_outsig); + dict op_mux_conn_map = + find_valid_op_mux_conns(module, op_outbit_to_outsig, outsig_to_operator, op_aux_to_outsig); - std::vector shared_ops; - for (auto cell : module->cells()) { - if (!cell->type.in("$mux", "$_MUX_", "$pmux")) - continue; + // Group op connections connected to same ports of the same $mux. Sort them in ascending order of their port offset + dict>> mux_port_op_conns; + for (auto& val: op_mux_conn_map) { + OpMuxConn p = val.second; + auto& mux_port_conns = mux_port_op_conns[p.mux]; - RTLIL::SigSpec sig_a = cell->getPort("\\A"); - RTLIL::SigSpec sig_b = cell->getPort("\\B"); - RTLIL::SigSpec sig_s = cell->getPort("\\S"); + if (mux_port_conns.size() == 0) { + int mux_port_num; - std::vector ports; + if (p.mux->type.in("$mux", "$_MUX_")) + mux_port_num = 2; + else + mux_port_num = p.mux->getPort("\\S").size(); - if (cell->type.in("$mux", "$_MUX_")) { - ports.push_back(InPort(assign_map(sig_a), cell, 0)); - ports.push_back(InPort(assign_map(sig_b), cell, 1)); - } else { - RTLIL::SigSpec sig_s = cell->getPort("\\S"); - for (int i = 0; i < sig_s.size(); i++) { - auto inp = sig_b.extract(i * sig_a.size(), sig_a.size()); - ports.push_back(InPort(assign_map(inp), cell, i)); - } + mux_port_conns.resize(mux_port_num); } + mux_port_conns[p.mux_port_id].insert(p); + } + + std::vector merged_ops; + for (auto& val: mux_port_op_conns) { + + RTLIL::Cell* cell = val.first; + auto &mux_port_conns = val.second; + + const OpMuxConn *seed = NULL; + // Look through the bits of the $mux inputs and see which of them are connected to the operator // results. Operator results can be concatenated with other signals before led to the $mux. - for (int i = 0; i < sig_a.size(); ++i) { - std::vector alu_ports; - for (auto& p: ports) - if (op_outbit_to_outsig.count(p.sig[i])) { - p.alu = outsig_to_operator.at(op_outbit_to_outsig.at(p.sig[i])); - alu_ports.push_back(&p); - } + while (true) { - int alu_port_width = 0; + // Remove either the merged ports from the last iteration or the seed that failed to yield a merger + if (seed != NULL) { + mux_port_conns[seed->mux_port_id].erase(*seed); + seed = NULL; + } - while (alu_ports.size() > 1) { - std::vector shared_ports(alu_ports); + // For a new merger, find the seed op connection that starts at lowest port offset among port connections + for (auto &port_conns : mux_port_conns) { + if (!port_conns.size()) + continue; - auto seed = alu_ports[0]; - alu_ports.erase(alu_ports.begin()); + const OpMuxConn *next_p = &(*port_conns.begin()); - // Find ports whose $alu-s share an operand with $alu connected to the seed port - auto shared_operand = find_shared_operand(seed, shared_ports, operand_to_users); + if ((seed == NULL) || (seed->mux_port_offset > next_p->mux_port_offset)) + seed = next_p; + } - if (shared_operand.empty()) + // Cannot find the seed -> nothing to do for this $mux anymore + if (seed == NULL) + break; + + // Find all other op connections that start from the same port offset, and whose ops can be merged with the seed op + std::vector mergeable_conns; + for (auto &port_conns : mux_port_conns) { + if (!port_conns.size()) continue; - // Some bits of the operator results might be unconnected. Calculate the number of conneted - // bits. - if (!find_op_res_width(i, alu_port_width, shared_ports, op_outbit_to_outsig)) - break; + const OpMuxConn *next_p = &(*port_conns.begin()); + + if ((next_p->op_outsig_offset == seed->op_outsig_offset) && + (next_p->mux_port_offset == seed->mux_port_offset) && mergeable(next_p->op, seed->op) && + next_p->sig.size() == seed->sig.size()) + mergeable_conns.push_back(next_p); + } + + // We need at least two mergeable connections for the merger + if (mergeable_conns.size() < 2) + continue; - if (shared_ports.size() < 2) - break; + // Filter mergeable connections whose ops share an operand with seed connection's op + auto shared_operand = find_shared_operand(seed, mergeable_conns, operand_to_users); - // Remember the combination for the merger - std::vector shared_p; - for (auto p: shared_ports) - shared_p.push_back(*p); + if (shared_operand.empty()) + continue; - shared_ops.push_back(shared_op_t{cell, shared_p, i, alu_port_width, shared_operand}); + check_muxed_operands(mergeable_conns, shared_operand); - // Remove merged ports from the list and try to find other mergers for the mux - remove_val(alu_ports, shared_ports); + if (mergeable_conns.size() < 2) + continue; + + // Remember the combination for the merger + std::vector merged_ports; + for (auto p : mergeable_conns) { + merged_ports.push_back(*p); + mux_port_conns[p->mux_port_id].erase(*p); } - if (alu_port_width) - i += alu_port_width - 1; + seed = NULL; + + merged_ops.push_back(merged_op_t{cell, merged_ports, shared_operand}); + + design->scratchpad_set_bool("opt.did_something", true); } } - for (auto &shared : shared_ops) { - log(" Found arithmetic cells that share an operand and can be merged by moving the %s %s in front " + for (auto &shared : merged_ops) { + log(" Found cells that share an operand and can be merged by moving the %s %s in front " "of " "them:\n", log_id(shared.mux->type), log_id(shared.mux)); for (const auto& op : shared.ports) - log(" %s\n", log_id(op.alu)); + log(" %s\n", log_id(op.op)); log("\n"); - merge_operators(module, shared.mux, shared.ports, shared.offset, shared.width, shared.shared_operand); + merge_operators(module, shared.mux, shared.ports, shared.shared_operand); } } } -- cgit v1.2.3 From bfc7164af7bf64cb2fe5d00e87bbfead841a4dc2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 15:25:50 -0700 Subject: Move LSB-trimming functionality from wreduce to opt_expr --- passes/opt/opt_expr.cc | 25 +++++++++++++++++++++++++ passes/opt/wreduce.cc | 24 +----------------------- 2 files changed, 26 insertions(+), 23 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 512ef0cbf..acdc39937 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -641,6 +641,31 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } } + + if (cell->type.in("$add", "$sub")) { + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + bool sub = cell->type == "$sub"; + + int i; + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_a[i]); + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) + module->connect(sig_y[i], sig_b[i]); + else + break; + } + if (i > 0) { + cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); + cell->setPort("\\A", sig_a.extract_end(i)); + cell->setPort("\\B", sig_b.extract_end(i)); + cell->setPort("\\Y", sig_y.extract_end(i)); + cell->fixup_parameters(); + did_something = true; + } + } } if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" || diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 22af0bd8b..1eeca2748 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -365,28 +365,6 @@ struct WreduceWorker } } - if (cell->type.in("$add", "$sub")) { - SigSpec A = mi.sigmap(cell->getPort("\\A")); - SigSpec B = mi.sigmap(cell->getPort("\\B")); - bool sub = cell->type == "$sub"; - - int i; - for (i = 0; i < GetSize(sig); i++) { - if (B.at(i, Sx) == S0 && A.at(i, Sx) != Sx) - module->connect(sig[i], A[i]); - else if (!sub && A.at(i, Sx) == S0 && B.at(i, Sx) != Sx) - module->connect(sig[i], B[i]); - else - break; - } - if (i > 0) { - cell->setPort("\\A", A.extract(i, -1)); - cell->setPort("\\B", B.extract(i, -1)); - sig.remove(0, i); - bits_removed += i; - } - } - if (GetSize(sig) == 0) { log("Removed cell %s.%s (%s).\n", log_id(module), log_id(cell), log_id(cell->type)); module->remove(cell); @@ -394,7 +372,7 @@ struct WreduceWorker } if (bits_removed) { - log("Removed %d bits (of %d) from port Y of cell %s.%s (%s).\n", + log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); cell->setPort("\\Y", sig); did_something = true; -- cgit v1.2.3 From 43081337fa4a85cd4a1a007576eaf945816bd576 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:04:21 -0700 Subject: Cleanup opt_expr.cc --- passes/opt/opt_expr.cc | 65 +++++++++++++++++++++++--------------------------- 1 file changed, 30 insertions(+), 35 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 512ef0cbf..ef4b8b57a 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -367,10 +367,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : module->cells()) if (design->selected(module, cell) && cell->type[0] == '$') { - if ((cell->type == "$_NOT_" || cell->type == "$not" || cell->type == "$logic_not") && + if (cell->type.in("$_NOT_", "$not", "$logic_not") && cell->getPort("\\A").size() == 1 && cell->getPort("\\Y").size() == 1) invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\A")); - if ((cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == SigSpec(State::S1) && cell->getPort("\\B") == SigSpec(State::S0)) + if (cell->type.in("$mux", "$_MUX_") && + cell->getPort("\\A") == SigSpec(State::S1) && cell->getPort("\\B") == SigSpec(State::S0)) invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\S")); if (ct_combinational.cell_known(cell->type)) for (auto &conn : cell->connections()) { @@ -512,13 +513,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (do_fine) { - if (cell->type == "$not" || cell->type == "$pos" || - cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor") + if (cell->type.in("$not", "$pos", "$and", "$or", "$xor", "$xnor")) if (group_cell_inputs(module, cell, true, assign_map)) goto next_cell; - if (cell->type == "$logic_not" || cell->type == "$logic_and" || cell->type == "$logic_or" || - cell->type == "$reduce_or" || cell->type == "$reduce_and" || cell->type == "$reduce_bool") + if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool")) { SigBit neutral_bit = cell->type == "$reduce_and" ? State::S1 : State::S0; @@ -541,7 +540,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$logic_and" || cell->type == "$logic_or") + if (cell->type.in("$logic_and", "$logic_or")) { SigBit neutral_bit = State::S0; @@ -590,7 +589,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$logic_not" || cell->type == "$logic_and" || cell->type == "$logic_or" || cell->type == "$reduce_or" || cell->type == "$reduce_bool") + if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool")) { RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); @@ -616,7 +615,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$logic_and" || cell->type == "$logic_or") + if (cell->type.in("$logic_and", "$logic_or")) { RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); @@ -643,16 +642,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || cell->type == "$shift" || cell->type == "$shiftx" || - cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || - cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt" || - cell->type == "$neg" || cell->type == "$add" || cell->type == "$sub" || - cell->type == "$mul" || cell->type == "$div" || cell->type == "$mod" || cell->type == "$pow") + if (cell->type.in("$reduce_xor", "$reduce_xnor", "$shift", "$shiftx", "$shl", "$shr", "$sshl", "$sshr", + "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow")) { RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec sig_b = cell->hasPort("\\B") ? assign_map(cell->getPort("\\B")) : RTLIL::SigSpec(); - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || cell->type == "$shift" || cell->type == "$shiftx") + if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) sig_a = RTLIL::SigSpec(); for (auto &bit : sig_a.to_sigbit_vector()) @@ -667,8 +663,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons found_the_x_bit: cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str()); - if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor" || - cell->type == "$lt" || cell->type == "$le" || cell->type == "$ge" || cell->type == "$gt") + if (cell->type.in("$reduce_xor", "$reduce_xnor", "$lt", "$le", "$ge", "$gt")) replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::State::Sx); else replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort("\\Y").size())); @@ -676,14 +671,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if ((cell->type == "$_NOT_" || cell->type == "$not" || cell->type == "$logic_not") && cell->getPort("\\Y").size() == 1 && + if (cell->type.in("$_NOT_", "$not", "$logic_not") && cell->getPort("\\Y").size() == 1 && invert_map.count(assign_map(cell->getPort("\\A"))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); replace_cell(assign_map, module, cell, "double_invert", "\\Y", invert_map.at(assign_map(cell->getPort("\\A")))); goto next_cell; } - if ((cell->type == "$_MUX_" || cell->type == "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) { + if (cell->type.in("$_MUX_", "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) { cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str()); log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); RTLIL::SigSpec tmp = cell->getPort("\\A"); @@ -786,7 +781,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$_TBUF_" || cell->type == "$tribuf") { + if (cell->type.in("$_TBUF_", "$tribuf")) { RTLIL::SigSpec input = cell->getPort(cell->type == "$_TBUF_" ? "\\E" : "\\EN"); RTLIL::SigSpec a = cell->getPort("\\A"); assign_map.apply(input); @@ -803,7 +798,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex") + if (cell->type.in("$eq", "$ne", "$eqx", "$nex")) { RTLIL::SigSpec a = cell->getPort("\\A"); RTLIL::SigSpec b = cell->getPort("\\B"); @@ -820,7 +815,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (int i = 0; i < GetSize(a); i++) { if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) { cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1); + RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1); new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y); goto next_cell; @@ -833,7 +828,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a.size() == 0) { cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - RTLIL::SigSpec new_y = RTLIL::SigSpec((cell->type == "$eq" || cell->type == "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0); + RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0); new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); replace_cell(assign_map, module, cell, "empty", "\\Y", new_y); goto next_cell; @@ -848,7 +843,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if ((cell->type == "$eq" || cell->type == "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 && + if (cell->type.in("$eq", "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 && cell->parameters["\\A_WIDTH"].as_int() == 1 && cell->parameters["\\B_WIDTH"].as_int() == 1) { RTLIL::SigSpec a = assign_map(cell->getPort("\\A")); @@ -878,7 +873,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if ((cell->type == "$eq" || cell->type == "$ne") && + if (cell->type.in("$eq", "$ne") && (assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero())) { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); @@ -937,7 +932,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons bool identity_wrt_b = false; bool arith_inverse = false; - if (cell->type == "$add" || cell->type == "$sub" || cell->type == "$or" || cell->type == "$xor") + if (cell->type.in("$add", "$sub", "$or", "$xor")) { RTLIL::SigSpec a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); @@ -949,7 +944,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons identity_wrt_a = true; } - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr" || cell->type == "$shift" || cell->type == "$shiftx") + if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) { RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); @@ -1004,15 +999,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && - cell->getPort("\\A") == RTLIL::SigSpec(0, 1) && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) { + if (mux_bool && cell->type.in("$mux", "$_MUX_") && + cell->getPort("\\A") == State::S0 && cell->getPort("\\B") == State::S1) { cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str()); replace_cell(assign_map, module, cell, "mux_bool", "\\Y", cell->getPort("\\S")); goto next_cell; } - if (mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && - cell->getPort("\\A") == RTLIL::SigSpec(1, 1) && cell->getPort("\\B") == RTLIL::SigSpec(0, 1)) { + if (mux_bool && cell->type.in("$mux", "$_MUX_") && + cell->getPort("\\A") == State::S1 && cell->getPort("\\B") == State::S0) { cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", cell->getPort("\\S")); @@ -1031,7 +1026,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\A") == RTLIL::SigSpec(0, 1)) { + if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\A") == State::S0) { cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\A", cell->getPort("\\S")); @@ -1051,7 +1046,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (consume_x && mux_bool && (cell->type == "$mux" || cell->type == "$_MUX_") && cell->getPort("\\B") == RTLIL::SigSpec(1, 1)) { + if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\B") == State::S1) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->setPort("\\B", cell->getPort("\\S")); @@ -1071,7 +1066,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (mux_undef && (cell->type == "$mux" || cell->type == "$pmux")) { + if (mux_undef && cell->type.in("$mux", "$pmux")) { RTLIL::SigSpec new_a, new_b, new_s; int width = cell->getPort("\\A").size(); if ((cell->getPort("\\A").is_fully_undef() && cell->getPort("\\B").is_fully_undef()) || @@ -1413,7 +1408,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } // simplify comparisons - if (do_fine && (cell->type == "$lt" || cell->type == "$ge" || cell->type == "$gt" || cell->type == "$le")) + if (do_fine && cell->type.in("$lt", "$ge", "$gt", "$le")) { IdString cmp_type = cell->type; SigSpec var_sig = cell->getPort("\\A"); -- cgit v1.2.3 From 3486235338faa1377bb4e1a8981a45b4ee6edfa9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:18:18 -0700 Subject: Make liberal use of IdString.in() --- passes/opt/opt_merge.cc | 8 ++++---- passes/opt/opt_muxtree.cc | 2 +- passes/opt/opt_rmdff.cc | 6 +++--- passes/opt/share.cc | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 7567d4657..8964171e6 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -94,8 +94,8 @@ struct OptMergeWorker const dict *conn = &cell->connections(); dict alt_conn; - if (cell->type == "$and" || cell->type == "$or" || cell->type == "$xor" || cell->type == "$xnor" || cell->type == "$add" || cell->type == "$mul" || - cell->type == "$logic_and" || cell->type == "$logic_or" || cell->type == "$_AND_" || cell->type == "$_OR_" || cell->type == "$_XOR_") { + if (cell->type.in("$and", "$or", "$xor", "$xnor", "$add", "$mul", + "$logic_and", "$logic_or", "$_AND_", "$_OR_", "$_XOR_")) { alt_conn = *conn; if (assign_map(alt_conn.at("\\A")) < assign_map(alt_conn.at("\\B"))) { alt_conn["\\A"] = conn->at("\\B"); @@ -103,13 +103,13 @@ struct OptMergeWorker } conn = &alt_conn; } else - if (cell->type == "$reduce_xor" || cell->type == "$reduce_xnor") { + if (cell->type.in("$reduce_xor", "$reduce_xnor")) { alt_conn = *conn; assign_map.apply(alt_conn.at("\\A")); alt_conn.at("\\A").sort(); conn = &alt_conn; } else - if (cell->type == "$reduce_and" || cell->type == "$reduce_or" || cell->type == "$reduce_bool") { + if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool")) { alt_conn = *conn; assign_map.apply(alt_conn.at("\\A")); alt_conn.at("\\A").sort_and_unify(); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 6511e091b..4b96fe524 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -84,7 +84,7 @@ struct OptMuxtreeWorker // .const_deactivated for (auto cell : module->cells()) { - if (cell->type == "$mux" || cell->type == "$pmux") + if (cell->type.in("$mux", "$pmux")) { RTLIL::SigSpec sig_a = cell->getPort("\\A"); RTLIL::SigSpec sig_b = cell->getPort("\\B"); diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index be6ac2d30..d712736c1 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -71,7 +71,7 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) pol_set = cell->type[12] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; } else - if (cell->type == "$dffsr" || cell->type == "$dlatchsr") { + if (cell->type.in("$dffsr", "$dlatchsr")) { pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0; pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0; } else @@ -137,7 +137,7 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) return true; } - if (cell->type == "$dffsr" || cell->type == "$dlatchsr") + if (cell->type.in("$dffsr", "$dlatchsr")) { cell->setParam("\\WIDTH", GetSize(sig_d)); cell->setPort("\\SET", sig_set); @@ -624,7 +624,7 @@ struct OptRmdffPass : public Pass { } } - if (cell->type == "$mux" || cell->type == "$pmux") { + if (cell->type.in("$mux", "$pmux")) { if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell); continue; diff --git a/passes/opt/share.cc b/passes/opt/share.cc index c85c27427..7f66f749f 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -376,13 +376,13 @@ struct ShareWorker continue; } - if (cell->type == "$mul" || cell->type == "$div" || cell->type == "$mod") { + if (cell->type.in("$mul", "$div", "$mod")) { if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4) shareable_cells.insert(cell); continue; } - if (cell->type == "$shl" || cell->type == "$shr" || cell->type == "$sshl" || cell->type == "$sshr") { + if (cell->type.in("$shl", "$shr", "$sshl", "$sshr")) { if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8) shareable_cells.insert(cell); continue; -- cgit v1.2.3 From e38f40af5b7cdd5c8b896ffba17069bd65f01f29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:42:25 -0700 Subject: Use IdString::begins_with() --- passes/opt/opt_rmdff.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index d712736c1..450626f4a 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -63,11 +63,11 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) log_assert(GetSize(sig_set) == GetSize(sig_clr)); - if (cell->type.substr(0,8) == "$_DFFSR_") { + if (cell->type.begins_with("$_DFFSR_")) { pol_set = cell->type[9] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[10] == 'P' ? State::S1 : State::S0; } else - if (cell->type.substr(0,11) == "$_DLATCHSR_") { + if (cell->type.begins_with("$_DLATCHSR_")) { pol_set = cell->type[12] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; } else @@ -198,9 +198,9 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) { IdString new_type; - if (cell->type.substr(0,8) == "$_DFFSR_") + if (cell->type.begins_with("$_DFFSR_")) new_type = stringf("$_DFF_%c_", cell->type[8]); - else if (cell->type.substr(0,11) == "$_DLATCHSR_") + else if (cell->type.begins_with("$_DLATCHSR_")) new_type = stringf("$_DLATCH_%c_", cell->type[11]); else log_abort(); @@ -278,7 +278,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_c = dff->getPort("\\C"); val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1); } - else if (dff->type.substr(0,6) == "$_DFF_" && dff->type.substr(9) == "_" && + else if (dff->type.begins_with("$_DFF_") && dff->type.substr(9) == "_" && (dff->type[6] == 'N' || dff->type[6] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == '0' || dff->type[8] == '1')) { @@ -290,7 +290,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); } - else if (dff->type.substr(0,7) == "$_DFFE_" && dff->type.substr(9) == "_" && + else if (dff->type.begins_with("$_DFFE_") && dff->type.substr(9) == "_" && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == 'N' || dff->type[8] == 'P')) { sig_d = dff->getPort("\\D"); @@ -428,7 +428,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) return true; } - log_assert(dff->type.substr(0,6) == "$_DFF_"); + log_assert(dff->type.begins_with("$_DFF_")); dff->type = stringf("$_DFF_%c_", + dff->type[6]); dff->unsetPort("\\R"); } @@ -452,7 +452,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) return true; } - log_assert(dff->type.substr(0,7) == "$_DFFE_"); + log_assert(dff->type.begins_with("$_DFFE_")); dff->type = stringf("$_DFF_%c_", + dff->type[7]); dff->unsetPort("\\E"); } -- cgit v1.2.3 From c11ad24fd7d961432cfdbca7497ba229d3b4f38d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 6 Aug 2019 16:45:48 -0700 Subject: Use std::stoi instead of atoi(.c_str()) --- passes/opt/opt_lut.cc | 4 ++-- passes/opt/pmux2shiftx.cc | 4 ++-- passes/opt/share.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 587ef878a..6d97c0bb4 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -555,14 +555,14 @@ struct OptLutPass : public Pass { if (conn_tokens.size() != 2) log_cmd_error("Invalid format of -dlogic signal mapping.\n"); IdString logic_port = "\\" + conn_tokens[0]; - int lut_input = atoi(conn_tokens[1].c_str()); + int lut_input = std::stoi(conn_tokens[1]); dlogic[type][lut_input] = logic_port; } continue; } if (args[argidx] == "-limit" && argidx + 1 < args.size()) { - limit = atoi(args[++argidx].c_str()); + limit = std::stoi(args[++argidx]); continue; } break; diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 65d8b8f32..e571ed3c6 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -240,11 +240,11 @@ struct Pmux2ShiftxPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-min_density" && argidx+1 < args.size()) { - min_density = atoi(args[++argidx].c_str()); + min_density = std::stoi(args[++argidx]); continue; } if (args[argidx] == "-min_choices" && argidx+1 < args.size()) { - min_choices = atoi(args[++argidx].c_str()); + min_choices = std::stoi(args[++argidx]); continue; } if (args[argidx] == "-onehot" && argidx+1 < args.size() && args[argidx+1] == "ignore") { diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 7f66f749f..ea5bf8d33 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -1521,7 +1521,7 @@ struct SharePass : public Pass { continue; } if (args[argidx] == "-limit" && argidx+1 < args.size()) { - config.limit = atoi(args[++argidx].c_str()); + config.limit = std::stoi(args[++argidx]); continue; } break; -- cgit v1.2.3 From 067b44938c1fd3e24fc9478b96a47bac7152c111 Mon Sep 17 00:00:00 2001 From: Bogdan Vukobratovic Date: Wed, 7 Aug 2019 09:30:58 +0200 Subject: Fix wrong results when opt_share called before opt_clean --- passes/opt/opt_share.cc | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index e8f44749a..a2ec9cc37 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -138,7 +138,7 @@ RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { if (cell->type == "$alu" && port_name == "\\B") return cell->getPort("\\BI"); - else if (cell->type == "$sub" && port_name == "\\B") + else if (cell->type == "$sub" && port_name == "\\B") return RTLIL::Const(1, 1); return RTLIL::Const(0, 1); @@ -177,14 +177,12 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< auto op = p.op; RTLIL::IdString muxed_port_name = "\\A"; - if (op->getPort("\\A") == operand.sig) { + if (decode_port(op, "\\A", &assign_map) == operand) muxed_port_name = "\\B"; - } auto operand = decode_port(op, muxed_port_name, &assign_map); - if (operand.sig.size() > max_width) { + if (operand.sig.size() > max_width) max_width = operand.sig.size(); - } muxed_operands.push_back(operand); } @@ -196,10 +194,8 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< max_width = shared_op->getParam("\\Y_WIDTH").as_int(); - for (auto &operand : muxed_operands) { + for (auto &operand : muxed_operands) operand.sig.extend_u0(max_width, operand.is_signed); - } - for (const auto& p : ports) { auto op = p.op; @@ -208,11 +204,10 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< module->remove(op); } - for (auto &muxed_op : muxed_operands) { - if (muxed_op.sign != muxed_operands[0].sign) { + for (auto &muxed_op : muxed_operands) + if (muxed_op.sign != muxed_operands[0].sign) muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed)); - } - } + RTLIL::SigSpec mux_y = mux->getPort("\\Y"); RTLIL::SigSpec mux_a = mux->getPort("\\A"); @@ -261,7 +256,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< shared_op->setParam("\\Y_WIDTH", conn_width); - if (shared_op->getPort("\\A") == operand.sig) { + if (decode_port(shared_op, "\\A", &assign_map) == operand) { shared_op->setPort("\\B", mux_to_oper); shared_op->setParam("\\B_WIDTH", max_width); } else { @@ -299,7 +294,7 @@ void check_muxed_operands(std::vector &ports, const ExtSigSpe auto op = p->op; RTLIL::IdString muxed_port_name = "\\A"; - if (op->getPort("\\A") == shared_operand.sig) { + if (decode_port(op, "\\A", &assign_map) == shared_operand) { muxed_port_name = "\\B"; } @@ -486,10 +481,11 @@ struct OptSharePass : public Pass { log("\n"); log("This pass identifies mutually exclusive cells of the same type that:\n"); - log(" (a) share an input signal\n"); - log(" (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell allowing\n"); - log(" the cell to be merged and the multiplexer to be moved from\n"); - log(" multiplexing its output to multiplexing the non-shared input signals.\n"); + log(" (a) share an input signal,\n"); + log(" (b) drive the same $mux, $_MUX_, or $pmux multiplexing cell,\n"); + log("\n"); + log("allowing the cell to be merged and the multiplexer to be moved from\n"); + log("multiplexing its output to multiplexing the non-shared input signals.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From 48d0f994064557dc0832748e17133ee2eac88cbf Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 11:09:17 -0700 Subject: stoi -> atoi --- passes/opt/opt_lut.cc | 4 ++-- passes/opt/pmux2shiftx.cc | 4 ++-- passes/opt/share.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 6d97c0bb4..587ef878a 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -555,14 +555,14 @@ struct OptLutPass : public Pass { if (conn_tokens.size() != 2) log_cmd_error("Invalid format of -dlogic signal mapping.\n"); IdString logic_port = "\\" + conn_tokens[0]; - int lut_input = std::stoi(conn_tokens[1]); + int lut_input = atoi(conn_tokens[1].c_str()); dlogic[type][lut_input] = logic_port; } continue; } if (args[argidx] == "-limit" && argidx + 1 < args.size()) { - limit = std::stoi(args[++argidx]); + limit = atoi(args[++argidx].c_str()); continue; } break; diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index e571ed3c6..65d8b8f32 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -240,11 +240,11 @@ struct Pmux2ShiftxPass : public Pass { size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { if (args[argidx] == "-min_density" && argidx+1 < args.size()) { - min_density = std::stoi(args[++argidx]); + min_density = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-min_choices" && argidx+1 < args.size()) { - min_choices = std::stoi(args[++argidx]); + min_choices = atoi(args[++argidx].c_str()); continue; } if (args[argidx] == "-onehot" && argidx+1 < args.size() && args[argidx+1] == "ignore") { diff --git a/passes/opt/share.cc b/passes/opt/share.cc index ea5bf8d33..7f66f749f 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -1521,7 +1521,7 @@ struct SharePass : public Pass { continue; } if (args[argidx] == "-limit" && argidx+1 < args.size()) { - config.limit = std::stoi(args[++argidx]); + config.limit = atoi(args[++argidx].c_str()); continue; } break; -- cgit v1.2.3 From 71649969213863b2695f1c51956886fc7879c3e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 11:12:38 -0700 Subject: RTLIL::S{0,1} -> State::S{0,1} --- passes/opt/muxpack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 6697d6ca1..225c30d9a 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -49,7 +49,7 @@ struct ExclusiveDatabase } else if (cell->type == "$logic_not") { nonconst_sig = sigmap(cell->getPort("\\A")); - const_sig = Const(RTLIL::S0, GetSize(nonconst_sig)); + const_sig = Const(State::S0, GetSize(nonconst_sig)); y_port = sigmap(cell->getPort("\\Y")); } else if (cell->type == "$reduce_or") { -- cgit v1.2.3 From 6d77236f3845cd8785e7bdd4da3c5ef966be6043 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 12:20:08 -0700 Subject: substr() -> compare() --- passes/opt/opt_clean.cc | 6 +++--- passes/opt/opt_merge.cc | 2 +- passes/opt/opt_rmdff.cc | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index a8a8e0bc7..905c95b6c 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -222,10 +222,10 @@ bool compare_signals(RTLIL::SigBit &s1, RTLIL::SigBit &s2, SigPool ®s, SigPoo bool check_public_name(RTLIL::IdString id) { - const std::string &id_str = id.str(); - if (id_str[0] == '$') + if (id.begins_with("$")) return false; - if (id_str.substr(0, 2) == "\\_" && (id_str[id_str.size()-1] == '_' || id_str.find("_[") != std::string::npos)) + const std::string &id_str = id.str(); + if (id.begins_with("\\_") && (id.ends_with("_") || id_str.find("_[") != std::string::npos)) return false; if (id_str.find(".$") != std::string::npos) return false; diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index 8964171e6..cac7c0a6f 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -222,7 +222,7 @@ struct OptMergeWorker return true; } - if (cell1->type.substr(0, 1) == "$" && conn1.count("\\Q") != 0) { + if (cell1->type.begins_with("$") && conn1.count("\\Q") != 0) { std::vector q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector(); std::vector q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector(); for (size_t i = 0; i < q1.size(); i++) diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 450626f4a..8d42a37c3 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -278,7 +278,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) sig_c = dff->getPort("\\C"); val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1); } - else if (dff->type.begins_with("$_DFF_") && dff->type.substr(9) == "_" && + else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[6] == 'N' || dff->type[6] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == '0' || dff->type[8] == '1')) { @@ -290,7 +290,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); } - else if (dff->type.begins_with("$_DFFE_") && dff->type.substr(9) == "_" && + else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == 'N' || dff->type[8] == 'P')) { sig_d = dff->getPort("\\D"); -- cgit v1.2.3 From f69410daaf68cd3cef5e365df9b27c623ce589a7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 7 Aug 2019 13:12:28 -0700 Subject: opt_lut to ignore LUT cells, or those that drive bits, with (* keep *) --- passes/opt/opt_lut.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 587ef878a..4c199ba72 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -101,6 +101,12 @@ struct OptLutWorker { if (cell->type == "$lut") { + if (cell->has_keep_attr()) + continue; + SigBit lut_output = cell->getPort("\\Y"); + if (lut_output.wire->get_bool_attribute("\\keep")) + continue; + int lut_width = cell->getParam("\\WIDTH").as_int(); SigSpec lut_input = cell->getPort("\\A"); int lut_arity = 0; -- cgit v1.2.3 From 9f1b82f5941778a3691ce0ef08e0d06547451110 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 10:32:12 -0700 Subject: opt_expr -fine to trim LSBs of $alu too --- passes/opt/opt_expr.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index acdc39937..5a82b7066 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -642,26 +642,31 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in("$add", "$sub")) { + if (cell->type.in("$add", "$sub", "$alu")) + { RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - bool sub = cell->type == "$sub"; + bool ignore_a = cell->type == "$sub" || (cell->type == "$alu" && !cell->getPort("\\BI").is_fully_zero()); int i; for (i = 0; i < GetSize(sig_y); i++) { if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) module->connect(sig_y[i], sig_a[i]); - else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) + else if (!ignore_a && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) module->connect(sig_y[i], sig_b[i]); else break; } if (i > 0) { - cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); + cover_list("opt.opt_expr.fine", "$add", "$sub", "$alu", cell->type.str()); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\Y", sig_y.extract_end(i)); + if (cell->type == "$alu") { + cell->setPort("\\X", cell->getPort("\\X").extract_end(i)); + cell->setPort("\\CO", cell->getPort("\\CO").extract_end(i)); + } cell->fixup_parameters(); did_something = true; } -- cgit v1.2.3 From 31f6d745528e1cfc155e65ebb11de9499c0f11e6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 12:13:32 -0700 Subject: Separate $alu handling --- passes/opt/opt_expr.cc | 57 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 7 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 5a82b7066..0ddfa5e4c 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -642,31 +642,74 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in("$add", "$sub", "$alu")) + if (cell->type.in("$add", "$sub")) { RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - bool ignore_a = cell->type == "$sub" || (cell->type == "$alu" && !cell->getPort("\\BI").is_fully_zero()); + bool sub = cell->type == "$sub"; int i; for (i = 0; i < GetSize(sig_y); i++) { if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) module->connect(sig_y[i], sig_a[i]); - else if (!ignore_a && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) module->connect(sig_y[i], sig_b[i]); else break; } if (i > 0) { - cover_list("opt.opt_expr.fine", "$add", "$sub", "$alu", cell->type.str()); + cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\Y", sig_y.extract_end(i)); - if (cell->type == "$alu") { - cell->setPort("\\X", cell->getPort("\\X").extract_end(i)); - cell->setPort("\\CO", cell->getPort("\\CO").extract_end(i)); + cell->fixup_parameters(); + did_something = true; + } + } + + if (cell->type == "$alu") + { + RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigBit sig_ci = assign_map(cell->getPort("\\CI")); + RTLIL::SigBit sig_bi = assign_map(cell->getPort("\\BI")); + RTLIL::SigSpec sig_x = cell->getPort("\\X"); + RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + RTLIL::SigSpec sig_co = cell->getPort("\\CO"); + + if (sig_ci.wire || sig_bi.wire) + goto next_cell; + + bool sub = (sig_ci == State::S1 && sig_bi == State::S1); + + // If not a subtraction, yet there is a carry or B is inverted + // then no optimisation is possible as carry is not constant + if (!sub && (sig_ci != State::S0 || sig_bi != State::S0)) + goto next_cell; + + int i; + for (i = 0; i < GetSize(sig_y); i++) { + if (sig_b.at(i, State::Sx) == State::S0 && sig_a.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sub ? module->Not(NEW_ID, sig_a[i]).as_bit() : sig_a[i]); + module->connect(sig_y[i], sig_a[i]); + module->connect(sig_co[i], sub ? State::S1 : State::S0); } + else if (!sub && sig_a.at(i, State::Sx) == State::S0 && sig_b.at(i, State::Sx) != State::Sx) { + module->connect(sig_x[i], sig_b[i]); + module->connect(sig_y[i], sig_b[i]); + module->connect(sig_co[i], State::S0); + } + else + break; + } + if (i > 0) { + cover_list("opt.opt_expr.fine", "$alu", cell->type.str()); + cell->setPort("\\A", sig_a.extract_end(i)); + cell->setPort("\\B", sig_b.extract_end(i)); + cell->setPort("\\X", sig_x.extract_end(i)); + cell->setPort("\\Y", sig_y.extract_end(i)); + cell->setPort("\\CO", sig_co.extract_end(i)); cell->fixup_parameters(); did_something = true; } -- cgit v1.2.3 From 849e0eeab4408ed23d16abbf9d98a3603b770514 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 9 Aug 2019 12:43:21 -0700 Subject: Grammar --- passes/opt/opt_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 0ddfa5e4c..66f360f6e 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -684,7 +684,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons bool sub = (sig_ci == State::S1 && sig_bi == State::S1); // If not a subtraction, yet there is a carry or B is inverted - // then no optimisation is possible as carry is not constant + // then no optimisation is possible as carry will not be constant if (!sub && (sig_ci != State::S0 || sig_bi != State::S0)) goto next_cell; -- cgit v1.2.3 From 02b0d328ad4eadd2011344ef30e718262932cff8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 10 Aug 2019 08:26:41 -0700 Subject: cover_list -> cover as per @cliffordwolf --- passes/opt/opt_expr.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 66f360f6e..c803b5d3d 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -659,7 +659,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); + cover("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\Y", sig_y.extract_end(i)); @@ -704,7 +704,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - cover_list("opt.opt_expr.fine", "$alu", cell->type.str()); + cover_list("opt.opt_expr.fine.$alu"); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\X", sig_x.extract_end(i)); -- cgit v1.2.3 From 282cc77604a9a855c303869321d4179790b0b64b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 10 Aug 2019 11:55:00 -0700 Subject: Wrong way around --- passes/opt/opt_expr.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index c803b5d3d..29510fe81 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -659,7 +659,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - cover("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); + cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\Y", sig_y.extract_end(i)); @@ -704,7 +704,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons break; } if (i > 0) { - cover_list("opt.opt_expr.fine.$alu"); + cover("opt.opt_expr.fine.$alu"); cell->setPort("\\A", sig_a.extract_end(i)); cell->setPort("\\B", sig_b.extract_end(i)); cell->setPort("\\X", sig_x.extract_end(i)); -- cgit v1.2.3 From 6995914f3f55fc0f3d1160c7f45273b82eb923ce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 9 Aug 2019 18:58:14 +0200 Subject: Use ID() macro in all of passes/opt/ This was obtained by running the following SED command in passes/opt/ and then using "meld foo.cc foo.cc.orig" to manually fix all resulting compiler errors. sed -i.orig -r 's/"\\\\([a-zA-Z0-9_]+)"/ID(\1)/g; s/"(\$[a-zA-Z0-9_]+)"/ID(\1)/g;' *.cc Signed-off-by: Clifford Wolf --- passes/opt/muxpack.cc | 72 ++--- passes/opt/opt_clean.cc | 54 ++-- passes/opt/opt_demorgan.cc | 24 +- passes/opt/opt_expr.cc | 720 ++++++++++++++++++++++----------------------- passes/opt/opt_lut.cc | 54 ++-- passes/opt/opt_merge.cc | 102 +++---- passes/opt/opt_muxtree.cc | 42 +-- passes/opt/opt_reduce.cc | 110 +++---- passes/opt/opt_rmdff.cc | 248 ++++++++-------- passes/opt/pmux2shiftx.cc | 78 ++--- passes/opt/share.cc | 346 +++++++++++----------- passes/opt/wreduce.cc | 146 ++++----- 12 files changed, 998 insertions(+), 998 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 225c30d9a..cf6752b6e 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -37,22 +37,22 @@ struct ExclusiveDatabase SigBit y_port; pool reduce_or; for (auto cell : module->cells()) { - if (cell->type == "$eq") { - nonconst_sig = sigmap(cell->getPort("\\A")); - const_sig = sigmap(cell->getPort("\\B")); + if (cell->type == ID($eq)) { + nonconst_sig = sigmap(cell->getPort(ID(A))); + const_sig = sigmap(cell->getPort(ID(B))); if (!const_sig.is_fully_const()) { if (!nonconst_sig.is_fully_const()) continue; std::swap(nonconst_sig, const_sig); } - y_port = sigmap(cell->getPort("\\Y")); + y_port = sigmap(cell->getPort(ID(Y))); } - else if (cell->type == "$logic_not") { - nonconst_sig = sigmap(cell->getPort("\\A")); + else if (cell->type == ID($logic_not)) { + nonconst_sig = sigmap(cell->getPort(ID(A))); const_sig = Const(State::S0, GetSize(nonconst_sig)); - y_port = sigmap(cell->getPort("\\Y")); + y_port = sigmap(cell->getPort(ID(Y))); } - else if (cell->type == "$reduce_or") { + else if (cell->type == ID($reduce_or)) { reduce_or.insert(cell); continue; } @@ -66,7 +66,7 @@ struct ExclusiveDatabase for (auto cell : reduce_or) { nonconst_sig = SigSpec(); std::vector values; - SigSpec a_port = sigmap(cell->getPort("\\A")); + SigSpec a_port = sigmap(cell->getPort(ID(A))); for (auto bit : a_port) { auto it = sig_cmp_prev.find(bit); if (it == sig_cmp_prev.end()) { @@ -84,7 +84,7 @@ struct ExclusiveDatabase } if (nonconst_sig.empty()) continue; - y_port = sigmap(cell->getPort("\\Y")); + y_port = sigmap(cell->getPort(ID(Y))); sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values)); } } @@ -135,7 +135,7 @@ struct MuxpackWorker { for (auto wire : module->wires()) { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { + if (wire->port_output || wire->get_bool_attribute(ID(keep))) { for (auto bit : sigmap(wire)) sigbit_with_non_chain_users.insert(bit); } @@ -143,13 +143,13 @@ struct MuxpackWorker for (auto cell : module->cells()) { - if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep")) + if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep))) { - SigSpec a_sig = sigmap(cell->getPort("\\A")); + SigSpec a_sig = sigmap(cell->getPort(ID(A))); SigSpec b_sig; - if (cell->type == "$mux") - b_sig = sigmap(cell->getPort("\\B")); - SigSpec y_sig = sigmap(cell->getPort("\\Y")); + if (cell->type == ID($mux)) + b_sig = sigmap(cell->getPort(ID(B))); + SigSpec y_sig = sigmap(cell->getPort(ID(Y))); if (sig_chain_next.count(a_sig)) for (auto a_bit : a_sig.bits()) @@ -186,16 +186,16 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec a_sig = sigmap(cell->getPort("\\A")); - if (cell->type == "$mux") { - SigSpec b_sig = sigmap(cell->getPort("\\B")); + SigSpec a_sig = sigmap(cell->getPort(ID(A))); + if (cell->type == ID($mux)) { + SigSpec b_sig = sigmap(cell->getPort(ID(B))); if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) goto start_cell; if (!sig_chain_prev.count(a_sig)) a_sig = b_sig; } - else if (cell->type == "$pmux") { + else if (cell->type == ID($pmux)) { if (!sig_chain_prev.count(a_sig)) goto start_cell; } @@ -208,8 +208,8 @@ struct MuxpackWorker { Cell *prev_cell = sig_chain_prev.at(a_sig); log_assert(prev_cell); - SigSpec s_sig = sigmap(cell->getPort("\\S")); - s_sig.append(sigmap(prev_cell->getPort("\\S"))); + SigSpec s_sig = sigmap(cell->getPort(ID(S))); + s_sig.append(sigmap(prev_cell->getPort(ID(S)))); if (!excl_db.query(s_sig)) goto start_cell; } @@ -230,7 +230,7 @@ struct MuxpackWorker { chain.push_back(c); - SigSpec y_sig = sigmap(c->getPort("\\Y")); + SigSpec y_sig = sigmap(c->getPort(ID(Y))); if (sig_chain_next.count(y_sig) == 0) break; @@ -269,29 +269,29 @@ struct MuxpackWorker mux_count += cases; pmux_count += 1; - first_cell->type = "$pmux"; - SigSpec b_sig = first_cell->getPort("\\B"); - SigSpec s_sig = first_cell->getPort("\\S"); + first_cell->type = ID($pmux); + SigSpec b_sig = first_cell->getPort(ID(B)); + SigSpec s_sig = first_cell->getPort(ID(S)); for (int i = 1; i < cases; i++) { Cell* prev_cell = chain[cursor+i-1]; Cell* cursor_cell = chain[cursor+i]; - if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) { - b_sig.append(cursor_cell->getPort("\\B")); - s_sig.append(cursor_cell->getPort("\\S")); + if (sigmap(prev_cell->getPort(ID(Y))) == sigmap(cursor_cell->getPort(ID(A)))) { + b_sig.append(cursor_cell->getPort(ID(B))); + s_sig.append(cursor_cell->getPort(ID(S))); } else { - log_assert(cursor_cell->type == "$mux"); - b_sig.append(cursor_cell->getPort("\\A")); - s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S"))); + log_assert(cursor_cell->type == ID($mux)); + b_sig.append(cursor_cell->getPort(ID(A))); + s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S)))); } remove_cells.insert(cursor_cell); } - first_cell->setPort("\\B", b_sig); - first_cell->setPort("\\S", s_sig); - first_cell->setParam("\\S_WIDTH", GetSize(s_sig)); - first_cell->setPort("\\Y", last_cell->getPort("\\Y")); + first_cell->setPort(ID(B), b_sig); + first_cell->setPort(ID(S), s_sig); + first_cell->setParam(ID(S_WIDTH), GetSize(s_sig)); + first_cell->setPort(ID(Y), last_cell->getPort(ID(Y))); cursor += cases; } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 905c95b6c..1d3a85b3a 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -52,7 +52,7 @@ struct keep_cache_t return cache.at(module); cache[module] = true; - if (!module->get_bool_attribute("\\keep")) { + if (!module->get_bool_attribute(ID(keep))) { bool found_keep = false; for (auto cell : module->cells()) if (query(cell)) found_keep = true; @@ -64,7 +64,7 @@ struct keep_cache_t bool query(Cell *cell) { - if (cell->type.in("$memwr", "$meminit", "$assert", "$assume", "$live", "$fair", "$cover", "$specify2", "$specify3", "$specrule")) + if (cell->type.in(ID($memwr), ID($meminit), ID($assert), ID($assume), ID($live), ID($fair), ID($cover), ID($specify2), ID($specify3), ID($specrule))) return true; if (cell->has_keep_attr()) @@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it : module->wires_) { Wire *wire = it.second; - if (wire->port_output || wire->get_bool_attribute("\\keep")) { + if (wire->port_output || wire->get_bool_attribute(ID(keep))) { for (auto bit : sigmap(wire)) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); @@ -177,8 +177,8 @@ void rmunused_module_cells(Module *module, bool verbose) int count_nontrivial_wire_attrs(RTLIL::Wire *w) { int count = w->attributes.size(); - count -= w->attributes.count("\\src"); - count -= w->attributes.count("\\unused_bits"); + count -= w->attributes.count(ID(src)); + count -= w->attributes.count(ID(unused_bits)); return count; } @@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!wire->port_input) used_signals_nodrivers.add(sig); } - if (wire->get_bool_attribute("\\keep")) { + if (wire->get_bool_attribute(ID(keep))) { RTLIL::SigSpec sig = RTLIL::SigSpec(wire); assign_map.apply(sig); used_signals.add(sig); @@ -311,19 +311,19 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos log_assert(GetSize(s1) == GetSize(s2)); Const initval; - if (wire->attributes.count("\\init")) - initval = wire->attributes.at("\\init"); + if (wire->attributes.count(ID(init))) + initval = wire->attributes.at(ID(init)); if (GetSize(initval) != GetSize(wire)) initval.bits.resize(GetSize(wire), State::Sx); if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); + wire->attributes.erase(ID(init)); if (GetSize(wire) == 0) { // delete zero-width wires, unless they are module ports if (wire->port_id == 0) goto delete_this_wire; } else - if (wire->port_id != 0 || wire->get_bool_attribute("\\keep") || !initval.is_fully_undef()) { + if (wire->port_id != 0 || wire->get_bool_attribute(ID(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) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) { @@ -357,9 +357,9 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } if (new_conn.first.size() > 0) { if (initval.is_fully_undef()) - wire->attributes.erase("\\init"); + wire->attributes.erase(ID(init)); else - wire->attributes.at("\\init") = initval; + wire->attributes.at(ID(init)) = initval; used_signals.add(new_conn.first); used_signals.add(new_conn.second); module->connect(new_conn); @@ -377,11 +377,11 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos } } if (unused_bits.empty() || wire->port_id != 0) - wire->attributes.erase("\\unused_bits"); + wire->attributes.erase(ID(unused_bits)); else - wire->attributes["\\unused_bits"] = RTLIL::Const(unused_bits); + wire->attributes[ID(unused_bits)] = RTLIL::Const(unused_bits); } else { - wire->attributes.erase("\\unused_bits"); + wire->attributes.erase(ID(unused_bits)); } } } @@ -413,18 +413,18 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) dict qbits; for (auto cell : module->cells()) - if (fftypes.cell_known(cell->type) && cell->hasPort("\\Q")) + if (fftypes.cell_known(cell->type) && cell->hasPort(ID(Q))) { - SigSpec sig = cell->getPort("\\Q"); + SigSpec sig = cell->getPort(ID(Q)); for (int i = 0; i < GetSize(sig); i++) { SigBit bit = sig[i]; - if (bit.wire == nullptr || bit.wire->attributes.count("\\init") == 0) + if (bit.wire == nullptr || bit.wire->attributes.count(ID(init)) == 0) continue; - Const init = bit.wire->attributes.at("\\init"); + Const init = bit.wire->attributes.at(ID(init)); if (i >= GetSize(init) || init[i] == State::Sx || init[i] == State::Sz) continue; @@ -439,10 +439,10 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) if (!purge_mode && wire->name[0] == '\\') continue; - if (wire->attributes.count("\\init") == 0) + if (wire->attributes.count(ID(init)) == 0) continue; - Const init = wire->attributes.at("\\init"); + Const init = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(wire) && i < GetSize(init); i++) { @@ -465,7 +465,7 @@ bool rmunused_module_init(RTLIL::Module *module, bool purge_mode, bool verbose) if (verbose) log_debug(" removing redundant init attribute on %s.\n", log_id(wire)); - wire->attributes.erase("\\init"); + wire->attributes.erase(ID(init)); did_something = true; next_wire:; } @@ -480,10 +480,10 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool std::vector delcells; for (auto cell : module->cells()) - if (cell->type.in("$pos", "$_BUF_") && !cell->has_keep_attr()) { - bool is_signed = cell->type == "$pos" && cell->getParam("\\A_SIGNED").as_bool(); - RTLIL::SigSpec a = cell->getPort("\\A"); - RTLIL::SigSpec y = cell->getPort("\\Y"); + if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) { + bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool(); + RTLIL::SigSpec a = cell->getPort(ID(A)); + RTLIL::SigSpec y = cell->getPort(ID(Y)); a.extend_u0(GetSize(y), is_signed); module->connect(y, a); delcells.push_back(cell); @@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool for (auto cell : delcells) { if (verbose) log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), - log_signal(cell->getPort("\\Y")), log_signal(cell->getPort("\\A"))); + log_signal(cell->getPort(ID(Y))), log_signal(cell->getPort(ID(A)))); module->remove(cell); } if (!delcells.empty()) diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index 1699a6454..7defef442 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -35,10 +35,10 @@ void demorgan_worker( //TODO: Add support for reduce_xor //DeMorgan of XOR is either XOR (if even number of inputs) or XNOR (if odd number) - if( (cell->type != "$reduce_and") && (cell->type != "$reduce_or") ) + if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) ) return; - auto insig = sigmap(cell->getPort("\\A")); + auto insig = sigmap(cell->getPort(ID(A))); log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig)); int num_inverted = 0; for(int i=0; itype == "$_NOT_") + if(x.port == ID(Y) && x.cell->type == ID($_NOT_)) { inverted = true; break; @@ -85,7 +85,7 @@ void demorgan_worker( RTLIL::Cell* srcinv = NULL; for(auto x : ports) { - if(x.port == "\\Y" && x.cell->type == "$_NOT_") + if(x.port == ID(Y) && x.cell->type == ID($_NOT_)) { srcinv = x.cell; break; @@ -103,7 +103,7 @@ void demorgan_worker( //We ARE inverted - bypass it //Don't automatically delete the inverter since other stuff might still use it else - insig[i] = srcinv->getPort("\\A"); + insig[i] = srcinv->getPort(ID(A)); } //Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it @@ -151,20 +151,20 @@ void demorgan_worker( } //Push the new input signal back to the reduction (after bypassing/adding inverters) - cell->setPort("\\A", insig); + cell->setPort(ID(A), insig); //Change the cell type - if(cell->type == "$reduce_and") - cell->type = "$reduce_or"; - else if(cell->type == "$reduce_or") - cell->type = "$reduce_and"; + if(cell->type == ID($reduce_and)) + cell->type = ID($reduce_or); + else if(cell->type == ID($reduce_or)) + cell->type = ID($reduce_and); //don't change XOR //Add an inverter to the output - auto inverted_output = cell->getPort("\\Y"); + auto inverted_output = cell->getPort(ID(Y)); auto uninverted_output = m->addWire(NEW_ID); m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output); - cell->setPort("\\Y", uninverted_output); + cell->setPort(ID(Y), uninverted_output); } struct OptDemorganPass : public Pass { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b2dc9a448..8f6e660a2 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -51,9 +51,9 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } for (auto wire : module->wires()) { - if (wire->attributes.count("\\init")) { + if (wire->attributes.count(ID(init))) { SigSpec sig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { if (initval[i] == State::S0 || initval[i] == State::S1) initbits[sig[i]] = make_pair(wire, initval[i]); @@ -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 || wire->get_bool_attribute("\\keep")) + if (wire->port_output || wire->get_bool_attribute(ID(keep))) used_signals.add(sigmap(wire)); all_signals.add(sigmap(wire)); } @@ -99,25 +99,25 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) for (auto wire : revisit_initwires) { SigSpec sig = sm2(wire); - Const initval = wire->attributes.at("\\init"); + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { if (SigBit(initval[i]) == sig[i]) initval[i] = State::Sx; } if (initval.is_fully_undef()) { log_debug("Removing init attribute from %s/%s.\n", log_id(module), log_id(wire)); - wire->attributes.erase("\\init"); + wire->attributes.erase(ID(init)); did_something = true; - } else if (initval != wire->attributes.at("\\init")) { + } else if (initval != wire->attributes.at(ID(init))) { log_debug("Updating init attribute on %s/%s: %s\n", log_id(module), log_id(wire), log_signal(initval)); - wire->attributes["\\init"] = initval; + wire->attributes[ID(init)] = initval; did_something = true; } } } } -void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) +void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, IdString out_port, RTLIL::SigSpec out_val) { RTLIL::SigSpec Y = cell->getPort(out_port); out_val.extend_u0(Y.size(), false); @@ -134,14 +134,14 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap) { - std::string b_name = cell->hasPort("\\B") ? "\\B" : "\\A"; + IdString b_name = cell->hasPort(ID(B)) ? ID(B) : ID(A); - bool a_signed = cell->parameters.at("\\A_SIGNED").as_bool(); - bool b_signed = cell->parameters.at(b_name + "_SIGNED").as_bool(); + bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool(); + bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool(); - RTLIL::SigSpec sig_a = sigmap(cell->getPort("\\A")); + RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID(A))); RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name)); - RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y")); + RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y))); sig_a.extend_u0(sig_y.size(), a_signed); sig_b.extend_u0(sig_y.size(), b_signed); @@ -156,10 +156,10 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ int group_idx = GRP_DYN; RTLIL::SigBit bit_a = bits_a[i], bit_b = bits_b[i]; - if (cell->type == "$or" && (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1)) + if (cell->type == ID($or) && (bit_a == RTLIL::State::S1 || bit_b == RTLIL::State::S1)) bit_a = bit_b = RTLIL::State::S1; - if (cell->type == "$and" && (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0)) + if (cell->type == ID($and) && (bit_a == RTLIL::State::S0 || bit_b == RTLIL::State::S0)) bit_a = bit_b = RTLIL::State::S0; if (bit_a.wire == NULL && bit_b.wire == NULL) @@ -199,7 +199,7 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ new_b.append_bit(it.first.second); } - if (cell->type.in("$and", "$or") && i == GRP_CONST_A) { + if (cell->type.in(ID($and), ID($or)) && i == GRP_CONST_A) { log_debug(" Direct Connection: %s (%s with %s)\n", log_signal(new_b), log_id(cell->type), log_signal(new_a)); module->connect(new_y, new_b); module->connect(new_conn); @@ -208,24 +208,24 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ RTLIL::Cell *c = module->addCell(NEW_ID, cell->type); - c->setPort("\\A", new_a); - c->parameters["\\A_WIDTH"] = new_a.size(); - c->parameters["\\A_SIGNED"] = false; + c->setPort(ID(A), new_a); + c->parameters[ID(A_WIDTH)] = new_a.size(); + c->parameters[ID(A_SIGNED)] = false; - if (b_name == "\\B") { - c->setPort("\\B", new_b); - c->parameters["\\B_WIDTH"] = new_b.size(); - c->parameters["\\B_SIGNED"] = false; + if (b_name == ID(B)) { + c->setPort(ID(B), new_b); + c->parameters[ID(B_WIDTH)] = new_b.size(); + c->parameters[ID(B_SIGNED)] = false; } - c->setPort("\\Y", new_y); - c->parameters["\\Y_WIDTH"] = new_y->width; + c->setPort(ID(Y), new_y); + c->parameters[ID(Y_WIDTH)] = new_y->width; c->check(); module->connect(new_conn); log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); - if (b_name == "\\B") + if (b_name == ID(B)) log_debug(", B=%s", log_signal(new_b)); log_debug("\n"); } @@ -367,12 +367,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : module->cells()) if (design->selected(module, cell) && cell->type[0] == '$') { - if (cell->type.in("$_NOT_", "$not", "$logic_not") && - cell->getPort("\\A").size() == 1 && cell->getPort("\\Y").size() == 1) - invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\A")); - if (cell->type.in("$mux", "$_MUX_") && - cell->getPort("\\A") == SigSpec(State::S1) && cell->getPort("\\B") == SigSpec(State::S0)) - invert_map[assign_map(cell->getPort("\\Y"))] = assign_map(cell->getPort("\\S")); + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && + cell->getPort(ID(A)).size() == 1 && cell->getPort(ID(Y)).size() == 1) + invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(A))); + if (cell->type.in(ID($mux), ID($_MUX_)) && + cell->getPort(ID(A)) == SigSpec(State::S1) && cell->getPort(ID(B)) == SigSpec(State::S0)) + invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(S))); if (ct_combinational.cell_known(cell->type)) for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = assign_map(conn.second); @@ -396,66 +396,66 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : cells.sorted) { #define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0) -#define ACTION_DO_Y(_v_) ACTION_DO("\\Y", RTLIL::SigSpec(RTLIL::State::S ## _v_)) +#define ACTION_DO_Y(_v_) ACTION_DO(ID(Y), RTLIL::SigSpec(RTLIL::State::S ## _v_)) if (clkinv) { - if (cell->type.in("$dff", "$dffe", "$dffsr", "$adff", "$fsm", "$memrd", "$memwr")) - handle_polarity_inv(cell, "\\CLK", "\\CLK_POLARITY", assign_map, invert_map); + if (cell->type.in(ID($dff), ID($dffe), ID($dffsr), ID($adff), ID($fsm), ID($memrd), ID($memwr))) + handle_polarity_inv(cell, ID(CLK), ID(CLK_POLARITY), assign_map, invert_map); - if (cell->type.in("$sr", "$dffsr", "$dlatchsr")) { - handle_polarity_inv(cell, "\\SET", "\\SET_POLARITY", assign_map, invert_map); - handle_polarity_inv(cell, "\\CLR", "\\CLR_POLARITY", assign_map, invert_map); + if (cell->type.in(ID($sr), ID($dffsr), ID($dlatchsr))) { + handle_polarity_inv(cell, ID(SET), ID(SET_POLARITY), assign_map, invert_map); + handle_polarity_inv(cell, ID(CLR), ID(CLR_POLARITY), assign_map, invert_map); } - if (cell->type.in("$dffe", "$dlatch", "$dlatchsr")) - handle_polarity_inv(cell, "\\EN", "\\EN_POLARITY", assign_map, invert_map); + if (cell->type.in(ID($dffe), ID($dlatch), ID($dlatchsr))) + handle_polarity_inv(cell, ID(EN), ID(EN_POLARITY), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", "\\S", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", "\\R", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_SR_N?_", "$_SR_P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_SR_?N_", "$_SR_?P_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", "\\C", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_N_", "$_DFF_P_", ID(C), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", "\\C", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", "\\E", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFE_N?_", "$_DFFE_P?_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFE_?N_", "$_DFFE_?P_", ID(E), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", "\\C", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", "\\R", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_N??_", "$_DFF_P??_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFF_?N?_", "$_DFF_?P?_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", "\\C", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", "\\S", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", "\\R", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_N??_", "$_DFFSR_P??_", ID(C), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_?N?_", "$_DFFSR_?P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DFFSR_??N_", "$_DFFSR_??P_", ID(R), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", "\\E", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCH_N_", "$_DLATCH_P_", ID(E), assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", "\\E", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", "\\S", assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", "\\R", assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID(E), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID(S), assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID(R), assign_map, invert_map); } bool detect_const_and = false; bool detect_const_or = false; - if (cell->type.in("$reduce_and", "$_AND_")) + if (cell->type.in(ID($reduce_and), ID($_AND_))) detect_const_and = true; - if (cell->type.in("$and", "$logic_and") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool()) + if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_and = true; - if (cell->type.in("$reduce_or", "$reduce_bool", "$_OR_")) + if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_))) detect_const_or = true; - if (cell->type.in("$or", "$logic_or") && GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\B")) == 1 && !cell->getParam("\\A_SIGNED").as_bool()) + if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_or = true; if (detect_const_and || detect_const_or) { - pool input_bits = assign_map(cell->getPort("\\A")).to_sigbit_pool(); + pool input_bits = assign_map(cell->getPort(ID(A))).to_sigbit_pool(); bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false; SigBit non_const_input = State::Sm; - if (cell->hasPort("\\B")) { - vector more_bits = assign_map(cell->getPort("\\B")).to_sigbit_vector(); + if (cell->hasPort(ID(B))) { + vector more_bits = assign_map(cell->getPort(ID(B))).to_sigbit_vector(); input_bits.insert(more_bits.begin(), more_bits.end()); } @@ -495,14 +495,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool", "$reduce_xor", "$reduce_xnor", "$neg") && - GetSize(cell->getPort("\\A")) == 1 && GetSize(cell->getPort("\\Y")) == 1) + if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && + GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(Y))) == 1) { - if (cell->type == "$reduce_xnor") { + if (cell->type == ID($reduce_xnor)) { cover("opt.opt_expr.reduce_xnor_not"); log_debug("Replacing %s cell `%s' in module `%s' with $not cell.\n", log_id(cell->type), log_id(cell->name), log_id(module)); - cell->type = "$not"; + cell->type = ID($not); did_something = true; } else { cover("opt.opt_expr.unary_buffer"); @@ -513,15 +513,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (do_fine) { - if (cell->type.in("$not", "$pos", "$and", "$or", "$xor", "$xnor")) + if (cell->type.in(ID($not), ID($pos), ID($and), ID($or), ID($xor), ID($xnor))) if (group_cell_inputs(module, cell, true, assign_map)) goto next_cell; - if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool")) + if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_and), ID($reduce_bool))) { - SigBit neutral_bit = cell->type == "$reduce_and" ? State::S1 : State::S0; + SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0; - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); RTLIL::SigSpec new_sig_a; for (auto bit : sig_a) @@ -534,17 +534,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str()); log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a)); - cell->setPort("\\A", new_sig_a); - cell->parameters.at("\\A_WIDTH") = GetSize(new_sig_a); + cell->setPort(ID(A), new_sig_a); + cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a); did_something = true; } } - if (cell->type.in("$logic_and", "$logic_or")) + if (cell->type.in(ID($logic_and), ID($logic_or))) { SigBit neutral_bit = State::S0; - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); RTLIL::SigSpec new_sig_b; for (auto bit : sig_b) @@ -557,15 +557,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str()); log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b)); - cell->setPort("\\B", new_sig_b); - cell->parameters.at("\\B_WIDTH") = GetSize(new_sig_b); + cell->setPort(ID(B), new_sig_b); + cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b); did_something = true; } } - if (cell->type == "$reduce_and") + if (cell->type == ID($reduce_and)) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); RTLIL::State new_a = RTLIL::State::S1; for (auto &bit : sig_a.to_sigbit_vector()) @@ -583,15 +583,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover("opt.opt_expr.fine.$reduce_and"); log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); - cell->setPort("\\A", sig_a = new_a); - cell->parameters.at("\\A_WIDTH") = 1; + cell->setPort(ID(A), sig_a = new_a); + cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } } - if (cell->type.in("$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool")) + if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool))) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); RTLIL::State new_a = RTLIL::State::S0; for (auto &bit : sig_a.to_sigbit_vector()) @@ -609,15 +609,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str()); log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); - cell->setPort("\\A", sig_a = new_a); - cell->parameters.at("\\A_WIDTH") = 1; + cell->setPort(ID(A), sig_a = new_a); + cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } } - if (cell->type.in("$logic_and", "$logic_or")) + if (cell->type.in(ID($logic_and), ID($logic_or))) { - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); RTLIL::State new_b = RTLIL::State::S0; for (auto &bit : sig_b.to_sigbit_vector()) @@ -635,17 +635,17 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str()); log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b)); - cell->setPort("\\B", sig_b = new_b); - cell->parameters.at("\\B_WIDTH") = 1; + cell->setPort(ID(B), sig_b = new_b); + cell->parameters.at(ID(B_WIDTH)) = 1; did_something = true; } } - if (cell->type.in("$add", "$sub")) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); - RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - bool sub = cell->type == "$sub"; + if (cell->type.in(ID($add), ID($sub))) { + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); + bool sub = cell->type == ID($sub); int i; for (i = 0; i < GetSize(sig_y); i++) { @@ -658,22 +658,22 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (i > 0) { cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); - cell->setPort("\\A", sig_a.extract_end(i)); - cell->setPort("\\B", sig_b.extract_end(i)); - cell->setPort("\\Y", sig_y.extract_end(i)); + cell->setPort(ID(A), sig_a.extract_end(i)); + cell->setPort(ID(B), sig_b.extract_end(i)); + cell->setPort(ID(Y), sig_y.extract_end(i)); cell->fixup_parameters(); did_something = true; } } } - if (cell->type.in("$reduce_xor", "$reduce_xnor", "$shift", "$shiftx", "$shl", "$shr", "$sshl", "$sshr", - "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow")) + if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr), + ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = cell->hasPort("\\B") ? assign_map(cell->getPort("\\B")) : RTLIL::SigSpec(); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_b = cell->hasPort(ID(B)) ? assign_map(cell->getPort(ID(B))) : RTLIL::SigSpec(); - if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) + if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) sig_a = RTLIL::SigSpec(); for (auto &bit : sig_a.to_sigbit_vector()) @@ -688,7 +688,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons found_the_x_bit: cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str()); - if (cell->type.in("$reduce_xor", "$reduce_xnor", "$lt", "$le", "$ge", "$gt")) + if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt))) replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::State::Sx); else replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort("\\Y").size())); @@ -696,36 +696,36 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in("$_NOT_", "$not", "$logic_not") && cell->getPort("\\Y").size() == 1 && - invert_map.count(assign_map(cell->getPort("\\A"))) != 0) { + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID(Y)).size() == 1 && + invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); replace_cell(assign_map, module, cell, "double_invert", "\\Y", invert_map.at(assign_map(cell->getPort("\\A")))); goto next_cell; } - if (cell->type.in("$_MUX_", "$mux") && invert_map.count(assign_map(cell->getPort("\\S"))) != 0) { + if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) { cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str()); log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); - RTLIL::SigSpec tmp = cell->getPort("\\A"); - cell->setPort("\\A", cell->getPort("\\B")); - cell->setPort("\\B", tmp); - cell->setPort("\\S", invert_map.at(assign_map(cell->getPort("\\S")))); + RTLIL::SigSpec tmp = cell->getPort(ID(A)); + cell->setPort(ID(A), cell->getPort(ID(B))); + cell->setPort(ID(B), tmp); + cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S))))); did_something = true; goto next_cell; } - if (cell->type == "$_NOT_") { - RTLIL::SigSpec input = cell->getPort("\\A"); + if (cell->type == ID($_NOT_)) { + RTLIL::SigSpec input = cell->getPort(ID(A)); assign_map.apply(input); if (input.match("1")) ACTION_DO_Y(0); if (input.match("0")) ACTION_DO_Y(1); if (input.match("*")) ACTION_DO_Y(x); } - if (cell->type == "$_AND_") { + if (cell->type == ID($_AND_)) { RTLIL::SigSpec input; - input.append(cell->getPort("\\B")); - input.append(cell->getPort("\\A")); + input.append(cell->getPort(ID(B))); + input.append(cell->getPort(ID(A))); assign_map.apply(input); if (input.match(" 0")) ACTION_DO_Y(0); if (input.match("0 ")) ACTION_DO_Y(0); @@ -737,14 +737,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match(" *")) ACTION_DO_Y(0); if (input.match("* ")) ACTION_DO_Y(0); } - if (input.match(" 1")) ACTION_DO("\\Y", input.extract(1, 1)); - if (input.match("1 ")) ACTION_DO("\\Y", input.extract(0, 1)); + if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1)); + if (input.match("1 ")) ACTION_DO(ID(Y), input.extract(0, 1)); } - if (cell->type == "$_OR_") { + if (cell->type == ID($_OR_)) { RTLIL::SigSpec input; - input.append(cell->getPort("\\B")); - input.append(cell->getPort("\\A")); + input.append(cell->getPort(ID(B))); + input.append(cell->getPort(ID(A))); assign_map.apply(input); if (input.match(" 1")) ACTION_DO_Y(1); if (input.match("1 ")) ACTION_DO_Y(1); @@ -756,14 +756,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match(" *")) ACTION_DO_Y(1); if (input.match("* ")) ACTION_DO_Y(1); } - if (input.match(" 0")) ACTION_DO("\\Y", input.extract(1, 1)); - if (input.match("0 ")) ACTION_DO("\\Y", input.extract(0, 1)); + if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1)); + if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1)); } - if (cell->type == "$_XOR_") { + if (cell->type == ID($_XOR_)) { RTLIL::SigSpec input; - input.append(cell->getPort("\\B")); - input.append(cell->getPort("\\A")); + input.append(cell->getPort(ID(B))); + input.append(cell->getPort(ID(A))); assign_map.apply(input); if (input.match("00")) ACTION_DO_Y(0); if (input.match("01")) ACTION_DO_Y(1); @@ -771,27 +771,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("11")) ACTION_DO_Y(0); if (input.match(" *")) ACTION_DO_Y(x); if (input.match("* ")) ACTION_DO_Y(x); - if (input.match(" 0")) ACTION_DO("\\Y", input.extract(1, 1)); - if (input.match("0 ")) ACTION_DO("\\Y", input.extract(0, 1)); + if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1)); + if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1)); } - if (cell->type == "$_MUX_") { + if (cell->type == ID($_MUX_)) { RTLIL::SigSpec input; - input.append(cell->getPort("\\S")); - input.append(cell->getPort("\\B")); - input.append(cell->getPort("\\A")); + input.append(cell->getPort(ID(S))); + input.append(cell->getPort(ID(B))); + input.append(cell->getPort(ID(A))); assign_map.apply(input); if (input.extract(2, 1) == input.extract(1, 1)) - ACTION_DO("\\Y", input.extract(2, 1)); - if (input.match(" 0")) ACTION_DO("\\Y", input.extract(2, 1)); - if (input.match(" 1")) ACTION_DO("\\Y", input.extract(1, 1)); - if (input.match("01 ")) ACTION_DO("\\Y", input.extract(0, 1)); + ACTION_DO(ID(Y), input.extract(2, 1)); + if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(2, 1)); + if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1)); + if (input.match("01 ")) ACTION_DO(ID(Y), input.extract(0, 1)); if (input.match("10 ")) { cover("opt.opt_expr.mux_to_inv"); - cell->type = "$_NOT_"; - cell->setPort("\\A", input.extract(0, 1)); - cell->unsetPort("\\B"); - cell->unsetPort("\\S"); + cell->type = ID($_NOT_); + cell->setPort(ID(A), input.extract(0, 1)); + cell->unsetPort(ID(B)); + cell->unsetPort(ID(S)); goto next_cell; } if (input.match("11 ")) ACTION_DO_Y(1); @@ -800,38 +800,38 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("01*")) ACTION_DO_Y(x); if (input.match("10*")) ACTION_DO_Y(x); if (mux_undef) { - if (input.match("* ")) ACTION_DO("\\Y", input.extract(1, 1)); - if (input.match(" * ")) ACTION_DO("\\Y", input.extract(2, 1)); - if (input.match(" *")) ACTION_DO("\\Y", input.extract(2, 1)); + if (input.match("* ")) ACTION_DO(ID(Y), input.extract(1, 1)); + if (input.match(" * ")) ACTION_DO(ID(Y), input.extract(2, 1)); + if (input.match(" *")) ACTION_DO(ID(Y), input.extract(2, 1)); } } - if (cell->type.in("$_TBUF_", "$tribuf")) { - RTLIL::SigSpec input = cell->getPort(cell->type == "$_TBUF_" ? "\\E" : "\\EN"); - RTLIL::SigSpec a = cell->getPort("\\A"); + if (cell->type.in(ID($_TBUF_), ID($tribuf))) { + RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN)); + RTLIL::SigSpec a = cell->getPort(ID(A)); assign_map.apply(input); assign_map.apply(a); if (input == State::S1) - ACTION_DO("\\Y", cell->getPort("\\A")); + ACTION_DO(ID(Y), cell->getPort(ID(A))); if (input == State::S0 && !a.is_fully_undef()) { cover("opt.opt_expr.action_" S__LINE__); log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); - cell->setPort("\\A", SigSpec(State::Sx, GetSize(a))); + cell->setPort(ID(A), SigSpec(State::Sx, GetSize(a))); did_something = true; goto next_cell; } } - if (cell->type.in("$eq", "$ne", "$eqx", "$nex")) + if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex))) { - RTLIL::SigSpec a = cell->getPort("\\A"); - RTLIL::SigSpec b = cell->getPort("\\B"); + RTLIL::SigSpec a = cell->getPort(ID(A)); + RTLIL::SigSpec b = cell->getPort(ID(B)); - if (cell->parameters["\\A_WIDTH"].as_int() != cell->parameters["\\B_WIDTH"].as_int()) { - int width = max(cell->parameters["\\A_WIDTH"].as_int(), cell->parameters["\\B_WIDTH"].as_int()); - a.extend_u0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()); - b.extend_u0(width, cell->parameters["\\A_SIGNED"].as_bool() && cell->parameters["\\B_SIGNED"].as_bool()); + if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) { + int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int()); + a.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()); + b.extend_u0(width, cell->parameters[ID(A_SIGNED)].as_bool() && cell->parameters[ID(B_SIGNED)].as_bool()); } RTLIL::SigSpec new_a, new_b; @@ -840,8 +840,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (int i = 0; i < GetSize(a); i++) { if (a[i].wire == NULL && b[i].wire == NULL && a[i] != b[i] && a[i].data <= RTLIL::State::S1 && b[i].data <= RTLIL::State::S1) { cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ? RTLIL::State::S0 : RTLIL::State::S1); - new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); + RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1); + new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y); goto next_cell; } @@ -853,83 +853,83 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (new_a.size() == 0) { cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in("$eq", "$eqx") ? RTLIL::State::S1 : RTLIL::State::S0); - new_y.extend_u0(cell->parameters["\\Y_WIDTH"].as_int(), false); - replace_cell(assign_map, module, cell, "empty", "\\Y", new_y); + RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0); + new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); + replace_cell(assign_map, module, cell, "empty", ID(Y), new_y); goto next_cell; } if (new_a.size() < a.size() || new_b.size() < b.size()) { cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - cell->setPort("\\A", new_a); - cell->setPort("\\B", new_b); - cell->parameters["\\A_WIDTH"] = new_a.size(); - cell->parameters["\\B_WIDTH"] = new_b.size(); + cell->setPort(ID(A), new_a); + cell->setPort(ID(B), new_b); + cell->parameters[ID(A_WIDTH)] = new_a.size(); + cell->parameters[ID(B_WIDTH)] = new_b.size(); } } - if (cell->type.in("$eq", "$ne") && cell->parameters["\\Y_WIDTH"].as_int() == 1 && - cell->parameters["\\A_WIDTH"].as_int() == 1 && cell->parameters["\\B_WIDTH"].as_int() == 1) + if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 && + cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1) { - RTLIL::SigSpec a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); if (a.is_fully_const() && !b.is_fully_const()) { cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str()); - cell->setPort("\\A", b); - cell->setPort("\\B", a); + cell->setPort(ID(A), b); + cell->setPort(ID(B), a); std::swap(a, b); } if (b.is_fully_const()) { - if (b.as_bool() == (cell->type == "$eq")) { + if (b.as_bool() == (cell->type == ID($eq))) { RTLIL::SigSpec input = b; - ACTION_DO("\\Y", cell->getPort("\\A")); + ACTION_DO(ID(Y), cell->getPort(ID(A))); } else { cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->type = "$not"; - cell->parameters.erase("\\B_WIDTH"); - cell->parameters.erase("\\B_SIGNED"); - cell->unsetPort("\\B"); + cell->type = ID($not); + cell->parameters.erase(ID(B_WIDTH)); + cell->parameters.erase(ID(B_SIGNED)); + cell->unsetPort(ID(B)); did_something = true; } goto next_cell; } } - if (cell->type.in("$eq", "$ne") && - (assign_map(cell->getPort("\\A")).is_fully_zero() || assign_map(cell->getPort("\\B")).is_fully_zero())) + if (cell->type.in(ID($eq), ID($ne)) && + (assign_map(cell->getPort(ID(A))).is_fully_zero() || assign_map(cell->getPort(ID(B))).is_fully_zero())) { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), log_id(module), "$eq" ? "$logic_not" : "$reduce_bool"); - cell->type = cell->type == "$eq" ? "$logic_not" : "$reduce_bool"; - if (assign_map(cell->getPort("\\A")).is_fully_zero()) { - cell->setPort("\\A", cell->getPort("\\B")); - cell->setParam("\\A_SIGNED", cell->getParam("\\B_SIGNED")); - cell->setParam("\\A_WIDTH", cell->getParam("\\B_WIDTH")); + cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); + if (assign_map(cell->getPort(ID(A))).is_fully_zero()) { + cell->setPort(ID(A), cell->getPort(ID(B))); + cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED))); + cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH))); } - cell->unsetPort("\\B"); - cell->unsetParam("\\B_SIGNED"); - cell->unsetParam("\\B_WIDTH"); + cell->unsetPort(ID(B)); + cell->unsetParam(ID(B_SIGNED)); + cell->unsetParam(ID(B_WIDTH)); did_something = true; goto next_cell; } - if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx") && assign_map(cell->getPort("\\B")).is_fully_const()) + if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID(B))).is_fully_const()) { - bool sign_ext = cell->type == "$sshr" && cell->getParam("\\A_SIGNED").as_bool(); - int shift_bits = assign_map(cell->getPort("\\B")).as_int(cell->type.in("$shift", "$shiftx") && cell->getParam("\\B_SIGNED").as_bool()); + bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool(); + int shift_bits = assign_map(cell->getPort(ID(B))).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool()); - if (cell->type.in("$shl", "$sshl")) + if (cell->type.in(ID($shl), ID($sshl))) shift_bits *= -1; - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_y(cell->type == "$shiftx" ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam("\\Y_WIDTH").as_int()); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int()); if (GetSize(sig_a) < GetSize(sig_y)) - sig_a.extend_u0(GetSize(sig_y), cell->getParam("\\A_SIGNED").as_bool()); + sig_a.extend_u0(GetSize(sig_y), cell->getParam(ID(A_SIGNED)).as_bool()); for (int i = 0; i < GetSize(sig_y); i++) { int idx = i + shift_bits; @@ -942,9 +942,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str()); log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", - log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort("\\B"))), shift_bits, log_id(module), log_signal(sig_y)); + log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID(B)))), shift_bits, log_id(module), log_signal(sig_y)); - module->connect(cell->getPort("\\Y"), sig_y); + module->connect(cell->getPort(ID(Y)), sig_y); module->remove(cell); did_something = true; @@ -957,41 +957,41 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons bool identity_wrt_b = false; bool arith_inverse = false; - if (cell->type.in("$add", "$sub", "$or", "$xor")) + if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor))) { - RTLIL::SigSpec a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); - if (cell->type != "$sub" && a.is_fully_const() && a.as_bool() == false) + if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false) identity_wrt_b = true; if (b.is_fully_const() && b.as_bool() == false) identity_wrt_a = true; } - if (cell->type.in("$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx")) + if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) { - RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); if (b.is_fully_const() && b.as_bool() == false) identity_wrt_a = true; } - if (cell->type == "$mul") + if (cell->type == ID($mul)) { - RTLIL::SigSpec a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); - if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam("\\A_SIGNED").as_bool(), arith_inverse)) + if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse)) identity_wrt_b = true; else - if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam("\\B_SIGNED").as_bool(), arith_inverse)) + if (b.is_fully_const() && is_one_or_minus_one(b.as_const(), cell->getParam(ID(B_SIGNED)).as_bool(), arith_inverse)) identity_wrt_a = true; } - if (cell->type == "$div") + if (cell->type == ID($div)) { - RTLIL::SigSpec b = assign_map(cell->getPort("\\B")); + RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1) identity_wrt_a = true; @@ -1008,15 +1008,15 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); if (!identity_wrt_a) { - cell->setPort("\\A", cell->getPort("\\B")); - cell->parameters.at("\\A_WIDTH") = cell->parameters.at("\\B_WIDTH"); - cell->parameters.at("\\A_SIGNED") = cell->parameters.at("\\B_SIGNED"); + cell->setPort(ID(A), cell->getPort(ID(B))); + cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); + cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } - cell->type = arith_inverse ? "$neg" : "$pos"; - cell->unsetPort("\\B"); - cell->parameters.erase("\\B_WIDTH"); - cell->parameters.erase("\\B_SIGNED"); + cell->type = arith_inverse ? ID($neg) : ID($pos); + cell->unsetPort(ID(B)); + cell->parameters.erase(ID(B_WIDTH)); + cell->parameters.erase(ID(B_SIGNED)); cell->check(); did_something = true; @@ -1024,91 +1024,91 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (mux_bool && cell->type.in("$mux", "$_MUX_") && - cell->getPort("\\A") == State::S0 && cell->getPort("\\B") == State::S1) { + if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && + cell->getPort(ID(A)) == State::S0 && cell->getPort(ID(B)) == State::S1) { cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_bool", "\\Y", cell->getPort("\\S")); + replace_cell(assign_map, module, cell, "mux_bool", ID(Y), cell->getPort(ID(S))); goto next_cell; } - if (mux_bool && cell->type.in("$mux", "$_MUX_") && - cell->getPort("\\A") == State::S1 && cell->getPort("\\B") == State::S0) { + if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && + cell->getPort(ID(A)) == State::S1 && cell->getPort(ID(B)) == State::S0) { cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort("\\A", cell->getPort("\\S")); - cell->unsetPort("\\B"); - cell->unsetPort("\\S"); - if (cell->type == "$mux") { - Const width = cell->parameters["\\WIDTH"]; - cell->parameters["\\A_WIDTH"] = width; - cell->parameters["\\Y_WIDTH"] = width; - cell->parameters["\\A_SIGNED"] = 0; - cell->parameters.erase("\\WIDTH"); - cell->type = "$not"; + cell->setPort(ID(A), cell->getPort(ID(S))); + cell->unsetPort(ID(B)); + cell->unsetPort(ID(S)); + if (cell->type == ID($mux)) { + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); + cell->type = ID($not); } else - cell->type = "$_NOT_"; + cell->type = ID($_NOT_); did_something = true; goto next_cell; } - if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\A") == State::S0) { + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(A)) == State::S0) { cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort("\\A", cell->getPort("\\S")); - cell->unsetPort("\\S"); - if (cell->type == "$mux") { - Const width = cell->parameters["\\WIDTH"]; - cell->parameters["\\A_WIDTH"] = width; - cell->parameters["\\B_WIDTH"] = width; - cell->parameters["\\Y_WIDTH"] = width; - cell->parameters["\\A_SIGNED"] = 0; - cell->parameters["\\B_SIGNED"] = 0; - cell->parameters.erase("\\WIDTH"); - cell->type = "$and"; + cell->setPort(ID(A), cell->getPort(ID(S))); + cell->unsetPort(ID(S)); + if (cell->type == ID($mux)) { + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(B_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters[ID(B_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); + cell->type = ID($and); } else - cell->type = "$_AND_"; + cell->type = ID($_AND_); did_something = true; goto next_cell; } - if (consume_x && mux_bool && cell->type.in("$mux", "$_MUX_") && cell->getPort("\\B") == State::S1) { + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(B)) == State::S1) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort("\\B", cell->getPort("\\S")); - cell->unsetPort("\\S"); - if (cell->type == "$mux") { - Const width = cell->parameters["\\WIDTH"]; - cell->parameters["\\A_WIDTH"] = width; - cell->parameters["\\B_WIDTH"] = width; - cell->parameters["\\Y_WIDTH"] = width; - cell->parameters["\\A_SIGNED"] = 0; - cell->parameters["\\B_SIGNED"] = 0; - cell->parameters.erase("\\WIDTH"); - cell->type = "$or"; + cell->setPort(ID(B), cell->getPort(ID(S))); + cell->unsetPort(ID(S)); + if (cell->type == ID($mux)) { + Const width = cell->parameters[ID(WIDTH)]; + cell->parameters[ID(A_WIDTH)] = width; + cell->parameters[ID(B_WIDTH)] = width; + cell->parameters[ID(Y_WIDTH)] = width; + cell->parameters[ID(A_SIGNED)] = 0; + cell->parameters[ID(B_SIGNED)] = 0; + cell->parameters.erase(ID(WIDTH)); + cell->type = ID($or); } else - cell->type = "$_OR_"; + cell->type = ID($_OR_); did_something = true; goto next_cell; } - if (mux_undef && cell->type.in("$mux", "$pmux")) { + if (mux_undef && cell->type.in(ID($mux), ID($pmux))) { RTLIL::SigSpec new_a, new_b, new_s; - int width = cell->getPort("\\A").size(); - if ((cell->getPort("\\A").is_fully_undef() && cell->getPort("\\B").is_fully_undef()) || - cell->getPort("\\S").is_fully_undef()) { + int width = cell->getPort(ID(A)).size(); + if ((cell->getPort(ID(A)).is_fully_undef() && cell->getPort(ID(B)).is_fully_undef()) || + cell->getPort(ID(S)).is_fully_undef()) { cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_undef", "\\Y", cell->getPort("\\A")); + replace_cell(assign_map, module, cell, "mux_undef", ID(Y), cell->getPort(ID(A))); goto next_cell; } - for (int i = 0; i < cell->getPort("\\S").size(); i++) { - RTLIL::SigSpec old_b = cell->getPort("\\B").extract(i*width, width); - RTLIL::SigSpec old_s = cell->getPort("\\S").extract(i, 1); + for (int i = 0; i < cell->getPort(ID(S)).size(); i++) { + RTLIL::SigSpec old_b = cell->getPort(ID(B)).extract(i*width, width); + RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1); if (old_b.is_fully_undef() || old_s.is_fully_undef()) continue; new_b.append(old_b); new_s.append(old_s); } - new_a = cell->getPort("\\A"); + new_a = cell->getPort(ID(A)); if (new_a.is_fully_undef() && new_s.size() > 0) { new_a = new_b.extract((new_s.size()-1)*width, width); new_b = new_b.extract(0, (new_s.size()-1)*width); @@ -1116,27 +1116,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (new_s.size() == 0) { cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_empty", "\\Y", new_a); + replace_cell(assign_map, module, cell, "mux_empty", ID(Y), new_a); goto next_cell; } if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) { cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_sel01", "\\Y", new_s); + replace_cell(assign_map, module, cell, "mux_sel01", ID(Y), new_s); goto next_cell; } - if (cell->getPort("\\S").size() != new_s.size()) { + if (cell->getPort(ID(S)).size() != new_s.size()) { cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str()); log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", - GetSize(cell->getPort("\\S")) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort("\\A", new_a); - cell->setPort("\\B", new_b); - cell->setPort("\\S", new_s); + GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); + cell->setPort(ID(A), new_a); + cell->setPort(ID(B), new_b); + cell->setPort(ID(S), new_s); if (new_s.size() > 1) { - cell->type = "$pmux"; - cell->parameters["\\S_WIDTH"] = new_s.size(); + cell->type = ID($pmux); + cell->parameters[ID(S_WIDTH)] = new_s.size(); } else { - cell->type = "$mux"; - cell->parameters.erase("\\S_WIDTH"); + cell->type = ID($mux); + cell->parameters.erase(ID(S_WIDTH)); } did_something = true; } @@ -1144,30 +1144,30 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons #define FOLD_1ARG_CELL(_t) \ if (cell->type == "$" #_t) { \ - RTLIL::SigSpec a = cell->getPort("\\A"); \ + RTLIL::SigSpec a = cell->getPort(ID(A)); \ assign_map.apply(a); \ if (a.is_fully_const()) { \ RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \ RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), dummy_arg, \ - cell->parameters["\\A_SIGNED"].as_bool(), false, \ - cell->parameters["\\Y_WIDTH"].as_int())); \ + cell->parameters[ID(A_SIGNED)].as_bool(), false, \ + cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ - replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), "\\Y", y); \ + replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID(Y), y); \ goto next_cell; \ } \ } #define FOLD_2ARG_CELL(_t) \ if (cell->type == "$" #_t) { \ - RTLIL::SigSpec a = cell->getPort("\\A"); \ - RTLIL::SigSpec b = cell->getPort("\\B"); \ + RTLIL::SigSpec a = cell->getPort(ID(A)); \ + RTLIL::SigSpec b = cell->getPort(ID(B)); \ assign_map.apply(a), assign_map.apply(b); \ if (a.is_fully_const() && b.is_fully_const()) { \ RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \ - cell->parameters["\\A_SIGNED"].as_bool(), \ - cell->parameters["\\B_SIGNED"].as_bool(), \ - cell->parameters["\\Y_WIDTH"].as_int())); \ + cell->parameters[ID(A_SIGNED)].as_bool(), \ + cell->parameters[ID(B_SIGNED)].as_bool(), \ + cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ - replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), "\\Y", y); \ + replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID(Y), y); \ goto next_cell; \ } \ } @@ -1213,25 +1213,25 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons FOLD_1ARG_CELL(neg) // be very conservative with optimizing $mux cells as we do not want to break mux trees - if (cell->type == "$mux") { - RTLIL::SigSpec input = assign_map(cell->getPort("\\S")); - RTLIL::SigSpec inA = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec inB = assign_map(cell->getPort("\\B")); + if (cell->type == ID($mux)) { + RTLIL::SigSpec input = assign_map(cell->getPort(ID(S))); + RTLIL::SigSpec inA = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec inB = assign_map(cell->getPort(ID(B))); if (input.is_fully_const()) - ACTION_DO("\\Y", input.as_bool() ? cell->getPort("\\B") : cell->getPort("\\A")); + ACTION_DO(ID(Y), input.as_bool() ? cell->getPort(ID(B)) : cell->getPort(ID(A))); else if (inA == inB) - ACTION_DO("\\Y", cell->getPort("\\A")); + ACTION_DO(ID(Y), cell->getPort(ID(A))); } - if (!keepdc && cell->type == "$mul") + if (!keepdc && cell->type == ID($mul)) { - bool a_signed = cell->parameters["\\A_SIGNED"].as_bool(); - bool b_signed = cell->parameters["\\B_SIGNED"].as_bool(); + bool a_signed = cell->parameters[ID(A_SIGNED)].as_bool(); + bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); bool swapped_ab = false; - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); - RTLIL::SigSpec sig_y = assign_map(cell->getPort("\\Y")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID(Y))); if (sig_b.is_fully_const() && sig_b.size() <= 32) std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true; @@ -1266,9 +1266,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons a_val, cell->name.c_str(), module->name.c_str(), i); if (!swapped_ab) { - cell->setPort("\\A", cell->getPort("\\B")); - cell->parameters.at("\\A_WIDTH") = cell->parameters.at("\\B_WIDTH"); - cell->parameters.at("\\A_SIGNED") = cell->parameters.at("\\B_SIGNED"); + cell->setPort(ID(A), cell->getPort(ID(B))); + cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); + cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } std::vector new_b = RTLIL::SigSpec(i, 6); @@ -1276,10 +1276,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0) new_b.pop_back(); - cell->type = "$shl"; - cell->parameters["\\B_WIDTH"] = GetSize(new_b); - cell->parameters["\\B_SIGNED"] = false; - cell->setPort("\\B", new_b); + cell->type = ID($shl); + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); + cell->parameters[ID(B_SIGNED)] = false; + cell->setPort(ID(B), new_b); cell->check(); did_something = true; @@ -1288,11 +1288,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (!keepdc && cell->type.in("$div", "$mod")) + if (!keepdc && cell->type.in(ID($div), ID($mod))) { - bool b_signed = cell->parameters["\\B_SIGNED"].as_bool(); - SigSpec sig_b = assign_map(cell->getPort("\\B")); - SigSpec sig_y = assign_map(cell->getPort("\\Y")); + bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); + SigSpec sig_b = assign_map(cell->getPort(ID(B))); + SigSpec sig_y = assign_map(cell->getPort(ID(Y))); if (sig_b.is_fully_def() && sig_b.size() <= 32) { @@ -1315,7 +1315,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (int i = 1; i < (b_signed ? sig_b.size()-1 : sig_b.size()); i++) if (b_val == (1 << i)) { - if (cell->type == "$div") + if (cell->type == ID($div)) { cover("opt.opt_expr.div_shift"); @@ -1327,10 +1327,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons while (GetSize(new_b) > 1 && new_b.back() == RTLIL::State::S0) new_b.pop_back(); - cell->type = "$shr"; - cell->parameters["\\B_WIDTH"] = GetSize(new_b); - cell->parameters["\\B_SIGNED"] = false; - cell->setPort("\\B", new_b); + cell->type = ID($shr); + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); + cell->parameters[ID(B_SIGNED)] = false; + cell->setPort(ID(B), new_b); cell->check(); } else @@ -1345,9 +1345,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (b_signed) new_b.push_back(State::S0); - cell->type = "$and"; - cell->parameters["\\B_WIDTH"] = GetSize(new_b); - cell->setPort("\\B", new_b); + cell->type = ID($and); + cell->parameters[ID(B_WIDTH)] = GetSize(new_b); + cell->setPort(ID(B), new_b); cell->check(); } @@ -1359,7 +1359,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons // remove redundant pairs of bits in ==, ===, !=, and !== // replace cell with const driver if inputs can't be equal - if (do_fine && cell->type.in("$eq", "$ne", "$eqx", "$nex")) + if (do_fine && cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex))) { pool> redundant_cache; mfp contradiction_cache; @@ -1367,14 +1367,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons contradiction_cache.promote(State::S0); contradiction_cache.promote(State::S1); - int a_width = cell->getParam("\\A_WIDTH").as_int(); - int b_width = cell->getParam("\\B_WIDTH").as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); - bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width); - SigSpec sig_a = cell->getPort("\\A"); - SigSpec sig_b = cell->getPort("\\B"); + SigSpec sig_a = cell->getPort(ID(A)); + SigSpec sig_b = cell->getPort(ID(B)); int redundant_bits = 0; @@ -1404,8 +1404,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1)) { - SigSpec y_sig = cell->getPort("\\Y"); - Const y_value(cell->type.in("$eq", "$eqx") ? 0 : 1, GetSize(y_sig)); + SigSpec y_sig = cell->getPort(ID(Y)); + Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig)); log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n", log_id(cell), log_id(module), log_signal(y_value)); @@ -1422,10 +1422,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", redundant_bits, log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort("\\A", sig_a); - cell->setPort("\\B", sig_b); - cell->setParam("\\A_WIDTH", GetSize(sig_a)); - cell->setParam("\\B_WIDTH", GetSize(sig_b)); + cell->setPort(ID(A), sig_a); + cell->setPort(ID(B), sig_b); + cell->setParam(ID(A_WIDTH), GetSize(sig_a)); + cell->setParam(ID(B_WIDTH), GetSize(sig_b)); did_something = true; goto next_cell; @@ -1433,57 +1433,57 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } // simplify comparisons - if (do_fine && cell->type.in("$lt", "$ge", "$gt", "$le")) + if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le))) { IdString cmp_type = cell->type; - SigSpec var_sig = cell->getPort("\\A"); - SigSpec const_sig = cell->getPort("\\B"); - int var_width = cell->parameters["\\A_WIDTH"].as_int(); - int const_width = cell->parameters["\\B_WIDTH"].as_int(); - bool is_signed = cell->getParam("\\A_SIGNED").as_bool(); + SigSpec var_sig = cell->getPort(ID(A)); + SigSpec const_sig = cell->getPort(ID(B)); + int var_width = cell->parameters[ID(A_WIDTH)].as_int(); + int const_width = cell->parameters[ID(B_WIDTH)].as_int(); + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); if (!const_sig.is_fully_const()) { std::swap(var_sig, const_sig); std::swap(var_width, const_width); - if (cmp_type == "$gt") - cmp_type = "$lt"; - else if (cmp_type == "$lt") - cmp_type = "$gt"; - else if (cmp_type == "$ge") - cmp_type = "$le"; - else if (cmp_type == "$le") - cmp_type = "$ge"; + if (cmp_type == ID($gt)) + cmp_type = ID($lt); + else if (cmp_type == ID($lt)) + cmp_type = ID($gt); + else if (cmp_type == ID($ge)) + cmp_type = ID($le); + else if (cmp_type == ID($le)) + cmp_type = ID($ge); } if (const_sig.is_fully_def() && const_sig.is_fully_const()) { std::string condition, replacement; - SigSpec replace_sig(State::S0, GetSize(cell->getPort("\\Y"))); + SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID(Y)))); bool replace = false; bool remove = false; if (!is_signed) { /* unsigned */ - if (const_sig.is_fully_zero() && cmp_type == "$lt") { + if (const_sig.is_fully_zero() && cmp_type == ID($lt)) { condition = "unsigned X<0"; replacement = "constant 0"; replace_sig[0] = State::S0; replace = true; } - if (const_sig.is_fully_zero() && cmp_type == "$ge") { + if (const_sig.is_fully_zero() && cmp_type == ID($ge)) { condition = "unsigned X>=0"; replacement = "constant 1"; replace_sig[0] = State::S1; replace = true; } - if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$gt") { + if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($gt)) { condition = "unsigned X>~0"; replacement = "constant 0"; replace_sig[0] = State::S0; replace = true; } - if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == "$le") { + if (const_width == var_width && const_sig.is_fully_ones() && cmp_type == ID($le)) { condition = "unsigned X<=~0"; replacement = "constant 1"; replace_sig[0] = State::S1; @@ -1498,18 +1498,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons var_high_sig[i - const_bit_hot] = var_sig[i]; } - if (cmp_type == "$lt") + if (cmp_type == ID($lt)) { condition = stringf("unsigned X<%s", log_signal(const_sig)); replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot); - module->addLogicNot(NEW_ID, var_high_sig, cell->getPort("\\Y")); + module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID(Y))); remove = true; } - if (cmp_type == "$ge") + if (cmp_type == ID($ge)) { condition = stringf("unsigned X>=%s", log_signal(const_sig)); replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot); - module->addReduceOr(NEW_ID, var_high_sig, cell->getPort("\\Y")); + module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID(Y))); remove = true; } } @@ -1518,19 +1518,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if(const_bit_set >= var_width) { string cmp_name; - if (cmp_type == "$lt" || cmp_type == "$le") + if (cmp_type == ID($lt) || cmp_type == ID($le)) { - if (cmp_type == "$lt") cmp_name = "<"; - if (cmp_type == "$le") cmp_name = "<="; + if (cmp_type == ID($lt)) cmp_name = "<"; + if (cmp_type == ID($le)) cmp_name = "<="; condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); replacement = "constant 1"; replace_sig[0] = State::S1; replace = true; } - if (cmp_type == "$gt" || cmp_type == "$ge") + if (cmp_type == ID($gt) || cmp_type == ID($ge)) { - if (cmp_type == "$gt") cmp_name = ">"; - if (cmp_type == "$ge") cmp_name = ">="; + if (cmp_type == ID($gt)) cmp_name = ">"; + if (cmp_type == ID($ge)) cmp_name = ">="; condition = stringf("unsigned X[%d:0]%s%s", var_width - 1, cmp_name.c_str(), log_signal(const_sig)); replacement = "constant 0"; replace_sig[0] = State::S0; @@ -1540,18 +1540,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } else { /* signed */ - if (const_sig.is_fully_zero() && cmp_type == "$lt") + if (const_sig.is_fully_zero() && cmp_type == ID($lt)) { condition = "signed X<0"; replacement = stringf("X[%d]", var_width - 1); replace_sig[0] = var_sig[var_width - 1]; replace = true; } - if (const_sig.is_fully_zero() && cmp_type == "$ge") + if (const_sig.is_fully_zero() && cmp_type == ID($ge)) { condition = "signed X>=0"; replacement = stringf("X[%d]", var_width - 1); - module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort("\\Y")); + module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID(Y))); remove = true; } } @@ -1561,7 +1561,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n", log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); if (replace) - module->connect(cell->getPort("\\Y"), replace_sig); + module->connect(cell->getPort(ID(Y)), replace_sig); module->remove(cell); did_something = true; goto next_cell; diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 4c199ba72..e9d72044b 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -40,9 +40,9 @@ struct OptLutWorker bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { - SigSpec lut_input = sigmap(lut->getPort("\\A")); - int lut_width = lut->getParam("\\WIDTH").as_int(); - Const lut_table = lut->getParam("\\LUT"); + SigSpec lut_input = sigmap(lut->getPort(ID(A))); + int lut_width = lut->getParam(ID(WIDTH)).as_int(); + Const lut_table = lut->getParam(ID(LUT)); int lut_index = 0; for (int i = 0; i < lut_width; i++) @@ -99,16 +99,16 @@ struct OptLutWorker log("Discovering LUTs.\n"); for (auto cell : module->selected_cells()) { - if (cell->type == "$lut") + if (cell->type == ID($lut)) { if (cell->has_keep_attr()) continue; - SigBit lut_output = cell->getPort("\\Y"); - if (lut_output.wire->get_bool_attribute("\\keep")) + SigBit lut_output = cell->getPort(ID(Y)); + if (lut_output.wire->get_bool_attribute(ID(keep))) continue; - int lut_width = cell->getParam("\\WIDTH").as_int(); - SigSpec lut_input = cell->getPort("\\A"); + int lut_width = cell->getParam(ID(WIDTH)).as_int(); + SigSpec lut_input = cell->getPort(ID(A)); int lut_arity = 0; log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); @@ -205,7 +205,7 @@ struct OptLutWorker } auto lut = worklist.pop(); - SigSpec lut_input = sigmap(lut->getPort("\\A")); + SigSpec lut_input = sigmap(lut->getPort(ID(A))); pool &lut_dlogic_inputs = luts_dlogic_inputs[lut]; vector lut_inputs; @@ -267,7 +267,7 @@ struct OptLutWorker log_debug(" Not eliminating cell (connected to dedicated logic).\n"); else { - SigSpec lut_output = lut->getPort("\\Y"); + SigSpec lut_output = lut->getPort(ID(Y)); for (auto &port : index.query_ports(lut_output)) { if (port.cell != lut && luts.count(port.cell)) @@ -303,13 +303,13 @@ struct OptLutWorker } auto lutA = worklist.pop(); - SigSpec lutA_input = sigmap(lutA->getPort("\\A")); - SigSpec lutA_output = sigmap(lutA->getPort("\\Y")[0]); - int lutA_width = lutA->getParam("\\WIDTH").as_int(); + SigSpec lutA_input = sigmap(lutA->getPort(ID(A))); + SigSpec lutA_output = sigmap(lutA->getPort(ID(Y))[0]); + int lutA_width = lutA->getParam(ID(WIDTH)).as_int(); int lutA_arity = luts_arity[lutA]; pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; - auto lutA_output_ports = index.query_ports(lutA->getPort("\\Y")); + auto lutA_output_ports = index.query_ports(lutA->getPort(ID(Y))); if (lutA_output_ports.size() != 2) continue; @@ -321,15 +321,15 @@ struct OptLutWorker if (luts.count(port.cell)) { auto lutB = port.cell; - SigSpec lutB_input = sigmap(lutB->getPort("\\A")); - SigSpec lutB_output = sigmap(lutB->getPort("\\Y")[0]); - int lutB_width = lutB->getParam("\\WIDTH").as_int(); + SigSpec lutB_input = sigmap(lutB->getPort(ID(A))); + SigSpec lutB_output = sigmap(lutB->getPort(ID(Y))[0]); + int lutB_width = lutB->getParam(ID(WIDTH)).as_int(); int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); - if (index.query_is_output(lutA->getPort("\\Y"))) + if (index.query_is_output(lutA->getPort(ID(Y)))) { log_debug(" Not combining LUTs (cascade connection feeds module output).\n"); continue; @@ -372,7 +372,7 @@ struct OptLutWorker log_debug(" Not combining LUTs into cell A (combined LUT wider than cell A).\n"); else if (lutB_dlogic_inputs.size() > 0) log_debug(" Not combining LUTs into cell A (cell B is connected to dedicated logic).\n"); - else if (lutB->get_bool_attribute("\\lut_keep")) + else if (lutB->get_bool_attribute(ID(lut_keep))) log_debug(" Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n"); else combine_mask |= COMBINE_A; @@ -380,7 +380,7 @@ struct OptLutWorker log_debug(" Not combining LUTs into cell B (combined LUT wider than cell B).\n"); else if (lutA_dlogic_inputs.size() > 0) log_debug(" Not combining LUTs into cell B (cell A is connected to dedicated logic).\n"); - else if (lutA->get_bool_attribute("\\lut_keep")) + else if (lutA->get_bool_attribute(ID(lut_keep))) log_debug(" Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n"); else combine_mask |= COMBINE_B; @@ -440,8 +440,8 @@ struct OptLutWorker lutR_unique.insert(bit); } - int lutM_width = lutM->getParam("\\WIDTH").as_int(); - SigSpec lutM_input = sigmap(lutM->getPort("\\A")); + int lutM_width = lutM->getParam(ID(WIDTH)).as_int(); + SigSpec lutM_input = sigmap(lutM->getPort(ID(A))); std::vector lutM_new_inputs; for (int i = 0; i < lutM_width; i++) { @@ -482,13 +482,13 @@ struct OptLutWorker lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs); } - log_debug(" Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str()); - log_debug(" Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str()); + log_debug(" Cell A truth table: %s.\n", lutA->getParam(ID(LUT)).as_string().c_str()); + log_debug(" Cell B truth table: %s.\n", lutB->getParam(ID(LUT)).as_string().c_str()); log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); - lutM->setParam("\\LUT", lutM_new_table); - lutM->setPort("\\A", lutM_new_inputs); - lutM->setPort("\\Y", lutB_output); + lutM->setParam(ID(LUT), lutM_new_table); + lutM->setPort(ID(A), lutM_new_inputs); + lutM->setPort(ID(Y), lutB_output); luts_arity[lutM] = lutM_arity; luts.erase(lutR); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index cac7c0a6f..aa1a5c75c 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -47,8 +47,8 @@ struct OptMergeWorker static void sort_pmux_conn(dict &conn) { - SigSpec sig_s = conn.at("\\S"); - SigSpec sig_b = conn.at("\\B"); + SigSpec sig_s = conn.at(ID(S)); + SigSpec sig_b = conn.at(ID(B)); int s_width = GetSize(sig_s); int width = GetSize(sig_b) / s_width; @@ -59,12 +59,12 @@ struct OptMergeWorker std::sort(sb_pairs.begin(), sb_pairs.end()); - conn["\\S"] = SigSpec(); - conn["\\B"] = SigSpec(); + conn[ID(S)] = SigSpec(); + conn[ID(B)] = SigSpec(); for (auto &it : sb_pairs) { - conn["\\S"].append(it.first); - conn["\\B"].append(it.second); + conn[ID(S)].append(it.first); + conn[ID(B)].append(it.second); } } @@ -94,32 +94,32 @@ struct OptMergeWorker const dict *conn = &cell->connections(); dict alt_conn; - if (cell->type.in("$and", "$or", "$xor", "$xnor", "$add", "$mul", - "$logic_and", "$logic_or", "$_AND_", "$_OR_", "$_XOR_")) { + if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul), + ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) { alt_conn = *conn; - if (assign_map(alt_conn.at("\\A")) < assign_map(alt_conn.at("\\B"))) { - alt_conn["\\A"] = conn->at("\\B"); - alt_conn["\\B"] = conn->at("\\A"); + if (assign_map(alt_conn.at(ID(A))) < assign_map(alt_conn.at(ID(B)))) { + alt_conn[ID(A)] = conn->at(ID(B)); + alt_conn[ID(B)] = conn->at(ID(A)); } conn = &alt_conn; } else - if (cell->type.in("$reduce_xor", "$reduce_xnor")) { + if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) { alt_conn = *conn; - assign_map.apply(alt_conn.at("\\A")); - alt_conn.at("\\A").sort(); + assign_map.apply(alt_conn.at(ID(A))); + alt_conn.at(ID(A)).sort(); conn = &alt_conn; } else - if (cell->type.in("$reduce_and", "$reduce_or", "$reduce_bool")) { + if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) { alt_conn = *conn; - assign_map.apply(alt_conn.at("\\A")); - alt_conn.at("\\A").sort_and_unify(); + assign_map.apply(alt_conn.at(ID(A))); + alt_conn.at(ID(A)).sort_and_unify(); conn = &alt_conn; } else - if (cell->type == "$pmux") { + if (cell->type == ID($pmux)) { alt_conn = *conn; - assign_map.apply(alt_conn.at("\\A")); - assign_map.apply(alt_conn.at("\\B")); - assign_map.apply(alt_conn.at("\\S")); + assign_map.apply(alt_conn.at(ID(A))); + assign_map.apply(alt_conn.at(ID(B))); + assign_map.apply(alt_conn.at(ID(S))); sort_pmux_conn(alt_conn); conn = &alt_conn; } @@ -189,28 +189,28 @@ struct OptMergeWorker assign_map.apply(it.second); } - if (cell1->type == "$and" || cell1->type == "$or" || cell1->type == "$xor" || cell1->type == "$xnor" || cell1->type == "$add" || cell1->type == "$mul" || - cell1->type == "$logic_and" || cell1->type == "$logic_or" || cell1->type == "$_AND_" || cell1->type == "$_OR_" || cell1->type == "$_XOR_") { - if (conn1.at("\\A") < conn1.at("\\B")) { - RTLIL::SigSpec tmp = conn1["\\A"]; - conn1["\\A"] = conn1["\\B"]; - conn1["\\B"] = tmp; + if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || + cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) { + if (conn1.at(ID(A)) < conn1.at(ID(B))) { + RTLIL::SigSpec tmp = conn1[ID(A)]; + conn1[ID(A)] = conn1[ID(B)]; + conn1[ID(B)] = tmp; } - if (conn2.at("\\A") < conn2.at("\\B")) { - RTLIL::SigSpec tmp = conn2["\\A"]; - conn2["\\A"] = conn2["\\B"]; - conn2["\\B"] = tmp; + if (conn2.at(ID(A)) < conn2.at(ID(B))) { + RTLIL::SigSpec tmp = conn2[ID(A)]; + conn2[ID(A)] = conn2[ID(B)]; + conn2[ID(B)] = tmp; } } else - if (cell1->type == "$reduce_xor" || cell1->type == "$reduce_xnor") { - conn1["\\A"].sort(); - conn2["\\A"].sort(); + if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) { + conn1[ID(A)].sort(); + conn2[ID(A)].sort(); } else - if (cell1->type == "$reduce_and" || cell1->type == "$reduce_or" || cell1->type == "$reduce_bool") { - conn1["\\A"].sort_and_unify(); - conn2["\\A"].sort_and_unify(); + if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) { + conn1[ID(A)].sort_and_unify(); + conn2[ID(A)].sort_and_unify(); } else - if (cell1->type == "$pmux") { + if (cell1->type == ID($pmux)) { sort_pmux_conn(conn1); sort_pmux_conn(conn2); } @@ -222,9 +222,9 @@ struct OptMergeWorker return true; } - if (cell1->type.begins_with("$") && conn1.count("\\Q") != 0) { - std::vector q1 = dff_init_map(cell1->getPort("\\Q")).to_sigbit_vector(); - std::vector q2 = dff_init_map(cell2->getPort("\\Q")).to_sigbit_vector(); + if (cell1->type.begins_with("$") && conn1.count(ID(Q)) != 0) { + std::vector q1 = dff_init_map(cell1->getPort(ID(Q))).to_sigbit_vector(); + std::vector q2 = dff_init_map(cell2->getPort(ID(Q))).to_sigbit_vector(); for (size_t i = 0; i < q1.size(); i++) if ((q1.at(i).wire == NULL || q2.at(i).wire == NULL) && q1.at(i) != q2.at(i)) { lt = q1.at(i) < q2.at(i); @@ -271,24 +271,24 @@ struct OptMergeWorker ct.setup_stdcells_mem(); if (mode_nomux) { - ct.cell_types.erase("$mux"); - ct.cell_types.erase("$pmux"); + ct.cell_types.erase(ID($mux)); + ct.cell_types.erase(ID($pmux)); } - ct.cell_types.erase("$tribuf"); - ct.cell_types.erase("$_TBUF_"); - ct.cell_types.erase("$anyseq"); - ct.cell_types.erase("$anyconst"); - ct.cell_types.erase("$allseq"); - ct.cell_types.erase("$allconst"); + ct.cell_types.erase(ID($tribuf)); + ct.cell_types.erase(ID($_TBUF_)); + ct.cell_types.erase(ID($anyseq)); + ct.cell_types.erase(ID($anyconst)); + ct.cell_types.erase(ID($allseq)); + ct.cell_types.erase(ID($allconst)); log("Finding identical cells in module `%s'.\n", module->name.c_str()); assign_map.set(module); dff_init_map.set(module); for (auto &it : module->wires_) - if (it.second->attributes.count("\\init") != 0) { - Const initval = it.second->attributes.at("\\init"); + if (it.second->attributes.count(ID(init)) != 0) { + Const initval = it.second->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(it.second); i++) if (initval[i] == State::S0 || initval[i] == State::S1) dff_init_map.add(SigBit(it.second, i), initval[i]); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 4b96fe524..61f194569 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -84,12 +84,12 @@ struct OptMuxtreeWorker // .const_deactivated for (auto cell : module->cells()) { - if (cell->type.in("$mux", "$pmux")) + if (cell->type.in(ID($mux), ID($pmux))) { - RTLIL::SigSpec sig_a = cell->getPort("\\A"); - RTLIL::SigSpec sig_b = cell->getPort("\\B"); - RTLIL::SigSpec sig_s = cell->getPort("\\S"); - RTLIL::SigSpec sig_y = cell->getPort("\\Y"); + RTLIL::SigSpec sig_a = cell->getPort(ID(A)); + RTLIL::SigSpec sig_b = cell->getPort(ID(B)); + RTLIL::SigSpec sig_s = cell->getPort(ID(S)); + RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); muxinfo_t muxinfo; muxinfo.cell = cell; @@ -137,7 +137,7 @@ struct OptMuxtreeWorker } } for (auto wire : module->wires()) { - if (wire->port_output || wire->get_bool_attribute("\\keep")) + if (wire->port_output || wire->get_bool_attribute(ID(keep))) for (int idx : sig2bits(RTLIL::SigSpec(wire))) bit2info[idx].seen_non_mux = true; } @@ -227,10 +227,10 @@ struct OptMuxtreeWorker continue; } - RTLIL::SigSpec sig_a = mi.cell->getPort("\\A"); - RTLIL::SigSpec sig_b = mi.cell->getPort("\\B"); - RTLIL::SigSpec sig_s = mi.cell->getPort("\\S"); - RTLIL::SigSpec sig_y = mi.cell->getPort("\\Y"); + RTLIL::SigSpec sig_a = mi.cell->getPort(ID(A)); + RTLIL::SigSpec sig_b = mi.cell->getPort(ID(B)); + RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S)); + RTLIL::SigSpec sig_y = mi.cell->getPort(ID(Y)); RTLIL::SigSpec sig_ports = sig_b; sig_ports.append(sig_a); @@ -255,14 +255,14 @@ struct OptMuxtreeWorker } } - mi.cell->setPort("\\A", new_sig_a); - mi.cell->setPort("\\B", new_sig_b); - mi.cell->setPort("\\S", new_sig_s); + mi.cell->setPort(ID(A), new_sig_a); + mi.cell->setPort(ID(B), new_sig_b); + mi.cell->setPort(ID(S), new_sig_s); if (GetSize(new_sig_s) == 1) { - mi.cell->type = "$mux"; - mi.cell->parameters.erase("\\S_WIDTH"); + mi.cell->type = ID($mux); + mi.cell->parameters.erase(ID(S_WIDTH)); } else { - mi.cell->parameters["\\S_WIDTH"] = RTLIL::Const(GetSize(new_sig_s)); + mi.cell->parameters[ID(S_WIDTH)] = RTLIL::Const(GetSize(new_sig_s)); } } } @@ -364,9 +364,9 @@ struct OptMuxtreeWorker int width = 0; idict ctrl_bits; - if (portname == "\\B") - width = GetSize(muxinfo.cell->getPort("\\A")); - for (int bit : sig2bits(muxinfo.cell->getPort("\\S"), false)) + if (portname == ID(B)) + width = GetSize(muxinfo.cell->getPort(ID(A))); + for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false)) ctrl_bits(bit); int port_idx = 0, port_off = 0; @@ -414,8 +414,8 @@ struct OptMuxtreeWorker // set input ports to constants if we find known active or inactive signals if (do_replace_known) { - replace_known(knowledge, muxinfo, "\\A"); - replace_known(knowledge, muxinfo, "\\B"); + replace_known(knowledge, muxinfo, ID(A)); + replace_known(knowledge, muxinfo, ID(B)); } // if there is a constant activated port we just use it diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index d99f1ca6a..332e0443e 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -43,13 +43,13 @@ struct OptReduceWorker return; cells.erase(cell); - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); pool new_sig_a_bits; for (auto &bit : sig_a.to_sigbit_set()) { if (bit == RTLIL::State::S0) { - if (cell->type == "$reduce_and") { + if (cell->type == ID($reduce_and)) { new_sig_a_bits.clear(); new_sig_a_bits.insert(RTLIL::State::S0); break; @@ -57,7 +57,7 @@ struct OptReduceWorker continue; } if (bit == RTLIL::State::S1) { - if (cell->type == "$reduce_or") { + if (cell->type == ID($reduce_or)) { new_sig_a_bits.clear(); new_sig_a_bits.insert(RTLIL::State::S1); break; @@ -73,8 +73,8 @@ struct OptReduceWorker for (auto child_cell : drivers.find(bit)) { if (child_cell->type == cell->type) { opt_reduce(cells, drivers, child_cell); - if (child_cell->getPort("\\Y")[0] == bit) { - pool child_sig_a_bits = assign_map(child_cell->getPort("\\A")).to_sigbit_pool(); + if (child_cell->getPort(ID(Y))[0] == bit) { + pool child_sig_a_bits = assign_map(child_cell->getPort(ID(A))).to_sigbit_pool(); new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end()); } else new_sig_a_bits.insert(RTLIL::State::S0); @@ -87,22 +87,22 @@ struct OptReduceWorker RTLIL::SigSpec new_sig_a(new_sig_a_bits); - if (new_sig_a != sig_a || sig_a.size() != cell->getPort("\\A").size()) { + if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID(A)).size()) { log(" New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a)); did_something = true; total_count++; } - cell->setPort("\\A", new_sig_a); - cell->parameters["\\A_WIDTH"] = RTLIL::Const(new_sig_a.size()); + cell->setPort(ID(A), new_sig_a); + cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size()); return; } void opt_mux(RTLIL::Cell *cell) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); - RTLIL::SigSpec sig_s = assign_map(cell->getPort("\\S")); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S))); RTLIL::SigSpec new_sig_b, new_sig_s; pool handled_sig; @@ -123,15 +123,15 @@ struct OptReduceWorker if (this_s.size() > 1) { - RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, "$reduce_or"); - reduce_or_cell->setPort("\\A", this_s); - reduce_or_cell->parameters["\\A_SIGNED"] = RTLIL::Const(0); - reduce_or_cell->parameters["\\A_WIDTH"] = RTLIL::Const(this_s.size()); - reduce_or_cell->parameters["\\Y_WIDTH"] = RTLIL::Const(1); + RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or)); + reduce_or_cell->setPort(ID(A), this_s); + reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0); + reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size()); + reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1); RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID); this_s = RTLIL::SigSpec(reduce_or_wire); - reduce_or_cell->setPort("\\Y", this_s); + reduce_or_cell->setPort(ID(Y), this_s); } new_sig_b.append(this_b); @@ -147,28 +147,28 @@ struct OptReduceWorker if (new_sig_s.size() == 0) { - module->connect(RTLIL::SigSig(cell->getPort("\\Y"), cell->getPort("\\A"))); - assign_map.add(cell->getPort("\\Y"), cell->getPort("\\A")); + module->connect(RTLIL::SigSig(cell->getPort(ID(Y)), cell->getPort(ID(A)))); + assign_map.add(cell->getPort(ID(Y)), cell->getPort(ID(A))); module->remove(cell); } else { - cell->setPort("\\B", new_sig_b); - cell->setPort("\\S", new_sig_s); + cell->setPort(ID(B), new_sig_b); + cell->setPort(ID(S), new_sig_s); if (new_sig_s.size() > 1) { - cell->parameters["\\S_WIDTH"] = RTLIL::Const(new_sig_s.size()); + cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size()); } else { - cell->type = "$mux"; - cell->parameters.erase("\\S_WIDTH"); + cell->type = ID($mux); + cell->parameters.erase(ID(S_WIDTH)); } } } void opt_mux_bits(RTLIL::Cell *cell) { - std::vector sig_a = assign_map(cell->getPort("\\A")).to_sigbit_vector(); - std::vector sig_b = assign_map(cell->getPort("\\B")).to_sigbit_vector(); - std::vector sig_y = assign_map(cell->getPort("\\Y")).to_sigbit_vector(); + std::vector sig_a = assign_map(cell->getPort(ID(A))).to_sigbit_vector(); + std::vector sig_b = assign_map(cell->getPort(ID(B))).to_sigbit_vector(); + std::vector sig_y = assign_map(cell->getPort(ID(Y))).to_sigbit_vector(); std::vector new_sig_y; RTLIL::SigSig old_sig_conn; @@ -209,29 +209,29 @@ struct OptReduceWorker if (new_sig_y.size() != sig_y.size()) { log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str()); - log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")), - log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y"))); + log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))), + log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y)))); - cell->setPort("\\A", RTLIL::SigSpec()); + cell->setPort(ID(A), RTLIL::SigSpec()); for (auto &in_tuple : consolidated_in_tuples) { - RTLIL::SigSpec new_a = cell->getPort("\\A"); + RTLIL::SigSpec new_a = cell->getPort(ID(A)); new_a.append(in_tuple.at(0)); - cell->setPort("\\A", new_a); + cell->setPort(ID(A), new_a); } - cell->setPort("\\B", RTLIL::SigSpec()); - for (int i = 1; i <= cell->getPort("\\S").size(); i++) + cell->setPort(ID(B), RTLIL::SigSpec()); + for (int i = 1; i <= cell->getPort(ID(S)).size(); i++) for (auto &in_tuple : consolidated_in_tuples) { - RTLIL::SigSpec new_b = cell->getPort("\\B"); + RTLIL::SigSpec new_b = cell->getPort(ID(B)); new_b.append(in_tuple.at(i)); - cell->setPort("\\B", new_b); + cell->setPort(ID(B), new_b); } - cell->parameters["\\WIDTH"] = RTLIL::Const(new_sig_y.size()); - cell->setPort("\\Y", new_sig_y); + cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size()); + cell->setPort(ID(Y), new_sig_y); - log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort("\\A")), - log_signal(cell->getPort("\\B")), log_signal(cell->getPort("\\Y"))); + log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))), + log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y)))); log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second)); module->connect(old_sig_conn); @@ -253,15 +253,15 @@ struct OptReduceWorker SigPool mem_wren_sigs; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (cell->type == "$mem") - mem_wren_sigs.add(assign_map(cell->getPort("\\WR_EN"))); - if (cell->type == "$memwr") - mem_wren_sigs.add(assign_map(cell->getPort("\\EN"))); + if (cell->type == ID($mem)) + mem_wren_sigs.add(assign_map(cell->getPort(ID(WR_EN)))); + if (cell->type == ID($memwr)) + mem_wren_sigs.add(assign_map(cell->getPort(ID(EN)))); } for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (cell->type == "$dff" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Q")))) - mem_wren_sigs.add(assign_map(cell->getPort("\\D"))); + if (cell->type == ID($dff) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Q))))) + mem_wren_sigs.add(assign_map(cell->getPort(ID(D)))); } bool keep_expanding_mem_wren_sigs = true; @@ -269,12 +269,12 @@ struct OptReduceWorker keep_expanding_mem_wren_sigs = false; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (cell->type == "$mux" && mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y")))) { - if (!mem_wren_sigs.check_all(assign_map(cell->getPort("\\A"))) || - !mem_wren_sigs.check_all(assign_map(cell->getPort("\\B")))) + if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) { + if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(A)))) || + !mem_wren_sigs.check_all(assign_map(cell->getPort(ID(B))))) keep_expanding_mem_wren_sigs = true; - mem_wren_sigs.add(assign_map(cell->getPort("\\A"))); - mem_wren_sigs.add(assign_map(cell->getPort("\\B"))); + mem_wren_sigs.add(assign_map(cell->getPort(ID(A)))); + mem_wren_sigs.add(assign_map(cell->getPort(ID(B)))); } } } @@ -286,7 +286,7 @@ struct OptReduceWorker // merge trees of reduce_* cells to one single cell and unify input vectors // (only handle reduce_and and reduce_or for various reasons) - const char *type_list[] = { "$reduce_or", "$reduce_and" }; + const IdString type_list[] = { ID($reduce_or), ID($reduce_and) }; for (auto type : type_list) { SigSet drivers; @@ -296,7 +296,7 @@ struct OptReduceWorker RTLIL::Cell *cell = cell_it.second; if (cell->type != type || !design->selected(module, cell)) continue; - drivers.insert(assign_map(cell->getPort("\\Y")), cell); + drivers.insert(assign_map(cell->getPort(ID(Y))), cell); cells.insert(cell); } @@ -311,14 +311,14 @@ struct OptReduceWorker std::vector cells; for (auto &it : module->cells_) - if ((it.second->type == "$mux" || it.second->type == "$pmux") && design->selected(module, it.second)) + if ((it.second->type == ID($mux) || it.second->type == ID($pmux)) && design->selected(module, it.second)) cells.push_back(it.second); for (auto cell : cells) { // this optimization is to aggressive for most coarse-grain applications. // but we always want it for multiplexers driving write enable ports. - if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort("\\Y")))) + if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) opt_mux_bits(cell); opt_mux(cell); diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 8d42a37c3..4ba61e512 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -41,7 +41,7 @@ void remove_init_attr(SigSpec sig) for (auto bit : assign_map(sig)) if (init_attributes.count(bit)) for (auto wbit : init_attributes.at(bit)) - wbit.wire->attributes.at("\\init")[wbit.offset] = State::Sx; + wbit.wire->attributes.at(ID(init))[wbit.offset] = State::Sx; } bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) @@ -49,17 +49,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) SigSpec sig_set, sig_clr; State pol_set, pol_clr; - if (cell->hasPort("\\S")) - sig_set = cell->getPort("\\S"); + if (cell->hasPort(ID(S))) + sig_set = cell->getPort(ID(S)); - if (cell->hasPort("\\R")) - sig_clr = cell->getPort("\\R"); + if (cell->hasPort(ID(R))) + sig_clr = cell->getPort(ID(R)); - if (cell->hasPort("\\SET")) - sig_set = cell->getPort("\\SET"); + if (cell->hasPort(ID(SET))) + sig_set = cell->getPort(ID(SET)); - if (cell->hasPort("\\CLR")) - sig_clr = cell->getPort("\\CLR"); + if (cell->hasPort(ID(CLR))) + sig_clr = cell->getPort(ID(CLR)); log_assert(GetSize(sig_set) == GetSize(sig_clr)); @@ -71,17 +71,17 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) pol_set = cell->type[12] == 'P' ? State::S1 : State::S0; pol_clr = cell->type[13] == 'P' ? State::S1 : State::S0; } else - if (cell->type.in("$dffsr", "$dlatchsr")) { - pol_set = cell->parameters["\\SET_POLARITY"].as_bool() ? State::S1 : State::S0; - pol_clr = cell->parameters["\\CLR_POLARITY"].as_bool() ? State::S1 : State::S0; + if (cell->type.in(ID($dffsr), ID($dlatchsr))) { + pol_set = cell->parameters[ID(SET_POLARITY)].as_bool() ? State::S1 : State::S0; + pol_clr = cell->parameters[ID(CLR_POLARITY)].as_bool() ? State::S1 : State::S0; } else log_abort(); State npol_set = pol_set == State::S0 ? State::S1 : State::S0; State npol_clr = pol_clr == State::S0 ? State::S1 : State::S0; - SigSpec sig_d = cell->getPort("\\D"); - SigSpec sig_q = cell->getPort("\\Q"); + SigSpec sig_d = cell->getPort(ID(D)); + SigSpec sig_q = cell->getPort(ID(Q)); bool did_something = false; bool proper_sr = false; @@ -137,20 +137,20 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) return true; } - if (cell->type.in("$dffsr", "$dlatchsr")) + if (cell->type.in(ID($dffsr), ID($dlatchsr))) { - cell->setParam("\\WIDTH", GetSize(sig_d)); - cell->setPort("\\SET", sig_set); - cell->setPort("\\CLR", sig_clr); - cell->setPort("\\D", sig_d); - cell->setPort("\\Q", sig_q); + cell->setParam(ID(WIDTH), GetSize(sig_d)); + cell->setPort(ID(SET), sig_set); + cell->setPort(ID(CLR), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); } else { - cell->setPort("\\S", sig_set); - cell->setPort("\\R", sig_clr); - cell->setPort("\\D", sig_d); - cell->setPort("\\Q", sig_q); + cell->setPort(ID(S), sig_set); + cell->setPort(ID(R), sig_clr); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); } if (proper_sr) @@ -159,36 +159,36 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) if (used_pol_set && used_pol_clr && pol_set != pol_clr) return did_something; - if (cell->type == "$dlatchsr") + if (cell->type == ID($dlatchsr)) return did_something; State unified_pol = used_pol_set ? pol_set : pol_clr; - if (cell->type == "$dffsr") + if (cell->type == ID($dffsr)) { if (hasreset) { log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$adff", log_id(mod)); - cell->type = "$adff"; - cell->setParam("\\ARST_POLARITY", unified_pol); - cell->setParam("\\ARST_VALUE", reset_val); - cell->setPort("\\ARST", sig_reset); + cell->type = ID($adff); + cell->setParam(ID(ARST_POLARITY), unified_pol); + cell->setParam(ID(ARST_VALUE), reset_val); + cell->setPort(ID(ARST), sig_reset); - cell->unsetParam("\\SET_POLARITY"); - cell->unsetParam("\\CLR_POLARITY"); - cell->unsetPort("\\SET"); - cell->unsetPort("\\CLR"); + cell->unsetParam(ID(SET_POLARITY)); + cell->unsetParam(ID(CLR_POLARITY)); + cell->unsetPort(ID(SET)); + cell->unsetPort(ID(CLR)); } else { log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), "$dff", log_id(mod)); - cell->type = "$dff"; - cell->unsetParam("\\SET_POLARITY"); - cell->unsetParam("\\CLR_POLARITY"); - cell->unsetPort("\\SET"); - cell->unsetPort("\\CLR"); + cell->type = ID($dff); + cell->unsetParam(ID(SET_POLARITY)); + cell->unsetParam(ID(CLR_POLARITY)); + cell->unsetPort(ID(SET)); + cell->unsetPort(ID(CLR)); } return true; @@ -208,8 +208,8 @@ bool handle_dffsr(RTLIL::Module *mod, RTLIL::Cell *cell) log("Converting %s (%s) to %s in module %s.\n", log_id(cell), log_id(cell->type), log_id(new_type), log_id(mod)); cell->type = new_type; - cell->unsetPort("\\S"); - cell->unsetPort("\\R"); + cell->unsetPort(ID(S)); + cell->unsetPort(ID(R)); return true; } @@ -222,18 +222,18 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) SigSpec sig_e; State on_state, off_state; - if (dlatch->type == "$dlatch") { - sig_e = assign_map(dlatch->getPort("\\EN")); - on_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S1 : State::S0; - off_state = dlatch->getParam("\\EN_POLARITY").as_bool() ? State::S0 : State::S1; + if (dlatch->type == ID($dlatch)) { + sig_e = assign_map(dlatch->getPort(ID(EN))); + on_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S1 : State::S0; + off_state = dlatch->getParam(ID(EN_POLARITY)).as_bool() ? State::S0 : State::S1; } else - if (dlatch->type == "$_DLATCH_P_") { - sig_e = assign_map(dlatch->getPort("\\E")); + if (dlatch->type == ID($_DLATCH_P_)) { + sig_e = assign_map(dlatch->getPort(ID(E))); on_state = State::S1; off_state = State::S0; } else - if (dlatch->type == "$_DLATCH_N_") { - sig_e = assign_map(dlatch->getPort("\\E")); + if (dlatch->type == ID($_DLATCH_N_)) { + sig_e = assign_map(dlatch->getPort(ID(E))); on_state = State::S0; off_state = State::S1; } else @@ -242,15 +242,15 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) if (sig_e == off_state) { RTLIL::Const val_init; - for (auto bit : dff_init_map(dlatch->getPort("\\Q"))) + for (auto bit : dff_init_map(dlatch->getPort(ID(Q)))) val_init.bits.push_back(bit.wire == NULL ? bit.data : State::Sx); - mod->connect(dlatch->getPort("\\Q"), val_init); + mod->connect(dlatch->getPort(ID(Q)), val_init); goto delete_dlatch; } if (sig_e == on_state) { - mod->connect(dlatch->getPort("\\Q"), dlatch->getPort("\\D")); + mod->connect(dlatch->getPort(ID(Q)), dlatch->getPort(ID(D))); goto delete_dlatch; } @@ -258,7 +258,7 @@ bool handle_dlatch(RTLIL::Module *mod, RTLIL::Cell *dlatch) delete_dlatch: log("Removing %s (%s) from module %s.\n", log_id(dlatch), log_id(dlatch->type), log_id(mod)); - remove_init_attr(dlatch->getPort("\\Q")); + remove_init_attr(dlatch->getPort(ID(Q))); mod->remove(dlatch); return true; } @@ -268,24 +268,24 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) RTLIL::SigSpec sig_d, sig_q, sig_c, sig_r, sig_e; RTLIL::Const val_cp, val_rp, val_rv, val_ep; - if (dff->type == "$_FF_") { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); + if (dff->type == ID($_FF_)) { + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); } - else if (dff->type == "$_DFF_N_" || dff->type == "$_DFF_P_") { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\C"); - val_cp = RTLIL::Const(dff->type == "$_DFF_P_", 1); + else if (dff->type == ID($_DFF_N_) || dff->type == ID($_DFF_P_)) { + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); + val_cp = RTLIL::Const(dff->type == ID($_DFF_P_), 1); } else if (dff->type.begins_with("$_DFF_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[6] == 'N' || dff->type[6] == 'P') && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == '0' || dff->type[8] == '1')) { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\C"); - sig_r = dff->getPort("\\R"); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); + sig_r = dff->getPort(ID(R)); val_cp = RTLIL::Const(dff->type[6] == 'P', 1); val_rp = RTLIL::Const(dff->type[7] == 'P', 1); val_rv = RTLIL::Const(dff->type[8] == '1', 1); @@ -293,39 +293,39 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) else if (dff->type.begins_with("$_DFFE_") && dff->type.compare(9, 1, "_") == 0 && (dff->type[7] == 'N' || dff->type[7] == 'P') && (dff->type[8] == 'N' || dff->type[8] == 'P')) { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\C"); - sig_e = dff->getPort("\\E"); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(C)); + sig_e = dff->getPort(ID(E)); val_cp = RTLIL::Const(dff->type[7] == 'P', 1); val_ep = RTLIL::Const(dff->type[8] == 'P', 1); } - else if (dff->type == "$ff") { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); + else if (dff->type == ID($ff)) { + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); } - else if (dff->type == "$dff") { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\CLK"); - val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); + else if (dff->type == ID($dff)) { + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); } - else if (dff->type == "$dffe") { - sig_e = dff->getPort("\\EN"); - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\CLK"); - val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); - val_ep = RTLIL::Const(dff->parameters["\\EN_POLARITY"].as_bool(), 1); + else if (dff->type == ID($dffe)) { + sig_e = dff->getPort(ID(EN)); + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); + val_ep = RTLIL::Const(dff->parameters[ID(EN_POLARITY)].as_bool(), 1); } - else if (dff->type == "$adff") { - sig_d = dff->getPort("\\D"); - sig_q = dff->getPort("\\Q"); - sig_c = dff->getPort("\\CLK"); - sig_r = dff->getPort("\\ARST"); - val_cp = RTLIL::Const(dff->parameters["\\CLK_POLARITY"].as_bool(), 1); - val_rp = RTLIL::Const(dff->parameters["\\ARST_POLARITY"].as_bool(), 1); - val_rv = dff->parameters["\\ARST_VALUE"]; + else if (dff->type == ID($adff)) { + sig_d = dff->getPort(ID(D)); + sig_q = dff->getPort(ID(Q)); + sig_c = dff->getPort(ID(CLK)); + sig_r = dff->getPort(ID(ARST)); + val_cp = RTLIL::Const(dff->parameters[ID(CLK_POLARITY)].as_bool(), 1); + val_rp = RTLIL::Const(dff->parameters[ID(ARST_POLARITY)].as_bool(), 1); + val_rv = dff->parameters[ID(ARST_VALUE)]; } else log_abort(); @@ -343,12 +343,12 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) val_init.bits.push_back(bit.wire == NULL ? bit.data : RTLIL::State::Sx); } - if (dff->type.in("$ff", "$dff") && mux_drivers.has(sig_d)) { + if (dff->type.in(ID($ff), ID($dff)) && mux_drivers.has(sig_d)) { std::set muxes; mux_drivers.find(sig_d, muxes); for (auto mux : muxes) { - RTLIL::SigSpec sig_a = assign_map(mux->getPort("\\A")); - RTLIL::SigSpec sig_b = assign_map(mux->getPort("\\B")); + RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID(A))); + RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID(B))); if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) { mod->connect(sig_q, sig_b); goto delete_dff; @@ -420,17 +420,17 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) log("Removing unused reset from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); - if (dff->type == "$adff") { - dff->type = "$dff"; - dff->unsetPort("\\ARST"); - dff->unsetParam("\\ARST_POLARITY"); - dff->unsetParam("\\ARST_VALUE"); + if (dff->type == ID($adff)) { + dff->type = ID($dff); + dff->unsetPort(ID(ARST)); + dff->unsetParam(ID(ARST_POLARITY)); + dff->unsetParam(ID(ARST_VALUE)); return true; } log_assert(dff->type.begins_with("$_DFF_")); dff->type = stringf("$_DFF_%c_", + dff->type[6]); - dff->unsetPort("\\R"); + dff->unsetPort(ID(R)); } // If enable signal is present, and is fully constant @@ -445,16 +445,16 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) log("Removing unused enable from %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); - if (dff->type == "$dffe") { - dff->type = "$dff"; - dff->unsetPort("\\EN"); - dff->unsetParam("\\EN_POLARITY"); + if (dff->type == ID($dffe)) { + dff->type = ID($dff); + dff->unsetPort(ID(EN)); + dff->unsetParam(ID(EN_POLARITY)); return true; } log_assert(dff->type.begins_with("$_DFFE_")); dff->type = stringf("$_DFF_%c_", + dff->type[7]); - dff->unsetPort("\\E"); + dff->unsetPort(ID(E)); } if (sat && has_init && (!sig_r.size() || val_init == val_rv)) @@ -509,9 +509,9 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) log("Setting constant %d-bit at position %d on %s (%s) from module %s.\n", sigbit_init_val ? 1 : 0, position, log_id(dff), log_id(dff->type), log_id(mod)); - SigSpec tmp = dff->getPort("\\D"); + SigSpec tmp = dff->getPort(ID(D)); tmp[position] = sigbit_init_val; - dff->setPort("\\D", tmp); + dff->setPort(ID(D), tmp); removed_sigbits = true; } @@ -528,7 +528,7 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) delete_dff: log("Removing %s (%s) from module %s.\n", log_id(dff), log_id(dff->type), log_id(mod)); - remove_init_attr(dff->getPort("\\Q")); + remove_init_attr(dff->getPort(ID(Q))); mod->remove(dff); for (auto &entry : bit2driver) @@ -588,8 +588,8 @@ struct OptRmdffPass : public Pass { for (auto wire : module->wires()) { - if (wire->attributes.count("\\init") != 0) { - Const initval = wire->attributes.at("\\init"); + if (wire->attributes.count(ID(init)) != 0) { + Const initval = wire->attributes.at(ID(init)); for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) if (initval[i] == State::S0 || initval[i] == State::S1) dff_init_map.add(SigBit(wire, i), initval[i]); @@ -624,29 +624,29 @@ struct OptRmdffPass : public Pass { } } - if (cell->type.in("$mux", "$pmux")) { - if (cell->getPort("\\A").size() == cell->getPort("\\B").size()) - mux_drivers.insert(assign_map(cell->getPort("\\Y")), cell); + if (cell->type.in(ID($mux), ID($pmux))) { + if (cell->getPort(ID(A)).size() == cell->getPort(ID(B)).size()) + mux_drivers.insert(assign_map(cell->getPort(ID(Y))), cell); continue; } if (!design->selected(module, cell)) continue; - if (cell->type.in("$_DFFSR_NNN_", "$_DFFSR_NNP_", "$_DFFSR_NPN_", "$_DFFSR_NPP_", - "$_DFFSR_PNN_", "$_DFFSR_PNP_", "$_DFFSR_PPN_", "$_DFFSR_PPP_", "$dffsr", - "$_DLATCHSR_NNN_", "$_DLATCHSR_NNP_", "$_DLATCHSR_NPN_", "$_DLATCHSR_NPP_", - "$_DLATCHSR_PNN_", "$_DLATCHSR_PNP_", "$_DLATCHSR_PPN_", "$_DLATCHSR_PPP_", "$dlatchsr")) + if (cell->type.in(ID($_DFFSR_NNN_), ID($_DFFSR_NNP_), ID($_DFFSR_NPN_), ID($_DFFSR_NPP_), + ID($_DFFSR_PNN_), ID($_DFFSR_PNP_), ID($_DFFSR_PPN_), ID($_DFFSR_PPP_), ID($dffsr), + ID($_DLATCHSR_NNN_), ID($_DLATCHSR_NNP_), ID($_DLATCHSR_NPN_), ID($_DLATCHSR_NPP_), + ID($_DLATCHSR_PNN_), ID($_DLATCHSR_PNP_), ID($_DLATCHSR_PPN_), ID($_DLATCHSR_PPP_), ID($dlatchsr))) dffsr_list.push_back(cell->name); - if (cell->type.in("$_FF_", "$_DFF_N_", "$_DFF_P_", - "$_DFF_NN0_", "$_DFF_NN1_", "$_DFF_NP0_", "$_DFF_NP1_", - "$_DFF_PN0_", "$_DFF_PN1_", "$_DFF_PP0_", "$_DFF_PP1_", - "$_DFFE_NN_", "$_DFFE_NP_", "$_DFFE_PN_", "$_DFFE_PP_", - "$ff", "$dff", "$dffe", "$adff")) + if (cell->type.in(ID($_FF_), ID($_DFF_N_), ID($_DFF_P_), + ID($_DFF_NN0_), ID($_DFF_NN1_), ID($_DFF_NP0_), ID($_DFF_NP1_), + ID($_DFF_PN0_), ID($_DFF_PN1_), ID($_DFF_PP0_), ID($_DFF_PP1_), + ID($_DFFE_NN_), ID($_DFFE_NP_), ID($_DFFE_PN_), ID($_DFFE_PP_), + ID($ff), ID($dff), ID($dffe), ID($adff))) dff_list.push_back(cell->name); - if (cell->type.in("$dlatch", "$_DLATCH_P_", "$_DLATCH_N_")) + if (cell->type.in(ID($dlatch), ID($_DLATCH_P_), ID($_DLATCH_N_))) dlatch_list.push_back(cell->name); } diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 65d8b8f32..3e34bfbbd 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -46,7 +46,7 @@ struct OnehotDatabase for (auto wire : module->wires()) { - auto it = wire->attributes.find("\\init"); + auto it = wire->attributes.find(ID(init)); if (it == wire->attributes.end()) continue; @@ -63,19 +63,19 @@ struct OnehotDatabase vector inputs; SigSpec output; - if (cell->type.in("$adff", "$dff", "$dffe", "$dlatch", "$ff")) + if (cell->type.in(ID($adff), ID($dff), ID($dffe), ID($dlatch), ID($ff))) { - output = cell->getPort("\\Q"); - if (cell->type == "$adff") - inputs.push_back(cell->getParam("\\ARST_VALUE")); - inputs.push_back(cell->getPort("\\D")); + output = cell->getPort(ID(Q)); + if (cell->type == ID($adff)) + inputs.push_back(cell->getParam(ID(ARST_VALUE))); + inputs.push_back(cell->getPort(ID(D))); } - if (cell->type.in("$mux", "$pmux")) + if (cell->type.in(ID($mux), ID($pmux))) { - output = cell->getPort("\\Y"); - inputs.push_back(cell->getPort("\\A")); - SigSpec B = cell->getPort("\\B"); + output = cell->getPort(ID(Y)); + inputs.push_back(cell->getPort(ID(A))); + SigSpec B = cell->getPort(ID(B)); for (int i = 0; i < GetSize(B); i += GetSize(output)) inputs.push_back(B.extract(i, GetSize(output))); } @@ -292,23 +292,23 @@ struct Pmux2ShiftxPass : public Pass { for (auto cell : module->cells()) { - if (cell->type == "$eq") + if (cell->type == ID($eq)) { dict bits; - SigSpec A = sigmap(cell->getPort("\\A")); - SigSpec B = sigmap(cell->getPort("\\B")); + SigSpec A = sigmap(cell->getPort(ID(A))); + SigSpec B = sigmap(cell->getPort(ID(B))); - int a_width = cell->getParam("\\A_WIDTH").as_int(); - int b_width = cell->getParam("\\B_WIDTH").as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); if (a_width < b_width) { - bool a_signed = cell->getParam("\\A_SIGNED").as_int(); + bool a_signed = cell->getParam(ID(A_SIGNED)).as_int(); A.extend_u0(b_width, a_signed); } if (b_width < a_width) { - bool b_signed = cell->getParam("\\B_SIGNED").as_int(); + bool b_signed = cell->getParam(ID(B_SIGNED)).as_int(); B.extend_u0(a_width, b_signed); } @@ -335,15 +335,15 @@ struct Pmux2ShiftxPass : public Pass { entry.second.bits.push_back(it.second); } - eqdb[sigmap(cell->getPort("\\Y")[0])] = entry; + eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry; goto next_cell; } - if (cell->type == "$logic_not") + if (cell->type == ID($logic_not)) { dict bits; - SigSpec A = sigmap(cell->getPort("\\A")); + SigSpec A = sigmap(cell->getPort(ID(A))); for (int i = 0; i < GetSize(A); i++) bits[A[i]] = State::S0; @@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass { entry.second.bits.push_back(it.second); } - eqdb[sigmap(cell->getPort("\\Y")[0])] = entry; + eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry; goto next_cell; } next_cell:; @@ -364,11 +364,11 @@ struct Pmux2ShiftxPass : public Pass { for (auto cell : module->selected_cells()) { - if (cell->type != "$pmux") + if (cell->type != ID($pmux)) continue; string src = cell->get_src_attribute(); - int width = cell->getParam("\\WIDTH").as_int(); + int width = cell->getParam(ID(WIDTH)).as_int(); int width_bits = ceil_log2(width); int extwidth = width; @@ -377,9 +377,9 @@ struct Pmux2ShiftxPass : public Pass { dict> seldb; - SigSpec A = cell->getPort("\\A"); - SigSpec B = cell->getPort("\\B"); - SigSpec S = sigmap(cell->getPort("\\S")); + SigSpec A = cell->getPort(ID(A)); + SigSpec B = cell->getPort(ID(B)); + SigSpec S = sigmap(cell->getPort(ID(S))); for (int i = 0; i < GetSize(S); i++) { if (!eqdb.count(S[i])) @@ -400,8 +400,8 @@ struct Pmux2ShiftxPass : public Pass { log(" data width: %d (next power-of-2 = %d, log2 = %d)\n", width, extwidth, width_bits); } - SigSpec updated_S = cell->getPort("\\S"); - SigSpec updated_B = cell->getPort("\\B"); + SigSpec updated_S = cell->getPort(ID(S)); + SigSpec updated_B = cell->getPort(ID(B)); while (!seldb.empty()) { @@ -727,9 +727,9 @@ struct Pmux2ShiftxPass : public Pass { } // update $pmux cell - cell->setPort("\\S", updated_S); - cell->setPort("\\B", updated_B); - cell->setParam("\\S_WIDTH", GetSize(updated_S)); + cell->setPort(ID(S), updated_S); + cell->setPort(ID(B), updated_B); + cell->setParam(ID(S_WIDTH), GetSize(updated_S)); } } } @@ -779,22 +779,22 @@ struct OnehotPass : public Pass { for (auto cell : module->selected_cells()) { - if (cell->type != "$eq") + if (cell->type != ID($eq)) continue; - SigSpec A = sigmap(cell->getPort("\\A")); - SigSpec B = sigmap(cell->getPort("\\B")); + SigSpec A = sigmap(cell->getPort(ID(A))); + SigSpec B = sigmap(cell->getPort(ID(B))); - int a_width = cell->getParam("\\A_WIDTH").as_int(); - int b_width = cell->getParam("\\B_WIDTH").as_int(); + int a_width = cell->getParam(ID(A_WIDTH)).as_int(); + int b_width = cell->getParam(ID(B_WIDTH)).as_int(); if (a_width < b_width) { - bool a_signed = cell->getParam("\\A_SIGNED").as_int(); + bool a_signed = cell->getParam(ID(A_SIGNED)).as_int(); A.extend_u0(b_width, a_signed); } if (b_width < a_width) { - bool b_signed = cell->getParam("\\B_SIGNED").as_int(); + bool b_signed = cell->getParam(ID(B_SIGNED)).as_int(); B.extend_u0(a_width, b_signed); } @@ -830,7 +830,7 @@ struct OnehotPass : public Pass { continue; } - SigSpec Y = cell->getPort("\\Y"); + SigSpec Y = cell->getPort(ID(Y)); if (not_onehot) { diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 7f66f749f..84290bb97 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -89,8 +89,8 @@ struct ShareWorker queue_bits.clear(); for (auto &pbit : portbits) { - if (pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") { - pool bits = modwalker.sigmap(pbit.cell->getPort("\\S")).to_sigbit_pool(); + if (pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) { + pool bits = modwalker.sigmap(pbit.cell->getPort(ID(S))).to_sigbit_pool(); terminal_bits.insert(bits.begin(), bits.end()); queue_bits.insert(bits.begin(), bits.end()); visited_cells.insert(pbit.cell); @@ -128,7 +128,7 @@ struct ShareWorker static int bits_macc(RTLIL::Cell *c) { Macc m(c); - int width = GetSize(c->getPort("\\Y")); + int width = GetSize(c->getPort(ID(Y))); return bits_macc(m, width); } @@ -242,7 +242,7 @@ struct ShareWorker { Macc m1(c1), m2(c2), supermacc; - int w1 = GetSize(c1->getPort("\\Y")), w2 = GetSize(c2->getPort("\\Y")); + int w1 = GetSize(c1->getPort(ID(Y))), w2 = GetSize(c2->getPort(ID(Y))); int width = max(w1, w2); m1.optimize(w1); @@ -328,11 +328,11 @@ struct ShareWorker { RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width); - supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort("\\Y"))); - supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort("\\Y"))); + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID(Y)))); + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID(Y)))); - supercell->setParam("\\Y_WIDTH", width); - supercell->setPort("\\Y", sig_y); + supercell->setParam(ID(Y_WIDTH), width); + supercell->setPort(ID(Y), sig_y); supermacc.optimize(width); supermacc.to_cell(supercell); @@ -368,22 +368,22 @@ struct ShareWorker continue; } - if (cell->type == "$memrd") { - if (cell->parameters.at("\\CLK_ENABLE").as_bool()) + if (cell->type == ID($memrd)) { + if (cell->parameters.at(ID(CLK_ENABLE)).as_bool()) continue; - if (config.opt_aggressive || !modwalker.sigmap(cell->getPort("\\ADDR")).is_fully_const()) + if (config.opt_aggressive || !modwalker.sigmap(cell->getPort(ID(ADDR))).is_fully_const()) shareable_cells.insert(cell); continue; } - if (cell->type.in("$mul", "$div", "$mod")) { - if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 4) + if (cell->type.in(ID($mul), ID($div), ID($mod))) { + if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 4) shareable_cells.insert(cell); continue; } - if (cell->type.in("$shl", "$shr", "$sshl", "$sshr")) { - if (config.opt_aggressive || cell->parameters.at("\\Y_WIDTH").as_int() >= 8) + if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) { + if (config.opt_aggressive || cell->parameters.at(ID(Y_WIDTH)).as_int() >= 8) shareable_cells.insert(cell); continue; } @@ -401,9 +401,9 @@ struct ShareWorker if (c1->type != c2->type) return false; - if (c1->type == "$memrd") + if (c1->type == ID($memrd)) { - if (c1->parameters.at("\\MEMID").decode_string() != c2->parameters.at("\\MEMID").decode_string()) + if (c1->parameters.at(ID(MEMID)).decode_string() != c2->parameters.at(ID(MEMID)).decode_string()) return false; return true; @@ -413,11 +413,11 @@ struct ShareWorker { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); - int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); - int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(y1_width, y2_width) > 2 * min(y1_width, y2_width)) return false; @@ -426,17 +426,17 @@ struct ShareWorker return true; } - if (config.generic_bin_ops.count(c1->type) || c1->type == "$alu") + if (config.generic_bin_ops.count(c1->type) || c1->type == ID($alu)) { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); - int b1_width = c1->parameters.at("\\B_WIDTH").as_int(); - int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); - int b2_width = c2->parameters.at("\\B_WIDTH").as_int(); - int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); if (max(a1_width, a2_width) > 2 * min(a1_width, a2_width)) return false; if (max(b1_width, b2_width) > 2 * min(b1_width, b2_width)) return false; @@ -450,13 +450,13 @@ struct ShareWorker { if (!config.opt_aggressive) { - int a1_width = c1->parameters.at("\\A_WIDTH").as_int(); - int b1_width = c1->parameters.at("\\B_WIDTH").as_int(); - int y1_width = c1->parameters.at("\\Y_WIDTH").as_int(); + int a1_width = c1->parameters.at(ID(A_WIDTH)).as_int(); + int b1_width = c1->parameters.at(ID(B_WIDTH)).as_int(); + int y1_width = c1->parameters.at(ID(Y_WIDTH)).as_int(); - int a2_width = c2->parameters.at("\\A_WIDTH").as_int(); - int b2_width = c2->parameters.at("\\B_WIDTH").as_int(); - int y2_width = c2->parameters.at("\\Y_WIDTH").as_int(); + int a2_width = c2->parameters.at(ID(A_WIDTH)).as_int(); + int b2_width = c2->parameters.at(ID(B_WIDTH)).as_int(); + int y2_width = c2->parameters.at(ID(Y_WIDTH)).as_int(); int min1_width = min(a1_width, b1_width); int max1_width = max(a1_width, b1_width); @@ -472,7 +472,7 @@ struct ShareWorker return true; } - if (c1->type == "$macc") + if (c1->type == ID($macc)) { if (!config.opt_aggressive) if (share_macc(c1, c2) > 2 * min(bits_macc(c1), bits_macc(c2))) return false; @@ -510,27 +510,27 @@ struct ShareWorker if (config.generic_uni_ops.count(c1->type)) { - if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool()) + if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool()) { - RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1; - if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1; - RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A"); + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; + if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) { + unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; + RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A)); new_a.append_bit(RTLIL::State::S0); - unsigned_cell->setPort("\\A", new_a); + unsigned_cell->setPort(ID(A), new_a); } - unsigned_cell->parameters.at("\\A_SIGNED") = true; + unsigned_cell->parameters.at(ID(A_SIGNED)) = true; unsigned_cell->check(); } - bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool(); - log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool()); + bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool(); + log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool()); - RTLIL::SigSpec a1 = c1->getPort("\\A"); - RTLIL::SigSpec y1 = c1->getPort("\\Y"); + RTLIL::SigSpec a1 = c1->getPort(ID(A)); + RTLIL::SigSpec y1 = c1->getPort(ID(Y)); - RTLIL::SigSpec a2 = c2->getPort("\\A"); - RTLIL::SigSpec y2 = c2->getPort("\\Y"); + RTLIL::SigSpec a2 = c2->getPort(ID(A)); + RTLIL::SigSpec y2 = c2->getPort(ID(Y)); int a_width = max(a1.size(), a2.size()); int y_width = max(y1.size(), y2.size()); @@ -544,11 +544,11 @@ struct ShareWorker RTLIL::Wire *y = module->addWire(NEW_ID, y_width); RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); - supercell->parameters["\\A_SIGNED"] = a_signed; - supercell->parameters["\\A_WIDTH"] = a_width; - supercell->parameters["\\Y_WIDTH"] = y_width; - supercell->setPort("\\A", a); - supercell->setPort("\\Y", y); + supercell->parameters[ID(A_SIGNED)] = a_signed; + supercell->parameters[ID(A_WIDTH)] = a_width; + supercell->parameters[ID(Y_WIDTH)] = y_width; + supercell->setPort(ID(A), a); + supercell->setPort(ID(Y), y); supercell_aux.insert(module->addPos(NEW_ID, y, y1)); supercell_aux.insert(module->addPos(NEW_ID, y, y2)); @@ -557,54 +557,54 @@ struct ShareWorker return supercell; } - if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == "$alu") + if (config.generic_bin_ops.count(c1->type) || config.generic_cbin_ops.count(c1->type) || c1->type == ID($alu)) { bool modified_src_cells = false; if (config.generic_cbin_ops.count(c1->type)) { - int score_unflipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()) + - max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()); + int score_unflipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()) + + max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()); - int score_flipped = max(c1->parameters.at("\\A_WIDTH").as_int(), c2->parameters.at("\\B_WIDTH").as_int()) + - max(c1->parameters.at("\\B_WIDTH").as_int(), c2->parameters.at("\\A_WIDTH").as_int()); + int score_flipped = max(c1->parameters.at(ID(A_WIDTH)).as_int(), c2->parameters.at(ID(B_WIDTH)).as_int()) + + max(c1->parameters.at(ID(B_WIDTH)).as_int(), c2->parameters.at(ID(A_WIDTH)).as_int()); if (score_flipped < score_unflipped) { - RTLIL::SigSpec tmp = c2->getPort("\\A"); - c2->setPort("\\A", c2->getPort("\\B")); - c2->setPort("\\B", tmp); + RTLIL::SigSpec tmp = c2->getPort(ID(A)); + c2->setPort(ID(A), c2->getPort(ID(B))); + c2->setPort(ID(B), tmp); - std::swap(c2->parameters.at("\\A_WIDTH"), c2->parameters.at("\\B_WIDTH")); - std::swap(c2->parameters.at("\\A_SIGNED"), c2->parameters.at("\\B_SIGNED")); + std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH))); + std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED))); modified_src_cells = true; } } - if (c1->parameters.at("\\A_SIGNED").as_bool() != c2->parameters.at("\\A_SIGNED").as_bool()) + if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool()) { - RTLIL::Cell *unsigned_cell = c1->parameters.at("\\A_SIGNED").as_bool() ? c2 : c1; - if (unsigned_cell->getPort("\\A").to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at("\\A_WIDTH") = unsigned_cell->parameters.at("\\A_WIDTH").as_int() + 1; - RTLIL::SigSpec new_a = unsigned_cell->getPort("\\A"); + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; + if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) { + unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; + RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A)); new_a.append_bit(RTLIL::State::S0); - unsigned_cell->setPort("\\A", new_a); + unsigned_cell->setPort(ID(A), new_a); } - unsigned_cell->parameters.at("\\A_SIGNED") = true; + unsigned_cell->parameters.at(ID(A_SIGNED)) = true; modified_src_cells = true; } - if (c1->parameters.at("\\B_SIGNED").as_bool() != c2->parameters.at("\\B_SIGNED").as_bool()) + if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool()) { - RTLIL::Cell *unsigned_cell = c1->parameters.at("\\B_SIGNED").as_bool() ? c2 : c1; - if (unsigned_cell->getPort("\\B").to_sigbit_vector().back() != RTLIL::State::S0) { - unsigned_cell->parameters.at("\\B_WIDTH") = unsigned_cell->parameters.at("\\B_WIDTH").as_int() + 1; - RTLIL::SigSpec new_b = unsigned_cell->getPort("\\B"); + RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1; + if (unsigned_cell->getPort(ID(B)).to_sigbit_vector().back() != RTLIL::State::S0) { + unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1; + RTLIL::SigSpec new_b = unsigned_cell->getPort(ID(B)); new_b.append_bit(RTLIL::State::S0); - unsigned_cell->setPort("\\B", new_b); + unsigned_cell->setPort(ID(B), new_b); } - unsigned_cell->parameters.at("\\B_SIGNED") = true; + unsigned_cell->parameters.at(ID(B_SIGNED)) = true; modified_src_cells = true; } @@ -613,28 +613,28 @@ struct ShareWorker c2->check(); } - bool a_signed = c1->parameters.at("\\A_SIGNED").as_bool(); - bool b_signed = c1->parameters.at("\\B_SIGNED").as_bool(); + bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool(); + bool b_signed = c1->parameters.at(ID(B_SIGNED)).as_bool(); - log_assert(a_signed == c2->parameters.at("\\A_SIGNED").as_bool()); - log_assert(b_signed == c2->parameters.at("\\B_SIGNED").as_bool()); + log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool()); + log_assert(b_signed == c2->parameters.at(ID(B_SIGNED)).as_bool()); - if (c1->type == "$shl" || c1->type == "$shr" || c1->type == "$sshl" || c1->type == "$sshr") + if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr)) b_signed = false; - RTLIL::SigSpec a1 = c1->getPort("\\A"); - RTLIL::SigSpec b1 = c1->getPort("\\B"); - RTLIL::SigSpec y1 = c1->getPort("\\Y"); + RTLIL::SigSpec a1 = c1->getPort(ID(A)); + RTLIL::SigSpec b1 = c1->getPort(ID(B)); + RTLIL::SigSpec y1 = c1->getPort(ID(Y)); - RTLIL::SigSpec a2 = c2->getPort("\\A"); - RTLIL::SigSpec b2 = c2->getPort("\\B"); - RTLIL::SigSpec y2 = c2->getPort("\\Y"); + RTLIL::SigSpec a2 = c2->getPort(ID(A)); + RTLIL::SigSpec b2 = c2->getPort(ID(B)); + RTLIL::SigSpec y2 = c2->getPort(ID(Y)); int a_width = max(a1.size(), a2.size()); int b_width = max(b1.size(), b2.size()); int y_width = max(y1.size(), y2.size()); - if (c1->type == "$shr" && a_signed) + if (c1->type == ID($shr) && a_signed) { a_width = max(y_width, a_width); @@ -660,43 +660,43 @@ struct ShareWorker supercell_aux.insert(module->addMux(NEW_ID, b2, b1, act, b)); RTLIL::Wire *y = module->addWire(NEW_ID, y_width); - RTLIL::Wire *x = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; - RTLIL::Wire *co = c1->type == "$alu" ? module->addWire(NEW_ID, y_width) : nullptr; + RTLIL::Wire *x = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr; + RTLIL::Wire *co = c1->type == ID($alu) ? module->addWire(NEW_ID, y_width) : nullptr; RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); - supercell->parameters["\\A_SIGNED"] = a_signed; - supercell->parameters["\\B_SIGNED"] = b_signed; - supercell->parameters["\\A_WIDTH"] = a_width; - supercell->parameters["\\B_WIDTH"] = b_width; - supercell->parameters["\\Y_WIDTH"] = y_width; - supercell->setPort("\\A", a); - supercell->setPort("\\B", b); - supercell->setPort("\\Y", y); - if (c1->type == "$alu") { + supercell->parameters[ID(A_SIGNED)] = a_signed; + supercell->parameters[ID(B_SIGNED)] = b_signed; + supercell->parameters[ID(A_WIDTH)] = a_width; + supercell->parameters[ID(B_WIDTH)] = b_width; + supercell->parameters[ID(Y_WIDTH)] = y_width; + supercell->setPort(ID(A), a); + supercell->setPort(ID(B), b); + supercell->setPort(ID(Y), y); + if (c1->type == ID($alu)) { RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID); - supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\CI"), c1->getPort("\\CI"), act, ci)); - supercell_aux.insert(module->addMux(NEW_ID, c2->getPort("\\BI"), c1->getPort("\\BI"), act, bi)); - supercell->setPort("\\CI", ci); - supercell->setPort("\\BI", bi); - supercell->setPort("\\CO", co); - supercell->setPort("\\X", x); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci)); + supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(BI)), c1->getPort(ID(BI)), act, bi)); + supercell->setPort(ID(CI), ci); + supercell->setPort(ID(BI), bi); + supercell->setPort(ID(CO), co); + supercell->setPort(ID(X), x); } supercell->check(); supercell_aux.insert(module->addPos(NEW_ID, y, y1)); supercell_aux.insert(module->addPos(NEW_ID, y, y2)); - if (c1->type == "$alu") { - supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort("\\CO"))); - supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort("\\CO"))); - supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort("\\X"))); - supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort("\\X"))); + if (c1->type == ID($alu)) { + supercell_aux.insert(module->addPos(NEW_ID, co, c1->getPort(ID(CO)))); + supercell_aux.insert(module->addPos(NEW_ID, co, c2->getPort(ID(CO)))); + supercell_aux.insert(module->addPos(NEW_ID, x, c1->getPort(ID(X)))); + supercell_aux.insert(module->addPos(NEW_ID, x, c2->getPort(ID(X)))); } supercell_aux.insert(supercell); return supercell; } - if (c1->type == "$macc") + if (c1->type == ID($macc)) { RTLIL::Cell *supercell = module->addCell(NEW_ID, c1->type); supercell_aux.insert(supercell); @@ -705,18 +705,18 @@ struct ShareWorker return supercell; } - if (c1->type == "$memrd") + if (c1->type == ID($memrd)) { RTLIL::Cell *supercell = module->addCell(NEW_ID, c1); - RTLIL::SigSpec addr1 = c1->getPort("\\ADDR"); - RTLIL::SigSpec addr2 = c2->getPort("\\ADDR"); + RTLIL::SigSpec addr1 = c1->getPort(ID(ADDR)); + RTLIL::SigSpec addr2 = c2->getPort(ID(ADDR)); if (GetSize(addr1) < GetSize(addr2)) addr1.extend_u0(GetSize(addr2)); else addr2.extend_u0(GetSize(addr1)); - supercell->setPort("\\ADDR", addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); - supercell->parameters["\\ABITS"] = RTLIL::Const(GetSize(addr1)); - supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort("\\DATA"), c2->getPort("\\DATA"))); + supercell->setPort(ID(ADDR), addr1 != addr2 ? module->Mux(NEW_ID, addr2, addr1, act) : addr1); + supercell->parameters[ID(ABITS)] = RTLIL::Const(GetSize(addr1)); + supercell_aux.insert(module->addPos(NEW_ID, supercell->getPort(ID(DATA)), c2->getPort(ID(DATA)))); supercell_aux.insert(supercell); return supercell; } @@ -747,8 +747,8 @@ struct ShareWorker modwalker.get_consumers(pbits, modwalker.cell_outputs[cell]); for (auto &bit : pbits) { - if ((bit.cell->type == "$mux" || bit.cell->type == "$pmux") && bit.port == "\\S") - forbidden_controls_cache[cell].insert(bit.cell->getPort("\\S").extract(bit.offset, 1)); + if ((bit.cell->type == ID($mux) || bit.cell->type == ID($pmux)) && bit.port == ID(S)) + forbidden_controls_cache[cell].insert(bit.cell->getPort(ID(S)).extract(bit.offset, 1)); consumer_cells.insert(bit.cell); } @@ -874,7 +874,7 @@ struct ShareWorker } for (auto &pbit : modwalker.signal_consumers[bit]) { log_assert(fwd_ct.cell_known(pbit.cell->type)); - if ((pbit.cell->type == "$mux" || pbit.cell->type == "$pmux") && (pbit.port == "\\A" || pbit.port == "\\B")) + if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID(A) || pbit.port == ID(B))) driven_data_muxes.insert(pbit.cell); else driven_cells.insert(pbit.cell); @@ -890,10 +890,10 @@ struct ShareWorker bool used_in_a = false; std::set used_in_b_parts; - int width = c->parameters.at("\\WIDTH").as_int(); - std::vector sig_a = modwalker.sigmap(c->getPort("\\A")); - std::vector sig_b = modwalker.sigmap(c->getPort("\\B")); - std::vector sig_s = modwalker.sigmap(c->getPort("\\S")); + int width = c->parameters.at(ID(WIDTH)).as_int(); + std::vector sig_a = modwalker.sigmap(c->getPort(ID(A))); + std::vector sig_b = modwalker.sigmap(c->getPort(ID(B))); + std::vector sig_s = modwalker.sigmap(c->getPort(ID(S))); for (auto &bit : sig_a) if (cell_out_bits.count(bit)) @@ -1132,14 +1132,14 @@ struct ShareWorker fwd_ct.setup_internals(); cone_ct.setup_internals(); - cone_ct.cell_types.erase("$mul"); - cone_ct.cell_types.erase("$mod"); - cone_ct.cell_types.erase("$div"); - cone_ct.cell_types.erase("$pow"); - cone_ct.cell_types.erase("$shl"); - cone_ct.cell_types.erase("$shr"); - cone_ct.cell_types.erase("$sshl"); - cone_ct.cell_types.erase("$sshr"); + cone_ct.cell_types.erase(ID($mul)); + cone_ct.cell_types.erase(ID($mod)); + cone_ct.cell_types.erase(ID($div)); + cone_ct.cell_types.erase(ID($pow)); + cone_ct.cell_types.erase(ID($shl)); + cone_ct.cell_types.erase(ID($shr)); + cone_ct.cell_types.erase(ID($sshl)); + cone_ct.cell_types.erase(ID($sshr)); modwalker.setup(design, module); @@ -1153,9 +1153,9 @@ struct ShareWorker GetSize(shareable_cells), log_id(module)); for (auto cell : module->cells()) - if (cell->type == "$pmux") - for (auto bit : cell->getPort("\\S")) - for (auto other_bit : cell->getPort("\\S")) + if (cell->type == ID($pmux)) + for (auto bit : cell->getPort(ID(S))) + for (auto other_bit : cell->getPort(ID(S))) if (bit < other_bit) exclusive_ctrls.push_back(std::pair(bit, other_bit)); @@ -1466,43 +1466,43 @@ struct SharePass : public Pass { config.opt_aggressive = false; config.opt_fast = false; - config.generic_uni_ops.insert("$not"); - // config.generic_uni_ops.insert("$pos"); - config.generic_uni_ops.insert("$neg"); - - config.generic_cbin_ops.insert("$and"); - config.generic_cbin_ops.insert("$or"); - config.generic_cbin_ops.insert("$xor"); - config.generic_cbin_ops.insert("$xnor"); - - config.generic_bin_ops.insert("$shl"); - config.generic_bin_ops.insert("$shr"); - config.generic_bin_ops.insert("$sshl"); - config.generic_bin_ops.insert("$sshr"); - - config.generic_bin_ops.insert("$lt"); - config.generic_bin_ops.insert("$le"); - config.generic_bin_ops.insert("$eq"); - config.generic_bin_ops.insert("$ne"); - config.generic_bin_ops.insert("$eqx"); - config.generic_bin_ops.insert("$nex"); - config.generic_bin_ops.insert("$ge"); - config.generic_bin_ops.insert("$gt"); - - config.generic_cbin_ops.insert("$add"); - config.generic_cbin_ops.insert("$mul"); - - config.generic_bin_ops.insert("$sub"); - config.generic_bin_ops.insert("$div"); - config.generic_bin_ops.insert("$mod"); - // config.generic_bin_ops.insert("$pow"); - - config.generic_uni_ops.insert("$logic_not"); - config.generic_cbin_ops.insert("$logic_and"); - config.generic_cbin_ops.insert("$logic_or"); - - config.generic_other_ops.insert("$alu"); - config.generic_other_ops.insert("$macc"); + config.generic_uni_ops.insert(ID($not)); + // config.generic_uni_ops.insert(ID($pos)); + config.generic_uni_ops.insert(ID($neg)); + + config.generic_cbin_ops.insert(ID($and)); + config.generic_cbin_ops.insert(ID($or)); + config.generic_cbin_ops.insert(ID($xor)); + config.generic_cbin_ops.insert(ID($xnor)); + + config.generic_bin_ops.insert(ID($shl)); + config.generic_bin_ops.insert(ID($shr)); + config.generic_bin_ops.insert(ID($sshl)); + config.generic_bin_ops.insert(ID($sshr)); + + config.generic_bin_ops.insert(ID($lt)); + config.generic_bin_ops.insert(ID($le)); + config.generic_bin_ops.insert(ID($eq)); + config.generic_bin_ops.insert(ID($ne)); + config.generic_bin_ops.insert(ID($eqx)); + config.generic_bin_ops.insert(ID($nex)); + config.generic_bin_ops.insert(ID($ge)); + config.generic_bin_ops.insert(ID($gt)); + + config.generic_cbin_ops.insert(ID($add)); + config.generic_cbin_ops.insert(ID($mul)); + + config.generic_bin_ops.insert(ID($sub)); + config.generic_bin_ops.insert(ID($div)); + config.generic_bin_ops.insert(ID($mod)); + // config.generic_bin_ops.insert(ID($pow)); + + config.generic_uni_ops.insert(ID($logic_not)); + config.generic_cbin_ops.insert(ID($logic_and)); + config.generic_cbin_ops.insert(ID($logic_or)); + + config.generic_other_ops.insert(ID($alu)); + config.generic_other_ops.insert(ID($macc)); log_header(design, "Executing SHARE pass (SAT-based resource sharing).\n"); diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 1eeca2748..ca0be54d2 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -34,13 +34,13 @@ struct WreduceConfig WreduceConfig() { supported_cell_types = pool({ - "$not", "$pos", "$neg", - "$and", "$or", "$xor", "$xnor", - "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", - "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", - "$add", "$sub", "$mul", // "$div", "$mod", "$pow", - "$mux", "$pmux", - "$dff", "$adff" + ID($not), ID($pos), ID($neg), + ID($and), ID($or), ID($xor), ID($xnor), + ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx), + ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), + ID($add), ID($sub), ID($mul), // ID($div), ID($mod), ID($pow), + ID($mux), ID($pmux), + ID($dff), ID($adff) }); } }; @@ -64,10 +64,10 @@ struct WreduceWorker { // Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused - SigSpec sig_a = mi.sigmap(cell->getPort("\\A")); - SigSpec sig_b = mi.sigmap(cell->getPort("\\B")); - SigSpec sig_s = mi.sigmap(cell->getPort("\\S")); - SigSpec sig_y = mi.sigmap(cell->getPort("\\Y")); + SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))); + SigSpec sig_b = mi.sigmap(cell->getPort(ID(B))); + SigSpec sig_s = mi.sigmap(cell->getPort(ID(S))); + SigSpec sig_y = mi.sigmap(cell->getPort(ID(Y))); std::vector bits_removed; if (sig_y.has_const()) @@ -130,9 +130,9 @@ struct WreduceWorker for (auto bit : new_work_queue_bits) work_queue_bits.insert(bit); - cell->setPort("\\A", new_sig_a); - cell->setPort("\\B", new_sig_b); - cell->setPort("\\Y", new_sig_y); + cell->setPort(ID(A), new_sig_a); + cell->setPort(ID(B), new_sig_b); + cell->setPort(ID(Y), new_sig_y); cell->fixup_parameters(); module->connect(sig_y.extract(n_kept, n_removed), sig_removed); @@ -142,8 +142,8 @@ struct WreduceWorker { // Reduce size of FF if inputs are just sign/zero extended or output bit is not used - SigSpec sig_d = mi.sigmap(cell->getPort("\\D")); - SigSpec sig_q = mi.sigmap(cell->getPort("\\Q")); + SigSpec sig_d = mi.sigmap(cell->getPort(ID(D))); + SigSpec sig_q = mi.sigmap(cell->getPort(ID(Q))); Const initval; int width_before = GetSize(sig_q); @@ -214,14 +214,14 @@ struct WreduceWorker work_queue_bits.insert(bit); // Narrow ARST_VALUE parameter to new size. - if (cell->parameters.count("\\ARST_VALUE")) { - Const arst_value = cell->getParam("\\ARST_VALUE"); + if (cell->parameters.count(ID(ARST_VALUE))) { + Const arst_value = cell->getParam(ID(ARST_VALUE)); arst_value.bits.resize(GetSize(sig_q)); - cell->setParam("\\ARST_VALUE", arst_value); + cell->setParam(ID(ARST_VALUE), arst_value); } - cell->setPort("\\D", sig_d); - cell->setPort("\\Q", sig_q); + cell->setPort(ID(D), sig_d); + cell->setPort(ID(Q), sig_q); cell->fixup_parameters(); } @@ -230,7 +230,7 @@ struct WreduceWorker port_signed = cell->getParam(stringf("\\%c_SIGNED", port)).as_bool(); SigSpec sig = mi.sigmap(cell->getPort(stringf("\\%c", port))); - if (port == 'B' && cell->type.in("$shl", "$shr", "$sshl", "$sshr")) + if (port == 'B' && cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) port_signed = false; int bits_removed = 0; @@ -264,13 +264,13 @@ struct WreduceWorker if (!cell->type.in(config->supported_cell_types)) return; - if (cell->type.in("$mux", "$pmux")) + if (cell->type.in(ID($mux), ID($pmux))) return run_cell_mux(cell); - if (cell->type.in("$dff", "$adff")) + if (cell->type.in(ID($dff), ID($adff))) return run_cell_dff(cell); - SigSpec sig = mi.sigmap(cell->getPort("\\Y")); + SigSpec sig = mi.sigmap(cell->getPort(ID(Y))); if (sig.has_const()) return; @@ -278,10 +278,10 @@ struct WreduceWorker // Reduce size of ports A and B based on constant input bits and size of output port - int max_port_a_size = cell->hasPort("\\A") ? GetSize(cell->getPort("\\A")) : -1; - int max_port_b_size = cell->hasPort("\\B") ? GetSize(cell->getPort("\\B")) : -1; + int max_port_a_size = cell->hasPort(ID(A)) ? GetSize(cell->getPort(ID(A))) : -1; + int max_port_b_size = cell->hasPort(ID(B)) ? GetSize(cell->getPort(ID(B))) : -1; - if (cell->type.in("$not", "$pos", "$neg", "$and", "$or", "$xor", "$add", "$sub")) { + if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) { max_port_a_size = min(max_port_a_size, GetSize(sig)); max_port_b_size = min(max_port_b_size, GetSize(sig)); } @@ -289,32 +289,32 @@ struct WreduceWorker bool port_a_signed = false; bool port_b_signed = false; - if (max_port_a_size >= 0 && cell->type != "$shiftx") + if (max_port_a_size >= 0 && cell->type != ID($shiftx)) run_reduce_inport(cell, 'A', max_port_a_size, port_a_signed, did_something); if (max_port_b_size >= 0) run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something); - if (cell->hasPort("\\A") && cell->hasPort("\\B") && port_a_signed && port_b_signed) { - SigSpec sig_a = mi.sigmap(cell->getPort("\\A")), sig_b = mi.sigmap(cell->getPort("\\B")); + if (cell->hasPort(ID(A)) && cell->hasPort(ID(B)) && port_a_signed && port_b_signed) { + SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))), sig_b = mi.sigmap(cell->getPort(ID(B))); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 && GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", log_id(module), log_id(cell), log_id(cell->type)); - cell->setParam("\\A_SIGNED", 0); - cell->setParam("\\B_SIGNED", 0); + cell->setParam(ID(A_SIGNED), 0); + cell->setParam(ID(B_SIGNED), 0); port_a_signed = false; port_b_signed = false; did_something = true; } } - if (cell->hasPort("\\A") && !cell->hasPort("\\B") && port_a_signed) { - SigSpec sig_a = mi.sigmap(cell->getPort("\\A")); + if (cell->hasPort(ID(A)) && !cell->hasPort(ID(B)) && port_a_signed) { + SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", log_id(module), log_id(cell), log_id(cell->type)); - cell->setParam("\\A_SIGNED", 0); + cell->setParam(ID(A_SIGNED), 0); port_a_signed = false; did_something = true; } @@ -324,7 +324,7 @@ struct WreduceWorker // Reduce size of port Y based on sizes for A and B and unused bits in Y int bits_removed = 0; - if (port_a_signed && cell->type == "$shr") { + if (port_a_signed && cell->type == ID($shr)) { // do not reduce size of output on $shr cells with signed A inputs } else { while (GetSize(sig) > 0) @@ -342,20 +342,20 @@ struct WreduceWorker } } - if (cell->type.in("$pos", "$add", "$mul", "$and", "$or", "$xor", "$sub")) + if (cell->type.in(ID($pos), ID($add), ID($mul), ID($and), ID($or), ID($xor), ID($sub))) { - bool is_signed = cell->getParam("\\A_SIGNED").as_bool() || cell->type == "$sub"; + bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub); int a_size = 0, b_size = 0; - if (cell->hasPort("\\A")) a_size = GetSize(cell->getPort("\\A")); - if (cell->hasPort("\\B")) b_size = GetSize(cell->getPort("\\B")); + if (cell->hasPort(ID(A))) a_size = GetSize(cell->getPort(ID(A))); + if (cell->hasPort(ID(B))) b_size = GetSize(cell->getPort(ID(B))); int max_y_size = max(a_size, b_size); - if (cell->type.in("$add", "$sub")) + if (cell->type.in(ID($add), ID($sub))) max_y_size++; - if (cell->type == "$mul") + if (cell->type == ID($mul)) max_y_size = a_size + b_size; while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) { @@ -374,7 +374,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); - cell->setPort("\\Y", sig); + cell->setPort(ID(Y), sig); did_something = true; } @@ -387,8 +387,8 @@ struct WreduceWorker static int count_nontrivial_wire_attrs(RTLIL::Wire *w) { int count = w->attributes.size(); - count -= w->attributes.count("\\src"); - count -= w->attributes.count("\\unused_bits"); + count -= w->attributes.count(ID(src)); + count -= w->attributes.count(ID(unused_bits)); return count; } @@ -398,11 +398,11 @@ struct WreduceWorker SigMap init_attr_sigmap = mi.sigmap; for (auto w : module->wires()) { - if (w->get_bool_attribute("\\keep")) + if (w->get_bool_attribute(ID(keep))) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); - if (w->attributes.count("\\init")) { - Const initval = w->attributes.at("\\init"); + if (w->attributes.count(ID(init))) { + Const initval = w->attributes.at(ID(init)); SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); for (int i = 0; i < width; i++) @@ -459,8 +459,8 @@ struct WreduceWorker if (!remove_init_bits.empty()) { for (auto w : module->wires()) { - if (w->attributes.count("\\init")) { - Const initval = w->attributes.at("\\init"); + if (w->attributes.count(ID(init))) { + Const initval = w->attributes.at(ID(init)); Const new_initval(State::Sx, GetSize(w)); SigSpec initsig = init_attr_sigmap(w); int width = std::min(GetSize(initval), GetSize(initsig)); @@ -468,7 +468,7 @@ struct WreduceWorker if (!remove_init_bits.count(initsig[i])) new_initval[i] = initval[i]; } - w->attributes.at("\\init") = new_initval; + w->attributes.at(ID(init)) = new_initval; } } } @@ -528,23 +528,23 @@ struct WreducePass : public Pass { for (auto c : module->selected_cells()) { - if (c->type.in("$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", - "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt", - "$logic_not", "$logic_and", "$logic_or") && GetSize(c->getPort("\\Y")) > 1) { - SigSpec sig = c->getPort("\\Y"); + if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), + ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), + ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID(Y))) > 1) { + SigSpec sig = c->getPort(ID(Y)); if (!sig.has_const()) { - c->setPort("\\Y", sig[0]); - c->setParam("\\Y_WIDTH", 1); + c->setPort(ID(Y), sig[0]); + c->setParam(ID(Y_WIDTH), 1); sig.remove(0); module->connect(sig, Const(0, GetSize(sig))); } } - if (c->type.in("$div", "$mod", "$pow")) + if (c->type.in(ID($div), ID($mod), ID($pow))) { - SigSpec A = c->getPort("\\A"); + SigSpec A = c->getPort(ID(A)); int original_a_width = GetSize(A); - if (c->getParam("\\A_SIGNED").as_bool()) { + if (c->getParam(ID(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 { @@ -554,13 +554,13 @@ struct WreducePass : public Pass { 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)); + c->setPort(ID(A), A); + c->setParam(ID(A_WIDTH), GetSize(A)); } - SigSpec B = c->getPort("\\B"); + SigSpec B = c->getPort(ID(B)); int original_b_width = GetSize(B); - if (c->getParam("\\B_SIGNED").as_bool()) { + if (c->getParam(ID(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 { @@ -570,24 +570,24 @@ struct WreducePass : public Pass { 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)); + c->setPort(ID(B), B); + c->setParam(ID(B_WIDTH), GetSize(B)); } } - if (!opt_memx && c->type.in("$memrd", "$memwr", "$meminit")) { - IdString memid = c->getParam("\\MEMID").decode_string(); + if (!opt_memx && c->type.in(ID($memrd), ID($memwr), ID($meminit))) { + IdString memid = c->getParam(ID(MEMID)).decode_string(); RTLIL::Memory *mem = module->memories.at(memid); if (mem->start_offset >= 0) { - int cur_addrbits = c->getParam("\\ABITS").as_int(); + int cur_addrbits = c->getParam(ID(ABITS)).as_int(); int max_addrbits = ceil_log2(mem->start_offset + mem->size); if (cur_addrbits > max_addrbits) { log("Removed top %d address bits (of %d) from memory %s port %s.%s (%s).\n", cur_addrbits-max_addrbits, cur_addrbits, - c->type == "$memrd" ? "read" : c->type == "$memwr" ? "write" : "init", + c->type == ID($memrd) ? "read" : c->type == ID($memwr) ? "write" : "init", log_id(module), log_id(c), log_id(memid)); - c->setParam("\\ABITS", max_addrbits); - c->setPort("\\ADDR", c->getPort("\\ADDR").extract(0, max_addrbits)); + c->setParam(ID(ABITS), max_addrbits); + c->setPort(ID(ADDR), c->getPort(ID(ADDR)).extract(0, max_addrbits)); } } } -- cgit v1.2.3 From 0c5db07cd6cc3c19b926da21a46599f97592b20f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sun, 11 Aug 2019 23:25:46 +0200 Subject: Fix various NDEBUG compiler warnings, closes #1255 Signed-off-by: Clifford Wolf --- passes/opt/opt_expr.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b2dc9a448..1512cea1b 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -117,7 +117,8 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) } } -void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) +void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, + const std::string &info YS_ATTRIBUTE(unused), IdString out_port, RTLIL::SigSpec out_val) { RTLIL::SigSpec Y = cell->getPort(out_port); out_val.extend_u0(Y.size(), false); -- cgit v1.2.3 From 467c34eff05bd62fd64c35f07fe140f33edf4511 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 10:24:35 -0700 Subject: Convert a few more to ID --- passes/opt/opt_expr.cc | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index fcdc1d173..330c56e22 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -478,19 +478,19 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (detect_const_and && (found_zero || found_inv)) { cover("opt.opt_expr.const_and"); - replace_cell(assign_map, module, cell, "const_and", "\\Y", RTLIL::State::S0); + replace_cell(assign_map, module, cell, "const_and", ID(Y), RTLIL::State::S0); goto next_cell; } if (detect_const_or && (found_one || found_inv)) { cover("opt.opt_expr.const_or"); - replace_cell(assign_map, module, cell, "const_or", "\\Y", RTLIL::State::S1); + replace_cell(assign_map, module, cell, "const_or", ID(Y), RTLIL::State::S1); goto next_cell; } if (non_const_input != State::Sm && !found_undef) { cover("opt.opt_expr.and_or_buffer"); - replace_cell(assign_map, module, cell, "and_or_buffer", "\\Y", non_const_input); + replace_cell(assign_map, module, cell, "and_or_buffer", ID(Y), non_const_input); goto next_cell; } } @@ -506,7 +506,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } else { cover("opt.opt_expr.unary_buffer"); - replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort("\\A")); + replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort(ID(A))); } goto next_cell; } @@ -669,13 +669,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == "$alu") { - RTLIL::SigSpec sig_a = assign_map(cell->getPort("\\A")); - RTLIL::SigSpec sig_b = assign_map(cell->getPort("\\B")); - RTLIL::SigBit sig_ci = assign_map(cell->getPort("\\CI")); - RTLIL::SigBit sig_bi = assign_map(cell->getPort("\\BI")); - RTLIL::SigSpec sig_x = cell->getPort("\\X"); - RTLIL::SigSpec sig_y = cell->getPort("\\Y"); - RTLIL::SigSpec sig_co = cell->getPort("\\CO"); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI))); + RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI))); + RTLIL::SigSpec sig_x = cell->getPort(ID(X)); + RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); + RTLIL::SigSpec sig_co = cell->getPort(ID(CO)); if (sig_ci.wire || sig_bi.wire) goto next_cell; @@ -704,11 +704,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (i > 0) { cover("opt.opt_expr.fine.$alu"); - cell->setPort("\\A", sig_a.extract_end(i)); - cell->setPort("\\B", sig_b.extract_end(i)); - cell->setPort("\\X", sig_x.extract_end(i)); - cell->setPort("\\Y", sig_y.extract_end(i)); - cell->setPort("\\CO", sig_co.extract_end(i)); + cell->setPort(ID(A), sig_a.extract_end(i)); + cell->setPort(ID(B), sig_b.extract_end(i)); + cell->setPort(ID(X), sig_x.extract_end(i)); + cell->setPort(ID(Y), sig_y.extract_end(i)); + cell->setPort(ID(CO), sig_co.extract_end(i)); cell->fixup_parameters(); did_something = true; } @@ -737,9 +737,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str()); if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt))) - replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::State::Sx); + replace_cell(assign_map, module, cell, "x-bit in input", ID(Y), RTLIL::State::Sx); else - replace_cell(assign_map, module, cell, "x-bit in input", "\\Y", RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort("\\Y").size())); + replace_cell(assign_map, module, cell, "x-bit in input", ID(Y), RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID(Y)).size())); goto next_cell; } } @@ -747,7 +747,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID(Y)).size() == 1 && invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); - replace_cell(assign_map, module, cell, "double_invert", "\\Y", invert_map.at(assign_map(cell->getPort("\\A")))); + replace_cell(assign_map, module, cell, "double_invert", ID(Y), invert_map.at(assign_map(cell->getPort(ID("A"))))); goto next_cell; } @@ -890,7 +890,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1); new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); - replace_cell(assign_map, module, cell, "isneq", "\\Y", new_y); + replace_cell(assign_map, module, cell, "isneq", ID(Y), new_y); goto next_cell; } if (a[i] == b[i]) -- cgit v1.2.3 From 6cd8cace0c1d2a9f7b1f1cd56a223c38a5ea799a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 11:25:42 -0700 Subject: Fix --- passes/opt/opt_expr.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 330c56e22..6dea611e3 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -506,7 +506,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } else { cover("opt.opt_expr.unary_buffer"); - replace_cell(assign_map, module, cell, "unary_buffer", "\\Y", cell->getPort(ID(A))); + replace_cell(assign_map, module, cell, "unary_buffer", ID(Y), cell->getPort(ID(A))); } goto next_cell; } @@ -747,7 +747,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID(Y)).size() == 1 && invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); - replace_cell(assign_map, module, cell, "double_invert", ID(Y), invert_map.at(assign_map(cell->getPort(ID("A"))))); + replace_cell(assign_map, module, cell, "double_invert", ID(Y), invert_map.at(assign_map(cell->getPort(ID(A))))); goto next_cell; } -- cgit v1.2.3 From 52355f5185fe42e28775e897f458b38a439c0ec5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 14:50:10 -0700 Subject: Use more ID::{A,B,Y,blackbox,whitebox} --- passes/opt/muxpack.cc | 38 +++--- passes/opt/opt_clean.cc | 6 +- passes/opt/opt_demorgan.cc | 14 +- passes/opt/opt_expr.cc | 318 ++++++++++++++++++++++----------------------- passes/opt/opt_lut.cc | 28 ++-- passes/opt/opt_merge.cc | 48 +++---- passes/opt/opt_muxtree.cc | 24 ++-- passes/opt/opt_reduce.cc | 66 +++++----- passes/opt/opt_rmdff.cc | 8 +- passes/opt/pmux2shiftx.cc | 30 ++--- passes/opt/share.cc | 70 +++++----- passes/opt/wreduce.cc | 46 +++---- 12 files changed, 348 insertions(+), 348 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index cf6752b6e..97c88f423 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -38,19 +38,19 @@ struct ExclusiveDatabase pool reduce_or; for (auto cell : module->cells()) { if (cell->type == ID($eq)) { - nonconst_sig = sigmap(cell->getPort(ID(A))); - const_sig = sigmap(cell->getPort(ID(B))); + nonconst_sig = sigmap(cell->getPort(ID::A)); + const_sig = sigmap(cell->getPort(ID::B)); if (!const_sig.is_fully_const()) { if (!nonconst_sig.is_fully_const()) continue; std::swap(nonconst_sig, const_sig); } - y_port = sigmap(cell->getPort(ID(Y))); + y_port = sigmap(cell->getPort(ID::Y)); } else if (cell->type == ID($logic_not)) { - nonconst_sig = sigmap(cell->getPort(ID(A))); + nonconst_sig = sigmap(cell->getPort(ID::A)); const_sig = Const(State::S0, GetSize(nonconst_sig)); - y_port = sigmap(cell->getPort(ID(Y))); + y_port = sigmap(cell->getPort(ID::Y)); } else if (cell->type == ID($reduce_or)) { reduce_or.insert(cell); @@ -66,7 +66,7 @@ struct ExclusiveDatabase for (auto cell : reduce_or) { nonconst_sig = SigSpec(); std::vector values; - SigSpec a_port = sigmap(cell->getPort(ID(A))); + SigSpec a_port = sigmap(cell->getPort(ID::A)); for (auto bit : a_port) { auto it = sig_cmp_prev.find(bit); if (it == sig_cmp_prev.end()) { @@ -84,7 +84,7 @@ struct ExclusiveDatabase } if (nonconst_sig.empty()) continue; - y_port = sigmap(cell->getPort(ID(Y))); + y_port = sigmap(cell->getPort(ID::Y)); sig_cmp_prev[y_port] = std::make_pair(nonconst_sig,std::move(values)); } } @@ -145,11 +145,11 @@ struct MuxpackWorker { if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep))) { - SigSpec a_sig = sigmap(cell->getPort(ID(A))); + SigSpec a_sig = sigmap(cell->getPort(ID::A)); SigSpec b_sig; if (cell->type == ID($mux)) - b_sig = sigmap(cell->getPort(ID(B))); - SigSpec y_sig = sigmap(cell->getPort(ID(Y))); + b_sig = sigmap(cell->getPort(ID::B)); + SigSpec y_sig = sigmap(cell->getPort(ID::Y)); if (sig_chain_next.count(a_sig)) for (auto a_bit : a_sig.bits()) @@ -186,9 +186,9 @@ struct MuxpackWorker { log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type)); - SigSpec a_sig = sigmap(cell->getPort(ID(A))); + SigSpec a_sig = sigmap(cell->getPort(ID::A)); if (cell->type == ID($mux)) { - SigSpec b_sig = sigmap(cell->getPort(ID(B))); + SigSpec b_sig = sigmap(cell->getPort(ID::B)); if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1) goto start_cell; @@ -230,7 +230,7 @@ struct MuxpackWorker { chain.push_back(c); - SigSpec y_sig = sigmap(c->getPort(ID(Y))); + SigSpec y_sig = sigmap(c->getPort(ID::Y)); if (sig_chain_next.count(y_sig) == 0) break; @@ -270,28 +270,28 @@ struct MuxpackWorker pmux_count += 1; first_cell->type = ID($pmux); - SigSpec b_sig = first_cell->getPort(ID(B)); + SigSpec b_sig = first_cell->getPort(ID::B); SigSpec s_sig = first_cell->getPort(ID(S)); for (int i = 1; i < cases; i++) { Cell* prev_cell = chain[cursor+i-1]; Cell* cursor_cell = chain[cursor+i]; - if (sigmap(prev_cell->getPort(ID(Y))) == sigmap(cursor_cell->getPort(ID(A)))) { - b_sig.append(cursor_cell->getPort(ID(B))); + if (sigmap(prev_cell->getPort(ID::Y)) == sigmap(cursor_cell->getPort(ID::A))) { + b_sig.append(cursor_cell->getPort(ID::B)); s_sig.append(cursor_cell->getPort(ID(S))); } else { log_assert(cursor_cell->type == ID($mux)); - b_sig.append(cursor_cell->getPort(ID(A))); + b_sig.append(cursor_cell->getPort(ID::A)); s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort(ID(S)))); } remove_cells.insert(cursor_cell); } - first_cell->setPort(ID(B), b_sig); + first_cell->setPort(ID::B, b_sig); first_cell->setPort(ID(S), s_sig); first_cell->setParam(ID(S_WIDTH), GetSize(s_sig)); - first_cell->setPort(ID(Y), last_cell->getPort(ID(Y))); + first_cell->setPort(ID::Y, last_cell->getPort(ID::Y)); cursor += cases; } diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index 1d3a85b3a..bf75c7adc 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -482,8 +482,8 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool for (auto cell : module->cells()) if (cell->type.in(ID($pos), ID($_BUF_)) && !cell->has_keep_attr()) { bool is_signed = cell->type == ID($pos) && cell->getParam(ID(A_SIGNED)).as_bool(); - RTLIL::SigSpec a = cell->getPort(ID(A)); - RTLIL::SigSpec y = cell->getPort(ID(Y)); + RTLIL::SigSpec a = cell->getPort(ID::A); + RTLIL::SigSpec y = cell->getPort(ID::Y); a.extend_u0(GetSize(y), is_signed); module->connect(y, a); delcells.push_back(cell); @@ -491,7 +491,7 @@ void rmunused_module(RTLIL::Module *module, bool purge_mode, bool verbose, bool for (auto cell : delcells) { if (verbose) log_debug(" removing buffer cell `%s': %s = %s\n", cell->name.c_str(), - log_signal(cell->getPort(ID(Y))), log_signal(cell->getPort(ID(A)))); + log_signal(cell->getPort(ID::Y)), log_signal(cell->getPort(ID::A))); module->remove(cell); } if (!delcells.empty()) diff --git a/passes/opt/opt_demorgan.cc b/passes/opt/opt_demorgan.cc index 7defef442..4bc82815b 100644 --- a/passes/opt/opt_demorgan.cc +++ b/passes/opt/opt_demorgan.cc @@ -38,7 +38,7 @@ void demorgan_worker( if( (cell->type != ID($reduce_and)) && (cell->type != ID($reduce_or)) ) return; - auto insig = sigmap(cell->getPort(ID(A))); + auto insig = sigmap(cell->getPort(ID::A)); log("Inspecting %s cell %s (%d inputs)\n", log_id(cell->type), log_id(cell->name), GetSize(insig)); int num_inverted = 0; for(int i=0; itype == ID($_NOT_)) + if(x.port == ID::Y && x.cell->type == ID($_NOT_)) { inverted = true; break; @@ -85,7 +85,7 @@ void demorgan_worker( RTLIL::Cell* srcinv = NULL; for(auto x : ports) { - if(x.port == ID(Y) && x.cell->type == ID($_NOT_)) + if(x.port == ID::Y && x.cell->type == ID($_NOT_)) { srcinv = x.cell; break; @@ -103,7 +103,7 @@ void demorgan_worker( //We ARE inverted - bypass it //Don't automatically delete the inverter since other stuff might still use it else - insig[i] = srcinv->getPort(ID(A)); + insig[i] = srcinv->getPort(ID::A); } //Cosmetic fixup: If our input is just a scrambled version of one bus, rearrange it @@ -151,7 +151,7 @@ void demorgan_worker( } //Push the new input signal back to the reduction (after bypassing/adding inverters) - cell->setPort(ID(A), insig); + cell->setPort(ID::A, insig); //Change the cell type if(cell->type == ID($reduce_and)) @@ -161,10 +161,10 @@ void demorgan_worker( //don't change XOR //Add an inverter to the output - auto inverted_output = cell->getPort(ID(Y)); + auto inverted_output = cell->getPort(ID::Y); auto uninverted_output = m->addWire(NEW_ID); m->addNot(NEW_ID, RTLIL::SigSpec(uninverted_output), inverted_output); - cell->setPort(ID(Y), uninverted_output); + cell->setPort(ID::Y, uninverted_output); } struct OptDemorganPass : public Pass { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 6dea611e3..85ec9a55a 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -134,14 +134,14 @@ void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutative, SigMap &sigmap) { - IdString b_name = cell->hasPort(ID(B)) ? ID(B) : ID(A); + IdString b_name = cell->hasPort(ID::B) ? ID::B : ID::A; bool a_signed = cell->parameters.at(ID(A_SIGNED)).as_bool(); bool b_signed = cell->parameters.at(b_name.str() + "_SIGNED").as_bool(); - RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = sigmap(cell->getPort(ID::A)); RTLIL::SigSpec sig_b = sigmap(cell->getPort(b_name)); - RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID(Y))); + RTLIL::SigSpec sig_y = sigmap(cell->getPort(ID::Y)); sig_a.extend_u0(sig_y.size(), a_signed); sig_b.extend_u0(sig_y.size(), b_signed); @@ -208,24 +208,24 @@ bool group_cell_inputs(RTLIL::Module *module, RTLIL::Cell *cell, bool commutativ RTLIL::Cell *c = module->addCell(NEW_ID, cell->type); - c->setPort(ID(A), new_a); + c->setPort(ID::A, new_a); c->parameters[ID(A_WIDTH)] = new_a.size(); c->parameters[ID(A_SIGNED)] = false; - if (b_name == ID(B)) { - c->setPort(ID(B), new_b); + if (b_name == ID::B) { + c->setPort(ID::B, new_b); c->parameters[ID(B_WIDTH)] = new_b.size(); c->parameters[ID(B_SIGNED)] = false; } - c->setPort(ID(Y), new_y); + c->setPort(ID::Y, new_y); c->parameters[ID(Y_WIDTH)] = new_y->width; c->check(); module->connect(new_conn); log_debug(" New cell `%s': A=%s", log_id(c), log_signal(new_a)); - if (b_name == ID(B)) + if (b_name == ID::B) log_debug(", B=%s", log_signal(new_b)); log_debug("\n"); } @@ -368,11 +368,11 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : module->cells()) if (design->selected(module, cell) && cell->type[0] == '$') { if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && - cell->getPort(ID(A)).size() == 1 && cell->getPort(ID(Y)).size() == 1) - invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(A))); + cell->getPort(ID::A).size() == 1 && cell->getPort(ID::Y).size() == 1) + invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A)); if (cell->type.in(ID($mux), ID($_MUX_)) && - cell->getPort(ID(A)) == SigSpec(State::S1) && cell->getPort(ID(B)) == SigSpec(State::S0)) - invert_map[assign_map(cell->getPort(ID(Y)))] = assign_map(cell->getPort(ID(S))); + cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0)) + invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID(S))); if (ct_combinational.cell_known(cell->type)) for (auto &conn : cell->connections()) { RTLIL::SigSpec sig = assign_map(conn.second); @@ -396,7 +396,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : cells.sorted) { #define ACTION_DO(_p_, _s_) do { cover("opt.opt_expr.action_" S__LINE__); replace_cell(assign_map, module, cell, input.as_string(), _p_, _s_); goto next_cell; } while (0) -#define ACTION_DO_Y(_v_) ACTION_DO(ID(Y), RTLIL::SigSpec(RTLIL::State::S ## _v_)) +#define ACTION_DO_Y(_v_) ACTION_DO(ID::Y, RTLIL::SigSpec(RTLIL::State::S ## _v_)) if (clkinv) { @@ -439,23 +439,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($reduce_and), ID($_AND_))) detect_const_and = true; - if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) + if (cell->type.in(ID($and), ID($logic_and)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_and = true; if (cell->type.in(ID($reduce_or), ID($reduce_bool), ID($_OR_))) detect_const_or = true; - if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(B))) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) + if (cell->type.in(ID($or), ID($logic_or)) && GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::B)) == 1 && !cell->getParam(ID(A_SIGNED)).as_bool()) detect_const_or = true; if (detect_const_and || detect_const_or) { - pool input_bits = assign_map(cell->getPort(ID(A))).to_sigbit_pool(); + pool input_bits = assign_map(cell->getPort(ID::A)).to_sigbit_pool(); bool found_zero = false, found_one = false, found_undef = false, found_inv = false, many_conconst = false; SigBit non_const_input = State::Sm; - if (cell->hasPort(ID(B))) { - vector more_bits = assign_map(cell->getPort(ID(B))).to_sigbit_vector(); + if (cell->hasPort(ID::B)) { + vector more_bits = assign_map(cell->getPort(ID::B)).to_sigbit_vector(); input_bits.insert(more_bits.begin(), more_bits.end()); } @@ -478,25 +478,25 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (detect_const_and && (found_zero || found_inv)) { cover("opt.opt_expr.const_and"); - replace_cell(assign_map, module, cell, "const_and", ID(Y), RTLIL::State::S0); + replace_cell(assign_map, module, cell, "const_and", ID::Y, RTLIL::State::S0); goto next_cell; } if (detect_const_or && (found_one || found_inv)) { cover("opt.opt_expr.const_or"); - replace_cell(assign_map, module, cell, "const_or", ID(Y), RTLIL::State::S1); + replace_cell(assign_map, module, cell, "const_or", ID::Y, RTLIL::State::S1); goto next_cell; } if (non_const_input != State::Sm && !found_undef) { cover("opt.opt_expr.and_or_buffer"); - replace_cell(assign_map, module, cell, "and_or_buffer", ID(Y), non_const_input); + replace_cell(assign_map, module, cell, "and_or_buffer", ID::Y, non_const_input); goto next_cell; } } if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool), ID($reduce_xor), ID($reduce_xnor), ID($neg)) && - GetSize(cell->getPort(ID(A))) == 1 && GetSize(cell->getPort(ID(Y))) == 1) + GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1) { if (cell->type == ID($reduce_xnor)) { cover("opt.opt_expr.reduce_xnor_not"); @@ -506,7 +506,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons did_something = true; } else { cover("opt.opt_expr.unary_buffer"); - replace_cell(assign_map, module, cell, "unary_buffer", ID(Y), cell->getPort(ID(A))); + replace_cell(assign_map, module, cell, "unary_buffer", ID::Y, cell->getPort(ID::A)); } goto next_cell; } @@ -521,7 +521,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { SigBit neutral_bit = cell->type == ID($reduce_and) ? State::S1 : State::S0; - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec new_sig_a; for (auto bit : sig_a) @@ -534,7 +534,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.neutral_A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_and", "$reduce_bool", cell->type.str()); log_debug("Replacing port A of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_sig_a)); - cell->setPort(ID(A), new_sig_a); + cell->setPort(ID::A, new_sig_a); cell->parameters.at(ID(A_WIDTH)) = GetSize(new_sig_a); did_something = true; } @@ -544,7 +544,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { SigBit neutral_bit = State::S0; - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); RTLIL::SigSpec new_sig_b; for (auto bit : sig_b) @@ -557,7 +557,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.neutral_B", "$logic_and", "$logic_or", cell->type.str()); log_debug("Replacing port B of %s cell `%s' in module `%s' with shorter expression: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_sig_b)); - cell->setPort(ID(B), new_sig_b); + cell->setPort(ID::B, new_sig_b); cell->parameters.at(ID(B_WIDTH)) = GetSize(new_sig_b); did_something = true; } @@ -565,7 +565,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == ID($reduce_and)) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::State new_a = RTLIL::State::S1; for (auto &bit : sig_a.to_sigbit_vector()) @@ -583,7 +583,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover("opt.opt_expr.fine.$reduce_and"); log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); - cell->setPort(ID(A), sig_a = new_a); + cell->setPort(ID::A, sig_a = new_a); cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } @@ -591,7 +591,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($logic_not), ID($logic_and), ID($logic_or), ID($reduce_or), ID($reduce_bool))) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::State new_a = RTLIL::State::S0; for (auto &bit : sig_a.to_sigbit_vector()) @@ -609,7 +609,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.A", "$logic_not", "$logic_and", "$logic_or", "$reduce_or", "$reduce_bool", cell->type.str()); log_debug("Replacing port A of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_a), log_signal(new_a)); - cell->setPort(ID(A), sig_a = new_a); + cell->setPort(ID::A, sig_a = new_a); cell->parameters.at(ID(A_WIDTH)) = 1; did_something = true; } @@ -617,7 +617,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($logic_and), ID($logic_or))) { - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); RTLIL::State new_b = RTLIL::State::S0; for (auto &bit : sig_b.to_sigbit_vector()) @@ -635,7 +635,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.fine.B", "$logic_and", "$logic_or", cell->type.str()); log_debug("Replacing port B of %s cell `%s' in module `%s' with constant driver: %s -> %s\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str(), log_signal(sig_b), log_signal(new_b)); - cell->setPort(ID(B), sig_b = new_b); + cell->setPort(ID::B, sig_b = new_b); cell->parameters.at(ID(B_WIDTH)) = 1; did_something = true; } @@ -643,9 +643,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($add), ID($sub))) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); - RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); + RTLIL::SigSpec sig_y = cell->getPort(ID::Y); bool sub = cell->type == ID($sub); int i; @@ -659,9 +659,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (i > 0) { cover_list("opt.opt_expr.fine", "$add", "$sub", cell->type.str()); - cell->setPort(ID(A), sig_a.extract_end(i)); - cell->setPort(ID(B), sig_b.extract_end(i)); - cell->setPort(ID(Y), sig_y.extract_end(i)); + cell->setPort(ID::A, sig_a.extract_end(i)); + cell->setPort(ID::B, sig_b.extract_end(i)); + cell->setPort(ID::Y, sig_y.extract_end(i)); cell->fixup_parameters(); did_something = true; } @@ -669,12 +669,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == "$alu") { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); RTLIL::SigBit sig_ci = assign_map(cell->getPort(ID(CI))); RTLIL::SigBit sig_bi = assign_map(cell->getPort(ID(BI))); RTLIL::SigSpec sig_x = cell->getPort(ID(X)); - RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); + RTLIL::SigSpec sig_y = cell->getPort(ID::Y); RTLIL::SigSpec sig_co = cell->getPort(ID(CO)); if (sig_ci.wire || sig_bi.wire) @@ -704,10 +704,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (i > 0) { cover("opt.opt_expr.fine.$alu"); - cell->setPort(ID(A), sig_a.extract_end(i)); - cell->setPort(ID(B), sig_b.extract_end(i)); + cell->setPort(ID::A, sig_a.extract_end(i)); + cell->setPort(ID::B, sig_b.extract_end(i)); cell->setPort(ID(X), sig_x.extract_end(i)); - cell->setPort(ID(Y), sig_y.extract_end(i)); + cell->setPort(ID::Y, sig_y.extract_end(i)); cell->setPort(ID(CO), sig_co.extract_end(i)); cell->fixup_parameters(); did_something = true; @@ -718,8 +718,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($shift), ID($shiftx), ID($shl), ID($shr), ID($sshl), ID($sshr), ID($lt), ID($le), ID($ge), ID($gt), ID($neg), ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($pow))) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec sig_b = cell->hasPort(ID(B)) ? assign_map(cell->getPort(ID(B))) : RTLIL::SigSpec(); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_b = cell->hasPort(ID::B) ? assign_map(cell->getPort(ID::B)) : RTLIL::SigSpec(); if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) sig_a = RTLIL::SigSpec(); @@ -737,33 +737,33 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.xbit", "$reduce_xor", "$reduce_xnor", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", "$lt", "$le", "$ge", "$gt", "$neg", "$add", "$sub", "$mul", "$div", "$mod", "$pow", cell->type.str()); if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt))) - replace_cell(assign_map, module, cell, "x-bit in input", ID(Y), RTLIL::State::Sx); + replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx); else - replace_cell(assign_map, module, cell, "x-bit in input", ID(Y), RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID(Y)).size())); + replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID::Y).size())); goto next_cell; } } - if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID(Y)).size() == 1 && - invert_map.count(assign_map(cell->getPort(ID(A)))) != 0) { + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 && + invert_map.count(assign_map(cell->getPort(ID::A))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); - replace_cell(assign_map, module, cell, "double_invert", ID(Y), invert_map.at(assign_map(cell->getPort(ID(A))))); + replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A)))); goto next_cell; } if (cell->type.in(ID($_MUX_), ID($mux)) && invert_map.count(assign_map(cell->getPort(ID(S)))) != 0) { cover_list("opt.opt_expr.invert.muxsel", "$_MUX_", "$mux", cell->type.str()); log_debug("Optimizing away select inverter for %s cell `%s' in module `%s'.\n", log_id(cell->type), log_id(cell), log_id(module)); - RTLIL::SigSpec tmp = cell->getPort(ID(A)); - cell->setPort(ID(A), cell->getPort(ID(B))); - cell->setPort(ID(B), tmp); + RTLIL::SigSpec tmp = cell->getPort(ID::A); + cell->setPort(ID::A, cell->getPort(ID::B)); + cell->setPort(ID::B, tmp); cell->setPort(ID(S), invert_map.at(assign_map(cell->getPort(ID(S))))); did_something = true; goto next_cell; } if (cell->type == ID($_NOT_)) { - RTLIL::SigSpec input = cell->getPort(ID(A)); + RTLIL::SigSpec input = cell->getPort(ID::A); assign_map.apply(input); if (input.match("1")) ACTION_DO_Y(0); if (input.match("0")) ACTION_DO_Y(1); @@ -772,8 +772,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == ID($_AND_)) { RTLIL::SigSpec input; - input.append(cell->getPort(ID(B))); - input.append(cell->getPort(ID(A))); + input.append(cell->getPort(ID::B)); + input.append(cell->getPort(ID::A)); assign_map.apply(input); if (input.match(" 0")) ACTION_DO_Y(0); if (input.match("0 ")) ACTION_DO_Y(0); @@ -785,14 +785,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match(" *")) ACTION_DO_Y(0); if (input.match("* ")) ACTION_DO_Y(0); } - if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1)); - if (input.match("1 ")) ACTION_DO(ID(Y), input.extract(0, 1)); + if (input.match(" 1")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match("1 ")) ACTION_DO(ID::Y, input.extract(0, 1)); } if (cell->type == ID($_OR_)) { RTLIL::SigSpec input; - input.append(cell->getPort(ID(B))); - input.append(cell->getPort(ID(A))); + input.append(cell->getPort(ID::B)); + input.append(cell->getPort(ID::A)); assign_map.apply(input); if (input.match(" 1")) ACTION_DO_Y(1); if (input.match("1 ")) ACTION_DO_Y(1); @@ -804,14 +804,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match(" *")) ACTION_DO_Y(1); if (input.match("* ")) ACTION_DO_Y(1); } - if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1)); - if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1)); + if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1)); } if (cell->type == ID($_XOR_)) { RTLIL::SigSpec input; - input.append(cell->getPort(ID(B))); - input.append(cell->getPort(ID(A))); + input.append(cell->getPort(ID::B)); + input.append(cell->getPort(ID::A)); assign_map.apply(input); if (input.match("00")) ACTION_DO_Y(0); if (input.match("01")) ACTION_DO_Y(1); @@ -819,26 +819,26 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("11")) ACTION_DO_Y(0); if (input.match(" *")) ACTION_DO_Y(x); if (input.match("* ")) ACTION_DO_Y(x); - if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(1, 1)); - if (input.match("0 ")) ACTION_DO(ID(Y), input.extract(0, 1)); + if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match("0 ")) ACTION_DO(ID::Y, input.extract(0, 1)); } if (cell->type == ID($_MUX_)) { RTLIL::SigSpec input; input.append(cell->getPort(ID(S))); - input.append(cell->getPort(ID(B))); - input.append(cell->getPort(ID(A))); + input.append(cell->getPort(ID::B)); + input.append(cell->getPort(ID::A)); assign_map.apply(input); if (input.extract(2, 1) == input.extract(1, 1)) - ACTION_DO(ID(Y), input.extract(2, 1)); - if (input.match(" 0")) ACTION_DO(ID(Y), input.extract(2, 1)); - if (input.match(" 1")) ACTION_DO(ID(Y), input.extract(1, 1)); - if (input.match("01 ")) ACTION_DO(ID(Y), input.extract(0, 1)); + ACTION_DO(ID::Y, input.extract(2, 1)); + if (input.match(" 0")) ACTION_DO(ID::Y, input.extract(2, 1)); + if (input.match(" 1")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match("01 ")) ACTION_DO(ID::Y, input.extract(0, 1)); if (input.match("10 ")) { cover("opt.opt_expr.mux_to_inv"); cell->type = ID($_NOT_); - cell->setPort(ID(A), input.extract(0, 1)); - cell->unsetPort(ID(B)); + cell->setPort(ID::A, input.extract(0, 1)); + cell->unsetPort(ID::B); cell->unsetPort(ID(S)); goto next_cell; } @@ -848,24 +848,24 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (input.match("01*")) ACTION_DO_Y(x); if (input.match("10*")) ACTION_DO_Y(x); if (mux_undef) { - if (input.match("* ")) ACTION_DO(ID(Y), input.extract(1, 1)); - if (input.match(" * ")) ACTION_DO(ID(Y), input.extract(2, 1)); - if (input.match(" *")) ACTION_DO(ID(Y), input.extract(2, 1)); + if (input.match("* ")) ACTION_DO(ID::Y, input.extract(1, 1)); + if (input.match(" * ")) ACTION_DO(ID::Y, input.extract(2, 1)); + if (input.match(" *")) ACTION_DO(ID::Y, input.extract(2, 1)); } } if (cell->type.in(ID($_TBUF_), ID($tribuf))) { RTLIL::SigSpec input = cell->getPort(cell->type == ID($_TBUF_) ? ID(E) : ID(EN)); - RTLIL::SigSpec a = cell->getPort(ID(A)); + RTLIL::SigSpec a = cell->getPort(ID::A); assign_map.apply(input); assign_map.apply(a); if (input == State::S1) - ACTION_DO(ID(Y), cell->getPort(ID(A))); + ACTION_DO(ID::Y, cell->getPort(ID::A)); if (input == State::S0 && !a.is_fully_undef()) { cover("opt.opt_expr.action_" S__LINE__); log_debug("Replacing data input of %s cell `%s' in module `%s' with constant undef.\n", cell->type.c_str(), cell->name.c_str(), module->name.c_str()); - cell->setPort(ID(A), SigSpec(State::Sx, GetSize(a))); + cell->setPort(ID::A, SigSpec(State::Sx, GetSize(a))); did_something = true; goto next_cell; } @@ -873,8 +873,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($eq), ID($ne), ID($eqx), ID($nex))) { - RTLIL::SigSpec a = cell->getPort(ID(A)); - RTLIL::SigSpec b = cell->getPort(ID(B)); + RTLIL::SigSpec a = cell->getPort(ID::A); + RTLIL::SigSpec b = cell->getPort(ID::B); if (cell->parameters[ID(A_WIDTH)].as_int() != cell->parameters[ID(B_WIDTH)].as_int()) { int width = max(cell->parameters[ID(A_WIDTH)].as_int(), cell->parameters[ID(B_WIDTH)].as_int()); @@ -890,7 +890,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.eqneq.isneq", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S0 : RTLIL::State::S1); new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); - replace_cell(assign_map, module, cell, "isneq", ID(Y), new_y); + replace_cell(assign_map, module, cell, "isneq", ID::Y, new_y); goto next_cell; } if (a[i] == b[i]) @@ -903,14 +903,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.eqneq.empty", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); RTLIL::SigSpec new_y = RTLIL::SigSpec(cell->type.in(ID($eq), ID($eqx)) ? RTLIL::State::S1 : RTLIL::State::S0); new_y.extend_u0(cell->parameters[ID(Y_WIDTH)].as_int(), false); - replace_cell(assign_map, module, cell, "empty", ID(Y), new_y); + replace_cell(assign_map, module, cell, "empty", ID::Y, new_y); goto next_cell; } if (new_a.size() < a.size() || new_b.size() < b.size()) { cover_list("opt.opt_expr.eqneq.resize", "$eq", "$ne", "$eqx", "$nex", cell->type.str()); - cell->setPort(ID(A), new_a); - cell->setPort(ID(B), new_b); + cell->setPort(ID::A, new_a); + cell->setPort(ID::B, new_b); cell->parameters[ID(A_WIDTH)] = new_a.size(); cell->parameters[ID(B_WIDTH)] = new_b.size(); } @@ -919,27 +919,27 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($eq), ID($ne)) && cell->parameters[ID(Y_WIDTH)].as_int() == 1 && cell->parameters[ID(A_WIDTH)].as_int() == 1 && cell->parameters[ID(B_WIDTH)].as_int() == 1) { - RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); if (a.is_fully_const() && !b.is_fully_const()) { cover_list("opt.opt_expr.eqneq.swapconst", "$eq", "$ne", cell->type.str()); - cell->setPort(ID(A), b); - cell->setPort(ID(B), a); + cell->setPort(ID::A, b); + cell->setPort(ID::B, a); std::swap(a, b); } if (b.is_fully_const()) { if (b.as_bool() == (cell->type == ID($eq))) { RTLIL::SigSpec input = b; - ACTION_DO(ID(Y), cell->getPort(ID(A))); + ACTION_DO(ID::Y, cell->getPort(ID::A)); } else { cover_list("opt.opt_expr.eqneq.isnot", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); cell->type = ID($not); cell->parameters.erase(ID(B_WIDTH)); cell->parameters.erase(ID(B_SIGNED)); - cell->unsetPort(ID(B)); + cell->unsetPort(ID::B); did_something = true; } goto next_cell; @@ -947,33 +947,33 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (cell->type.in(ID($eq), ID($ne)) && - (assign_map(cell->getPort(ID(A))).is_fully_zero() || assign_map(cell->getPort(ID(B))).is_fully_zero())) + (assign_map(cell->getPort(ID::A)).is_fully_zero() || assign_map(cell->getPort(ID::B)).is_fully_zero())) { cover_list("opt.opt_expr.eqneq.cmpzero", "$eq", "$ne", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with %s.\n", log_id(cell->type), log_id(cell), log_id(module), "$eq" ? "$logic_not" : "$reduce_bool"); cell->type = cell->type == ID($eq) ? ID($logic_not) : ID($reduce_bool); - if (assign_map(cell->getPort(ID(A))).is_fully_zero()) { - cell->setPort(ID(A), cell->getPort(ID(B))); + if (assign_map(cell->getPort(ID::A)).is_fully_zero()) { + cell->setPort(ID::A, cell->getPort(ID::B)); cell->setParam(ID(A_SIGNED), cell->getParam(ID(B_SIGNED))); cell->setParam(ID(A_WIDTH), cell->getParam(ID(B_WIDTH))); } - cell->unsetPort(ID(B)); + cell->unsetPort(ID::B); cell->unsetParam(ID(B_SIGNED)); cell->unsetParam(ID(B_WIDTH)); did_something = true; goto next_cell; } - if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID(B))).is_fully_const()) + if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && assign_map(cell->getPort(ID::B)).is_fully_const()) { bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID(A_SIGNED)).as_bool(); - int shift_bits = assign_map(cell->getPort(ID(B))).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool()); + int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID(B_SIGNED)).as_bool()); if (cell->type.in(ID($shl), ID($sshl))) shift_bits *= -1; - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); RTLIL::SigSpec sig_y(cell->type == ID($shiftx) ? RTLIL::State::Sx : RTLIL::State::S0, cell->getParam(ID(Y_WIDTH)).as_int()); if (GetSize(sig_a) < GetSize(sig_y)) @@ -990,9 +990,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cover_list("opt.opt_expr.constshift", "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx", cell->type.str()); log_debug("Replacing %s cell `%s' (B=%s, SHR=%d) in module `%s' with fixed wiring: %s\n", - log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID(B)))), shift_bits, log_id(module), log_signal(sig_y)); + log_id(cell->type), log_id(cell), log_signal(assign_map(cell->getPort(ID::B))), shift_bits, log_id(module), log_signal(sig_y)); - module->connect(cell->getPort(ID(Y)), sig_y); + module->connect(cell->getPort(ID::Y), sig_y); module->remove(cell); did_something = true; @@ -1007,8 +1007,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($add), ID($sub), ID($or), ID($xor))) { - RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); if (cell->type != ID($sub) && a.is_fully_const() && a.as_bool() == false) identity_wrt_b = true; @@ -1019,7 +1019,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) { - RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); if (b.is_fully_const() && b.as_bool() == false) identity_wrt_a = true; @@ -1027,8 +1027,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == ID($mul)) { - RTLIL::SigSpec a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); if (a.is_fully_const() && is_one_or_minus_one(a.as_const(), cell->getParam(ID(A_SIGNED)).as_bool(), arith_inverse)) identity_wrt_b = true; @@ -1039,7 +1039,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type == ID($div)) { - RTLIL::SigSpec b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec b = assign_map(cell->getPort(ID::B)); if (b.is_fully_const() && b.size() <= 32 && b.as_int() == 1) identity_wrt_a = true; @@ -1056,13 +1056,13 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type.c_str(), cell->name.c_str(), module->name.c_str(), identity_wrt_a ? 'A' : 'B'); if (!identity_wrt_a) { - cell->setPort(ID(A), cell->getPort(ID(B))); + cell->setPort(ID::A, cell->getPort(ID::B)); cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } cell->type = arith_inverse ? ID($neg) : ID($pos); - cell->unsetPort(ID(B)); + cell->unsetPort(ID::B); cell->parameters.erase(ID(B_WIDTH)); cell->parameters.erase(ID(B_SIGNED)); cell->check(); @@ -1073,18 +1073,18 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && - cell->getPort(ID(A)) == State::S0 && cell->getPort(ID(B)) == State::S1) { + cell->getPort(ID::A) == State::S0 && cell->getPort(ID::B) == State::S1) { cover_list("opt.opt_expr.mux_bool", "$mux", "$_MUX_", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_bool", ID(Y), cell->getPort(ID(S))); + replace_cell(assign_map, module, cell, "mux_bool", ID::Y, cell->getPort(ID(S))); goto next_cell; } if (mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && - cell->getPort(ID(A)) == State::S1 && cell->getPort(ID(B)) == State::S0) { + cell->getPort(ID::A) == State::S1 && cell->getPort(ID::B) == State::S0) { cover_list("opt.opt_expr.mux_invert", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with inverter.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID(A), cell->getPort(ID(S))); - cell->unsetPort(ID(B)); + cell->setPort(ID::A, cell->getPort(ID(S))); + cell->unsetPort(ID::B); cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { Const width = cell->parameters[ID(WIDTH)]; @@ -1099,10 +1099,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(A)) == State::S0) { + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == State::S0) { cover_list("opt.opt_expr.mux_and", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with and-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID(A), cell->getPort(ID(S))); + cell->setPort(ID::A, cell->getPort(ID(S))); cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { Const width = cell->parameters[ID(WIDTH)]; @@ -1119,10 +1119,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons goto next_cell; } - if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID(B)) == State::S1) { + if (consume_x && mux_bool && cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::B) == State::S1) { cover_list("opt.opt_expr.mux_or", "$mux", "$_MUX_", cell->type.str()); log_debug("Replacing %s cell `%s' in module `%s' with or-gate.\n", log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID(B), cell->getPort(ID(S))); + cell->setPort(ID::B, cell->getPort(ID(S))); cell->unsetPort(ID(S)); if (cell->type == ID($mux)) { Const width = cell->parameters[ID(WIDTH)]; @@ -1141,22 +1141,22 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (mux_undef && cell->type.in(ID($mux), ID($pmux))) { RTLIL::SigSpec new_a, new_b, new_s; - int width = cell->getPort(ID(A)).size(); - if ((cell->getPort(ID(A)).is_fully_undef() && cell->getPort(ID(B)).is_fully_undef()) || + int width = cell->getPort(ID::A).size(); + if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) || cell->getPort(ID(S)).is_fully_undef()) { cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_undef", ID(Y), cell->getPort(ID(A))); + replace_cell(assign_map, module, cell, "mux_undef", ID::Y, cell->getPort(ID::A)); goto next_cell; } for (int i = 0; i < cell->getPort(ID(S)).size(); i++) { - RTLIL::SigSpec old_b = cell->getPort(ID(B)).extract(i*width, width); + RTLIL::SigSpec old_b = cell->getPort(ID::B).extract(i*width, width); RTLIL::SigSpec old_s = cell->getPort(ID(S)).extract(i, 1); if (old_b.is_fully_undef() || old_s.is_fully_undef()) continue; new_b.append(old_b); new_s.append(old_s); } - new_a = cell->getPort(ID(A)); + new_a = cell->getPort(ID::A); if (new_a.is_fully_undef() && new_s.size() > 0) { new_a = new_b.extract((new_s.size()-1)*width, width); new_b = new_b.extract(0, (new_s.size()-1)*width); @@ -1164,20 +1164,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (new_s.size() == 0) { cover_list("opt.opt_expr.mux_empty", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_empty", ID(Y), new_a); + replace_cell(assign_map, module, cell, "mux_empty", ID::Y, new_a); goto next_cell; } if (new_a == RTLIL::SigSpec(RTLIL::State::S0) && new_b == RTLIL::SigSpec(RTLIL::State::S1)) { cover_list("opt.opt_expr.mux_sel01", "$mux", "$pmux", cell->type.str()); - replace_cell(assign_map, module, cell, "mux_sel01", ID(Y), new_s); + replace_cell(assign_map, module, cell, "mux_sel01", ID::Y, new_s); goto next_cell; } if (cell->getPort(ID(S)).size() != new_s.size()) { cover_list("opt.opt_expr.mux_reduce", "$mux", "$pmux", cell->type.str()); log_debug("Optimized away %d select inputs of %s cell `%s' in module `%s'.\n", GetSize(cell->getPort(ID(S))) - GetSize(new_s), log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID(A), new_a); - cell->setPort(ID(B), new_b); + cell->setPort(ID::A, new_a); + cell->setPort(ID::B, new_b); cell->setPort(ID(S), new_s); if (new_s.size() > 1) { cell->type = ID($pmux); @@ -1192,7 +1192,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons #define FOLD_1ARG_CELL(_t) \ if (cell->type == "$" #_t) { \ - RTLIL::SigSpec a = cell->getPort(ID(A)); \ + RTLIL::SigSpec a = cell->getPort(ID::A); \ assign_map.apply(a); \ if (a.is_fully_const()) { \ RTLIL::Const dummy_arg(RTLIL::State::S0, 1); \ @@ -1200,14 +1200,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->parameters[ID(A_SIGNED)].as_bool(), false, \ cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ - replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID(Y), y); \ + replace_cell(assign_map, module, cell, stringf("%s", log_signal(a)), ID::Y, y); \ goto next_cell; \ } \ } #define FOLD_2ARG_CELL(_t) \ if (cell->type == "$" #_t) { \ - RTLIL::SigSpec a = cell->getPort(ID(A)); \ - RTLIL::SigSpec b = cell->getPort(ID(B)); \ + RTLIL::SigSpec a = cell->getPort(ID::A); \ + RTLIL::SigSpec b = cell->getPort(ID::B); \ assign_map.apply(a), assign_map.apply(b); \ if (a.is_fully_const() && b.is_fully_const()) { \ RTLIL::SigSpec y(RTLIL::const_ ## _t(a.as_const(), b.as_const(), \ @@ -1215,7 +1215,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->parameters[ID(B_SIGNED)].as_bool(), \ cell->parameters[ID(Y_WIDTH)].as_int())); \ cover("opt.opt_expr.const.$" #_t); \ - replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID(Y), y); \ + replace_cell(assign_map, module, cell, stringf("%s, %s", log_signal(a), log_signal(b)), ID::Y, y); \ goto next_cell; \ } \ } @@ -1263,12 +1263,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons // be very conservative with optimizing $mux cells as we do not want to break mux trees if (cell->type == ID($mux)) { RTLIL::SigSpec input = assign_map(cell->getPort(ID(S))); - RTLIL::SigSpec inA = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec inB = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec inA = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec inB = assign_map(cell->getPort(ID::B)); if (input.is_fully_const()) - ACTION_DO(ID(Y), input.as_bool() ? cell->getPort(ID(B)) : cell->getPort(ID(A))); + ACTION_DO(ID::Y, input.as_bool() ? cell->getPort(ID::B) : cell->getPort(ID::A)); else if (inA == inB) - ACTION_DO(ID(Y), cell->getPort(ID(A))); + ACTION_DO(ID::Y, cell->getPort(ID::A)); } if (!keepdc && cell->type == ID($mul)) @@ -1277,9 +1277,9 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); bool swapped_ab = false; - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); - RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID(Y))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); + RTLIL::SigSpec sig_y = assign_map(cell->getPort(ID::Y)); if (sig_b.is_fully_const() && sig_b.size() <= 32) std::swap(sig_a, sig_b), std::swap(a_signed, b_signed), swapped_ab = true; @@ -1314,7 +1314,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons a_val, cell->name.c_str(), module->name.c_str(), i); if (!swapped_ab) { - cell->setPort(ID(A), cell->getPort(ID(B))); + cell->setPort(ID::A, cell->getPort(ID::B)); cell->parameters.at(ID(A_WIDTH)) = cell->parameters.at(ID(B_WIDTH)); cell->parameters.at(ID(A_SIGNED)) = cell->parameters.at(ID(B_SIGNED)); } @@ -1327,7 +1327,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type = ID($shl); cell->parameters[ID(B_WIDTH)] = GetSize(new_b); cell->parameters[ID(B_SIGNED)] = false; - cell->setPort(ID(B), new_b); + cell->setPort(ID::B, new_b); cell->check(); did_something = true; @@ -1339,8 +1339,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (!keepdc && cell->type.in(ID($div), ID($mod))) { bool b_signed = cell->parameters[ID(B_SIGNED)].as_bool(); - SigSpec sig_b = assign_map(cell->getPort(ID(B))); - SigSpec sig_y = assign_map(cell->getPort(ID(Y))); + SigSpec sig_b = assign_map(cell->getPort(ID::B)); + SigSpec sig_y = assign_map(cell->getPort(ID::Y)); if (sig_b.is_fully_def() && sig_b.size() <= 32) { @@ -1378,7 +1378,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type = ID($shr); cell->parameters[ID(B_WIDTH)] = GetSize(new_b); cell->parameters[ID(B_SIGNED)] = false; - cell->setPort(ID(B), new_b); + cell->setPort(ID::B, new_b); cell->check(); } else @@ -1395,7 +1395,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons cell->type = ID($and); cell->parameters[ID(B_WIDTH)] = GetSize(new_b); - cell->setPort(ID(B), new_b); + cell->setPort(ID::B, new_b); cell->check(); } @@ -1421,8 +1421,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); int width = is_signed ? std::min(a_width, b_width) : std::max(a_width, b_width); - SigSpec sig_a = cell->getPort(ID(A)); - SigSpec sig_b = cell->getPort(ID(B)); + SigSpec sig_a = cell->getPort(ID::A); + SigSpec sig_b = cell->getPort(ID::B); int redundant_bits = 0; @@ -1452,7 +1452,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (contradiction_cache.find(State::S0) == contradiction_cache.find(State::S1)) { - SigSpec y_sig = cell->getPort(ID(Y)); + SigSpec y_sig = cell->getPort(ID::Y); Const y_value(cell->type.in(ID($eq), ID($eqx)) ? 0 : 1, GetSize(y_sig)); log_debug("Replacing cell `%s' in module `%s' with constant driver %s.\n", @@ -1470,8 +1470,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Removed %d redundant input bits from %s cell `%s' in module `%s'.\n", redundant_bits, log_id(cell->type), log_id(cell), log_id(module)); - cell->setPort(ID(A), sig_a); - cell->setPort(ID(B), sig_b); + cell->setPort(ID::A, sig_a); + cell->setPort(ID::B, sig_b); cell->setParam(ID(A_WIDTH), GetSize(sig_a)); cell->setParam(ID(B_WIDTH), GetSize(sig_b)); @@ -1484,8 +1484,8 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (do_fine && cell->type.in(ID($lt), ID($ge), ID($gt), ID($le))) { IdString cmp_type = cell->type; - SigSpec var_sig = cell->getPort(ID(A)); - SigSpec const_sig = cell->getPort(ID(B)); + SigSpec var_sig = cell->getPort(ID::A); + SigSpec const_sig = cell->getPort(ID::B); int var_width = cell->parameters[ID(A_WIDTH)].as_int(); int const_width = cell->parameters[ID(B_WIDTH)].as_int(); bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool(); @@ -1507,7 +1507,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (const_sig.is_fully_def() && const_sig.is_fully_const()) { std::string condition, replacement; - SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID(Y)))); + SigSpec replace_sig(State::S0, GetSize(cell->getPort(ID::Y))); bool replace = false; bool remove = false; @@ -1550,14 +1550,14 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { condition = stringf("unsigned X<%s", log_signal(const_sig)); replacement = stringf("!X[%d:%d]", var_width - 1, const_bit_hot); - module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID(Y))); + module->addLogicNot(NEW_ID, var_high_sig, cell->getPort(ID::Y)); remove = true; } if (cmp_type == ID($ge)) { condition = stringf("unsigned X>=%s", log_signal(const_sig)); replacement = stringf("|X[%d:%d]", var_width - 1, const_bit_hot); - module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID(Y))); + module->addReduceOr(NEW_ID, var_high_sig, cell->getPort(ID::Y)); remove = true; } } @@ -1599,7 +1599,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons { condition = "signed X>=0"; replacement = stringf("X[%d]", var_width - 1); - module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID(Y))); + module->addNot(NEW_ID, var_sig[var_width - 1], cell->getPort(ID::Y)); remove = true; } } @@ -1609,7 +1609,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons log_debug("Replacing %s cell `%s' (implementing %s) with %s.\n", log_id(cell->type), log_id(cell), condition.c_str(), replacement.c_str()); if (replace) - module->connect(cell->getPort(ID(Y)), replace_sig); + module->connect(cell->getPort(ID::Y), replace_sig); module->remove(cell); did_something = true; goto next_cell; diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index e9d72044b..733bc547c 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -40,7 +40,7 @@ struct OptLutWorker bool evaluate_lut(RTLIL::Cell *lut, dict inputs) { - SigSpec lut_input = sigmap(lut->getPort(ID(A))); + SigSpec lut_input = sigmap(lut->getPort(ID::A)); int lut_width = lut->getParam(ID(WIDTH)).as_int(); Const lut_table = lut->getParam(ID(LUT)); int lut_index = 0; @@ -103,12 +103,12 @@ struct OptLutWorker { if (cell->has_keep_attr()) continue; - SigBit lut_output = cell->getPort(ID(Y)); + SigBit lut_output = cell->getPort(ID::Y); if (lut_output.wire->get_bool_attribute(ID(keep))) continue; int lut_width = cell->getParam(ID(WIDTH)).as_int(); - SigSpec lut_input = cell->getPort(ID(A)); + SigSpec lut_input = cell->getPort(ID::A); int lut_arity = 0; log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell)); @@ -205,7 +205,7 @@ struct OptLutWorker } auto lut = worklist.pop(); - SigSpec lut_input = sigmap(lut->getPort(ID(A))); + SigSpec lut_input = sigmap(lut->getPort(ID::A)); pool &lut_dlogic_inputs = luts_dlogic_inputs[lut]; vector lut_inputs; @@ -267,7 +267,7 @@ struct OptLutWorker log_debug(" Not eliminating cell (connected to dedicated logic).\n"); else { - SigSpec lut_output = lut->getPort(ID(Y)); + SigSpec lut_output = lut->getPort(ID::Y); for (auto &port : index.query_ports(lut_output)) { if (port.cell != lut && luts.count(port.cell)) @@ -303,13 +303,13 @@ struct OptLutWorker } auto lutA = worklist.pop(); - SigSpec lutA_input = sigmap(lutA->getPort(ID(A))); - SigSpec lutA_output = sigmap(lutA->getPort(ID(Y))[0]); + SigSpec lutA_input = sigmap(lutA->getPort(ID::A)); + SigSpec lutA_output = sigmap(lutA->getPort(ID::Y)[0]); int lutA_width = lutA->getParam(ID(WIDTH)).as_int(); int lutA_arity = luts_arity[lutA]; pool &lutA_dlogic_inputs = luts_dlogic_inputs[lutA]; - auto lutA_output_ports = index.query_ports(lutA->getPort(ID(Y))); + auto lutA_output_ports = index.query_ports(lutA->getPort(ID::Y)); if (lutA_output_ports.size() != 2) continue; @@ -321,15 +321,15 @@ struct OptLutWorker if (luts.count(port.cell)) { auto lutB = port.cell; - SigSpec lutB_input = sigmap(lutB->getPort(ID(A))); - SigSpec lutB_output = sigmap(lutB->getPort(ID(Y))[0]); + SigSpec lutB_input = sigmap(lutB->getPort(ID::A)); + SigSpec lutB_output = sigmap(lutB->getPort(ID::Y)[0]); int lutB_width = lutB->getParam(ID(WIDTH)).as_int(); int lutB_arity = luts_arity[lutB]; pool &lutB_dlogic_inputs = luts_dlogic_inputs[lutB]; log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB)); - if (index.query_is_output(lutA->getPort(ID(Y)))) + if (index.query_is_output(lutA->getPort(ID::Y))) { log_debug(" Not combining LUTs (cascade connection feeds module output).\n"); continue; @@ -441,7 +441,7 @@ struct OptLutWorker } int lutM_width = lutM->getParam(ID(WIDTH)).as_int(); - SigSpec lutM_input = sigmap(lutM->getPort(ID(A))); + SigSpec lutM_input = sigmap(lutM->getPort(ID::A)); std::vector lutM_new_inputs; for (int i = 0; i < lutM_width; i++) { @@ -487,8 +487,8 @@ struct OptLutWorker log_debug(" Merged truth table: %s.\n", lutM_new_table.as_string().c_str()); lutM->setParam(ID(LUT), lutM_new_table); - lutM->setPort(ID(A), lutM_new_inputs); - lutM->setPort(ID(Y), lutB_output); + lutM->setPort(ID::A, lutM_new_inputs); + lutM->setPort(ID::Y, lutB_output); luts_arity[lutM] = lutM_arity; luts.erase(lutR); diff --git a/passes/opt/opt_merge.cc b/passes/opt/opt_merge.cc index aa1a5c75c..aaea6159e 100644 --- a/passes/opt/opt_merge.cc +++ b/passes/opt/opt_merge.cc @@ -48,7 +48,7 @@ struct OptMergeWorker static void sort_pmux_conn(dict &conn) { SigSpec sig_s = conn.at(ID(S)); - SigSpec sig_b = conn.at(ID(B)); + SigSpec sig_b = conn.at(ID::B); int s_width = GetSize(sig_s); int width = GetSize(sig_b) / s_width; @@ -60,11 +60,11 @@ struct OptMergeWorker std::sort(sb_pairs.begin(), sb_pairs.end()); conn[ID(S)] = SigSpec(); - conn[ID(B)] = SigSpec(); + conn[ID::B] = SigSpec(); for (auto &it : sb_pairs) { conn[ID(S)].append(it.first); - conn[ID(B)].append(it.second); + conn[ID::B].append(it.second); } } @@ -97,28 +97,28 @@ struct OptMergeWorker if (cell->type.in(ID($and), ID($or), ID($xor), ID($xnor), ID($add), ID($mul), ID($logic_and), ID($logic_or), ID($_AND_), ID($_OR_), ID($_XOR_))) { alt_conn = *conn; - if (assign_map(alt_conn.at(ID(A))) < assign_map(alt_conn.at(ID(B)))) { - alt_conn[ID(A)] = conn->at(ID(B)); - alt_conn[ID(B)] = conn->at(ID(A)); + if (assign_map(alt_conn.at(ID::A)) < assign_map(alt_conn.at(ID::B))) { + alt_conn[ID::A] = conn->at(ID::B); + alt_conn[ID::B] = conn->at(ID::A); } conn = &alt_conn; } else if (cell->type.in(ID($reduce_xor), ID($reduce_xnor))) { alt_conn = *conn; - assign_map.apply(alt_conn.at(ID(A))); - alt_conn.at(ID(A)).sort(); + assign_map.apply(alt_conn.at(ID::A)); + alt_conn.at(ID::A).sort(); conn = &alt_conn; } else if (cell->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_bool))) { alt_conn = *conn; - assign_map.apply(alt_conn.at(ID(A))); - alt_conn.at(ID(A)).sort_and_unify(); + assign_map.apply(alt_conn.at(ID::A)); + alt_conn.at(ID::A).sort_and_unify(); conn = &alt_conn; } else if (cell->type == ID($pmux)) { alt_conn = *conn; - assign_map.apply(alt_conn.at(ID(A))); - assign_map.apply(alt_conn.at(ID(B))); + assign_map.apply(alt_conn.at(ID::A)); + assign_map.apply(alt_conn.at(ID::B)); assign_map.apply(alt_conn.at(ID(S))); sort_pmux_conn(alt_conn); conn = &alt_conn; @@ -191,24 +191,24 @@ struct OptMergeWorker if (cell1->type == ID($and) || cell1->type == ID($or) || cell1->type == ID($xor) || cell1->type == ID($xnor) || cell1->type == ID($add) || cell1->type == ID($mul) || cell1->type == ID($logic_and) || cell1->type == ID($logic_or) || cell1->type == ID($_AND_) || cell1->type == ID($_OR_) || cell1->type == ID($_XOR_)) { - if (conn1.at(ID(A)) < conn1.at(ID(B))) { - RTLIL::SigSpec tmp = conn1[ID(A)]; - conn1[ID(A)] = conn1[ID(B)]; - conn1[ID(B)] = tmp; + if (conn1.at(ID::A) < conn1.at(ID::B)) { + RTLIL::SigSpec tmp = conn1[ID::A]; + conn1[ID::A] = conn1[ID::B]; + conn1[ID::B] = tmp; } - if (conn2.at(ID(A)) < conn2.at(ID(B))) { - RTLIL::SigSpec tmp = conn2[ID(A)]; - conn2[ID(A)] = conn2[ID(B)]; - conn2[ID(B)] = tmp; + if (conn2.at(ID::A) < conn2.at(ID::B)) { + RTLIL::SigSpec tmp = conn2[ID::A]; + conn2[ID::A] = conn2[ID::B]; + conn2[ID::B] = tmp; } } else if (cell1->type == ID($reduce_xor) || cell1->type == ID($reduce_xnor)) { - conn1[ID(A)].sort(); - conn2[ID(A)].sort(); + conn1[ID::A].sort(); + conn2[ID::A].sort(); } else if (cell1->type == ID($reduce_and) || cell1->type == ID($reduce_or) || cell1->type == ID($reduce_bool)) { - conn1[ID(A)].sort_and_unify(); - conn2[ID(A)].sort_and_unify(); + conn1[ID::A].sort_and_unify(); + conn2[ID::A].sort_and_unify(); } else if (cell1->type == ID($pmux)) { sort_pmux_conn(conn1); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 61f194569..3d7e9cccb 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -86,10 +86,10 @@ struct OptMuxtreeWorker { if (cell->type.in(ID($mux), ID($pmux))) { - RTLIL::SigSpec sig_a = cell->getPort(ID(A)); - RTLIL::SigSpec sig_b = cell->getPort(ID(B)); + RTLIL::SigSpec sig_a = cell->getPort(ID::A); + RTLIL::SigSpec sig_b = cell->getPort(ID::B); RTLIL::SigSpec sig_s = cell->getPort(ID(S)); - RTLIL::SigSpec sig_y = cell->getPort(ID(Y)); + RTLIL::SigSpec sig_y = cell->getPort(ID::Y); muxinfo_t muxinfo; muxinfo.cell = cell; @@ -227,10 +227,10 @@ struct OptMuxtreeWorker continue; } - RTLIL::SigSpec sig_a = mi.cell->getPort(ID(A)); - RTLIL::SigSpec sig_b = mi.cell->getPort(ID(B)); + RTLIL::SigSpec sig_a = mi.cell->getPort(ID::A); + RTLIL::SigSpec sig_b = mi.cell->getPort(ID::B); RTLIL::SigSpec sig_s = mi.cell->getPort(ID(S)); - RTLIL::SigSpec sig_y = mi.cell->getPort(ID(Y)); + RTLIL::SigSpec sig_y = mi.cell->getPort(ID::Y); RTLIL::SigSpec sig_ports = sig_b; sig_ports.append(sig_a); @@ -255,8 +255,8 @@ struct OptMuxtreeWorker } } - mi.cell->setPort(ID(A), new_sig_a); - mi.cell->setPort(ID(B), new_sig_b); + mi.cell->setPort(ID::A, new_sig_a); + mi.cell->setPort(ID::B, new_sig_b); mi.cell->setPort(ID(S), new_sig_s); if (GetSize(new_sig_s) == 1) { mi.cell->type = ID($mux); @@ -364,8 +364,8 @@ struct OptMuxtreeWorker int width = 0; idict ctrl_bits; - if (portname == ID(B)) - width = GetSize(muxinfo.cell->getPort(ID(A))); + if (portname == ID::B) + width = GetSize(muxinfo.cell->getPort(ID::A)); for (int bit : sig2bits(muxinfo.cell->getPort(ID(S)), false)) ctrl_bits(bit); @@ -414,8 +414,8 @@ struct OptMuxtreeWorker // set input ports to constants if we find known active or inactive signals if (do_replace_known) { - replace_known(knowledge, muxinfo, ID(A)); - replace_known(knowledge, muxinfo, ID(B)); + replace_known(knowledge, muxinfo, ID::A); + replace_known(knowledge, muxinfo, ID::B); } // if there is a constant activated port we just use it diff --git a/passes/opt/opt_reduce.cc b/passes/opt/opt_reduce.cc index 332e0443e..6a8d8cabd 100644 --- a/passes/opt/opt_reduce.cc +++ b/passes/opt/opt_reduce.cc @@ -43,7 +43,7 @@ struct OptReduceWorker return; cells.erase(cell); - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); pool new_sig_a_bits; for (auto &bit : sig_a.to_sigbit_set()) @@ -73,8 +73,8 @@ struct OptReduceWorker for (auto child_cell : drivers.find(bit)) { if (child_cell->type == cell->type) { opt_reduce(cells, drivers, child_cell); - if (child_cell->getPort(ID(Y))[0] == bit) { - pool child_sig_a_bits = assign_map(child_cell->getPort(ID(A))).to_sigbit_pool(); + if (child_cell->getPort(ID::Y)[0] == bit) { + pool child_sig_a_bits = assign_map(child_cell->getPort(ID::A)).to_sigbit_pool(); new_sig_a_bits.insert(child_sig_a_bits.begin(), child_sig_a_bits.end()); } else new_sig_a_bits.insert(RTLIL::State::S0); @@ -87,21 +87,21 @@ struct OptReduceWorker RTLIL::SigSpec new_sig_a(new_sig_a_bits); - if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID(A)).size()) { + if (new_sig_a != sig_a || sig_a.size() != cell->getPort(ID::A).size()) { log(" New input vector for %s cell %s: %s\n", cell->type.c_str(), cell->name.c_str(), log_signal(new_sig_a)); did_something = true; total_count++; } - cell->setPort(ID(A), new_sig_a); + cell->setPort(ID::A, new_sig_a); cell->parameters[ID(A_WIDTH)] = RTLIL::Const(new_sig_a.size()); return; } void opt_mux(RTLIL::Cell *cell) { - RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID(A))); - RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID(B))); + RTLIL::SigSpec sig_a = assign_map(cell->getPort(ID::A)); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); RTLIL::SigSpec sig_s = assign_map(cell->getPort(ID(S))); RTLIL::SigSpec new_sig_b, new_sig_s; @@ -124,14 +124,14 @@ struct OptReduceWorker if (this_s.size() > 1) { RTLIL::Cell *reduce_or_cell = module->addCell(NEW_ID, ID($reduce_or)); - reduce_or_cell->setPort(ID(A), this_s); + reduce_or_cell->setPort(ID::A, this_s); reduce_or_cell->parameters[ID(A_SIGNED)] = RTLIL::Const(0); reduce_or_cell->parameters[ID(A_WIDTH)] = RTLIL::Const(this_s.size()); reduce_or_cell->parameters[ID(Y_WIDTH)] = RTLIL::Const(1); RTLIL::Wire *reduce_or_wire = module->addWire(NEW_ID); this_s = RTLIL::SigSpec(reduce_or_wire); - reduce_or_cell->setPort(ID(Y), this_s); + reduce_or_cell->setPort(ID::Y, this_s); } new_sig_b.append(this_b); @@ -147,13 +147,13 @@ struct OptReduceWorker if (new_sig_s.size() == 0) { - module->connect(RTLIL::SigSig(cell->getPort(ID(Y)), cell->getPort(ID(A)))); - assign_map.add(cell->getPort(ID(Y)), cell->getPort(ID(A))); + module->connect(RTLIL::SigSig(cell->getPort(ID::Y), cell->getPort(ID::A))); + assign_map.add(cell->getPort(ID::Y), cell->getPort(ID::A)); module->remove(cell); } else { - cell->setPort(ID(B), new_sig_b); + cell->setPort(ID::B, new_sig_b); cell->setPort(ID(S), new_sig_s); if (new_sig_s.size() > 1) { cell->parameters[ID(S_WIDTH)] = RTLIL::Const(new_sig_s.size()); @@ -166,9 +166,9 @@ struct OptReduceWorker void opt_mux_bits(RTLIL::Cell *cell) { - std::vector sig_a = assign_map(cell->getPort(ID(A))).to_sigbit_vector(); - std::vector sig_b = assign_map(cell->getPort(ID(B))).to_sigbit_vector(); - std::vector sig_y = assign_map(cell->getPort(ID(Y))).to_sigbit_vector(); + std::vector sig_a = assign_map(cell->getPort(ID::A)).to_sigbit_vector(); + std::vector sig_b = assign_map(cell->getPort(ID::B)).to_sigbit_vector(); + std::vector sig_y = assign_map(cell->getPort(ID::Y)).to_sigbit_vector(); std::vector new_sig_y; RTLIL::SigSig old_sig_conn; @@ -209,29 +209,29 @@ struct OptReduceWorker if (new_sig_y.size() != sig_y.size()) { log(" Consolidated identical input bits for %s cell %s:\n", cell->type.c_str(), cell->name.c_str()); - log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))), - log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y)))); + log(" Old ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)), + log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y))); - cell->setPort(ID(A), RTLIL::SigSpec()); + cell->setPort(ID::A, RTLIL::SigSpec()); for (auto &in_tuple : consolidated_in_tuples) { - RTLIL::SigSpec new_a = cell->getPort(ID(A)); + RTLIL::SigSpec new_a = cell->getPort(ID::A); new_a.append(in_tuple.at(0)); - cell->setPort(ID(A), new_a); + cell->setPort(ID::A, new_a); } - cell->setPort(ID(B), RTLIL::SigSpec()); + cell->setPort(ID::B, RTLIL::SigSpec()); for (int i = 1; i <= cell->getPort(ID(S)).size(); i++) for (auto &in_tuple : consolidated_in_tuples) { - RTLIL::SigSpec new_b = cell->getPort(ID(B)); + RTLIL::SigSpec new_b = cell->getPort(ID::B); new_b.append(in_tuple.at(i)); - cell->setPort(ID(B), new_b); + cell->setPort(ID::B, new_b); } cell->parameters[ID(WIDTH)] = RTLIL::Const(new_sig_y.size()); - cell->setPort(ID(Y), new_sig_y); + cell->setPort(ID::Y, new_sig_y); - log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID(A))), - log_signal(cell->getPort(ID(B))), log_signal(cell->getPort(ID(Y)))); + log(" New ports: A=%s, B=%s, Y=%s\n", log_signal(cell->getPort(ID::A)), + log_signal(cell->getPort(ID::B)), log_signal(cell->getPort(ID::Y))); log(" New connections: %s = %s\n", log_signal(old_sig_conn.first), log_signal(old_sig_conn.second)); module->connect(old_sig_conn); @@ -269,12 +269,12 @@ struct OptReduceWorker keep_expanding_mem_wren_sigs = false; for (auto &cell_it : module->cells_) { RTLIL::Cell *cell = cell_it.second; - if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) { - if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID(A)))) || - !mem_wren_sigs.check_all(assign_map(cell->getPort(ID(B))))) + if (cell->type == ID($mux) && mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) { + if (!mem_wren_sigs.check_all(assign_map(cell->getPort(ID::A))) || + !mem_wren_sigs.check_all(assign_map(cell->getPort(ID::B)))) keep_expanding_mem_wren_sigs = true; - mem_wren_sigs.add(assign_map(cell->getPort(ID(A)))); - mem_wren_sigs.add(assign_map(cell->getPort(ID(B)))); + mem_wren_sigs.add(assign_map(cell->getPort(ID::A))); + mem_wren_sigs.add(assign_map(cell->getPort(ID::B))); } } } @@ -296,7 +296,7 @@ struct OptReduceWorker RTLIL::Cell *cell = cell_it.second; if (cell->type != type || !design->selected(module, cell)) continue; - drivers.insert(assign_map(cell->getPort(ID(Y))), cell); + drivers.insert(assign_map(cell->getPort(ID::Y)), cell); cells.insert(cell); } @@ -318,7 +318,7 @@ struct OptReduceWorker { // this optimization is to aggressive for most coarse-grain applications. // but we always want it for multiplexers driving write enable ports. - if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID(Y))))) + if (do_fine || mem_wren_sigs.check_any(assign_map(cell->getPort(ID::Y)))) opt_mux_bits(cell); opt_mux(cell); diff --git a/passes/opt/opt_rmdff.cc b/passes/opt/opt_rmdff.cc index 4ba61e512..0bf74098a 100644 --- a/passes/opt/opt_rmdff.cc +++ b/passes/opt/opt_rmdff.cc @@ -347,8 +347,8 @@ bool handle_dff(RTLIL::Module *mod, RTLIL::Cell *dff) std::set muxes; mux_drivers.find(sig_d, muxes); for (auto mux : muxes) { - RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID(A))); - RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID(B))); + RTLIL::SigSpec sig_a = assign_map(mux->getPort(ID::A)); + RTLIL::SigSpec sig_b = assign_map(mux->getPort(ID::B)); if (sig_a == sig_q && sig_b.is_fully_const() && (!has_init || val_init == sig_b.as_const())) { mod->connect(sig_q, sig_b); goto delete_dff; @@ -625,8 +625,8 @@ struct OptRmdffPass : public Pass { } if (cell->type.in(ID($mux), ID($pmux))) { - if (cell->getPort(ID(A)).size() == cell->getPort(ID(B)).size()) - mux_drivers.insert(assign_map(cell->getPort(ID(Y))), cell); + if (cell->getPort(ID::A).size() == cell->getPort(ID::B).size()) + mux_drivers.insert(assign_map(cell->getPort(ID::Y)), cell); continue; } diff --git a/passes/opt/pmux2shiftx.cc b/passes/opt/pmux2shiftx.cc index 3e34bfbbd..92b5794ac 100644 --- a/passes/opt/pmux2shiftx.cc +++ b/passes/opt/pmux2shiftx.cc @@ -73,9 +73,9 @@ struct OnehotDatabase if (cell->type.in(ID($mux), ID($pmux))) { - output = cell->getPort(ID(Y)); - inputs.push_back(cell->getPort(ID(A))); - SigSpec B = cell->getPort(ID(B)); + output = cell->getPort(ID::Y); + inputs.push_back(cell->getPort(ID::A)); + SigSpec B = cell->getPort(ID::B); for (int i = 0; i < GetSize(B); i += GetSize(output)) inputs.push_back(B.extract(i, GetSize(output))); } @@ -296,8 +296,8 @@ struct Pmux2ShiftxPass : public Pass { { dict bits; - SigSpec A = sigmap(cell->getPort(ID(A))); - SigSpec B = sigmap(cell->getPort(ID(B))); + SigSpec A = sigmap(cell->getPort(ID::A)); + SigSpec B = sigmap(cell->getPort(ID::B)); int a_width = cell->getParam(ID(A_WIDTH)).as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int(); @@ -335,7 +335,7 @@ struct Pmux2ShiftxPass : public Pass { entry.second.bits.push_back(it.second); } - eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry; + eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; goto next_cell; } @@ -343,7 +343,7 @@ struct Pmux2ShiftxPass : public Pass { { dict bits; - SigSpec A = sigmap(cell->getPort(ID(A))); + SigSpec A = sigmap(cell->getPort(ID::A)); for (int i = 0; i < GetSize(A); i++) bits[A[i]] = State::S0; @@ -356,7 +356,7 @@ struct Pmux2ShiftxPass : public Pass { entry.second.bits.push_back(it.second); } - eqdb[sigmap(cell->getPort(ID(Y))[0])] = entry; + eqdb[sigmap(cell->getPort(ID::Y)[0])] = entry; goto next_cell; } next_cell:; @@ -377,8 +377,8 @@ struct Pmux2ShiftxPass : public Pass { dict> seldb; - SigSpec A = cell->getPort(ID(A)); - SigSpec B = cell->getPort(ID(B)); + SigSpec A = cell->getPort(ID::A); + SigSpec B = cell->getPort(ID::B); SigSpec S = sigmap(cell->getPort(ID(S))); for (int i = 0; i < GetSize(S); i++) { @@ -401,7 +401,7 @@ struct Pmux2ShiftxPass : public Pass { } SigSpec updated_S = cell->getPort(ID(S)); - SigSpec updated_B = cell->getPort(ID(B)); + SigSpec updated_B = cell->getPort(ID::B); while (!seldb.empty()) { @@ -728,7 +728,7 @@ struct Pmux2ShiftxPass : public Pass { // update $pmux cell cell->setPort(ID(S), updated_S); - cell->setPort(ID(B), updated_B); + cell->setPort(ID::B, updated_B); cell->setParam(ID(S_WIDTH), GetSize(updated_S)); } } @@ -782,8 +782,8 @@ struct OnehotPass : public Pass { if (cell->type != ID($eq)) continue; - SigSpec A = sigmap(cell->getPort(ID(A))); - SigSpec B = sigmap(cell->getPort(ID(B))); + SigSpec A = sigmap(cell->getPort(ID::A)); + SigSpec B = sigmap(cell->getPort(ID::B)); int a_width = cell->getParam(ID(A_WIDTH)).as_int(); int b_width = cell->getParam(ID(B_WIDTH)).as_int(); @@ -830,7 +830,7 @@ struct OnehotPass : public Pass { continue; } - SigSpec Y = cell->getPort(ID(Y)); + SigSpec Y = cell->getPort(ID::Y); if (not_onehot) { diff --git a/passes/opt/share.cc b/passes/opt/share.cc index 84290bb97..92ce3fd11 100644 --- a/passes/opt/share.cc +++ b/passes/opt/share.cc @@ -128,7 +128,7 @@ struct ShareWorker static int bits_macc(RTLIL::Cell *c) { Macc m(c); - int width = GetSize(c->getPort(ID(Y))); + int width = GetSize(c->getPort(ID::Y)); return bits_macc(m, width); } @@ -242,7 +242,7 @@ struct ShareWorker { Macc m1(c1), m2(c2), supermacc; - int w1 = GetSize(c1->getPort(ID(Y))), w2 = GetSize(c2->getPort(ID(Y))); + int w1 = GetSize(c1->getPort(ID::Y)), w2 = GetSize(c2->getPort(ID::Y)); int width = max(w1, w2); m1.optimize(w1); @@ -328,11 +328,11 @@ struct ShareWorker { RTLIL::SigSpec sig_y = module->addWire(NEW_ID, width); - supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID(Y)))); - supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID(Y)))); + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c1->getPort(ID::Y))); + supercell_aux->insert(module->addPos(NEW_ID, sig_y, c2->getPort(ID::Y))); supercell->setParam(ID(Y_WIDTH), width); - supercell->setPort(ID(Y), sig_y); + supercell->setPort(ID::Y, sig_y); supermacc.optimize(width); supermacc.to_cell(supercell); @@ -513,11 +513,11 @@ struct ShareWorker if (c1->parameters.at(ID(A_SIGNED)).as_bool() != c2->parameters.at(ID(A_SIGNED)).as_bool()) { RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; - if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) { + if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) { unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; - RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A)); + RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A); new_a.append_bit(RTLIL::State::S0); - unsigned_cell->setPort(ID(A), new_a); + unsigned_cell->setPort(ID::A, new_a); } unsigned_cell->parameters.at(ID(A_SIGNED)) = true; unsigned_cell->check(); @@ -526,11 +526,11 @@ struct ShareWorker bool a_signed = c1->parameters.at(ID(A_SIGNED)).as_bool(); log_assert(a_signed == c2->parameters.at(ID(A_SIGNED)).as_bool()); - RTLIL::SigSpec a1 = c1->getPort(ID(A)); - RTLIL::SigSpec y1 = c1->getPort(ID(Y)); + RTLIL::SigSpec a1 = c1->getPort(ID::A); + RTLIL::SigSpec y1 = c1->getPort(ID::Y); - RTLIL::SigSpec a2 = c2->getPort(ID(A)); - RTLIL::SigSpec y2 = c2->getPort(ID(Y)); + RTLIL::SigSpec a2 = c2->getPort(ID::A); + RTLIL::SigSpec y2 = c2->getPort(ID::Y); int a_width = max(a1.size(), a2.size()); int y_width = max(y1.size(), y2.size()); @@ -547,8 +547,8 @@ struct ShareWorker supercell->parameters[ID(A_SIGNED)] = a_signed; supercell->parameters[ID(A_WIDTH)] = a_width; supercell->parameters[ID(Y_WIDTH)] = y_width; - supercell->setPort(ID(A), a); - supercell->setPort(ID(Y), y); + supercell->setPort(ID::A, a); + supercell->setPort(ID::Y, y); supercell_aux.insert(module->addPos(NEW_ID, y, y1)); supercell_aux.insert(module->addPos(NEW_ID, y, y2)); @@ -571,9 +571,9 @@ struct ShareWorker if (score_flipped < score_unflipped) { - RTLIL::SigSpec tmp = c2->getPort(ID(A)); - c2->setPort(ID(A), c2->getPort(ID(B))); - c2->setPort(ID(B), tmp); + RTLIL::SigSpec tmp = c2->getPort(ID::A); + c2->setPort(ID::A, c2->getPort(ID::B)); + c2->setPort(ID::B, tmp); std::swap(c2->parameters.at(ID(A_WIDTH)), c2->parameters.at(ID(B_WIDTH))); std::swap(c2->parameters.at(ID(A_SIGNED)), c2->parameters.at(ID(B_SIGNED))); @@ -585,11 +585,11 @@ struct ShareWorker { RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(A_SIGNED)).as_bool() ? c2 : c1; - if (unsigned_cell->getPort(ID(A)).to_sigbit_vector().back() != RTLIL::State::S0) { + if (unsigned_cell->getPort(ID::A).to_sigbit_vector().back() != RTLIL::State::S0) { unsigned_cell->parameters.at(ID(A_WIDTH)) = unsigned_cell->parameters.at(ID(A_WIDTH)).as_int() + 1; - RTLIL::SigSpec new_a = unsigned_cell->getPort(ID(A)); + RTLIL::SigSpec new_a = unsigned_cell->getPort(ID::A); new_a.append_bit(RTLIL::State::S0); - unsigned_cell->setPort(ID(A), new_a); + unsigned_cell->setPort(ID::A, new_a); } unsigned_cell->parameters.at(ID(A_SIGNED)) = true; modified_src_cells = true; @@ -598,11 +598,11 @@ struct ShareWorker if (c1->parameters.at(ID(B_SIGNED)).as_bool() != c2->parameters.at(ID(B_SIGNED)).as_bool()) { RTLIL::Cell *unsigned_cell = c1->parameters.at(ID(B_SIGNED)).as_bool() ? c2 : c1; - if (unsigned_cell->getPort(ID(B)).to_sigbit_vector().back() != RTLIL::State::S0) { + if (unsigned_cell->getPort(ID::B).to_sigbit_vector().back() != RTLIL::State::S0) { unsigned_cell->parameters.at(ID(B_WIDTH)) = unsigned_cell->parameters.at(ID(B_WIDTH)).as_int() + 1; - RTLIL::SigSpec new_b = unsigned_cell->getPort(ID(B)); + RTLIL::SigSpec new_b = unsigned_cell->getPort(ID::B); new_b.append_bit(RTLIL::State::S0); - unsigned_cell->setPort(ID(B), new_b); + unsigned_cell->setPort(ID::B, new_b); } unsigned_cell->parameters.at(ID(B_SIGNED)) = true; modified_src_cells = true; @@ -622,13 +622,13 @@ struct ShareWorker if (c1->type == ID($shl) || c1->type == ID($shr) || c1->type == ID($sshl) || c1->type == ID($sshr)) b_signed = false; - RTLIL::SigSpec a1 = c1->getPort(ID(A)); - RTLIL::SigSpec b1 = c1->getPort(ID(B)); - RTLIL::SigSpec y1 = c1->getPort(ID(Y)); + RTLIL::SigSpec a1 = c1->getPort(ID::A); + RTLIL::SigSpec b1 = c1->getPort(ID::B); + RTLIL::SigSpec y1 = c1->getPort(ID::Y); - RTLIL::SigSpec a2 = c2->getPort(ID(A)); - RTLIL::SigSpec b2 = c2->getPort(ID(B)); - RTLIL::SigSpec y2 = c2->getPort(ID(Y)); + RTLIL::SigSpec a2 = c2->getPort(ID::A); + RTLIL::SigSpec b2 = c2->getPort(ID::B); + RTLIL::SigSpec y2 = c2->getPort(ID::Y); int a_width = max(a1.size(), a2.size()); int b_width = max(b1.size(), b2.size()); @@ -669,9 +669,9 @@ struct ShareWorker supercell->parameters[ID(A_WIDTH)] = a_width; supercell->parameters[ID(B_WIDTH)] = b_width; supercell->parameters[ID(Y_WIDTH)] = y_width; - supercell->setPort(ID(A), a); - supercell->setPort(ID(B), b); - supercell->setPort(ID(Y), y); + supercell->setPort(ID::A, a); + supercell->setPort(ID::B, b); + supercell->setPort(ID::Y, y); if (c1->type == ID($alu)) { RTLIL::Wire *ci = module->addWire(NEW_ID), *bi = module->addWire(NEW_ID); supercell_aux.insert(module->addMux(NEW_ID, c2->getPort(ID(CI)), c1->getPort(ID(CI)), act, ci)); @@ -874,7 +874,7 @@ struct ShareWorker } for (auto &pbit : modwalker.signal_consumers[bit]) { log_assert(fwd_ct.cell_known(pbit.cell->type)); - if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID(A) || pbit.port == ID(B))) + if ((pbit.cell->type == ID($mux) || pbit.cell->type == ID($pmux)) && (pbit.port == ID::A || pbit.port == ID::B)) driven_data_muxes.insert(pbit.cell); else driven_cells.insert(pbit.cell); @@ -891,8 +891,8 @@ struct ShareWorker std::set used_in_b_parts; int width = c->parameters.at(ID(WIDTH)).as_int(); - std::vector sig_a = modwalker.sigmap(c->getPort(ID(A))); - std::vector sig_b = modwalker.sigmap(c->getPort(ID(B))); + std::vector sig_a = modwalker.sigmap(c->getPort(ID::A)); + std::vector sig_b = modwalker.sigmap(c->getPort(ID::B)); std::vector sig_s = modwalker.sigmap(c->getPort(ID(S))); for (auto &bit : sig_a) diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index ca0be54d2..792c69c55 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -64,10 +64,10 @@ struct WreduceWorker { // Reduce size of MUX if inputs agree on a value for a bit or a output bit is unused - SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))); - SigSpec sig_b = mi.sigmap(cell->getPort(ID(B))); + SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)); + SigSpec sig_b = mi.sigmap(cell->getPort(ID::B)); SigSpec sig_s = mi.sigmap(cell->getPort(ID(S))); - SigSpec sig_y = mi.sigmap(cell->getPort(ID(Y))); + SigSpec sig_y = mi.sigmap(cell->getPort(ID::Y)); std::vector bits_removed; if (sig_y.has_const()) @@ -130,9 +130,9 @@ struct WreduceWorker for (auto bit : new_work_queue_bits) work_queue_bits.insert(bit); - cell->setPort(ID(A), new_sig_a); - cell->setPort(ID(B), new_sig_b); - cell->setPort(ID(Y), new_sig_y); + cell->setPort(ID::A, new_sig_a); + cell->setPort(ID::B, new_sig_b); + cell->setPort(ID::Y, new_sig_y); cell->fixup_parameters(); module->connect(sig_y.extract(n_kept, n_removed), sig_removed); @@ -270,7 +270,7 @@ struct WreduceWorker if (cell->type.in(ID($dff), ID($adff))) return run_cell_dff(cell); - SigSpec sig = mi.sigmap(cell->getPort(ID(Y))); + SigSpec sig = mi.sigmap(cell->getPort(ID::Y)); if (sig.has_const()) return; @@ -278,8 +278,8 @@ struct WreduceWorker // Reduce size of ports A and B based on constant input bits and size of output port - int max_port_a_size = cell->hasPort(ID(A)) ? GetSize(cell->getPort(ID(A))) : -1; - int max_port_b_size = cell->hasPort(ID(B)) ? GetSize(cell->getPort(ID(B))) : -1; + int max_port_a_size = cell->hasPort(ID::A) ? GetSize(cell->getPort(ID::A)) : -1; + int max_port_b_size = cell->hasPort(ID::B) ? GetSize(cell->getPort(ID::B)) : -1; if (cell->type.in(ID($not), ID($pos), ID($neg), ID($and), ID($or), ID($xor), ID($add), ID($sub))) { max_port_a_size = min(max_port_a_size, GetSize(sig)); @@ -295,8 +295,8 @@ struct WreduceWorker if (max_port_b_size >= 0) run_reduce_inport(cell, 'B', max_port_b_size, port_b_signed, did_something); - if (cell->hasPort(ID(A)) && cell->hasPort(ID(B)) && port_a_signed && port_b_signed) { - SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))), sig_b = mi.sigmap(cell->getPort(ID(B))); + if (cell->hasPort(ID::A) && cell->hasPort(ID::B) && port_a_signed && port_b_signed) { + SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)), sig_b = mi.sigmap(cell->getPort(ID::B)); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0 && GetSize(sig_b) > 0 && sig_b[GetSize(sig_b)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", @@ -309,8 +309,8 @@ struct WreduceWorker } } - if (cell->hasPort(ID(A)) && !cell->hasPort(ID(B)) && port_a_signed) { - SigSpec sig_a = mi.sigmap(cell->getPort(ID(A))); + if (cell->hasPort(ID::A) && !cell->hasPort(ID::B) && port_a_signed) { + SigSpec sig_a = mi.sigmap(cell->getPort(ID::A)); if (GetSize(sig_a) > 0 && sig_a[GetSize(sig_a)-1] == State::S0) { log("Converting cell %s.%s (%s) from signed to unsigned.\n", log_id(module), log_id(cell), log_id(cell->type)); @@ -347,8 +347,8 @@ struct WreduceWorker bool is_signed = cell->getParam(ID(A_SIGNED)).as_bool() || cell->type == ID($sub); int a_size = 0, b_size = 0; - if (cell->hasPort(ID(A))) a_size = GetSize(cell->getPort(ID(A))); - if (cell->hasPort(ID(B))) b_size = GetSize(cell->getPort(ID(B))); + if (cell->hasPort(ID::A)) a_size = GetSize(cell->getPort(ID::A)); + if (cell->hasPort(ID::B)) b_size = GetSize(cell->getPort(ID::B)); int max_y_size = max(a_size, b_size); @@ -374,7 +374,7 @@ struct WreduceWorker if (bits_removed) { log("Removed top %d bits (of %d) from port Y of cell %s.%s (%s).\n", bits_removed, GetSize(sig) + bits_removed, log_id(module), log_id(cell), log_id(cell->type)); - cell->setPort(ID(Y), sig); + cell->setPort(ID::Y, sig); did_something = true; } @@ -530,10 +530,10 @@ struct WreducePass : public Pass { { if (c->type.in(ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt), - ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID(Y))) > 1) { - SigSpec sig = c->getPort(ID(Y)); + ID($logic_not), ID($logic_and), ID($logic_or)) && GetSize(c->getPort(ID::Y)) > 1) { + SigSpec sig = c->getPort(ID::Y); if (!sig.has_const()) { - c->setPort(ID(Y), sig[0]); + c->setPort(ID::Y, sig[0]); c->setParam(ID(Y_WIDTH), 1); sig.remove(0); module->connect(sig, Const(0, GetSize(sig))); @@ -542,7 +542,7 @@ struct WreducePass : public Pass { if (c->type.in(ID($div), ID($mod), ID($pow))) { - SigSpec A = c->getPort(ID(A)); + SigSpec A = c->getPort(ID::A); int original_a_width = GetSize(A); if (c->getParam(ID(A_SIGNED)).as_bool()) { while (GetSize(A) > 1 && A[GetSize(A)-1] == State::S0 && A[GetSize(A)-2] == State::S0) @@ -554,11 +554,11 @@ struct WreducePass : public Pass { 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(ID(A), A); + c->setPort(ID::A, A); c->setParam(ID(A_WIDTH), GetSize(A)); } - SigSpec B = c->getPort(ID(B)); + SigSpec B = c->getPort(ID::B); int original_b_width = GetSize(B); if (c->getParam(ID(B_SIGNED)).as_bool()) { while (GetSize(B) > 1 && B[GetSize(B)-1] == State::S0 && B[GetSize(B)-2] == State::S0) @@ -570,7 +570,7 @@ struct WreducePass : public Pass { 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(ID(B), B); + c->setPort(ID::B, B); c->setParam(ID(B_WIDTH), GetSize(B)); } } -- cgit v1.2.3 From eae5a6b12c0f44230f61ed23068e7200507f9520 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 15 Aug 2019 14:51:12 -0700 Subject: Use ID::keep more liberally too --- passes/opt/muxpack.cc | 4 ++-- passes/opt/opt_clean.cc | 8 ++++---- passes/opt/opt_expr.cc | 2 +- passes/opt/opt_lut.cc | 2 +- passes/opt/opt_muxtree.cc | 2 +- passes/opt/wreduce.cc | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/muxpack.cc b/passes/opt/muxpack.cc index 97c88f423..c40c02acd 100644 --- a/passes/opt/muxpack.cc +++ b/passes/opt/muxpack.cc @@ -135,7 +135,7 @@ struct MuxpackWorker { for (auto wire : module->wires()) { - if (wire->port_output || wire->get_bool_attribute(ID(keep))) { + if (wire->port_output || wire->get_bool_attribute(ID::keep)) { for (auto bit : sigmap(wire)) sigbit_with_non_chain_users.insert(bit); } @@ -143,7 +143,7 @@ struct MuxpackWorker for (auto cell : module->cells()) { - if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID(keep))) + if (cell->type.in(ID($mux), ID($pmux)) && !cell->get_bool_attribute(ID::keep)) { SigSpec a_sig = sigmap(cell->getPort(ID::A)); SigSpec b_sig; diff --git a/passes/opt/opt_clean.cc b/passes/opt/opt_clean.cc index bf75c7adc..2f69b3d4c 100644 --- a/passes/opt/opt_clean.cc +++ b/passes/opt/opt_clean.cc @@ -52,7 +52,7 @@ struct keep_cache_t return cache.at(module); cache[module] = true; - if (!module->get_bool_attribute(ID(keep))) { + if (!module->get_bool_attribute(ID::keep)) { bool found_keep = false; for (auto cell : module->cells()) if (query(cell)) found_keep = true; @@ -122,7 +122,7 @@ void rmunused_module_cells(Module *module, bool verbose) for (auto &it : module->wires_) { Wire *wire = it.second; - if (wire->port_output || wire->get_bool_attribute(ID(keep))) { + if (wire->port_output || wire->get_bool_attribute(ID::keep)) { for (auto bit : sigmap(wire)) for (auto c : wire2driver[bit]) queue.insert(c), unused.erase(c); @@ -297,7 +297,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (!wire->port_input) used_signals_nodrivers.add(sig); } - if (wire->get_bool_attribute(ID(keep))) { + if (wire->get_bool_attribute(ID::keep)) { RTLIL::SigSpec sig = RTLIL::SigSpec(wire); assign_map.apply(sig); used_signals.add(sig); @@ -323,7 +323,7 @@ bool rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos if (wire->port_id == 0) goto delete_this_wire; } else - if (wire->port_id != 0 || wire->get_bool_attribute(ID(keep)) || !initval.is_fully_undef()) { + if (wire->port_id != 0 || wire->get_bool_attribute(ID::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) && (raw_used_signals.check_any(s1) || used_signals.check_any(s2) || s1 != s2)) { diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 85ec9a55a..f7469853b 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 || wire->get_bool_attribute(ID(keep))) + if (wire->port_output || wire->get_bool_attribute(ID::keep)) used_signals.add(sigmap(wire)); all_signals.add(sigmap(wire)); } diff --git a/passes/opt/opt_lut.cc b/passes/opt/opt_lut.cc index 733bc547c..c4f278706 100644 --- a/passes/opt/opt_lut.cc +++ b/passes/opt/opt_lut.cc @@ -104,7 +104,7 @@ struct OptLutWorker if (cell->has_keep_attr()) continue; SigBit lut_output = cell->getPort(ID::Y); - if (lut_output.wire->get_bool_attribute(ID(keep))) + if (lut_output.wire->get_bool_attribute(ID::keep)) continue; int lut_width = cell->getParam(ID(WIDTH)).as_int(); diff --git a/passes/opt/opt_muxtree.cc b/passes/opt/opt_muxtree.cc index 3d7e9cccb..3c486bbcc 100644 --- a/passes/opt/opt_muxtree.cc +++ b/passes/opt/opt_muxtree.cc @@ -137,7 +137,7 @@ struct OptMuxtreeWorker } } for (auto wire : module->wires()) { - if (wire->port_output || wire->get_bool_attribute(ID(keep))) + if (wire->port_output || wire->get_bool_attribute(ID::keep)) for (int idx : sig2bits(RTLIL::SigSpec(wire))) bit2info[idx].seen_non_mux = true; } diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 792c69c55..37de8cb61 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -398,7 +398,7 @@ struct WreduceWorker SigMap init_attr_sigmap = mi.sigmap; for (auto w : module->wires()) { - if (w->get_bool_attribute(ID(keep))) + if (w->get_bool_attribute(ID::keep)) for (auto bit : mi.sigmap(w)) keep_bits.insert(bit); if (w->attributes.count(ID(init))) { -- cgit v1.2.3 From 29e14e674eccc173b354dacd96fdbe0040c423d0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 16 Aug 2019 19:36:45 +0000 Subject: Remove `using namespace RTLIL;` --- passes/opt/wreduce.cc | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/wreduce.cc b/passes/opt/wreduce.cc index 37de8cb61..c02c355cb 100644 --- a/passes/opt/wreduce.cc +++ b/passes/opt/wreduce.cc @@ -22,7 +22,6 @@ #include "kernel/modtools.h" USING_YOSYS_NAMESPACE -using namespace RTLIL; PRIVATE_NAMESPACE_BEGIN @@ -77,15 +76,15 @@ struct WreduceWorker { auto info = mi.query(sig_y[i]); if (!info->is_output && GetSize(info->ports) <= 1 && !keep_bits.count(mi.sigmap(sig_y[i]))) { - bits_removed.push_back(Sx); + bits_removed.push_back(State::Sx); continue; } SigBit ref = sig_a[i]; for (int k = 0; k < GetSize(sig_s); k++) { - if ((config->keepdc || (ref != Sx && sig_b[k*GetSize(sig_a) + i] != Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) + if ((config->keepdc || (ref != State::Sx && sig_b[k*GetSize(sig_a) + i] != State::Sx)) && ref != sig_b[k*GetSize(sig_a) + i]) goto no_match_ab; - if (sig_b[k*GetSize(sig_a) + i] != Sx) + if (sig_b[k*GetSize(sig_a) + i] != State::Sx) ref = sig_b[k*GetSize(sig_a) + i]; } if (0) @@ -245,7 +244,7 @@ struct WreduceWorker while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == sig[GetSize(sig)-2]) work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++; } else { - while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == S0) + while (GetSize(sig) > 1 && sig[GetSize(sig)-1] == State::S0) work_queue_bits.insert(sig[GetSize(sig)-1]), sig.remove(GetSize(sig)-1), bits_removed++; } @@ -359,7 +358,7 @@ struct WreduceWorker max_y_size = a_size + b_size; while (GetSize(sig) > 1 && GetSize(sig) > max_y_size) { - module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : S0); + module->connect(sig[GetSize(sig)-1], is_signed ? sig[GetSize(sig)-2] : State::S0); sig.remove(GetSize(sig)-1); bits_removed++; } -- cgit v1.2.3 From fab067cecef205ce246904cf122a5e545e348f99 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 16 Aug 2019 13:47:37 -0700 Subject: Add 'opt_share' to 'opt -full' --- passes/opt/opt.cc | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt.cc b/passes/opt/opt.cc index e9a43e0f3..396819883 100644 --- a/passes/opt/opt.cc +++ b/passes/opt/opt.cc @@ -44,6 +44,7 @@ struct OptPass : public Pass { log(" opt_muxtree\n"); log(" opt_reduce [-fine] [-full]\n"); log(" opt_merge [-share_all]\n"); + log(" opt_share (-full only)\n"); log(" opt_rmdff [-keepdc] [-sat]\n"); log(" opt_clean [-purge]\n"); log(" opt_expr [-mux_undef] [-mux_bool] [-undriven] [-clkinv] [-fine] [-full] [-keepdc]\n"); @@ -70,6 +71,7 @@ struct OptPass : public Pass { std::string opt_reduce_args; std::string opt_merge_args; std::string opt_rmdff_args; + bool opt_share = false; bool fast_mode = false; log_header(design, "Executing OPT pass (performing simple optimizations).\n"); @@ -105,6 +107,7 @@ struct OptPass : public Pass { if (args[argidx] == "-full") { opt_expr_args += " -full"; opt_reduce_args += " -full"; + opt_share = true; continue; } if (args[argidx] == "-keepdc") { @@ -151,6 +154,8 @@ struct OptPass : public Pass { Pass::call(design, "opt_muxtree"); Pass::call(design, "opt_reduce" + opt_reduce_args); Pass::call(design, "opt_merge" + opt_merge_args); + if (opt_share) + Pass::call(design, "opt_share"); Pass::call(design, "opt_rmdff" + opt_rmdff_args); Pass::call(design, "opt_clean" + opt_clean_args); Pass::call(design, "opt_expr" + opt_expr_args); -- cgit v1.2.3 From 3d3779b0376b8204ed7637053176a07b7271ac1d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 16 Aug 2019 14:01:55 -0700 Subject: Use ID() macro --- passes/opt/opt_share.cc | 228 +++++++++++++++++++++++------------------------- 1 file changed, 110 insertions(+), 118 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index a2ec9cc37..734cbcf81 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -83,52 +83,51 @@ struct ExtSigSpec { bool operator==(const ExtSigSpec &other) const { return is_signed == other.is_signed && sign == other.sign && sig == other.sig && semantics == other.semantics; } }; -#define BITWISE_OPS "$_AND_", "$_NAND_", "$_OR_", "$_NOR_", "$_XOR_", "$_XNOR_", "$_ANDNOT_", "$_ORNOT_", "$and", "$or", "$xor", "$xnor" +#define BITWISE_OPS ID($_AND_), ID($_NAND_), ID($_OR_), ID($_NOR_), ID($_XOR_), ID($_XNOR_), ID($_ANDNOT_), ID($_ORNOT_), ID($and), ID($or), ID($xor), ID($xnor) -#define REDUCTION_OPS "$reduce_and", "$reduce_or", "$reduce_xor", "$reduce_xnor", "$reduce_bool", "$reduce_nand" +#define REDUCTION_OPS ID($reduce_and), ID($reduce_or), ID($reduce_xor), ID($reduce_xnor), ID($reduce_bool), ID($reduce_nand) -#define LOGICAL_OPS "$logic_and", "$logic_or" +#define LOGICAL_OPS ID($logic_and), ID($logic_or) -#define SHIFT_OPS "$shl", "$shr", "$sshl", "$sshr", "$shift", "$shiftx" +#define SHIFT_OPS ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx) -#define RELATIONAL_OPS "$lt", "$le", "$eq", "$ne", "$eqx", "$nex", "$ge", "$gt" +#define RELATIONAL_OPS ID($lt), ID($le), ID($eq), ID($ne), ID($eqx), ID($nex), ID($ge), ID($gt) bool cell_supported(RTLIL::Cell *cell) { - - if (cell->type.in("$alu")) { - RTLIL::SigSpec sig_bi = cell->getPort("\\BI"); - RTLIL::SigSpec sig_ci = cell->getPort("\\CI"); + if (cell->type.in(ID($alu))) { + RTLIL::SigSpec sig_bi = cell->getPort(ID(BI)); + RTLIL::SigSpec sig_ci = cell->getPort(ID(CI)); if (sig_bi.is_fully_const() && sig_ci.is_fully_const() && sig_bi == sig_ci) return true; - } else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, "$add", "$sub", "$mul", "$div", "$mod", "$concat")) { + } else if (cell->type.in(LOGICAL_OPS, SHIFT_OPS, BITWISE_OPS, RELATIONAL_OPS, ID($add), ID($sub), ID($mul), ID($div), ID($mod), ID($concat))) { return true; } return false; } -std::map mergeable_type_map{ - {"$sub", "$add"}, +std::map mergeable_type_map{ + {ID($sub), ID($add)}, }; bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) { auto a_type = a->type; - if (mergeable_type_map.count(a_type.str())) - a_type = mergeable_type_map.at(a_type.str()); + if (mergeable_type_map.count(a_type)) + a_type = mergeable_type_map.at(a_type); auto b_type = b->type; - if (mergeable_type_map.count(b_type.str())) - b_type = mergeable_type_map.at(b_type.str()); + if (mergeable_type_map.count(b_type)) + b_type = mergeable_type_map.at(b_type); return a_type == b_type; } RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name) { - if (cell->type.in("$lt", "$le", "$ge", "$gt", "$div", "$mod", "$concat", SHIFT_OPS) && port_name == "\\B") + if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID(B)) return port_name; return ""; @@ -136,9 +135,9 @@ RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_na RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { - if (cell->type == "$alu" && port_name == "\\B") - return cell->getPort("\\BI"); - else if (cell->type == "$sub" && port_name == "\\B") + if (cell->type == ID($alu) && port_name == ID(B)) + return cell->getPort(ID(BI)); + else if (cell->type == ID($sub) && port_name == ID(B)) return RTLIL::Const(1, 1); return RTLIL::Const(0, 1); @@ -153,7 +152,6 @@ bool decode_port_signed(RTLIL::Cell *cell, RTLIL::IdString port_name) return cell->getParam(port_name.str() + "_SIGNED").as_bool(); return false; - } ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sigmap) @@ -170,15 +168,14 @@ ExtSigSpec decode_port(RTLIL::Cell *cell, RTLIL::IdString port_name, SigMap *sig void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector &ports, const ExtSigSpec &operand) { - std::vector muxed_operands; int max_width = 0; for (const auto& p : ports) { auto op = p.op; - RTLIL::IdString muxed_port_name = "\\A"; - if (decode_port(op, "\\A", &assign_map) == operand) - muxed_port_name = "\\B"; + RTLIL::IdString muxed_port_name = ID(A); + if (decode_port(op, ID(A), &assign_map) == operand) + muxed_port_name = ID(B); auto operand = decode_port(op, muxed_port_name, &assign_map); if (operand.sig.size() > max_width) @@ -190,8 +187,7 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< auto shared_op = ports[0].op; if (std::any_of(muxed_operands.begin(), muxed_operands.end(), [&](ExtSigSpec &op) { return op.sign != muxed_operands[0].sign; })) - if (max_width < shared_op->getParam("\\Y_WIDTH").as_int()) - max_width = shared_op->getParam("\\Y_WIDTH").as_int(); + max_width = std::max(max_width, shared_op->getParam(ID(Y_WIDTH)).as_int()); for (auto &operand : muxed_operands) @@ -208,11 +204,10 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< if (muxed_op.sign != muxed_operands[0].sign) muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed)); - - RTLIL::SigSpec mux_y = mux->getPort("\\Y"); - RTLIL::SigSpec mux_a = mux->getPort("\\A"); - RTLIL::SigSpec mux_b = mux->getPort("\\B"); - RTLIL::SigSpec mux_s = mux->getPort("\\S"); + RTLIL::SigSpec mux_y = mux->getPort(ID(Y)); + RTLIL::SigSpec mux_a = mux->getPort(ID(A)); + RTLIL::SigSpec mux_b = mux->getPort(ID(B)); + RTLIL::SigSpec mux_s = mux->getPort(ID(S)); RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); RTLIL::SigSpec shared_pmux_b; @@ -221,49 +216,48 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< int conn_width = ports[0].sig.size(); int conn_offset = ports[0].mux_port_offset; - shared_op->setPort("\\Y", shared_op->getPort("\\Y").extract(0, conn_width)); + shared_op->setPort(ID(Y), shared_op->getPort(ID(Y)).extract(0, conn_width)); - if (mux->type == "$pmux") { + if (mux->type == ID($pmux)) { shared_pmux_s = RTLIL::SigSpec(); for (const auto &p : ports) { shared_pmux_s.append(mux_s[p.mux_port_id]); - mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort("\\Y")); + mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID(Y))); } } else { shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)}; - mux_a.replace(conn_offset, shared_op->getPort("\\Y")); - mux_b.replace(conn_offset, shared_op->getPort("\\Y")); + mux_a.replace(conn_offset, shared_op->getPort(ID(Y))); + mux_b.replace(conn_offset, shared_op->getPort(ID(Y))); } - mux->setPort("\\A", mux_a); - mux->setPort("\\B", mux_b); - mux->setPort("\\Y", mux_y); - mux->setPort("\\S", mux_s); + mux->setPort(ID(A), mux_a); + mux->setPort(ID(B), mux_b); + mux->setPort(ID(Y), mux_y); + mux->setPort(ID(S), mux_s); for (const auto &op : muxed_operands) shared_pmux_b.append(op.sig); auto mux_to_oper = module->Pmux(NEW_ID, shared_pmux_a, shared_pmux_b, shared_pmux_s); - if (shared_op->type.in("$alu")) { - RTLIL::SigSpec alu_x = shared_op->getPort("\\X"); - RTLIL::SigSpec alu_co = shared_op->getPort("\\CO"); + if (shared_op->type.in(ID($alu))) { + RTLIL::SigSpec alu_x = shared_op->getPort(ID(X)); + RTLIL::SigSpec alu_co = shared_op->getPort(ID(CO)); - shared_op->setPort("\\X", alu_x.extract(0, conn_width)); - shared_op->setPort("\\CO", alu_co.extract(0, conn_width)); + shared_op->setPort(ID(X), alu_x.extract(0, conn_width)); + shared_op->setPort(ID(CO), alu_co.extract(0, conn_width)); } - shared_op->setParam("\\Y_WIDTH", conn_width); + shared_op->setParam(ID(Y_WIDTH), conn_width); - if (decode_port(shared_op, "\\A", &assign_map) == operand) { - shared_op->setPort("\\B", mux_to_oper); - shared_op->setParam("\\B_WIDTH", max_width); + if (decode_port(shared_op, ID(A), &assign_map) == operand) { + shared_op->setPort(ID(B), mux_to_oper); + shared_op->setParam(ID(B_WIDTH), max_width); } else { - shared_op->setPort("\\A", mux_to_oper); - shared_op->setParam("\\A_WIDTH", max_width); + shared_op->setPort(ID(A), mux_to_oper); + shared_op->setParam(ID(A_WIDTH), max_width); } - } typedef struct { @@ -285,7 +279,6 @@ template void remove_val(std::vector &v, const std::vector &v void check_muxed_operands(std::vector &ports, const ExtSigSpec &shared_operand) { - auto it = ports.begin(); ExtSigSpec seed; @@ -293,9 +286,9 @@ void check_muxed_operands(std::vector &ports, const ExtSigSpe auto p = *it; auto op = p->op; - RTLIL::IdString muxed_port_name = "\\A"; - if (decode_port(op, "\\A", &assign_map) == shared_operand) { - muxed_port_name = "\\B"; + RTLIL::IdString muxed_port_name = ID(A); + if (decode_port(op, ID(A), &assign_map) == shared_operand) { + muxed_port_name = ID(B); } auto operand = decode_port(op, muxed_port_name, &assign_map); @@ -322,7 +315,7 @@ ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vectorop; - for (RTLIL::IdString port_name : {"\\A", "\\B"}) { + for (RTLIL::IdString port_name : {ID(A), ID(B)}) { oper = decode_port(op_a, port_name, &assign_map); auto operand_users = operand_to_users.at(oper); @@ -362,78 +355,77 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d std::function remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) { auto aux_outsig = op_aux_to_outsig.at(auxbit); auto op = outsig_to_operator.at(aux_outsig); - auto op_outsig = assign_map(op->getPort("\\Y")); + auto op_outsig = assign_map(op->getPort(ID(Y))); remove_outsig(op_outsig); for (auto aux_outbit : aux_outsig) op_aux_to_outsig.erase(aux_outbit); }; - std::function - find_op_mux_conns = [&](RTLIL::Cell *mux) { - RTLIL::SigSpec sig; - int mux_port_size; + std::function find_op_mux_conns = [&](RTLIL::Cell *mux) { + RTLIL::SigSpec sig; + int mux_port_size; - if (mux->type.in("$mux", "$_MUX_")) { - mux_port_size = mux->getPort("\\A").size(); - sig = RTLIL::SigSpec{mux->getPort("\\B"), mux->getPort("\\A")}; - } else { - mux_port_size = mux->getPort("\\A").size(); - sig = mux->getPort("\\B"); - } + if (mux->type.in(ID($mux), ID($_MUX_))) { + mux_port_size = mux->getPort(ID(A)).size(); + sig = RTLIL::SigSpec{mux->getPort(ID(B)), mux->getPort(ID(A))}; + } else { + mux_port_size = mux->getPort(ID(A)).size(); + sig = mux->getPort(ID(B)); + } - auto mux_insig = assign_map(sig); + auto mux_insig = assign_map(sig); - for (int i = 0; i < mux_insig.size(); ++i) { - if (op_aux_to_outsig.count(mux_insig[i])) { - remove_outsig_from_aux_bit(mux_insig[i]); - continue; - } + for (int i = 0; i < mux_insig.size(); ++i) { + if (op_aux_to_outsig.count(mux_insig[i])) { + remove_outsig_from_aux_bit(mux_insig[i]); + continue; + } - if (!op_outbit_to_outsig.count(mux_insig[i])) - continue; + if (!op_outbit_to_outsig.count(mux_insig[i])) + continue; - auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]); + auto op_outsig = op_outbit_to_outsig.at(mux_insig[i]); - if (op_mux_conn_map.count(op_outsig)) { - remove_outsig(op_outsig); - continue; - } + if (op_mux_conn_map.count(op_outsig)) { + remove_outsig(op_outsig); + continue; + } - int mux_port_id = i / mux_port_size; - int mux_port_offset = i % mux_port_size; + int mux_port_id = i / mux_port_size; + int mux_port_offset = i % mux_port_size; - int op_outsig_offset; - for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset) - ; + int op_outsig_offset; + for (op_outsig_offset = 0; op_outsig[op_outsig_offset] != mux_insig[i]; ++op_outsig_offset) + ; - int j = op_outsig_offset; - do { - if (!op_outbit_to_outsig.count(mux_insig[i])) - break; + int j = op_outsig_offset; + do { + if (!op_outbit_to_outsig.count(mux_insig[i])) + break; - if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig) - break; + if (op_outbit_to_outsig.at(mux_insig[i]) != op_outsig) + break; - ++i; - ++j; - } while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size())); + ++i; + ++j; + } while ((i / mux_port_size == mux_port_id) && (j < op_outsig.size())); - int op_conn_width = j - op_outsig_offset; - OpMuxConn inp = { - op_outsig.extract(op_outsig_offset, op_conn_width), - mux, - outsig_to_operator.at(op_outsig), - mux_port_id, - mux_port_offset, - op_outsig_offset, - }; + int op_conn_width = j - op_outsig_offset; + OpMuxConn inp = { + op_outsig.extract(op_outsig_offset, op_conn_width), + mux, + outsig_to_operator.at(op_outsig), + mux_port_id, + mux_port_offset, + op_outsig_offset, + }; - op_mux_conn_map[op_outsig] = inp; + op_mux_conn_map[op_outsig] = inp; - --i; - } - }; + --i; + } + }; std::function remove_connected_ops = [&](RTLIL::SigSpec sig) { auto mux_insig = assign_map(sig); @@ -451,8 +443,8 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d }; for (auto cell : module->cells()) { - if (cell->type.in("$mux", "$_MUX_", "$pmux")) { - remove_connected_ops(cell->getPort("\\S")); + if (cell->type.in(ID($mux), ID($_MUX_), ID($pmux))) { + remove_connected_ops(cell->getPort(ID(S))); find_op_mux_conns(cell); } else { for (auto &conn : cell->connections()) @@ -509,8 +501,8 @@ struct OptSharePass : public Pass { if (!cell_supported(cell)) continue; - if (cell->type == "$alu") { - for (RTLIL::IdString port_name : {"\\X", "\\CO"}) { + if (cell->type == ID($alu)) { + for (RTLIL::IdString port_name : {ID(X), ID(CO)}) { auto mux_insig = assign_map(cell->getPort(port_name)); outsig_to_operator[mux_insig] = cell; for (auto outbit : mux_insig) @@ -518,12 +510,12 @@ struct OptSharePass : public Pass { } } - auto mux_insig = assign_map(cell->getPort("\\Y")); + auto mux_insig = assign_map(cell->getPort(ID(Y))); outsig_to_operator[mux_insig] = cell; for (auto outbit : mux_insig) op_outbit_to_outsig[outbit] = mux_insig; - for (RTLIL::IdString port_name : {"\\A", "\\B"}) { + for (RTLIL::IdString port_name : {ID(A), ID(B)}) { auto op_insig = decode_port(cell, port_name, &assign_map); op_insigs.push_back(op_insig); operand_to_users[op_insig].insert(cell); @@ -549,10 +541,10 @@ struct OptSharePass : public Pass { if (mux_port_conns.size() == 0) { int mux_port_num; - if (p.mux->type.in("$mux", "$_MUX_")) + if (p.mux->type.in(ID($mux), ID($_MUX_))) mux_port_num = 2; else - mux_port_num = p.mux->getPort("\\S").size(); + mux_port_num = p.mux->getPort(ID(S)).size(); mux_port_conns.resize(mux_port_num); } -- cgit v1.2.3 From f42ba811b63e38be8b921c8896e340404b6a5ac5 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 19 Aug 2019 10:11:47 -0700 Subject: ID({A,B,Y}) -> ID::{A,B,Y} for opt_share.cc --- passes/opt/opt_share.cc | 60 ++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index 734cbcf81..c53fb3113 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -127,7 +127,7 @@ bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_name) { - if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID(B)) + if (cell->type.in(ID($lt), ID($le), ID($ge), ID($gt), ID($div), ID($mod), ID($concat), SHIFT_OPS) && port_name == ID::B) return port_name; return ""; @@ -135,9 +135,9 @@ RTLIL::IdString decode_port_semantics(RTLIL::Cell *cell, RTLIL::IdString port_na RTLIL::SigSpec decode_port_sign(RTLIL::Cell *cell, RTLIL::IdString port_name) { - if (cell->type == ID($alu) && port_name == ID(B)) + if (cell->type == ID($alu) && port_name == ID::B) return cell->getPort(ID(BI)); - else if (cell->type == ID($sub) && port_name == ID(B)) + else if (cell->type == ID($sub) && port_name == ID::B) return RTLIL::Const(1, 1); return RTLIL::Const(0, 1); @@ -173,9 +173,9 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< for (const auto& p : ports) { auto op = p.op; - RTLIL::IdString muxed_port_name = ID(A); - if (decode_port(op, ID(A), &assign_map) == operand) - muxed_port_name = ID(B); + RTLIL::IdString muxed_port_name = ID::A; + if (decode_port(op, ID::A, &assign_map) == operand) + muxed_port_name = ID::B; auto operand = decode_port(op, muxed_port_name, &assign_map); if (operand.sig.size() > max_width) @@ -204,9 +204,9 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< if (muxed_op.sign != muxed_operands[0].sign) muxed_op = ExtSigSpec(module->Neg(NEW_ID, muxed_op.sig, muxed_op.is_signed)); - RTLIL::SigSpec mux_y = mux->getPort(ID(Y)); - RTLIL::SigSpec mux_a = mux->getPort(ID(A)); - RTLIL::SigSpec mux_b = mux->getPort(ID(B)); + RTLIL::SigSpec mux_y = mux->getPort(ID::Y); + RTLIL::SigSpec mux_a = mux->getPort(ID::A); + RTLIL::SigSpec mux_b = mux->getPort(ID::B); RTLIL::SigSpec mux_s = mux->getPort(ID(S)); RTLIL::SigSpec shared_pmux_a = RTLIL::Const(RTLIL::State::Sx, max_width); @@ -216,24 +216,24 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< int conn_width = ports[0].sig.size(); int conn_offset = ports[0].mux_port_offset; - shared_op->setPort(ID(Y), shared_op->getPort(ID(Y)).extract(0, conn_width)); + shared_op->setPort(ID::Y, shared_op->getPort(ID::Y).extract(0, conn_width)); if (mux->type == ID($pmux)) { shared_pmux_s = RTLIL::SigSpec(); for (const auto &p : ports) { shared_pmux_s.append(mux_s[p.mux_port_id]); - mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID(Y))); + mux_b.replace(p.mux_port_id * mux_a.size() + conn_offset, shared_op->getPort(ID::Y)); } } else { shared_pmux_s = RTLIL::SigSpec{mux_s, module->Not(NEW_ID, mux_s)}; - mux_a.replace(conn_offset, shared_op->getPort(ID(Y))); - mux_b.replace(conn_offset, shared_op->getPort(ID(Y))); + mux_a.replace(conn_offset, shared_op->getPort(ID::Y)); + mux_b.replace(conn_offset, shared_op->getPort(ID::Y)); } - mux->setPort(ID(A), mux_a); - mux->setPort(ID(B), mux_b); - mux->setPort(ID(Y), mux_y); + mux->setPort(ID::A, mux_a); + mux->setPort(ID::B, mux_b); + mux->setPort(ID::Y, mux_y); mux->setPort(ID(S), mux_s); for (const auto &op : muxed_operands) @@ -251,11 +251,11 @@ void merge_operators(RTLIL::Module *module, RTLIL::Cell *mux, const std::vector< shared_op->setParam(ID(Y_WIDTH), conn_width); - if (decode_port(shared_op, ID(A), &assign_map) == operand) { - shared_op->setPort(ID(B), mux_to_oper); + if (decode_port(shared_op, ID::A, &assign_map) == operand) { + shared_op->setPort(ID::B, mux_to_oper); shared_op->setParam(ID(B_WIDTH), max_width); } else { - shared_op->setPort(ID(A), mux_to_oper); + shared_op->setPort(ID::A, mux_to_oper); shared_op->setParam(ID(A_WIDTH), max_width); } } @@ -286,9 +286,9 @@ void check_muxed_operands(std::vector &ports, const ExtSigSpe auto p = *it; auto op = p->op; - RTLIL::IdString muxed_port_name = ID(A); - if (decode_port(op, ID(A), &assign_map) == shared_operand) { - muxed_port_name = ID(B); + RTLIL::IdString muxed_port_name = ID::A; + if (decode_port(op, ID::A, &assign_map) == shared_operand) { + muxed_port_name = ID::B; } auto operand = decode_port(op, muxed_port_name, &assign_map); @@ -315,7 +315,7 @@ ExtSigSpec find_shared_operand(const OpMuxConn* seed, std::vectorop; - for (RTLIL::IdString port_name : {ID(A), ID(B)}) { + for (RTLIL::IdString port_name : {ID::A, ID::B}) { oper = decode_port(op_a, port_name, &assign_map); auto operand_users = operand_to_users.at(oper); @@ -355,7 +355,7 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d std::function remove_outsig_from_aux_bit = [&](RTLIL::SigBit auxbit) { auto aux_outsig = op_aux_to_outsig.at(auxbit); auto op = outsig_to_operator.at(aux_outsig); - auto op_outsig = assign_map(op->getPort(ID(Y))); + auto op_outsig = assign_map(op->getPort(ID::Y)); remove_outsig(op_outsig); for (auto aux_outbit : aux_outsig) @@ -367,11 +367,11 @@ dict find_valid_op_mux_conns(RTLIL::Module *module, d int mux_port_size; if (mux->type.in(ID($mux), ID($_MUX_))) { - mux_port_size = mux->getPort(ID(A)).size(); - sig = RTLIL::SigSpec{mux->getPort(ID(B)), mux->getPort(ID(A))}; + mux_port_size = mux->getPort(ID::A).size(); + sig = RTLIL::SigSpec{mux->getPort(ID::B), mux->getPort(ID::A)}; } else { - mux_port_size = mux->getPort(ID(A)).size(); - sig = mux->getPort(ID(B)); + mux_port_size = mux->getPort(ID::A).size(); + sig = mux->getPort(ID::B); } auto mux_insig = assign_map(sig); @@ -510,12 +510,12 @@ struct OptSharePass : public Pass { } } - auto mux_insig = assign_map(cell->getPort(ID(Y))); + auto mux_insig = assign_map(cell->getPort(ID::Y)); outsig_to_operator[mux_insig] = cell; for (auto outbit : mux_insig) op_outbit_to_outsig[outbit] = mux_insig; - for (RTLIL::IdString port_name : {ID(A), ID(B)}) { + for (RTLIL::IdString port_name : {ID::A, ID::B}) { auto op_insig = decode_port(cell, port_name, &assign_map); op_insigs.push_back(op_insig); operand_to_users[op_insig].insert(cell); -- cgit v1.2.3 From d3a212ff91de5e4f082f2c133becd4338661ac16 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 21 Aug 2019 19:18:05 -0700 Subject: opt_expr to trim A port of $shiftx if Y_WIDTH == 1 --- passes/opt/opt_expr.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 858b3560c..b56ce252f 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -745,6 +745,23 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } + if (cell->type == ID($shiftx) && cell->getPort(ID::Y).size() == 1) { + SigSpec sig_a = assign_map(cell->getPort(ID::A)); + int width; + for (width = GetSize(sig_a); width > 1; width--) { + if (sig_a[width-1] != State::Sx) + break; + } + + if (width < GetSize(sig_a)) { + sig_a.remove(width, GetSize(sig_a)-width); + cell->setPort(ID::A, sig_a); + cell->setParam(ID(A_WIDTH), width); + did_something = true; + goto next_cell; + } + } + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 && invert_map.count(assign_map(cell->getPort(ID::A))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); -- cgit v1.2.3 From d0ffe7544cd3c808857f3a99bbf330de61c618f2 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 08:05:01 -0700 Subject: Canonical form --- passes/opt/opt_expr.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index b56ce252f..7fdfa82bd 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -369,7 +369,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons for (auto cell : module->cells()) if (design->selected(module, cell) && cell->type[0] == '$') { if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && - cell->getPort(ID::A).size() == 1 && cell->getPort(ID::Y).size() == 1) + GetSize(cell->getPort(ID::A)) == 1 && GetSize(cell->getPort(ID::Y)) == 1) invert_map[assign_map(cell->getPort(ID::Y))] = assign_map(cell->getPort(ID::A)); if (cell->type.in(ID($mux), ID($_MUX_)) && cell->getPort(ID::A) == SigSpec(State::S1) && cell->getPort(ID::B) == SigSpec(State::S0)) @@ -740,12 +740,12 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($reduce_xor), ID($reduce_xnor), ID($lt), ID($le), ID($ge), ID($gt))) replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::State::Sx); else - replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, cell->getPort(ID::Y).size())); + replace_cell(assign_map, module, cell, "x-bit in input", ID::Y, RTLIL::SigSpec(RTLIL::State::Sx, GetSize(cell->getPort(ID::Y)))); goto next_cell; } } - if (cell->type == ID($shiftx) && cell->getPort(ID::Y).size() == 1) { + if (cell->type == ID($shiftx) && GetSize(cell->getPort(ID::Y)) == 1) { SigSpec sig_a = assign_map(cell->getPort(ID::A)); int width; for (width = GetSize(sig_a); width > 1; width--) { @@ -762,7 +762,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && cell->getPort(ID::Y).size() == 1 && + if (cell->type.in(ID($_NOT_), ID($not), ID($logic_not)) && GetSize(cell->getPort(ID::Y)) == 1 && invert_map.count(assign_map(cell->getPort(ID::A))) != 0) { cover_list("opt.opt_expr.invert.double", "$_NOT_", "$not", "$logic_not", cell->type.str()); replace_cell(assign_map, module, cell, "double_invert", ID::Y, invert_map.at(assign_map(cell->getPort(ID::A)))); @@ -1159,7 +1159,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (mux_undef && cell->type.in(ID($mux), ID($pmux))) { RTLIL::SigSpec new_a, new_b, new_s; - int width = cell->getPort(ID::A).size(); + int width = GetSize(cell->getPort(ID::A)); if ((cell->getPort(ID::A).is_fully_undef() && cell->getPort(ID::B).is_fully_undef()) || cell->getPort(ID(S)).is_fully_undef()) { cover_list("opt.opt_expr.mux_undef", "$mux", "$pmux", cell->type.str()); -- cgit v1.2.3 From 9e31f01b343a9b246430419e81da647e75bd1626 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 08:06:24 -0700 Subject: Add cover() --- passes/opt/opt_expr.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 7fdfa82bd..aca15e5f2 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -754,6 +754,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (width < GetSize(sig_a)) { + cover("opt.opt_expr.trim_shiftx"); sig_a.remove(width, GetSize(sig_a)-width); cell->setPort(ID::A, sig_a); cell->setParam(ID(A_WIDTH), width); -- cgit v1.2.3 From 379f33af5489850ef8e2e58ef12ff5b22da87711 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 08:22:23 -0700 Subject: Handle $shift and Y_WIDTH > 1 as per @cliffordwolf --- passes/opt/opt_expr.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index aca15e5f2..c4da613ab 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -745,16 +745,20 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } } - if (cell->type == ID($shiftx) && GetSize(cell->getPort(ID::Y)) == 1) { + if (cell->type.in(ID($shiftx), ID($shift))) { SigSpec sig_a = assign_map(cell->getPort(ID::A)); int width; + bool trim_x = true; + bool trim_0 = cell->type == ID($shift); for (width = GetSize(sig_a); width > 1; width--) { - if (sig_a[width-1] != State::Sx) - break; + if ((trim_x && sig_a[width-1] == State::Sx) || + (trim_0 && sig_a[width-1] == State::S0)) + continue; + break; } if (width < GetSize(sig_a)) { - cover("opt.opt_expr.trim_shiftx"); + cover_list("opt.opt_expr.xbit", "$shiftx", "$shift", cell->type.str()); sig_a.remove(width, GetSize(sig_a)-width); cell->setPort(ID::A, sig_a); cell->setParam(ID(A_WIDTH), width); -- cgit v1.2.3 From 6f971470f83b8e4ed29232be4b6cb5da89d50dc0 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 08:37:27 -0700 Subject: Respect opt_expr -keepdc as per @cliffordwolf --- passes/opt/opt_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index c4da613ab..73f48317a 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -748,7 +748,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons if (cell->type.in(ID($shiftx), ID($shift))) { SigSpec sig_a = assign_map(cell->getPort(ID::A)); int width; - bool trim_x = true; + bool trim_x = cell->type == ID($shiftx) || !keepdc; bool trim_0 = cell->type == ID($shift); for (width = GetSize(sig_a); width > 1; width--) { if ((trim_x && sig_a[width-1] == State::Sx) || -- cgit v1.2.3 From 9245f0d3f564644290b6650b3f8f642789062e9e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 22 Aug 2019 08:43:44 -0700 Subject: Copy-paste typo --- passes/opt/opt_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 73f48317a..00d7d6063 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -758,7 +758,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (width < GetSize(sig_a)) { - cover_list("opt.opt_expr.xbit", "$shiftx", "$shift", cell->type.str()); + cover_list("opt.opt_expr.trim", "$shiftx", "$shift", cell->type.str()); sig_a.remove(width, GetSize(sig_a)-width); cell->setPort(ID::A, sig_a); cell->setParam(ID(A_WIDTH), width); -- cgit v1.2.3 From 8d128ba6d079fd5f0741c31a9308bf06aaf4673c Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Mon, 9 Sep 2019 12:40:01 +0800 Subject: passes: opt_share: don't statically initialize mergeable_type_map In 3d3779b0376b8204ed7637053176a07b7271ac1d this got turned from a `std::map` to `std::map`. Consequently, this exposed some initialization sequencing issues (#1361). Only initialize the map when it's first used, to avoid these static issues. This fixes #1361. Signed-off-by: Sean Cross --- passes/opt/opt_share.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'passes/opt') diff --git a/passes/opt/opt_share.cc b/passes/opt/opt_share.cc index c53fb3113..2c456705c 100644 --- a/passes/opt/opt_share.cc +++ b/passes/opt/opt_share.cc @@ -108,12 +108,13 @@ bool cell_supported(RTLIL::Cell *cell) return false; } -std::map mergeable_type_map{ - {ID($sub), ID($add)}, -}; +std::map mergeable_type_map; bool mergeable(RTLIL::Cell *a, RTLIL::Cell *b) { + if (mergeable_type_map.empty()) { + mergeable_type_map.insert({ID($sub), ID($add)}); + } auto a_type = a->type; if (mergeable_type_map.count(a_type)) a_type = mergeable_type_map.at(a_type); -- cgit v1.2.3 From a67d63714be52e4a4f789c2a82b6283748db8902 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 13 Sep 2019 13:39:39 +0200 Subject: Fix handling of z_digit "?" and fix optimization of cmp with "z" Signed-off-by: Clifford Wolf --- passes/opt/opt_expr.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'passes/opt') diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 00d7d6063..6cf66fb95 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -953,6 +953,10 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons } if (b.is_fully_const()) { + if (b.is_fully_undef()) { + RTLIL::SigSpec input = b; + ACTION_DO(ID::Y, Const(State::Sx, GetSize(cell->getPort(ID::Y)))); + } else if (b.as_bool() == (cell->type == ID($eq))) { RTLIL::SigSpec input = b; ACTION_DO(ID::Y, cell->getPort(ID::A)); -- cgit v1.2.3