mirror of https://github.com/YosysHQ/yosys.git
kernel/mem: Add emulate_priority helper.
This commit is contained in:
parent
e0736c1622
commit
4858721637
|
@ -599,3 +599,41 @@ void Mem::narrow() {
|
|||
std::swap(rd_ports, new_rd_ports);
|
||||
std::swap(wr_ports, new_wr_ports);
|
||||
}
|
||||
|
||||
void Mem::emulate_priority(int idx1, int idx2)
|
||||
{
|
||||
auto &port1 = wr_ports[idx1];
|
||||
auto &port2 = wr_ports[idx2];
|
||||
if (!port2.priority_mask[idx1])
|
||||
return;
|
||||
int min_wide_log2 = std::min(port1.wide_log2, port2.wide_log2);
|
||||
int max_wide_log2 = std::max(port1.wide_log2, port2.wide_log2);
|
||||
bool wide1 = port1.wide_log2 > port2.wide_log2;
|
||||
for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
|
||||
SigSpec addr1 = port1.addr;
|
||||
SigSpec addr2 = port2.addr;
|
||||
for (int j = min_wide_log2; j < max_wide_log2; j++)
|
||||
if (wide1)
|
||||
addr1[j] = State(sub >> j & 1);
|
||||
else
|
||||
addr2[j] = State(sub >> j & 1);
|
||||
SigSpec addr_eq = module->Eq(NEW_ID, addr1, addr2);
|
||||
int ewidth = width << min_wide_log2;
|
||||
int sub1 = wide1 ? sub : 0;
|
||||
int sub2 = wide1 ? 0 : sub;
|
||||
dict<std::pair<SigBit, SigBit>, SigBit> cache;
|
||||
for (int pos = 0; pos < ewidth; pos++) {
|
||||
SigBit &en1 = port1.en[pos + sub1 * width];
|
||||
SigBit &en2 = port2.en[pos + sub2 * width];
|
||||
std::pair<SigBit, SigBit> key(en1, en2);
|
||||
if (cache.count(key)) {
|
||||
en1 = cache[key];
|
||||
} else {
|
||||
SigBit active2 = module->And(NEW_ID, addr_eq, en2);
|
||||
SigBit nactive2 = module->Not(NEW_ID, active2);
|
||||
en1 = cache[key] = module->And(NEW_ID, en1, nactive2);
|
||||
}
|
||||
}
|
||||
}
|
||||
port2.priority_mask[idx1] = false;
|
||||
}
|
||||
|
|
|
@ -77,6 +77,12 @@ struct Mem {
|
|||
Cell *extract_rdff(int idx, FfInitVals *initvals);
|
||||
void narrow();
|
||||
|
||||
// If write port idx2 currently has priority over write port idx1,
|
||||
// inserts extra logic on idx1's enable signal to disable writes
|
||||
// when idx2 is writing to the same address, then removes the priority
|
||||
// from the priority mask.
|
||||
void emulate_priority(int idx1, int idx2);
|
||||
|
||||
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