mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Pack partial-product adder DSP48E1 packing
This commit is contained in:
		
							parent
							
								
									a002eba14a
								
							
						
					
					
						commit
						0b5b56c1ec
					
				
					 3 changed files with 81 additions and 10 deletions
				
			
		|  | @ -37,16 +37,26 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) | ||||||
| 	log("ffA:   %s\n", log_id(st.ffA, "--")); | 	log("ffA:   %s\n", log_id(st.ffA, "--")); | ||||||
| 	log("ffB:   %s\n", log_id(st.ffB, "--")); | 	log("ffB:   %s\n", log_id(st.ffB, "--")); | ||||||
| 	log("dsp:   %s\n", log_id(st.dsp, "--")); | 	log("dsp:   %s\n", log_id(st.dsp, "--")); | ||||||
|  | 	log("addAB: %s\n", log_id(st.addAB, "--")); | ||||||
| 	log("ffP:   %s\n", log_id(st.ffP, "--")); | 	log("ffP:   %s\n", log_id(st.ffP, "--")); | ||||||
| 	//log("muxP:  %s\n", log_id(st.muxP, "--"));
 | 	//log("muxP:  %s\n", log_id(st.muxP, "--"));
 | ||||||
| 	log("sigPused: %s\n", log_signal(st.sigPused)); | 	log("sigPused: %s\n", log_signal(st.sigPused)); | ||||||
| 	log_module(pm.module); |  | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp)); | 	log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); | ||||||
| 
 | 
 | ||||||
| 	Cell *cell = st.dsp; | 	Cell *cell = st.dsp; | ||||||
| 	log_assert(cell); | 	SigSpec P = st.sigP; | ||||||
|  | 
 | ||||||
|  | 	if (st.addAB) { | ||||||
|  | 		log("  adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); | ||||||
|  | 		cell->setPort("\\C", st.sigC.extend_u0(48, true)); | ||||||
|  | 		SigSpec &opmode = cell->connections_.at("\\OPMODE"); | ||||||
|  | 		opmode[6] = State::S0; | ||||||
|  | 		opmode[5] = State::S1; | ||||||
|  | 		opmode[4] = State::S1; | ||||||
|  | 		pm.autoremove(st.addAB); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (st.clock != SigBit()) | 	if (st.clock != SigBit()) | ||||||
| 	{ | 	{ | ||||||
|  | @ -79,7 +89,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) | ||||||
| 			else log_abort(); | 			else log_abort(); | ||||||
| 		} | 		} | ||||||
| 		if (st.ffP) { | 		if (st.ffP) { | ||||||
| 			SigSpec P = cell->getPort("\\P"); |  | ||||||
| 			SigSpec D; | 			SigSpec D; | ||||||
| 			//if (st.muxP)
 | 			//if (st.muxP)
 | ||||||
| 			//	D = st.muxP->getPort("\\B");
 | 			//	D = st.muxP->getPort("\\B");
 | ||||||
|  | @ -87,7 +96,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) | ||||||
| 				D = st.ffP->getPort("\\D"); | 				D = st.ffP->getPort("\\D"); | ||||||
| 			SigSpec Q = st.ffP->getPort("\\Q"); | 			SigSpec Q = st.ffP->getPort("\\Q"); | ||||||
| 			P.replace(pm.sigmap(D), Q); | 			P.replace(pm.sigmap(D), Q); | ||||||
| 			cell->setPort("\\P", P); |  | ||||||
| 			cell->setParam("\\PREG", State::S1); | 			cell->setParam("\\PREG", State::S1); | ||||||
| 			if (st.ffP->type == "$dff") | 			if (st.ffP->type == "$dff") | ||||||
| 				cell->setPort("\\CEP", State::S1); | 				cell->setPort("\\CEP", State::S1); | ||||||
|  | @ -112,6 +120,10 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (GetSize(P) < 48) | ||||||
|  | 		P.append(pm.module->addWire(NEW_ID, 48-GetSize(P))); | ||||||
|  | 	cell->setPort("\\P", P); | ||||||
|  | 
 | ||||||
| 	pm.blacklist(cell); | 	pm.blacklist(cell); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,8 @@ | ||||||
| pattern xilinx_dsp | pattern xilinx_dsp | ||||||
| 
 | 
 | ||||||
| state <SigBit> clock | state <SigBit> clock | ||||||
| state <SigSpec> sigPused | state <SigSpec> sigC sigP sigPused | ||||||
|  | state <Cell*> addAB | ||||||
| 
 | 
 | ||||||
| match dsp | match dsp | ||||||
| 	select dsp->type.in(\DSP48E1) | 	select dsp->type.in(\DSP48E1) | ||||||
|  | @ -43,13 +44,69 @@ code clock | ||||||
| 	} | 	} | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
|  | code sigP | ||||||
|  | 	sigP = port(dsp, \P); | ||||||
|  | endcode | ||||||
|  | 
 | ||||||
|  | match addA | ||||||
|  | 	select addA->type.in($add) | ||||||
|  | 	select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool() | ||||||
|  | 	select nusers(port(addA, \A)) == 2 | ||||||
|  | 	//index <SigSpec> port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int()) | ||||||
|  | 	filter GetSize(sigP) >= param(addA, \A_WIDTH).as_int() | ||||||
|  | 	filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int()) | ||||||
|  | 	optional | ||||||
|  | endmatch | ||||||
|  | 
 | ||||||
|  | match addB | ||||||
|  | 	if !addA | ||||||
|  | 	select addB->type.in($add, $sub) | ||||||
|  | 	select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool() | ||||||
|  | 	select nusers(port(addB, \B)) == 2 | ||||||
|  | 	//index <SigSpec> port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int()) | ||||||
|  | 	filter GetSize(sigP) >= param(addB, \B_WIDTH).as_int() | ||||||
|  | 	filter port(addB, \B) ==  sigP.extract(0, param(addB, \B_WIDTH).as_int()) | ||||||
|  | 	optional | ||||||
|  | endmatch | ||||||
|  | 
 | ||||||
|  | code addAB sigC sigP | ||||||
|  | 	bool C_SIGNED = false; | ||||||
|  | 	if (addA) { | ||||||
|  | 		addAB = addA; | ||||||
|  | 		sigC = port(addAB, \B); | ||||||
|  | 		C_SIGNED = param(addAB, \B_SIGNED).as_bool(); | ||||||
|  | 	} | ||||||
|  | 	if (addB) { | ||||||
|  | 		addAB = addB; | ||||||
|  | 		sigC = port(addAB, \A); | ||||||
|  | 		C_SIGNED = param(addAB, \B_SIGNED).as_bool(); | ||||||
|  | 	} | ||||||
|  | 	if (addAB) { | ||||||
|  | 		// Ensure that adder is not used | ||||||
|  | 		SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3); | ||||||
|  | 		if (!opmodeZ.is_fully_zero()) | ||||||
|  | 			reject; | ||||||
|  | 
 | ||||||
|  | 		int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B)); | ||||||
|  | 		int actual_mul_width = GetSize(sigP); | ||||||
|  | 		int actual_acc_width = GetSize(sigC); | ||||||
|  | 
 | ||||||
|  | 		if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width)) | ||||||
|  | 			reject; | ||||||
|  | 		//if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool())) | ||||||
|  | 		//	reject; | ||||||
|  | 
 | ||||||
|  | 		sigP = port(addAB, \Y); | ||||||
|  |                 sigC.extend_u0(32, C_SIGNED); | ||||||
|  | 	} | ||||||
|  | endcode | ||||||
|  | 
 | ||||||
| // Extract the bits of P that actually have a consumer | // Extract the bits of P that actually have a consumer | ||||||
| // (as opposed to being a dummy) | // (as opposed to being a dummy) | ||||||
| code sigPused | code sigPused | ||||||
| 	SigSpec P = port(dsp, \P); | 	for (int i = 0; i < GetSize(sigP); i++) | ||||||
| 	for (int i = 0; i < GetSize(P); i++) | 		if (sigP[i].wire && nusers(sigP[i]) > 1) | ||||||
| 		if (P[i].wire && nusers(P[i]) > 1) | 			sigPused.append(sigP[i]); | ||||||
| 			sigPused.append(P[i]); |  | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
| match ffP | match ffP | ||||||
|  |  | ||||||
|  | @ -287,6 +287,8 @@ struct SynthXilinxPass : public ScriptPass | ||||||
| 			if (!nodsp || help_mode) { | 			if (!nodsp || help_mode) { | ||||||
| 				// NB: Xilinx multipliers are signed only
 | 				// NB: Xilinx multipliers are signed only
 | ||||||
| 				run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); | 				run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')"); | ||||||
|  | 				run("opt_expr -fine", "                 (skip if '-nodsp')"); | ||||||
|  | 				run("wreduce", "                        (skip if '-nodsp')"); | ||||||
| 				run("xilinx_dsp", "                     (skip if '-nodsp')"); | 				run("xilinx_dsp", "                     (skip if '-nodsp')"); | ||||||
| 				run("chtype -set $mul t:$__soft_mul","  (skip if '-nodsp')"); | 				run("chtype -set $mul t:$__soft_mul","  (skip if '-nodsp')"); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue