mirror of https://github.com/YosysHQ/yosys.git
kernel/mem: Add helpers for write port widening.
This commit is contained in:
parent
83a218141c
commit
b019db1f37
|
@ -798,3 +798,49 @@ void Mem::prepare_wr_merge(int idx1, int idx2) {
|
|||
oport.priority_mask[idx1] = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Mem::widen_prep(int wide_log2) {
|
||||
// Make sure start_offset and size are aligned to the port width,
|
||||
// adjust if necessary.
|
||||
int mask = ((1 << wide_log2) - 1);
|
||||
int delta = start_offset & mask;
|
||||
start_offset -= delta;
|
||||
size += delta;
|
||||
if (size & mask) {
|
||||
size |= mask;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
void Mem::widen_wr_port(int idx, int wide_log2) {
|
||||
widen_prep(wide_log2);
|
||||
auto &port = wr_ports[idx];
|
||||
log_assert(port.wide_log2 <= wide_log2);
|
||||
if (port.wide_log2 < wide_log2) {
|
||||
SigSpec new_data, new_en;
|
||||
SigSpec addr_lo = port.addr.extract(0, wide_log2);
|
||||
for (int sub = 0; sub < (1 << wide_log2); sub += (1 << port.wide_log2))
|
||||
{
|
||||
Const cur_addr_lo(sub, wide_log2);
|
||||
if (addr_lo == cur_addr_lo) {
|
||||
// Always writes to this subword.
|
||||
new_data.append(port.data);
|
||||
new_en.append(port.en);
|
||||
} else if (addr_lo.is_fully_const()) {
|
||||
// Never writes to this subword.
|
||||
new_data.append(Const(State::Sx, GetSize(port.data)));
|
||||
new_en.append(Const(State::S0, GetSize(port.data)));
|
||||
} else {
|
||||
// May or may not write to this subword.
|
||||
new_data.append(port.data);
|
||||
SigSpec addr_eq = module->Eq(NEW_ID, addr_lo, cur_addr_lo);
|
||||
SigSpec en = module->Mux(NEW_ID, Const(State::S0, GetSize(port.data)), port.en, addr_eq);
|
||||
new_en.append(en);
|
||||
}
|
||||
}
|
||||
port.addr.replace(port.wide_log2, Const(State::S0, wide_log2 - port.wide_log2));
|
||||
port.data = new_data;
|
||||
port.en = new_en;
|
||||
port.wide_log2 = wide_log2;
|
||||
}
|
||||
}
|
||||
|
|
11
kernel/mem.h
11
kernel/mem.h
|
@ -109,6 +109,17 @@ struct Mem {
|
|||
// is called.
|
||||
void prepare_wr_merge(int idx1, int idx2);
|
||||
|
||||
// Prepares the memory for widening a port to a given width. This
|
||||
// involves ensuring that start_offset and size are aligned to the
|
||||
// target width.
|
||||
void widen_prep(int wide_log2);
|
||||
|
||||
// Widens a write port up to a given width. The newly port is
|
||||
// equivalent to the original, made by replicating enable/data bits
|
||||
// and masking enable bits with decoders on the low part of the
|
||||
// original address.
|
||||
void widen_wr_port(int idx, int wide_log2);
|
||||
|
||||
Mem(Module *module, IdString memid, int width, int start_offset, int size) : module(module), memid(memid), packed(false), mem(nullptr), cell(nullptr), width(width), start_offset(start_offset), size(size) {}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue