From: Icenowy Zheng Date: Fri, 17 Dec 2021 12:25:32 +0000 (+0800) Subject: anlogic: support BRAM mapping X-Git-Tag: yosys-0.14~27^2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c2b7ad3b28ebd7865c8b2e795b2942d5d1bd00f5;p=yosys.git anlogic: support BRAM mapping Anlogic FPGAs all have two kinds of BRAMs, one is 9bit*1K when being true dual port (or 18bit*512 when simple dual port), the other is 16bit*2K. Supports mapping of these two kinds of BRAMs. 9Kbit BRAM in SDP mode and 32Kbit BRAM with 8bit width are not support yet. Signed-off-by: Icenowy Zheng --- diff --git a/techlibs/anlogic/.gitignore b/techlibs/anlogic/.gitignore new file mode 100644 index 000000000..d127107db --- /dev/null +++ b/techlibs/anlogic/.gitignore @@ -0,0 +1,2 @@ +brams_init.mk +brams_init_*.vh diff --git a/techlibs/anlogic/Makefile.inc b/techlibs/anlogic/Makefile.inc index 2d8d65e2e..79519c645 100644 --- a/techlibs/anlogic/Makefile.inc +++ b/techlibs/anlogic/Makefile.inc @@ -3,6 +3,22 @@ OBJS += techlibs/anlogic/synth_anlogic.o OBJS += techlibs/anlogic/anlogic_eqn.o OBJS += techlibs/anlogic/anlogic_fixcarry.o +GENFILES += techlibs/anlogic/brams_init_16.vh +GENFILES += techlibs/anlogic/brams_init_9.vh +GENFILES += techlibs/anlogic/brams_init_8.vh + +EXTRA_OBJS += techlibs/anlogic/brams_init.mk +.SECONDARY: techlibs/anlogic/brams_init.mk + +techlibs/anlogic/brams_init.mk: techlibs/anlogic/brams_init.py + $(Q) mkdir -p techlibs/anlogic + $(P) $(PYTHON_EXECUTABLE) $< + $(Q) touch $@ + +techlibs/anlogic/brams_init_16.vh: techlibs/anlogic/brams_init.mk +techlibs/anlogic/brams_init_9.vh: techlibs/anlogic/brams_init.mk +techlibs/anlogic/brams_init_8.vh: techlibs/anlogic/brams_init.mk + $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/arith_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/cells_sim.v)) @@ -10,3 +26,9 @@ $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/eagle_bb.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams.txt)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutrams_map.v)) $(eval $(call add_share_file,share/anlogic,techlibs/anlogic/lutram_init_16x4.vh)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams.txt)) +$(eval $(call add_share_file,share/anlogic,techlibs/anlogic/brams_map.v)) + +$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_16.vh)) +$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_9.vh)) +$(eval $(call add_gen_share_file,share/anlogic,techlibs/anlogic/brams_init_8.vh)) diff --git a/techlibs/anlogic/brams.txt b/techlibs/anlogic/brams.txt new file mode 100644 index 000000000..817d7d6f4 --- /dev/null +++ b/techlibs/anlogic/brams.txt @@ -0,0 +1,45 @@ +bram $__ANLOGIC_BRAM9K_TDP + init 1 + abits 13 @a13d1 + dbits 1 @a13d1 + abits 12 @a12d2 + dbits 2 @a12d2 + abits 11 @a11d4 + dbits 4 @a11d4 + abits 10 @a10d8 + dbits 8 @a10d8 + abits 10 @a10d9 + dbits 9 @a10d9 + groups 2 + ports 1 1 + wrmode 0 1 + enable 1 1 + transp 2 0 + clocks 2 3 + clkpol 2 3 +endbram + +bram $__ANLOGIC_BRAM32K + init 1 + abits 11 + dbits 16 + groups 2 + ports 1 1 + wrmode 0 1 + enable 1 2 + transp 0 0 + clocks 2 3 + clkpol 2 3 +endbram + +match $__ANLOGIC_BRAM32K + min efficiency 30 + shuffle_enable B + make_transp + or_next_if_better +endmatch + +match $__ANLOGIC_BRAM9K_TDP + min efficiency 5 + make_transp +endmatch diff --git a/techlibs/anlogic/brams_init.py b/techlibs/anlogic/brams_init.py new file mode 100644 index 000000000..8dda0d33e --- /dev/null +++ b/techlibs/anlogic/brams_init.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +with open("techlibs/anlogic/brams_init_9.vh", "w") as f: + for i in range(4): + init_snippets = [" INIT[%3d*9+8]" % (k+256*i,) for k in range(255, -1, -1)] + for k in range(4, 256, 4): + init_snippets[k] = "\n " + init_snippets[k] + print(".INITP_%02X({%s})," % (i, ",".join(init_snippets)), file=f) + for i in range(32): + init_snippets = [" INIT[%3d*9 +: 8]" % (k+32*i,) for k in range(31, -1, -1)] + for k in range(4, 32, 4): + init_snippets[k] = "\n " + init_snippets[k] + print(".INIT_%02X({%s})," % (i, ",".join(init_snippets)), file=f) + +with open("techlibs/anlogic/brams_init_8.vh", "w") as f: + for i in range(32): + print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f) + +with open("techlibs/anlogic/brams_init_16.vh", "w") as f: + for i in range(128): + print(".INIT_%02X(INIT[%3d*256 +: 256])," % (i, i), file=f) diff --git a/techlibs/anlogic/brams_map.v b/techlibs/anlogic/brams_map.v new file mode 100644 index 000000000..ee02b6d7c --- /dev/null +++ b/techlibs/anlogic/brams_map.v @@ -0,0 +1,162 @@ +module \$__ANLOGIC_BRAM9K_TDP (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 10; + parameter CFG_DBITS = 9; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [9215:0] INIT = 9216'bx; + parameter TRANSP2 = 0; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + output [CFG_DBITS-1:0] A1DATA; + input A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + input [CFG_DBITS-1:0] B1DATA; + input B1EN; + + localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV"; + localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV"; + + localparam WRITEMODE_B = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE"; + + localparam DATA_WIDTH = CFG_DBITS == 1 ? "1" : + (CFG_DBITS == 2 ? "2" : + (CFG_DBITS <= 4 ? "4" : "9")); + + localparam APADBITS = $clog2(CFG_DBITS == 9 ? 8 : CFG_DBITS); + + wire [12:0] addra; + wire [12:0] addrb; + + assign addra[12:APADBITS] = A1ADDR; + assign addrb[12:APADBITS] = B1ADDR; + + wire [8:0] doa; + wire [8:0] dib; + + assign A1DATA[CFG_DBITS-1:0] = doa; + assign dib[CFG_DBITS-1:0] = B1DATA; + + generate if (CFG_DBITS == 9) begin + EG_PHY_BRAM #( + .MODE("DP8K"), + .DATA_WIDTH_A(DATA_WIDTH), + .DATA_WIDTH_B(DATA_WIDTH), + .READBACK("OFF"), + .REGMODE_A("NOREG"), + .REGMODE_B("NOREG"), + .WRITEMODE_A("READBEFOREWRITE"), + .WRITEMODE_B(WRITEMODE_B), + .RESETMODE("ASYNC"), + .CEAMUX("SIG"), .CEBMUX("SIG"), + .OCEAMUX("1"), .OCEBMUX("1"), + .RSTAMUX("0"), .RSTBMUX("0"), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WEAMUX("0"), .WEBMUX("SIG"), + .CSA0("1"), .CSA1("1"), + .CSA2("1"), .CSB0("1"), + .CSB1("1"), .CSB2("1"), + `include "brams_init_9.vh" + ) _TECHMAP_REPLACE_ ( + .doa(doa), .dib(dib), + .addra(addra), .addrb(addrb), + .clka(CLK2), .clkb(CLK3), + .cea(A1EN), .ceb(B1EN), + .ocea(1'b1), .oceb(1'b1), + .rsta(1'b0), .rstb(1'b0), + .wea(1'b0), .web(B1EN), + .csa(3'b111), .csb(3'b111) + ); + end else begin + EG_PHY_BRAM #( + .MODE("DP8K"), + .DATA_WIDTH_A(DATA_WIDTH), + .DATA_WIDTH_B(DATA_WIDTH), + .READBACK("OFF"), + .REGMODE_A("NOREG"), + .REGMODE_B("NOREG"), + .WRITEMODE_A("READBEFOREWRITE"), + .WRITEMODE_B(WRITEMODE_B), + .RESETMODE("ASYNC"), + .CEAMUX("SIG"), .CEBMUX("SIG"), + .OCEAMUX("1"), .OCEBMUX("1"), + .RSTAMUX("0"), .RSTBMUX("0"), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WEAMUX("0"), .WEBMUX("SIG"), + .CSA0("1"), .CSA1("1"), + .CSA2("1"), .CSB0("1"), + .CSB1("1"), .CSB2("1"), + `include "brams_init_8.vh" + ) _TECHMAP_REPLACE_ ( + .doa(doa), .dib(dib), + .addra(addra), .addrb(addrb), + .clka(CLK2), .clkb(CLK3), + .cea(A1EN), .ceb(B1EN), + .ocea(1'b1), .oceb(1'b1), + .rsta(1'b0), .rstb(1'b0), + .wea(1'b0), .web(B1EN), + .csa(3'b111), .csb(3'b111) + ); + end endgenerate +endmodule + +module \$__ANLOGIC_BRAM32K (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN); + parameter CFG_ABITS = 11; + parameter CFG_DBITS = 16; + + parameter CLKPOL2 = 1; + parameter CLKPOL3 = 1; + parameter [32767:0] INIT = 32768'bx; + + input CLK2; + input CLK3; + + input [CFG_ABITS-1:0] A1ADDR; + output [CFG_DBITS-1:0] A1DATA; + input A1EN; + + input [CFG_ABITS-1:0] B1ADDR; + input [CFG_DBITS-1:0] B1DATA; + input [1:0] B1EN; + + localparam CLKAMUX = CLKPOL2 ? "SIG" : "INV"; + localparam CLKBMUX = CLKPOL3 ? "SIG" : "INV"; + + wire byteweb = B1EN[1] ^ B1EN[0]; + wire byteb = B1EN[1]; + + EG_PHY_BRAM32K #( + .MODE("DP16K"), + .DATA_WIDTH_A("16"), + .DATA_WIDTH_B("16"), + .REGMODE_A("NOREG"), + .REGMODE_B("NOREG"), + .WRITEMODE_A("NORMAL"), + .WRITEMODE_B("NORMAL"), + .SRMODE("ASYNC"), + .CSAMUX("SIG"), .CSBMUX("SIG"), + .OCEAMUX("1"), .OCEBMUX("1"), + .RSTAMUX("0"), .RSTBMUX("0"), + .CLKAMUX(CLKAMUX), + .CLKBMUX(CLKBMUX), + .WEAMUX("0"), .WEBMUX("SIG"), + .READBACK("OFF"), + `include "brams_init_16.vh" + ) _TECHMAP_REPLACE_ ( + .doa(A1DATA), .dib(B1DATA), + .addra(A1ADDR), .addrb(B1ADDR), + .bytea(1'b0), .byteb(byteb), + .bytewea(1'b0), .byteweb(byteweb), + .csa(A1EN), .csb(|B1EN), + .wea(1'b0), .web(|B1EN), + .clka(CLK2), .clkb(CLK3), + .rsta(1'b0), .rstb(1'b0), + .ocea(1'b1), .oceb(1'b1) + ); +endmodule diff --git a/techlibs/anlogic/synth_anlogic.cc b/techlibs/anlogic/synth_anlogic.cc index 039cae00e..5da14c26b 100644 --- a/techlibs/anlogic/synth_anlogic.cc +++ b/techlibs/anlogic/synth_anlogic.cc @@ -63,6 +63,9 @@ struct SynthAnlogicPass : public ScriptPass log(" -nolutram\n"); log(" do not use EG_LOGIC_DRAM16X4 cells in output netlist\n"); log("\n"); + log(" -nobram\n"); + log(" do not use EG_PHY_BRAM or EG_PHY_BRAM32K cells in output netlist\n"); + log("\n"); log("\n"); log("The following commands are executed by this synthesis command:\n"); help_script(); @@ -70,7 +73,7 @@ struct SynthAnlogicPass : public ScriptPass } string top_opt, edif_file, json_file; - bool flatten, retime, nolutram; + bool flatten, retime, nolutram, nobram; void clear_flags() override { @@ -80,6 +83,7 @@ struct SynthAnlogicPass : public ScriptPass flatten = true; retime = false; nolutram = false; + nobram = false; } void execute(std::vector args, RTLIL::Design *design) override @@ -118,6 +122,10 @@ struct SynthAnlogicPass : public ScriptPass nolutram = true; continue; } + if (args[argidx] == "-nobram") { + nobram = true; + continue; + } if (args[argidx] == "-retime") { retime = true; continue; @@ -158,6 +166,14 @@ struct SynthAnlogicPass : public ScriptPass run("synth -run coarse"); } + if (!nobram && check_label("map_bram", "(skip if -nobram)")) + { + run("memory_bram -rules +/anlogic/brams.txt"); + run("techmap -map +/anlogic/brams_map.v"); + run("setundef -zero -params t:EG_PHY_BRAM"); + run("setundef -zero -params t:EG_PHY_BRAM32K"); + } + if (!nolutram && check_label("map_lutram", "(skip if -nolutram)")) { run("memory_bram -rules +/anlogic/lutrams.txt"); diff --git a/tests/arch/anlogic/blockram.ys b/tests/arch/anlogic/blockram.ys new file mode 100644 index 000000000..da23409ba --- /dev/null +++ b/tests/arch/anlogic/blockram.ys @@ -0,0 +1,13 @@ +read_verilog ../common/blockram.v +hierarchy -top sync_ram_sp +proc +memory -nomap +equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic +memory +opt -full + +design -load postopt +cd sync_ram_sp + +select -assert-count 1 t:EG_PHY_BRAM +select -assert-none t:EG_PHY_BRAM %% t:* %D diff --git a/tests/arch/anlogic/lutram.ys b/tests/arch/anlogic/lutram.ys index 6dbdbdac3..fe6135c73 100644 --- a/tests/arch/anlogic/lutram.ys +++ b/tests/arch/anlogic/lutram.ys @@ -2,7 +2,7 @@ read_verilog ../common/lutram.v hierarchy -top lutram_1w1r proc memory -nomap -equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic +equiv_opt -run :prove -map +/anlogic/cells_sim.v synth_anlogic -nobram memory opt -full