mirror of https://github.com/YosysHQ/yosys.git
memory_map: Use const drivers instead of FFs for ROMs.
This commit is contained in:
parent
bb634d39ef
commit
01daa077a2
|
@ -191,6 +191,10 @@ struct MemoryMapWorker
|
|||
data_reg_out[idx] = static_cells_map[addr];
|
||||
count_static++;
|
||||
}
|
||||
else if (mem.wr_ports.empty())
|
||||
{
|
||||
data_reg_out[idx] = init_data.extract(i*mem.width, mem.width);
|
||||
}
|
||||
else
|
||||
{
|
||||
RTLIL::Cell *c = module->addCell(genid(mem.memid, "", addr), ID($dff));
|
||||
|
@ -266,69 +270,72 @@ struct MemoryMapWorker
|
|||
|
||||
log(" read interface: %d $dff and %d $mux cells.\n", count_dff, count_mux);
|
||||
|
||||
for (int i = 0; i < mem.size; i++)
|
||||
if (!mem.wr_ports.empty())
|
||||
{
|
||||
int addr = i + mem.start_offset;
|
||||
int idx = addr & ((1 << abits) - 1);
|
||||
if (static_cells_map.count(addr) > 0)
|
||||
continue;
|
||||
|
||||
RTLIL::SigSpec sig = data_reg_out[idx];
|
||||
|
||||
for (int j = 0; j < GetSize(mem.wr_ports); j++)
|
||||
for (int i = 0; i < mem.size; i++)
|
||||
{
|
||||
auto &port = mem.wr_ports[j];
|
||||
RTLIL::SigSpec wr_addr = port.addr.extract_end(port.wide_log2);
|
||||
RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(addr >> port.wide_log2, GetSize(wr_addr)));
|
||||
int addr = i + mem.start_offset;
|
||||
int idx = addr & ((1 << abits) - 1);
|
||||
if (static_cells_map.count(addr) > 0)
|
||||
continue;
|
||||
|
||||
int sub = addr & ((1 << port.wide_log2) - 1);
|
||||
RTLIL::SigSpec sig = data_reg_out[idx];
|
||||
|
||||
int wr_offset = 0;
|
||||
while (wr_offset < mem.width)
|
||||
for (int j = 0; j < GetSize(mem.wr_ports); j++)
|
||||
{
|
||||
int wr_width = 1;
|
||||
RTLIL::SigSpec wr_bit = port.en.extract(wr_offset + sub * mem.width, 1);
|
||||
auto &port = mem.wr_ports[j];
|
||||
RTLIL::SigSpec wr_addr = port.addr.extract_end(port.wide_log2);
|
||||
RTLIL::Wire *w_seladdr = addr_decode(wr_addr, RTLIL::SigSpec(addr >> port.wide_log2, GetSize(wr_addr)));
|
||||
|
||||
while (wr_offset + wr_width < mem.width) {
|
||||
RTLIL::SigSpec next_wr_bit = port.en.extract(wr_offset + wr_width + sub * mem.width, 1);
|
||||
if (next_wr_bit != wr_bit)
|
||||
break;
|
||||
wr_width++;
|
||||
}
|
||||
int sub = addr & ((1 << port.wide_log2) - 1);
|
||||
|
||||
RTLIL::Wire *w = w_seladdr;
|
||||
|
||||
if (wr_bit != State::S1)
|
||||
int wr_offset = 0;
|
||||
while (wr_offset < mem.width)
|
||||
{
|
||||
RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wren", addr, "", j, "", wr_offset), ID($and));
|
||||
c->parameters[ID::A_SIGNED] = RTLIL::Const(0);
|
||||
c->parameters[ID::B_SIGNED] = RTLIL::Const(0);
|
||||
c->parameters[ID::A_WIDTH] = RTLIL::Const(1);
|
||||
c->parameters[ID::B_WIDTH] = RTLIL::Const(1);
|
||||
c->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
|
||||
c->setPort(ID::A, w);
|
||||
c->setPort(ID::B, wr_bit);
|
||||
int wr_width = 1;
|
||||
RTLIL::SigSpec wr_bit = port.en.extract(wr_offset + sub * mem.width, 1);
|
||||
|
||||
w = module->addWire(genid(mem.memid, "$wren", addr, "", j, "", wr_offset, "$y"));
|
||||
c->setPort(ID::Y, RTLIL::SigSpec(w));
|
||||
while (wr_offset + wr_width < mem.width) {
|
||||
RTLIL::SigSpec next_wr_bit = port.en.extract(wr_offset + wr_width + sub * mem.width, 1);
|
||||
if (next_wr_bit != wr_bit)
|
||||
break;
|
||||
wr_width++;
|
||||
}
|
||||
|
||||
RTLIL::Wire *w = w_seladdr;
|
||||
|
||||
if (wr_bit != State::S1)
|
||||
{
|
||||
RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wren", addr, "", j, "", wr_offset), ID($and));
|
||||
c->parameters[ID::A_SIGNED] = RTLIL::Const(0);
|
||||
c->parameters[ID::B_SIGNED] = RTLIL::Const(0);
|
||||
c->parameters[ID::A_WIDTH] = RTLIL::Const(1);
|
||||
c->parameters[ID::B_WIDTH] = RTLIL::Const(1);
|
||||
c->parameters[ID::Y_WIDTH] = RTLIL::Const(1);
|
||||
c->setPort(ID::A, w);
|
||||
c->setPort(ID::B, wr_bit);
|
||||
|
||||
w = module->addWire(genid(mem.memid, "$wren", addr, "", j, "", wr_offset, "$y"));
|
||||
c->setPort(ID::Y, RTLIL::SigSpec(w));
|
||||
}
|
||||
|
||||
RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset), ID($mux));
|
||||
c->parameters[ID::WIDTH] = wr_width;
|
||||
c->setPort(ID::A, sig.extract(wr_offset, wr_width));
|
||||
c->setPort(ID::B, port.data.extract(wr_offset + sub * mem.width, wr_width));
|
||||
c->setPort(ID::S, RTLIL::SigSpec(w));
|
||||
|
||||
w = module->addWire(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset, "$y"), wr_width);
|
||||
c->setPort(ID::Y, w);
|
||||
|
||||
sig.replace(wr_offset, w);
|
||||
wr_offset += wr_width;
|
||||
count_wrmux++;
|
||||
}
|
||||
|
||||
RTLIL::Cell *c = module->addCell(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset), ID($mux));
|
||||
c->parameters[ID::WIDTH] = wr_width;
|
||||
c->setPort(ID::A, sig.extract(wr_offset, wr_width));
|
||||
c->setPort(ID::B, port.data.extract(wr_offset + sub * mem.width, wr_width));
|
||||
c->setPort(ID::S, RTLIL::SigSpec(w));
|
||||
|
||||
w = module->addWire(genid(mem.memid, "$wrmux", addr, "", j, "", wr_offset, "$y"), wr_width);
|
||||
c->setPort(ID::Y, w);
|
||||
|
||||
sig.replace(wr_offset, w);
|
||||
wr_offset += wr_width;
|
||||
count_wrmux++;
|
||||
}
|
||||
}
|
||||
|
||||
module->connect(RTLIL::SigSig(data_reg_in[idx], sig));
|
||||
module->connect(RTLIL::SigSig(data_reg_in[idx], sig));
|
||||
}
|
||||
}
|
||||
|
||||
log(" write interface: %d write mux blocks.\n", count_wrmux);
|
||||
|
|
Loading…
Reference in New Issue