mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
pattern ql_dsp_macc
 | 
						|
// Rough sketch: (mux is optional)
 | 
						|
//
 | 
						|
//               /-----------------------\
 | 
						|
//               |                       |
 | 
						|
//              \ /                      |
 | 
						|
//   mul ----> add -----> mux -----> ff -+---->
 | 
						|
//         |              /\
 | 
						|
//         |              |
 | 
						|
//          --------------
 | 
						|
 | 
						|
state <IdString> add_ba
 | 
						|
state <IdString> mux_ab
 | 
						|
 | 
						|
// Is the output taken from before or after the FF?
 | 
						|
state <bool> output_registered
 | 
						|
 | 
						|
// Is there a mux in the pattern?
 | 
						|
state <bool> mux_in_pattern
 | 
						|
 | 
						|
code mux_in_pattern
 | 
						|
    mux_in_pattern = false;
 | 
						|
    branch;
 | 
						|
    mux_in_pattern = true;
 | 
						|
endcode
 | 
						|
 | 
						|
// The multiplier is at the center of our pattern
 | 
						|
match mul
 | 
						|
    select mul->type.in($mul)
 | 
						|
    // It has either two or three consumers depending on whether there's a mux
 | 
						|
    // in the pattern or not
 | 
						|
    select nusers(port(mul, \Y)) <= 3
 | 
						|
    filter nusers(port(mul, \Y)) == (mux_in_pattern ? 3 : 2)
 | 
						|
endmatch
 | 
						|
 | 
						|
code output_registered
 | 
						|
    output_registered = false;
 | 
						|
    branch;
 | 
						|
    output_registered = true;
 | 
						|
endcode
 | 
						|
 | 
						|
match add
 | 
						|
    select add->type.in($add, $sub)
 | 
						|
    choice <IdString> AB {\A, \B}
 | 
						|
    define <IdString> BA (AB == \A ? \B : \A)
 | 
						|
    // One input to the adder is fed by the multiplier
 | 
						|
    index <SigSpec> port(add, AB) === port(mul, \Y)
 | 
						|
    // Save the other input port, it needs to be fed by the flip-flop
 | 
						|
    set add_ba BA
 | 
						|
    // Adder has either two or three consumers; it will have three consumers
 | 
						|
    // IFF there's no mux in the pattern and the multiplier-accumulator result
 | 
						|
    // is taken unregistered
 | 
						|
    filter nusers(port(add, \Y)) == (!mux_in_pattern && !output_registered ? 3 : 2)
 | 
						|
endmatch
 | 
						|
 | 
						|
match mux
 | 
						|
    if mux_in_pattern
 | 
						|
    select mux->type.in($mux)
 | 
						|
    choice <IdString> AB {\A, \B}
 | 
						|
    define <IdString> BA (AB == \A ? \B : \A)
 | 
						|
    index <SigSpec> port(mux, AB) === port(mul, \Y)
 | 
						|
    index <SigSpec> port(mux, BA) === port(add, \Y)
 | 
						|
    filter nusers(port(mux, \Y)) == (output_registered ? 2 : 3)
 | 
						|
    set mux_ab AB
 | 
						|
endmatch
 | 
						|
 | 
						|
match ff
 | 
						|
    select ff->type.in($dff, $adff, $dffe, $adffe)
 | 
						|
    select param(ff, \CLK_POLARITY).as_bool()
 | 
						|
    index <SigSpec> port(ff, \D) === mux_in_pattern ? port(mux, \Y) : port(add, \Y);
 | 
						|
    index <SigSpec> port(ff, \Q) === port(add, add_ba)
 | 
						|
    filter nusers(port(ff, \Q)) == (output_registered ? 3 : 2)
 | 
						|
endmatch
 | 
						|
 | 
						|
code
 | 
						|
    accept;
 | 
						|
endcode
 |