mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-23 09:05:32 +00:00
kernel/mem: Introduce transparency masks.
This commit is contained in:
parent
681a1c07e5
commit
e6f3d1c225
8 changed files with 407 additions and 117 deletions
|
@ -405,10 +405,6 @@ bool replace_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals, const
|
|||
auto portinfos = bram.make_portinfos();
|
||||
int dup_count = 1;
|
||||
|
||||
pair<SigBit, bool> make_transp_clk;
|
||||
bool enable_make_transp = false;
|
||||
int make_transp_enbits = 0;
|
||||
|
||||
dict<int, pair<SigBit, bool>> clock_domains;
|
||||
dict<int, bool> clock_polarities;
|
||||
dict<int, bool> read_transp;
|
||||
|
@ -496,8 +492,6 @@ bool replace_memory(Mem &mem, const rules_t &rules, FfInitVals *initvals, const
|
|||
for (; bram_port_i < GetSize(portinfos); bram_port_i++)
|
||||
{
|
||||
auto &pi = portinfos[bram_port_i];
|
||||
make_transp_enbits = pi.enable ? pi.enable : 1;
|
||||
make_transp_clk = clkdom;
|
||||
|
||||
if (pi.wrmode != 1)
|
||||
skip_bram_wport:
|
||||
|
@ -606,10 +600,16 @@ grow_read_ports:;
|
|||
for (int cell_port_i = 0; cell_port_i < GetSize(mem.rd_ports); cell_port_i++)
|
||||
{
|
||||
auto &port = mem.rd_ports[cell_port_i];
|
||||
bool transp = port.transparent;
|
||||
bool transp = false;
|
||||
bool non_transp = false;
|
||||
|
||||
if (mem.wr_ports.empty())
|
||||
transp = false;
|
||||
if (port.clk_enable) {
|
||||
for (int i = 0; i < GetSize(mem.wr_ports); i++)
|
||||
if (port.transparency_mask[i])
|
||||
transp = true;
|
||||
else if (!port.collision_x_mask[i])
|
||||
non_transp = true;
|
||||
}
|
||||
|
||||
pair<SigBit, bool> clkdom(port.clk, port.clk_polarity);
|
||||
if (!port.clk_enable)
|
||||
|
@ -660,16 +660,13 @@ grow_read_ports:;
|
|||
log(" Bram port %c%d.%d has no initial value support.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
|
||||
goto skip_bram_rport;
|
||||
}
|
||||
if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) {
|
||||
if (match.make_transp && GetSize(mem.wr_ports) <= 1) {
|
||||
if (non_transp && read_transp.count(pi.transp) && read_transp.at(pi.transp)) {
|
||||
log(" Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
|
||||
goto skip_bram_rport;
|
||||
}
|
||||
if (transp && (non_transp || (read_transp.count(pi.transp) && !read_transp.at(pi.transp)))) {
|
||||
if (match.make_transp) {
|
||||
pi.make_transp = true;
|
||||
if (pi.clocks != 0) {
|
||||
if (GetSize(mem.wr_ports) == 1 && wr_clkdom != clkdom) {
|
||||
log(" Bram port %c%d.%d cannot have soft transparency logic added as read and write clock domains differ.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
|
||||
goto skip_bram_rport;
|
||||
}
|
||||
enable_make_transp = true;
|
||||
}
|
||||
} else {
|
||||
log(" Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
|
||||
goto skip_bram_rport;
|
||||
|
@ -689,8 +686,10 @@ grow_read_ports:;
|
|||
if (pi.clocks) {
|
||||
clock_domains[pi.clocks] = clkdom;
|
||||
clock_polarities[pi.clkpol] = clkdom.second;
|
||||
if (!pi.make_transp)
|
||||
read_transp[pi.transp] = transp;
|
||||
if (non_transp)
|
||||
read_transp[pi.transp] = false;
|
||||
if (transp && !pi.make_transp)
|
||||
read_transp[pi.transp] = true;
|
||||
}
|
||||
|
||||
if (grow_read_ports_cursor < cell_port_i) {
|
||||
|
@ -793,10 +792,22 @@ grow_read_ports:;
|
|||
|
||||
// At this point we are commited to replacing the RAM, and can mutate mem.
|
||||
|
||||
// Apply make_outreg and make_transp where necessary.
|
||||
for (auto &pi : portinfos) {
|
||||
if (pi.make_outreg)
|
||||
mem.extract_rdff(pi.mapped_port, initvals);
|
||||
if (pi.make_transp) {
|
||||
auto &port = mem.rd_ports[pi.mapped_port];
|
||||
for (int i = 0; i < GetSize(mem.wr_ports); i++)
|
||||
if (port.transparency_mask[i])
|
||||
mem.emulate_transparency(i, pi.mapped_port, initvals);
|
||||
}
|
||||
}
|
||||
|
||||
// We don't really support priorities, emulate them.
|
||||
for (int i = 0; i < GetSize(mem.wr_ports); i++)
|
||||
for (int j = 0; j < i; j++)
|
||||
mem.emulate_priority(j, i);
|
||||
mem.emulate_priority(j, i, initvals);
|
||||
|
||||
// Swizzle the init data. Do this before changing mem.width, so that get_init_data works.
|
||||
bool cell_init = !mem.inits.empty();
|
||||
|
@ -861,29 +872,12 @@ grow_read_ports:;
|
|||
for (auto &other_bram : rules.brams.at(bram.name))
|
||||
bram.find_variant_params(variant_params, other_bram);
|
||||
|
||||
// Apply make_outreg where necessary.
|
||||
for (auto &pi : portinfos)
|
||||
if (pi.make_outreg)
|
||||
mem.extract_rdff(pi.mapped_port, initvals);
|
||||
|
||||
// actually replace that memory cell
|
||||
|
||||
dict<SigSpec, pair<SigSpec, SigSpec>> dout_cache;
|
||||
|
||||
for (int grid_d = 0; grid_d < dcells; grid_d++)
|
||||
{
|
||||
SigSpec mktr_wraddr, mktr_wrdata, mktr_wrdata_q;
|
||||
vector<SigSpec> mktr_wren;
|
||||
|
||||
if (enable_make_transp) {
|
||||
mktr_wraddr = module->addWire(NEW_ID, bram.abits);
|
||||
mktr_wrdata = module->addWire(NEW_ID, bram.dbits);
|
||||
mktr_wrdata_q = module->addWire(NEW_ID, bram.dbits);
|
||||
module->addDff(NEW_ID, make_transp_clk.first, mktr_wrdata, mktr_wrdata_q, make_transp_clk.second);
|
||||
for (int grid_a = 0; grid_a < acells; grid_a++)
|
||||
mktr_wren.push_back(module->addWire(NEW_ID, make_transp_enbits));
|
||||
}
|
||||
|
||||
for (int grid_a = 0; grid_a < acells; grid_a++)
|
||||
for (int dupidx = 0; dupidx < dup_count; dupidx++)
|
||||
{
|
||||
|
@ -964,15 +958,6 @@ grow_read_ports:;
|
|||
|
||||
c->setPort(stringf("\\%sEN", pf), sig_en);
|
||||
|
||||
if (enable_make_transp)
|
||||
module->connect(mktr_wren[grid_a], sig_en);
|
||||
}
|
||||
else if (enable_make_transp)
|
||||
module->connect(mktr_wren[grid_a], addr_ok);
|
||||
|
||||
if (enable_make_transp && grid_a == 0) {
|
||||
module->connect(mktr_wraddr, sig_addr);
|
||||
module->connect(mktr_wrdata, sig_data);
|
||||
}
|
||||
} else {
|
||||
if (pi.mapped_port == -1)
|
||||
|
@ -986,22 +971,6 @@ grow_read_ports:;
|
|||
|
||||
SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits);
|
||||
c->setPort(stringf("\\%sDATA", pf), bram_dout);
|
||||
if (pi.make_transp) {
|
||||
log(" Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
|
||||
|
||||
SigSpec transp_en_d = module->Mux(NEW_ID, SigSpec(0, make_transp_enbits),
|
||||
mktr_wren[grid_a], module->Eq(NEW_ID, mktr_wraddr, sig_addr));
|
||||
|
||||
SigSpec transp_en_q = module->addWire(NEW_ID, make_transp_enbits);
|
||||
module->addDff(NEW_ID, make_transp_clk.first, transp_en_d, transp_en_q, make_transp_clk.second);
|
||||
|
||||
for (int i = 0; i < make_transp_enbits; i++) {
|
||||
int en_width = bram.dbits / make_transp_enbits;
|
||||
SigSpec orig_bram_dout = bram_dout.extract(i * en_width, en_width);
|
||||
SigSpec bypass_dout = mktr_wrdata_q.extract(i * en_width, en_width);
|
||||
bram_dout.replace(i * en_width, module->Mux(NEW_ID, orig_bram_dout, bypass_dout, transp_en_q[i]));
|
||||
}
|
||||
}
|
||||
|
||||
SigSpec addr_ok_q = addr_ok;
|
||||
if (port.clk_enable && !addr_ok.empty()) {
|
||||
|
|
|
@ -143,7 +143,8 @@ struct MemoryDffWorker
|
|||
port.addr = ff.sig_d;
|
||||
port.clk_enable = true;
|
||||
port.clk_polarity = ff.pol_clk;
|
||||
port.transparent = true;
|
||||
for (int i = 0; i < GetSize(mem.wr_ports); i++)
|
||||
port.transparency_mask[i] = true;
|
||||
mem.emit();
|
||||
log("merged address FF to cell.\n");
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "kernel/sigtools.h"
|
||||
#include "kernel/modtools.h"
|
||||
#include "kernel/mem.h"
|
||||
#include "kernel/ffinit.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
@ -32,6 +33,7 @@ struct MemoryShareWorker
|
|||
RTLIL::Module *module;
|
||||
SigMap sigmap, sigmap_xmux;
|
||||
ModWalker modwalker;
|
||||
FfInitVals initvals;
|
||||
bool flag_widen;
|
||||
|
||||
|
||||
|
@ -106,8 +108,6 @@ struct MemoryShareWorker
|
|||
continue;
|
||||
if (port1.ce_over_srst != port2.ce_over_srst)
|
||||
continue;
|
||||
if (port1.transparent != port2.transparent)
|
||||
continue;
|
||||
// If the width of the ports doesn't match, they can still be
|
||||
// merged by widening the narrow one. Check if the conditions
|
||||
// hold for that.
|
||||
|
@ -147,8 +147,10 @@ struct MemoryShareWorker
|
|||
continue;
|
||||
if (!merge_rst_value(mem, srst_value, wide_log2, port1.srst_value, sub1, port2.srst_value, sub2))
|
||||
continue;
|
||||
// At this point we are committed to the merge.
|
||||
{
|
||||
log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(port1.addr));
|
||||
mem.prepare_rd_merge(i, j, &initvals);
|
||||
mem.widen_prep(wide_log2);
|
||||
SigSpec new_data = module->addWire(NEW_ID, mem.width << wide_log2);
|
||||
module->connect(port1.data, new_data.extract(sub1 * mem.width, mem.width << port1.wide_log2));
|
||||
|
@ -231,7 +233,7 @@ struct MemoryShareWorker
|
|||
continue;
|
||||
}
|
||||
log(" Merging ports %d, %d (address %s).\n", i, j, log_signal(port1.addr));
|
||||
mem.prepare_wr_merge(i, j);
|
||||
mem.prepare_wr_merge(i, j, &initvals);
|
||||
port1.addr = sigmap_xmux(port1.addr);
|
||||
port2.addr = sigmap_xmux(port2.addr);
|
||||
mem.widen_wr_port(i, wide_log2);
|
||||
|
@ -391,7 +393,7 @@ struct MemoryShareWorker
|
|||
}
|
||||
|
||||
log(" Merging port %d into port %d.\n", idx2, idx1);
|
||||
mem.prepare_wr_merge(idx1, idx2);
|
||||
mem.prepare_wr_merge(idx1, idx2, &initvals);
|
||||
port_to_sat_variable.at(idx1) = qcsat.ez->OR(port_to_sat_variable.at(idx1), port_to_sat_variable.at(idx2));
|
||||
|
||||
RTLIL::SigSpec last_addr = port1.addr;
|
||||
|
@ -453,6 +455,7 @@ struct MemoryShareWorker
|
|||
|
||||
this->module = module;
|
||||
sigmap.set(module);
|
||||
initvals.set(&sigmap, module);
|
||||
|
||||
sigmap_xmux = sigmap;
|
||||
for (auto cell : module->cells())
|
||||
|
|
|
@ -43,6 +43,7 @@ struct OptMemFeedbackWorker
|
|||
RTLIL::Design *design;
|
||||
RTLIL::Module *module;
|
||||
SigMap sigmap, sigmap_xmux;
|
||||
FfInitVals initvals;
|
||||
|
||||
dict<RTLIL::SigBit, std::pair<RTLIL::Cell*, int>> sig_to_mux;
|
||||
dict<RTLIL::SigBit, int> sig_users_count;
|
||||
|
@ -245,7 +246,7 @@ struct OptMemFeedbackWorker
|
|||
|
||||
for (int i = 0; i < wrport_idx; i++)
|
||||
if (port.priority_mask[i])
|
||||
mem.emulate_priority(i, wrport_idx);
|
||||
mem.emulate_priority(i, wrport_idx, &initvals);
|
||||
}
|
||||
|
||||
for (auto &it : portbit_conds)
|
||||
|
@ -278,6 +279,7 @@ struct OptMemFeedbackWorker
|
|||
|
||||
this->module = module;
|
||||
sigmap.set(module);
|
||||
initvals.set(&sigmap, module);
|
||||
sig_to_mux.clear();
|
||||
conditions_logic_cache.clear();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue