From 924d9d6e86a5e9a2294479345daac1c03d78008a Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 25 Sep 2015 12:23:11 +0200 Subject: Added read-enable to memory model --- passes/memory/memory_bram.cc | 20 +++++++++++----- passes/memory/memory_collect.cc | 37 +++++++++++++++++------------ passes/memory/memory_dff.cc | 52 ++++++++++++++++++++++++++++++++++------- passes/memory/memory_map.cc | 33 ++++++++++++++++---------- passes/memory/memory_unpack.cc | 1 + 5 files changed, 101 insertions(+), 42 deletions(-) (limited to 'passes') diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index f638b5bb..3e83a6d9 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -112,15 +112,15 @@ struct rules_t if (ports[i] != other.ports[i]) log_error("Bram %s variants %d and %d have different number of %c-ports.\n", log_id(name), variant, other.variant, 'A'+i); if (wrmode[i] != other.wrmode[i]) - variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[1]; + variant_params[stringf("\\CFG_WRMODE_%c", 'A' + i)] = wrmode[i]; if (enable[i] != other.enable[i]) - variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[1]; + variant_params[stringf("\\CFG_ENABLE_%c", 'A' + i)] = enable[i]; if (transp[i] != other.transp[i]) - variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[1]; + variant_params[stringf("\\CFG_TRANSP_%c", 'A' + i)] = transp[i]; if (clocks[i] != other.clocks[i]) - variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[1]; + variant_params[stringf("\\CFG_CLOCKS_%c", 'A' + i)] = clocks[i]; if (clkpol[i] != other.clkpol[i]) - variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[1]; + variant_params[stringf("\\CFG_CLKPOL_%c", 'A' + i)] = clkpol[i]; } } }; @@ -429,6 +429,7 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram, rd_clkpol.extend_u0(rd_ports); rd_transp.extend_u0(rd_ports); + SigSpec rd_en = cell->getPort("\\RD_EN"); SigSpec rd_clk = cell->getPort("\\RD_CLK"); SigSpec rd_data = cell->getPort("\\RD_DATA"); SigSpec rd_addr = cell->getPort("\\RD_ADDR"); @@ -688,6 +689,10 @@ grow_read_ports:; log(" Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); goto skip_bram_rport; } + if (rd_en[cell_port_i] != State::S1 && pi.enable == 0) { + log(" Bram port %c%d.%d has no read enable input.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1); + goto skip_bram_rport; + } skip_bram_rport_clkcheck: if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) { if (match.make_transp && wr_ports <= 1) { @@ -713,6 +718,7 @@ grow_read_ports:; clock_polarities[pi.clkpol] = clkdom.second; read_transp[pi.transp] = transp; pi.sig_clock = clkdom.first; + pi.sig_en = rd_en[cell_port_i]; pi.effective_clkpol = clkdom.second; } @@ -886,6 +892,8 @@ grow_read_ports:; if (pi.make_outreg) { SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits); + if (!pi.sig_en.empty()) + bram_dout = module->Mux(NEW_ID, bram_dout_q, bram_dout, pi.sig_en); module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol); bram_dout = bram_dout_q; } @@ -1126,7 +1134,7 @@ struct MemoryBramPass : public Pass { log(" groups 2 # number of port groups\n"); log(" ports 1 1 # number of ports in each group\n"); log(" wrmode 1 0 # set to '1' if this groups is write ports\n"); - log(" enable 4 0 # number of enable bits (for write ports)\n"); + log(" enable 4 1 # number of enable bits\n"); log(" transp 0 2 # transparent (for read ports)\n"); log(" clocks 1 2 # clock configuration\n"); log(" clkpol 2 2 # clock polarity configuration\n"); diff --git a/passes/memory/memory_collect.cc b/passes/memory/memory_collect.cc index 91b5759e..abd4b124 100644 --- a/passes/memory/memory_collect.cc +++ b/passes/memory/memory_collect.cc @@ -57,6 +57,7 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) SigSpec sig_rd_transparent; SigSpec sig_rd_addr; SigSpec sig_rd_data; + SigSpec sig_rd_en; std::vector memcells; @@ -139,22 +140,27 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) SigSpec transparent = SigSpec(cell->parameters["\\TRANSPARENT"]); SigSpec addr = sigmap(cell->getPort("\\ADDR")); SigSpec data = sigmap(cell->getPort("\\DATA")); + SigSpec en = sigmap(cell->getPort("\\EN")); - clk.extend_u0(1, false); - clk_enable.extend_u0(1, false); - clk_polarity.extend_u0(1, false); - transparent.extend_u0(1, false); - addr.extend_u0(addr_bits, false); - data.extend_u0(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); - - rd_ports++; + if (!en.is_fully_zero()) + { + clk.extend_u0(1, false); + clk_enable.extend_u0(1, false); + clk_polarity.extend_u0(1, false); + transparent.extend_u0(1, false); + addr.extend_u0(addr_bits, false); + data.extend_u0(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); + sig_rd_en.append(en); + + rd_ports++; + } continue; } } @@ -203,6 +209,7 @@ Cell *handle_memory(Module *module, RTLIL::Memory *memory) mem->setPort("\\RD_CLK", sig_rd_clk); mem->setPort("\\RD_ADDR", sig_rd_addr); mem->setPort("\\RD_DATA", sig_rd_data); + mem->setPort("\\RD_EN", sig_rd_en); for (auto c : memcells) module->remove(c); diff --git a/passes/memory/memory_dff.cc b/passes/memory/memory_dff.cc index 5584f27c..3373369f 100644 --- a/passes/memory/memory_dff.cc +++ b/passes/memory/memory_dff.cc @@ -31,6 +31,7 @@ struct MemoryDffWorker vector dff_cells; dict invbits; dict sigbit_users_count; + dict mux_cells_a, mux_cells_b; MemoryDffWorker(Module *module) : module(module), sigmap(module) { } @@ -150,16 +151,44 @@ struct MemoryDffWorker if (sigbit_users_count[bit] > 1) goto skip_ff_after_read_merging; - if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx)) + if (mux_cells_a.count(sig_data) || mux_cells_b.count(sig_data)) { - disconnect_dff(sig_data); - cell->setPort("\\CLK", clk_data); - cell->setPort("\\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; + bool enable_invert = mux_cells_a.count(sig_data); + Cell *mux = enable_invert ? mux_cells_a.at(sig_data) : mux_cells_b.at(sig_data); + SigSpec check_q = sigmap(mux->getPort(enable_invert ? "\\B" : "\\A")); + + sig_data = sigmap(mux->getPort("\\Y")); + for (auto bit : sig_data) + if (sigbit_users_count[bit] > 1) + goto skip_ff_after_read_merging; + + if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx) && sig_data == check_q) + { + disconnect_dff(sig_data); + cell->setPort("\\CLK", clk_data); + cell->setPort("\\EN", enable_invert ? module->LogicNot(NEW_ID, mux->getPort("\\S")) : mux->getPort("\\S")); + cell->setPort("\\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 with rd enable to cell.\n"); + return; + } + } + else + { + if (find_sig_before_dff(sig_data, clk_data, clk_polarity, true) && clk_data != RTLIL::SigSpec(RTLIL::State::Sx)) + { + disconnect_dff(sig_data); + cell->setPort("\\CLK", clk_data); + cell->setPort("\\EN", State::S1); + cell->setPort("\\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; + } } skip_ff_after_read_merging:; @@ -169,6 +198,7 @@ struct MemoryDffWorker clk_addr != RTLIL::SigSpec(RTLIL::State::Sx)) { cell->setPort("\\CLK", clk_addr); + cell->setPort("\\EN", State::S1); cell->setPort("\\ADDR", sig_addr); cell->parameters["\\CLK_ENABLE"] = RTLIL::Const(1); cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(clk_polarity); @@ -191,6 +221,10 @@ struct MemoryDffWorker for (auto cell : module->cells()) { if (cell->type == "$dff") dff_cells.push_back(cell); + if (cell->type == "$mux") { + mux_cells_a[sigmap(cell->getPort("\\A"))] = cell; + mux_cells_b[sigmap(cell->getPort("\\B"))] = cell; + } if (cell->type == "$not" || cell->type == "$_NOT_" || (cell->type == "$logic_not" && GetSize(cell->getPort("\\A")) == 1)) { SigSpec sig_a = cell->getPort("\\A"); SigSpec sig_y = cell->getPort("\\Y"); diff --git a/passes/memory/memory_map.cc b/passes/memory/memory_map.cc index 524fa8d2..0b8ccb36 100644 --- a/passes/memory/memory_map.cc +++ b/passes/memory/memory_map.cc @@ -200,34 +200,43 @@ struct MemoryMapWorker if (cell->parameters["\\RD_CLK_ENABLE"].bits[i] == RTLIL::State::S1) { + RTLIL::Cell *dff_cell = nullptr; + if (cell->parameters["\\RD_TRANSPARENT"].bits[i] == RTLIL::State::S1) { - RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); - c->parameters["\\WIDTH"] = RTLIL::Const(mem_abits); - c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); - c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); - c->setPort("\\D", rd_addr); + dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); + dff_cell->parameters["\\WIDTH"] = RTLIL::Const(mem_abits); + dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); + dff_cell->setPort("\\D", rd_addr); count_dff++; RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$q"), mem_abits); - c->setPort("\\Q", RTLIL::SigSpec(w)); + dff_cell->setPort("\\Q", RTLIL::SigSpec(w)); rd_addr = RTLIL::SigSpec(w); } else { - RTLIL::Cell *c = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); - c->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; - c->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); - c->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); - c->setPort("\\Q", rd_signals.back()); + dff_cell = module->addCell(genid(cell->name, "$rdreg", i), "$dff"); + dff_cell->parameters["\\WIDTH"] = cell->parameters["\\WIDTH"]; + dff_cell->parameters["\\CLK_POLARITY"] = RTLIL::Const(cell->parameters["\\RD_CLK_POLARITY"].bits[i]); + dff_cell->setPort("\\CLK", cell->getPort("\\RD_CLK").extract(i, 1)); + dff_cell->setPort("\\Q", rd_signals.back()); count_dff++; RTLIL::Wire *w = module->addWire(genid(cell->name, "$rdreg", i, "$d"), mem_width); rd_signals.clear(); rd_signals.push_back(RTLIL::SigSpec(w)); - c->setPort("\\D", rd_signals.back()); + dff_cell->setPort("\\D", rd_signals.back()); + } + + SigBit en_bit = cell->getPort("\\RD_EN").extract(i); + if (en_bit != State::S1) { + SigSpec new_d = module->Mux(genid(cell->name, "$rdenmux", i), + dff_cell->getPort("\\Q"), dff_cell->getPort("\\D"), en_bit); + dff_cell->setPort("\\D", new_d); } } diff --git a/passes/memory/memory_unpack.cc b/passes/memory/memory_unpack.cc index a497362b..60724da7 100644 --- a/passes/memory/memory_unpack.cc +++ b/passes/memory/memory_unpack.cc @@ -57,6 +57,7 @@ void handle_memory(RTLIL::Module *module, RTLIL::Cell *memory) 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->setPort("\\CLK", memory->getPort("\\RD_CLK").extract(i, 1)); + cell->setPort("\\EN", memory->getPort("\\RD_EN").extract(i, 1)); cell->setPort("\\ADDR", memory->getPort("\\RD_ADDR").extract(i*abits, abits)); cell->setPort("\\DATA", memory->getPort("\\RD_DATA").extract(i*mem->width, mem->width)); } -- cgit v1.2.3