pattern ql_dsp_macc // Rough sketch: (mux is optional) // // /-----------------------\ // | | // \ / | // mul ----> add -----> mux -----> ff -+----> // | /\ // | | // -------------- state add_ba state mux_ab // Is the output taken from before or after the FF? state output_registered // Is there a mux in the pattern? state 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 AB {\A, \B} define BA (AB == \A ? \B : \A) // One input to the adder is fed by the multiplier index 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 AB {\A, \B} define BA (AB == \A ? \B : \A) index port(mux, AB) === port(mul, \Y) index 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 port(ff, \D) === mux_in_pattern ? port(mux, \Y) : port(add, \Y); index port(ff, \Q) === port(add, add_ba) filter nusers(port(ff, \Q)) == (output_registered ? 3 : 2) endmatch code accept; endcode