aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/Makefile.inc13
-rw-r--r--passes/techmap/alumacc.cc92
-rw-r--r--passes/techmap/dff2dffe.cc337
-rw-r--r--passes/techmap/dfflibmap.cc113
-rw-r--r--passes/techmap/extract.cc534
-rw-r--r--passes/techmap/hilomap.cc10
-rw-r--r--passes/techmap/iopadmap.cc23
-rw-r--r--passes/techmap/libparse.cc45
-rw-r--r--passes/techmap/libparse.h2
-rw-r--r--passes/techmap/maccmap.cc84
-rw-r--r--passes/techmap/simplemap.cc121
-rw-r--r--passes/techmap/simplemap.h48
-rw-r--r--passes/techmap/techmap.cc140
13 files changed, 1062 insertions, 500 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index 72998f87b..6b6846e20 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -2,14 +2,15 @@
OBJS += passes/techmap/techmap.o
OBJS += passes/techmap/simplemap.o
OBJS += passes/techmap/dfflibmap.o
+OBJS += passes/techmap/maccmap.o
OBJS += passes/techmap/libparse.o
ifneq ($(SMALL),1)
OBJS += passes/techmap/iopadmap.o
OBJS += passes/techmap/hilomap.o
OBJS += passes/techmap/extract.o
-OBJS += passes/techmap/maccmap.o
OBJS += passes/techmap/alumacc.o
+OBJS += passes/techmap/dff2dffe.o
endif
GENFILES += passes/techmap/techmap.inc
@@ -23,9 +24,11 @@ passes/techmap/techmap.inc: techlibs/common/techmap.v
passes/techmap/techmap.o: passes/techmap/techmap.inc
-TARGETS += yosys-filterlib
-GENFILES += passes/techmap/filterlib.o
+ifneq ($(CONFIG),emcc)
+TARGETS += yosys-filterlib$(EXE)
+EXTRA_OBJS += passes/techmap/filterlib.o
-yosys-filterlib: passes/techmap/filterlib.o
- $(P) $(CXX) -o yosys-filterlib $(LDFLAGS) $^ $(LDLIBS)
+yosys-filterlib$(EXE): passes/techmap/filterlib.o
+ $(P) $(CXX) -o yosys-filterlib$(EXE) $(LDFLAGS) $^ $(LDLIBS)
+endif
diff --git a/passes/techmap/alumacc.cc b/passes/techmap/alumacc.cc
index 1115eead5..dcffed94d 100644
--- a/passes/techmap/alumacc.cc
+++ b/passes/techmap/alumacc.cc
@@ -21,6 +21,9 @@
#include "kernel/sigtools.h"
#include "kernel/macc.h"
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
struct AlumaccWorker
{
RTLIL::Module *module;
@@ -45,51 +48,51 @@ struct AlumaccWorker
RTLIL::SigSpec cached_cf, cached_of, cached_sf;
RTLIL::SigSpec get_lt() {
- if (SIZE(cached_lt) == 0)
+ if (GetSize(cached_lt) == 0)
cached_lt = is_signed ? alu_cell->module->Xor(NEW_ID, get_of(), get_sf()) : get_cf();
return cached_lt;
}
RTLIL::SigSpec get_gt() {
- if (SIZE(cached_gt) == 0)
+ if (GetSize(cached_gt) == 0)
cached_gt = alu_cell->module->Not(NEW_ID, alu_cell->module->Or(NEW_ID, get_lt(), get_eq()));
return cached_gt;
}
RTLIL::SigSpec get_eq() {
- if (SIZE(cached_eq) == 0)
+ if (GetSize(cached_eq) == 0)
cached_eq = alu_cell->module->ReduceAnd(NEW_ID, alu_cell->getPort("\\X"));
return cached_eq;
}
RTLIL::SigSpec get_ne() {
- if (SIZE(cached_ne) == 0)
+ if (GetSize(cached_ne) == 0)
cached_ne = alu_cell->module->Not(NEW_ID, get_eq());
return cached_ne;
}
RTLIL::SigSpec get_cf() {
- if (SIZE(cached_cf) == 0) {
+ if (GetSize(cached_cf) == 0) {
cached_cf = alu_cell->getPort("\\CO");
- log_assert(SIZE(cached_cf) >= 1);
- cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[SIZE(cached_cf)-1]);
+ log_assert(GetSize(cached_cf) >= 1);
+ cached_cf = alu_cell->module->Not(NEW_ID, cached_cf[GetSize(cached_cf)-1]);
}
return cached_cf;
}
RTLIL::SigSpec get_of() {
- if (SIZE(cached_of) == 0) {
+ if (GetSize(cached_of) == 0) {
cached_of = {alu_cell->getPort("\\CO"), alu_cell->getPort("\\CI")};
- log_assert(SIZE(cached_of) >= 2);
- cached_of = alu_cell->module->Xor(NEW_ID, cached_of[SIZE(cached_of)-1], cached_of[SIZE(cached_of)-2]);
+ log_assert(GetSize(cached_of) >= 2);
+ cached_of = alu_cell->module->Xor(NEW_ID, cached_of[GetSize(cached_of)-1], cached_of[GetSize(cached_of)-2]);
}
return cached_of;
}
RTLIL::SigSpec get_sf() {
- if (SIZE(cached_sf) == 0) {
+ if (GetSize(cached_sf) == 0) {
cached_sf = alu_cell->getPort("\\Y");
- cached_sf = cached_sf[SIZE(cached_sf)-1];
+ cached_sf = cached_sf[GetSize(cached_sf)-1];
}
return cached_sf;
}
@@ -181,10 +184,10 @@ struct AlumaccWorker
return true;
if (!port.is_signed && port.do_subtract)
return true;
- if (SIZE(port.in_b))
- port_sizes.push_back(SIZE(port.in_a) + SIZE(port.in_b));
+ if (GetSize(port.in_b))
+ port_sizes.push_back(GetSize(port.in_a) + GetSize(port.in_b));
else
- port_sizes.push_back(SIZE(port.in_a));
+ port_sizes.push_back(GetSize(port.in_a));
}
std::sort(port_sizes.begin(), port_sizes.end());
@@ -221,11 +224,11 @@ struct AlumaccWorker
if (delete_nodes.count(n))
continue;
- for (int i = 0; i < SIZE(n->macc.ports); i++)
+ for (int i = 0; i < GetSize(n->macc.ports); i++)
{
auto &port = n->macc.ports[i];
- if (SIZE(port.in_b) > 0 || sig_macc.count(port.in_a) == 0)
+ if (GetSize(port.in_b) > 0 || sig_macc.count(port.in_a) == 0)
continue;
auto other_n = sig_macc.at(port.in_a);
@@ -233,13 +236,13 @@ struct AlumaccWorker
if (other_n->users > 1)
continue;
- if (SIZE(other_n->y) != SIZE(n->y) && macc_may_overflow(other_n->macc, SIZE(other_n->y), port.is_signed))
+ if (GetSize(other_n->y) != GetSize(n->y) && macc_may_overflow(other_n->macc, GetSize(other_n->y), port.is_signed))
continue;
log(" merging $macc model for %s into %s.\n", log_id(other_n->cell), log_id(n->cell));
bool do_subtract = port.do_subtract;
- for (int j = 0; j < SIZE(other_n->macc.ports); j++) {
+ for (int j = 0; j < GetSize(other_n->macc.ports); j++) {
if (do_subtract)
other_n->macc.ports[j].do_subtract = !other_n->macc.ports[j].do_subtract;
if (j == 0)
@@ -275,38 +278,38 @@ struct AlumaccWorker
alunode_t *alunode;
for (auto &port : n->macc.ports)
- if (SIZE(port.in_b) > 0) {
+ if (GetSize(port.in_b) > 0) {
goto next_macc;
- } else if (SIZE(port.in_a) == 1 && !port.is_signed && !port.do_subtract) {
+ } else if (GetSize(port.in_a) == 1 && !port.is_signed && !port.do_subtract) {
C.append(port.in_a);
- } else if (SIZE(A) || port.do_subtract) {
- if (SIZE(B))
+ } else if (GetSize(A) || port.do_subtract) {
+ if (GetSize(B))
goto next_macc;
B = port.in_a;
b_signed = port.is_signed;
subtract_b = port.do_subtract;
} else {
- if (SIZE(A))
+ if (GetSize(A))
goto next_macc;
A = port.in_a;
a_signed = port.is_signed;
}
if (!a_signed || !b_signed) {
- if (SIZE(A) == SIZE(n->y))
+ if (GetSize(A) == GetSize(n->y))
a_signed = false;
- if (SIZE(B) == SIZE(n->y))
+ if (GetSize(B) == GetSize(n->y))
b_signed = false;
if (a_signed != b_signed)
goto next_macc;
}
- if (SIZE(A) == 0 && SIZE(C) > 0) {
+ if (GetSize(A) == 0 && GetSize(C) > 0) {
A = C[0];
C.remove(0);
}
- if (SIZE(B) == 0 && SIZE(C) > 0) {
+ if (GetSize(B) == 0 && GetSize(C) > 0) {
B = C[0];
C.remove(0);
}
@@ -314,10 +317,10 @@ struct AlumaccWorker
if (subtract_b)
C.append(RTLIL::S1);
- if (SIZE(C) > 1)
+ if (GetSize(C) > 1)
goto next_macc;
- if (!subtract_b && B < A && SIZE(B))
+ if (!subtract_b && B < A && GetSize(B))
std::swap(A, B);
log(" creating $alu model for $macc %s.\n", log_id(n->cell));
@@ -353,7 +356,7 @@ struct AlumaccWorker
log(" creating $macc cell for %s: %s\n", log_id(n->cell), log_id(cell));
- n->macc.optimize(SIZE(n->y));
+ n->macc.optimize(GetSize(n->y));
n->macc.to_cell(cell);
cell->setPort("\\Y", n->y);
cell->fixup_parameters();
@@ -388,7 +391,7 @@ struct AlumaccWorker
RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
- if (B < A && SIZE(B)) {
+ if (B < A && GetSize(B)) {
cmp_less = !cmp_less;
std::swap(A, B);
}
@@ -406,7 +409,7 @@ struct AlumaccWorker
n->a = A;
n->b = B;
n->c = RTLIL::S1;
- n->y = module->addWire(NEW_ID, std::max(SIZE(A), SIZE(B)));
+ n->y = module->addWire(NEW_ID, std::max(GetSize(A), GetSize(B)));
n->is_signed = is_signed;
n->invert_b = true;
sig_alu[RTLIL::SigSig(A, B)].insert(n);
@@ -428,7 +431,7 @@ struct AlumaccWorker
RTLIL::SigSpec B = sigmap(cell->getPort("\\B"));
RTLIL::SigSpec Y = sigmap(cell->getPort("\\Y"));
- if (B < A && SIZE(B))
+ if (B < A && GetSize(B))
std::swap(A, B);
alunode_t *n = nullptr;
@@ -452,12 +455,12 @@ struct AlumaccWorker
for (auto &it1 : sig_alu)
for (auto n : it1.second)
{
- if (SIZE(n->b) == 0 && SIZE(n->c) == 0 && SIZE(n->cmp) == 0)
+ if (GetSize(n->b) == 0 && GetSize(n->c) == 0 && GetSize(n->cmp) == 0)
{
n->alu_cell = module->addPos(NEW_ID, n->a, n->y, n->is_signed);
log(" creating $pos cell for ");
- for (int i = 0; i < SIZE(n->cells); i++)
+ for (int i = 0; i < GetSize(n->cells); i++)
log("%s%s", i ? ", ": "", log_id(n->cells[i]));
log(": %s\n", log_id(n->alu_cell));
@@ -468,17 +471,17 @@ struct AlumaccWorker
alu_counter++;
log(" creating $alu cell for ");
- for (int i = 0; i < SIZE(n->cells); i++)
+ for (int i = 0; i < GetSize(n->cells); i++)
log("%s%s", i ? ", ": "", log_id(n->cells[i]));
log(": %s\n", log_id(n->alu_cell));
n->alu_cell->setPort("\\A", n->a);
n->alu_cell->setPort("\\B", n->b);
- n->alu_cell->setPort("\\CI", SIZE(n->c) ? n->c : RTLIL::S0);
+ n->alu_cell->setPort("\\CI", GetSize(n->c) ? n->c : RTLIL::S0);
n->alu_cell->setPort("\\BI", n->invert_b ? RTLIL::S1 : RTLIL::S0);
n->alu_cell->setPort("\\Y", n->y);
- n->alu_cell->setPort("\\X", module->addWire(NEW_ID, SIZE(n->y)));
- n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, SIZE(n->y)));
+ n->alu_cell->setPort("\\X", module->addWire(NEW_ID, GetSize(n->y)));
+ n->alu_cell->setPort("\\CO", module->addWire(NEW_ID, GetSize(n->y)));
n->alu_cell->fixup_parameters(n->is_signed, n->is_signed);
for (auto &it : n->cmp)
@@ -495,10 +498,10 @@ struct AlumaccWorker
if (cmp_eq) sig.append(n->get_eq());
if (cmp_ne) sig.append(n->get_ne());
- if (SIZE(sig) > 1)
+ if (GetSize(sig) > 1)
sig = module->ReduceOr(NEW_ID, sig);
- sig.extend(SIZE(cmp_y));
+ sig.extend_u0(GetSize(cmp_y));
module->connect(cmp_y, sig);
}
@@ -535,8 +538,8 @@ struct AlumaccPass : public Pass {
log("\n");
log(" alumacc [selection]\n");
log("\n");
- log("This pass translates arithmetic operations $add, $mul, $lt, etc. to $alu and\n");
- log("$macc cells.\n");
+ log("This pass translates arithmetic operations like $add, $mul, $lt, etc. to $alu\n");
+ log("and $macc cells.\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -561,3 +564,4 @@ struct AlumaccPass : public Pass {
}
} AlumaccPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dff2dffe.cc b/passes/techmap/dff2dffe.cc
new file mode 100644
index 000000000..17549bd06
--- /dev/null
+++ b/passes/techmap/dff2dffe.cc
@@ -0,0 +1,337 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+#include "kernel/celltypes.h"
+#include "passes/techmap/simplemap.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct Dff2dffeWorker
+{
+ RTLIL::Module *module;
+ SigMap sigmap;
+ CellTypes ct;
+
+ RTLIL::IdString direct_to;
+
+ typedef std::pair<RTLIL::Cell*, int> cell_int_t;
+ std::map<RTLIL::SigBit, cell_int_t> bit2mux;
+ std::vector<RTLIL::Cell*> dff_cells;
+ std::map<RTLIL::SigBit, int> bitusers;
+
+ typedef std::map<RTLIL::SigBit, bool> pattern_t;
+ typedef std::set<pattern_t> patterns_t;
+
+
+ Dff2dffeWorker(RTLIL::Module *module, RTLIL::IdString direct_from, RTLIL::IdString direct_to) :
+ module(module), sigmap(module), ct(module->design), direct_to(direct_to)
+ {
+ for (auto wire : module->wires()) {
+ if (wire->port_output)
+ for (auto bit : sigmap(wire))
+ bitusers[bit]++;
+ }
+
+ for (auto cell : module->cells()) {
+ if (cell->type == "$mux" || cell->type == "$pmux" || cell->type == "$_MUX_") {
+ RTLIL::SigSpec sig_y = sigmap(cell->getPort("\\Y"));
+ for (int i = 0; i < GetSize(sig_y); i++)
+ bit2mux[sig_y[i]] = cell_int_t(cell, i);
+ }
+ if (direct_to.empty()) {
+ if (cell->type == "$dff" || cell->type == "$_DFF_N_" || cell->type == "$_DFF_P_")
+ dff_cells.push_back(cell);
+ } else {
+ if (cell->type == direct_from)
+ dff_cells.push_back(cell);
+ }
+ for (auto conn : cell->connections()) {
+ if (ct.cell_output(cell->type, conn.first))
+ continue;
+ for (auto bit : sigmap(conn.second))
+ bitusers[bit]++;
+ }
+ }
+ }
+
+ patterns_t find_muxtree_feedback_patterns(RTLIL::SigBit d, RTLIL::SigBit q, pattern_t path)
+ {
+ patterns_t ret;
+
+ if (d == q) {
+ ret.insert(path);
+ return ret;
+ }
+
+ if (bit2mux.count(d) == 0 || bitusers[d] > 1)
+ return ret;
+
+ cell_int_t mux_cell_int = bit2mux.at(d);
+ RTLIL::SigSpec sig_a = sigmap(mux_cell_int.first->getPort("\\A"));
+ RTLIL::SigSpec sig_b = sigmap(mux_cell_int.first->getPort("\\B"));
+ RTLIL::SigSpec sig_s = sigmap(mux_cell_int.first->getPort("\\S"));
+ int width = GetSize(sig_a), index = mux_cell_int.second;
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ if (path.count(sig_s[i]) && path.at(sig_s[i]))
+ {
+ ret = find_muxtree_feedback_patterns(sig_b[i*width + index], q, path);
+
+ if (sig_b[i*width + index] == q) {
+ RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B");
+ s[i*width + index] = RTLIL::Sx;
+ mux_cell_int.first->setPort("\\B", s);
+ }
+
+ return ret;
+ }
+
+ pattern_t path_else = path;
+
+ for (int i = 0; i < GetSize(sig_s); i++)
+ {
+ if (path.count(sig_s[i]))
+ continue;
+
+ pattern_t path_this = path;
+ path_else[sig_s[i]] = false;
+ path_this[sig_s[i]] = true;
+
+ for (auto &pat : find_muxtree_feedback_patterns(sig_b[i*width + index], q, path_this))
+ ret.insert(pat);
+
+ if (sig_b[i*width + index] == q) {
+ RTLIL::SigSpec s = mux_cell_int.first->getPort("\\B");
+ s[i*width + index] = RTLIL::Sx;
+ mux_cell_int.first->setPort("\\B", s);
+ }
+ }
+
+ for (auto &pat : find_muxtree_feedback_patterns(sig_a[index], q, path_else))
+ ret.insert(pat);
+
+ if (sig_a[index] == q) {
+ RTLIL::SigSpec s = mux_cell_int.first->getPort("\\A");
+ s[index] = RTLIL::Sx;
+ mux_cell_int.first->setPort("\\A", s);
+ }
+
+ return ret;
+ }
+
+ void simplify_patterns(patterns_t&)
+ {
+ // TBD
+ }
+
+ RTLIL::SigSpec make_patterns_logic(patterns_t patterns, bool make_gates)
+ {
+ RTLIL::SigSpec or_input;
+
+ for (auto pat : patterns)
+ {
+ RTLIL::SigSpec s1, s2;
+ for (auto it : pat) {
+ s1.append(it.first);
+ s2.append(it.second);
+ }
+
+ RTLIL::SigSpec y = module->addWire(NEW_ID);
+ RTLIL::Cell *c = module->addNe(NEW_ID, s1, s2, y);
+
+ if (make_gates) {
+ simplemap(module, c);
+ module->remove(c);
+ }
+
+ or_input.append(y);
+ }
+
+ if (GetSize(or_input) == 0)
+ return RTLIL::S1;
+
+ if (GetSize(or_input) == 1)
+ return or_input;
+
+ RTLIL::SigSpec y = module->addWire(NEW_ID);
+ RTLIL::Cell *c = module->addReduceAnd(NEW_ID, or_input, y);
+
+ if (make_gates) {
+ simplemap(module, c);
+ module->remove(c);
+ }
+
+ return y;
+ }
+
+ void handle_dff_cell(RTLIL::Cell *dff_cell)
+ {
+ RTLIL::SigSpec sig_d = sigmap(dff_cell->getPort("\\D"));
+ RTLIL::SigSpec sig_q = sigmap(dff_cell->getPort("\\Q"));
+
+ std::map<patterns_t, std::set<int>> grouped_patterns;
+ std::set<int> remaining_indices;
+
+ for (int i = 0 ; i < GetSize(sig_d); i++) {
+ patterns_t patterns = find_muxtree_feedback_patterns(sig_d[i], sig_q[i], pattern_t());
+ if (!patterns.empty()) {
+ simplify_patterns(patterns);
+ grouped_patterns[patterns].insert(i);
+ } else
+ remaining_indices.insert(i);
+ }
+
+ for (auto &it : grouped_patterns) {
+ RTLIL::SigSpec new_sig_d, new_sig_q;
+ for (int i : it.second) {
+ new_sig_d.append(sig_d[i]);
+ new_sig_q.append(sig_q[i]);
+ }
+ if (!direct_to.empty()) {
+ log(" converting %s cell %s to %s for %s -> %s.\n", log_id(dff_cell->type), log_id(dff_cell), log_id(direct_to), log_signal(new_sig_d), log_signal(new_sig_q));
+ dff_cell->setPort("\\E", make_patterns_logic(it.first, true));
+ dff_cell->type = direct_to;
+ } else
+ if (dff_cell->type == "$dff") {
+ RTLIL::Cell *new_cell = module->addDffe(NEW_ID, dff_cell->getPort("\\CLK"), make_patterns_logic(it.first, false),
+ new_sig_d, new_sig_q, dff_cell->getParam("\\CLK_POLARITY").as_bool(), true);
+ log(" created $dffe cell %s for %s -> %s.\n", log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
+ } else {
+ RTLIL::Cell *new_cell = module->addDffeGate(NEW_ID, dff_cell->getPort("\\C"), make_patterns_logic(it.first, true),
+ new_sig_d, new_sig_q, dff_cell->type == "$_DFF_P_", true);
+ log(" created %s cell %s for %s -> %s.\n", log_id(new_cell->type), log_id(new_cell), log_signal(new_sig_d), log_signal(new_sig_q));
+ }
+ }
+
+ if (!direct_to.empty())
+ return;
+
+ if (remaining_indices.empty()) {
+ log(" removing now obsolete cell %s.\n", log_id(dff_cell));
+ module->remove(dff_cell);
+ } else if (GetSize(remaining_indices) != GetSize(sig_d)) {
+ log(" removing %d now obsolete bits from cell %s.\n", GetSize(sig_d) - GetSize(remaining_indices), log_id(dff_cell));
+ RTLIL::SigSpec new_sig_d, new_sig_q;
+ for (int i : remaining_indices) {
+ new_sig_d.append(sig_d[i]);
+ new_sig_q.append(sig_q[i]);
+ }
+ dff_cell->setPort("\\D", new_sig_d);
+ dff_cell->setPort("\\Q", new_sig_q);
+ dff_cell->setParam("\\WIDTH", GetSize(remaining_indices));
+ }
+ }
+
+ void run()
+ {
+ log("Transforming $dff to $dffe cells in module %s:\n", log_id(module));
+ for (auto dff_cell : dff_cells)
+ handle_dff_cell(dff_cell);
+ }
+};
+
+struct Dff2dffePass : public Pass {
+ Dff2dffePass() : Pass("dff2dffe", "transform $dff cells to $dffe cells") { }
+ virtual void help()
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" dff2dffe [selection]\n");
+ log("\n");
+ log("This pass transforms $dff cells driven by a tree of multiplexers with one or\n");
+ log("more feedback paths to $dffe cells. It also works on gate-level cells such as\n");
+ log("$_DFF_P_, $_DFF_N_ and $_MUX_.\n");
+ log("\n");
+ log(" -unmap\n");
+ log(" operate in the opposite direction: replace $dffe cells with combinations\n");
+ log(" of $dff and $mux cells. the options below are ignore in unmap mode.\n");
+ log("\n");
+ log(" -direct <internal_gate_type> <external_gate_type>\n");
+ log(" map directly to external gate type. <internal_gate_type> can\n");
+ log(" be any internal gate-level FF cell (except $_DFFE_??_). the\n");
+ log(" <external_gate_type> is the cell type name for a cell with an\n");
+ log(" identical interface to the <internal_gate_type>, except it\n");
+ log(" also has an high-active enable port 'E'.\n");
+ log(" Usually <external_gate_type> is an intemediate cell type\n");
+ log(" that is then translated to the final type using 'techmap'.\n");
+ log("\n");
+ }
+ virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
+ {
+ log_header("Executing DFF2DFFE pass (transform $dff to $dffe where applicable).\n");
+
+ bool unmap_mode = false;
+ RTLIL::IdString direct_from, direct_to;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-unmap") {
+ unmap_mode = true;
+ continue;
+ }
+ if (args[argidx] == "-direct" && argidx + 2 < args.size()) {
+ direct_from = RTLIL::escape_id(args[++argidx]);
+ direct_to = RTLIL::escape_id(args[++argidx]);
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ for (auto mod : design->selected_modules())
+ if (!mod->has_processes_warn())
+ {
+ if (unmap_mode) {
+ for (auto cell : mod->selected_cells()) {
+ if (cell->type == "$dffe") {
+ RTLIL::SigSpec tmp = mod->addWire(NEW_ID, GetSize(cell->getPort("\\D")));
+ mod->addDff(NEW_ID, cell->getPort("\\CLK"), tmp, cell->getPort("\\Q"), cell->getParam("\\CLK_POLARITY").as_bool());
+ if (cell->getParam("\\EN_POLARITY").as_bool())
+ mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\EN"), tmp);
+ else
+ mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\EN"), tmp);
+ mod->remove(cell);
+ continue;
+ }
+ if (cell->type.substr(0, 7) == "$_DFFE_") {
+ bool clk_pol = cell->type.substr(7, 1) == "P";
+ bool en_pol = cell->type.substr(8, 1) == "P";
+ RTLIL::SigSpec tmp = mod->addWire(NEW_ID);
+ mod->addDff(NEW_ID, cell->getPort("\\C"), tmp, cell->getPort("\\Q"), clk_pol);
+ if (en_pol)
+ mod->addMux(NEW_ID, cell->getPort("\\Q"), cell->getPort("\\D"), cell->getPort("\\E"), tmp);
+ else
+ mod->addMux(NEW_ID, cell->getPort("\\D"), cell->getPort("\\Q"), cell->getPort("\\E"), tmp);
+ mod->remove(cell);
+ continue;
+ }
+ }
+ continue;
+ }
+
+ Dff2dffeWorker worker(mod, direct_from, direct_to);
+ worker.run();
+ }
+ }
+} Dff2dffePass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc
index 07993b868..b0318a0b3 100644
--- a/passes/techmap/dfflibmap.cc
+++ b/passes/techmap/dfflibmap.cc
@@ -23,7 +23,8 @@
#include <string.h>
#include <errno.h>
-using namespace PASS_DFFLIBMAP;
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
struct cell_mapping {
std::string cell_name;
@@ -102,12 +103,12 @@ static bool parse_pin(LibertyAst *cell, LibertyAst *attr, std::string &pin_name,
return false;
}
-static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval)
+static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool has_reset, bool rstpol, bool rstval, bool prepare_mode)
{
LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
- float best_cell_area = 0;
+ double best_cell_area = 0;
if (ast->id != "library")
log_error("Format error in liberty file.\n");
@@ -143,7 +144,7 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
this_cell_ports[cell_rst_pin] = 'R';
this_cell_ports[cell_next_pin] = 'D';
- float area = 0;
+ double area = 0;
LibertyAst *ar = cell->find("area");
if (ar != NULL && !ar->value.empty())
area = atof(ar->value.c_str());
@@ -192,18 +193,27 @@ static void find_cell(LibertyAst *ast, std::string cell_type, bool clkpol, bool
}
if (best_cell != NULL) {
- log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.substr(1).c_str());
- cell_mappings[cell_type].cell_name = best_cell->args[0];
- cell_mappings[cell_type].ports = best_cell_ports;
+ log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str());
+ if (prepare_mode) {
+ cell_mappings[cell_type].cell_name = cell_type;
+ cell_mappings[cell_type].ports["C"] = 'C';
+ if (has_reset)
+ cell_mappings[cell_type].ports["R"] = 'R';
+ cell_mappings[cell_type].ports["D"] = 'D';
+ cell_mappings[cell_type].ports["Q"] = 'Q';
+ } else {
+ cell_mappings[cell_type].cell_name = best_cell->args[0];
+ cell_mappings[cell_type].ports = best_cell_ports;
+ }
}
}
-static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol)
+static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bool setpol, bool clrpol, bool prepare_mode)
{
LibertyAst *best_cell = NULL;
std::map<std::string, char> best_cell_ports;
int best_cell_pins = 0;
- float best_cell_area = 0;
+ double best_cell_area = 0;
if (ast->id != "library")
log_error("Format error in liberty file.\n");
@@ -235,7 +245,7 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
this_cell_ports[cell_clr_pin] = 'R';
this_cell_ports[cell_next_pin] = 'D';
- float area = 0;
+ double area = 0;
LibertyAst *ar = cell->find("area");
if (ar != NULL && !ar->value.empty())
area = atof(ar->value.c_str());
@@ -284,9 +294,18 @@ static void find_cell_sr(LibertyAst *ast, std::string cell_type, bool clkpol, bo
}
if (best_cell != NULL) {
- log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.substr(1).c_str());
- cell_mappings[cell_type].cell_name = best_cell->args[0];
- cell_mappings[cell_type].ports = best_cell_ports;
+ log(" cell %s (pins=%d, area=%.2f) is a direct match for cell type %s.\n", best_cell->args[0].c_str(), best_cell_pins, best_cell_area, cell_type.c_str());
+ if (prepare_mode) {
+ cell_mappings[cell_type].cell_name = cell_type;
+ cell_mappings[cell_type].ports["C"] = 'C';
+ cell_mappings[cell_type].ports["S"] = 'S';
+ cell_mappings[cell_type].ports["R"] = 'R';
+ cell_mappings[cell_type].ports["D"] = 'D';
+ cell_mappings[cell_type].ports["Q"] = 'Q';
+ } else {
+ cell_mappings[cell_type].cell_name = best_cell->args[0];
+ cell_mappings[cell_type].ports = best_cell_ports;
+ }
}
}
@@ -346,8 +365,12 @@ static void map_sr_to_arst(const char *from, const char *to)
if (!cell_mappings.count(from) || cell_mappings.count(to) > 0)
return;
- char from_clk_pol = from[8], from_set_pol = from[9], from_clr_pol = from[10];
- char to_clk_pol = to[6], to_rst_pol = to[7], to_rst_val = to[8];
+ char from_clk_pol YS_ATTRIBUTE(unused) = from[8];
+ char from_set_pol = from[9];
+ char from_clr_pol = from[10];
+ char to_clk_pol YS_ATTRIBUTE(unused) = to[6];
+ char to_rst_pol YS_ATTRIBUTE(unused) = to[7];
+ char to_rst_val = to[8];
log_assert(from_clk_pol == to_clk_pol);
log_assert(to_rst_pol == from_set_pol && to_rst_pol == from_clr_pol);
@@ -383,7 +406,7 @@ static void map_sr_to_arst(const char *from, const char *to)
}
}
-static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module)
+static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module, bool prepare_mode)
{
log("Mapping DFF cells in module `%s':\n", module->name.c_str());
@@ -402,7 +425,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module)
module->remove(cell);
cell_mapping &cm = cell_mappings[cell_type];
- RTLIL::Cell *new_cell = module->addCell(cell_name, "\\" + cm.cell_name);
+ RTLIL::Cell *new_cell = module->addCell(cell_name, prepare_mode ? cm.cell_name : "\\" + cm.cell_name);
for (auto &port : cm.ports) {
RTLIL::SigSpec sig;
@@ -411,7 +434,7 @@ static void dfflibmap(RTLIL::Design *design, RTLIL::Module *module)
} else
if (port.second == 'q') {
RTLIL::SigSpec old_sig = cell_connections[std::string("\\") + char(port.second - ('a' - 'A'))];
- sig = module->addWire(NEW_ID, SIZE(old_sig));
+ sig = module->addWire(NEW_ID, GetSize(old_sig));
module->addNotGate(NEW_ID, sig, old_sig);
} else
if ('a' <= port.second && port.second <= 'z') {
@@ -438,7 +461,7 @@ struct DfflibmapPass : public Pass {
virtual void help()
{
log("\n");
- log(" dfflibmap -liberty <file> [selection]\n");
+ log(" dfflibmap [-prepare] -liberty <file> [selection]\n");
log("\n");
log("Map internal flip-flop cells to the flip-flop cells in the technology\n");
log("library specified in the given liberty file.\n");
@@ -446,12 +469,17 @@ struct DfflibmapPass : public Pass {
log("This pass may add inverters as needed. Therefore it is recommended to\n");
log("first run this pass and then map the logic paths to the target technology.\n");
log("\n");
+ log("When called with -prepare, this command will convert the internal FF cells\n");
+ log("to the internal cell types that best match the cells found in the given\n");
+ log("liberty file.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
log_header("Executing DFFLIBMAP pass (mapping DFF cells to sequential cells from liberty file).\n");
std::string liberty_file;
+ bool prepare_mode = false;
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++)
@@ -461,6 +489,10 @@ struct DfflibmapPass : public Pass {
liberty_file = args[++argidx];
continue;
}
+ if (arg == "-prepare") {
+ prepare_mode = true;
+ continue;
+ }
break;
}
extra_args(args, argidx, design);
@@ -475,26 +507,26 @@ struct DfflibmapPass : public Pass {
LibertyParser libparser(f);
f.close();
- find_cell(libparser.ast, "$_DFF_N_", false, false, false, false);
- find_cell(libparser.ast, "$_DFF_P_", true, false, false, false);
-
- find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false);
- find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true);
- find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false);
- find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true);
- find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false);
- find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true);
- find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false);
- find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true);
-
- find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false);
- find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true);
- find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false);
- find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true);
- find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false);
- find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true);
- find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false);
- find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true);
+ find_cell(libparser.ast, "$_DFF_N_", false, false, false, false, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_P_", true, false, false, false, prepare_mode);
+
+ find_cell(libparser.ast, "$_DFF_NN0_", false, true, false, false, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_NN1_", false, true, false, true, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_NP0_", false, true, true, false, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_NP1_", false, true, true, true, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_PN0_", true, true, false, false, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_PN1_", true, true, false, true, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_PP0_", true, true, true, false, prepare_mode);
+ find_cell(libparser.ast, "$_DFF_PP1_", true, true, true, true, prepare_mode);
+
+ find_cell_sr(libparser.ast, "$_DFFSR_NNN_", false, false, false, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_NNP_", false, false, true, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_NPN_", false, true, false, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_NPP_", false, true, true, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_PNN_", true, false, false, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_PNP_", true, false, true, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_PPN_", true, true, false, prepare_mode);
+ find_cell_sr(libparser.ast, "$_DFFSR_PPP_", true, true, true, prepare_mode);
// try to implement as many cells as possible just by inverting
// the SET and RESET pins. If necessary, implement cell types
@@ -532,9 +564,10 @@ struct DfflibmapPass : public Pass {
for (auto &it : design->modules_)
if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
- dfflibmap(design, it.second);
+ dfflibmap(design, it.second, prepare_mode);
cell_mappings.clear();
}
} DfflibmapPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/extract.cc b/passes/techmap/extract.cc
index 221e9e49d..ff99040e1 100644
--- a/passes/techmap/extract.cc
+++ b/passes/techmap/extract.cc
@@ -26,256 +26,240 @@
#include <stdio.h>
#include <string.h>
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
using RTLIL::id2cstr;
-namespace
+class SubCircuitSolver : public SubCircuit::Solver
{
- class SubCircuitSolver : public SubCircuit::Solver
- {
- public:
- bool ignore_parameters;
- std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> ignored_parameters;
- std::set<RTLIL::IdString> cell_attr, wire_attr;
+public:
+ bool ignore_parameters;
+ std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> ignored_parameters;
+ std::set<RTLIL::IdString> cell_attr, wire_attr;
- SubCircuitSolver() : ignore_parameters(false)
- {
- }
+ SubCircuitSolver() : ignore_parameters(false)
+ {
+ }
- bool compareAttributes(const std::set<RTLIL::IdString> &attr, const std::map<RTLIL::IdString, RTLIL::Const> &needleAttr, const std::map<RTLIL::IdString, RTLIL::Const> &haystackAttr)
- {
- for (auto &it : attr) {
- size_t nc = needleAttr.count(it), hc = haystackAttr.count(it);
- if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it)))
- return false;
- }
- return true;
+ bool compareAttributes(const std::set<RTLIL::IdString> &attr, const dict<RTLIL::IdString, RTLIL::Const> &needleAttr, const dict<RTLIL::IdString, RTLIL::Const> &haystackAttr)
+ {
+ for (auto &it : attr) {
+ size_t nc = needleAttr.count(it), hc = haystackAttr.count(it);
+ if (nc != hc || (nc > 0 && needleAttr.at(it) != haystackAttr.at(it)))
+ return false;
}
+ return true;
+ }
- RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value)
- {
- if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_")
- return value;
-
- #define param_bool(_n) if (param == _n) return value.as_bool();
- param_bool("\\ARST_POLARITY");
- param_bool("\\A_SIGNED");
- param_bool("\\B_SIGNED");
- param_bool("\\CLK_ENABLE");
- param_bool("\\CLK_POLARITY");
- param_bool("\\CLR_POLARITY");
- param_bool("\\EN_POLARITY");
- param_bool("\\SET_POLARITY");
- param_bool("\\TRANSPARENT");
- #undef param_bool
-
- #define param_int(_n) if (param == _n) return value.as_int();
- param_int("\\ABITS")
- param_int("\\A_WIDTH")
- param_int("\\B_WIDTH")
- param_int("\\CTRL_IN_WIDTH")
- param_int("\\CTRL_OUT_WIDTH")
- param_int("\\OFFSET")
- param_int("\\PRIORITY")
- param_int("\\RD_PORTS")
- param_int("\\SIZE")
- param_int("\\STATE_BITS")
- param_int("\\STATE_NUM")
- param_int("\\STATE_NUM_LOG2")
- param_int("\\STATE_RST")
- param_int("\\S_WIDTH")
- param_int("\\TRANS_NUM")
- param_int("\\WIDTH")
- param_int("\\WR_PORTS")
- param_int("\\Y_WIDTH")
- #undef param_int
-
+ RTLIL::Const unified_param(RTLIL::IdString cell_type, RTLIL::IdString param, RTLIL::Const value)
+ {
+ if (cell_type.substr(0, 1) != "$" || cell_type.substr(0, 2) == "$_")
return value;
- }
- virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData,
- const std::string &, const std::string &, void *haystackUserData, const std::map<std::string, std::string> &portMapping)
- {
- RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData;
- RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData;
+ #define param_bool(_n) if (param == _n) return value.as_bool();
+ param_bool("\\ARST_POLARITY");
+ param_bool("\\A_SIGNED");
+ param_bool("\\B_SIGNED");
+ param_bool("\\CLK_ENABLE");
+ param_bool("\\CLK_POLARITY");
+ param_bool("\\CLR_POLARITY");
+ param_bool("\\EN_POLARITY");
+ param_bool("\\SET_POLARITY");
+ param_bool("\\TRANSPARENT");
+ #undef param_bool
+
+ #define param_int(_n) if (param == _n) return value.as_int();
+ param_int("\\ABITS")
+ param_int("\\A_WIDTH")
+ param_int("\\B_WIDTH")
+ param_int("\\CTRL_IN_WIDTH")
+ param_int("\\CTRL_OUT_WIDTH")
+ param_int("\\OFFSET")
+ param_int("\\PRIORITY")
+ param_int("\\RD_PORTS")
+ param_int("\\SIZE")
+ param_int("\\STATE_BITS")
+ param_int("\\STATE_NUM")
+ param_int("\\STATE_NUM_LOG2")
+ param_int("\\STATE_RST")
+ param_int("\\S_WIDTH")
+ param_int("\\TRANS_NUM")
+ param_int("\\WIDTH")
+ param_int("\\WR_PORTS")
+ param_int("\\Y_WIDTH")
+ #undef param_int
+
+ return value;
+ }
- if (!needleCell || !haystackCell) {
- log_assert(!needleCell && !haystackCell);
- return true;
- }
+ virtual bool userCompareNodes(const std::string &, const std::string &, void *needleUserData,
+ const std::string &, const std::string &, void *haystackUserData, const std::map<std::string, std::string> &portMapping)
+ {
+ RTLIL::Cell *needleCell = (RTLIL::Cell*) needleUserData;
+ RTLIL::Cell *haystackCell = (RTLIL::Cell*) haystackUserData;
- if (!ignore_parameters) {
- std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param;
- for (auto &it : needleCell->parameters)
- if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(needleCell->type, it.first)))
- needle_param[it.first] = unified_param(needleCell->type, it.first, it.second);
- for (auto &it : haystackCell->parameters)
- if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(haystackCell->type, it.first)))
- haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second);
- if (needle_param != haystack_param)
- return false;
- }
+ if (!needleCell || !haystackCell) {
+ log_assert(!needleCell && !haystackCell);
+ return true;
+ }
- if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes))
+ if (!ignore_parameters) {
+ std::map<RTLIL::IdString, RTLIL::Const> needle_param, haystack_param;
+ for (auto &it : needleCell->parameters)
+ if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(needleCell->type, it.first)))
+ needle_param[it.first] = unified_param(needleCell->type, it.first, it.second);
+ for (auto &it : haystackCell->parameters)
+ if (!ignored_parameters.count(std::pair<RTLIL::IdString, RTLIL::IdString>(haystackCell->type, it.first)))
+ haystack_param[it.first] = unified_param(haystackCell->type, it.first, it.second);
+ if (needle_param != haystack_param)
return false;
+ }
- if (wire_attr.size() > 0)
- {
- RTLIL::Wire *lastNeedleWire = NULL;
- RTLIL::Wire *lastHaystackWire = NULL;
- std::map<RTLIL::IdString, RTLIL::Const> emptyAttr;
+ if (cell_attr.size() > 0 && !compareAttributes(cell_attr, needleCell->attributes, haystackCell->attributes))
+ return false;
- for (auto &conn : needleCell->connections())
- {
- RTLIL::SigSpec needleSig = conn.second;
- RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str()));
-
- for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) {
- RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire;
- if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
- if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr))
- return false;
- lastNeedleWire = needleWire, lastHaystackWire = haystackWire;
- }
+ if (wire_attr.size() > 0)
+ {
+ RTLIL::Wire *lastNeedleWire = NULL;
+ RTLIL::Wire *lastHaystackWire = NULL;
+ dict<RTLIL::IdString, RTLIL::Const> emptyAttr;
+
+ for (auto &conn : needleCell->connections())
+ {
+ RTLIL::SigSpec needleSig = conn.second;
+ RTLIL::SigSpec haystackSig = haystackCell->getPort(portMapping.at(conn.first.str()));
+
+ for (int i = 0; i < std::min(needleSig.size(), haystackSig.size()); i++) {
+ RTLIL::Wire *needleWire = needleSig[i].wire, *haystackWire = haystackSig[i].wire;
+ if (needleWire != lastNeedleWire || haystackWire != lastHaystackWire)
+ if (!compareAttributes(wire_attr, needleWire ? needleWire->attributes : emptyAttr, haystackWire ? haystackWire->attributes : emptyAttr))
+ return false;
+ lastNeedleWire = needleWire, lastHaystackWire = haystackWire;
}
}
-
- return true;
}
- };
- struct bit_ref_t {
- std::string cell, port;
- int bit;
- };
+ return true;
+ }
+};
- bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL,
- int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL)
- {
- SigMap sigmap(mod);
- std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref;
+struct bit_ref_t {
+ std::string cell, port;
+ int bit;
+};
- if (sel && !sel->selected(mod)) {
- log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name));
- return false;
- }
+bool module2graph(SubCircuit::Graph &graph, RTLIL::Module *mod, bool constports, RTLIL::Design *sel = NULL,
+ int max_fanout = -1, std::set<std::pair<RTLIL::IdString, RTLIL::IdString>> *split = NULL)
+{
+ SigMap sigmap(mod);
+ std::map<RTLIL::SigBit, bit_ref_t> sig_bit_ref;
- if (mod->processes.size() > 0) {
- log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
- return false;
- }
+ if (sel && !sel->selected(mod)) {
+ log(" Skipping module %s as it is not selected.\n", id2cstr(mod->name));
+ return false;
+ }
- if (constports) {
- graph.createNode("$const$0", "$const$0", NULL, true);
- graph.createNode("$const$1", "$const$1", NULL, true);
- graph.createNode("$const$x", "$const$x", NULL, true);
- graph.createNode("$const$z", "$const$z", NULL, true);
- graph.createPort("$const$0", "\\Y", 1);
- graph.createPort("$const$1", "\\Y", 1);
- graph.createPort("$const$x", "\\Y", 1);
- graph.createPort("$const$z", "\\Y", 1);
- graph.markExtern("$const$0", "\\Y", 0);
- graph.markExtern("$const$1", "\\Y", 0);
- graph.markExtern("$const$x", "\\Y", 0);
- graph.markExtern("$const$z", "\\Y", 0);
- }
+ if (mod->processes.size() > 0) {
+ log(" Skipping module %s as it contains unprocessed processes.\n", id2cstr(mod->name));
+ return false;
+ }
- std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count;
- if (max_fanout > 0)
- for (auto &cell_it : mod->cells_)
- {
- RTLIL::Cell *cell = cell_it.second;
- if (!sel || sel->selected(mod, cell))
- for (auto &conn : cell->connections()) {
- RTLIL::SigSpec conn_sig = conn.second;
- sigmap.apply(conn_sig);
- for (auto &bit : conn_sig)
- if (bit.wire != NULL)
- sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++;
- }
- }
+ if (constports) {
+ graph.createNode("$const$0", "$const$0", NULL, true);
+ graph.createNode("$const$1", "$const$1", NULL, true);
+ graph.createNode("$const$x", "$const$x", NULL, true);
+ graph.createNode("$const$z", "$const$z", NULL, true);
+ graph.createPort("$const$0", "\\Y", 1);
+ graph.createPort("$const$1", "\\Y", 1);
+ graph.createPort("$const$x", "\\Y", 1);
+ graph.createPort("$const$z", "\\Y", 1);
+ graph.markExtern("$const$0", "\\Y", 0);
+ graph.markExtern("$const$1", "\\Y", 0);
+ graph.markExtern("$const$x", "\\Y", 0);
+ graph.markExtern("$const$z", "\\Y", 0);
+ }
- // create graph nodes from cells
+ std::map<std::pair<RTLIL::Wire*, int>, int> sig_use_count;
+ if (max_fanout > 0)
for (auto &cell_it : mod->cells_)
{
RTLIL::Cell *cell = cell_it.second;
- if (sel && !sel->selected(mod, cell))
- continue;
+ if (!sel || sel->selected(mod, cell))
+ for (auto &conn : cell->connections()) {
+ RTLIL::SigSpec conn_sig = conn.second;
+ sigmap.apply(conn_sig);
+ for (auto &bit : conn_sig)
+ if (bit.wire != NULL)
+ sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)]++;
+ }
+ }
- std::string type = cell->type.str();
- if (sel == NULL && type.substr(0, 2) == "\\$")
- type = type.substr(1);
- graph.createNode(cell->name.str(), type, (void*)cell);
+ // create graph nodes from cells
+ for (auto &cell_it : mod->cells_)
+ {
+ RTLIL::Cell *cell = cell_it.second;
+ if (sel && !sel->selected(mod, cell))
+ continue;
- for (auto &conn : cell->connections())
- {
- graph.createPort(cell->name.str(), conn.first.str(), conn.second.size());
+ std::string type = cell->type.str();
+ if (sel == NULL && type.substr(0, 2) == "\\$")
+ type = type.substr(1);
+ graph.createNode(cell->name.str(), type, (void*)cell);
- if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0)
- continue;
+ for (auto &conn : cell->connections())
+ {
+ graph.createPort(cell->name.str(), conn.first.str(), conn.second.size());
- RTLIL::SigSpec conn_sig = conn.second;
- sigmap.apply(conn_sig);
+ if (split && split->count(std::pair<RTLIL::IdString, RTLIL::IdString>(cell->type, conn.first)) > 0)
+ continue;
- for (int i = 0; i < conn_sig.size(); i++)
- {
- auto &bit = conn_sig[i];
-
- if (bit.wire == NULL) {
- if (constports) {
- std::string node = "$const$x";
- if (bit == RTLIL::State::S0) node = "$const$0";
- if (bit == RTLIL::State::S1) node = "$const$1";
- if (bit == RTLIL::State::Sz) node = "$const$z";
- graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0);
- } else
- graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data));
- continue;
- }
+ RTLIL::SigSpec conn_sig = conn.second;
+ sigmap.apply(conn_sig);
- if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)] > max_fanout)
- continue;
+ for (int i = 0; i < conn_sig.size(); i++)
+ {
+ auto &bit = conn_sig[i];
+
+ if (bit.wire == NULL) {
+ if (constports) {
+ std::string node = "$const$x";
+ if (bit == RTLIL::State::S0) node = "$const$0";
+ if (bit == RTLIL::State::S1) node = "$const$1";
+ if (bit == RTLIL::State::Sz) node = "$const$z";
+ graph.createConnection(cell->name.str(), conn.first.str(), i, node, "\\Y", 0);
+ } else
+ graph.createConstant(cell->name.str(), conn.first.str(), i, int(bit.data));
+ continue;
+ }
- if (sel && !sel->selected(mod, bit.wire))
- continue;
+ if (max_fanout > 0 && sig_use_count[std::pair<RTLIL::Wire*, int>(bit.wire, bit.offset)] > max_fanout)
+ continue;
- if (sig_bit_ref.count(bit) == 0) {
- bit_ref_t &bit_ref = sig_bit_ref[bit];
- bit_ref.cell = cell->name.str();
- bit_ref.port = conn.first.str();
- bit_ref.bit = i;
- }
+ if (sel && !sel->selected(mod, bit.wire))
+ continue;
+ if (sig_bit_ref.count(bit) == 0) {
bit_ref_t &bit_ref = sig_bit_ref[bit];
- graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i);
+ bit_ref.cell = cell->name.str();
+ bit_ref.port = conn.first.str();
+ bit_ref.bit = i;
}
- }
- }
-
- // mark external signals (used in non-selected cells)
- for (auto &cell_it : mod->cells_)
- {
- RTLIL::Cell *cell = cell_it.second;
- if (sel && !sel->selected(mod, cell))
- for (auto &conn : cell->connections())
- {
- RTLIL::SigSpec conn_sig = conn.second;
- sigmap.apply(conn_sig);
- for (auto &bit : conn_sig)
- if (sig_bit_ref.count(bit) != 0) {
- bit_ref_t &bit_ref = sig_bit_ref[bit];
- graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
- }
- }
+ bit_ref_t &bit_ref = sig_bit_ref[bit];
+ graph.createConnection(bit_ref.cell, bit_ref.port, bit_ref.bit, cell->name.str(), conn.first.str(), i);
+ }
}
+ }
- // mark external signals (used in module ports)
- for (auto &wire_it : mod->wires_)
- {
- RTLIL::Wire *wire = wire_it.second;
- if (wire->port_id > 0)
+ // mark external signals (used in non-selected cells)
+ for (auto &cell_it : mod->cells_)
+ {
+ RTLIL::Cell *cell = cell_it.second;
+ if (sel && !sel->selected(mod, cell))
+ for (auto &conn : cell->connections())
{
- RTLIL::SigSpec conn_sig(wire);
+ RTLIL::SigSpec conn_sig = conn.second;
sigmap.apply(conn_sig);
for (auto &bit : conn_sig)
@@ -284,70 +268,86 @@ namespace
graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
}
}
- }
-
- // graph.print();
- return true;
}
- RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
+ // mark external signals (used in module ports)
+ for (auto &wire_it : mod->wires_)
{
- SigMap sigmap(needle);
- SigSet<std::pair<RTLIL::IdString, int>> sig2port;
-
- // create new cell
- RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name);
-
- // create cell ports
- for (auto &it : needle->wires_) {
- RTLIL::Wire *wire = it.second;
- if (wire->port_id > 0) {
- for (int i = 0; i < wire->width; i++)
- sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i));
- cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width));
- }
+ RTLIL::Wire *wire = wire_it.second;
+ if (wire->port_id > 0)
+ {
+ RTLIL::SigSpec conn_sig(wire);
+ sigmap.apply(conn_sig);
+
+ for (auto &bit : conn_sig)
+ if (sig_bit_ref.count(bit) != 0) {
+ bit_ref_t &bit_ref = sig_bit_ref[bit];
+ graph.markExtern(bit_ref.cell, bit_ref.port, bit_ref.bit);
+ }
}
+ }
- // delete replaced cells and connect new ports
- for (auto &it : match.mappings)
- {
- auto &mapping = it.second;
- RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
- RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;
+ // graph.print();
+ return true;
+}
- if (needle_cell == NULL)
- continue;
+RTLIL::Cell *replace(RTLIL::Module *needle, RTLIL::Module *haystack, SubCircuit::Solver::Result &match)
+{
+ SigMap sigmap(needle);
+ SigSet<std::pair<RTLIL::IdString, int>> sig2port;
+
+ // create new cell
+ RTLIL::Cell *cell = haystack->addCell(stringf("$extract$%s$%d", needle->name.c_str(), autoidx++), needle->name);
+
+ // create cell ports
+ for (auto &it : needle->wires_) {
+ RTLIL::Wire *wire = it.second;
+ if (wire->port_id > 0) {
+ for (int i = 0; i < wire->width; i++)
+ sig2port.insert(sigmap(RTLIL::SigSpec(wire, i)), std::pair<RTLIL::IdString, int>(wire->name, i));
+ cell->setPort(wire->name, RTLIL::SigSpec(RTLIL::State::Sz, wire->width));
+ }
+ }
- for (auto &conn : needle_cell->connections()) {
- RTLIL::SigSpec sig = sigmap(conn.second);
- if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) {
- for (int i = 0; i < sig.size(); i++)
- for (auto &port : sig2port.find(sig[i])) {
- RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1);
- RTLIL::SigSpec new_sig = cell->getPort(port.first);
- new_sig.replace(port.second, bitsig);
- cell->setPort(port.first, new_sig);
- }
+ // delete replaced cells and connect new ports
+ for (auto &it : match.mappings)
+ {
+ auto &mapping = it.second;
+ RTLIL::Cell *needle_cell = (RTLIL::Cell*)mapping.needleUserData;
+ RTLIL::Cell *haystack_cell = (RTLIL::Cell*)mapping.haystackUserData;
+
+ if (needle_cell == NULL)
+ continue;
+
+ for (auto &conn : needle_cell->connections()) {
+ RTLIL::SigSpec sig = sigmap(conn.second);
+ if (mapping.portMapping.count(conn.first.str()) > 0 && sig2port.has(sigmap(sig))) {
+ for (int i = 0; i < sig.size(); i++)
+ for (auto &port : sig2port.find(sig[i])) {
+ RTLIL::SigSpec bitsig = haystack_cell->getPort(mapping.portMapping[conn.first.str()]).extract(i, 1);
+ RTLIL::SigSpec new_sig = cell->getPort(port.first);
+ new_sig.replace(port.second, bitsig);
+ cell->setPort(port.first, new_sig);
}
}
-
- haystack->remove(haystack_cell);
}
- return cell;
+ haystack->remove(haystack_cell);
}
- bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
- {
- int left_idx = 0, right_idx = 0;
- if (left->attributes.count("\\extract_order") > 0)
- left_idx = left->attributes.at("\\extract_order").as_int();
- if (right->attributes.count("\\extract_order") > 0)
- right_idx = right->attributes.at("\\extract_order").as_int();
- if (left_idx != right_idx)
- return left_idx < right_idx;
- return left->name < right->name;
- }
+ return cell;
+}
+
+bool compareSortNeedleList(RTLIL::Module *left, RTLIL::Module *right)
+{
+ int left_idx = 0, right_idx = 0;
+ if (left->attributes.count("\\extract_order") > 0)
+ left_idx = left->attributes.at("\\extract_order").as_int();
+ if (right->attributes.count("\\extract_order") > 0)
+ right_idx = right->attributes.at("\\extract_order").as_int();
+ if (left_idx != right_idx)
+ return left_idx < right_idx;
+ return left->name < right->name;
}
struct ExtractPass : public Pass {
@@ -518,24 +518,21 @@ struct ExtractPass : public Pass {
if (args[argidx] == "-swap" && argidx+2 < args.size()) {
std::string type = RTLIL::escape_id(args[++argidx]);
std::set<std::string> ports;
- char *ports_str = strdup(args[++argidx].c_str());
- for (char *sptr, *p = strtok_r(ports_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+ std::string ports_str = args[++argidx], p;
+ while (!(p = next_token(ports_str, ",\t\r\n ")).empty())
ports.insert(RTLIL::escape_id(p));
- free(ports_str);
solver.addSwappablePorts(type, ports);
continue;
}
if (args[argidx] == "-perm" && argidx+3 < args.size()) {
std::string type = RTLIL::escape_id(args[++argidx]);
std::vector<std::string> map_left, map_right;
- char *left_str = strdup(args[++argidx].c_str());
- char *right_str = strdup(args[++argidx].c_str());
- for (char *sptr, *p = strtok_r(left_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+ std::string left_str = args[++argidx];
+ std::string right_str = args[++argidx], p;
+ while (!(p = next_token(left_str, ",\t\r\n ")).empty())
map_left.push_back(RTLIL::escape_id(p));
- for (char *sptr, *p = strtok_r(right_str, ",\t\r\n ", &sptr); p != NULL; p = strtok_r(NULL, ",\t\r\n ", &sptr))
+ while (!(p = next_token(right_str, ",\t\r\n ")).empty())
map_right.push_back(RTLIL::escape_id(p));
- free(left_str);
- free(right_str);
if (map_left.size() != map_right.size())
log_cmd_error("Arguments to -perm are not a valid permutation!\n");
std::map<std::string, std::string> map;
@@ -665,7 +662,7 @@ struct ExtractPass : public Pass {
log("Solving for %s in %s.\n", ("needle_" + RTLIL::unescape_id(needle->name)).c_str(), haystack_it.first.c_str());
solver.solve(results, "needle_" + RTLIL::unescape_id(needle->name), haystack_it.first, false);
}
- log("Found %zd matches.\n", results.size());
+ log("Found %d matches.\n", GetSize(results));
if (results.size() > 0)
{
@@ -761,3 +758,4 @@ struct ExtractPass : public Pass {
}
} ExtractPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/hilomap.cc b/passes/techmap/hilomap.cc
index 784c4cf31..9a14ffa3c 100644
--- a/passes/techmap/hilomap.cc
+++ b/passes/techmap/hilomap.cc
@@ -21,6 +21,9 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
static std::string hicell_celltype, hicell_portname;
static std::string locell_celltype, locell_portname;
static bool singleton_mode;
@@ -57,9 +60,7 @@ struct HilomapPass : public Pass {
log("\n");
log(" hilomap [options] [selection]\n");
log("\n");
- log("Map module inputs/outputs to PAD cells from a library. This pass\n");
- log("can only map to very simple PAD cells. Use 'techmap' to further map\n");
- log("the resulting cells to more sophisticated PAD cells.\n");
+ log("Map constants to 'tielo' and 'tiehi' driver cells.\n");
log("\n");
log(" -hicell <celltype> <portname>\n");
log(" Replace constant hi bits with this cell.\n");
@@ -75,7 +76,7 @@ struct HilomapPass : public Pass {
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
- log_header("Executing HILOPAD pass (mapping to constant drivers).\n");
+ log_header("Executing HILOMAP pass (mapping to constant drivers).\n");
hicell_celltype = std::string();
hicell_portname = std::string();
@@ -119,3 +120,4 @@ struct HilomapPass : public Pass {
}
} HilomapPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/iopadmap.cc b/passes/techmap/iopadmap.cc
index 9cd23ce6f..3fba0e618 100644
--- a/passes/techmap/iopadmap.cc
+++ b/passes/techmap/iopadmap.cc
@@ -21,7 +21,10 @@
#include "kernel/rtlil.h"
#include "kernel/log.h"
-static void split_portname_pair(std::string &port1, std::string &port2)
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+void split_portname_pair(std::string &port1, std::string &port2)
{
size_t pos = port1.find_first_of(':');
if (pos != std::string::npos) {
@@ -59,8 +62,8 @@ struct IopadmapPass : public Pass {
log("\n");
log(" -bits\n");
log(" create individual bit-wide buffers even for ports that\n");
- log(" are wider. (the default behavio is to create word-wide\n");
- log(" buffers use -widthparam to set the word size on the cell.)\n");
+ log(" are wider. (the default behavior is to create word-wide\n");
+ log(" buffers using -widthparam to set the word size on the cell.)\n");
log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
@@ -111,18 +114,11 @@ struct IopadmapPass : public Pass {
}
extra_args(args, argidx, design);
- for (auto &it : design->modules_)
+ for (auto module : design->selected_modules())
{
- RTLIL::Module *module = it.second;
-
- if (!design->selected(module) || module->get_bool_attribute("\\blackbox"))
- continue;
-
- for (auto &it2 : module->wires_)
+ for (auto wire : module->selected_wires())
{
- RTLIL::Wire *wire = it2.second;
-
- if (!wire->port_id || !design->selected(module, wire))
+ if (!wire->port_id)
continue;
std::string celltype, portname, portname2;
@@ -207,3 +203,4 @@ struct IopadmapPass : public Pass {
}
} IopadmapPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc
index 612fa1117..def480394 100644
--- a/passes/techmap/libparse.cc
+++ b/passes/techmap/libparse.cc
@@ -29,7 +29,7 @@
#include "kernel/log.h"
#endif
-using namespace PASS_DFFLIBMAP;
+using namespace Yosys;
std::set<std::string> LibertyAst::blacklist;
std::set<std::string> LibertyAst::whitelist;
@@ -43,8 +43,6 @@ LibertyAst::~LibertyAst()
LibertyAst *LibertyAst::find(std::string name)
{
- if (this == NULL)
- return NULL;
for (auto child : children)
if (child->id == name)
return child;
@@ -107,14 +105,14 @@ int LibertyParser::lexer(std::string &str)
}
if (c == '"') {
- str = c;
+ str = "";
while (1) {
c = f.get();
if (c == '\n')
line++;
- str += c;
if (c == '"')
break;
+ str += c;
}
// fprintf(stderr, "LEX: string >>%s<<\n", str.c_str());
return 'v';
@@ -244,21 +242,6 @@ void LibertyParser::error()
/**** BEGIN: http://svn.clifford.at/tools/trunk/examples/check.h ****/
-// This is to not confuse the VIM syntax highlighting
-#define CHECK_VAL_OPEN (
-#define CHECK_VAL_CLOSE )
-
-#define CHECK(result, check) \
- CHECK_VAL_OPEN{ \
- auto _R = (result); \
- if (!(_R check)) { \
- fprintf(stderr, "Error from '%s' (%ld %s) in %s:%d.\n", \
- #result, (long int)_R, #check, __FILE__, __LINE__); \
- abort(); \
- } \
- _R; \
- }CHECK_VAL_CLOSE
-
#define CHECK_NV(result, check) \
do { \
auto _R = (result); \
@@ -280,6 +263,14 @@ void LibertyParser::error()
/**** END: http://svn.clifford.at/tools/trunk/examples/check.h ****/
+LibertyAst *find_non_null(LibertyAst *node, const char *name)
+{
+ LibertyAst *ret = node->find(name);
+ if (ret == NULL)
+ fprintf(stderr, "Error: expected to find `%s' node.\n", name);
+ return ret;
+}
+
std::string func2vl(std::string str)
{
for (size_t pos = str.find_first_of("\" \t"); pos != std::string::npos; pos = str.find_first_of("\" \t")) {
@@ -388,7 +379,7 @@ void gen_verilogsim_cell(LibertyAst *ast)
if (child->id != "pin")
continue;
CHECK_NV(child->args.size(), == 1);
- LibertyAst *dir = CHECK(child->find("direction"), != NULL);
+ LibertyAst *dir = find_non_null(child, "direction");
LibertyAst *func = child->find("function");
printf(" %s %s;\n", dir->value.c_str(), child->args[0].c_str());
if (func != NULL)
@@ -428,8 +419,8 @@ void gen_verilogsim_cell(LibertyAst *ast)
const char *else_prefix = "";
if (!clear_expr.empty() && !preset_expr.empty()) {
printf(" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str());
- clear_preset_var(iq_var, CHECK(child->find("clear_preset_var1"), != NULL)->value);
- clear_preset_var(iqn_var, CHECK(child->find("clear_preset_var2"), != NULL)->value);
+ clear_preset_var(iq_var, find_non_null(child, "clear_preset_var1")->value);
+ clear_preset_var(iqn_var, find_non_null(child, "clear_preset_var2")->value);
printf(" end\n");
else_prefix = "else ";
}
@@ -449,7 +440,7 @@ void gen_verilogsim_cell(LibertyAst *ast)
}
if (*else_prefix)
printf(" %sbegin\n", else_prefix);
- std::string expr = CHECK(child->find("next_state"), != NULL)->value;
+ std::string expr = find_non_null(child, "next_state")->value;
printf(" // %s\n", expr.c_str());
printf(" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str());
printf(" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str());
@@ -481,8 +472,8 @@ void gen_verilogsim_cell(LibertyAst *ast)
const char *else_prefix = "";
if (!clear_expr.empty() && !preset_expr.empty()) {
printf(" %sif ((%s) && (%s)) begin\n", else_prefix, clear_expr.c_str(), preset_expr.c_str());
- clear_preset_var(iq_var, CHECK(child->find("clear_preset_var1"), != NULL)->value);
- clear_preset_var(iqn_var, CHECK(child->find("clear_preset_var2"), != NULL)->value);
+ clear_preset_var(iq_var, find_non_null(child, "clear_preset_var1")->value);
+ clear_preset_var(iqn_var, find_non_null(child, "clear_preset_var2")->value);
printf(" end\n");
else_prefix = "else ";
}
@@ -502,7 +493,7 @@ void gen_verilogsim_cell(LibertyAst *ast)
}
if (!enable_expr.empty()) {
printf(" %sif (%s) begin\n", else_prefix, enable_expr.c_str());
- std::string expr = CHECK(child->find("data_in"), != NULL)->value;
+ std::string expr = find_non_null(child, "data_in")->value;
printf(" %s <= %s;\n", iq_var.c_str(), func2vl(expr).c_str());
printf(" %s <= ~(%s);\n", iqn_var.c_str(), func2vl(expr).c_str());
printf(" end\n");
diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h
index 247487424..e947bd8cd 100644
--- a/passes/techmap/libparse.h
+++ b/passes/techmap/libparse.h
@@ -25,7 +25,7 @@
#include <vector>
#include <set>
-namespace PASS_DFFLIBMAP
+namespace Yosys
{
struct LibertyAst
{
diff --git a/passes/techmap/maccmap.cc b/passes/techmap/maccmap.cc
index 2d625eefe..ffbd6289d 100644
--- a/passes/techmap/maccmap.cc
+++ b/passes/techmap/maccmap.cc
@@ -20,7 +20,8 @@
#include "kernel/yosys.h"
#include "kernel/macc.h"
-extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false);
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
struct MaccmapWorker
{
@@ -48,7 +49,7 @@ struct MaccmapWorker
void add(RTLIL::SigSpec a, bool is_signed, bool do_subtract)
{
- a.extend(width, is_signed);
+ a.extend_u0(width, is_signed);
if (do_subtract) {
a = module->Not(NEW_ID, a);
@@ -61,16 +62,16 @@ struct MaccmapWorker
void add(RTLIL::SigSpec a, RTLIL::SigSpec b, bool is_signed, bool do_subtract)
{
- if (SIZE(a) < SIZE(b))
+ if (GetSize(a) < GetSize(b))
std::swap(a, b);
- a.extend(width, is_signed);
+ a.extend_u0(width, is_signed);
- if (SIZE(b) > width)
- b.extend(width, is_signed);
+ if (GetSize(b) > width)
+ b.extend_u0(width, is_signed);
- for (int i = 0; i < SIZE(b); i++)
- if (is_signed && i+1 == SIZE(b))
+ for (int i = 0; i < GetSize(b); i++)
+ if (is_signed && i+1 == GetSize(b))
{
a = {module->Not(NEW_ID, a.extract(i, width-i)), RTLIL::SigSpec(0, i)};
add(module->And(NEW_ID, a, RTLIL::SigSpec(b[i], width)), false, do_subtract);
@@ -85,7 +86,7 @@ struct MaccmapWorker
void fulladd(RTLIL::SigSpec &in1, RTLIL::SigSpec &in2, RTLIL::SigSpec &in3, RTLIL::SigSpec &out1, RTLIL::SigSpec &out2)
{
- int start_index = 0, stop_index = SIZE(in1);
+ int start_index = 0, stop_index = GetSize(in1);
while (start_index < stop_index && in1[start_index] == RTLIL::S0 && in2[start_index] == RTLIL::S0 && in3[start_index] == RTLIL::S0)
start_index++;
@@ -95,18 +96,18 @@ struct MaccmapWorker
if (start_index == stop_index)
{
- out1 = RTLIL::SigSpec(0, SIZE(in1));
- out2 = RTLIL::SigSpec(0, SIZE(in1));
+ out1 = RTLIL::SigSpec(0, GetSize(in1));
+ out2 = RTLIL::SigSpec(0, GetSize(in1));
}
else
{
- RTLIL::SigSpec out_zeros_lsb(0, start_index), out_zeros_msb(0, SIZE(in1)-stop_index);
+ RTLIL::SigSpec out_zeros_lsb(0, start_index), out_zeros_msb(0, GetSize(in1)-stop_index);
in1 = in1.extract(start_index, stop_index-start_index);
in2 = in2.extract(start_index, stop_index-start_index);
in3 = in3.extract(start_index, stop_index-start_index);
- int width = SIZE(in1);
+ int width = GetSize(in1);
RTLIL::Wire *w1 = module->addWire(NEW_ID, width);
RTLIL::Wire *w2 = module->addWire(NEW_ID, width);
@@ -164,12 +165,12 @@ struct MaccmapWorker
while (1)
{
- int free_bit_slots = tree_bit_slots(SIZE(summands)) - SIZE(tree_sum_bits);
+ int free_bit_slots = tree_bit_slots(GetSize(summands)) - GetSize(tree_sum_bits);
int max_depth = 0, max_position = 0;
for (int i = 0; i < width; i++)
- if (max_depth <= SIZE(bits.at(i))) {
- max_depth = SIZE(bits.at(i));
+ if (max_depth <= GetSize(bits.at(i))) {
+ max_depth = GetSize(bits.at(i));
max_position = i;
}
@@ -178,14 +179,14 @@ struct MaccmapWorker
int required_bits = 0;
for (int i = 0; i <= max_position; i++)
- if (SIZE(bits.at(i)) == max_depth)
+ if (GetSize(bits.at(i)) == max_depth)
required_bits += 1 << i;
if (required_bits > free_bit_slots)
break;
for (int i = 0; i <= max_position; i++)
- if (SIZE(bits.at(i)) == max_depth) {
+ if (GetSize(bits.at(i)) == max_depth) {
auto it = bits.at(i).begin();
RTLIL::SigBit bit = *it;
for (int k = 0; k < (1 << i); k++, free_bit_slots--)
@@ -199,23 +200,23 @@ struct MaccmapWorker
}
if (!tree_sum_bits.empty())
- log(" packed %d (%d) bits / %d words into adder tree\n", SIZE(tree_sum_bits), unique_tree_bits, count_tree_words);
+ log(" packed %d (%d) bits / %d words into adder tree\n", GetSize(tree_sum_bits), unique_tree_bits, count_tree_words);
- if (SIZE(summands) == 0) {
+ if (GetSize(summands) == 0) {
log_assert(tree_sum_bits.empty());
return RTLIL::SigSpec(0, width);
}
- if (SIZE(summands) == 1) {
+ if (GetSize(summands) == 1) {
log_assert(tree_sum_bits.empty());
return summands.front();
}
- while (SIZE(summands) > 2)
+ while (GetSize(summands) > 2)
{
std::vector<RTLIL::SigSpec> new_summands;
- for (int i = 0; i < SIZE(summands); i += 3)
- if (i+2 < SIZE(summands)) {
+ for (int i = 0; i < GetSize(summands); i += 3)
+ if (i+2 < GetSize(summands)) {
RTLIL::SigSpec in1 = summands[i];
RTLIL::SigSpec in2 = summands[i+1];
RTLIL::SigSpec in3 = summands[i+2];
@@ -256,9 +257,14 @@ struct MaccmapWorker
}
};
+PRIVATE_NAMESPACE_END
+YOSYS_NAMESPACE_BEGIN
+
+extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false);
+
void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
{
- int width = SIZE(cell->getPort("\\Y"));
+ int width = GetSize(cell->getPort("\\Y"));
Macc macc;
macc.from_cell(cell);
@@ -273,15 +279,15 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
}
for (auto &port : macc.ports)
- if (SIZE(port.in_b) == 0)
+ if (GetSize(port.in_b) == 0)
log(" %s %s (%d bits, %s)\n", port.do_subtract ? "sub" : "add", log_signal(port.in_a),
- SIZE(port.in_a), port.is_signed ? "signed" : "unsigned");
+ GetSize(port.in_a), port.is_signed ? "signed" : "unsigned");
else
log(" %s %s * %s (%dx%d bits, %s)\n", port.do_subtract ? "sub" : "add", log_signal(port.in_a), log_signal(port.in_b),
- SIZE(port.in_a), SIZE(port.in_b), port.is_signed ? "signed" : "unsigned");
+ GetSize(port.in_a), GetSize(port.in_b), port.is_signed ? "signed" : "unsigned");
- if (SIZE(macc.bit_ports) != 0)
- log(" add bits %s (%d bits)\n", log_signal(macc.bit_ports), SIZE(macc.bit_ports));
+ if (GetSize(macc.bit_ports) != 0)
+ log(" add bits %s (%d bits)\n", log_signal(macc.bit_ports), GetSize(macc.bit_ports));
if (unmap)
{
@@ -290,10 +296,10 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
for (auto &port : macc.ports) {
summand_t this_summand;
- if (SIZE(port.in_b)) {
+ if (GetSize(port.in_b)) {
this_summand.first = module->addWire(NEW_ID, width);
module->addMul(NEW_ID, port.in_a, port.in_b, this_summand.first, port.is_signed);
- } else if (SIZE(port.in_a) != width) {
+ } else if (GetSize(port.in_a) != width) {
this_summand.first = module->addWire(NEW_ID, width);
module->addPos(NEW_ID, port.in_a, this_summand.first, port.is_signed);
} else {
@@ -306,14 +312,14 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
for (auto &bit : macc.bit_ports)
summands.push_back(summand_t(bit, false));
- if (SIZE(summands) == 0)
+ if (GetSize(summands) == 0)
summands.push_back(summand_t(RTLIL::SigSpec(0, width), false));
- while (SIZE(summands) > 1)
+ while (GetSize(summands) > 1)
{
std::vector<summand_t> new_summands;
- for (int i = 0; i < SIZE(summands); i += 2) {
- if (i+1 < SIZE(summands)) {
+ for (int i = 0; i < GetSize(summands); i += 2) {
+ if (i+1 < GetSize(summands)) {
summand_t this_summand;
this_summand.first = module->addWire(NEW_ID, width);
this_summand.second = summands[i].second && summands[i+1].second;
@@ -342,7 +348,7 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
MaccmapWorker worker(module, width);
for (auto &port : macc.ports)
- if (SIZE(port.in_b) == 0)
+ if (GetSize(port.in_b) == 0)
worker.add(port.in_a, port.is_signed, port.do_subtract);
else
worker.add(port.in_a, port.in_b, port.is_signed, port.do_subtract);
@@ -354,6 +360,9 @@ void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap)
}
}
+YOSYS_NAMESPACE_END
+PRIVATE_NAMESPACE_BEGIN
+
struct MaccmapPass : public Pass {
MaccmapPass() : Pass("maccmap", "mapping macc cells") { }
virtual void help()
@@ -392,3 +401,4 @@ struct MaccmapPass : public Pass {
}
} MaccmapPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc
index f8d5d4584..9cea5f45d 100644
--- a/passes/techmap/simplemap.cc
+++ b/passes/techmap/simplemap.cc
@@ -17,53 +17,53 @@
*
*/
-#include "kernel/register.h"
+#include "simplemap.h"
#include "kernel/sigtools.h"
-#include "kernel/log.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
-extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
+USING_YOSYS_NAMESPACE
+YOSYS_NAMESPACE_BEGIN
-static void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
- sig_a.extend(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
+ sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
- for (int i = 0; i < SIZE(sig_y); i++) {
+ for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
gate->setPort("\\A", sig_a[i]);
gate->setPort("\\Y", sig_y[i]);
}
}
-static void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
- sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
+ sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
module->connect(RTLIL::SigSig(sig_y, sig_a));
}
-static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
- sig_a.extend_u0(SIZE(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
- sig_b.extend_u0(SIZE(sig_y), cell->parameters.at("\\B_SIGNED").as_bool());
+ sig_a.extend_u0(GetSize(sig_y), cell->parameters.at("\\A_SIGNED").as_bool());
+ sig_b.extend_u0(GetSize(sig_y), cell->parameters.at("\\B_SIGNED").as_bool());
if (cell->type == "$xnor")
{
- RTLIL::SigSpec sig_t = module->addWire(NEW_ID, SIZE(sig_y));
+ RTLIL::SigSpec sig_t = module->addWire(NEW_ID, GetSize(sig_y));
- for (int i = 0; i < SIZE(sig_y); i++) {
+ for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_NOT_");
gate->setPort("\\A", sig_t[i]);
gate->setPort("\\Y", sig_y[i]);
@@ -79,7 +79,7 @@ static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
if (cell->type == "$xnor") gate_type = "$_XOR_";
log_assert(!gate_type.empty());
- for (int i = 0; i < SIZE(sig_y); i++) {
+ for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
gate->setPort("\\A", sig_a[i]);
gate->setPort("\\B", sig_b[i]);
@@ -87,7 +87,7 @@ static void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_reduce(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
@@ -182,7 +182,7 @@ static void logic_reduce(RTLIL::Module *module, RTLIL::SigSpec &sig)
sig = RTLIL::SigSpec(0, 1);
}
-static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
logic_reduce(module, sig_a);
@@ -202,7 +202,7 @@ static void simplemap_lognot(RTLIL::Module *module, RTLIL::Cell *cell)
gate->setPort("\\Y", sig_y);
}
-static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
logic_reduce(module, sig_a);
@@ -231,13 +231,38 @@ static void simplemap_logbin(RTLIL::Module *module, RTLIL::Cell *cell)
gate->setPort("\\Y", sig_y);
}
-static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_eqne(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_a = cell->getPort("\\A");
RTLIL::SigSpec sig_b = cell->getPort("\\B");
RTLIL::SigSpec sig_y = cell->getPort("\\Y");
+ bool is_signed = cell->parameters.at("\\A_SIGNED").as_bool();
+ bool is_ne = cell->type == "$ne" || cell->type == "$nex";
+
+ RTLIL::SigSpec xor_out = module->addWire(NEW_ID, std::max(GetSize(sig_a), GetSize(sig_b)));
+ RTLIL::Cell *xor_cell = module->addXor(NEW_ID, sig_a, sig_b, xor_out, is_signed);
+ simplemap_bitop(module, xor_cell);
+ module->remove(xor_cell);
+
+ RTLIL::SigSpec reduce_out = is_ne ? sig_y : module->addWire(NEW_ID);
+ RTLIL::Cell *reduce_cell = module->addReduceOr(NEW_ID, xor_out, reduce_out);
+ simplemap_reduce(module, reduce_cell);
+ module->remove(reduce_cell);
+
+ if (!is_ne) {
+ RTLIL::Cell *not_cell = module->addLogicNot(NEW_ID, reduce_out, sig_y);
+ simplemap_lognot(module, not_cell);
+ module->remove(not_cell);
+ }
+}
- for (int i = 0; i < SIZE(sig_y); i++) {
+void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ RTLIL::SigSpec sig_a = cell->getPort("\\A");
+ RTLIL::SigSpec sig_b = cell->getPort("\\B");
+ RTLIL::SigSpec sig_y = cell->getPort("\\Y");
+
+ for (int i = 0; i < GetSize(sig_y); i++) {
RTLIL::Cell *gate = module->addCell(NEW_ID, "$_MUX_");
gate->setPort("\\A", sig_a[i]);
gate->setPort("\\B", sig_b[i]);
@@ -246,7 +271,7 @@ static void simplemap_mux(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
{
int offset = cell->parameters.at("\\OFFSET").as_int();
RTLIL::SigSpec sig_a = cell->getPort("\\A");
@@ -254,7 +279,7 @@ static void simplemap_slice(RTLIL::Module *module, RTLIL::Cell *cell)
module->connect(RTLIL::SigSig(sig_y, sig_a.extract(offset, sig_y.size())));
}
-static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
{
RTLIL::SigSpec sig_ab = cell->getPort("\\A");
sig_ab.append(cell->getPort("\\B"));
@@ -262,7 +287,7 @@ static void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell)
module->connect(RTLIL::SigSig(sig_y, sig_ab));
}
-static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at("\\WIDTH").as_int();
char set_pol = cell->parameters.at("\\SET_POLARITY").as_bool() ? 'P' : 'N';
@@ -282,7 +307,7 @@ static void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at("\\WIDTH").as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
@@ -301,7 +326,29 @@ static void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ int width = cell->parameters.at("\\WIDTH").as_int();
+ char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
+ char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
+
+ RTLIL::SigSpec sig_clk = cell->getPort("\\CLK");
+ RTLIL::SigSpec sig_en = cell->getPort("\\EN");
+ RTLIL::SigSpec sig_d = cell->getPort("\\D");
+ RTLIL::SigSpec sig_q = cell->getPort("\\Q");
+
+ std::string gate_type = stringf("$_DFFE_%c%c_", clk_pol, en_pol);
+
+ for (int i = 0; i < width; i++) {
+ RTLIL::Cell *gate = module->addCell(NEW_ID, gate_type);
+ gate->setPort("\\C", sig_clk);
+ gate->setPort("\\E", sig_en);
+ gate->setPort("\\D", sig_d[i]);
+ gate->setPort("\\Q", sig_q[i]);
+ }
+}
+
+void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at("\\WIDTH").as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
@@ -326,7 +373,7 @@ static void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at("\\WIDTH").as_int();
char clk_pol = cell->parameters.at("\\CLK_POLARITY").as_bool() ? 'P' : 'N';
@@ -353,7 +400,7 @@ static void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell)
}
}
-static void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
+void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell)
{
int width = cell->parameters.at("\\WIDTH").as_int();
char en_pol = cell->parameters.at("\\EN_POLARITY").as_bool() ? 'P' : 'N';
@@ -388,16 +435,37 @@ void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTL
mappers["$logic_not"] = simplemap_lognot;
mappers["$logic_and"] = simplemap_logbin;
mappers["$logic_or"] = simplemap_logbin;
+ mappers["$eq"] = simplemap_eqne;
+ mappers["$eqx"] = simplemap_eqne;
+ mappers["$ne"] = simplemap_eqne;
+ mappers["$nex"] = simplemap_eqne;
mappers["$mux"] = simplemap_mux;
mappers["$slice"] = simplemap_slice;
mappers["$concat"] = simplemap_concat;
mappers["$sr"] = simplemap_sr;
mappers["$dff"] = simplemap_dff;
+ mappers["$dffe"] = simplemap_dffe;
mappers["$dffsr"] = simplemap_dffsr;
mappers["$adff"] = simplemap_adff;
mappers["$dlatch"] = simplemap_dlatch;
}
+void simplemap(RTLIL::Module *module, RTLIL::Cell *cell)
+{
+ static std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> mappers;
+ static bool initialized_mappers = false;
+
+ if (!initialized_mappers) {
+ simplemap_get_mappers(mappers);
+ initialized_mappers = true;
+ }
+
+ mappers.at(cell->type)(module, cell);
+}
+
+YOSYS_NAMESPACE_END
+PRIVATE_NAMESPACE_BEGIN
+
struct SimplemapPass : public Pass {
SimplemapPass() : Pass("simplemap", "mapping simple coarse-grain cells") { }
virtual void help()
@@ -440,3 +508,4 @@ struct SimplemapPass : public Pass {
}
} SimplemapPass;
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/simplemap.h b/passes/techmap/simplemap.h
new file mode 100644
index 000000000..dc2a395d3
--- /dev/null
+++ b/passes/techmap/simplemap.h
@@ -0,0 +1,48 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2012 Clifford Wolf <clifford@clifford.at>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#ifndef SIMPLEMAP_H
+#define SIMPLEMAP_H
+
+#include "kernel/yosys.h"
+
+YOSYS_NAMESPACE_BEGIN
+
+extern void simplemap_not(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_pos(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_bitop(RTLIL::Module *module, RTLIL::Cell *cell);
+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_slice(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_concat(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_sr(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_dff(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_dffe(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_dffsr(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_adff(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap_dlatch(RTLIL::Module *module, RTLIL::Cell *cell);
+extern void simplemap(RTLIL::Module *module, RTLIL::Cell *cell);
+
+extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
+
+YOSYS_NAMESPACE_END
+
+#endif
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index ed466faa1..ab748ed74 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -26,15 +26,20 @@
#include <stdio.h>
#include <string.h>
+#include "simplemap.h"
#include "passes/techmap/techmap.inc"
-// see simplemap.cc
-extern void simplemap_get_mappers(std::map<RTLIL::IdString, void(*)(RTLIL::Module*, RTLIL::Cell*)> &mappers);
+YOSYS_NAMESPACE_BEGIN
// see maccmap.cc
extern void maccmap(RTLIL::Module *module, RTLIL::Cell *cell, bool unmap = false);
-static void apply_prefix(std::string prefix, std::string &id)
+YOSYS_NAMESPACE_END
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+void apply_prefix(std::string prefix, std::string &id)
{
if (id[0] == '\\')
id = prefix + "." + id.substr(1);
@@ -42,7 +47,7 @@ static void apply_prefix(std::string prefix, std::string &id)
id = "$techmap" + prefix + "." + id;
}
-static void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
+void apply_prefix(std::string prefix, RTLIL::SigSpec &sig, RTLIL::Module *module)
{
std::vector<RTLIL::SigChunk> chunks = sig;
for (auto &chunk : chunks)
@@ -61,6 +66,11 @@ struct TechmapWorker
std::map<std::pair<RTLIL::IdString, std::map<RTLIL::IdString, RTLIL::Const>>, RTLIL::Module*> techmap_cache;
std::map<RTLIL::Module*, bool> techmap_do_cache;
std::set<RTLIL::Module*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Module>> module_queue;
+ dict<Module*, SigMap> sigmaps;
+
+ pool<IdString> flatten_do_list;
+ pool<IdString> flatten_done_list;
+ pool<Cell*> flatten_keep_list;
struct TechmapWireData {
RTLIL::Wire *wire;
@@ -90,7 +100,7 @@ struct TechmapWorker
std::map<RTLIL::SigBit, std::pair<RTLIL::IdString, int>> connbits_map;
for (auto conn : cell->connections())
- for (int i = 0; i < SIZE(conn.second); i++) {
+ for (int i = 0; i < GetSize(conn.second); i++) {
RTLIL::SigBit bit = sigmap(conn.second[i]);
if (bit.wire == nullptr) {
if (verbose)
@@ -102,8 +112,10 @@ struct TechmapWorker
connbits_map.at(bit).second, log_id(connbits_map.at(bit).first));
constmap_info += stringf("|%s %d %s %d", log_id(conn.first), i,
log_id(connbits_map.at(bit).first), connbits_map.at(bit).second);
- } else
- connbits_map[bit] = std::pair<RTLIL::IdString, int>(conn.first, i);stringf("%s %d", log_id(conn.first), i, bit.data);
+ } else {
+ connbits_map[bit] = std::pair<RTLIL::IdString, int>(conn.first, i);
+ constmap_info += stringf("|%s %d", log_id(conn.first), i);
+ }
}
return stringf("$paramod$constmap:%s%s", sha1(constmap_info).c_str(), tpl->name.c_str());
@@ -122,7 +134,7 @@ struct TechmapWorker
continue;
const char *q = strrchr(p+1, '.');
- p = q ? q : p+1;
+ p = q ? q+1 : p+1;
if (!strncmp(p, "_TECHMAP_", 9)) {
TechmapWireData record;
@@ -146,16 +158,13 @@ struct TechmapWorker
void techmap_module_worker(RTLIL::Design *design, RTLIL::Module *module, RTLIL::Cell *cell, RTLIL::Module *tpl)
{
- if (tpl->memories.size() != 0)
- log_error("Technology map yielded memories -> this is not supported.\n");
-
if (tpl->processes.size() != 0) {
log("Technology map yielded processes:\n");
for (auto &it : tpl->processes)
log(" %s",RTLIL::id2cstr(it.first));
if (autoproc_mode) {
Pass::call_on_module(tpl->design, tpl, "proc");
- log_assert(SIZE(tpl->processes) == 0);
+ log_assert(GetSize(tpl->processes) == 0);
} else
log_error("Technology map yielded processes -> this is not supported (use -autoproc to run 'proc' automatically).\n");
}
@@ -169,6 +178,22 @@ struct TechmapWorker
break;
}
+ dict<IdString, IdString> memory_renames;
+
+ for (auto &it : tpl->memories) {
+ std::string m_name = it.first.str();
+ apply_prefix(cell->name.str(), m_name);
+ RTLIL::Memory *m = new RTLIL::Memory;
+ m->name = m_name;
+ m->width = it.second->width;
+ m->start_offset = it.second->start_offset;
+ m->size = it.second->size;
+ m->attributes = it.second->attributes;
+ module->memories[m->name] = m;
+ memory_renames[it.first] = m->name;
+ design->select(module, m);
+ }
+
std::map<RTLIL::IdString, RTLIL::IdString> positional_ports;
for (auto &it : tpl->wires_) {
@@ -215,6 +240,11 @@ struct TechmapWorker
if (flatten_mode) {
// more conservative approach:
// connect internal and external wires
+ if (sigmaps.count(module) == 0)
+ sigmaps[module].set(module);
+ if (sigmaps.at(module)(c.first).has_const())
+ log_error("Mismatch in directionality for cell port %s.%s.%s: %s <= %s\n",
+ log_id(module), log_id(cell), log_id(it.first), log_signal(c.first), log_signal(c.second));
module->connect(c);
} else {
// approach that yields nicer outputs:
@@ -245,6 +275,12 @@ struct TechmapWorker
apply_prefix(cell->name.str(), it2.second, module);
port_signal_map.apply(it2.second);
}
+
+ if (c->type == "$memrd" || c->type == "$memwr") {
+ IdString memid = c->getParam("\\MEMID").decode_string();
+ log_assert(memory_renames.count(memid));
+ c->setParam("\\MEMID", Const(memory_renames[memid].str()));
+ }
}
for (auto &it : tpl->connections()) {
@@ -272,7 +308,7 @@ struct TechmapWorker
SigMap sigmap(module);
- TopoSort<RTLIL::Cell*> cells;
+ TopoSort<RTLIL::Cell*, RTLIL::IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
std::map<RTLIL::Cell*, std::set<RTLIL::SigBit>> cell_to_inbit;
std::map<RTLIL::SigBit, std::set<RTLIL::Cell*>> outbit_to_cell;
@@ -291,12 +327,28 @@ struct TechmapWorker
continue;
}
+ if (flatten_mode) {
+ bool keepit = cell->get_bool_attribute("\\keep_hierarchy");
+ for (auto &tpl_name : celltypeMap.at(cell_type))
+ if (map->modules_[tpl_name]->get_bool_attribute("\\keep_hierarchy"))
+ keepit = true;
+ if (keepit) {
+ if (!flatten_keep_list[cell]) {
+ log("Keeping %s.%s (found keep_hierarchy property).\n", log_id(module), log_id(cell));
+ flatten_keep_list.insert(cell);
+ }
+ if (!flatten_done_list[cell->type])
+ flatten_do_list.insert(cell->type);
+ continue;
+ }
+ }
+
for (auto &conn : cell->connections())
{
RTLIL::SigSpec sig = sigmap(conn.second);
sig.remove_const();
- if (SIZE(sig) == 0)
+ if (GetSize(sig) == 0)
continue;
for (auto &tpl_name : celltypeMap.at(cell_type)) {
@@ -334,7 +386,7 @@ struct TechmapWorker
{
RTLIL::IdString derived_name = tpl_name;
RTLIL::Module *tpl = map->modules_[tpl_name];
- std::map<RTLIL::IdString, RTLIL::Const> parameters = cell->parameters;
+ std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end());
if (tpl->get_bool_attribute("\\blackbox"))
continue;
@@ -376,7 +428,7 @@ struct TechmapWorker
int port_counter = 1;
for (auto &c : extmapper_cell->connections_) {
- RTLIL::Wire *w = extmapper_module->addWire(c.first, SIZE(c.second));
+ RTLIL::Wire *w = extmapper_module->addWire(c.first, GetSize(c.second));
if (w->name == "\\Y" || w->name == "\\Q")
w->port_output = true;
else
@@ -522,7 +574,7 @@ struct TechmapWorker
tpl = techmap_cache[key];
} else {
if (cell->parameters.size() != 0) {
- derived_name = tpl->derive(map, parameters);
+ derived_name = tpl->derive(map, dict<RTLIL::IdString, RTLIL::Const>(parameters.begin(), parameters.end()));
tpl = map->module(derived_name);
log_continue = true;
}
@@ -623,7 +675,7 @@ struct TechmapWorker
}
for (auto conn : cell->connections())
- for (int i = 0; i < SIZE(conn.second); i++)
+ for (int i = 0; i < GetSize(conn.second); i++)
{
RTLIL::SigBit bit = sigmap(conn.second[i]);
RTLIL::SigBit tplbit(tpl->wire(conn.first), i);
@@ -968,7 +1020,7 @@ struct TechmapPass : public Pass {
Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend);
}
- std::map<RTLIL::IdString, RTLIL::Module*> modules_new;
+ dict<RTLIL::IdString, RTLIL::Module*> modules_new;
for (auto &it : map->modules_) {
if (it.first.substr(0, 2) == "\\$")
it.second->name = it.first.substr(1);
@@ -1027,6 +1079,9 @@ struct FlattenPass : public Pass {
log("pass is very simmilar to the 'techmap' pass. The only difference is that this\n");
log("pass is using the current design as mapping library.\n");
log("\n");
+ log("Cells and/or modules with the 'keep_hiearchy' attribute set will not be\n");
+ log("flattened by this command.\n");
+ log("\n");
}
virtual void execute(std::vector<std::string> args, RTLIL::Design *design)
{
@@ -1039,8 +1094,8 @@ struct FlattenPass : public Pass {
worker.flatten_mode = true;
std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
- for (auto &it : design->modules_)
- celltypeMap[it.first].insert(it.first);
+ for (auto module : design->modules())
+ celltypeMap[module->name].insert(module->name);
RTLIL::Module *top_mod = NULL;
if (design->full_selection())
@@ -1048,26 +1103,40 @@ struct FlattenPass : public Pass {
if (mod->get_bool_attribute("\\top"))
top_mod = mod;
- bool did_something = true;
std::set<RTLIL::Cell*> handled_cells;
- while (did_something) {
- did_something = false;
- if (top_mod != NULL) {
- if (worker.techmap_module(design, top_mod, design, handled_cells, celltypeMap, false))
- did_something = true;
- } else {
- for (auto mod : design->modules())
- if (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false))
- did_something = true;
+ if (top_mod != NULL) {
+ worker.flatten_do_list.insert(top_mod->name);
+ while (!worker.flatten_do_list.empty()) {
+ auto mod = design->module(*worker.flatten_do_list.begin());
+ while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { }
+ worker.flatten_done_list.insert(mod->name);
+ worker.flatten_do_list.erase(mod->name);
}
+ } else {
+ for (auto mod : vector<Module*>(design->modules()))
+ while (worker.techmap_module(design, mod, design, handled_cells, celltypeMap, false)) { }
}
log("No more expansions possible.\n");
- if (top_mod != NULL) {
- std::map<RTLIL::IdString, RTLIL::Module*> new_modules;
- for (auto mod : design->modules())
- if (mod == top_mod || mod->get_bool_attribute("\\blackbox")) {
+ if (top_mod != NULL)
+ {
+ pool<RTLIL::IdString> used_modules, new_used_modules;
+ new_used_modules.insert(top_mod->name);
+ while (!new_used_modules.empty()) {
+ pool<RTLIL::IdString> queue;
+ queue.swap(new_used_modules);
+ for (auto modname : queue)
+ used_modules.insert(modname);
+ for (auto modname : queue)
+ for (auto cell : design->module(modname)->cells())
+ if (design->module(cell->type) && !used_modules[cell->type])
+ new_used_modules.insert(cell->type);
+ }
+
+ dict<RTLIL::IdString, RTLIL::Module*> new_modules;
+ for (auto mod : vector<Module*>(design->modules()))
+ if (used_modules[mod->name] || mod->get_bool_attribute("\\blackbox")) {
new_modules[mod->name] = mod;
} else {
log("Deleting now unused module %s.\n", log_id(mod));
@@ -1080,3 +1149,4 @@ struct FlattenPass : public Pass {
}
} FlattenPass;
+PRIVATE_NAMESPACE_END