From 90f4017703a275c1a32cb347e4b60bd43873bbce Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Fri, 2 Jan 2015 22:45:26 +0100 Subject: Added proper clkpol support to memory_bram --- passes/memory/memory_bram.cc | 36 ++++++++++++++++++++++++++++++++---- techlibs/common/simlib.v | 2 +- tests/bram/generate.py | 2 +- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/passes/memory/memory_bram.cc b/passes/memory/memory_bram.cc index 1f7436d2..356663e0 100644 --- a/passes/memory/memory_bram.cc +++ b/passes/memory/memory_bram.cc @@ -225,13 +225,23 @@ bool replace_cell(Cell *cell, const rules_t::bram_t &bram, const rules_t::match_ int dup_count = 1; dict> clock_domains; + dict clock_polarities; pool clocks_wr_ports; + pool 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) diff --git a/techlibs/common/simlib.v b/techlibs/common/simlib.v index ca4b1d36..4680e209 100644 --- a/techlibs/common/simlib.v +++ b/techlibs/common/simlib.v @@ -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]; diff --git a/tests/bram/generate.py b/tests/bram/generate.py index 514dfb9f..0e803218 100644 --- a/tests/bram/generate.py +++ b/tests/bram/generate.py @@ -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: -- cgit v1.2.3