1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
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
|