From a6750b375301f2c2ebb51a2496cdf2c820b2546b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 3 Feb 2014 13:01:45 +0100 Subject: Added TRANSPARENT parameter to $memrd (and RD_TRANSPARENT to $mem) --- passes/memory/memory_collect.cc | 9 ++++-- passes/memory/memory_dff.cc | 67 ++++++++++++++++++++++---------------- passes/memory/memory_map.cc | 71 +++++++++++++++++++++-------------------- passes/memory/memory_unpack.cc | 1 + 4 files changed, 84 insertions(+), 64 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index ad4df228..40504d78 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -54,6 +54,7 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) RTLIL::SigSpec sig_rd_clk; RTLIL::SigSpec sig_rd_clk_enable; RTLIL::SigSpec sig_rd_clk_polarity; + RTLIL::SigSpec sig_rd_transparent; RTLIL::SigSpec sig_rd_addr; RTLIL::SigSpec sig_rd_data; @@ -105,18 +106,21 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) RTLIL::SigSpec clk = cell->connections["\\CLK"]; RTLIL::SigSpec clk_enable = RTLIL::SigSpec(cell->parameters["\\CLK_ENABLE"]); RTLIL::SigSpec clk_polarity = RTLIL::SigSpec(cell->parameters["\\CLK_POLARITY"]); + RTLIL::SigSpec transparent = RTLIL::SigSpec(cell->parameters["\\TRANSPARENT"]); RTLIL::SigSpec addr = cell->connections["\\ADDR"]; RTLIL::SigSpec data = cell->connections["\\DATA"]; clk.extend(1, false); clk_enable.extend(1, false); clk_polarity.extend(1, false); + transparent.extend(1, false); addr.extend(addr_bits, false); data.extend(memory->width, false); sig_rd_clk.append(clk); sig_rd_clk_enable.append(clk_enable); sig_rd_clk_polarity.append(clk_polarity); + sig_rd_transparent.append(transparent); sig_rd_addr.append(addr); sig_rd_data.append(data); } @@ -147,7 +151,7 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) mem->parameters["\\WR_PORTS"] = RTLIL::Const(wr_ports); mem->parameters["\\WR_CLK_ENABLE"] = wr_ports ? sig_wr_clk_enable.chunks[0].data : RTLIL::Const(0, 0); - mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_enable.chunks[0].data : RTLIL::Const(0, 0); + mem->parameters["\\WR_CLK_POLARITY"] = wr_ports ? sig_wr_clk_polarity.chunks[0].data : RTLIL::Const(0, 0); mem->connections["\\WR_CLK"] = sig_wr_clk; mem->connections["\\WR_ADDR"] = sig_wr_addr; @@ -165,7 +169,8 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Memory *memory) mem->parameters["\\RD_PORTS"] = RTLIL::Const(rd_ports); mem->parameters["\\RD_CLK_ENABLE"] = rd_ports ? sig_rd_clk_enable.chunks[0].data : RTLIL::Const(0, 0); - mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_enable.chunks[0].data : RTLIL::Const(0, 0); + mem->parameters["\\RD_CLK_POLARITY"] = rd_ports ? sig_rd_clk_polarity.chunks[0].data : RTLIL::Const(0, 0); + mem->parameters["\\RD_TRANSPARENT"] = rd_ports ? sig_rd_transparent.chunks[0].data : RTLIL::Const(0, 0); mem->connections["\\RD_CLK"] = sig_rd_clk; mem->connections["\\RD_ADDR"] = sig_rd_addr; diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 6ba9bf23..2502a8b6 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -113,14 +113,6 @@ static void handle_wr_cell(RTLIL::Module *module, RTLIL::Cell *cell) } } -#if 1 -static void handle_rd_cell(RTLIL::Module*, RTLIL::Cell*) -{ - // merging dffs into read ports isn't neccessary for memory_map. - // we'd loose the information if the register is on the address or - // data port and wouldn't get any benefits. -} -#else static void disconnect_dff(RTLIL::Module *module, RTLIL::SigSpec sig) { normalize_sig(module, sig); @@ -149,43 +141,46 @@ static void handle_rd_cell(RTLIL::Module *module, RTLIL::Cell *cell) bool clk_polarity = 0; - RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx); - RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"]; - if (find_sig_before_dff(module, sig_addr, clk_addr, clk_polarity)) - { - cell->connections["\\CLK"] = clk_addr; - cell->connections["\\ADDR"] = sig_addr; - cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); - cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); - log("merged address $dff to cell.\n"); - return; - } - RTLIL::SigSpec clk_data = RTLIL::SigSpec(RTLIL::State::Sx); RTLIL::SigSpec sig_data = cell->connections["\\DATA"]; - if (find_sig_before_dff(module, sig_data, clk_data, clk_polarity, true)) + if (find_sig_before_dff(module, sig_data, clk_data, clk_polarity, true) && + clk_data != RTLIL::SigSpec(RTLIL::State::Sx)) { disconnect_dff(module, sig_data); cell->connections["\\CLK"] = clk_data; cell->connections["\\DATA"] = sig_data; cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(0); log("merged data $dff to cell.\n"); return; } + RTLIL::SigSpec clk_addr = RTLIL::SigSpec(RTLIL::State::Sx); + RTLIL::SigSpec sig_addr = cell->connections["\\ADDR"]; + if (find_sig_before_dff(module, sig_addr, clk_addr, clk_polarity) && + clk_addr != RTLIL::SigSpec(RTLIL::State::Sx)) + { + cell->connections["\\CLK"] = clk_addr; + cell->connections["\\ADDR"] = sig_addr; + cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); + cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); + cell->parameters["\\TRANSPARENT"] = RTLIL::Const(1); + log("merged address $dff to cell.\n"); + return; + } + log("no (compatible) $dff found.\n"); } -#endif -static void handle_module(RTLIL::Design *design, RTLIL::Module *module) +static void handle_module(RTLIL::Design *design, RTLIL::Module *module, bool flag_wr_only) { for (auto &cell_it : module->cells) { if (!design->selected(module, cell_it.second)) continue; if (cell_it.second->type == "$memwr" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool()) handle_wr_cell(module, cell_it.second); - if (cell_it.second->type == "$memrd" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool()) + if (!flag_wr_only && cell_it.second->type == "$memrd" && !cell_it.second->parameters["\\CLK_ENABLE"].as_bool()) handle_rd_cell(module, cell_it.second); } } @@ -196,19 +191,35 @@ struct MemoryDffPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" memory_dff [selection]\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("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(" -wr_only\n"); + log(" do not merge registers on read ports\n"); + log("\n"); } - virtual void execute(std::vector args, RTLIL::Design *design) { + virtual void execute(std::vector args, RTLIL::Design *design) + { + bool flag_wr_only = false; + log_header("Executing MEMORY_DFF pass (merging $dff cells to $memrd and $memwr).\n"); - extra_args(args, 1, design); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-wr_only") { + flag_wr_only = true; + continue; + } + break; + } + extra_args(args, argidx, design); + for (auto &mod_it : design->modules) if (design->selected(mod_it.second)) - handle_module(design, mod_it.second); + handle_module(design, mod_it.second, flag_wr_only); } } MemoryDffPass; diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 9f2b6994..e0e3802d 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -162,44 +162,47 @@ static void handle_cell(RTLIL::Module *module, RTLIL::Cell *cell) if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1) { -#if 1 - RTLIL::Cell *c = new RTLIL::Cell; - c->name = genid(cell->name, "$rdreg", i); - c->type = "$dff"; - c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits); - c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); - c->connections["\\CLK"] = cell->connections["\\RD_CLK"].extract(i, 1); - c->connections["\\D"] = rd_addr; - module->cells[c->name] = c; - count_dff++; + if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1) + { + RTLIL::Cell *c = new RTLIL::Cell; + c->name = genid(cell->name, "$rdreg", i); + c->type = "$dff"; + c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits); + c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + c->connections["\\CLK"] = cell->connections["\\RD_CLK"].extract(i, 1); + c->connections["\\D"] = rd_addr; + module->cells[c->name] = c; + count_dff++; - RTLIL::Wire *w = new RTLIL::Wire; - w->name = genid(cell->name, "$rdreg", i, "$q"); - w->width = mem_abits; - module->wires[w->name] = w; + RTLIL::Wire *w = new RTLIL::Wire; + w->name = genid(cell->name, "$rdreg", i, "$q"); + w->width = mem_abits; + module->wires[w->name] = w; - c->connections["\\Q"] = RTLIL::SigSpec(w); - rd_addr = RTLIL::SigSpec(w); -#else - RTLIL::Cell *c = new RTLIL::Cell; - c->name = genid(cell->name, "$rdreg", i); - c->type = "$dff"; - c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; - c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); - c->connections["\\CLK"] = cell->connections["\\RD_CLK"].extract(i, 1); - c->connections["\\Q"] = rd_signals.back(); - module->cells[c->name] = c; - count_dff++; + c->connections["\\Q"] = RTLIL::SigSpec(w); + rd_addr = RTLIL::SigSpec(w); + } + else + { + RTLIL::Cell *c = new RTLIL::Cell; + c->name = genid(cell->name, "$rdreg", i); + c->type = "$dff"; + c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; + c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + c->connections["\\CLK"] = cell->connections["\\RD_CLK"].extract(i, 1); + c->connections["\\Q"] = rd_signals.back(); + module->cells[c->name] = c; + count_dff++; - RTLIL::Wire *w = new RTLIL::Wire; - w->name = genid(cell->name, "$rdreg", i, "$d"); - w->width = mem_width; - module->wires[w->name] = w; + RTLIL::Wire *w = new RTLIL::Wire; + w->name = genid(cell->name, "$rdreg", i, "$d"); + w->width = mem_width; + module->wires[w->name] = w; - rd_signals.clear(); - rd_signals.push_back(RTLIL::SigSpec(w)); - c->connections["\\D"] = rd_signals.back(); -#endif + rd_signals.clear(); + rd_signals.push_back(RTLIL::SigSpec(w)); + c->connections["\\D"] = rd_signals.back(); + } } for (int j = 0; j < mem_abits; j++) diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc index 060d8e67..782c0cd7 100644 --- a/passes/memory/memory_unpack.cc +++ b/passes/memory/memory_unpack.cc @@ -55,6 +55,7 @@ static void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) cell->parameters["\\WIDTH"] = memory->parameters.at("\\WIDTH"); cell->parameters["\\CLK_ENABLE"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_ENABLE")).extract(i, 1).as_const(); cell->parameters["\\CLK_POLARITY"] = RTLIL::SigSpec(memory->parameters.at("\\RD_CLK_POLARITY")).extract(i, 1).as_const(); + cell->parameters["\\TRANSPARENT"] = RTLIL::SigSpec(memory->parameters.at("\\RD_TRANSPARENT")).extract(i, 1).as_const(); cell->connections["\\CLK"] = memory->connections.at("\\RD_CLK").extract(i, 1); cell->connections["\\ADDR"] = memory->connections.at("\\RD_ADDR").extract(i*abits, abits); cell->connections["\\DATA"] = memory->connections.at("\\RD_DATA").extract(i*mem->width, mem->width); -- cgit v1.2.3