Added proper clkpol support to memory_bram
authorClifford Wolf <clifford@clifford.at>
Fri, 2 Jan 2015 21:45:26 +0000 (22:45 +0100)
committerClifford Wolf <clifford@clifford.at>
Fri, 2 Jan 2015 21:57:08 +0000 (22:57 +0100)
passes/memory/memory_bram.cc
techlibs/common/simlib.v
tests/bram/generate.py

index 1f7436d2d3c8b48ec8a2ba2c93598b20b92e41a2..356663e034b94695ceaf03f4157a8c2d348d8fc4 100644 (file)
@@ -225,13 +225,23 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_
        int dup_count = 1;
 
        dict<int, pair<SigBit, bool>> clock_domains;
+       dict<int, bool> clock_polarities;
        pool<int> clocks_wr_ports;
+       pool<int> clkpol_wr_ports;
        int clocks_max = 0;
+       int clkpol_max = 0;
+
+       clock_polarities[0] = false;
+       clock_polarities[1] = true;
 
        for (auto &pi : portinfos) {
-               if (pi.wrmode)
+               if (pi.wrmode) {
                        clocks_wr_ports.insert(pi.clocks);
+                       if (pi.clkpol > 1)
+                               clkpol_wr_ports.insert(pi.clkpol);
+               }
                clocks_max = std::max(clocks_max, pi.clocks);
+               clkpol_max = std::max(clkpol_max, pi.clkpol);
        }
 
        log("  Mapping to bram type %s:\n", log_id(bram.name));
@@ -295,6 +305,10 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_
                                        log("      Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1);
                                        goto skip_bram_wport;
                                }
+                               if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) {
+                                       log("      Bram port %c%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1);
+                                       goto skip_bram_wport;
+                               }
                        } else {
                                if (pi.clocks != 0) {
                                        log("      Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1);
@@ -320,6 +334,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_
 
                        if (clken) {
                                clock_domains[pi.clocks] = clkdom;
+                               clock_polarities[pi.clkpol] = clkdom.second;
                                pi.sig_clock = clkdom.first;
                                pi.effective_clkpol = clkdom.second;
                        }
@@ -340,6 +355,7 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_
        int grow_read_ports_cursor = -1;
        bool try_growing_more_read_ports = false;
        auto backup_clock_domains = clock_domains;
+       auto backup_clock_polarities = clock_polarities;
 
        if (0) {
 grow_read_ports:;
@@ -356,6 +372,8 @@ grow_read_ports:;
                        if (pi.dupidx == dup_count-1) {
                                if (pi.clocks && !clocks_wr_ports[pi.clocks])
                                        pi.clocks += clocks_max;
+                               if (pi.clkpol > 1 && !clkpol_wr_ports[pi.clkpol])
+                                       pi.clkpol += clkpol_max;
                                pi.dupidx++;
                                new_portinfos.push_back(pi);
                        }
@@ -363,6 +381,7 @@ grow_read_ports:;
                try_growing_more_read_ports = false;
                portinfos.swap(new_portinfos);
                clock_domains = backup_clock_domains;
+               clock_polarities = backup_clock_polarities;
                dup_count++;
        }
 
@@ -390,16 +409,20 @@ grow_read_ports:;
 
                        if (clken) {
                                if (pi.clocks == 0) {
-                                       log("      Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1);
+                                       log("      Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                        goto skip_bram_rport;
                                }
                                if (clock_domains.count(pi.clocks) && clock_domains.at(pi.clocks) != clkdom) {
-                                       log("      Bram port %c%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1);
+                                       log("      Bram port %c%d.%d is in a different clock domain.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
+                                       goto skip_bram_rport;
+                               }
+                               if (clock_polarities.count(pi.clkpol) && clock_polarities.at(pi.clkpol) != clkpol) {
+                                       log("      Bram port %c%d.%d has incompatible clock polarity.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                        goto skip_bram_rport;
                                }
                        } else {
                                if (pi.clocks != 0) {
-                                       log("      Bram port %c%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1);
+                                       log("      Bram port %c%d.%d has incompatible clock type.\n", pi.group + 'A', pi.index + 1, pi.dupidx + 1);
                                        goto skip_bram_rport;
                                }
                        }
@@ -409,6 +432,7 @@ grow_read_ports:;
 
                        if (clken) {
                                clock_domains[pi.clocks] = clkdom;
+                               clock_polarities[pi.clkpol] = clkdom.second;
                                pi.sig_clock = clkdom.first;
                                pi.effective_clkpol = clkdom.second;
                        }
@@ -506,6 +530,10 @@ grow_read_ports:;
 
                for (auto &it : clocks)
                        c->setPort(stringf("\\CLK%d", (it.first-1) % clocks_max + 1), it.second);
+
+               for (auto &it : clock_polarities)
+                       if (it.first > 1)
+                               c->setParam(stringf("\\CLKPOL%d", (it.first-1) % clkpol_max + 1), it.second);
        }
 
        for (auto &it : dout_cache)
index ca4b1d36cc43ead3b501e17506363bf47adfe7aa..4680e209a87c0b24ebceeb56f2667790acf84d34 100644 (file)
@@ -1539,7 +1539,7 @@ function port_active;
        end
 endfunction
 
-always @* begin
+always @(RD_CLK, RD_ADDR, RD_DATA, WR_CLK, WR_EN, WR_ADDR, WR_DATA) begin
        for (i = 0; i < RD_PORTS; i = i+1) begin
                if ((!RD_TRANSPARENT[i] && RD_CLK_ENABLE[i]) && port_active(RD_CLK_ENABLE[i], RD_CLK_POLARITY[i], LAST_RD_CLK[i], RD_CLK[i]))
                        RD_DATA[i*WIDTH +: WIDTH] <= memory[RD_ADDR[i*ABITS +: ABITS] - OFFSET];
index 514dfb9fbd526ba1b375319e57c9b1e84715bbb4..0e803218a39fec1cb8c4b1fc84f3faf662ae4a52 100644 (file)
@@ -32,7 +32,7 @@ def create_bram(dsc_f, sim_f, ref_f, tb_f, k1, k2):
         # XXX
         init = 0
         transp = [ 0 for i in range(groups) ]
-        clkpol = [ 1 for i in range(groups) ]
+        clkpol = [ random.randrange(0, 2) for i in range(groups) ]
 
         for p1 in range(groups):
             if wrmode[p1] == 0: