aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/Makefile.inc2
-rw-r--r--passes/techmap/abc.cc40
-rw-r--r--passes/techmap/deminout.cc32
-rw-r--r--passes/techmap/dff2dffe.cc14
-rw-r--r--passes/techmap/dff2dffs.cc142
-rw-r--r--passes/techmap/dfflibmap.cc4
-rw-r--r--passes/techmap/extract_reduce.cc1
-rw-r--r--passes/techmap/iopadmap.cc57
-rw-r--r--passes/techmap/techmap.cc4
9 files changed, 279 insertions, 17 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 140a9f892..4faa0ab00 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -35,6 +35,7 @@ OBJS += passes/techmap/insbuf.o
OBJS += passes/techmap/attrmvcp.o
OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
+OBJS += passes/techmap/dff2dffs.o
endif
GENFILES += passes/techmap/techmap.inc
@@ -57,4 +58,3 @@ yosys-filterlib$(EXE): passes/techmap/filterlib.o
$(Q) mkdir -p $(dir $@)
$(P) $(LD) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
endif
-
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index be86f642a..18868c6d7 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -60,6 +60,10 @@
#include "frontends/blif/blifparse.h"
+#ifdef YOSYS_LINK_ABC
+extern "C" int Abc_RealMain(int argc, char *argv[]);
+#endif
+
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -546,11 +550,13 @@ std::string replace_tempdir(std::string text, std::string tempdir_name, bool sho
}
std::string selfdir_name = proc_self_dirname();
- while (1) {
- size_t pos = text.find(selfdir_name);
- if (pos == std::string::npos)
- break;
- text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
+ if (selfdir_name != "/") {
+ while (1) {
+ size_t pos = text.find(selfdir_name);
+ if (pos == std::string::npos)
+ break;
+ text = text.substr(0, pos) + "<yosys-exe-dir>/" + text.substr(pos + GetSize(selfdir_name));
+ }
}
return text;
@@ -943,8 +949,24 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
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
abc_output_filter filt(tempdir_name, show_tempdir);
int ret = run_command(buffer, std::bind(&abc_output_filter::next_line, filt, std::placeholders::_1));
+#else
+ // These needs to be mutable, supposedly due to getopt
+ char *abc_argv[5];
+ string tmp_script_name = stringf("%s/abc.script", tempdir_name.c_str());
+ abc_argv[0] = strdup(exe_file.c_str());
+ abc_argv[1] = strdup("-s");
+ 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);
+ free(abc_argv[0]);
+ free(abc_argv[1]);
+ free(abc_argv[2]);
+ free(abc_argv[3]);
+#endif
if (ret != 0)
log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
@@ -1388,8 +1410,12 @@ struct AbcPass : public Pass {
log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
log("loaded into ABC before the ABC script is executed.\n");
log("\n");
- log("This pass does not operate on modules with unprocessed processes in it.\n");
- log("(I.e. the 'proc' pass should be used first to convert processes to netlists.)\n");
+ log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
+ log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
+ log("ABC on logic snippets extracted from your design. You will not get any useful\n");
+ log("output when passing an ABC script that writes a file. Instead write your full\n");
+ log("design as BLIF file with write_blif and the load that into ABC externally if\n");
+ log("you want to use ABC to convert your design into another format.\n");
log("\n");
log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
log("\n");
diff --git a/passes/techmap/deminout.cc b/passes/techmap/deminout.cc
index ed4e45762..0b8fd5246 100644
--- a/passes/techmap/deminout.cc
+++ b/passes/techmap/deminout.cc
@@ -57,7 +57,7 @@ struct DeminoutPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- pool<SigBit> bits_written, bits_used, bits_inout;
+ pool<SigBit> bits_written, bits_used, bits_inout, bits_tribuf;
dict<SigBit, int> bits_numports;
for (auto wire : module->wires())
@@ -82,6 +82,25 @@ struct DeminoutPass : public Pass {
if (cellport_in)
for (auto bit : sigmap(conn.second))
bits_used.insert(bit);
+
+ if (conn.first == "\\Y" && cell->type.in("$mux", "$pmux", "$_MUX_", "$_TBUF_"))
+ {
+ bool tribuf = (cell->type == "$_TBUF_");
+
+ if (!tribuf) {
+ for (auto &c : cell->connections()) {
+ if (!c.first.in("\\A", "\\B"))
+ continue;
+ for (auto b : sigmap(c.second))
+ if (b == State::Sz)
+ tribuf = true;
+ }
+ }
+
+ if (tribuf)
+ for (auto bit : sigmap(conn.second))
+ bits_tribuf.insert(bit);
+ }
}
for (auto wire : module->selected_wires())
@@ -95,10 +114,15 @@ struct DeminoutPass : public Pass {
if (bits_numports[bit] > 1 || bits_inout.count(bit))
new_input = true, new_output = true;
- if (bits_written.count(bit))
+ if (bits_written.count(bit)) {
new_output = true;
- else if (bits_used.count(bit))
- new_input = true;
+ if (bits_tribuf.count(bit))
+ goto tribuf_bit;
+ } else {
+ tribuf_bit:
+ if (bits_used.count(bit))
+ new_input = true;
+ }
}
if (new_input != new_output) {
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
index 1b8920bb7..4d515f174 100644
--- a/passes/techmap/dff2dffe.cc
+++ b/passes/techmap/dff2dffe.cc
@@ -279,8 +279,9 @@ struct Dff2dffePass : public Pass {
log(" -direct-match <pattern>\n");
log(" like -direct for all DFF cell types matching the expression.\n");
log(" this will use $__DFFE_* as <external_gate_type> matching the\n");
- log(" internal gate type $_DFF_*_, except for $_DFF_[NP]_, which is\n");
- log(" converted to $_DFFE_[NP]_.\n");
+ log(" internal gate type $_DFF_*_, and $__DFFSE_* for those matching\n");
+ log(" $_DFFS_*_, except for $_DFF_[NP]_, which is converted to \n");
+ log(" $_DFFE_[NP]_.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -315,6 +316,15 @@ struct Dff2dffePass : public Pass {
if (patmatch(pattern, "$_DFF_PN1_")) found_match = true, direct_dict["$_DFF_PN1_"] = "$__DFFE_PN1";
if (patmatch(pattern, "$_DFF_PP0_")) found_match = true, direct_dict["$_DFF_PP0_"] = "$__DFFE_PP0";
if (patmatch(pattern, "$_DFF_PP1_")) found_match = true, direct_dict["$_DFF_PP1_"] = "$__DFFE_PP1";
+
+ if (patmatch(pattern, "$__DFFS_NN0_")) found_match = true, direct_dict["$__DFFS_NN0_"] = "$__DFFSE_NN0";
+ if (patmatch(pattern, "$__DFFS_NN1_")) found_match = true, direct_dict["$__DFFS_NN1_"] = "$__DFFSE_NN1";
+ if (patmatch(pattern, "$__DFFS_NP0_")) found_match = true, direct_dict["$__DFFS_NP0_"] = "$__DFFSE_NP0";
+ if (patmatch(pattern, "$__DFFS_NP1_")) found_match = true, direct_dict["$__DFFS_NP1_"] = "$__DFFSE_NP1";
+ if (patmatch(pattern, "$__DFFS_PN0_")) found_match = true, direct_dict["$__DFFS_PN0_"] = "$__DFFSE_PN0";
+ if (patmatch(pattern, "$__DFFS_PN1_")) found_match = true, direct_dict["$__DFFS_PN1_"] = "$__DFFSE_PN1";
+ if (patmatch(pattern, "$__DFFS_PP0_")) found_match = true, direct_dict["$__DFFS_PP0_"] = "$__DFFSE_PP0";
+ if (patmatch(pattern, "$__DFFS_PP1_")) found_match = true, direct_dict["$__DFFS_PP1_"] = "$__DFFSE_PP1";
if (!found_match)
log_cmd_error("No cell types matched pattern '%s'.\n", pattern);
continue;
diff --git a/passes/techmap/dff2dffs.cc b/passes/techmap/dff2dffs.cc
new file mode 100644
index 000000000..0bfbdc965
--- /dev/null
+++ b/passes/techmap/dff2dffs.cc
@@ -0,0 +1,142 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ * Copyright (C) 2018 David Shah <dave@ds0.me>
+ *
+ * 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 Dff2dffsPass : public Pass {
+ Dff2dffsPass() : Pass("dff2dffs", "process sync set/reset with SR over CE priority") { }
+ virtual void help()
+ {
+ log("\n");
+ log(" dff2dffs [options] [selection]\n");
+ log("\n");
+ log("Merge synchronous set/reset $_MUX_ cells to create $__DFFS_[NP][NP][01], to be run before\n");
+ log("dff2dffe for SR over CE priority.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header(design, "Executing dff2dffs pass (merge synchronous set/reset into FF cells).\n");
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++)
+ {
+ // if (args[argidx] == "-singleton") {
+ // singleton_mode = true;
+ // continue;
+ // }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ pool<IdString> dff_types;
+ dff_types.insert("$_DFF_N_");
+ dff_types.insert("$_DFF_P_");
+
+ for (auto module : design->selected_modules())
+ {
+ log("Merging set/reset $_MUX_ cells into DFFs in %s.\n", log_id(module));
+
+ SigMap sigmap(module);
+ dict<SigBit, Cell*> sr_muxes;
+ vector<Cell*> ff_cells;
+
+ for (auto cell : module->selected_cells())
+ {
+ if (dff_types.count(cell->type)) {
+ ff_cells.push_back(cell);
+ continue;
+ }
+
+ if (cell->type != "$_MUX_")
+ continue;
+
+ SigBit bit_a = sigmap(cell->getPort("\\A"));
+ SigBit bit_b = sigmap(cell->getPort("\\B"));
+
+ if (bit_a.wire == nullptr || bit_b.wire == nullptr)
+ sr_muxes[sigmap(cell->getPort("\\Y"))] = cell;
+ }
+
+ for (auto cell : ff_cells)
+ {
+ SigSpec sig_d = cell->getPort("\\D");
+
+ if (GetSize(sig_d) < 1)
+ continue;
+
+ SigBit bit_d = sigmap(sig_d[0]);
+
+ if (sr_muxes.count(bit_d) == 0)
+ continue;
+
+ Cell *mux_cell = sr_muxes.at(bit_d);
+ SigBit bit_a = sigmap(mux_cell->getPort("\\A"));
+ SigBit bit_b = sigmap(mux_cell->getPort("\\B"));
+ SigBit bit_s = sigmap(mux_cell->getPort("\\S"));
+
+ log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell),
+ log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type));
+
+ SigBit sr_val, sr_sig;
+ bool invert_sr;
+ sr_sig = bit_s;
+ if (bit_a.wire == nullptr) {
+ bit_d = bit_b;
+ sr_val = bit_a;
+ invert_sr = true;
+ } else {
+ log_assert(bit_b.wire == nullptr);
+ bit_d = bit_a;
+ sr_val = bit_b;
+ invert_sr = false;
+ }
+
+ if (sr_val == State::S1) {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN1_";
+ else cell->type = "$__DFFS_NP1_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN1_";
+ else cell->type = "$__DFFS_PP1_";
+ }
+ } else {
+ if (cell->type == "$_DFF_N_") {
+ if (invert_sr) cell->type = "$__DFFS_NN0_";
+ else cell->type = "$__DFFS_NP0_";
+ } else {
+ log_assert(cell->type == "$_DFF_P_");
+ if (invert_sr) cell->type = "$__DFFS_PN0_";
+ else cell->type = "$__DFFS_PP0_";
+ }
+ }
+ cell->setPort("\\R", sr_sig);
+ cell->setPort("\\D", bit_d);
+ }
+ }
+ }
+} Dff2dffsPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 4cb1489a8..5ccb770c4 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -240,6 +240,10 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
if (cell->id != "cell" || cell->args.size() != 1)
continue;
+ LibertyAst *dn = cell->find("dont_use");
+ if (dn != NULL && dn->value == "true")
+ continue;
+
LibertyAst *ff = cell->find("ff");
if (ff == NULL)
continue;
diff --git a/passes/techmap/extract_reduce.cc b/passes/techmap/extract_reduce.cc
index cc21c8665..0ce596fda 100644
--- a/passes/techmap/extract_reduce.cc
+++ b/passes/techmap/extract_reduce.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include <deque>
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 4acbf7c0d..690ba87ed 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -146,11 +146,37 @@ struct IopadmapPass : public Pass {
for (auto module : design->selected_modules())
{
dict<IdString, pool<int>> skip_wires;
+ pool<SigBit> skip_wire_bits;
+ SigMap sigmap(module);
+
+ for (auto cell : module->cells())
+ {
+ if (cell->type == RTLIL::escape_id(inpad_celltype) && cell->hasPort(RTLIL::escape_id(inpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(outpad_celltype) && cell->hasPort(RTLIL::escape_id(outpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(outpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(inoutpad_celltype) && cell->hasPort(RTLIL::escape_id(inoutpad_portname2)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(inoutpad_portname2))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(toutpad_celltype) && cell->hasPort(RTLIL::escape_id(toutpad_portname3)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(toutpad_portname3))))
+ skip_wire_bits.insert(bit);
+
+ if (cell->type == RTLIL::escape_id(tinoutpad_celltype) && cell->hasPort(RTLIL::escape_id(tinoutpad_portname4)))
+ for (auto bit : sigmap(cell->getPort(RTLIL::escape_id(tinoutpad_portname4))))
+ skip_wire_bits.insert(bit);
+ }
if (!toutpad_celltype.empty() || !tinoutpad_celltype.empty())
{
- SigMap sigmap(module);
dict<SigBit, pair<IdString, pool<IdString>>> tbuf_bits;
+ pool<pair<IdString, IdString>> norewrites;
+ SigMap rewrites;
for (auto cell : module->cells())
if (cell->type == "$_TBUF_") {
@@ -177,6 +203,9 @@ struct IopadmapPass : public Pass {
if (tbuf_bits.count(mapped_wire_bit) == 0)
continue;
+ if (skip_wire_bits.count(mapped_wire_bit))
+ continue;
+
auto &tbuf_cache = tbuf_bits.at(mapped_wire_bit);
Cell *tbuf_cell = module->cell(tbuf_cache.first);
@@ -219,6 +248,9 @@ struct IopadmapPass : public Pass {
module->remove(tbuf_cell);
skip_wires[wire->name].insert(i);
+
+ norewrites.insert(make_pair(cell->name, RTLIL::escape_id(tinoutpad_portname4)));
+ rewrites.add(sigmap(wire_bit), owire);
continue;
}
@@ -256,6 +288,22 @@ struct IopadmapPass : public Pass {
}
}
}
+
+ if (GetSize(norewrites))
+ {
+ for (auto cell : module->cells())
+ for (auto port : cell->connections())
+ {
+ if (norewrites.count(make_pair(cell->name, port.first)))
+ continue;
+
+ SigSpec orig_sig = sigmap(port.second);
+ SigSpec new_sig = rewrites(orig_sig);
+
+ if (orig_sig != new_sig)
+ cell->setPort(port.first, new_sig);
+ }
+ }
}
for (auto wire : module->selected_wires())
@@ -272,6 +320,13 @@ struct IopadmapPass : public Pass {
skip_bit_indices = skip_wires.at(wire->name);
}
+ for (int i = 0; i < GetSize(wire); i++)
+ if (skip_wire_bits.count(sigmap(SigBit(wire, i))))
+ skip_bit_indices.insert(i);
+
+ if (GetSize(wire) == GetSize(skip_bit_indices))
+ continue;
+
if (wire->port_input && !wire->port_output) {
if (inpad_celltype.empty()) {
log("Don't map input port %s.%s: Missing option -inpad.\n", RTLIL::id2cstr(module->name), RTLIL::id2cstr(wire->name));
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index 02d0d47e8..1908ae8b5 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -933,7 +933,7 @@ struct TechmapPass : public Pass {
log(" -D <define>, -I <incdir>\n");
log(" this options are passed as-is to the Verilog frontend for loading the\n");
log(" map file. Note that the Verilog frontend is also called with the\n");
- log(" '-ignore_redef' option set.\n");
+ log(" '-nooverwrite' option set.\n");
log("\n");
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");
@@ -1031,7 +1031,7 @@ struct TechmapPass : public Pass {
simplemap_get_mappers(worker.simplemap_mappers);
std::vector<std::string> map_files;
- std::string verilog_frontend = "verilog -ignore_redef";
+ std::string verilog_frontend = "verilog -nooverwrite";
int max_iter = -1;
size_t argidx;