aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/Makefile.inc1
-rw-r--r--passes/techmap/abc.cc44
-rw-r--r--passes/techmap/abc9.cc13
-rw-r--r--passes/techmap/abc9_exe.cc16
-rw-r--r--passes/techmap/abc9_ops.cc40
-rw-r--r--passes/techmap/bmuxmap.cc39
-rw-r--r--passes/techmap/bwmuxmap.cc70
-rw-r--r--passes/techmap/dfflegalize.cc38
-rw-r--r--passes/techmap/dfflibmap.cc2
-rw-r--r--passes/techmap/dffunmap.cc4
-rw-r--r--passes/techmap/flowmap.cc3
-rw-r--r--passes/techmap/insbuf.cc40
-rw-r--r--passes/techmap/simplemap.cc49
-rw-r--r--passes/techmap/simplemap.h1
-rw-r--r--passes/techmap/techmap.cc18
15 files changed, 263 insertions, 115 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 98ccfc303..1b834fabc 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -31,6 +31,7 @@ OBJS += passes/techmap/dffinit.o
OBJS += passes/techmap/pmuxtree.o
OBJS += passes/techmap/bmuxmap.o
OBJS += passes/techmap/demuxmap.o
+OBJS += passes/techmap/bwmuxmap.o
OBJS += passes/techmap/muxcover.o
OBJS += passes/techmap/aigmap.o
OBJS += passes/techmap/tribuf.o
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 61ee99ee7..da601a856 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -29,11 +29,11 @@
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
// http://en.wikipedia.org/wiki/Topological_sorting
-#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
-#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
-#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
-#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
-#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
+#define ABC_COMMAND_LIB "strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
+#define ABC_COMMAND_CTR "strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
+#define ABC_COMMAND_LUT "strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; dch -f; if; mfs2"
+#define ABC_COMMAND_SOP "strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
+#define ABC_COMMAND_DFL "strash; &get -n; &fraig -x; &put; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
@@ -65,7 +65,9 @@
#include "frontends/blif/blifparse.h"
#ifdef YOSYS_LINK_ABC
-extern "C" int Abc_RealMain(int argc, char *argv[]);
+namespace abc {
+ int Abc_RealMain(int argc, char *argv[]);
+}
#endif
USING_YOSYS_NAMESPACE
@@ -780,22 +782,25 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
if (dff_mode && clk_sig.empty())
log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
- std::string tempdir_name = get_base_tmpdir() + "/" + proc_program_prefix()+ "yosys-abc-XXXXXX";
- if (!cleanup)
- tempdir_name[0] = tempdir_name[4] = '_';
+ std::string tempdir_name;
+ if (cleanup)
+ tempdir_name = get_base_tmpdir() + "/";
+ else
+ tempdir_name = "_tmp_";
+ tempdir_name += proc_program_prefix() + "yosys-abc-XXXXXX";
tempdir_name = make_temp_dir(tempdir_name);
log_header(design, "Extracting gate netlist of module `%s' to `%s/input.blif'..\n",
module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
- std::string abc_script = stringf("read_blif %s/input.blif; ", tempdir_name.c_str());
+ std::string abc_script = stringf("read_blif \"%s/input.blif\"; ", tempdir_name.c_str());
if (!liberty_files.empty() || !genlib_files.empty()) {
for (std::string liberty_file : liberty_files)
- abc_script += stringf("read_lib -w %s; ", liberty_file.c_str());
+ abc_script += stringf("read_lib -w \"%s\"; ", liberty_file.c_str());
for (std::string liberty_file : genlib_files)
- abc_script += stringf("read_library %s; ", liberty_file.c_str());
+ abc_script += stringf("read_library \"%s\"; ", liberty_file.c_str());
if (!constr_file.empty())
- abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
+ abc_script += stringf("read_constr -v \"%s\"; ", constr_file.c_str());
} else
if (!lut_costs.empty())
abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
@@ -844,7 +849,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
if (abc_dress)
- abc_script += "; dress";
+ abc_script += stringf("; dress \"%s/input.blif\"", tempdir_name.c_str());
abc_script += stringf("; write_blif %s/output.blif", tempdir_name.c_str());
abc_script = add_echos_to_abc_cmd(abc_script);
@@ -1083,7 +1088,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
fclose(f);
}
- buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
+ buffer = stringf("\"%s\" -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
#ifndef YOSYS_LINK_ABC
@@ -1098,7 +1103,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
abc_argv[2] = strdup("-f");
abc_argv[3] = strdup(tmp_script_name.c_str());
abc_argv[4] = 0;
- int ret = Abc_RealMain(4, abc_argv);
+ int ret = abc::Abc_RealMain(4, abc_argv);
free(abc_argv[0]);
free(abc_argv[1]);
free(abc_argv[2]);
@@ -1530,7 +1535,8 @@ struct AbcPass : public Pass {
log(" NMUX, AOI3, OAI3, AOI4, OAI4.\n");
log(" (The NOT gate is always added to this list automatically.)\n");
log("\n");
- log(" The following aliases can be used to reference common sets of gate types:\n");
+ log(" The following aliases can be used to reference common sets of gate\n");
+ log(" types:\n");
log(" simple: AND OR XOR MUX\n");
log(" cmos2: NAND NOR\n");
log(" cmos3: NAND NOR AOI3 OAI3\n");
@@ -1574,8 +1580,8 @@ struct AbcPass : public Pass {
log("\n");
log(" -dress\n");
log(" run the 'dress' command after all other ABC commands. This aims to\n");
- log(" preserve naming by an equivalence check between the original and post-ABC\n");
- log(" netlists (experimental).\n");
+ log(" preserve naming by an equivalence check between the original and\n");
+ log(" post-ABC netlists (experimental).\n");
log("\n");
log("When no target cell library is specified the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index 79c994b11..876917e56 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -93,8 +93,8 @@ struct Abc9Pass : public ScriptPass
log("\n");
log(" abc9 [options] [selection]\n");
log("\n");
- log("This script pass performs a sequence of commands to facilitate the use of the ABC\n");
- log("tool [1] for technology mapping of the current design to a target FPGA\n");
+ log("This script pass performs a sequence of commands to facilitate the use of the\n");
+ log("ABC tool [1] for technology mapping of the current design to a target FPGA\n");
log("architecture. Only fully-selected modules are supported.\n");
log("\n");
log(" -run <from_label>:<to_label>\n");
@@ -404,9 +404,12 @@ struct Abc9Pass : public ScriptPass
if (!active_design->selected_whole_module(mod))
log_error("Can't handle partially selected module %s!\n", log_id(mod));
- std::string tempdir_name = get_base_tmpdir() + "/" + proc_program_prefix() + "yosys-abc-XXXXXX";
- if (!cleanup)
- tempdir_name[0] = tempdir_name[4] = '_';
+ std::string tempdir_name;
+ if (cleanup)
+ tempdir_name = get_base_tmpdir() + "/";
+ else
+ tempdir_name = "_tmp_";
+ tempdir_name += proc_program_prefix() + "yosys-abc-XXXXXX";
tempdir_name = make_temp_dir(tempdir_name);
if (!lut_mode)
diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc
index a66e95e21..1d9bb4332 100644
--- a/passes/techmap/abc9_exe.cc
+++ b/passes/techmap/abc9_exe.cc
@@ -31,7 +31,9 @@
#endif
#ifdef YOSYS_LINK_ABC
-extern "C" int Abc_RealMain(int argc, char *argv[]);
+namespace abc {
+ int Abc_RealMain(int argc, char *argv[]);
+}
#endif
std::string fold_abc9_cmd(std::string str)
@@ -173,12 +175,12 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
if (!lut_costs.empty())
abc9_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
else if (!lut_file.empty())
- abc9_script += stringf("read_lut %s; ", lut_file.c_str());
+ abc9_script += stringf("read_lut \"%s\"; ", lut_file.c_str());
else
log_abort();
log_assert(!box_file.empty());
- abc9_script += stringf("read_box %s; ", box_file.c_str());
+ abc9_script += stringf("read_box \"%s\"; ", box_file.c_str());
abc9_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
if (!script_file.empty()) {
@@ -262,7 +264,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
fclose(f);
}
- buffer = stringf("%s -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
+ buffer = stringf("\"%s\" -s -f %s/abc.script 2>&1", exe_file.c_str(), tempdir_name.c_str());
log("Running ABC command: %s\n", replace_tempdir(buffer, tempdir_name, show_tempdir).c_str());
#ifndef YOSYS_LINK_ABC
@@ -277,7 +279,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe
abc9_argv[2] = strdup("-f");
abc9_argv[3] = strdup(tmp_script_name.c_str());
abc9_argv[4] = 0;
- int ret = Abc_RealMain(4, abc9_argv);
+ int ret = abc::Abc_RealMain(4, abc9_argv);
free(abc9_argv[0]);
free(abc9_argv[1]);
free(abc9_argv[2]);
@@ -301,8 +303,8 @@ struct Abc9ExePass : public Pass {
log("\n");
log(" \n");
log("This pass uses the ABC tool [1] for technology mapping of the top module\n");
- log("(according to the (* top *) attribute or if only one module is currently selected)\n");
- log("to a target FPGA architecture.\n");
+ log("(according to the (* top *) attribute or if only one module is currently\n");
+ log("selected) to a target FPGA architecture.\n");
log("\n");
log(" -exe <command>\n");
#ifdef ABCEXTERNAL
diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc
index acafb0b65..9766e81cb 100644
--- a/passes/techmap/abc9_ops.cc
+++ b/passes/techmap/abc9_ops.cc
@@ -1572,14 +1572,14 @@ struct Abc9OpsPass : public Pass {
log("the `abc9' script pass. Only fully-selected modules are supported.\n");
log("\n");
log(" -check\n");
- log(" check that the design is valid, e.g. (* abc9_box_id *) values are unique,\n");
- log(" (* abc9_carry *) is only given for one input/output port, etc.\n");
+ log(" check that the design is valid, e.g. (* abc9_box_id *) values are\n");
+ log(" unique, (* abc9_carry *) is only given for one input/output port, etc.\n");
log("\n");
log(" -prep_hier\n");
log(" derive all used (* abc9_box *) or (* abc9_flop *) (if -dff option)\n");
log(" whitebox modules. with (* abc9_flop *) modules, only those containing\n");
- log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC limitation\n");
- log(" -- will be derived.\n");
+ log(" $dff/$_DFF_[NP]_ cells with zero initial state -- due to an ABC\n");
+ log(" limitation -- will be derived.\n");
log("\n");
log(" -prep_bypass\n");
log(" create techmap rules in the '$abc9_map' and '$abc9_unmap' designs for\n");
@@ -1597,33 +1597,35 @@ struct Abc9OpsPass : public Pass {
log(" -prep_dff_submod\n");
log(" within (* abc9_flop *) modules, rewrite all edge-sensitive path\n");
log(" declarations and $setup() timing checks ($specify3 and $specrule cells)\n");
- log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port to\n");
- log(" the DFF's 'D' port. this is to prepare such specify cells to be moved\n");
+ log(" that share a 'DST' port with the $_DFF_[NP]_.Q port from this 'Q' port\n");
+ log(" to the DFF's 'D' port. this is to prepare such specify cells to be moved\n");
log(" into the flop box.\n");
log("\n");
log(" -prep_dff_unmap\n");
- log(" populate the '$abc9_unmap' design with techmap rules for mapping *_$abc9_flop\n");
- log(" cells back into their derived cell types (where the rules created by\n");
- log(" -prep_hier will then map back to the original cell with parameters).\n");
+ log(" populate the '$abc9_unmap' design with techmap rules for mapping\n");
+ log(" *_$abc9_flop cells back into their derived cell types (where the rules\n");
+ log(" created by -prep_hier will then map back to the original cell with\n");
+ log(" parameters).\n");
log("\n");
log(" -prep_delays\n");
log(" insert `$__ABC9_DELAY' blackbox cells into the design to account for\n");
log(" certain required times.\n");
log("\n");
log(" -break_scc\n");
- log(" for an arbitrarily chosen cell in each unique SCC of each selected module\n");
- log(" (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt all wires\n");
- log(" driven by this cell's outputs with a temporary $__ABC9_SCC_BREAKER cell\n");
- log(" to break the SCC.\n");
+ log(" for an arbitrarily chosen cell in each unique SCC of each selected\n");
+ log(" module (tagged with an (* abc9_scc_id = <int> *) attribute) interrupt\n");
+ log(" all wires driven by this cell's outputs with a temporary\n");
+ log(" $__ABC9_SCC_BREAKER cell to break the SCC.\n");
log("\n");
log(" -prep_xaiger\n");
log(" prepare the design for XAIGER output. this includes computing the\n");
- log(" topological ordering of ABC9 boxes, as well as preparing the '$abc9_holes'\n");
- log(" design that contains the logic behaviour of ABC9 whiteboxes.\n");
+ log(" topological ordering of ABC9 boxes, as well as preparing the \n");
+ log(" '$abc9_holes' design that contains the logic behaviour of ABC9\n");
+ log(" whiteboxes.\n");
log("\n");
log(" -dff\n");
- log(" consider flop cells (those instantiating modules marked with (* abc9_flop *))\n");
- log(" during -prep_{delays,xaiger,box}.\n");
+ log(" consider flop cells (those instantiating modules marked with\n");
+ log(" (* abc9_flop *)) during -prep_{delays,xaiger,box}.\n");
log("\n");
log(" -prep_lut <maxlut>\n");
log(" pre-compute the lut library by analysing all modules marked with\n");
@@ -1641,8 +1643,8 @@ struct Abc9OpsPass : public Pass {
log("\n");
log(" -reintegrate\n");
log(" for each selected module, re-intergrate the module '<module-name>$abc9'\n");
- log(" by first recovering ABC9 boxes, and then stitching in the remaining primary\n");
- log(" inputs and outputs.\n");
+ log(" by first recovering ABC9 boxes, and then stitching in the remaining\n");
+ log(" primary inputs and outputs.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
diff --git a/passes/techmap/bmuxmap.cc b/passes/techmap/bmuxmap.cc
index 03673c278..7aa67d3c0 100644
--- a/passes/techmap/bmuxmap.cc
+++ b/passes/techmap/bmuxmap.cc
@@ -33,13 +33,22 @@ struct BmuxmapPass : public Pass {
log("\n");
log("This pass transforms $bmux cells to trees of $mux cells.\n");
log("\n");
+ log(" -pmux\n");
+ log(" transform to $pmux instead of $mux cells.\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
+ bool pmux_mode = false;
+
log_header(design, "Executing BMUXMAP pass.\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-pmux") {
+ pmux_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -53,18 +62,36 @@ struct BmuxmapPass : public Pass {
SigSpec sel = cell->getPort(ID::S);
SigSpec data = cell->getPort(ID::A);
int width = GetSize(cell->getPort(ID::Y));
+ int s_width = GetSize(cell->getPort(ID::S));
- for (int idx = 0; idx < GetSize(sel); idx++) {
- SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
- for (int i = 0; i < GetSize(new_data); i += width) {
- RTLIL::Cell *mux = module->addMux(NEW_ID,
+ if(pmux_mode)
+ {
+ int num_cases = 1 << s_width;
+ SigSpec new_a = SigSpec(State::Sx, width);
+ SigSpec new_s = module->addWire(NEW_ID, num_cases);
+ SigSpec new_data = module->addWire(NEW_ID, width);
+ for (int val = 0; val < num_cases; val++)
+ {
+ module->addEq(NEW_ID, sel, SigSpec(val, GetSize(sel)), new_s[val]);
+ }
+ RTLIL::Cell *pmux = module->addPmux(NEW_ID, new_a, data, new_s, new_data);
+ pmux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ data = new_data;
+ }
+ else
+ {
+ for (int idx = 0; idx < GetSize(sel); idx++) {
+ SigSpec new_data = module->addWire(NEW_ID, GetSize(data)/2);
+ for (int i = 0; i < GetSize(new_data); i += width) {
+ RTLIL::Cell *mux = module->addMux(NEW_ID,
data.extract(i*2, width),
data.extract(i*2+width, width),
sel[idx],
new_data.extract(i, width));
- mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ mux->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ }
+ data = new_data;
}
- data = new_data;
}
module->connect(cell->getPort(ID::Y), data);
diff --git a/passes/techmap/bwmuxmap.cc b/passes/techmap/bwmuxmap.cc
new file mode 100644
index 000000000..7fe1cded7
--- /dev/null
+++ b/passes/techmap/bwmuxmap.cc
@@ -0,0 +1,70 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2022 Jannis Harder <jix@yosyshq.com> <me@jix.one>
+ *
+ * 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"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct BwmuxmapPass : public Pass {
+ BwmuxmapPass() : Pass("bwmuxmap", "replace $bwmux cells with equivalent logic") {}
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" bwmxumap [options] [selection]\n");
+ log("\n");
+ log("This pass replaces $bwmux cells with equivalent logic\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing BWMUXMAP pass.\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ // if (args[argidx] == "-arg") {
+ // continue;
+ // }
+ break;
+ }
+
+ extra_args(args, argidx, design);
+
+ for (auto module : design->selected_modules())
+ for (auto cell : module->selected_cells())
+ {
+ if (cell->type != ID($bwmux))
+ continue;
+ auto &sig_y = cell->getPort(ID::Y);
+ auto &sig_a = cell->getPort(ID::A);
+ auto &sig_b = cell->getPort(ID::B);
+ auto &sig_s = cell->getPort(ID::S);
+
+ auto not_s = module->Not(NEW_ID, sig_s);
+ auto masked_b = module->And(NEW_ID, sig_s, sig_b);
+ auto masked_a = module->And(NEW_ID, not_s, sig_a);
+ module->addOr(NEW_ID, masked_a, masked_b, sig_y);
+
+ module->remove(cell);
+ }
+ }
+} BwmuxmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
index 1d99caa3a..c6c3a58c5 100644
--- a/passes/techmap/dfflegalize.cc
+++ b/passes/techmap/dfflegalize.cc
@@ -118,34 +118,24 @@ struct DffLegalizePass : public Pass {
log("- $_DLATCH_[NP][NP][01]_\n");
log("- $_DLATCHSR_[NP][NP][NP]_\n");
log("\n");
- log("The following transformations are performed by this pass:");
- log("\n");
- log("- upconversion from a less capable cell to a more capable cell, if the less");
- log(" capable cell is not supported (eg. dff -> dffe, or adff -> dffsr)");
- log("\n");
- log("- unmapping FFs with clock enable (due to unsupported cell type or -mince)");
- log("\n");
- log("- unmapping FFs with sync reset (due to unsupported cell type or -minsrst)");
- log("\n");
- log("- adding inverters on the control pins (due to unsupported polarity)");
+ log("The following transformations are performed by this pass:\n");
log("\n");
+ log("- upconversion from a less capable cell to a more capable cell, if the less\n");
+ log(" capable cell is not supported (eg. dff -> dffe, or adff -> dffsr)\n");
+ log("- unmapping FFs with clock enable (due to unsupported cell type or -mince)\n");
+ log("- unmapping FFs with sync reset (due to unsupported cell type or -minsrst)\n");
+ log("- adding inverters on the control pins (due to unsupported polarity)\n");
log("- adding inverters on the D and Q pins and inverting the init/reset values\n");
- log(" (due to unsupported init or reset value)");
- log("\n");
- log("- converting sr into adlatch (by tying D to 1 and using E as set input)");
- log("\n");
- log("- emulating unsupported dffsr cell by adff + adff + sr + mux");
- log("\n");
- log("- emulating unsupported dlatchsr cell by adlatch + adlatch + sr + mux");
- log("\n");
+ log(" (due to unsupported init or reset value)\n");
+ log("- converting sr into adlatch (by tying D to 1 and using E as set input)\n");
+ log("- emulating unsupported dffsr cell by adff + adff + sr + mux\n");
+ log("- emulating unsupported dlatchsr cell by adlatch + adlatch + sr + mux\n");
log("- emulating adff when the (reset, init) value combination is unsupported by\n");
- log(" dff + adff + dlatch + mux");
- log("\n");
+ log(" dff + adff + dlatch + mux\n");
log("- emulating adlatch when the (reset, init) value combination is unsupported by\n");
- log("- dlatch + adlatch + dlatch + mux");
- log("\n");
- log("If the pass is unable to realize a given cell type (eg. adff when only plain dff");
- log("is available), an error is raised.");
+ log("- dlatch + adlatch + dlatch + mux\n");
+ log("If the pass is unable to realize a given cell type (eg. adff when only plain dff\n");
+ log("is available), an error is raised.\n");
}
// Table of all supported cell types.
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 252baae9a..12c3a95de 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -431,7 +431,7 @@ struct DfflibmapPass : public Pass {
log("cells, leaving remaining internal cells untouched.\n");
log("\n");
log("When called with -info, this command will only print the target cell\n");
- log("list, along with their associated internal cell types, and the arguments");
+ log("list, along with their associated internal cell types, and the arguments\n");
log("that would be passed to the dfflegalize pass. The design will not be\n");
log("changed.\n");
log("\n");
diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc
index 7312015f1..8703bf1a0 100644
--- a/passes/techmap/dffunmap.cc
+++ b/passes/techmap/dffunmap.cc
@@ -33,8 +33,8 @@ struct DffunmapPass : public Pass {
log(" dffunmap [options] [selection]\n");
log("\n");
log("This pass transforms FF types with clock enable and/or synchronous reset into\n");
- log("their base type (with neither clock enable nor sync reset) by emulating the clock\n");
- log("enable and synchronous reset with multiplexers on the cell input.\n");
+ log("their base type (with neither clock enable nor sync reset) by emulating the\n");
+ log("clock enable and synchronous reset with multiplexers on the cell input.\n");
log("\n");
log(" -ce-only\n");
log(" unmap only clock enables, leave synchronous resets alone.\n");
diff --git a/passes/techmap/flowmap.cc b/passes/techmap/flowmap.cc
index dfdbe6b88..579503a0b 100644
--- a/passes/techmap/flowmap.cc
+++ b/passes/techmap/flowmap.cc
@@ -1406,7 +1406,8 @@ struct FlowmapWorker
RTLIL::SigSpec lut_a, lut_y = node;
for (auto input_node : input_nodes)
lut_a.append(input_node);
- lut_a.append(RTLIL::Const(State::Sx, minlut - input_nodes.size()));
+ if ((int)input_nodes.size() < minlut)
+ lut_a.append(RTLIL::Const(State::Sx, minlut - input_nodes.size()));
RTLIL::Cell *lut = module->addLut(NEW_ID, lut_a, lut_y, lut_table);
mapped_nodes.insert(node);
diff --git a/passes/techmap/insbuf.cc b/passes/techmap/insbuf.cc
index 68c22c317..f288987a1 100644
--- a/passes/techmap/insbuf.cc
+++ b/passes/techmap/insbuf.cc
@@ -36,12 +36,16 @@ struct InsbufPass : public Pass {
log(" Use the given cell type instead of $_BUF_. (Notice that the next\n");
log(" call to \"clean\" will remove all $_BUF_ in the design.)\n");
log("\n");
+ log(" -chain\n");
+ log(" Chain buffer cells\n");
+ log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing INSBUF pass (insert buffer cells for connected wires).\n");
IdString celltype = ID($_BUF_), in_portname = ID::A, out_portname = ID::Y;
+ bool chain_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -53,6 +57,10 @@ struct InsbufPass : public Pass {
out_portname = RTLIL::escape_id(args[++argidx]);
continue;
}
+ if (arg == "-chain") {
+ chain_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -60,6 +68,8 @@ struct InsbufPass : public Pass {
for (auto module : design->selected_modules())
{
std::vector<RTLIL::SigSig> new_connections;
+ pool<Cell*> bufcells;
+ SigMap sigmap;
for (auto &conn : module->connections())
{
@@ -70,22 +80,48 @@ struct InsbufPass : public Pass {
SigBit lhs = conn.first[i];
SigBit rhs = conn.second[i];
- if (lhs.wire && !design->selected(module, lhs.wire)) {
+ if (!lhs.wire || !design->selected(module, lhs.wire)) {
new_conn.first.append(lhs);
new_conn.second.append(rhs);
+ log("Skip %s: %s -> %s\n", log_id(module), log_signal(rhs), log_signal(lhs));
continue;
}
+ if (chain_mode && rhs.wire) {
+ rhs = sigmap(rhs);
+ SigBit outbit = sigmap(lhs);
+ sigmap.add(lhs, rhs);
+ sigmap.add(outbit);
+ }
+
Cell *cell = module->addCell(NEW_ID, celltype);
cell->setPort(in_portname, rhs);
cell->setPort(out_portname, lhs);
- log("Added %s.%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs));
+
+ log("Add %s/%s: %s -> %s\n", log_id(module), log_id(cell), log_signal(rhs), log_signal(lhs));
+ bufcells.insert(cell);
}
if (GetSize(new_conn.first))
new_connections.push_back(new_conn);
}
+ if (chain_mode) {
+ for (auto &cell : module->selected_cells()) {
+ if (bufcells.count(cell))
+ continue;
+ for (auto &port : cell->connections())
+ if (cell->input(port.first)) {
+ auto s = sigmap(port.second);
+ if (s == port.second)
+ continue;
+ log("Rewrite %s/%s/%s: %s -> %s\n", log_id(module), log_id(cell),
+ log_id(port.first), log_signal(port.second), log_signal(s));
+ cell->setPort(port.first, s);
+ }
+ }
+ }
+
module->new_connections(new_connections);
}
}
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index 7d8dba439..11692b715 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -58,28 +58,17 @@ void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
RTLIL::SigSpec sig_b = cell->getPort(ID::B);
RTLIL::SigSpec sig_y = cell->getPort(ID::Y);
- sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
- sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool());
-
- if (cell->type == ID($xnor))
- {
- RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y));
-
- for (int i = 0; i < GetSize(sig_y); i++) {
- RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_NOT_));
- gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
- gate->setPort(ID::A, sig_t[i]);
- gate->setPort(ID::Y, sig_y[i]);
- }
-
- sig_y = sig_t;
+ if (cell->type != ID($bweqx)) {
+ sig_a.extend_u0(GetSize(sig_y), cell->parameters.at(ID::A_SIGNED).as_bool());
+ sig_b.extend_u0(GetSize(sig_y), cell->parameters.at(ID::B_SIGNED).as_bool());
}
IdString gate_type;
- if (cell->type == ID($and)) gate_type = ID($_AND_);
- if (cell->type == ID($or)) gate_type = ID($_OR_);
- if (cell->type == ID($xor)) gate_type = ID($_XOR_);
- if (cell->type == ID($xnor)) gate_type = ID($_XOR_);
+ if (cell->type == ID($and)) gate_type = ID($_AND_);
+ if (cell->type == ID($or)) gate_type = ID($_OR_);
+ if (cell->type == ID($xor)) gate_type = ID($_XOR_);
+ if (cell->type == ID($xnor)) gate_type = ID($_XNOR_);
+ if (cell->type == ID($bweqx)) gate_type = ID($_XNOR_);
log_assert(!gate_type.empty());
for (int i = 0; i < GetSize(sig_y); i++) {
@@ -284,6 +273,23 @@ void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
+void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ 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);
+
+ for (int i = 0; i < GetSize(sig_y); i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, ID($_MUX_));
+ gate->add_strpool_attribute(ID::src, cell->get_strpool_attribute(ID::src));
+ gate->setPort(ID::A, sig_a[i]);
+ gate->setPort(ID::B, sig_b[i]);
+ gate->setPort(ID::S, sig_s[i]);
+ gate->setPort(ID::Y, sig_y[i]);
+ }
+}
+
void simplemap_tribuf(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort(ID::A);
@@ -409,6 +415,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
mappers[ID($or)] = simplemap_bitop;
mappers[ID($xor)] = simplemap_bitop;
mappers[ID($xnor)] = simplemap_bitop;
+ mappers[ID($bweqx)] = simplemap_bitop;
mappers[ID($reduce_and)] = simplemap_reduce;
mappers[ID($reduce_or)] = simplemap_reduce;
mappers[ID($reduce_xor)] = simplemap_reduce;
@@ -422,6 +429,7 @@ void simplemap_get_mappers(dict<IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)>
mappers[ID($ne)] = simplemap_eqne;
mappers[ID($nex)] = simplemap_eqne;
mappers[ID($mux)] = simplemap_mux;
+ mappers[ID($bwmux)] = simplemap_bwmux;
mappers[ID($tribuf)] = simplemap_tribuf;
mappers[ID($bmux)] = simplemap_bmux;
mappers[ID($lut)] = simplemap_lut;
@@ -476,7 +484,8 @@ struct SimplemapPass : public Pass {
log(" $not, $pos, $and, $or, $xor, $xnor\n");
log(" $reduce_and, $reduce_or, $reduce_xor, $reduce_xnor, $reduce_bool\n");
log(" $logic_not, $logic_and, $logic_or, $mux, $tribuf\n");
- log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff, $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
+ log(" $sr, $ff, $dff, $dffe, $dffsr, $dffsre, $adff, $adffe, $aldff, $aldffe, $sdff,\n");
+ log(" $sdffe, $sdffce, $dlatch, $adlatch, $dlatchsr\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h
index c7654f68c..30cc1ccfe 100644
--- a/passes/techmap/simplemap.h
+++ b/passes/techmap/simplemap.h
@@ -31,6 +31,7 @@ extern void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_bwmux(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_lut(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell);
extern void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell);
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 5cd78fe28..144f596c8 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -1026,8 +1026,8 @@ struct TechmapPass : public Pass {
log("When a module in the map file has the 'techmap_celltype' attribute set, it will\n");
log("match cells with a type that match the text value of this attribute. Otherwise\n");
log("the module name will be used to match the cell. Multiple space-separated cell\n");
- log("types can be listed, and wildcards using [] will be expanded (ie. \"$_DFF_[PN]_\"\n");
- log("is the same as \"$_DFF_P_ $_DFF_N_\").\n");
+ log("types can be listed, and wildcards using [] will be expanded (ie.\n");
+ log("\"$_DFF_[PN]_\" is the same as \"$_DFF_P_ $_DFF_N_\").\n");
log("\n");
log("When a module in the map file has the 'techmap_simplemap' attribute set, techmap\n");
log("will use 'simplemap' (see 'help simplemap') to map cells matching the module.\n");
@@ -1083,11 +1083,11 @@ struct TechmapPass : public Pass {
log(" It is possible to combine both prefixes to 'RECURSION; CONSTMAP; '.\n");
log("\n");
log(" _TECHMAP_REMOVEINIT_<port-name>_\n");
- log(" When this wire is set to a constant value, the init attribute of the wire(s)\n");
- log(" connected to this port will be consumed. This wire must have the same\n");
- log(" width as the given port, and for every bit that is set to 1 in the value,\n");
- log(" the corresponding init attribute bit will be changed to 1'bx. If all\n");
- log(" bits of an init attribute are left as x, it will be removed.\n");
+ log(" When this wire is set to a constant value, the init attribute of the\n");
+ log(" wire(s) connected to this port will be consumed. This wire must have\n");
+ log(" the same width as the given port, and for every bit that is set to 1 in\n");
+ log(" the value, the corresponding init attribute bit will be changed to 1'bx.\n");
+ log(" If all bits of an init attribute are left as x, it will be removed.\n");
log("\n");
log("In addition to this special wires, techmap also supports special parameters in\n");
log("modules in the map file:\n");
@@ -1108,8 +1108,8 @@ struct TechmapPass : public Pass {
log("\n");
log(" _TECHMAP_WIREINIT_<port-name>_\n");
log(" When a parameter with this name exists, it will be set to the initial\n");
- log(" value of the wire(s) connected to the given port, as specified by the init\n");
- log(" attribute. If the attribute doesn't exist, x will be filled for the\n");
+ log(" value of the wire(s) connected to the given port, as specified by the\n");
+ log(" init attribute. If the attribute doesn't exist, x will be filled for the\n");
log(" missing bits. To remove the init attribute bits used, use the\n");
log(" _TECHMAP_REMOVEINIT_*_ wires.\n");
log("\n");