aboutsummaryrefslogtreecommitdiffstats
path: root/passes/memory/memory_dff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'passes/memory/memory_dff.cc')
-rw-r--r--passes/memory/memory_dff.cc146
1 files changed, 19 insertions, 127 deletions
diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc
index 4adcb462e..83c9d7631 100644
--- a/passes/memory/memory_dff.cc
+++ b/passes/memory/memory_dff.cc
@@ -33,8 +33,6 @@ struct MemoryDffWorker
vector<Cell*> dff_cells;
dict<SigBit, SigBit> invbits;
dict<SigBit, int> sigbit_users_count;
- dict<SigSpec, Cell*> mux_cells_a, mux_cells_b;
- pool<Cell*> forward_merged_dffs, candidate_dffs;
FfInitVals initvals;
MemoryDffWorker(Module *module) : module(module), sigmap(module)
@@ -114,7 +112,6 @@ struct MemoryDffWorker
bit = d;
clk = this_clk;
clk_polarity = this_clk_polarity;
- candidate_dffs.insert(cell);
goto replaced_this_bit;
}
@@ -136,8 +133,6 @@ struct MemoryDffWorker
for (auto cell : dff_cells)
{
- if (forward_merged_dffs.count(cell))
- continue;
if (!cell->type.in(ID($dff), ID($dffe)))
continue;
@@ -187,7 +182,6 @@ struct MemoryDffWorker
clk_polarity = this_clk_polarity;
en = this_en;
en_polarity = this_en_polarity;
- candidate_dffs.insert(cell);
goto replaced_this_bit;
}
@@ -198,51 +192,6 @@ struct MemoryDffWorker
return true;
}
- void handle_wr_cell(RTLIL::Cell *cell)
- {
- log("Checking cell `%s' in module `%s': ", cell->name.c_str(), module->name.c_str());
-
- RTLIL::SigSpec clk = RTLIL::SigSpec(RTLIL::State::Sx);
- bool clk_polarity = 0;
- candidate_dffs.clear();
-
- RTLIL::SigSpec sig_addr = cell->getPort(ID::ADDR);
- if (!find_sig_before_dff(sig_addr, clk, clk_polarity)) {
- log("no (compatible) $dff for address input found.\n");
- return;
- }
-
- RTLIL::SigSpec sig_data = cell->getPort(ID::DATA);
- if (!find_sig_before_dff(sig_data, clk, clk_polarity)) {
- log("no (compatible) $dff for data input found.\n");
- return;
- }
-
- RTLIL::SigSpec sig_en = cell->getPort(ID::EN);
- if (!find_sig_before_dff(sig_en, clk, clk_polarity)) {
- log("no (compatible) $dff for enable input found.\n");
- return;
- }
-
- if (clk != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- for (auto cell : candidate_dffs)
- forward_merged_dffs.insert(cell);
-
- cell->setPort(ID::CLK, clk);
- cell->setPort(ID::ADDR, sig_addr);
- cell->setPort(ID::DATA, sig_data);
- cell->setPort(ID::EN, sig_en);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
-
- log("merged $dff to cell.\n");
- return;
- }
-
- log("no (compatible) $dff found.\n");
- }
-
void disconnect_dff(RTLIL::SigSpec sig)
{
sigmap.apply(sig);
@@ -276,58 +225,19 @@ struct MemoryDffWorker
if (sigbit_users_count[bit] > 1)
goto skip_ff_after_read_merging;
- if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data))
+ if (find_sig_after_dffe(sig_data, clk_data, clk_polarity, en_data, en_polarity) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
{
- RTLIL::SigSpec en;
- std::vector<RTLIL::SigSpec> check_q;
-
- do {
- bool enable_invert = mux_cells_a.count(sig_data) != 0;
- Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data);
- check_q.push_back(sigmap(mux->getPort(enable_invert ? ID::B : ID::A)));
- sig_data = sigmap(mux->getPort(ID::Y));
- en.append(enable_invert ? module->LogicNot(NEW_ID, mux->getPort(ID::S)) : mux->getPort(ID::S));
- } while (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data));
-
- for (auto bit : sig_data)
- if (sigbit_users_count[bit] > 1)
- goto skip_ff_after_read_merging;
-
- if (find_sig_after_dffe(sig_data, clk_data, clk_polarity, en_data, en_polarity) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) &&
- std::all_of(check_q.begin(), check_q.end(), [&](const SigSpec &cq) {return cq == sig_data; }))
- {
- if (en_data != State::S1 || !en_polarity) {
- if (!en_polarity)
- en_data = module->LogicNot(NEW_ID, en_data);
- en.append(en_data);
- }
- disconnect_dff(sig_data);
- cell->setPort(ID::CLK, clk_data);
- cell->setPort(ID::EN, en.size() > 1 ? module->ReduceAnd(NEW_ID, en) : en);
- cell->setPort(ID::DATA, sig_data);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
- cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
- log("merged data $dff with rd enable to cell.\n");
- return;
- }
- }
- else
- {
- if (find_sig_after_dffe(sig_data, clk_data, clk_polarity, en_data, en_polarity) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx))
- {
- if (!en_polarity)
- en_data = module->LogicNot(NEW_ID, en_data);
- disconnect_dff(sig_data);
- cell->setPort(ID::CLK, clk_data);
- cell->setPort(ID::EN, en_data);
- cell->setPort(ID::DATA, sig_data);
- cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
- cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
- cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
- log("merged data $dff to cell.\n");
- return;
- }
+ if (!en_polarity)
+ en_data = module->LogicNot(NEW_ID, en_data);
+ disconnect_dff(sig_data);
+ cell->setPort(ID::CLK, clk_data);
+ cell->setPort(ID::EN, en_data);
+ cell->setPort(ID::DATA, sig_data);
+ cell->parameters[ID::CLK_ENABLE] = RTLIL::Const(1);
+ cell->parameters[ID::CLK_POLARITY] = RTLIL::Const(clk_polarity);
+ cell->parameters[ID::TRANSPARENT] = RTLIL::Const(0);
+ log("merged data $dff to cell.\n");
+ return;
}
skip_ff_after_read_merging:;
@@ -349,7 +259,7 @@ struct MemoryDffWorker
log("no (compatible) $dff found.\n");
}
- void run(bool flag_wr_only)
+ void run()
{
for (auto wire : module->wires()) {
if (wire->port_output)
@@ -360,10 +270,6 @@ struct MemoryDffWorker
for (auto cell : module->cells()) {
if (cell->type.in(ID($dff), ID($dffe), ID($sdff), ID($sdffe), ID($sdffce)))
dff_cells.push_back(cell);
- if (cell->type == ID($mux)) {
- mux_cells_a[sigmap(cell->getPort(ID::A))] = cell;
- mux_cells_b[sigmap(cell->getPort(ID::B))] = cell;
- }
if (cell->type.in(ID($not), ID($_NOT_)) || (cell->type == ID($logic_not) && GetSize(cell->getPort(ID::A)) == 1)) {
SigSpec sig_a = cell->getPort(ID::A);
SigSpec sig_y = cell->getPort(ID::Y);
@@ -381,51 +287,37 @@ struct MemoryDffWorker
}
for (auto cell : module->selected_cells())
- if (cell->type == ID($memwr) && !cell->parameters[ID::CLK_ENABLE].as_bool())
- handle_wr_cell(cell);
-
- if (!flag_wr_only)
- for (auto cell : module->selected_cells())
- if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool())
- handle_rd_cell(cell);
+ if (cell->type == ID($memrd) && !cell->parameters[ID::CLK_ENABLE].as_bool())
+ handle_rd_cell(cell);
}
};
struct MemoryDffPass : public Pass {
- MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memories") { }
+ MemoryDffPass() : Pass("memory_dff", "merge input/output DFFs into memory read ports") { }
void help() override
{
// |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
log("\n");
log(" memory_dff [options] [selection]\n");
log("\n");
- log("This pass detects DFFs at memory ports and merges them into the memory port.\n");
+ log("This pass detects DFFs at memory read ports and merges them into the memory port.\n");
log("I.e. it consumes an asynchronous memory port and the flip-flops at its\n");
log("interface and yields a synchronous memory port.\n");
log("\n");
- log(" -nordfff\n");
- log(" do not merge registers on read ports\n");
- log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
- bool flag_wr_only = false;
-
- log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n");
+ log_header(design, "Executing MEMORY_DFF pass (merging $dff cells to $memrd).\n");
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
- if (args[argidx] == "-nordff" || args[argidx] == "-wr_only") {
- flag_wr_only = true;
- continue;
- }
break;
}
extra_args(args, argidx, design);
for (auto mod : design->selected_modules()) {
MemoryDffWorker worker(mod);
- worker.run(flag_wr_only);
+ worker.run();
}
}
} MemoryDffPass;