mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 11:42:30 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			162 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			3.1 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| pattern ice40_dsp
 | |
| 
 | |
| state <SigBit> clock
 | |
| state <bool> clock_pol clock_vld
 | |
| state <SigSpec> sigA sigB sigY sigS
 | |
| state <Cell*> addAB muxAB
 | |
| 
 | |
| match mul
 | |
| 	select mul->type.in($mul)
 | |
| 	select GetSize(mul->getPort(\A)) + GetSize(mul->getPort(\B)) > 10
 | |
| 	select GetSize(mul->getPort(\Y)) > 10
 | |
| endmatch
 | |
| 
 | |
| match ffA
 | |
| 	select ffA->type.in($dff)
 | |
| 	// select nusers(port(ffA, \Q)) == 2
 | |
| 	index <SigSpec> port(ffA, \Q) === port(mul, \A)
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| code sigA clock clock_pol clock_vld
 | |
| 	sigA = port(mul, \A);
 | |
| 
 | |
| 	if (ffA) {
 | |
| 		sigA = port(ffA, \D);
 | |
| 
 | |
| 		clock = port(ffA, \CLK).as_bit();
 | |
| 		clock_pol = param(ffA, \CLK_POLARITY).as_bool();
 | |
| 		clock_vld = true;
 | |
| 	}
 | |
| endcode
 | |
| 
 | |
| match ffB
 | |
| 	select ffB->type.in($dff)
 | |
| 	// select nusers(port(ffB, \Q)) == 2
 | |
| 	index <SigSpec> port(ffB, \Q) === port(mul, \B)
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| code sigB clock clock_pol clock_vld
 | |
| 	sigB = port(mul, \B);
 | |
| 
 | |
| 	if (ffB) {
 | |
| 		sigB = port(ffB, \D);
 | |
| 		SigBit c = port(ffB, \CLK).as_bit();
 | |
| 		bool cp = param(ffB, \CLK_POLARITY).as_bool();
 | |
| 
 | |
| 		if (clock_vld && (c != clock || cp != clock_pol))
 | |
| 			reject;
 | |
| 
 | |
| 		clock = c;
 | |
| 		clock_pol = cp;
 | |
| 		clock_vld = true;
 | |
| 	}
 | |
| endcode
 | |
| 
 | |
| match ffY
 | |
| 	select ffY->type.in($dff)
 | |
| 	select nusers(port(ffY, \D)) == 2
 | |
| 	index <SigSpec> port(ffY, \D) === port(mul, \Y)
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| code sigY clock clock_pol clock_vld
 | |
| 	sigY = port(mul, \Y);
 | |
| 
 | |
| 	if (ffY) {
 | |
| 		sigY = port(ffY, \Q);
 | |
| 		SigBit c = port(ffY, \CLK).as_bit();
 | |
| 		bool cp = param(ffY, \CLK_POLARITY).as_bool();
 | |
| 
 | |
| 		if (clock_vld && (c != clock || cp != clock_pol))
 | |
| 			reject;
 | |
| 
 | |
| 		clock = c;
 | |
| 		clock_pol = cp;
 | |
| 		clock_vld = true;
 | |
| 	}
 | |
| endcode
 | |
| 
 | |
| match addA
 | |
| 	select addA->type.in($add)
 | |
| 	select nusers(port(addA, \A)) == 2
 | |
| 	index <SigSpec> port(addA, \A) === sigY
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| match addB
 | |
| 	if !addA
 | |
| 	select addB->type.in($add, $sub)
 | |
| 	select nusers(port(addB, \B)) == 2
 | |
| 	index <SigSpec> port(addB, \B) === sigY
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| code addAB sigS
 | |
| 	if (addA) {
 | |
| 		addAB = addA;
 | |
| 		sigS = port(addA, \B);
 | |
| 	}
 | |
| 	if (addB) {
 | |
| 		addAB = addB;
 | |
| 		sigS = port(addB, \A);
 | |
| 	}
 | |
| 	if (addAB) {
 | |
| 		int natural_mul_width = GetSize(sigA) + GetSize(sigB);
 | |
| 		int actual_mul_width = GetSize(sigY);
 | |
| 		int actual_acc_width = GetSize(sigS);
 | |
| 
 | |
| 		if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
 | |
| 			reject;
 | |
| 		if ((actual_acc_width != actual_mul_width) && (param(mul, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
 | |
| 			reject;
 | |
| 	}
 | |
| endcode
 | |
| 
 | |
| match muxA
 | |
| 	if addAB
 | |
| 	select muxA->type.in($mux)
 | |
| 	select nusers(port(muxA, \A)) == 2
 | |
| 	index <SigSpec> port(muxA, \A) === port(addAB, \Y)
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| match muxB
 | |
| 	if addAB
 | |
| 	if !muxA
 | |
| 	select muxB->type.in($mux)
 | |
| 	select nusers(port(muxB, \B)) == 2
 | |
| 	index <SigSpec> port(muxB, \B) === port(addAB, \Y)
 | |
| 	optional
 | |
| endmatch
 | |
| 
 | |
| code muxAB
 | |
| 	muxAB = addAB;
 | |
| 	if (muxA)
 | |
| 		muxAB = muxA;
 | |
| 	if (muxB)
 | |
| 		muxAB = muxB;
 | |
| endcode
 | |
| 
 | |
| match ffS
 | |
| 	if muxAB
 | |
| 	select ffS->type.in($dff)
 | |
| 	select nusers(port(ffS, \D)) == 2
 | |
| 	index <SigSpec> port(ffS, \D) === port(muxAB, \Y)
 | |
| 	index <SigSpec> port(ffS, \Q) === sigS
 | |
| endmatch
 | |
| 
 | |
| code clock clock_pol clock_vld
 | |
| 	if (ffS) {
 | |
| 		SigBit c = port(ffS, \CLK).as_bit();
 | |
| 		bool cp = param(ffS, \CLK_POLARITY).as_bool();
 | |
| 
 | |
| 		if (clock_vld && (c != clock || cp != clock_pol))
 | |
| 			reject;
 | |
| 
 | |
| 		clock = c;
 | |
| 		clock_pol = cp;
 | |
| 		clock_vld = true;
 | |
| 	}
 | |
| endcode
 |