mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 19:52:31 +00:00 
			
		
		
		
	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 <icenowy@aosc.io>
This commit is contained in:
		
							parent
							
								
									60c3ea367c
								
							
						
					
					
						commit
						c2b7ad3b28
					
				
					 8 changed files with 283 additions and 2 deletions
				
			
		
							
								
								
									
										2
									
								
								techlibs/anlogic/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								techlibs/anlogic/.gitignore
									
										
									
									
										vendored
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| brams_init.mk | ||||
| brams_init_*.vh | ||||
|  | @ -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)) | ||||
|  |  | |||
							
								
								
									
										45
									
								
								techlibs/anlogic/brams.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								techlibs/anlogic/brams.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
							
								
								
									
										21
									
								
								techlibs/anlogic/brams_init.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								techlibs/anlogic/brams_init.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -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) | ||||
							
								
								
									
										162
									
								
								techlibs/anlogic/brams_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								techlibs/anlogic/brams_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
|  | @ -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<std::string> 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"); | ||||
|  |  | |||
							
								
								
									
										13
									
								
								tests/arch/anlogic/blockram.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tests/arch/anlogic/blockram.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -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 | ||||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue