kernel/mem: Add emulate_priority helper.

This commit is contained in:
Marcelina Kościelnicka 2021-05-25 02:56:35 +02:00
parent e0736c1622
commit 4858721637
2 changed files with 44 additions and 0 deletions

View File

@ -599,3 +599,41 @@ void Mem::narrow() {
std::swap(rd_ports, new_rd_ports); std::swap(rd_ports, new_rd_ports);
std::swap(wr_ports, new_wr_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;
}

View File

@ -77,6 +77,12 @@ struct Mem {
Cell *extract_rdff(int idx, FfInitVals *initvals); Cell *extract_rdff(int idx, FfInitVals *initvals);
void narrow(); 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) {} 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) {}
}; };