mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge pull request #2443 from YosysHQ/dave/nexus-mult-infer
nexus: Multiplier inference support
This commit is contained in:
		
						commit
						de58e774ef
					
				
					 4 changed files with 151 additions and 13 deletions
				
			
		|  | @ -11,4 +11,5 @@ $(eval $(call add_share_file,share/nexus,techlibs/nexus/brams_map.v)) | |||
| $(eval $(call add_share_file,share/nexus,techlibs/nexus/brams.txt)) | ||||
| $(eval $(call add_share_file,share/nexus,techlibs/nexus/arith_map.v)) | ||||
| $(eval $(call add_share_file,share/nexus,techlibs/nexus/latches_map.v)) | ||||
| $(eval $(call add_share_file,share/nexus,techlibs/nexus/dsp_map.v)) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										79
									
								
								techlibs/nexus/dsp_map.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								techlibs/nexus/dsp_map.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | |||
| module \$__NX_MUL36X36 (input [35:0] A, input [35:0] B, output [71:0] Y); | ||||
| 
 | ||||
| 	parameter A_WIDTH = 36; | ||||
| 	parameter B_WIDTH = 36; | ||||
| 	parameter Y_WIDTH = 72; | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 
 | ||||
| 	MULT36X36 #( | ||||
| 		.REGINPUTA("BYPASS"), | ||||
| 		.REGINPUTB("BYPASS"), | ||||
| 		.REGOUTPUT("BYPASS") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.A(A), .B(B), | ||||
| 		.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.Z(Y) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| module \$__NX_MUL36X18 (input [35:0] A, input [17:0] B, output [53:0] Y); | ||||
| 
 | ||||
| 	parameter A_WIDTH = 36; | ||||
| 	parameter B_WIDTH = 18; | ||||
| 	parameter Y_WIDTH = 54; | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 
 | ||||
| 	MULT18X36 #( | ||||
| 		.REGINPUTA("BYPASS"), | ||||
| 		.REGINPUTB("BYPASS"), | ||||
| 		.REGOUTPUT("BYPASS") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.A(B), .B(A), | ||||
| 		.SIGNEDA(B_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.SIGNEDB(A_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.Z(Y) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| module \$__NX_MUL18X18 (input [17:0] A, input [17:0] B, output [35:0] Y); | ||||
| 
 | ||||
| 	parameter A_WIDTH = 18; | ||||
| 	parameter B_WIDTH = 18; | ||||
| 	parameter Y_WIDTH = 36; | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 
 | ||||
| 	MULT18X18 #( | ||||
| 		.REGINPUTA("BYPASS"), | ||||
| 		.REGINPUTB("BYPASS"), | ||||
| 		.REGOUTPUT("BYPASS") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.A(A), .B(B), | ||||
| 		.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.Z(Y) | ||||
| 	); | ||||
| endmodule | ||||
| 
 | ||||
| module \$__NX_MUL9X9 (input [8:0] A, input [8:0] B, output [17:0] Y); | ||||
| 
 | ||||
| 	parameter A_WIDTH = 9; | ||||
| 	parameter B_WIDTH = 9; | ||||
| 	parameter Y_WIDTH = 18; | ||||
| 	parameter A_SIGNED = 0; | ||||
| 	parameter B_SIGNED = 0; | ||||
| 
 | ||||
| 	MULT9X9 #( | ||||
| 		.REGINPUTA("BYPASS"), | ||||
| 		.REGINPUTB("BYPASS"), | ||||
| 		.REGOUTPUT("BYPASS") | ||||
| 	) _TECHMAP_REPLACE_ ( | ||||
| 		.A(A), .B(B), | ||||
| 		.SIGNEDA(A_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.SIGNEDB(B_SIGNED ? 1'b1 : 1'b0), | ||||
| 		.Z(Y) | ||||
| 	); | ||||
| endmodule | ||||
|  | @ -89,6 +89,9 @@ struct SynthNexusPass : public ScriptPass | |||
| 		log("    -noiopad\n"); | ||||
| 		log("        do not insert IO buffers\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -nodsp\n"); | ||||
| 		log("        do not infer DSP multipliers\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -abc9\n"); | ||||
| 		log("        use new ABC9 flow (EXPERIMENTAL)\n"); | ||||
| 		log("\n"); | ||||
|  | @ -98,7 +101,7 @@ struct SynthNexusPass : public ScriptPass | |||
| 	} | ||||
| 
 | ||||
| 	string top_opt, json_file, vm_file, family; | ||||
| 	bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, flatten, dff, retime, abc9; | ||||
| 	bool noccu2, nodffe, nobram, nolutram, nowidelut, noiopad, nodsp, flatten, dff, retime, abc9; | ||||
| 
 | ||||
| 	void clear_flags() override | ||||
| 	{ | ||||
|  | @ -112,6 +115,7 @@ struct SynthNexusPass : public ScriptPass | |||
| 		nolutram = false; | ||||
| 		nowidelut = false; | ||||
| 		noiopad = false; | ||||
| 		nodsp = false; | ||||
| 		flatten = true; | ||||
| 		dff = false; | ||||
| 		retime = false; | ||||
|  | @ -161,6 +165,10 @@ struct SynthNexusPass : public ScriptPass | |||
| 				dff = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-nodsp") { | ||||
| 				nodsp = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-retime") { | ||||
| 				retime = true; | ||||
| 				continue; | ||||
|  | @ -211,6 +219,22 @@ struct SynthNexusPass : public ScriptPass | |||
| 		log_pop(); | ||||
| 	} | ||||
| 
 | ||||
| 	struct DSPRule { | ||||
| 		int a_maxwidth; | ||||
| 		int b_maxwidth; | ||||
| 		int a_minwidth; | ||||
| 		int b_minwidth; | ||||
| 		std::string prim; | ||||
| 	}; | ||||
| 
 | ||||
| 	const std::vector<DSPRule> dsp_rules = { | ||||
| 		{36, 36, 22, 22, "$__NX_MUL36X36"}, | ||||
| 		{36, 18, 22, 10, "$__NX_MUL36X18"}, | ||||
| 		{18, 18, 10,  4, "$__NX_MUL18X18"}, | ||||
| 		{18, 18,  4, 10, "$__NX_MUL18X18"}, | ||||
| 		{ 9,  9,  4,  4, "$__NX_MUL9X9"}, | ||||
| 	}; | ||||
| 
 | ||||
| 	void script() override | ||||
| 	{ | ||||
| 
 | ||||
|  | @ -244,6 +268,18 @@ struct SynthNexusPass : public ScriptPass | |||
| 			run("opt_expr"); | ||||
| 			run("opt_clean"); | ||||
| 
 | ||||
| 			if (help_mode) { | ||||
| 				run("techmap -map +/mul2dsp.v [...]", "(unless -nodsp)"); | ||||
| 				run("techmap -map +/nexus/dsp_map.v", "(unless -nodsp)"); | ||||
| 			} else if (!nodsp) { | ||||
| 				for (const auto &rule : dsp_rules) { | ||||
| 					run(stringf("techmap -map +/mul2dsp.v -D DSP_A_MAXWIDTH=%d -D DSP_B_MAXWIDTH=%d -D DSP_A_MINWIDTH=%d -D DSP_B_MINWIDTH=%d -D DSP_NAME=%s", | ||||
| 						rule.a_maxwidth, rule.b_maxwidth, rule.a_minwidth, rule.b_minwidth, rule.prim.c_str())); | ||||
| 					run("chtype -set $mul t:$__soft_mul"); | ||||
| 				} | ||||
| 				run("techmap -map +/nexus/dsp_map.v"); | ||||
| 			} | ||||
| 
 | ||||
| 			run("alumacc"); | ||||
| 			run("opt"); | ||||
| 			run("memory -nomap"); | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| read_verilog ../common/mul.v | ||||
| chparam -set X_WIDTH 8 -set Y_WIDTH 8 -set A_WIDTH 16 | ||||
| hierarchy -top top | ||||
| proc | ||||
| 
 | ||||
|  | @ -7,22 +8,43 @@ design -save read | |||
| equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus | ||||
| 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 | ||||
| select -assert-count 7 t:CCU2 | ||||
| select -assert-max 5 t:WIDEFN9 | ||||
| select -assert-max 62 t:LUT4 | ||||
| select -assert-count 1 t:MULT9X9 | ||||
| 
 | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:MULT9X9 %% t:* %D | ||||
| 
 | ||||
| design -load read | ||||
| 
 | ||||
| equiv_opt -assert -map +/nexus/cells_sim.v synth_nexus -abc9 | ||||
| design -load postopt # load the post-opt design (otherwise equiv_opt loads the pre-opt design) | ||||
| design -reset | ||||
| read_verilog ../common/mul.v | ||||
| chparam -set X_WIDTH 16 -set Y_WIDTH 16 -set A_WIDTH 32 | ||||
| hierarchy -top top | ||||
| proc | ||||
| # equivalence checking is too slow here | ||||
| synth_nexus | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:MULT18X18 | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X18 %% t:* %D | ||||
| 
 | ||||
| stat | ||||
| 
 | ||||
| select -assert-count 7 t:CCU2 | ||||
| select -assert-max 12 t:WIDEFN9 | ||||
| select -assert-max 58 t:LUT4 | ||||
| design -reset | ||||
| read_verilog ../common/mul.v | ||||
| chparam -set X_WIDTH 32 -set Y_WIDTH 16 -set A_WIDTH 48 | ||||
| hierarchy -top top | ||||
| proc | ||||
| # equivalence checking is too slow here | ||||
| synth_nexus | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:MULT18X36 | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:MULT18X36 %% t:* %D | ||||
| 
 | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:LUT4 t:CCU2 t:WIDEFN9 %% t:* %D | ||||
| 
 | ||||
| design -reset | ||||
| read_verilog ../common/mul.v | ||||
| chparam -set X_WIDTH 32 -set Y_WIDTH 32 -set A_WIDTH 64 | ||||
| hierarchy -top top | ||||
| proc | ||||
| # equivalence checking is too slow here | ||||
| synth_nexus | ||||
| cd top # Constrain all select calls below inside the top module | ||||
| select -assert-count 1 t:MULT36X36 | ||||
| 
 | ||||
| select -assert-none t:IB t:OB t:VLO t:VHI t:MULT36X36 %% t:* %D | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue