mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	intel_alm: DSP inference
This commit is contained in:
		
							parent
							
								
									01772dec8c
								
							
						
					
					
						commit
						b004f09018
					
				
					 7 changed files with 209 additions and 9 deletions
				
			
		|  | @ -10,6 +10,8 @@ $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/al | ||||||
| $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v)) | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/arith_alm_map.v)) | ||||||
| $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v)) | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_map.v)) | ||||||
| $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v)) | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dff_sim.v)) | ||||||
|  | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_sim.v)) | ||||||
|  | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/dsp_map.v)) | ||||||
| $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v)) | $(eval $(call add_share_file,share/intel_alm/common,techlibs/intel_alm/common/mem_sim.v)) | ||||||
| 
 | 
 | ||||||
| # RAM
 | # RAM
 | ||||||
|  |  | ||||||
							
								
								
									
										49
									
								
								techlibs/intel_alm/common/dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								techlibs/intel_alm/common/dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | module __MUL27X27(A, B, Y); | ||||||
|  | 
 | ||||||
|  | parameter A_SIGNED = 1; | ||||||
|  | parameter B_SIGNED = 1; | ||||||
|  | parameter A_WIDTH = 27; | ||||||
|  | parameter B_WIDTH = 27; | ||||||
|  | parameter Y_WIDTH = 54; | ||||||
|  | 
 | ||||||
|  | input [A_WIDTH-1:0] A; | ||||||
|  | input [B_WIDTH-1:0] B; | ||||||
|  | output [Y_WIDTH-1:0] Y; | ||||||
|  | 
 | ||||||
|  | MISTRAL_MUL27X27 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | module __MUL18X18(A, B, Y); | ||||||
|  | 
 | ||||||
|  | parameter A_SIGNED = 1; | ||||||
|  | parameter B_SIGNED = 1; | ||||||
|  | parameter A_WIDTH = 18; | ||||||
|  | parameter B_WIDTH = 18; | ||||||
|  | parameter Y_WIDTH = 36; | ||||||
|  | 
 | ||||||
|  | input [A_WIDTH-1:0] A; | ||||||
|  | input [B_WIDTH-1:0] B; | ||||||
|  | output [Y_WIDTH-1:0] Y; | ||||||
|  | 
 | ||||||
|  | MISTRAL_MUL18X18 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | module __MUL9X9(A, B, Y); | ||||||
|  | 
 | ||||||
|  | parameter A_SIGNED = 1; | ||||||
|  | parameter B_SIGNED = 1; | ||||||
|  | parameter A_WIDTH = 9; | ||||||
|  | parameter B_WIDTH = 9; | ||||||
|  | parameter Y_WIDTH = 18; | ||||||
|  | 
 | ||||||
|  | input [A_WIDTH-1:0] A; | ||||||
|  | input [B_WIDTH-1:0] B; | ||||||
|  | output [Y_WIDTH-1:0] Y; | ||||||
|  | 
 | ||||||
|  | MISTRAL_MUL9X9 _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
							
								
								
									
										35
									
								
								techlibs/intel_alm/common/dsp_sim.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								techlibs/intel_alm/common/dsp_sim.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | (* abc9_box *) | ||||||
|  | module MISTRAL_MUL27x27(input [26:0] A, input [26:0] B, output [53:0] Y); | ||||||
|  | 
 | ||||||
|  | specify | ||||||
|  |     (A *> Y) = 4057; | ||||||
|  |     (B *> Y) = 4057; | ||||||
|  | endspecify | ||||||
|  | 
 | ||||||
|  | assign Y = $signed(A) * $signed(B); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* abc9_box *) | ||||||
|  | module MISTRAL_MUL18X18(input [17:0] A, input [17:0] B, output [35:0] Y); | ||||||
|  | 
 | ||||||
|  | specify | ||||||
|  |     (A *> Y) = 4057; | ||||||
|  |     (B *> Y) = 4057; | ||||||
|  | endspecify | ||||||
|  | 
 | ||||||
|  | assign Y = $signed(A) * $signed(B); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* abc9_box *) | ||||||
|  | module MISTRAL_MUL9X9(input [8:0] A, input [8:0] B, output [17:0] Y); | ||||||
|  | 
 | ||||||
|  | specify | ||||||
|  |     (A *> Y) = 4057; | ||||||
|  |     (B *> Y) = 4057; | ||||||
|  | endspecify | ||||||
|  | 
 | ||||||
|  | assign Y = $signed(A) * $signed(B); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | @ -129,3 +129,31 @@ output [data_width-1:0] portbdataout; | ||||||
| input ena0, clk0, clk1; | input ena0, clk0, clk1; | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module cyclonev_mac(ax, ay, resulta); | ||||||
|  | 
 | ||||||
|  | parameter ax_width = 9; | ||||||
|  | parameter ay_scan_in_width = 9; | ||||||
|  | parameter result_a_width = 18; | ||||||
|  | parameter operation_mode = "M9x9"; | ||||||
|  | 
 | ||||||
|  | input [ax_width-1:0] ax; | ||||||
|  | input [ay_scan_in_width-1:0] ay; | ||||||
|  | output [result_a_width-1:0] resulta; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | (* blackbox *) | ||||||
|  | module cyclone10gx_mac(ax, ay, resulta); | ||||||
|  | 
 | ||||||
|  | parameter ax_width = 18; | ||||||
|  | parameter ay_scan_in_width = 18; | ||||||
|  | parameter result_a_width = 36; | ||||||
|  | parameter operation_mode = "M18X18_FULL"; | ||||||
|  | 
 | ||||||
|  | input [ax_width-1:0] ax; | ||||||
|  | input [ay_scan_in_width-1:0] ay; | ||||||
|  | output [result_a_width-1:0] resulta; | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | @ -1,9 +1,11 @@ | ||||||
| `ifdef cyclonev | `ifdef cyclonev | ||||||
| `define LCELL cyclonev_lcell_comb | `define LCELL cyclonev_lcell_comb | ||||||
|  | `define MAC cyclonev_mac | ||||||
| `define MLAB cyclonev_mlab_cell | `define MLAB cyclonev_mlab_cell | ||||||
| `endif | `endif | ||||||
| `ifdef cyclone10gx | `ifdef cyclone10gx | ||||||
| `define LCELL cyclone10gx_lcell_comb | `define LCELL cyclone10gx_lcell_comb | ||||||
|  | `define MAC cyclone10gx_mac | ||||||
| `define MLAB cyclone10gx_mlab_cell | `define MLAB cyclone10gx_mlab_cell | ||||||
| `endif | `endif | ||||||
| 
 | 
 | ||||||
|  | @ -119,3 +121,24 @@ module MISTRAL_MLAB(input [4:0] A1ADDR, input A1DATA, A1EN, CLK1, input [4:0] B1 | ||||||
| ); | ); | ||||||
| 
 | 
 | ||||||
| endmodule | endmodule | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | module MISTRAL_MUL27X27(input [26:0] A, B, output [53:0] Y); | ||||||
|  | 
 | ||||||
|  | `MAC #(.ax_width(27), .ay_scan_in_width(27), .result_a_width(54), .operation_mode("M27x27")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | module MISTRAL_MUL18X18(input [17:0] A, B, output [35:0] Y); | ||||||
|  | 
 | ||||||
|  | `MAC #(.ax_width(18), .ay_scan_in_width(18), .result_a_width(36), .operation_mode("M18x18_FULL")) _TECHMAP_REPLACE_ (.ax(B), .ay(A), .resulta(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | module MISTRAL_MUL9X9(input [8:0] A, B, output [17:0] Y); | ||||||
|  | 
 | ||||||
|  | `MAC #(.ax_width(9), .ay_scan_in_width(9), .result_a_width(18), .operation_mode("M9x9")) _TECHMAP_REPLACE_ (.ax(A), .ay(B), .resulta(Y)); | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  |  | ||||||
|  | @ -69,13 +69,16 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 		log("    -nobram\n"); | 		log("    -nobram\n"); | ||||||
| 		log("        do not use block RAM cells in output netlist\n"); | 		log("        do not use block RAM cells in output netlist\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
|  | 		log("    -nodsp\n"); | ||||||
|  | 		log("        do not map multipliers to MISTRAL_MUL cells\n"); | ||||||
|  | 		log("\n"); | ||||||
| 		log("The following commands are executed by this synthesis command:\n"); | 		log("The following commands are executed by this synthesis command:\n"); | ||||||
| 		help_script(); | 		help_script(); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	string top_opt, family_opt, bram_type, vout_file; | 	string top_opt, family_opt, bram_type, vout_file; | ||||||
| 	bool flatten, quartus, nolutram, nobram, dff; | 	bool flatten, quartus, nolutram, nobram, dff, nodsp; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() override | 	void clear_flags() override | ||||||
| 	{ | 	{ | ||||||
|  | @ -88,6 +91,7 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 		nolutram = false; | 		nolutram = false; | ||||||
| 		nobram = false; | 		nobram = false; | ||||||
| 		dff = false; | 		dff = false; | ||||||
|  | 		nodsp = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) override | 	void execute(std::vector<std::string> args, RTLIL::Design *design) override | ||||||
|  | @ -130,6 +134,10 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 				nobram = true; | 				nobram = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-nodsp") { | ||||||
|  | 				nodsp = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			if (args[argidx] == "-noflatten") { | 			if (args[argidx] == "-noflatten") { | ||||||
| 				flatten = false; | 				flatten = false; | ||||||
| 				continue; | 				continue; | ||||||
|  | @ -169,9 +177,11 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("begin")) { | 		if (check_label("begin")) { | ||||||
| 			run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str())); | 			if (family_opt == "cyclonev") | ||||||
|  | 				run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str())); | ||||||
| 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str())); | 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/alm_sim.v", family_opt.c_str())); | ||||||
| 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str())); | 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dff_sim.v", family_opt.c_str())); | ||||||
|  | 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/dsp_sim.v", family_opt.c_str())); | ||||||
| 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str())); | 			run(stringf("read_verilog -specify -lib -D %s +/intel_alm/common/mem_sim.v", family_opt.c_str())); | ||||||
| 			run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str())); | 			run(stringf("read_verilog -specify -lib -D %s -icells +/intel_alm/common/abc9_model.v", family_opt.c_str())); | ||||||
| 
 | 
 | ||||||
|  | @ -181,16 +191,46 @@ struct SynthIntelALMPass : public ScriptPass { | ||||||
| 			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); | 			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str())); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (flatten && check_label("flatten", "(unless -noflatten)")) { | 		if (check_label("coarse")) { | ||||||
| 			run("proc"); | 			run("proc"); | ||||||
| 			run("flatten"); | 			if (flatten || help_mode) | ||||||
|  | 				run("flatten", "(skip if -noflatten)"); | ||||||
| 			run("tribuf -logic"); | 			run("tribuf -logic"); | ||||||
| 			run("deminout"); | 			run("deminout"); | ||||||
| 		} | 			run("opt_expr"); | ||||||
| 
 | 			run("opt_clean"); | ||||||
| 		if (check_label("coarse")) { | 			run("check"); | ||||||
| 			run("synth -run coarse -lut 6"); | 			run("opt"); | ||||||
| 			run("techmap -map +/intel_alm/common/arith_alm_map.v"); | 			run("wreduce"); | ||||||
|  | 			run("peepopt"); | ||||||
|  | 			run("opt_clean"); | ||||||
|  | 			run("share"); | ||||||
|  | 			run("techmap -map +/cmp2lut.v -D LUT_WIDTH=6"); | ||||||
|  | 			run("opt_expr"); | ||||||
|  | 			run("opt_clean"); | ||||||
|  | 			if (help_mode) { | ||||||
|  | 				run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)"); | ||||||
|  | 			} else if (!nodsp) { | ||||||
|  | 				// Cyclone V supports 9x9 multiplication, Cyclone 10 GX does not.
 | ||||||
|  | 				run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=27 -D DSP_B_MAXWIDTH=27  -D DSP_A_MINWIDTH=19 -D DSP_B_MINWIDTH=19  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL27X27"); | ||||||
|  | 				run("chtype -set $mul t:$__soft_mul"); | ||||||
|  | 				if (family_opt == "cyclonev") { | ||||||
|  | 					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=10 -D DSP_B_MINWIDTH=10  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL18X18"); | ||||||
|  | 					run("chtype -set $mul t:$__soft_mul"); | ||||||
|  | 					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=9 -D DSP_B_MAXWIDTH=9  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL9X9"); | ||||||
|  | 					run("chtype -set $mul t:$__soft_mul"); | ||||||
|  | 				} else if (family_opt == "cyclone10gx") { | ||||||
|  | 					run("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=18 -D DSP_B_MAXWIDTH=18  -D DSP_A_MINWIDTH=4 -D DSP_B_MINWIDTH=4  -D DSP_SIGNEDONLY  -D DSP_NAME=__MUL18X18"); | ||||||
|  | 					run("chtype -set $mul t:$__soft_mul"); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			run("alumacc"); | ||||||
|  | 			run("techmap -map +/intel_alm/common/arith_alm_map.v -map +/intel_alm/common/dsp_map.v"); | ||||||
|  | 			run("opt"); | ||||||
|  | 			run("fsm"); | ||||||
|  | 			run("opt -fast"); | ||||||
|  | 			run("memory -nomap"); | ||||||
|  | 			run("opt_clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!nobram && check_label("map_bram", "(skip if -nobram)")) { | 		if (!nobram && check_label("map_bram", "(skip if -nobram)")) { | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								tests/arch/intel_alm/mul.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/arch/intel_alm/mul.ys
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | read_verilog ../common/mul.v | ||||||
|  | hierarchy -top top | ||||||
|  | proc | ||||||
|  | equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclonev # equivalency check | ||||||
|  | design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||||
|  | cd top # Constrain all select calls below inside the top module | ||||||
|  | 
 | ||||||
|  | stat | ||||||
|  | 
 | ||||||
|  | select -assert-count 1 t:MISTRAL_MUL9X9 | ||||||
|  | select -assert-none t:MISTRAL_MUL9X9 %% t:* %D | ||||||
|  | 
 | ||||||
|  | design -reset | ||||||
|  | read_verilog ../common/mul.v | ||||||
|  | hierarchy -top top | ||||||
|  | proc | ||||||
|  | equiv_opt -assert -map +/intel_alm/common/dsp_sim.v synth_intel_alm -family cyclone10gx # equivalency check | ||||||
|  | design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||||
|  | cd top # Constrain all select calls below inside the top module | ||||||
|  | 
 | ||||||
|  | # Cyclone 10 GX does not have 9x9 multipliers, so we use 18x18. | ||||||
|  | select -assert-count 1 t:MISTRAL_MUL18X18 | ||||||
|  | select -assert-none t:MISTRAL_MUL18X18 %% t:* %D | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue