aboutsummaryrefslogtreecommitdiffstats
path: root/passes/techmap
diff options
context:
space:
mode:
Diffstat (limited to 'passes/techmap')
-rw-r--r--passes/techmap/Makefile.inc1
-rw-r--r--passes/techmap/abc.cc31
-rw-r--r--passes/techmap/abc9.cc2
-rw-r--r--passes/techmap/dffinit.cc48
-rw-r--r--passes/techmap/dfflegalize.cc105
-rw-r--r--passes/techmap/dffunmap.cc107
-rw-r--r--passes/techmap/shregmap.cc49
-rw-r--r--passes/techmap/techmap.cc51
-rw-r--r--passes/techmap/zinit.cc54
9 files changed, 178 insertions, 270 deletions
diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc
index e3b3d8dea..5a4d84f94 100644
--- a/passes/techmap/Makefile.inc
+++ b/passes/techmap/Makefile.inc
@@ -43,6 +43,7 @@ OBJS += passes/techmap/attrmap.o
OBJS += passes/techmap/zinit.o
OBJS += passes/techmap/dfflegalize.o
OBJS += passes/techmap/dff2dffs.o
+OBJS += passes/techmap/dffunmap.o
OBJS += passes/techmap/flowmap.o
OBJS += passes/techmap/extractinv.o
endif
diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc
index 0a58fdcc0..ce50e9a5b 100644
--- a/passes/techmap/abc.cc
+++ b/passes/techmap/abc.cc
@@ -44,6 +44,7 @@
#include "kernel/register.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"
+#include "kernel/ffinit.h"
#include "kernel/cost.h"
#include "kernel/log.h"
#include <stdlib.h>
@@ -111,7 +112,7 @@ SigMap assign_map;
RTLIL::Module *module;
std::vector<gate_t> signal_list;
std::map<RTLIL::SigBit, int> signal_map;
-std::map<RTLIL::SigBit, RTLIL::State> signal_init;
+FfInitVals initvals;
pool<std::string> enabled_gates;
bool recover_init, cmos_cost;
@@ -133,10 +134,7 @@ int map_signal(RTLIL::SigBit bit, gate_type_t gate_type = G(NONE), int in1 = -1,
gate.in4 = -1;
gate.is_port = false;
gate.bit = bit;
- if (signal_init.count(bit))
- gate.init = signal_init.at(bit);
- else
- gate.init = State::Sx;
+ gate.init = initvals(bit);
signal_list.push_back(gate);
signal_map[bit] = gate.id;
}
@@ -1468,7 +1466,7 @@ struct AbcPass : public Pass {
assign_map.clear();
signal_list.clear();
signal_map.clear();
- signal_init.clear();
+ initvals.clear();
pi_map.clear();
po_map.clear();
@@ -1854,24 +1852,7 @@ struct AbcPass : public Pass {
}
assign_map.set(mod);
- signal_init.clear();
-
- for (Wire *wire : mod->wires())
- if (wire->attributes.count(ID::init)) {
- SigSpec initsig = assign_map(wire);
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- switch (initval[i]) {
- case State::S0:
- signal_init[initsig[i]] = State::S0;
- break;
- case State::S1:
- signal_init[initsig[i]] = State::S1;
- break;
- default:
- break;
- }
- }
+ initvals.set(&assign_map, mod);
if (!dff_mode || !clk_str.empty()) {
abc_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
@@ -2028,7 +2009,7 @@ struct AbcPass : public Pass {
assign_map.clear();
signal_list.clear();
signal_map.clear();
- signal_init.clear();
+ initvals.clear();
pi_map.clear();
po_map.clear();
diff --git a/passes/techmap/abc9.cc b/passes/techmap/abc9.cc
index e99c56d8d..7d017ac40 100644
--- a/passes/techmap/abc9.cc
+++ b/passes/techmap/abc9.cc
@@ -295,7 +295,7 @@ struct Abc9Pass : public ScriptPass
run("proc");
run("wbflip");
run("techmap -wb -map %$abc9 -map +/techmap.v A:abc9_flop");
- run("opt");
+ run("opt -nodffe -nosdff");
if (dff_mode || help_mode) {
if (!help_mode)
active_design->scratchpad_unset("abc9_ops.prep_dff_submod.did_something");
diff --git a/passes/techmap/dffinit.cc b/passes/techmap/dffinit.cc
index c60a901c1..44af043db 100644
--- a/passes/techmap/dffinit.cc
+++ b/passes/techmap/dffinit.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -94,29 +95,10 @@ struct DffinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, State> init_bits;
- pool<SigBit> cleanup_bits;
- pool<SigBit> used_bits;
-
- for (auto wire : module->selected_wires()) {
- if (wire->attributes.count(ID::init)) {
- Const value = wire->attributes.at(ID::init);
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
- if (value[i] != State::Sx)
- init_bits[sigmap(SigBit(wire, i))] = value[i];
- }
- if (wire->port_output)
- for (auto bit : sigmap(wire))
- used_bits.insert(bit);
- }
+ FfInitVals initvals(&sigmap, module);
for (auto cell : module->selected_cells())
{
- for (auto it : cell->connections())
- if (!cell->known() || cell->input(it.first))
- for (auto bit : sigmap(it.second))
- used_bits.insert(bit);
-
if (ff_types.count(cell->type) == 0)
continue;
@@ -131,17 +113,18 @@ struct DffinitPass : public Pass {
if (cell->hasParam(it.second))
value = cell->getParam(it.second);
+ Const initval = initvals(sig);
+ initvals.remove_init(sig);
for (int i = 0; i < GetSize(sig); i++) {
- if (init_bits.count(sig[i]) == 0)
+ if (initval[i] == State::Sx)
continue;
while (GetSize(value.bits) <= i)
value.bits.push_back(State::S0);
- if (noreinit && value.bits[i] != State::Sx && value.bits[i] != init_bits.at(sig[i]))
+ if (noreinit && value.bits[i] != State::Sx && value.bits[i] != initval[i])
log_error("Trying to assign a different init value for %s.%s.%s which technically "
"have a conflicted init value.\n",
log_id(module), log_id(cell), log_id(it.second));
- value.bits[i] = init_bits.at(sig[i]);
- cleanup_bits.insert(sig[i]);
+ value.bits[i] = initval[i];
}
if (highlow_mode && GetSize(value) != 0) {
@@ -161,23 +144,6 @@ struct DffinitPass : public Pass {
}
}
}
-
- for (auto wire : module->selected_wires())
- if (wire->attributes.count(ID::init)) {
- Const &value = wire->attributes.at(ID::init);
- bool do_cleanup = true;
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
- SigBit bit = sigmap(SigBit(wire, i));
- if (cleanup_bits.count(bit) || !used_bits.count(bit))
- value[i] = State::Sx;
- else if (value[i] != State::Sx)
- do_cleanup = false;
- }
- if (do_cleanup) {
- log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
- wire->attributes.erase(ID::init);
- }
- }
}
}
} DffinitPass;
diff --git a/passes/techmap/dfflegalize.cc b/passes/techmap/dfflegalize.cc
index 13ce4f49a..8ad65493f 100644
--- a/passes/techmap/dfflegalize.cc
+++ b/passes/techmap/dfflegalize.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -170,7 +171,7 @@ struct DffLegalizePass : public Pass {
dict<SigBit, int> srst_used;
SigMap sigmap;
- dict<SigBit, std::pair<State,SigBit>> initbits;
+ FfInitVals initvals;
int flip_initmask(int mask) {
int res = mask & INIT_X;
@@ -303,13 +304,7 @@ struct DffLegalizePass : public Pass {
return;
}
- State initval = State::Sx;
- SigBit initbit;
- if (GetSize(sig_q) > 0 && initbits.count(sigmap(sig_q[0]))) {
- const auto &d = initbits.at(sigmap(sig_q[0]));
- initval = d.first;
- initbit = d.second;
- }
+ State initval = initvals(sig_q[0]);
FfInit initmask = INIT_X;
if (initval == State::S0)
@@ -345,12 +340,8 @@ flip_dqi:
sig_d = cell->module->NotGate(NEW_ID, sig_d[0]);
SigBit new_q = SigSpec(cell->module->addWire(NEW_ID))[0];
cell->module->addNotGate(NEW_ID, new_q, sig_q[0]);
- if (initbit.wire) {
- initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
- initbit = new_q;
- new_q.wire->attributes[ID::init] = initval;
- initbits[new_q] = std::make_pair(initval, new_q);
- }
+ initvals.remove_init(sig_q[0]);
+ initvals.set_init(new_q, initval);
sig_q = new_q;
continue;
}
@@ -484,15 +475,12 @@ unmap_enable:
}
log_warning("Emulating mismatched async reset and init with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- if (initbit.wire)
- initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ initvals.remove_init(sig_q[0]);
Wire *adff_q = cell->module->addWire(NEW_ID);
Wire *dff_q = cell->module->addWire(NEW_ID);
Wire *sel_q = cell->module->addWire(NEW_ID);
- dff_q->attributes[ID::init] = initval;
- initbits[SigBit(dff_q, 0)] = std::make_pair(initval, SigBit(dff_q, 0));
- sel_q->attributes[ID::init] = State::S0;
- initbits[SigBit(sel_q, 0)] = std::make_pair(State::S0, SigBit(sel_q, 0));
+ initvals.set_init(SigBit(dff_q, 0), initval);
+ initvals.set_init(SigBit(sel_q, 0), State::S0);
Cell *cell_dff;
Cell *cell_adff;
Cell *cell_sel;
@@ -588,21 +576,15 @@ flip_dqisr:;
}
log_warning("Emulating async set + reset with several FFs and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- if (initbit.wire)
- initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ initvals.remove_init(sig_q[0]);
Wire *adff0_q = cell->module->addWire(NEW_ID);
Wire *adff1_q = cell->module->addWire(NEW_ID);
Wire *sel_q = cell->module->addWire(NEW_ID);
- if (init0) {
- adff0_q->attributes[ID::init] = initval;
- initbits[SigBit(adff0_q, 0)] = std::make_pair(initval, SigBit(adff0_q, 0));
- }
- if (init1) {
- adff1_q->attributes[ID::init] = initval;
- initbits[SigBit(adff1_q, 0)] = std::make_pair(initval, SigBit(adff1_q, 0));
- }
- sel_q->attributes[ID::init] = initsel;
- initbits[SigBit(sel_q, 0)] = std::make_pair(initsel, SigBit(sel_q, 0));
+ if (init0)
+ initvals.set_init(SigBit(adff0_q, 0), initval);
+ if (init1)
+ initvals.set_init(SigBit(adff1_q, 0), initval);
+ initvals.set_init(SigBit(sel_q, 0), initsel);
Cell *cell_adff0;
Cell *cell_adff1;
Cell *cell_sel;
@@ -741,15 +723,12 @@ flip_dqisr:;
// The only hope left is breaking down to adff + dff + dlatch + mux.
log_warning("Emulating mismatched async reset and init with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- if (initbit.wire)
- initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ initvals.remove_init(sig_q[0]);
Wire *adlatch_q = cell->module->addWire(NEW_ID);
Wire *dlatch_q = cell->module->addWire(NEW_ID);
Wire *sel_q = cell->module->addWire(NEW_ID);
- dlatch_q->attributes[ID::init] = initval;
- initbits[SigBit(dlatch_q, 0)] = std::make_pair(initval, SigBit(dlatch_q, 0));
- sel_q->attributes[ID::init] = State::S0;
- initbits[SigBit(sel_q, 0)] = std::make_pair(State::S0, SigBit(sel_q, 0));
+ initvals.set_init(SigBit(dlatch_q, 0), initval);
+ initvals.set_init(SigBit(sel_q, 0), State::S0);
Cell *cell_dlatch;
Cell *cell_adlatch;
Cell *cell_sel;
@@ -797,21 +776,15 @@ flip_dqisr:;
}
log_warning("Emulating async set + reset with several latches and a mux for %s.%s\n", log_id(cell->module->name), log_id(cell->name));
- if (initbit.wire)
- initbit.wire->attributes.at(ID::init)[initbit.offset] = State::Sx;
+ initvals.remove_init(sig_q[0]);
Wire *adlatch0_q = cell->module->addWire(NEW_ID);
Wire *adlatch1_q = cell->module->addWire(NEW_ID);
Wire *sel_q = cell->module->addWire(NEW_ID);
- if (init0) {
- adlatch0_q->attributes[ID::init] = initval;
- initbits[SigBit(adlatch0_q, 0)] = std::make_pair(initval, SigBit(adlatch0_q, 0));
- }
- if (init1) {
- adlatch1_q->attributes[ID::init] = initval;
- initbits[SigBit(adlatch1_q, 0)] = std::make_pair(initval, SigBit(adlatch1_q, 0));
- }
- sel_q->attributes[ID::init] = initsel;
- initbits[SigBit(sel_q, 0)] = std::make_pair(initsel, SigBit(sel_q, 0));
+ if (init0)
+ initvals.set_init(SigBit(adlatch0_q, 0), initval);
+ if (init1)
+ initvals.set_init(SigBit(adlatch1_q, 0), initval);
+ initvals.set_init(SigBit(sel_q, 0), initsel);
Cell *cell_adlatch0;
Cell *cell_adlatch1;
Cell *cell_sel;
@@ -1294,35 +1267,7 @@ unrecognized:
for (auto module : design->selected_modules())
{
sigmap.set(module);
- initbits.clear();
-
- for (auto wire : module->wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
- {
- SigBit bit = wirebits[i];
- State val = initval[i];
-
- if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
- continue;
-
- if (initbits.count(bit)) {
- if (initbits.at(bit).first != val)
- log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
- log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit).first));
- continue;
- }
-
- initbits[bit] = std::make_pair(val,SigBit(wire,i));
- }
- }
+ initvals.set(&sigmap, module);
if (mince || minsrst) {
ce_used.clear();
@@ -1365,7 +1310,7 @@ unrecognized:
}
sigmap.clear();
- initbits.clear();
+ initvals.clear();
ce_used.clear();
srst_used.clear();
}
diff --git a/passes/techmap/dffunmap.cc b/passes/techmap/dffunmap.cc
new file mode 100644
index 000000000..fb107ff75
--- /dev/null
+++ b/passes/techmap/dffunmap.cc
@@ -0,0 +1,107 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2020 Marcelina Koƛcielnicka <mwk@0x04.net>
+ *
+ * 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/ff.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct DffunmapPass : public Pass {
+ DffunmapPass() : Pass("dffunmap", "unmap clock enable and synchronous reset from FFs") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" dffunmap [options] [selection]\n");
+ log("\n");
+ log("This pass transforms FF types with clock enable and/or synchronous reset into\n");
+ log("their base type (with neither clock enable nor sync reset) by emulating the clock\n");
+ log("enable and synchronous reset with multiplexers on the cell input.\n");
+ log("\n");
+ log(" -ce-only\n");
+ log(" unmap only clock enables, leave synchronous resets alone.\n");
+ log("\n");
+ log(" -srst-only\n");
+ log(" unmap only synchronous resets, leave clock enables alone.\n");
+ log("\n");
+ }
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing DFFUNMAP pass (unmap clock enable and synchronous reset from FFs).\n");
+
+ bool ce_only = false;
+ bool srst_only = false;
+
+ size_t argidx;
+ for (argidx = 1; argidx < args.size(); argidx++) {
+ if (args[argidx] == "-ce-only") {
+ ce_only = true;
+ continue;
+ }
+ if (args[argidx] == "-srst-only") {
+ srst_only = true;
+ continue;
+ }
+ break;
+ }
+ extra_args(args, argidx, design);
+
+ if (ce_only && srst_only)
+ log_cmd_error("Options -ce-only and -srst-only are mutually exclusive!\n");
+
+ for (auto mod : design->selected_modules())
+ {
+ SigMap sigmap(mod);
+ FfInitVals initvals(&sigmap, mod);
+
+ for (auto cell : mod->selected_cells())
+ {
+ if (!RTLIL::builtin_ff_cell_types().count(cell->type))
+ continue;
+
+ FfData ff(&initvals, cell);
+ IdString name = cell->name;
+
+ if (!ff.has_clk)
+ continue;
+
+ if (ce_only) {
+ if (!ff.has_en)
+ continue;
+ ff.unmap_ce(mod);
+ } else if (srst_only) {
+ if (!ff.has_srst)
+ continue;
+ ff.unmap_srst(mod);
+ } else {
+ if (!ff.has_en && !ff.has_srst)
+ continue;
+ ff.unmap_ce_srst(mod);
+ }
+
+ mod->remove(cell);
+ ff.emit(mod, name);
+ }
+ }
+ }
+} DffunmapPass;
+
+PRIVATE_NAMESPACE_END
diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc
index 237c261ae..b971068f7 100644
--- a/passes/techmap/shregmap.cc
+++ b/passes/techmap/shregmap.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -100,9 +101,8 @@ struct ShregmapWorker
int dff_count, shreg_count;
pool<Cell*> remove_cells;
- pool<SigBit> remove_init;
- dict<SigBit, bool> sigbit_init;
+ FfInitVals initvals;
dict<SigBit, Cell*> sigbit_chain_next;
dict<SigBit, Cell*> sigbit_chain_prev;
pool<SigBit> sigbit_with_non_chain_users;
@@ -116,16 +116,6 @@ struct ShregmapWorker
for (auto bit : sigmap(wire))
sigbit_with_non_chain_users.insert(bit);
}
-
- if (wire->attributes.count(ID::init)) {
- SigSpec initsig = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- if (initval[i] == State::S0 && !opts.zinit)
- sigbit_init[initsig[i]] = false;
- else if (initval[i] == State::S1)
- sigbit_init[initsig[i]] = true;
- }
}
for (auto cell : module->cells())
@@ -137,8 +127,9 @@ struct ShregmapWorker
SigBit d_bit = sigmap(cell->getPort(d_port).as_bit());
SigBit q_bit = sigmap(cell->getPort(q_port).as_bit());
+ State initval = initvals(q_bit);
- if (opts.init || sigbit_init.count(q_bit) == 0)
+ if (opts.init || initval == State::Sx || (opts.zinit && initval == State::S0))
{
auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
if (!r.second) {
@@ -310,22 +301,17 @@ struct ShregmapWorker
if (opts.init) {
vector<State> initval;
for (int i = depth-1; i >= 0; i--) {
- SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
- if (sigbit_init.count(bit) == 0)
- initval.push_back(State::Sx);
- else if (sigbit_init.at(bit))
- initval.push_back(State::S1);
- else
- initval.push_back(State::S0);
- remove_init.insert(bit);
+ SigBit bit = chain[cursor+i]->getPort(q_port).as_bit();
+ initval.push_back(initvals(bit));
+ initvals.remove_init(bit);
}
first_cell->setParam(ID::INIT, initval);
}
if (opts.zinit)
for (int i = depth-1; i >= 0; i--) {
- SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit());
- remove_init.insert(bit);
+ SigBit bit = chain[cursor+i]->getPort(q_port).as_bit();
+ initvals.remove_init(bit);
}
if (opts.params)
@@ -364,22 +350,6 @@ struct ShregmapWorker
for (auto cell : remove_cells)
module->remove(cell);
- for (auto wire : module->wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec initsig = sigmap(wire);
- Const &initval = wire->attributes.at(ID::init);
-
- for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++)
- if (remove_init.count(initsig[i]))
- initval[i] = State::Sx;
-
- if (SigSpec(initval).is_fully_undef())
- wire->attributes.erase(ID::init);
- }
-
remove_cells.clear();
sigbit_chain_next.clear();
sigbit_chain_prev.clear();
@@ -389,6 +359,7 @@ struct ShregmapWorker
ShregmapWorker(Module *module, const ShregmapOptions &opts) :
module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
{
+ initvals.set(&sigmap, module);
make_sigbit_chain_next_prev();
find_chain_start_cells();
diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc
index f98d1564a..c22ae8ef0 100644
--- a/passes/techmap/techmap.cc
+++ b/passes/techmap/techmap.cc
@@ -20,6 +20,7 @@
#include "kernel/yosys.h"
#include "kernel/utils.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
#include "libs/sha1/sha1.h"
#include <stdlib.h>
@@ -426,18 +427,7 @@ struct TechmapWorker
LogMakeDebugHdl mkdebug;
SigMap sigmap(module);
-
- dict<SigBit, State> init_bits;
- pool<SigBit> remove_init_bits;
-
- for (auto wire : module->wires()) {
- if (wire->attributes.count(ID::init)) {
- Const value = wire->attributes.at(ID::init);
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++)
- if (value[i] != State::Sx)
- init_bits[sigmap(SigBit(wire, i))] = value[i];
- }
- }
+ FfInitVals initvals(&sigmap, module);
TopoSort<RTLIL::Cell*, IdString::compare_ptr_by_name<RTLIL::Cell>> cells;
dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_to_inbit;
@@ -643,6 +633,8 @@ struct TechmapWorker
if (tpl->avail_parameters.count(ID::_TECHMAP_CELLTYPE_) != 0)
parameters.emplace(ID::_TECHMAP_CELLTYPE_, RTLIL::unescape_id(cell->type));
+ if (tpl->avail_parameters.count(ID::_TECHMAP_CELLNAME_) != 0)
+ parameters.emplace(ID::_TECHMAP_CELLNAME_, RTLIL::unescape_id(cell->name));
for (auto &conn : cell->connections()) {
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_CONSTMSK_%s_", log_id(conn.first))) != 0) {
@@ -659,15 +651,7 @@ struct TechmapWorker
parameters.emplace(stringf("\\_TECHMAP_CONSTVAL_%s_", log_id(conn.first)), RTLIL::SigSpec(v).as_const());
}
if (tpl->avail_parameters.count(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first))) != 0) {
- auto sig = sigmap(conn.second);
- RTLIL::Const value(State::Sx, sig.size());
- for (int i = 0; i < sig.size(); i++) {
- auto it = init_bits.find(sig[i]);
- if (it != init_bits.end()) {
- value[i] = it->second;
- }
- }
- parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), value);
+ parameters.emplace(stringf("\\_TECHMAP_WIREINIT_%s_", log_id(conn.first)), initvals(conn.second));
}
}
@@ -912,7 +896,7 @@ struct TechmapWorker
auto sig = sigmap(it->second);
for (int i = 0; i < sig.size(); i++)
if (val[i] == State::S1)
- remove_init_bits.insert(sig[i]);
+ initvals.remove_init(sig[i]);
}
}
}
@@ -961,25 +945,6 @@ struct TechmapWorker
handled_cells.insert(cell);
}
- if (!remove_init_bits.empty()) {
- for (auto wire : module->wires())
- if (wire->attributes.count(ID::init)) {
- Const &value = wire->attributes.at(ID::init);
- bool do_cleanup = true;
- for (int i = 0; i < min(GetSize(value), GetSize(wire)); i++) {
- SigBit bit = sigmap(SigBit(wire, i));
- if (remove_init_bits.count(bit))
- value[i] = State::Sx;
- else if (value[i] != State::Sx)
- do_cleanup = false;
- }
- if (do_cleanup) {
- log("Removing init attribute from wire %s.%s.\n", log_id(module), log_id(wire));
- wire->attributes.erase(ID::init);
- }
- }
- }
-
if (log_continue) {
log_header(design, "Continuing TECHMAP pass.\n");
log_continue = false;
@@ -1111,6 +1076,10 @@ struct TechmapPass : public Pass {
log(" When a parameter with this name exists, it will be set to the type name\n");
log(" of the cell that matches the module.\n");
log("\n");
+ log(" _TECHMAP_CELLNAME_\n");
+ log(" When a parameter with this name exists, it will be set to the name\n");
+ log(" of the cell that matches the module.\n");
+ log("\n");
log(" _TECHMAP_CONSTMSK_<port-name>_\n");
log(" _TECHMAP_CONSTVAL_<port-name>_\n");
log(" When this pair of parameters is available in a module for a port, then\n");
diff --git a/passes/techmap/zinit.cc b/passes/techmap/zinit.cc
index cc0b26bcc..e3b4ae573 100644
--- a/passes/techmap/zinit.cc
+++ b/passes/techmap/zinit.cc
@@ -19,6 +19,7 @@
#include "kernel/yosys.h"
#include "kernel/sigtools.h"
+#include "kernel/ffinit.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
@@ -57,35 +58,7 @@ struct ZinitPass : public Pass {
for (auto module : design->selected_modules())
{
SigMap sigmap(module);
- dict<SigBit, std::pair<State,SigBit>> initbits;
-
- for (auto wire : module->selected_wires())
- {
- if (wire->attributes.count(ID::init) == 0)
- continue;
-
- SigSpec wirebits = sigmap(wire);
- Const initval = wire->attributes.at(ID::init);
-
- for (int i = 0; i < GetSize(wirebits) && i < GetSize(initval); i++)
- {
- SigBit bit = wirebits[i];
- State val = initval[i];
-
- if (val != State::S0 && val != State::S1 && bit.wire != nullptr)
- continue;
-
- if (initbits.count(bit)) {
- if (initbits.at(bit).first != val)
- log_error("Conflicting init values for signal %s (%s = %s != %s).\n",
- log_signal(bit), log_signal(SigBit(wire, i)),
- log_signal(val), log_signal(initbits.at(bit).first));
- continue;
- }
-
- initbits[bit] = std::make_pair(val,SigBit(wire,i));
- }
- }
+ FfInitVals initvals(&sigmap, module);
pool<IdString> dff_types = {
// FIXME: It would appear that supporting
@@ -127,33 +100,28 @@ struct ZinitPass : public Pass {
if (GetSize(sig_d) < 1 || GetSize(sig_q) < 1)
continue;
- Const initval;
+ Const initval = initvals(sig_q);
+ Const newval = initval;
+ initvals.remove_init(sig_q);
- for (int i = 0; i < GetSize(sig_q); i++) {
- if (initbits.count(sig_q[i])) {
- const auto &d = initbits.at(sig_q[i]);
- initval.bits.push_back(d.first);
- const auto &b = d.second;
- b.wire->attributes.at(ID::init)[b.offset] = State::Sx;
- } else
- initval.bits.push_back(all_mode ? State::S0 : State::Sx);
- }
-
- Wire *initwire = module->addWire(NEW_ID, GetSize(initval));
- initwire->attributes[ID::init] = initval;
+ Wire *initwire = module->addWire(NEW_ID, GetSize(sig_q));
for (int i = 0; i < GetSize(initwire); i++)
if (initval[i] == State::S1)
{
sig_d[i] = module->NotGate(NEW_ID, sig_d[i]);
module->addNotGate(NEW_ID, SigSpec(initwire, i), sig_q[i]);
- initwire->attributes[ID::init][i] = State::S0;
+ newval[i] = State::S0;
}
else
{
module->connect(sig_q[i], SigSpec(initwire, i));
+ if (all_mode)
+ newval[i] = State::S0;
}
+ initvals.set_init(initwire, newval);
+
log("FF init value for cell %s (%s): %s = %s\n", log_id(cell), log_id(cell->type),
log_signal(sig_q), log_signal(initval));