aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs/gatemate
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs/gatemate')
-rw-r--r--techlibs/gatemate/.gitignore4
-rw-r--r--techlibs/gatemate/Makefile.inc16
-rw-r--r--techlibs/gatemate/brams.txt360
-rw-r--r--techlibs/gatemate/brams_map.v1352
-rw-r--r--techlibs/gatemate/cells_sim.v44
-rw-r--r--techlibs/gatemate/gatemate_foldinv.cc219
-rw-r--r--techlibs/gatemate/inv_map.v4
-rw-r--r--techlibs/gatemate/make_lut_tree_lib.py323
-rw-r--r--techlibs/gatemate/synth_gatemate.cc39
9 files changed, 1574 insertions, 787 deletions
diff --git a/techlibs/gatemate/.gitignore b/techlibs/gatemate/.gitignore
new file mode 100644
index 000000000..f260d6e9d
--- /dev/null
+++ b/techlibs/gatemate/.gitignore
@@ -0,0 +1,4 @@
+lut_tree_cells.genlib
+lut_tree_map.v
+lut_tree_lib.mk
+
diff --git a/techlibs/gatemate/Makefile.inc b/techlibs/gatemate/Makefile.inc
index d1341d7bb..aeb318cc9 100644
--- a/techlibs/gatemate/Makefile.inc
+++ b/techlibs/gatemate/Makefile.inc
@@ -1,5 +1,6 @@
OBJS += techlibs/gatemate/synth_gatemate.o
+OBJS += techlibs/gatemate/gatemate_foldinv.o
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/reg_map.v))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/mux_map.v))
@@ -12,3 +13,18 @@ $(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_map.v))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams.txt))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_20.vh))
$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/brams_init_40.vh))
+$(eval $(call add_share_file,share/gatemate,techlibs/gatemate/inv_map.v))
+
+EXTRA_OBJS += techlibs/gatemate/lut_tree_lib.mk
+.SECONDARY: techlibs/gatemate/lut_tree_lib.mk
+
+techlibs/gatemate/lut_tree_lib.mk: techlibs/gatemate/make_lut_tree_lib.py
+ $(Q) mkdir -p techlibs/gatemate
+ $(P) $(PYTHON_EXECUTABLE) $<
+ $(Q) touch $@
+
+techlibs/gatemate/lut_tree_cells.genlib: techlibs/gatemate/lut_tree_lib.mk
+techlibs/gatemate/lut_tree_map.v: techlibs/gatemate/lut_tree_lib.mk
+
+$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_cells.genlib))
+$(eval $(call add_gen_share_file,share/gatemate,techlibs/gatemate/lut_tree_map.v))
diff --git a/techlibs/gatemate/brams.txt b/techlibs/gatemate/brams.txt
index 9e0bebba6..be22856ac 100644
--- a/techlibs/gatemate/brams.txt
+++ b/techlibs/gatemate/brams.txt
@@ -1,280 +1,80 @@
-bram $__CC_BRAM_CASCADE
- init 1
- abits 16 @a16d1
- dbits 1 @a16d1
- groups 2
- ports 1 1
- wrmode 1 0
- enable 1 1 @a16d1
- transp 0 0
- clocks 2 3
- clkpol 2 3
-endbram
-
-bram $__CC_BRAM_40K_SDP
- init 1
- abits 9 @a9d80
- dbits 80 @a9d80
- groups 2
- ports 1 1
- wrmode 1 0
- enable 80 1 @a9d80
- transp 0 0
- clocks 2 3
- clkpol 2 3
-endbram
-
-bram $__CC_BRAM_20K_SDP
- init 1
- abits 9 @a9d40
- dbits 40 @a9d40
- groups 2
- ports 1 1
- wrmode 1 0
- enable 40 1 @a9d40
- transp 0 0
- clocks 2 3
- clkpol 2 3
-endbram
-
-bram $__CC_BRAM_40K_TDP
- init 1
- abits 10 @a10d40
- dbits 40 @a10d40
- abits 11 @a11d20
- dbits 20 @a11d20
- abits 12 @a12d10
- dbits 10 @a12d10
- abits 13 @a13d5
- dbits 5 @a13d5
- abits 14 @a14d2
- dbits 2 @a14d2
- abits 15 @a15d1
- dbits 1 @a15d1
- groups 2
- ports 1 1
- wrmode 1 0
- enable 40 1 @a10d40
- enable 20 1 @a11d20
- enable 10 1 @a12d10
- enable 5 1 @a13d5
- enable 2 1 @a14d2
- enable 1 1 @a15d1
- transp 0 0
- clocks 2 3
- clkpol 2 3
-endbram
-
-bram $__CC_BRAM_20K_TDP
- init 1
- abits 10 @a10d20
- dbits 20 @a10d20
- abits 11 @a11d10
- dbits 10 @a11d10
- abits 12 @a12d5
- dbits 5 @a12d5
- abits 13 @a13d2
- dbits 2 @a13d2
- abits 14 @a14d1
- dbits 1 @a14d1
- groups 2
- ports 1 1
- wrmode 1 0
- enable 20 1 @a10d20
- enable 10 1 @a11d10
- enable 5 1 @a12d5
- enable 2 1 @a13d2
- enable 1 1 @a14d1
- transp 0 0
- clocks 2 3
- clkpol 2 3
-endbram
-
-match $__CC_BRAM_CASCADE
- # implicitly requested RAM or ROM
- attribute !syn_ramstyle syn_ramstyle=auto
- attribute !syn_romstyle syn_romstyle=auto
- attribute !ram_block
- attribute !rom_block
- attribute !logic_block
- min bits 512
- min efficiency 5
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_CASCADE
- # explicitly requested RAM
- attribute syn_ramstyle=block_ram ram_block
- attribute !syn_romstyle
- attribute !rom_block
- attribute !logic_block
- min wports 1
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_CASCADE
- # explicitly requested ROM
- attribute syn_romstyle=ebr rom_block
- attribute !syn_ramstyle
- attribute !ram_block
- attribute !logic_block
- max wports 0
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_SDP
- # implicitly requested RAM or ROM
- attribute !syn_ramstyle syn_ramstyle=auto
- attribute !syn_romstyle syn_romstyle=auto
- attribute !ram_block
- attribute !rom_block
- attribute !logic_block
- min bits 512
- min efficiency 5
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_SDP
- # explicitly requested RAM
- attribute syn_ramstyle=block_ram ram_block
- attribute !syn_romstyle
- attribute !rom_block
- attribute !logic_block
- min wports 1
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_SDP
- # explicitly requested ROM
- attribute syn_romstyle=ebr rom_block
- attribute !syn_ramstyle
- attribute !ram_block
- attribute !logic_block
- max wports 0
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_SDP
- # implicitly requested RAM or ROM
- attribute !syn_ramstyle syn_ramstyle=auto
- attribute !syn_romstyle syn_romstyle=auto
- attribute !ram_block
- attribute !rom_block
- attribute !logic_block
- min bits 512
- min efficiency 5
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_SDP
- # explicitly requested RAM
- attribute syn_ramstyle=block_ram ram_block
- attribute !syn_romstyle
- attribute !rom_block
- attribute !logic_block
- min wports 1
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_SDP
- # explicitly requested ROM
- attribute syn_romstyle=ebr rom_block
- attribute !syn_ramstyle
- attribute !ram_block
- attribute !logic_block
- max wports 0
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_TDP
- # implicitly requested RAM or ROM
- attribute !syn_ramstyle syn_ramstyle=auto
- attribute !syn_romstyle syn_romstyle=auto
- attribute !ram_block
- attribute !rom_block
- attribute !logic_block
- min bits 512
- min efficiency 5
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_TDP
- # explicitly requested RAM
- attribute syn_ramstyle=block_ram ram_block
- attribute !syn_romstyle
- attribute !rom_block
- attribute !logic_block
- min wports 1
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_40K_TDP
- # explicitly requested ROM
- attribute syn_romstyle=ebr rom_block
- attribute !syn_ramstyle
- attribute !ram_block
- attribute !logic_block
- max wports 0
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_TDP
- # implicitly requested RAM or ROM
- attribute !syn_ramstyle syn_ramstyle=auto
- attribute !syn_romstyle syn_romstyle=auto
- attribute !ram_block
- attribute !rom_block
- attribute !logic_block
- min bits 512
- min efficiency 5
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_TDP
- # explicitly requested RAM
- attribute syn_ramstyle=block_ram ram_block
- attribute !syn_romstyle
- attribute !rom_block
- attribute !logic_block
- min wports 1
- shuffle_enable A
- make_transp
- or_next_if_better
-endmatch
-
-match $__CC_BRAM_20K_TDP
- # explicitly requested ROM
- attribute syn_romstyle=ebr rom_block
- attribute !syn_ramstyle
- attribute !ram_block
- attribute !logic_block
- max wports 0
- shuffle_enable A
- make_transp
-endmatch
+ram block $__CC_BRAM_TDP_ {
+ option "MODE" "20K" {
+ abits 14;
+ widths 1 2 5 10 20 per_port;
+ cost 129;
+ }
+ option "MODE" "40K" {
+ abits 15;
+ widths 1 2 5 10 20 40 per_port;
+ cost 257;
+ }
+ option "MODE" "CASCADE" {
+ abits 16;
+ # hack to enforce same INIT layout as in the other modes
+ widths 1 2 5 per_port;
+ cost 513;
+ }
+ byte 1;
+ init no_undef;
+ port srsw "A" "B" {
+ clock anyedge;
+ clken;
+ option "MODE" "20K" {
+ width mix;
+ }
+ option "MODE" "40K" {
+ width mix;
+ }
+ option "MODE" "CASCADE" {
+ width mix 1;
+ }
+ portoption "WR_MODE" "NO_CHANGE" {
+ rdwr no_change;
+ }
+ portoption "WR_MODE" "WRITE_THROUGH" {
+ rdwr new;
+ wrtrans all new;
+ }
+ wrbe_separate;
+ optional_rw;
+ }
+}
+
+ram block $__CC_BRAM_SDP_ {
+ option "MODE" "20K" {
+ abits 14;
+ widths 1 2 5 10 20 40 per_port;
+ cost 129;
+ }
+ option "MODE" "40K" {
+ abits 15;
+ widths 1 2 5 10 20 40 80 per_port;
+ cost 257;
+ }
+ byte 1;
+ init no_undef;
+ port sr "R" {
+ option "MODE" "20K" {
+ width 40;
+ }
+ option "MODE" "40K" {
+ width 80;
+ }
+ clock anyedge;
+ clken;
+ optional;
+ }
+ port sw "W" {
+ option "MODE" "20K" {
+ width 40;
+ }
+ option "MODE" "40K" {
+ width 80;
+ }
+ clock anyedge;
+ clken;
+ wrbe_separate;
+ optional;
+ }
+}
diff --git a/techlibs/gatemate/brams_map.v b/techlibs/gatemate/brams_map.v
index f36f05212..171825f49 100644
--- a/techlibs/gatemate/brams_map.v
+++ b/techlibs/gatemate/brams_map.v
@@ -1,520 +1,882 @@
-/*
- * yosys -- Yosys Open SYnthesis Suite
- *
- * Copyright (C) 2021 Cologne Chip AG <support@colognechip.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- */
-
-module \$__CC_BRAM_20K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
- parameter CFG_ABITS = 14;
- parameter CFG_DBITS = 40;
- parameter CFG_ENABLE_A = 1;
- parameter CFG_ENABLE_B = 1;
-
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
-
- // 512 x 40 bit
- parameter [20479:0] INIT = 20480'b0;
-
- input CLK2;
- input CLK3;
-
- // write side of the memory
- input [15:0] A1ADDR;
- input [39:0] A1DATA;
- input [39:0] A1EN;
-
- // read side of the memory
- input [15:0] B1ADDR;
- output [39:0] B1DATA;
- input [0:0] B1EN;
-
- // unconnected signals
- wire ECC_1B_ERR, ECC_2B_ERR;
-
- // internal signals
- wire [15:0] ADDRA = {A1ADDR, 7'b0};
- wire [15:0] ADDRB = {B1ADDR, 7'b0};
-
- localparam INIT_CHUNK_SIZE = 320;
-
- function [319:0] permute_init;
- input [INIT_CHUNK_SIZE-1:0] chunk;
- integer i;
- begin
- permute_init = chunk;
- end
- endfunction
-
- CC_BRAM_20K #(
- `include "brams_init_20.vh"
- .LOC("UNPLACED"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
- .RAM_MODE("SDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .ECC_EN(1'b0)
- ) _TECHMAP_REPLACE_ (
- .A_DO(B1DATA[19:0]),
- .B_DO(B1DATA[39:20]),
- .ECC_1B_ERR(ECC_1B_ERR),
- .ECC_2B_ERR(ECC_2B_ERR),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
- .B_WE(1'b0),
- .A_ADDR(ADDRA),
- .B_ADDR(ADDRB),
- .A_DI(A1DATA[19:0]),
- .B_DI(A1DATA[39:20]),
- .A_BM(A1EN[19:0]),
- .B_BM(A1EN[39:20])
- );
-
-endmodule
-
-
-module \$__CC_BRAM_40K_SDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
- parameter CFG_ABITS = 15;
- parameter CFG_DBITS = 80;
- parameter CFG_ENABLE_A = 1;
- parameter CFG_ENABLE_B = 1;
-
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
-
- // 512 x 80 bit
- parameter [40959:0] INIT = 40960'b0;
-
- input CLK2;
- input CLK3;
-
- // write side of the memory
- input [15:0] A1ADDR;
- input [79:0] A1DATA;
- input [79:0] A1EN;
-
- // read side of the memory
- input [15:0] B1ADDR;
- output [79:0] B1DATA;
- input [0:0] B1EN;
-
- // unconnected signals
- wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
-
- // internal signals
- wire [15:0] ADDRA = {A1ADDR, 7'b0};
- wire [15:0] ADDRB = {B1ADDR, 7'b0};
-
- localparam INIT_CHUNK_SIZE = 320;
-
- function [319:0] permute_init;
- input [INIT_CHUNK_SIZE-1:0] chunk;
- integer i;
- begin
- permute_init = chunk;
- end
- endfunction
-
- CC_BRAM_40K #(
- `define INIT_LOWER
- `include "brams_init_40.vh"
- `undef INIT_LOWER
- .LOC("UNPLACED"),
- .CAS("NONE"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
- .RAM_MODE("SDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
- ) _TECHMAP_REPLACE_ (
- .A_DO(B1DATA[39:0]),
- .B_DO(B1DATA[79:40]),
- .A_ECC_1B_ERR(A_ECC_1B_ERR),
- .B_ECC_1B_ERR(B_ECC_1B_ERR),
- .A_ECC_2B_ERR(A_ECC_2B_ERR),
- .B_ECC_2B_ERR(B_ECC_2B_ERR),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
- .B_WE(1'b0),
- .A_ADDR(ADDRA),
- .B_ADDR(ADDRB),
- .A_DI(A1DATA[39:0]),
- .B_DI(A1DATA[79:40]),
- .A_BM(A1EN[39:0]),
- .B_BM(A1EN[79:40])
- );
-
-endmodule
-
-
-module \$__CC_BRAM_20K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
- parameter CFG_ABITS = 14;
- parameter CFG_DBITS = 20;
- parameter CFG_ENABLE_A = 1;
- parameter CFG_ENABLE_B = 1;
-
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
-
- // 512 x 40 bit
- parameter [20479:0] INIT = 20480'b0;
-
- input CLK2;
- input CLK3;
-
- // write side of the memory
- input [15:0] A1ADDR;
- input [19:0] A1DATA;
- input [19:0] A1EN;
-
- // read side of the memory
- input [15:0] B1ADDR;
- output [19:0] B1DATA;
- input [0:0] B1EN;
-
- // unconnected signals
- wire [19:0] A_DO;
- wire ECC_1B_ERR, ECC_2B_ERR;
-
- localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;
-
- function [319:0] permute_init;
- input [INIT_CHUNK_SIZE-1:0] chunk;
- integer i;
- begin
- if (CFG_DBITS <= 2) begin
- for (i = 0; i < 64; i = i + 1) begin
- permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
- end
- end else begin
- permute_init = chunk;
- end
- end
- endfunction
-
- // internal signals
- generate
- wire [15:0] ADDRA;
- wire [15:0] ADDRB;
-
- if (CFG_DBITS == 1) begin: blk
- assign ADDRA = {A1ADDR[13:5], 1'b0, A1ADDR[4:0], 1'b0};
- assign ADDRB = {B1ADDR[13:5], 1'b0, B1ADDR[4:0], 1'b0};
- end
- else if (CFG_DBITS == 2) begin: blk
- assign ADDRA = {A1ADDR[12:4], 1'b0, A1ADDR[3:0], 2'b0};
- assign ADDRB = {B1ADDR[12:4], 1'b0, B1ADDR[3:0], 2'b0};
- end
- else if (CFG_DBITS == 5) begin: blk
- assign ADDRA = {A1ADDR[11:3], 1'b0, A1ADDR[2:0], 3'b0};
- assign ADDRB = {B1ADDR[11:3], 1'b0, B1ADDR[2:0], 3'b0};
- end
- else if (CFG_DBITS == 10) begin: blk
- assign ADDRA = {A1ADDR[10:2], 1'b0, A1ADDR[1:0], 4'b0};
- assign ADDRB = {B1ADDR[10:2], 1'b0, B1ADDR[1:0], 4'b0};
- end
- else if (CFG_DBITS == 20) begin: blk
- assign ADDRA = {A1ADDR[9:1], 1'b0, A1ADDR[0], 5'b0};
- assign ADDRB = {B1ADDR[9:1], 1'b0, B1ADDR[0], 5'b0};
- end
-
+module $__CC_BRAM_TDP_(...);
+
+parameter INIT = 0;
+parameter OPTION_MODE = "20K";
+
+parameter PORT_A_CLK_POL = 1;
+parameter PORT_A_RD_USED = 1;
+parameter PORT_A_WR_USED = 1;
+parameter PORT_A_RD_WIDTH = 1;
+parameter PORT_A_WR_WIDTH = 1;
+parameter PORT_A_WR_BE_WIDTH = 1;
+parameter PORT_A_OPTION_WR_MODE = "NO_CHANGE";
+
+parameter PORT_B_CLK_POL = 1;
+parameter PORT_B_RD_USED = 1;
+parameter PORT_B_WR_USED = 1;
+parameter PORT_B_RD_WIDTH = 1;
+parameter PORT_B_WR_WIDTH = 1;
+parameter PORT_B_WR_BE_WIDTH = 1;
+parameter PORT_B_OPTION_WR_MODE = "NO_CHANGE";
+
+input PORT_A_CLK;
+input PORT_A_CLK_EN;
+input PORT_A_WR_EN;
+input [15:0] PORT_A_ADDR;
+input [PORT_A_WR_BE_WIDTH-1:0] PORT_A_WR_BE;
+input [PORT_A_WR_WIDTH-1:0] PORT_A_WR_DATA;
+output [PORT_A_RD_WIDTH-1:0] PORT_A_RD_DATA;
+
+input PORT_B_CLK;
+input PORT_B_CLK_EN;
+input PORT_B_WR_EN;
+input [15:0] PORT_B_ADDR;
+input [PORT_B_WR_BE_WIDTH-1:0] PORT_B_WR_BE;
+input [PORT_B_WR_WIDTH-1:0] PORT_B_WR_DATA;
+output [PORT_B_RD_WIDTH-1:0] PORT_B_RD_DATA;
+
+generate
+ if (OPTION_MODE == "20K") begin
CC_BRAM_20K #(
- `include "brams_init_20.vh"
- .LOC("UNPLACED"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .INIT_00(INIT['h00*320+:320]),
+ .INIT_01(INIT['h01*320+:320]),
+ .INIT_02(INIT['h02*320+:320]),
+ .INIT_03(INIT['h03*320+:320]),
+ .INIT_04(INIT['h04*320+:320]),
+ .INIT_05(INIT['h05*320+:320]),
+ .INIT_06(INIT['h06*320+:320]),
+ .INIT_07(INIT['h07*320+:320]),
+ .INIT_08(INIT['h08*320+:320]),
+ .INIT_09(INIT['h09*320+:320]),
+ .INIT_0A(INIT['h0a*320+:320]),
+ .INIT_0B(INIT['h0b*320+:320]),
+ .INIT_0C(INIT['h0c*320+:320]),
+ .INIT_0D(INIT['h0d*320+:320]),
+ .INIT_0E(INIT['h0e*320+:320]),
+ .INIT_0F(INIT['h0f*320+:320]),
+ .INIT_10(INIT['h10*320+:320]),
+ .INIT_11(INIT['h11*320+:320]),
+ .INIT_12(INIT['h12*320+:320]),
+ .INIT_13(INIT['h13*320+:320]),
+ .INIT_14(INIT['h14*320+:320]),
+ .INIT_15(INIT['h15*320+:320]),
+ .INIT_16(INIT['h16*320+:320]),
+ .INIT_17(INIT['h17*320+:320]),
+ .INIT_18(INIT['h18*320+:320]),
+ .INIT_19(INIT['h19*320+:320]),
+ .INIT_1A(INIT['h1a*320+:320]),
+ .INIT_1B(INIT['h1b*320+:320]),
+ .INIT_1C(INIT['h1c*320+:320]),
+ .INIT_1D(INIT['h1d*320+:320]),
+ .INIT_1E(INIT['h1e*320+:320]),
+ .INIT_1F(INIT['h1f*320+:320]),
+ .INIT_20(INIT['h20*320+:320]),
+ .INIT_21(INIT['h21*320+:320]),
+ .INIT_22(INIT['h22*320+:320]),
+ .INIT_23(INIT['h23*320+:320]),
+ .INIT_24(INIT['h24*320+:320]),
+ .INIT_25(INIT['h25*320+:320]),
+ .INIT_26(INIT['h26*320+:320]),
+ .INIT_27(INIT['h27*320+:320]),
+ .INIT_28(INIT['h28*320+:320]),
+ .INIT_29(INIT['h29*320+:320]),
+ .INIT_2A(INIT['h2a*320+:320]),
+ .INIT_2B(INIT['h2b*320+:320]),
+ .INIT_2C(INIT['h2c*320+:320]),
+ .INIT_2D(INIT['h2d*320+:320]),
+ .INIT_2E(INIT['h2e*320+:320]),
+ .INIT_2F(INIT['h2f*320+:320]),
+ .INIT_30(INIT['h30*320+:320]),
+ .INIT_31(INIT['h31*320+:320]),
+ .INIT_32(INIT['h32*320+:320]),
+ .INIT_33(INIT['h33*320+:320]),
+ .INIT_34(INIT['h34*320+:320]),
+ .INIT_35(INIT['h35*320+:320]),
+ .INIT_36(INIT['h36*320+:320]),
+ .INIT_37(INIT['h37*320+:320]),
+ .INIT_38(INIT['h38*320+:320]),
+ .INIT_39(INIT['h39*320+:320]),
+ .INIT_3A(INIT['h3a*320+:320]),
+ .INIT_3B(INIT['h3b*320+:320]),
+ .INIT_3C(INIT['h3c*320+:320]),
+ .INIT_3D(INIT['h3d*320+:320]),
+ .INIT_3E(INIT['h3e*320+:320]),
+ .INIT_3F(INIT['h3f*320+:320]),
+ .A_RD_WIDTH(PORT_A_RD_USED ? PORT_A_RD_WIDTH : 0),
+ .A_WR_WIDTH(PORT_A_WR_USED ? PORT_A_WR_WIDTH : 0),
+ .B_RD_WIDTH(PORT_B_RD_USED ? PORT_B_RD_WIDTH : 0),
+ .B_WR_WIDTH(PORT_B_WR_USED ? PORT_B_WR_WIDTH : 0),
.RAM_MODE("TDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .ECC_EN(1'b0)
+ .A_WR_MODE(PORT_A_OPTION_WR_MODE),
+ .B_WR_MODE(PORT_B_OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_A_CLK_POL),
+ .B_CLK_INV(!PORT_B_CLK_POL),
) _TECHMAP_REPLACE_ (
- .A_DO(A_DO),
- .B_DO(B1DATA),
- .ECC_1B_ERR(ECC_1B_ERR),
- .ECC_2B_ERR(ECC_2B_ERR),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
- .B_WE(1'b0),
- .A_ADDR(ADDRA),
- .B_ADDR(ADDRB),
- .A_DI(A1DATA),
- .B_DI(20'b0),
- .A_BM(A1EN),
- .B_BM(20'b0)
+ .A_CLK(PORT_A_CLK),
+ .A_EN(PORT_A_CLK_EN),
+ .A_WE(PORT_A_WR_EN),
+ .A_BM(PORT_A_WR_BE),
+ .A_DI(PORT_A_WR_DATA),
+ .A_ADDR({PORT_A_ADDR[13:5], 1'b0, PORT_A_ADDR[4:0], 1'b0}),
+ .A_DO(PORT_A_RD_DATA),
+ .B_CLK(PORT_B_CLK),
+ .B_EN(PORT_B_CLK_EN),
+ .B_WE(PORT_B_WR_EN),
+ .B_BM(PORT_B_WR_BE),
+ .B_DI(PORT_B_WR_DATA),
+ .B_ADDR({PORT_B_ADDR[13:5], 1'b0, PORT_B_ADDR[4:0], 1'b0}),
+ .B_DO(PORT_B_RD_DATA),
);
- endgenerate
-
-endmodule
-
-
-module \$__CC_BRAM_40K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
- parameter CFG_ABITS = 15;
- parameter CFG_DBITS = 40;
- parameter CFG_ENABLE_A = 1;
- parameter CFG_ENABLE_B = 1;
-
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
-
- // 512 x 80 bit
- parameter [40959:0] INIT = 40960'b0;
-
- input CLK2;
- input CLK3;
-
- // write side of the memory
- input [15:0] A1ADDR;
- input [39:0] A1DATA;
- input [39:0] A1EN;
-
- // read side of the memory
- input [15:0] B1ADDR;
- output [39:0] B1DATA;
- input [0:0] B1EN;
-
- // unconnected signals
- wire [39:0] A_DO;
- wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
-
- localparam INIT_CHUNK_SIZE = (CFG_DBITS <= 2) ? 256 : 320;
-
- function [319:0] permute_init;
- input [INIT_CHUNK_SIZE-1:0] chunk;
- integer i;
- begin
- if (CFG_DBITS <= 2) begin
- for (i = 0; i < 64; i = i + 1) begin
- permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
- end
- end else begin
- permute_init = chunk;
- end
- end
- endfunction
-
- generate
- wire [15:0] ADDRA;
- wire [15:0] ADDRB;
-
- if (CFG_DBITS == 1) begin
- assign ADDRA = {A1ADDR, 1'b0};
- assign ADDRB = {B1ADDR, 1'b0};
- end
- else if (CFG_DBITS == 2) begin
- assign ADDRA = {A1ADDR, 2'b0};
- assign ADDRB = {B1ADDR, 2'b0};
- end
- else if (CFG_DBITS == 5) begin
- assign ADDRA = {A1ADDR, 3'b0};
- assign ADDRB = {B1ADDR, 3'b0};
- end
- else if (CFG_DBITS == 10) begin
- assign ADDRA = {A1ADDR, 4'b0};
- assign ADDRB = {B1ADDR, 4'b0};
- end
- else if (CFG_DBITS == 20) begin
- assign ADDRA = {A1ADDR, 5'b0};
- assign ADDRB = {B1ADDR, 5'b0};
- end
- else if (CFG_DBITS == 40) begin
- assign ADDRA = {A1ADDR, 6'b0};
- assign ADDRB = {B1ADDR, 6'b0};
- end
-
+ end else if (OPTION_MODE == "40K") begin
CC_BRAM_40K #(
- `define INIT_LOWER
- `include "brams_init_40.vh"
- `undef INIT_LOWER
- .LOC("UNPLACED"),
- .CAS("NONE"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
+ .INIT_00(INIT['h00*320+:320]),
+ .INIT_01(INIT['h01*320+:320]),
+ .INIT_02(INIT['h02*320+:320]),
+ .INIT_03(INIT['h03*320+:320]),
+ .INIT_04(INIT['h04*320+:320]),
+ .INIT_05(INIT['h05*320+:320]),
+ .INIT_06(INIT['h06*320+:320]),
+ .INIT_07(INIT['h07*320+:320]),
+ .INIT_08(INIT['h08*320+:320]),
+ .INIT_09(INIT['h09*320+:320]),
+ .INIT_0A(INIT['h0a*320+:320]),
+ .INIT_0B(INIT['h0b*320+:320]),
+ .INIT_0C(INIT['h0c*320+:320]),
+ .INIT_0D(INIT['h0d*320+:320]),
+ .INIT_0E(INIT['h0e*320+:320]),
+ .INIT_0F(INIT['h0f*320+:320]),
+ .INIT_10(INIT['h10*320+:320]),
+ .INIT_11(INIT['h11*320+:320]),
+ .INIT_12(INIT['h12*320+:320]),
+ .INIT_13(INIT['h13*320+:320]),
+ .INIT_14(INIT['h14*320+:320]),
+ .INIT_15(INIT['h15*320+:320]),
+ .INIT_16(INIT['h16*320+:320]),
+ .INIT_17(INIT['h17*320+:320]),
+ .INIT_18(INIT['h18*320+:320]),
+ .INIT_19(INIT['h19*320+:320]),
+ .INIT_1A(INIT['h1a*320+:320]),
+ .INIT_1B(INIT['h1b*320+:320]),
+ .INIT_1C(INIT['h1c*320+:320]),
+ .INIT_1D(INIT['h1d*320+:320]),
+ .INIT_1E(INIT['h1e*320+:320]),
+ .INIT_1F(INIT['h1f*320+:320]),
+ .INIT_20(INIT['h20*320+:320]),
+ .INIT_21(INIT['h21*320+:320]),
+ .INIT_22(INIT['h22*320+:320]),
+ .INIT_23(INIT['h23*320+:320]),
+ .INIT_24(INIT['h24*320+:320]),
+ .INIT_25(INIT['h25*320+:320]),
+ .INIT_26(INIT['h26*320+:320]),
+ .INIT_27(INIT['h27*320+:320]),
+ .INIT_28(INIT['h28*320+:320]),
+ .INIT_29(INIT['h29*320+:320]),
+ .INIT_2A(INIT['h2a*320+:320]),
+ .INIT_2B(INIT['h2b*320+:320]),
+ .INIT_2C(INIT['h2c*320+:320]),
+ .INIT_2D(INIT['h2d*320+:320]),
+ .INIT_2E(INIT['h2e*320+:320]),
+ .INIT_2F(INIT['h2f*320+:320]),
+ .INIT_30(INIT['h30*320+:320]),
+ .INIT_31(INIT['h31*320+:320]),
+ .INIT_32(INIT['h32*320+:320]),
+ .INIT_33(INIT['h33*320+:320]),
+ .INIT_34(INIT['h34*320+:320]),
+ .INIT_35(INIT['h35*320+:320]),
+ .INIT_36(INIT['h36*320+:320]),
+ .INIT_37(INIT['h37*320+:320]),
+ .INIT_38(INIT['h38*320+:320]),
+ .INIT_39(INIT['h39*320+:320]),
+ .INIT_3A(INIT['h3a*320+:320]),
+ .INIT_3B(INIT['h3b*320+:320]),
+ .INIT_3C(INIT['h3c*320+:320]),
+ .INIT_3D(INIT['h3d*320+:320]),
+ .INIT_3E(INIT['h3e*320+:320]),
+ .INIT_3F(INIT['h3f*320+:320]),
+ .INIT_40(INIT['h40*320+:320]),
+ .INIT_41(INIT['h41*320+:320]),
+ .INIT_42(INIT['h42*320+:320]),
+ .INIT_43(INIT['h43*320+:320]),
+ .INIT_44(INIT['h44*320+:320]),
+ .INIT_45(INIT['h45*320+:320]),
+ .INIT_46(INIT['h46*320+:320]),
+ .INIT_47(INIT['h47*320+:320]),
+ .INIT_48(INIT['h48*320+:320]),
+ .INIT_49(INIT['h49*320+:320]),
+ .INIT_4A(INIT['h4a*320+:320]),
+ .INIT_4B(INIT['h4b*320+:320]),
+ .INIT_4C(INIT['h4c*320+:320]),
+ .INIT_4D(INIT['h4d*320+:320]),
+ .INIT_4E(INIT['h4e*320+:320]),
+ .INIT_4F(INIT['h4f*320+:320]),
+ .INIT_50(INIT['h50*320+:320]),
+ .INIT_51(INIT['h51*320+:320]),
+ .INIT_52(INIT['h52*320+:320]),
+ .INIT_53(INIT['h53*320+:320]),
+ .INIT_54(INIT['h54*320+:320]),
+ .INIT_55(INIT['h55*320+:320]),
+ .INIT_56(INIT['h56*320+:320]),
+ .INIT_57(INIT['h57*320+:320]),
+ .INIT_58(INIT['h58*320+:320]),
+ .INIT_59(INIT['h59*320+:320]),
+ .INIT_5A(INIT['h5a*320+:320]),
+ .INIT_5B(INIT['h5b*320+:320]),
+ .INIT_5C(INIT['h5c*320+:320]),
+ .INIT_5D(INIT['h5d*320+:320]),
+ .INIT_5E(INIT['h5e*320+:320]),
+ .INIT_5F(INIT['h5f*320+:320]),
+ .INIT_60(INIT['h60*320+:320]),
+ .INIT_61(INIT['h61*320+:320]),
+ .INIT_62(INIT['h62*320+:320]),
+ .INIT_63(INIT['h63*320+:320]),
+ .INIT_64(INIT['h64*320+:320]),
+ .INIT_65(INIT['h65*320+:320]),
+ .INIT_66(INIT['h66*320+:320]),
+ .INIT_67(INIT['h67*320+:320]),
+ .INIT_68(INIT['h68*320+:320]),
+ .INIT_69(INIT['h69*320+:320]),
+ .INIT_6A(INIT['h6a*320+:320]),
+ .INIT_6B(INIT['h6b*320+:320]),
+ .INIT_6C(INIT['h6c*320+:320]),
+ .INIT_6D(INIT['h6d*320+:320]),
+ .INIT_6E(INIT['h6e*320+:320]),
+ .INIT_6F(INIT['h6f*320+:320]),
+ .INIT_70(INIT['h70*320+:320]),
+ .INIT_71(INIT['h71*320+:320]),
+ .INIT_72(INIT['h72*320+:320]),
+ .INIT_73(INIT['h73*320+:320]),
+ .INIT_74(INIT['h74*320+:320]),
+ .INIT_75(INIT['h75*320+:320]),
+ .INIT_76(INIT['h76*320+:320]),
+ .INIT_77(INIT['h77*320+:320]),
+ .INIT_78(INIT['h78*320+:320]),
+ .INIT_79(INIT['h79*320+:320]),
+ .INIT_7A(INIT['h7a*320+:320]),
+ .INIT_7B(INIT['h7b*320+:320]),
+ .INIT_7C(INIT['h7c*320+:320]),
+ .INIT_7D(INIT['h7d*320+:320]),
+ .INIT_7E(INIT['h7e*320+:320]),
+ .INIT_7F(INIT['h7f*320+:320]),
+ .A_RD_WIDTH(PORT_A_RD_USED ? PORT_A_RD_WIDTH : 0),
+ .A_WR_WIDTH(PORT_A_WR_USED ? PORT_A_WR_WIDTH : 0),
+ .B_RD_WIDTH(PORT_B_RD_USED ? PORT_B_RD_WIDTH : 0),
+ .B_WR_WIDTH(PORT_B_WR_USED ? PORT_B_WR_WIDTH : 0),
.RAM_MODE("TDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
+ .A_WR_MODE(PORT_A_OPTION_WR_MODE),
+ .B_WR_MODE(PORT_B_OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_A_CLK_POL),
+ .B_CLK_INV(!PORT_B_CLK_POL),
) _TECHMAP_REPLACE_ (
- .A_DO(A_DO),
- .B_DO(B1DATA),
- .A_ECC_1B_ERR(A_ECC_1B_ERR),
- .B_ECC_1B_ERR(B_ECC_1B_ERR),
- .A_ECC_2B_ERR(A_ECC_2B_ERR),
- .B_ECC_2B_ERR(B_ECC_2B_ERR),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
- .B_WE(1'b0),
- .A_ADDR(ADDRA),
- .B_ADDR(ADDRB),
- .A_DI(A1DATA),
- .B_DI(40'b0),
- .A_BM(A1EN),
- .B_BM(40'b0)
+ .A_CLK(PORT_A_CLK),
+ .A_EN(PORT_A_CLK_EN),
+ .A_WE(PORT_A_WR_EN),
+ .A_BM(PORT_A_WR_BE),
+ .A_DI(PORT_A_WR_DATA),
+ .A_ADDR({PORT_A_ADDR[14:0], 1'b0}),
+ .A_DO(PORT_A_RD_DATA),
+ .B_CLK(PORT_B_CLK),
+ .B_EN(PORT_B_CLK_EN),
+ .B_WE(PORT_B_WR_EN),
+ .B_BM(PORT_B_WR_BE),
+ .B_DI(PORT_B_WR_DATA),
+ .B_ADDR({PORT_B_ADDR[14:0], 1'b0}),
+ .B_DO(PORT_B_RD_DATA),
);
- endgenerate
+ end else begin
+ wire CAS_A, CAS_B;
+ CC_BRAM_40K #(
+ .INIT_00(INIT['h00*320+:320]),
+ .INIT_01(INIT['h01*320+:320]),
+ .INIT_02(INIT['h02*320+:320]),
+ .INIT_03(INIT['h03*320+:320]),
+ .INIT_04(INIT['h04*320+:320]),
+ .INIT_05(INIT['h05*320+:320]),
+ .INIT_06(INIT['h06*320+:320]),
+ .INIT_07(INIT['h07*320+:320]),
+ .INIT_08(INIT['h08*320+:320]),
+ .INIT_09(INIT['h09*320+:320]),
+ .INIT_0A(INIT['h0a*320+:320]),
+ .INIT_0B(INIT['h0b*320+:320]),
+ .INIT_0C(INIT['h0c*320+:320]),
+ .INIT_0D(INIT['h0d*320+:320]),
+ .INIT_0E(INIT['h0e*320+:320]),
+ .INIT_0F(INIT['h0f*320+:320]),
+ .INIT_10(INIT['h10*320+:320]),
+ .INIT_11(INIT['h11*320+:320]),
+ .INIT_12(INIT['h12*320+:320]),
+ .INIT_13(INIT['h13*320+:320]),
+ .INIT_14(INIT['h14*320+:320]),
+ .INIT_15(INIT['h15*320+:320]),
+ .INIT_16(INIT['h16*320+:320]),
+ .INIT_17(INIT['h17*320+:320]),
+ .INIT_18(INIT['h18*320+:320]),
+ .INIT_19(INIT['h19*320+:320]),
+ .INIT_1A(INIT['h1a*320+:320]),
+ .INIT_1B(INIT['h1b*320+:320]),
+ .INIT_1C(INIT['h1c*320+:320]),
+ .INIT_1D(INIT['h1d*320+:320]),
+ .INIT_1E(INIT['h1e*320+:320]),
+ .INIT_1F(INIT['h1f*320+:320]),
+ .INIT_20(INIT['h20*320+:320]),
+ .INIT_21(INIT['h21*320+:320]),
+ .INIT_22(INIT['h22*320+:320]),
+ .INIT_23(INIT['h23*320+:320]),
+ .INIT_24(INIT['h24*320+:320]),
+ .INIT_25(INIT['h25*320+:320]),
+ .INIT_26(INIT['h26*320+:320]),
+ .INIT_27(INIT['h27*320+:320]),
+ .INIT_28(INIT['h28*320+:320]),
+ .INIT_29(INIT['h29*320+:320]),
+ .INIT_2A(INIT['h2a*320+:320]),
+ .INIT_2B(INIT['h2b*320+:320]),
+ .INIT_2C(INIT['h2c*320+:320]),
+ .INIT_2D(INIT['h2d*320+:320]),
+ .INIT_2E(INIT['h2e*320+:320]),
+ .INIT_2F(INIT['h2f*320+:320]),
+ .INIT_30(INIT['h30*320+:320]),
+ .INIT_31(INIT['h31*320+:320]),
+ .INIT_32(INIT['h32*320+:320]),
+ .INIT_33(INIT['h33*320+:320]),
+ .INIT_34(INIT['h34*320+:320]),
+ .INIT_35(INIT['h35*320+:320]),
+ .INIT_36(INIT['h36*320+:320]),
+ .INIT_37(INIT['h37*320+:320]),
+ .INIT_38(INIT['h38*320+:320]),
+ .INIT_39(INIT['h39*320+:320]),
+ .INIT_3A(INIT['h3a*320+:320]),
+ .INIT_3B(INIT['h3b*320+:320]),
+ .INIT_3C(INIT['h3c*320+:320]),
+ .INIT_3D(INIT['h3d*320+:320]),
+ .INIT_3E(INIT['h3e*320+:320]),
+ .INIT_3F(INIT['h3f*320+:320]),
+ .INIT_40(INIT['h40*320+:320]),
+ .INIT_41(INIT['h41*320+:320]),
+ .INIT_42(INIT['h42*320+:320]),
+ .INIT_43(INIT['h43*320+:320]),
+ .INIT_44(INIT['h44*320+:320]),
+ .INIT_45(INIT['h45*320+:320]),
+ .INIT_46(INIT['h46*320+:320]),
+ .INIT_47(INIT['h47*320+:320]),
+ .INIT_48(INIT['h48*320+:320]),
+ .INIT_49(INIT['h49*320+:320]),
+ .INIT_4A(INIT['h4a*320+:320]),
+ .INIT_4B(INIT['h4b*320+:320]),
+ .INIT_4C(INIT['h4c*320+:320]),
+ .INIT_4D(INIT['h4d*320+:320]),
+ .INIT_4E(INIT['h4e*320+:320]),
+ .INIT_4F(INIT['h4f*320+:320]),
+ .INIT_50(INIT['h50*320+:320]),
+ .INIT_51(INIT['h51*320+:320]),
+ .INIT_52(INIT['h52*320+:320]),
+ .INIT_53(INIT['h53*320+:320]),
+ .INIT_54(INIT['h54*320+:320]),
+ .INIT_55(INIT['h55*320+:320]),
+ .INIT_56(INIT['h56*320+:320]),
+ .INIT_57(INIT['h57*320+:320]),
+ .INIT_58(INIT['h58*320+:320]),
+ .INIT_59(INIT['h59*320+:320]),
+ .INIT_5A(INIT['h5a*320+:320]),
+ .INIT_5B(INIT['h5b*320+:320]),
+ .INIT_5C(INIT['h5c*320+:320]),
+ .INIT_5D(INIT['h5d*320+:320]),
+ .INIT_5E(INIT['h5e*320+:320]),
+ .INIT_5F(INIT['h5f*320+:320]),
+ .INIT_60(INIT['h60*320+:320]),
+ .INIT_61(INIT['h61*320+:320]),
+ .INIT_62(INIT['h62*320+:320]),
+ .INIT_63(INIT['h63*320+:320]),
+ .INIT_64(INIT['h64*320+:320]),
+ .INIT_65(INIT['h65*320+:320]),
+ .INIT_66(INIT['h66*320+:320]),
+ .INIT_67(INIT['h67*320+:320]),
+ .INIT_68(INIT['h68*320+:320]),
+ .INIT_69(INIT['h69*320+:320]),
+ .INIT_6A(INIT['h6a*320+:320]),
+ .INIT_6B(INIT['h6b*320+:320]),
+ .INIT_6C(INIT['h6c*320+:320]),
+ .INIT_6D(INIT['h6d*320+:320]),
+ .INIT_6E(INIT['h6e*320+:320]),
+ .INIT_6F(INIT['h6f*320+:320]),
+ .INIT_70(INIT['h70*320+:320]),
+ .INIT_71(INIT['h71*320+:320]),
+ .INIT_72(INIT['h72*320+:320]),
+ .INIT_73(INIT['h73*320+:320]),
+ .INIT_74(INIT['h74*320+:320]),
+ .INIT_75(INIT['h75*320+:320]),
+ .INIT_76(INIT['h76*320+:320]),
+ .INIT_77(INIT['h77*320+:320]),
+ .INIT_78(INIT['h78*320+:320]),
+ .INIT_79(INIT['h79*320+:320]),
+ .INIT_7A(INIT['h7a*320+:320]),
+ .INIT_7B(INIT['h7b*320+:320]),
+ .INIT_7C(INIT['h7c*320+:320]),
+ .INIT_7D(INIT['h7d*320+:320]),
+ .INIT_7E(INIT['h7e*320+:320]),
+ .INIT_7F(INIT['h7f*320+:320]),
+ .A_RD_WIDTH(PORT_A_RD_USED ? PORT_A_RD_WIDTH : 0),
+ .A_WR_WIDTH(PORT_A_WR_USED ? PORT_A_WR_WIDTH : 0),
+ .B_RD_WIDTH(PORT_B_RD_USED ? PORT_B_RD_WIDTH : 0),
+ .B_WR_WIDTH(PORT_B_WR_USED ? PORT_B_WR_WIDTH : 0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE(PORT_A_OPTION_WR_MODE),
+ .B_WR_MODE(PORT_B_OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_A_CLK_POL),
+ .B_CLK_INV(!PORT_B_CLK_POL),
+ .CAS("LOWER"),
+ ) lower (
+ .A_CO(CAS_A),
+ .B_CO(CAS_B),
+ .A_CLK(PORT_A_CLK),
+ .A_EN(PORT_A_CLK_EN),
+ .A_WE(PORT_A_WR_EN),
+ .A_BM(PORT_A_WR_BE),
+ .A_DI(PORT_A_WR_DATA),
+ .A_ADDR({PORT_A_ADDR[14:0], PORT_A_ADDR[15]}),
+ .B_CLK(PORT_B_CLK),
+ .B_EN(PORT_B_CLK_EN),
+ .B_WE(PORT_B_WR_EN),
+ .B_BM(PORT_B_WR_BE),
+ .B_DI(PORT_B_WR_DATA),
+ .B_ADDR({PORT_B_ADDR[14:0], PORT_B_ADDR[15]}),
+ );
+ CC_BRAM_40K #(
+ .INIT_00(INIT['h80*320+:320]),
+ .INIT_01(INIT['h81*320+:320]),
+ .INIT_02(INIT['h82*320+:320]),
+ .INIT_03(INIT['h83*320+:320]),
+ .INIT_04(INIT['h84*320+:320]),
+ .INIT_05(INIT['h85*320+:320]),
+ .INIT_06(INIT['h86*320+:320]),
+ .INIT_07(INIT['h87*320+:320]),
+ .INIT_08(INIT['h88*320+:320]),
+ .INIT_09(INIT['h89*320+:320]),
+ .INIT_0A(INIT['h8a*320+:320]),
+ .INIT_0B(INIT['h8b*320+:320]),
+ .INIT_0C(INIT['h8c*320+:320]),
+ .INIT_0D(INIT['h8d*320+:320]),
+ .INIT_0E(INIT['h8e*320+:320]),
+ .INIT_0F(INIT['h8f*320+:320]),
+ .INIT_10(INIT['h90*320+:320]),
+ .INIT_11(INIT['h91*320+:320]),
+ .INIT_12(INIT['h92*320+:320]),
+ .INIT_13(INIT['h93*320+:320]),
+ .INIT_14(INIT['h94*320+:320]),
+ .INIT_15(INIT['h95*320+:320]),
+ .INIT_16(INIT['h96*320+:320]),
+ .INIT_17(INIT['h97*320+:320]),
+ .INIT_18(INIT['h98*320+:320]),
+ .INIT_19(INIT['h99*320+:320]),
+ .INIT_1A(INIT['h9a*320+:320]),
+ .INIT_1B(INIT['h9b*320+:320]),
+ .INIT_1C(INIT['h9c*320+:320]),
+ .INIT_1D(INIT['h9d*320+:320]),
+ .INIT_1E(INIT['h9e*320+:320]),
+ .INIT_1F(INIT['h9f*320+:320]),
+ .INIT_20(INIT['ha0*320+:320]),
+ .INIT_21(INIT['ha1*320+:320]),
+ .INIT_22(INIT['ha2*320+:320]),
+ .INIT_23(INIT['ha3*320+:320]),
+ .INIT_24(INIT['ha4*320+:320]),
+ .INIT_25(INIT['ha5*320+:320]),
+ .INIT_26(INIT['ha6*320+:320]),
+ .INIT_27(INIT['ha7*320+:320]),
+ .INIT_28(INIT['ha8*320+:320]),
+ .INIT_29(INIT['ha9*320+:320]),
+ .INIT_2A(INIT['haa*320+:320]),
+ .INIT_2B(INIT['hab*320+:320]),
+ .INIT_2C(INIT['hac*320+:320]),
+ .INIT_2D(INIT['had*320+:320]),
+ .INIT_2E(INIT['hae*320+:320]),
+ .INIT_2F(INIT['haf*320+:320]),
+ .INIT_30(INIT['hb0*320+:320]),
+ .INIT_31(INIT['hb1*320+:320]),
+ .INIT_32(INIT['hb2*320+:320]),
+ .INIT_33(INIT['hb3*320+:320]),
+ .INIT_34(INIT['hb4*320+:320]),
+ .INIT_35(INIT['hb5*320+:320]),
+ .INIT_36(INIT['hb6*320+:320]),
+ .INIT_37(INIT['hb7*320+:320]),
+ .INIT_38(INIT['hb8*320+:320]),
+ .INIT_39(INIT['hb9*320+:320]),
+ .INIT_3A(INIT['hba*320+:320]),
+ .INIT_3B(INIT['hbb*320+:320]),
+ .INIT_3C(INIT['hbc*320+:320]),
+ .INIT_3D(INIT['hbd*320+:320]),
+ .INIT_3E(INIT['hbe*320+:320]),
+ .INIT_3F(INIT['hbf*320+:320]),
+ .INIT_40(INIT['hc0*320+:320]),
+ .INIT_41(INIT['hc1*320+:320]),
+ .INIT_42(INIT['hc2*320+:320]),
+ .INIT_43(INIT['hc3*320+:320]),
+ .INIT_44(INIT['hc4*320+:320]),
+ .INIT_45(INIT['hc5*320+:320]),
+ .INIT_46(INIT['hc6*320+:320]),
+ .INIT_47(INIT['hc7*320+:320]),
+ .INIT_48(INIT['hc8*320+:320]),
+ .INIT_49(INIT['hc9*320+:320]),
+ .INIT_4A(INIT['hca*320+:320]),
+ .INIT_4B(INIT['hcb*320+:320]),
+ .INIT_4C(INIT['hcc*320+:320]),
+ .INIT_4D(INIT['hcd*320+:320]),
+ .INIT_4E(INIT['hce*320+:320]),
+ .INIT_4F(INIT['hcf*320+:320]),
+ .INIT_50(INIT['hd0*320+:320]),
+ .INIT_51(INIT['hd1*320+:320]),
+ .INIT_52(INIT['hd2*320+:320]),
+ .INIT_53(INIT['hd3*320+:320]),
+ .INIT_54(INIT['hd4*320+:320]),
+ .INIT_55(INIT['hd5*320+:320]),
+ .INIT_56(INIT['hd6*320+:320]),
+ .INIT_57(INIT['hd7*320+:320]),
+ .INIT_58(INIT['hd8*320+:320]),
+ .INIT_59(INIT['hd9*320+:320]),
+ .INIT_5A(INIT['hda*320+:320]),
+ .INIT_5B(INIT['hdb*320+:320]),
+ .INIT_5C(INIT['hdc*320+:320]),
+ .INIT_5D(INIT['hdd*320+:320]),
+ .INIT_5E(INIT['hde*320+:320]),
+ .INIT_5F(INIT['hdf*320+:320]),
+ .INIT_60(INIT['he0*320+:320]),
+ .INIT_61(INIT['he1*320+:320]),
+ .INIT_62(INIT['he2*320+:320]),
+ .INIT_63(INIT['he3*320+:320]),
+ .INIT_64(INIT['he4*320+:320]),
+ .INIT_65(INIT['he5*320+:320]),
+ .INIT_66(INIT['he6*320+:320]),
+ .INIT_67(INIT['he7*320+:320]),
+ .INIT_68(INIT['he8*320+:320]),
+ .INIT_69(INIT['he9*320+:320]),
+ .INIT_6A(INIT['hea*320+:320]),
+ .INIT_6B(INIT['heb*320+:320]),
+ .INIT_6C(INIT['hec*320+:320]),
+ .INIT_6D(INIT['hed*320+:320]),
+ .INIT_6E(INIT['hee*320+:320]),
+ .INIT_6F(INIT['hef*320+:320]),
+ .INIT_70(INIT['hf0*320+:320]),
+ .INIT_71(INIT['hf1*320+:320]),
+ .INIT_72(INIT['hf2*320+:320]),
+ .INIT_73(INIT['hf3*320+:320]),
+ .INIT_74(INIT['hf4*320+:320]),
+ .INIT_75(INIT['hf5*320+:320]),
+ .INIT_76(INIT['hf6*320+:320]),
+ .INIT_77(INIT['hf7*320+:320]),
+ .INIT_78(INIT['hf8*320+:320]),
+ .INIT_79(INIT['hf9*320+:320]),
+ .INIT_7A(INIT['hfa*320+:320]),
+ .INIT_7B(INIT['hfb*320+:320]),
+ .INIT_7C(INIT['hfc*320+:320]),
+ .INIT_7D(INIT['hfd*320+:320]),
+ .INIT_7E(INIT['hfe*320+:320]),
+ .INIT_7F(INIT['hff*320+:320]),
+ .A_RD_WIDTH(PORT_A_RD_USED ? PORT_A_RD_WIDTH : 0),
+ .A_WR_WIDTH(PORT_A_WR_USED ? PORT_A_WR_WIDTH : 0),
+ .B_RD_WIDTH(PORT_B_RD_USED ? PORT_B_RD_WIDTH : 0),
+ .B_WR_WIDTH(PORT_B_WR_USED ? PORT_B_WR_WIDTH : 0),
+ .RAM_MODE("TDP"),
+ .A_WR_MODE(PORT_A_OPTION_WR_MODE),
+ .B_WR_MODE(PORT_B_OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_A_CLK_POL),
+ .B_CLK_INV(!PORT_B_CLK_POL),
+ .CAS("UPPER"),
+ ) upper (
+ .A_CI(CAS_A),
+ .B_CI(CAS_B),
+ .A_CLK(PORT_A_CLK),
+ .A_EN(PORT_A_CLK_EN),
+ .A_WE(PORT_A_WR_EN),
+ .A_BM(PORT_A_WR_BE),
+ .A_DI(PORT_A_WR_DATA),
+ .A_DO(PORT_A_RD_DATA),
+ .A_ADDR({PORT_A_ADDR[14:0], PORT_A_ADDR[15]}),
+ .B_CLK(PORT_B_CLK),
+ .B_EN(PORT_B_CLK_EN),
+ .B_WE(PORT_B_WR_EN),
+ .B_BM(PORT_B_WR_BE),
+ .B_DI(PORT_B_WR_DATA),
+ .B_DO(PORT_B_RD_DATA),
+ .B_ADDR({PORT_B_ADDR[14:0], PORT_B_ADDR[15]}),
+ );
+ end
+endgenerate
endmodule
-module \$__CC_BRAM_CASCADE (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
-
- parameter CFG_ABITS = 16;
- parameter CFG_DBITS = 1;
- parameter CFG_ENABLE_A = 1;
- parameter CFG_ENABLE_B = 1;
-
- parameter CLKPOL2 = 1;
- parameter CLKPOL3 = 1;
-
- // 64K x 1
- parameter [65535:0] INIT = 65535'b0;
-
- input CLK2;
- input CLK3;
+module $__CC_BRAM_SDP_(...);
- // write side of the memory
- input [15:0] A1ADDR;
- input [39:0] A1DATA;
- input [39:0] A1EN;
+parameter INIT = 0;
+parameter OPTION_MODE = "20K";
+parameter OPTION_WR_MODE = "NO_CHANGE";
- // read side of the memory
- input [15:0] B1ADDR;
- output [39:0] B1DATA;
- input [0:0] B1EN;
+parameter PORT_W_CLK_POL = 1;
+parameter PORT_W_USED = 1;
+parameter PORT_W_WIDTH = 40;
+parameter PORT_W_WR_BE_WIDTH = 40;
- // cascade signals
- wire A_CAS, B_CAS;
+parameter PORT_R_CLK_POL = 1;
+parameter PORT_R_USED = 1;
+parameter PORT_R_WIDTH = 40;
- // unconnected signals
- wire [39:0] A_UP_DO;
- wire A_ECC_1B_ERR, B_ECC_1B_ERR, A_ECC_2B_ERR, B_ECC_2B_ERR;
+input PORT_W_CLK;
+input PORT_W_CLK_EN;
+input PORT_W_WR_EN;
+input [15:0] PORT_W_ADDR;
+input [PORT_W_WR_BE_WIDTH-1:0] PORT_W_WR_BE;
+input [PORT_W_WIDTH-1:0] PORT_W_WR_DATA;
- localparam INIT_CHUNK_SIZE = 256;
+input PORT_R_CLK;
+input PORT_R_CLK_EN;
+input [15:0] PORT_R_ADDR;
+output [PORT_R_WIDTH-1:0] PORT_R_RD_DATA;
- function [319:0] permute_init;
- input [INIT_CHUNK_SIZE-1:0] chunk;
- integer i;
- begin
- for (i = 0; i < 64; i = i + 1) begin
- permute_init[i * 5 +: 5] = {1'b0, chunk[i * 4 +: 4]};
- end
- end
- endfunction
-
- generate
- CC_BRAM_40K #(
- `define INIT_UPPER
- `include "brams_init_40.vh" // INIT_80 .. INIT_FF
- `undef INIT_UPPER
- .LOC("UNPLACED"),
- .CAS("UPPER"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
- .RAM_MODE("TDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
- ) upper_cell (
- .A_CI(A_CAS),
- .B_CI(B_CAS),
- .A_DO(A_UP_DO),
- .B_DO(B1DATA),
- .A_ECC_1B_ERR(A_ECC_1B_ERR),
- .B_ECC_1B_ERR(B_ECC_1B_ERR),
- .A_ECC_2B_ERR(A_ECC_2B_ERR),
- .B_ECC_2B_ERR(B_ECC_2B_ERR),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
+generate
+ if (OPTION_MODE == "20K") begin
+ CC_BRAM_20K #(
+ .INIT_00(INIT['h00*320+:320]),
+ .INIT_01(INIT['h01*320+:320]),
+ .INIT_02(INIT['h02*320+:320]),
+ .INIT_03(INIT['h03*320+:320]),
+ .INIT_04(INIT['h04*320+:320]),
+ .INIT_05(INIT['h05*320+:320]),
+ .INIT_06(INIT['h06*320+:320]),
+ .INIT_07(INIT['h07*320+:320]),
+ .INIT_08(INIT['h08*320+:320]),
+ .INIT_09(INIT['h09*320+:320]),
+ .INIT_0A(INIT['h0a*320+:320]),
+ .INIT_0B(INIT['h0b*320+:320]),
+ .INIT_0C(INIT['h0c*320+:320]),
+ .INIT_0D(INIT['h0d*320+:320]),
+ .INIT_0E(INIT['h0e*320+:320]),
+ .INIT_0F(INIT['h0f*320+:320]),
+ .INIT_10(INIT['h10*320+:320]),
+ .INIT_11(INIT['h11*320+:320]),
+ .INIT_12(INIT['h12*320+:320]),
+ .INIT_13(INIT['h13*320+:320]),
+ .INIT_14(INIT['h14*320+:320]),
+ .INIT_15(INIT['h15*320+:320]),
+ .INIT_16(INIT['h16*320+:320]),
+ .INIT_17(INIT['h17*320+:320]),
+ .INIT_18(INIT['h18*320+:320]),
+ .INIT_19(INIT['h19*320+:320]),
+ .INIT_1A(INIT['h1a*320+:320]),
+ .INIT_1B(INIT['h1b*320+:320]),
+ .INIT_1C(INIT['h1c*320+:320]),
+ .INIT_1D(INIT['h1d*320+:320]),
+ .INIT_1E(INIT['h1e*320+:320]),
+ .INIT_1F(INIT['h1f*320+:320]),
+ .INIT_20(INIT['h20*320+:320]),
+ .INIT_21(INIT['h21*320+:320]),
+ .INIT_22(INIT['h22*320+:320]),
+ .INIT_23(INIT['h23*320+:320]),
+ .INIT_24(INIT['h24*320+:320]),
+ .INIT_25(INIT['h25*320+:320]),
+ .INIT_26(INIT['h26*320+:320]),
+ .INIT_27(INIT['h27*320+:320]),
+ .INIT_28(INIT['h28*320+:320]),
+ .INIT_29(INIT['h29*320+:320]),
+ .INIT_2A(INIT['h2a*320+:320]),
+ .INIT_2B(INIT['h2b*320+:320]),
+ .INIT_2C(INIT['h2c*320+:320]),
+ .INIT_2D(INIT['h2d*320+:320]),
+ .INIT_2E(INIT['h2e*320+:320]),
+ .INIT_2F(INIT['h2f*320+:320]),
+ .INIT_30(INIT['h30*320+:320]),
+ .INIT_31(INIT['h31*320+:320]),
+ .INIT_32(INIT['h32*320+:320]),
+ .INIT_33(INIT['h33*320+:320]),
+ .INIT_34(INIT['h34*320+:320]),
+ .INIT_35(INIT['h35*320+:320]),
+ .INIT_36(INIT['h36*320+:320]),
+ .INIT_37(INIT['h37*320+:320]),
+ .INIT_38(INIT['h38*320+:320]),
+ .INIT_39(INIT['h39*320+:320]),
+ .INIT_3A(INIT['h3a*320+:320]),
+ .INIT_3B(INIT['h3b*320+:320]),
+ .INIT_3C(INIT['h3c*320+:320]),
+ .INIT_3D(INIT['h3d*320+:320]),
+ .INIT_3E(INIT['h3e*320+:320]),
+ .INIT_3F(INIT['h3f*320+:320]),
+ .A_RD_WIDTH(0),
+ .A_WR_WIDTH(PORT_W_USED ? PORT_W_WIDTH : 0),
+ .B_RD_WIDTH(PORT_R_USED ? PORT_R_WIDTH : 0),
+ .B_WR_WIDTH(0),
+ .RAM_MODE("SDP"),
+ .A_WR_MODE(OPTION_WR_MODE),
+ .B_WR_MODE(OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_W_CLK_POL),
+ .B_CLK_INV(!PORT_R_CLK_POL),
+ ) _TECHMAP_REPLACE_ (
+ .A_CLK(PORT_W_CLK),
+ .A_EN(PORT_W_CLK_EN),
+ .A_WE(PORT_W_WR_EN),
+ .A_BM(PORT_W_WR_BE[19:0]),
+ .B_BM(PORT_W_WR_BE[39:20]),
+ .A_DI(PORT_W_WR_DATA[19:0]),
+ .B_DI(PORT_W_WR_DATA[39:20]),
+ .A_ADDR({PORT_W_ADDR[13:5], 1'b0, PORT_W_ADDR[4:0], 1'b0}),
+ .B_CLK(PORT_R_CLK),
+ .B_EN(PORT_R_CLK_EN),
.B_WE(1'b0),
- .A_ADDR(A1ADDR),
- .B_ADDR(B1ADDR),
- .A_DI(A1DATA),
- .B_DI(40'b0),
- .A_BM(A1EN),
- .B_BM(40'b0)
+ .B_ADDR({PORT_R_ADDR[13:5], 1'b0, PORT_R_ADDR[4:0], 1'b0}),
+ .A_DO(PORT_R_RD_DATA[19:0]),
+ .B_DO(PORT_R_RD_DATA[39:20]),
);
-
+ end else if (OPTION_MODE == "40K") begin
CC_BRAM_40K #(
- `define INIT_LOWER
- `include "brams_init_40.vh" // INIT_00 .. INIT_7F
- `undef INIT_LOWER
- .LOC("UNPLACED"),
- .CAS("LOWER"),
- .A_RD_WIDTH(0), .B_RD_WIDTH(CFG_DBITS),
- .A_WR_WIDTH(CFG_DBITS), .B_WR_WIDTH(0),
- .RAM_MODE("TDP"),
- .A_WR_MODE("NO_CHANGE"), .B_WR_MODE("NO_CHANGE"),
- .A_CLK_INV(!CLKPOL2), .B_CLK_INV(!CLKPOL3),
- .A_EN_INV(1'b0), .B_EN_INV(1'b0),
- .A_WE_INV(1'b0), .B_WE_INV(1'b0),
- .A_DO_REG(1'b0), .B_DO_REG(1'b0),
- .A_ECC_EN(1'b0), .B_ECC_EN(1'b0)
- ) lower_cell (
- .A_CI(),
- .B_CI(),
- .A_CO(A_CAS),
- .B_CO(B_CAS),
- .A_CLK(CLK2),
- .B_CLK(CLK3),
- .A_EN(1'b1),
- .B_EN(B1EN),
- .A_WE(|A1EN),
+ .INIT_00(INIT['h00*320+:320]),
+ .INIT_01(INIT['h01*320+:320]),
+ .INIT_02(INIT['h02*320+:320]),
+ .INIT_03(INIT['h03*320+:320]),
+ .INIT_04(INIT['h04*320+:320]),
+ .INIT_05(INIT['h05*320+:320]),
+ .INIT_06(INIT['h06*320+:320]),
+ .INIT_07(INIT['h07*320+:320]),
+ .INIT_08(INIT['h08*320+:320]),
+ .INIT_09(INIT['h09*320+:320]),
+ .INIT_0A(INIT['h0a*320+:320]),
+ .INIT_0B(INIT['h0b*320+:320]),
+ .INIT_0C(INIT['h0c*320+:320]),
+ .INIT_0D(INIT['h0d*320+:320]),
+ .INIT_0E(INIT['h0e*320+:320]),
+ .INIT_0F(INIT['h0f*320+:320]),
+ .INIT_10(INIT['h10*320+:320]),
+ .INIT_11(INIT['h11*320+:320]),
+ .INIT_12(INIT['h12*320+:320]),
+ .INIT_13(INIT['h13*320+:320]),
+ .INIT_14(INIT['h14*320+:320]),
+ .INIT_15(INIT['h15*320+:320]),
+ .INIT_16(INIT['h16*320+:320]),
+ .INIT_17(INIT['h17*320+:320]),
+ .INIT_18(INIT['h18*320+:320]),
+ .INIT_19(INIT['h19*320+:320]),
+ .INIT_1A(INIT['h1a*320+:320]),
+ .INIT_1B(INIT['h1b*320+:320]),
+ .INIT_1C(INIT['h1c*320+:320]),
+ .INIT_1D(INIT['h1d*320+:320]),
+ .INIT_1E(INIT['h1e*320+:320]),
+ .INIT_1F(INIT['h1f*320+:320]),
+ .INIT_20(INIT['h20*320+:320]),
+ .INIT_21(INIT['h21*320+:320]),
+ .INIT_22(INIT['h22*320+:320]),
+ .INIT_23(INIT['h23*320+:320]),
+ .INIT_24(INIT['h24*320+:320]),
+ .INIT_25(INIT['h25*320+:320]),
+ .INIT_26(INIT['h26*320+:320]),
+ .INIT_27(INIT['h27*320+:320]),
+ .INIT_28(INIT['h28*320+:320]),
+ .INIT_29(INIT['h29*320+:320]),
+ .INIT_2A(INIT['h2a*320+:320]),
+ .INIT_2B(INIT['h2b*320+:320]),
+ .INIT_2C(INIT['h2c*320+:320]),
+ .INIT_2D(INIT['h2d*320+:320]),
+ .INIT_2E(INIT['h2e*320+:320]),
+ .INIT_2F(INIT['h2f*320+:320]),
+ .INIT_30(INIT['h30*320+:320]),
+ .INIT_31(INIT['h31*320+:320]),
+ .INIT_32(INIT['h32*320+:320]),
+ .INIT_33(INIT['h33*320+:320]),
+ .INIT_34(INIT['h34*320+:320]),
+ .INIT_35(INIT['h35*320+:320]),
+ .INIT_36(INIT['h36*320+:320]),
+ .INIT_37(INIT['h37*320+:320]),
+ .INIT_38(INIT['h38*320+:320]),
+ .INIT_39(INIT['h39*320+:320]),
+ .INIT_3A(INIT['h3a*320+:320]),
+ .INIT_3B(INIT['h3b*320+:320]),
+ .INIT_3C(INIT['h3c*320+:320]),
+ .INIT_3D(INIT['h3d*320+:320]),
+ .INIT_3E(INIT['h3e*320+:320]),
+ .INIT_3F(INIT['h3f*320+:320]),
+ .INIT_40(INIT['h40*320+:320]),
+ .INIT_41(INIT['h41*320+:320]),
+ .INIT_42(INIT['h42*320+:320]),
+ .INIT_43(INIT['h43*320+:320]),
+ .INIT_44(INIT['h44*320+:320]),
+ .INIT_45(INIT['h45*320+:320]),
+ .INIT_46(INIT['h46*320+:320]),
+ .INIT_47(INIT['h47*320+:320]),
+ .INIT_48(INIT['h48*320+:320]),
+ .INIT_49(INIT['h49*320+:320]),
+ .INIT_4A(INIT['h4a*320+:320]),
+ .INIT_4B(INIT['h4b*320+:320]),
+ .INIT_4C(INIT['h4c*320+:320]),
+ .INIT_4D(INIT['h4d*320+:320]),
+ .INIT_4E(INIT['h4e*320+:320]),
+ .INIT_4F(INIT['h4f*320+:320]),
+ .INIT_50(INIT['h50*320+:320]),
+ .INIT_51(INIT['h51*320+:320]),
+ .INIT_52(INIT['h52*320+:320]),
+ .INIT_53(INIT['h53*320+:320]),
+ .INIT_54(INIT['h54*320+:320]),
+ .INIT_55(INIT['h55*320+:320]),
+ .INIT_56(INIT['h56*320+:320]),
+ .INIT_57(INIT['h57*320+:320]),
+ .INIT_58(INIT['h58*320+:320]),
+ .INIT_59(INIT['h59*320+:320]),
+ .INIT_5A(INIT['h5a*320+:320]),
+ .INIT_5B(INIT['h5b*320+:320]),
+ .INIT_5C(INIT['h5c*320+:320]),
+ .INIT_5D(INIT['h5d*320+:320]),
+ .INIT_5E(INIT['h5e*320+:320]),
+ .INIT_5F(INIT['h5f*320+:320]),
+ .INIT_60(INIT['h60*320+:320]),
+ .INIT_61(INIT['h61*320+:320]),
+ .INIT_62(INIT['h62*320+:320]),
+ .INIT_63(INIT['h63*320+:320]),
+ .INIT_64(INIT['h64*320+:320]),
+ .INIT_65(INIT['h65*320+:320]),
+ .INIT_66(INIT['h66*320+:320]),
+ .INIT_67(INIT['h67*320+:320]),
+ .INIT_68(INIT['h68*320+:320]),
+ .INIT_69(INIT['h69*320+:320]),
+ .INIT_6A(INIT['h6a*320+:320]),
+ .INIT_6B(INIT['h6b*320+:320]),
+ .INIT_6C(INIT['h6c*320+:320]),
+ .INIT_6D(INIT['h6d*320+:320]),
+ .INIT_6E(INIT['h6e*320+:320]),
+ .INIT_6F(INIT['h6f*320+:320]),
+ .INIT_70(INIT['h70*320+:320]),
+ .INIT_71(INIT['h71*320+:320]),
+ .INIT_72(INIT['h72*320+:320]),
+ .INIT_73(INIT['h73*320+:320]),
+ .INIT_74(INIT['h74*320+:320]),
+ .INIT_75(INIT['h75*320+:320]),
+ .INIT_76(INIT['h76*320+:320]),
+ .INIT_77(INIT['h77*320+:320]),
+ .INIT_78(INIT['h78*320+:320]),
+ .INIT_79(INIT['h79*320+:320]),
+ .INIT_7A(INIT['h7a*320+:320]),
+ .INIT_7B(INIT['h7b*320+:320]),
+ .INIT_7C(INIT['h7c*320+:320]),
+ .INIT_7D(INIT['h7d*320+:320]),
+ .INIT_7E(INIT['h7e*320+:320]),
+ .INIT_7F(INIT['h7f*320+:320]),
+ .A_RD_WIDTH(0),
+ .A_WR_WIDTH(PORT_W_USED ? PORT_W_WIDTH : 0),
+ .B_RD_WIDTH(PORT_R_USED ? PORT_R_WIDTH : 0),
+ .B_WR_WIDTH(0),
+ .RAM_MODE("SDP"),
+ .A_WR_MODE(OPTION_WR_MODE),
+ .B_WR_MODE(OPTION_WR_MODE),
+ .A_CLK_INV(!PORT_W_CLK_POL),
+ .B_CLK_INV(!PORT_R_CLK_POL),
+ ) _TECHMAP_REPLACE_ (
+ .A_CLK(PORT_W_CLK),
+ .A_EN(PORT_W_CLK_EN),
+ .A_WE(PORT_W_WR_EN),
+ .A_BM(PORT_W_WR_BE[39:0]),
+ .B_BM(PORT_W_WR_BE[79:40]),
+ .A_DI(PORT_W_WR_DATA[39:0]),
+ .B_DI(PORT_W_WR_DATA[79:40]),
+ .A_ADDR({PORT_W_ADDR[14:0], 1'b0}),
+ .B_CLK(PORT_R_CLK),
+ .B_EN(PORT_R_CLK_EN),
.B_WE(1'b0),
- .A_ADDR(A1ADDR),
- .B_ADDR(B1ADDR),
- .A_DI(A1DATA),
- .B_DI(40'b0),
- .A_BM(A1EN),
- .B_BM(40'b0)
+ .B_ADDR({PORT_R_ADDR[14:0], 1'b0}),
+ .A_DO(PORT_R_RD_DATA[39:0]),
+ .B_DO(PORT_R_RD_DATA[79:40]),
);
- endgenerate
+ end
+endgenerate
endmodule
diff --git a/techlibs/gatemate/cells_sim.v b/techlibs/gatemate/cells_sim.v
index 1de3d1c7a..7e88fd7cf 100644
--- a/techlibs/gatemate/cells_sim.v
+++ b/techlibs/gatemate/cells_sim.v
@@ -1409,3 +1409,47 @@ module CC_BRAM_40K (
end
endgenerate
endmodule
+
+// Models of the LUT2 tree primitives
+module CC_L2T4(
+ output O,
+ input I0, I1, I2, I3
+);
+ parameter [3:0] INIT_L00 = 4'b0000;
+ parameter [3:0] INIT_L01 = 4'b0000;
+ parameter [3:0] INIT_L10 = 4'b0000;
+
+ wire [1:0] l00_s1 = I1 ? INIT_L00[3:2] : INIT_L00[1:0];
+ wire l00 = I0 ? l00_s1[1] : l00_s1[0];
+
+ wire [1:0] l01_s1 = I3 ? INIT_L01[3:2] : INIT_L01[1:0];
+ wire l01 = I2 ? l01_s1[1] : l01_s1[0];
+
+ wire [1:0] l10_s1 = l01 ? INIT_L10[3:2] : INIT_L10[1:0];
+ assign O = l00 ? l10_s1[1] : l10_s1[0];
+
+endmodule
+
+
+module CC_L2T5(
+ output O,
+ input I0, I1, I2, I3, I4
+);
+ parameter [3:0] INIT_L02 = 4'b0000;
+ parameter [3:0] INIT_L03 = 4'b0000;
+ parameter [3:0] INIT_L11 = 4'b0000;
+ parameter [3:0] INIT_L20 = 4'b0000;
+
+ wire [1:0] l02_s1 = I1 ? INIT_L02[3:2] : INIT_L02[1:0];
+ wire l02 = I0 ? l02_s1[1] : l02_s1[0];
+
+ wire [1:0] l03_s1 = I3 ? INIT_L03[3:2] : INIT_L03[1:0];
+ wire l03 = I2 ? l03_s1[1] : l03_s1[0];
+
+ wire [1:0] l11_s1 = l03 ? INIT_L11[3:2] : INIT_L11[1:0];
+ wire l11 = l02 ? l11_s1[1] : l11_s1[0];
+
+ wire [1:0] l20_s1 = l11 ? INIT_L20[3:2] : INIT_L20[1:0];
+ assign O = I4 ? l20_s1[1] : l20_s1[0];
+
+endmodule
diff --git a/techlibs/gatemate/gatemate_foldinv.cc b/techlibs/gatemate/gatemate_foldinv.cc
new file mode 100644
index 000000000..752f8aac0
--- /dev/null
+++ b/techlibs/gatemate/gatemate_foldinv.cc
@@ -0,0 +1,219 @@
+/*
+ * yosys -- Yosys Open SYnthesis Suite
+ *
+ * Copyright (C) 2021 gatecat <gatecat@ds0.me>
+ * Copyright (C) 2021 Cologne Chip AG <support@colognechip.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "kernel/yosys.h"
+#include "kernel/sigtools.h"
+
+USING_YOSYS_NAMESPACE
+PRIVATE_NAMESPACE_BEGIN
+
+struct LUTPin {
+ int input_bit;
+ IdString init_param;
+};
+
+struct LUTType {
+ dict<IdString, LUTPin> inputs;
+ IdString output_param;
+};
+
+struct FoldInvWorker {
+ FoldInvWorker(Module *module) : module(module), sigmap(module) {};
+ Module *module;
+ SigMap sigmap;
+
+ // Mapping from inverter output to inverter input
+ dict<SigBit, SigBit> inverted_bits;
+ // Mapping from inverter input to inverter
+ dict<SigBit, Cell*> inverter_input;
+
+ const dict<IdString, LUTType> lut_types = {
+ {ID(CC_LUT2), {{
+ {ID(I0), {0, ID(INIT)}},
+ {ID(I1), {1, ID(INIT)}},
+ }, ID(INIT)}},
+ {ID(CC_L2T4), {{
+ {ID(I0), {0, ID(INIT_L00)}},
+ {ID(I1), {1, ID(INIT_L00)}},
+ {ID(I2), {0, ID(INIT_L01)}},
+ {ID(I3), {1, ID(INIT_L01)}},
+ }, ID(INIT_L10)}},
+ {ID(CC_L2T5), {{
+ {ID(I0), {0, ID(INIT_L02)}},
+ {ID(I1), {1, ID(INIT_L02)}},
+ {ID(I2), {0, ID(INIT_L03)}},
+ {ID(I3), {1, ID(INIT_L03)}},
+ {ID(I4), {0, ID(INIT_L20)}},
+ }, ID(INIT_L20)}},
+ };
+
+
+ void find_inverted_bits()
+ {
+ for (auto cell : module->selected_cells()) {
+ if (cell->type != ID($__CC_NOT))
+ continue;
+ SigBit a = sigmap(cell->getPort(ID::A)[0]);
+ SigBit y = sigmap(cell->getPort(ID::Y)[0]);
+ inverted_bits[y] = a;
+ inverter_input[a] = cell;
+ }
+ }
+
+ Const invert_lut_input(Const lut, int bit)
+ {
+ Const result(State::S0, GetSize(lut));
+ for (int i = 0; i < GetSize(lut); i++) {
+ int j = i ^ (1 << bit);
+ result[j] = lut[i];
+ }
+ return result;
+ }
+
+ Const invert_lut_output(Const lut)
+ {
+ Const result(State::S0, GetSize(lut));
+ for (int i = 0; i < GetSize(lut); i++)
+ result[i] = (lut[i] == State::S1) ? State::S0 : State::S1;
+ return result;
+ }
+
+ void fold_input_inverters()
+ {
+ for (auto cell : module->selected_cells()) {
+ auto found_type = lut_types.find(cell->type);
+ if (found_type == lut_types.end())
+ continue;
+ const auto &type = found_type->second;
+ for (const auto &ipin : type.inputs) {
+ if (!cell->hasPort(ipin.first))
+ continue;
+ auto sig = cell->getPort(ipin.first);
+ if (GetSize(sig) == 0)
+ continue;
+ SigBit bit = sigmap(sig[0]);
+ auto inv = inverted_bits.find(bit);
+ if (inv == inverted_bits.end())
+ continue; // not the output of an inverter
+ // Rewire to inverter input
+ cell->unsetPort(ipin.first);
+ cell->setPort(ipin.first, inv->second);
+ // Rewrite init
+ cell->setParam(ipin.second.init_param,
+ invert_lut_input(cell->getParam(ipin.second.init_param), ipin.second.input_bit));
+ }
+ }
+ }
+
+ void fold_output_inverters()
+ {
+ pool<SigBit> used_bits;
+ // Find bits that are actually used
+ for (auto cell : module->selected_cells()) {
+ for (auto conn : cell->connections()) {
+ if (cell->output(conn.first))
+ continue;
+ for (auto bit : sigmap(conn.second))
+ used_bits.insert(bit);
+ }
+ }
+ // Find LUTs driving inverters
+ // (create a vector to avoid iterate-and-modify issues)
+ std::vector<std::pair<Cell *, Cell*>> lut_inv;
+ for (auto cell : module->selected_cells()) {
+ auto found_type = lut_types.find(cell->type);
+ if (found_type == lut_types.end())
+ continue;
+ if (!cell->hasPort(ID::O))
+ continue;
+ auto o_sig = cell->getPort(ID::O);
+ if (GetSize(o_sig) == 0)
+ continue;
+ SigBit o = sigmap(o_sig[0]);
+ auto found_inv = inverter_input.find(o);
+ if (found_inv == inverter_input.end())
+ continue; // doesn't drive an inverter
+ lut_inv.emplace_back(cell, found_inv->second);
+ }
+ for (auto pair : lut_inv) {
+ Cell *orig_lut = pair.first;
+ Cell *inv = pair.second;
+ // Find the inverter output
+ SigBit inv_y = sigmap(inv->getPort(ID::Y)[0]);
+ // Inverter output might not actually be used; if all users were folded into inputs already
+ if (!used_bits.count(inv_y))
+ continue;
+ // Create a duplicate of the LUT with an inverted output
+ // (if the uninverted version becomes unused it will be swept away)
+ Cell *dup_lut = module->addCell(NEW_ID, orig_lut->type);
+ inv->unsetPort(ID::Y);
+ dup_lut->setPort(ID::O, inv_y);
+ for (auto conn : orig_lut->connections()) {
+ if (conn.first == ID::O)
+ continue;
+ dup_lut->setPort(conn.first, conn.second);
+ }
+ for (auto param : orig_lut->parameters) {
+ if (param.first == lut_types.at(orig_lut->type).output_param)
+ dup_lut->parameters[param.first] = invert_lut_output(param.second);
+ else
+ dup_lut->parameters[param.first] = param.second;
+ }
+ }
+ }
+
+ void operator()()
+ {
+ find_inverted_bits();
+ fold_input_inverters();
+ fold_output_inverters();
+ }
+};
+
+struct GatemateFoldInvPass : public Pass {
+ GatemateFoldInvPass() : Pass("gatemate_foldinv", "fold inverters into Gatemate LUT trees") { }
+ void help() override
+ {
+ // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
+ log("\n");
+ log(" gatemate_foldinv [selection]\n");
+ log("\n");
+ log("\n");
+ log("This pass searches for $__CC_NOT cells and folds them into CC_LUT2, CC_L2T4\n");
+ log("and CC_L2T5 cells as created by LUT tree mapping.\n");
+ log("\n");
+ }
+
+ void execute(std::vector<std::string> args, RTLIL::Design *design) override
+ {
+ log_header(design, "Executing GATEMATE_FOLDINV pass (folding LUT tree inverters).\n");
+
+ size_t argidx = 1;
+ extra_args(args, argidx, design);
+
+ for (Module *module : design->selected_modules()) {
+ FoldInvWorker worker(module);
+ worker();
+ }
+ }
+} GatemateFoldInvPass;
+
+PRIVATE_NAMESPACE_END
+
diff --git a/techlibs/gatemate/inv_map.v b/techlibs/gatemate/inv_map.v
new file mode 100644
index 000000000..8a5051747
--- /dev/null
+++ b/techlibs/gatemate/inv_map.v
@@ -0,0 +1,4 @@
+// Any inverters not folded into LUTs are mapped to a LUT of their own
+module \$__CC_NOT (input A, output Y);
+ CC_LUT1 #(.INIT(2'b01)) _TECHMAP_REPLACE_ (.I0(A), .O(Y));
+endmodule
diff --git a/techlibs/gatemate/make_lut_tree_lib.py b/techlibs/gatemate/make_lut_tree_lib.py
new file mode 100644
index 000000000..25ca88882
--- /dev/null
+++ b/techlibs/gatemate/make_lut_tree_lib.py
@@ -0,0 +1,323 @@
+#!/usr/bin/env python3
+
+class FNode:
+ def __init__(self, fun, *args):
+ self.fun = fun
+ self.args = args
+
+ if len(self.args) == 0:
+ assert fun not in ("BUF", "NOT", "AND", "OR", "XOR", "MUX")
+
+ if len(self.args) == 1:
+ assert fun in ("BUF", "NOT")
+
+ if len(self.args) == 2:
+ assert fun in ("AND", "OR", "XOR")
+
+ if len(self.args) == 3:
+ assert fun in ("MUX")
+
+ def __str__(self):
+ if len(self.args) == 0:
+ return self.fun
+ if self.fun == "NOT" and len(self.args[0].args) == 0:
+ return "!" + self.args[0].fun
+ return self.fun + "(" + ",".join([str(a) for a in self.args]) + ")"
+
+ def as_genlib_term(self):
+ if len(self.args) == 0:
+ return self.fun
+ if self.fun == "NOT":
+ assert len(self.args[0].args) == 0
+ return "!" + self.args[0].fun
+ if self.fun == "AND":
+ return "(" + self.args[0].as_genlib_term() + "*" + self.args[1].as_genlib_term() + ")"
+ if self.fun == "OR":
+ return "(" + self.args[0].as_genlib_term() + "+" + self.args[1].as_genlib_term() + ")"
+ assert False
+
+ def mapMux(self):
+ if self.fun == "MUX":
+ A, B, C = self.args
+ return OR(AND(A, NOT(C)), AND(B, C)).mapMux()
+ return FNode(self.fun, *[a.mapMux() for a in self.args])
+
+ def mapXor(self):
+ if self.fun == "XOR":
+ A, B = self.args
+ return OR(AND(A, NOT(B)), AND(NOT(A), B)).mapXor()
+ return FNode(self.fun, *[a.mapXor() for a in self.args])
+
+ def mapNot(self):
+ if self.fun == "BUF":
+ return self.arg1.mapNot()
+ if self.fun == "NOT":
+ if self.args[0].fun == "AND":
+ return OR(NOT(self.args[0].args[0]),NOT(self.args[0].args[1])).mapNot()
+ if self.args[0].fun == "OR":
+ return AND(NOT(self.args[0].args[0]),NOT(self.args[0].args[1])).mapNot()
+ if self.args[0].fun == "NOT":
+ return self.args[0].args[0].mapNot()
+ return FNode(self.fun, *[a.mapNot() for a in self.args])
+
+ def map(self):
+ n = self
+ n = n.mapMux()
+ n = n.mapXor()
+ n = n.mapNot()
+ return n
+
+ def isInv(self):
+ if len(self.args) == 0:
+ return False
+ if self.fun == "XOR":
+ return False
+ if self.fun == "NOT":
+ return self.args[0].isNonInv()
+ for a in self.args:
+ if not a.isInv():
+ return False
+ return True
+
+ def isNonInv(self):
+ if len(self.args) == 0:
+ return True
+ if self.fun == "XOR":
+ return False
+ if self.fun == "NOT":
+ return self.args[0].isInv()
+ for a in self.args:
+ if not a.isNonInv():
+ return False
+ return True
+
+A = FNode("A")
+B = FNode("B")
+C = FNode("C")
+D = FNode("D")
+E = FNode("E")
+
+def BUF(arg): return FNode("BUF", arg)
+def NOT(arg): return FNode("NOT", arg)
+def AND(arg1, arg2): return FNode("AND", arg1, arg2)
+def OR(arg1, arg2): return FNode( "OR", arg1, arg2)
+def XOR(arg1, arg2): return FNode("XOR", arg1, arg2)
+def MUX(arg1, arg2, arg3): return FNode("MUX", arg1, arg2, arg3)
+
+# Genlib Format:
+#
+# GATE <cell-name> <cell-area> <cell-logic-function>
+#
+# PIN <pin-name> <phase> <input-load> <max-load>
+# <rise-block-delay> <rise-fanout-delay>
+# <fall-block-delay> <fall-fanout-delay>
+#
+# phase:
+# INV, NONINV, or UNKNOWN
+#
+# cell-logic-function:
+# <output> = <term with *(AND), +(OR), !(NOT)>
+
+
+cells = [
+ ["$__CC_BUF", 5, A],
+ ["$__CC_NOT", 0, NOT(A)],
+ ["$__CC_MUX", 5, MUX(A, B, C)],
+]
+
+base_cells = [
+ ["$__CC2_A", AND(A, B)],
+ ["$__CC2_O", OR(A, B)],
+ ["$__CC2_X", XOR(A, B)],
+
+ ["$__CC3_AA", AND(AND(A, B), C)],
+ ["$__CC3_OO", OR( OR(A, B), C)],
+ ["$__CC3_XX", XOR(XOR(A, B), C)],
+ ["$__CC3_AO", OR(AND(A, B), C)],
+ ["$__CC3_OA", AND( OR(A, B), C)],
+ ["$__CC3_AX", XOR(AND(A, B), C)],
+ ["$__CC3_XA", AND(XOR(A, B), C)],
+
+# ["$__CC3_AAA", AND(AND(A,B),AND(A,C))],
+# ["$__CC3_AXA", XOR(AND(A,B),AND(A,C))],
+# ["$__CC3_XAX", AND(XOR(A,B),XOR(A,C))],
+# ["$__CC3_AAX", AND(AND(A,B),XOR(A,C))],
+# ["$__CC3_AXX", XOR(AND(A,B),XOR(A,C))],
+# ["$__CC3_XXX", XOR(XOR(A,B),XOR(A,C))],
+# ["$__CC3_AAO", AND(AND(A,B), OR(A,C))],
+# ["$__CC3_AOA", OR(AND(A,B),AND(A,C))],
+# ["$__CC3_AOX", OR(AND(A,B),XOR(A,C))],
+
+# ["$__CC3_AAA_N", AND(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_AXA_N", XOR(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_XAX_N", AND(XOR(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AAX_N", AND(AND(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AXX_N", XOR(AND(A,B),XOR(NOT(A),C))],
+# ["$__CC3_XXX_N", XOR(XOR(A,B),XOR(NOT(A),C))],
+# ["$__CC3_AAO_N", AND(AND(A,B), OR(NOT(A),C))],
+# ["$__CC3_AOA_N", OR(AND(A,B),AND(NOT(A),C))],
+# ["$__CC3_AOX_N", OR(AND(A,B),XOR(NOT(A),C))],
+
+ ["$__CC4_AAA", AND(AND(A,B),AND(C,D))],
+ ["$__CC4_AXA", XOR(AND(A,B),AND(C,D))],
+ ["$__CC4_XAX", AND(XOR(A,B),XOR(C,D))],
+ ["$__CC4_AAX", AND(AND(A,B),XOR(C,D))],
+ ["$__CC4_AXX", XOR(AND(A,B),XOR(C,D))],
+ ["$__CC4_XXX", XOR(XOR(A,B),XOR(C,D))],
+ ["$__CC4_AAO", AND(AND(A,B), OR(C,D))],
+ ["$__CC4_AOA", OR(AND(A,B),AND(C,D))],
+ ["$__CC4_AOX", OR(AND(A,B),XOR(C,D))],
+]
+
+for name, expr in base_cells:
+ cells.append([name, 10, expr])
+
+ name = (name
+ .replace("$__CC4_", "$__CC5_")
+ .replace("$__CC3_", "$__CC4_")
+ .replace("$__CC2_", "$__CC3_"))
+
+ # Cells such as $__CC4_AA_A are redundant, as $__CC4_AAA is equivalent
+ if name not in ("$__CC4_AA", "$__CC3_A"):
+ cells.append([name + "_A", 12, AND(E, expr)])
+ if name not in ("$__CC4_OO", "$__CC3_O"):
+ cells.append([name + "_O", 12, OR(E, expr)])
+ if name not in ("$__CC4_XX", "$__CC3_X"):
+ cells.append([name + "_X", 12, XOR(E, expr)])
+
+with open("techlibs/gatemate/lut_tree_cells.genlib", "w") as glf:
+ def mkGate(name, cost, expr, max_load=9999, block_delay = 10, fanout_delay = 5):
+ name = name.replace(" ", "")
+ expr = expr.map()
+
+ phase = "UNKNOWN"
+ if expr.isInv(): phase = "INV"
+ if expr.isNonInv(): phase = "NONINV"
+
+ print("", file=glf)
+ print("GATE %s %d Y=%s;" % (name, cost, expr.as_genlib_term()), file=glf)
+ print("PIN * %s 1 %d %d %d %d %d" % (phase, max_load, block_delay, fanout_delay, block_delay, fanout_delay), file=glf)
+ print("GATE $__ZERO 0 Y=CONST0;", file=glf)
+ print("GATE $__ONE 0 Y=CONST1;", file=glf)
+ for name, cost, expr in cells:
+ mkGate(name, cost, expr)
+
+class LUTTreeNode:
+ def __init__(self, name, width, inputs=None):
+ self.name = name
+ self.width = width
+ self.inputs = inputs
+ def is_input(self):
+ return self.width == 0
+ def map(self, expr, params, ports):
+ if self.is_input():
+ # Input to LUT tree
+ if expr is None:
+ ports[self.name] = "" # disconnected input
+ else:
+ assert(len(expr.args) == 0)
+ ports[self.name] = expr.fun
+ return
+ if expr is None:
+ # Unused part of tree
+ params[self.name] = "4'b0000"
+ for i in self.inputs:
+ i.map(None, params, ports)
+ return
+ elif len(expr.args) == 0:
+ # Input to the expression; but not LUT tree
+ # Insert a route through
+ params[self.name] = "4'b1010"
+ self.inputs[0].map(expr, params, ports)
+ for i in self.inputs[1:]:
+ i.map(None, params, ports)
+ return
+ # Map uphill LUTs; uninverting arguments and keeping track of that if needed
+ arg_inv = []
+ for (i, arg) in zip(self.inputs, expr.args):
+ if arg.fun == "NOT":
+ i.map(arg.args[0], params, ports)
+ arg_inv.append(True)
+ else:
+ i.map(arg, params, ports)
+ arg_inv.append(False)
+ # Determine base init value
+ assert self.width == 2
+ if expr.fun == "AND":
+ init = 0b1000
+ elif expr.fun == "OR":
+ init = 0b1110
+ elif expr.fun == "XOR":
+ init = 0b0110
+ else:
+ assert False, expr.fun
+ # Swap bits if init inverted
+ swapped_init = 0b0000
+ for b in range(4):
+ if ((init >> b) & 0x1) == 0: continue
+ for i in range(2):
+ if arg_inv[i]:
+ b ^= (1 << i)
+ swapped_init |= (1 << b)
+ # Set init param
+ params[self.name] = "4'b{:04b}".format(swapped_init)
+
+def LUT2(name, i0, i1): return LUTTreeNode(name, 2, [i0, i1])
+def I(name): return LUTTreeNode(name, 0)
+
+lut_prims = {
+ "CC_LUT2": LUT2("INIT", I("I0"), I("I1")),
+ "CC_L2T4": LUT2(
+ "INIT_L10",
+ LUT2("INIT_L00", I("I0"), I("I1")),
+ LUT2("INIT_L01", I("I2"), I("I3")),
+ ),
+ "CC_L2T5": LUT2(
+ "INIT_L20", I("I4"), LUT2("INIT_L11",
+ LUT2("INIT_L02", I("I0"), I("I1")),
+ LUT2("INIT_L03", I("I2"), I("I3")),
+ )
+ )
+}
+
+with open("techlibs/gatemate/lut_tree_map.v", "w") as vf:
+ # Non-automatic rules
+ print("""
+module \\$__ZERO (output Y); assign Y = 1'b0; endmodule
+module \\$__ONE (output Y); assign Y = 1'b1; endmodule
+
+module \\$__CC_BUF (input A, output Y); assign Y = A; endmodule
+
+module \\$__CC_MUX (input A, B, C, output Y);
+ CC_MX2 _TECHMAP_REPLACE_ (
+ .D0(A), .D1(B), .S0(C),
+ .Y(Y)
+ );
+endmodule
+""", file=vf)
+ for name, cost, expr in cells:
+ expr = expr.mapMux().mapNot() # Don't map XOR
+ if name in ("$__CC_BUF", "$__CC_NOT", "$__CC_MUX"):
+ # Special cases
+ continue
+ if name.startswith("$__CC2_"):
+ prim = "CC_LUT2"
+ elif name.startswith("$__CC5_") or (name.startswith("$__CC4_") and cost == 12):
+ prim = "CC_L2T5"
+ else:
+ prim = "CC_L2T4"
+ ports = {}
+ params = {}
+ lut_prims[prim].map(expr, params, ports)
+ print("", file=vf)
+ print("module \\%s (input %s, output Y);" % (name,
+ ", ".join(sorted(set(x for x in ports.values() if x)))), file=vf)
+ print(" %s #(" % prim, file=vf)
+ for k, v in sorted(params.items(), key=lambda x: x[0]):
+ print(" .%s(%s)," % (k, v), file=vf)
+ print(" ) _TECHMAP_REPLACE_ (", file=vf)
+ print(" %s," % ", ".join(".%s(%s)" % (k, v) for k, v in sorted(ports.items(), key=lambda x:x[0])),
+ file=vf)
+ print(" .O(Y)", file=vf)
+ print(" );", file=vf)
+ print("endmodule", file=vf)
diff --git a/techlibs/gatemate/synth_gatemate.cc b/techlibs/gatemate/synth_gatemate.cc
index 0131cdcdf..dd4fde643 100644
--- a/techlibs/gatemate/synth_gatemate.cc
+++ b/techlibs/gatemate/synth_gatemate.cc
@@ -67,7 +67,10 @@ struct SynthGateMatePass : public ScriptPass
log("\n");
log(" -nomx8, -nomx4\n");
log(" do not use CC_MX{8,4} multiplexer cells in output netlist.\n");
- log("\n");;
+ log("\n");
+ log(" -luttree\n");
+ log(" use new LUT tree mapping approach (EXPERIMENTAL).\n");
+ log("\n");
log(" -dff\n");
log(" run 'abc' with -dff option\n");
log("\n");
@@ -87,7 +90,7 @@ struct SynthGateMatePass : public ScriptPass
}
string top_opt, vlog_file, json_file;
- bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, dff, retime, noiopad, noclkbuf;
+ bool noflatten, nobram, noaddf, nomult, nomx4, nomx8, luttree, dff, retime, noiopad, noclkbuf;
void clear_flags() override
{
@@ -100,6 +103,7 @@ struct SynthGateMatePass : public ScriptPass
nomult = false;
nomx4 = false;
nomx8 = false;
+ luttree = false;
dff = false;
retime = false;
noiopad = false;
@@ -158,6 +162,10 @@ struct SynthGateMatePass : public ScriptPass
nomx8 = true;
continue;
}
+ if (args[argidx] == "-luttree") {
+ luttree = true;
+ continue;
+ }
if (args[argidx] == "-dff") {
dff = true;
continue;
@@ -237,12 +245,7 @@ struct SynthGateMatePass : public ScriptPass
if (check_label("map_bram", "(skip if '-nobram')") && !nobram)
{
- run("memory_bram -rules +/gatemate/brams.txt");
- run("setundef -zero -params "
- "t:$__CC_BRAM_CASCADE "
- "t:$__CC_BRAM_40K_SDP t:$__CC_BRAM_20K_SDP "
- "t:$__CC_BRAM_20K_TDP t:$__CC_BRAM_40K_TDP "
- );
+ run("memory_libmap -lib +/gatemate/brams.txt");
run("techmap -map +/gatemate/brams_map.v");
}
@@ -303,11 +306,23 @@ struct SynthGateMatePass : public ScriptPass
if (check_label("map_luts"))
{
- std::string abc_args = " -dress -lut 4";
- if (dff) {
- abc_args += " -dff";
+ if (luttree || help_mode) {
+ std::string abc_args = " -genlib +/gatemate/lut_tree_cells.genlib";
+ if (dff) {
+ abc_args += " -dff";
+ }
+ run("abc " + abc_args, "(with -luttree)");
+ run("techmap -map +/gatemate/lut_tree_map.v", "(with -luttree)");
+ run("gatemate_foldinv", "(with -luttree)");
+ run("techmap -map +/gatemate/inv_map.v", "(with -luttree)");
+ }
+ if (!luttree || help_mode) {
+ std::string abc_args = " -dress -lut 4";
+ if (dff) {
+ abc_args += " -dff";
+ }
+ run("abc " + abc_args, "(without -luttree)");
}
- run("abc " + abc_args);
run("clean");
}