Added memory_bram "make_outreg" feature
authorClifford Wolf <clifford@clifford.at>
Thu, 9 Apr 2015 14:08:54 +0000 (16:08 +0200)
committerClifford Wolf <clifford@clifford.at>
Thu, 9 Apr 2015 14:08:54 +0000 (16:08 +0200)
passes/memory/memory_bram.cc
techlibs/xilinx/drams.txt

index d6c74ee6e1cfa8bb92df37f1136bf14ae249600a..2e968b7aa8253a0b7c9bbd3ee63bbc2933d13cdd 100644 (file)
@@ -32,6 +32,7 @@ struct rules_t
                SigSpec sig_addr, sig_data, sig_en;
                bool effective_clkpol;
                bool make_transp;
+               bool make_outreg;
                int mapped_port;
        };
 
@@ -85,6 +86,7 @@ struct rules_t
                                pi.clkpol = clkpol[i];
                                pi.mapped_port = -1;
                                pi.make_transp = false;
+                               pi.make_outreg = false;
                                pi.effective_clkpol = false;
                                portinfos.push_back(pi);
                        }
@@ -126,7 +128,7 @@ struct rules_t
        struct match_t {
                IdString name;
                dict<string, int> min_limits, max_limits;
-               bool or_next_if_better, make_transp;
+               bool or_next_if_better, make_transp, make_outreg;
                char shuffle_enable;
        };
 
@@ -277,6 +279,7 @@ struct rules_t
                data.name = RTLIL::escape_id(tokens[1]);
                data.or_next_if_better = false;
                data.make_transp = false;
+               data.make_outreg = false;
                data.shuffle_enable = 0;
 
                while (next_line())
@@ -309,6 +312,12 @@ struct rules_t
                                continue;
                        }
 
+                       if (GetSize(tokens) == 1 && tokens[0] == "make_outreg") {
+                               data.make_transp = true;
+                               data.make_outreg = true;
+                               continue;
+                       }
+
                        if (GetSize(tokens) == 1 && tokens[0] == "or_next_if_better") {
                                data.or_next_if_better = true;
                                continue;
@@ -664,6 +673,10 @@ grow_read_ports:;
 
                        if (clken) {
                                if (pi.clocks == 0) {
+                                       if (match.make_outreg) {
+                                               pi.make_outreg = true;
+                                               goto skip_bram_rport_clkcheck;
+                                       }
                                        log("        Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                        goto skip_bram_rport;
                                }
@@ -675,6 +688,7 @@ grow_read_ports:;
                                        log("        Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                        goto skip_bram_rport;
                                }
+                       skip_bram_rport_clkcheck:
                                if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) {
                                        if (match.make_transp && wr_ports <= 1) {
                                                pi.make_transp = true;
@@ -870,6 +884,12 @@ grow_read_ports:;
                                        SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits);
                                        c->setPort(stringf("\\%sDATA", pf), bram_dout);
 
+                                       if (pi.make_outreg) {
+                                               SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits);
+                                               module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol);
+                                               bram_dout = bram_dout_q;
+                                       }
+
                                        if (pi.make_transp)
                                        {
                                                log("        Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
@@ -895,7 +915,7 @@ grow_read_ports:;
                                                }
 
                                        SigSpec addr_ok_q = addr_ok;
-                                       if (pi.clocks && !addr_ok.empty()) {
+                                       if ((pi.clocks || pi.make_outreg) && !addr_ok.empty()) {
                                                addr_ok_q = module->addWire(NEW_ID);
                                                module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol);
                                        }
@@ -1169,6 +1189,9 @@ struct MemoryBramPass : public Pass {
                log("A match containing the command 'make_transp' will add external circuitry\n");
                log("to simulate 'transparent read', if necessary.\n");
                log("\n");
+               log("A match containing the command 'make_outreg' will add external flip-flops\n");
+               log("to implement synchronous read ports, if necessary.\n");
+               log("\n");
                log("A match containing the command 'shuffle_enable A' will re-organize\n");
                log("the data bits to accommodate the enable pattern of port A.\n");
                log("\n");
index 5d2840ec0382e02a07d23be5cf80e195084ce279..e6635d0e218ba4395cedd5522bf546c8041d42fb 100644 (file)
@@ -26,9 +26,11 @@ bram $__XILINX_RAM128X1D
 endbram
 
 match $__XILINX_RAM64X1D
+  make_outreg
   or_next_if_better
 endmatch
 
 match $__XILINX_RAM128X1D
+  make_outreg
 endmatch