mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	Fine tune ice40_dsp.pmg, add support for packing subsets of registers
This commit is contained in:
		
							parent
							
								
									8f0e796be1
								
							
						
					
					
						commit
						9ad11ea2cc
					
				
					 4 changed files with 47 additions and 35 deletions
				
			
		|  | @ -23,13 +23,16 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
|  | template<class T> bool includes(const T &lhs, const T &rhs) { | ||||||
|  | 	return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); | ||||||
|  | } | ||||||
| #include "passes/pmgen/ice40_dsp_pm.h" | #include "passes/pmgen/ice40_dsp_pm.h" | ||||||
| 
 | 
 | ||||||
| void create_ice40_dsp(ice40_dsp_pm &pm) | void create_ice40_dsp(ice40_dsp_pm &pm) | ||||||
| { | { | ||||||
| 	auto &st = pm.st_ice40_dsp; | 	auto &st = pm.st_ice40_dsp; | ||||||
| 
 | 
 | ||||||
| #if 0 | #if 1 | ||||||
| 	log("\n"); | 	log("\n"); | ||||||
| 	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, "--")); | ||||||
|  | @ -100,7 +103,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) | ||||||
| 	cell->setPort("\\IRSTTOP", State::S0); | 	cell->setPort("\\IRSTTOP", State::S0); | ||||||
| 	cell->setPort("\\IRSTBOT", State::S0); | 	cell->setPort("\\IRSTBOT", State::S0); | ||||||
| 
 | 
 | ||||||
| 	if (st.clock_vld) | 	if (st.clock != SigBit()) | ||||||
| 	{ | 	{ | ||||||
| 		cell->setPort("\\CLK", st.clock); | 		cell->setPort("\\CLK", st.clock); | ||||||
| 		cell->setPort("\\CE", State::S1); | 		cell->setPort("\\CE", State::S1); | ||||||
|  |  | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| pattern ice40_dsp | pattern ice40_dsp | ||||||
| 
 | 
 | ||||||
| state <SigBit> clock | state <SigBit> clock | ||||||
| state <bool> clock_pol clock_vld | state <bool> clock_pol | ||||||
| state <SigSpec> sigA sigB sigY sigS | state <SigSpec> sigA sigB sigY sigS | ||||||
|  | state <SigSpec> sigYused | ||||||
| state <Cell*> addAB muxAB | state <Cell*> addAB muxAB | ||||||
| 
 | 
 | ||||||
| match mul | match mul | ||||||
|  | @ -13,68 +14,77 @@ endmatch | ||||||
| 
 | 
 | ||||||
| match ffA | match ffA | ||||||
| 	select ffA->type.in($dff) | 	select ffA->type.in($dff) | ||||||
| 	// select nusers(port(ffA, \Q)) == 2 | 	filter !port(mul, \A).remove_const().empty() | ||||||
| 	index <SigSpec> port(ffA, \Q) === port(mul, \A) | 	filter includes(port(ffA, \Q).to_sigbit_set(), port(mul, \A).remove_const().to_sigbit_set()) | ||||||
| 	optional | 	optional | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
| code sigA clock clock_pol clock_vld | code sigA clock clock_pol | ||||||
| 	sigA = port(mul, \A); | 	sigA = port(mul, \A); | ||||||
| 
 | 
 | ||||||
| 	if (ffA) { | 	if (ffA) { | ||||||
| 		sigA = port(ffA, \D); | 		sigA.replace(port(ffA, \Q), port(ffA, \D)); | ||||||
| 
 | 
 | ||||||
| 		clock = port(ffA, \CLK).as_bit(); | 		clock = port(ffA, \CLK).as_bit(); | ||||||
| 		clock_pol = param(ffA, \CLK_POLARITY).as_bool(); | 		clock_pol = param(ffA, \CLK_POLARITY).as_bool(); | ||||||
| 		clock_vld = true; |  | ||||||
| 	} | 	} | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
| match ffB | match ffB | ||||||
| 	select ffB->type.in($dff) | 	select ffB->type.in($dff) | ||||||
| 	// select nusers(port(ffB, \Q)) == 2 | 	filter !port(mul, \B).remove_const().empty() | ||||||
| 	index <SigSpec> port(ffB, \Q) === port(mul, \B) | 	filter includes(port(ffB, \Q).to_sigbit_set(), port(mul, \B).remove_const().to_sigbit_set()) | ||||||
| 	optional | 	optional | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
| code sigB clock clock_pol clock_vld | code sigB clock clock_pol | ||||||
| 	sigB = port(mul, \B); | 	sigB = port(mul, \B); | ||||||
| 
 | 
 | ||||||
| 	if (ffB) { | 	if (ffB) { | ||||||
| 		sigB = port(ffB, \D); | 		sigB.replace(port(ffB, \Q), port(ffB, \D)); | ||||||
|  | 		 | ||||||
| 		SigBit c = port(ffB, \CLK).as_bit(); | 		SigBit c = port(ffB, \CLK).as_bit(); | ||||||
| 		bool cp = param(ffB, \CLK_POLARITY).as_bool(); | 		bool cp = param(ffB, \CLK_POLARITY).as_bool(); | ||||||
| 
 | 
 | ||||||
| 		if (clock_vld && (c != clock || cp != clock_pol)) | 		if (clock != SigBit() && (c != clock || cp != clock_pol)) | ||||||
| 			reject; | 			reject; | ||||||
| 
 | 
 | ||||||
| 		clock = c; | 		clock = c; | ||||||
| 		clock_pol = cp; | 		clock_pol = cp; | ||||||
| 		clock_vld = true; |  | ||||||
| 	} | 	} | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
|  | // Extract the bits of Y that actually have a consumer | ||||||
|  | // (as opposed to being a sign extension) | ||||||
|  | code sigY sigYused | ||||||
|  | 	sigY = port(mul, \Y); | ||||||
|  | 	int i; | ||||||
|  | 	for (i = GetSize(sigY); i > 0; i--) | ||||||
|  | 		if (nusers(sigY[i-1]) > 1) | ||||||
|  | 			break; | ||||||
|  | 	sigYused = sigY.extract(0, i).remove_const(); | ||||||
|  | endcode | ||||||
|  | 
 | ||||||
| match ffY | match ffY | ||||||
| 	select ffY->type.in($dff) | 	select ffY->type.in($dff) | ||||||
| 	select nusers(port(ffY, \D)) == 2 | 	select nusers(port(ffY, \D)) == 2 | ||||||
| 	index <SigSpec> port(ffY, \D) === port(mul, \Y) | 	filter param(ffY, \WIDTH).as_int() >= GetSize(sigYused) | ||||||
|  | 	filter includes(port(ffY, \D).to_sigbit_set(), sigYused.to_sigbit_set()) | ||||||
| 	optional | 	optional | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
| code sigY clock clock_pol clock_vld | code clock clock_pol sigY | ||||||
| 	sigY = port(mul, \Y); |  | ||||||
| 
 |  | ||||||
| 	if (ffY) { | 	if (ffY) { | ||||||
| 		sigY = port(ffY, \Q); | 		sigY.replace(port(ffY, \D), port(ffY, \Q)); | ||||||
|  | 
 | ||||||
| 		SigBit c = port(ffY, \CLK).as_bit(); | 		SigBit c = port(ffY, \CLK).as_bit(); | ||||||
| 		bool cp = param(ffY, \CLK_POLARITY).as_bool(); | 		bool cp = param(ffY, \CLK_POLARITY).as_bool(); | ||||||
| 
 | 
 | ||||||
| 		if (clock_vld && (c != clock || cp != clock_pol)) | 		if (clock != SigBit() && (c != clock || cp != clock_pol)) | ||||||
| 			reject; | 			reject; | ||||||
| 
 | 
 | ||||||
| 		clock = c; | 		clock = c; | ||||||
| 		clock_pol = cp; | 		clock_pol = cp; | ||||||
| 		clock_vld = true; |  | ||||||
| 	} | 	} | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
|  | @ -147,16 +157,15 @@ match ffS | ||||||
| 	index <SigSpec> port(ffS, \Q) === sigS | 	index <SigSpec> port(ffS, \Q) === sigS | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
| code clock clock_pol clock_vld | code clock clock_pol | ||||||
| 	if (ffS) { | 	if (ffS) { | ||||||
| 		SigBit c = port(ffS, \CLK).as_bit(); | 		SigBit c = port(ffS, \CLK).as_bit(); | ||||||
| 		bool cp = param(ffS, \CLK_POLARITY).as_bool(); | 		bool cp = param(ffS, \CLK_POLARITY).as_bool(); | ||||||
| 
 | 
 | ||||||
| 		if (clock_vld && (c != clock || cp != clock_pol)) | 		if (clock != SigBit() && (c != clock || cp != clock_pol)) | ||||||
| 			reject; | 			reject; | ||||||
| 
 | 
 | ||||||
| 		clock = c; | 		clock = c; | ||||||
| 		clock_pol = cp; | 		clock_pol = cp; | ||||||
| 		clock_vld = true; |  | ||||||
| 	} | 	} | ||||||
| endcode | endcode | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm) | ||||||
| 	log("dsp:   %s\n", log_id(st.dsp, "--")); | 	log("dsp:   %s\n", log_id(st.dsp, "--")); | ||||||
| 	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("P_used: %s\n", log_signal(st.P_used)); | 	log("sigPused: %s\n", log_signal(st.sigPused)); | ||||||
| 	log_module(pm.module); | 	log_module(pm.module); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| pattern xilinx_dsp | pattern xilinx_dsp | ||||||
| 
 | 
 | ||||||
| state <SigBit> clock | state <SigBit> clock | ||||||
| state <SigSpec> P_used | state <SigSpec> sigPused | ||||||
| 
 | 
 | ||||||
| match dsp | match dsp | ||||||
| 	select dsp->type.in(\DSP48E1) | 	select dsp->type.in(\DSP48E1) | ||||||
|  | @ -43,23 +43,23 @@ 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 sign extension) | // (as opposed to being a sign extension) | ||||||
| code P_used | code sigPused | ||||||
| 	SigSpec P = port(dsp, \P); | 	SigSpec P = port(dsp, \P); | ||||||
| 	int i; | 	int i; | ||||||
| 	for (i = GetSize(P); i > 0; i--) | 	for (i = GetSize(P); i > 0; i--) | ||||||
| 		if (nusers(P[i-1]) > 1) | 		if (nusers(P[i-1]) > 1) | ||||||
| 			break; | 			break; | ||||||
| 	P_used = P.extract(0, i).remove_const(); | 	sigPused = P.extract(0, i).remove_const(); | ||||||
| endcode | endcode | ||||||
| 
 | 
 | ||||||
| match ffP | match ffP | ||||||
| 	if !P_used.empty() | 	if !sigPused.empty() | ||||||
| 	select ffP->type.in($dff, $dffe) | 	select ffP->type.in($dff, $dffe) | ||||||
| 	select nusers(port(ffP, \D)) == 2 | 	select nusers(port(ffP, \D)) == 2 | ||||||
| 	// DSP48E1 does not support clock inversion | 	// DSP48E1 does not support clock inversion | ||||||
| 	select param(ffP, \CLK_POLARITY).as_bool() | 	select param(ffP, \CLK_POLARITY).as_bool() | ||||||
| 	filter param(ffP, \WIDTH).as_int() >= GetSize(P_used) | 	filter param(ffP, \WIDTH).as_int() >= GetSize(sigPused) | ||||||
| 	filter includes(port(ffP, \D).to_sigbit_set(), P_used.to_sigbit_set()) | 	filter includes(port(ffP, \D).to_sigbit_set(), sigPused.to_sigbit_set()) | ||||||
| 	optional | 	optional | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
|  | @ -68,12 +68,12 @@ endmatch | ||||||
| //   since that would lose information helpful for | //   since that would lose information helpful for | ||||||
| //   efficient wide-mux inference | //   efficient wide-mux inference | ||||||
| match muxP | match muxP | ||||||
| 	if !P_used.empty() && !ffP | 	if !sigPused.empty() && !ffP | ||||||
| 	select muxP->type.in($mux) | 	select muxP->type.in($mux) | ||||||
| 	select nusers(port(muxP, \B)) == 2 | 	select nusers(port(muxP, \B)) == 2 | ||||||
| 	select port(muxP, \A).is_fully_undef() | 	select port(muxP, \A).is_fully_undef() | ||||||
| 	filter param(muxP, \WIDTH).as_int() >= GetSize(P_used) | 	filter param(muxP, \WIDTH).as_int() >= GetSize(sigPused) | ||||||
| 	filter includes(port(muxP, \B).to_sigbit_set(), P_used.to_sigbit_set()) | 	filter includes(port(muxP, \B).to_sigbit_set(), sigPused.to_sigbit_set()) | ||||||
| 	optional | 	optional | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
|  | @ -83,7 +83,7 @@ match ffY | ||||||
| 	select nusers(port(ffY, \D)) == 2 | 	select nusers(port(ffY, \D)) == 2 | ||||||
| 	// DSP48E1 does not support clock inversion | 	// DSP48E1 does not support clock inversion | ||||||
| 	select param(ffY, \CLK_POLARITY).as_bool() | 	select param(ffY, \CLK_POLARITY).as_bool() | ||||||
| 	filter param(ffY, \WIDTH).as_int() >= GetSize(P_used) | 	filter param(ffY, \WIDTH).as_int() >= GetSize(sigPused) | ||||||
| 	filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) | 	filter includes(port(ffY, \D).to_sigbit_set(), port(muxP, \Y).to_sigbit_set()) | ||||||
| endmatch | endmatch | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue