mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
Added read-enable to memory model
This commit is contained in:
parent
ec92c89659
commit
924d9d6e86
17 changed files with 157 additions and 76 deletions
|
@ -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");
|
||||
|
|
|
@ -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<Cell*> 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);
|
||||
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_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++;
|
||||
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);
|
||||
|
|
|
@ -31,6 +31,7 @@ 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;
|
||||
|
||||
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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue