mem/extract_rdff: Fix wire naming and wide port support.
authorMarcelina Kościelnicka <mwk@0x04.net>
Tue, 25 May 2021 13:48:52 +0000 (15:48 +0200)
committerMarcelina Kościelnicka <mwk@0x04.net>
Tue, 25 May 2021 15:51:47 +0000 (17:51 +0200)
kernel/mem.cc

index 649515e0c9b66945dc444318cac22b04272719c5..f1fedf3c296c1e8ffc6508630596f02ecfeadf44 100644 (file)
@@ -524,17 +524,33 @@ Cell *Mem::extract_rdff(int idx, FfInitVals *initvals) {
 
        if (port.transparent)
        {
-               SigSpec sig_q = module->addWire(stringf("%s$rdreg[%d]$q", memid.c_str(), idx), GetSize(port.addr));
-               SigSpec sig_d = port.addr;
-               port.addr = sig_q;
-               c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
+               log_assert(port.en == State::S1);
+
+               // Do not put a register in front of constant address bits — this is both
+               // unnecessary and will break wide ports.
+               int width = 0;
+               for (int i = 0; i < GetSize(port.addr); i++)
+                       if (port.addr[i].wire)
+                               width++;
+
+               SigSpec sig_q = module->addWire(stringf("$%s$rdreg[%d]$q", memid.c_str(), idx), width);
+               SigSpec sig_d;
+
+               int pos = 0;
+               for (int i = 0; i < GetSize(port.addr); i++)
+                       if (port.addr[i].wire) {
+                               sig_d.append(port.addr[i]);
+                               port.addr[i] = sig_q[pos++];
+                       }
+
+               c = module->addDffe(stringf("$%s$rdreg[%d]", memid.c_str(), idx), port.clk, State::S1, sig_d, sig_q, port.clk_polarity, true);
        }
        else
        {
-               SigSpec sig_d = module->addWire(stringf("%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
+               SigSpec sig_d = module->addWire(stringf("$%s$rdreg[%d]$d", memid.c_str(), idx), GetSize(port.data));
                SigSpec sig_q = port.data;
                port.data = sig_d;
-               c = module->addDffe(stringf("%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
+               c = module->addDffe(stringf("$%s$rdreg[%d]", memid.c_str(), idx), port.clk, port.en, sig_d, sig_q, port.clk_polarity, true);
        }
 
        log("Extracted %s FF from read port %d of %s.%s: %s\n", port.transparent ? "addr" : "data",