Merge pull request #1174 from YosysHQ/eddie/fix1173
[yosys.git] / passes / memory / memory_bram.cc
index cf4095d068f5ff09b9e6f0644a9be341436536e6..ddc56d9b5ef338c42a32548a85dff5441ee7ac5f 100644 (file)
@@ -542,7 +542,7 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
        }
 
        // assign write ports
-
+       pair<SigBit, bool> wr_clkdom;
        for (int cell_port_i = 0, bram_port_i = 0; cell_port_i < wr_ports; cell_port_i++)
        {
                bool clken = wr_clken[cell_port_i] == State::S1;
@@ -552,7 +552,7 @@ bool replace_cell(Cell *cell, const rules_t &rules, const rules_t::bram_t &bram,
                pair<SigBit, bool> clkdom(clksig, clkpol);
                if (!clken)
                        clkdom = pair<SigBit, bool>(State::S1, false);
-
+               wr_clkdom = clkdom;
                log("      Write port #%d is in clock domain %s%s.\n",
                                cell_port_i, clkdom.second ? "" : "!",
                                clken ? log_signal(clkdom.first) : "~async~");
@@ -641,6 +641,7 @@ grow_read_ports:;
                                pi.sig_data = SigSpec();
                                pi.sig_en = SigSpec();
                                pi.make_outreg = false;
+                               pi.make_transp = false;
                        }
                        new_portinfos.push_back(pi);
                        if (pi.dupidx == dup_count-1) {
@@ -718,7 +719,13 @@ grow_read_ports:;
                                if (read_transp.count(pi.transp) && read_transp.at(pi.transp) != transp) {
                                        if (match.make_transp && wr_ports <= 1) {
                                                pi.make_transp = true;
-                                               enable_make_transp = true;
+                                               if (pi.clocks != 0) {
+                                                       if (wr_ports == 1 && wr_clkdom != clkdom) {                                                             
+                                                               log("        Bram port %c%d.%d cannot have soft transparency logic added as read and write clock domains differ.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
+                                                               goto skip_bram_rport;
+                                                       }
+                                                       enable_make_transp = true;
+                                               }
                                        } else {
                                                log("        Bram port %c%d.%d has incompatible read transparency.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                                goto skip_bram_rport;
@@ -737,7 +744,8 @@ grow_read_ports:;
                        if (clken) {
                                clock_domains[pi.clocks] = clkdom;
                                clock_polarities[pi.clkpol] = clkdom.second;
-                               read_transp[pi.transp] = transp;
+                               if (!pi.make_transp)
+                                       read_transp[pi.transp] = transp;
                                pi.sig_clock = clkdom.first;
                                pi.sig_en = rd_en[cell_port_i];
                                pi.effective_clkpol = clkdom.second;
@@ -913,17 +921,18 @@ grow_read_ports:;
                                } else {
                                        SigSpec bram_dout = module->addWire(NEW_ID, bram.dbits);
                                        c->setPort(stringf("\\%sDATA", pf), bram_dout);
-
-                                       if (pi.make_outreg) {
+                                       if (pi.make_outreg && pi.make_transp) {
+                                               log("        Moving output register to address for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
+                                               SigSpec sig_addr_q = module->addWire(NEW_ID, bram.abits);
+                                               module->addDff(NEW_ID, pi.sig_clock, sig_addr, sig_addr_q, pi.effective_clkpol);
+                                               c->setPort(stringf("\\%sADDR", pf), sig_addr_q);
+                                       } else if (pi.make_outreg) {
                                                SigSpec bram_dout_q = module->addWire(NEW_ID, bram.dbits);
                                                if (!pi.sig_en.empty())
                                                        bram_dout = module->Mux(NEW_ID, bram_dout_q, bram_dout, pi.sig_en);
                                                module->addDff(NEW_ID, pi.sig_clock, bram_dout, bram_dout_q, pi.effective_clkpol);
                                                bram_dout = bram_dout_q;
-                                       }
-
-                                       if (pi.make_transp)
-                                       {
+                                       } else if (pi.make_transp) {
                                                log("        Adding extra logic for transparent port %c%d.%d.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
 
                                                SigSpec transp_en_d = module->Mux(NEW_ID, SigSpec(0, make_transp_enbits),
@@ -949,6 +958,8 @@ grow_read_ports:;
                                        SigSpec addr_ok_q = addr_ok;
                                        if ((pi.clocks || pi.make_outreg) && !addr_ok.empty()) {
                                                addr_ok_q = module->addWire(NEW_ID);
+                                               if (!pi.sig_en.empty())
+                                                       addr_ok = module->Mux(NEW_ID, addr_ok_q, addr_ok, pi.sig_en);
                                                module->addDff(NEW_ID, pi.sig_clock, addr_ok, addr_ok_q, pi.effective_clkpol);
                                        }