yosys/techlibs/quicklogic/ql_dsp_macc.pmg

78 lines
2.3 KiB
Plaintext
Raw Normal View History

2023-11-27 03:35:29 -06:00
pattern ql_dsp_macc
2023-10-02 08:55:41 -05:00
// Rough sketch: (mux is optional)
//
// /-----------------------\
// | |
// \ / |
// mul ----> add -----> mux -----> ff -+---->
// | /\
// | |
// --------------
2023-11-27 03:35:29 -06:00
state <IdString> add_ba
state <IdString> mux_ab
2023-10-02 08:55:41 -05:00
// Is the output taken from before or after the FF?
state <bool> output_registered
2023-11-27 03:35:29 -06:00
2023-10-02 08:55:41 -05:00
// 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
2023-11-27 03:35:29 -06:00
match mul
select mul->type.in($mul)
2023-10-02 08:55:41 -05:00
// It has either two or three consumers depending on whether there's a mux
// in the pattern or not
2023-11-27 03:35:29 -06:00
select nusers(port(mul, \Y)) <= 3
2023-10-02 08:55:41 -05:00
filter nusers(port(mul, \Y)) == (mux_in_pattern ? 3 : 2)
2023-11-27 03:35:29 -06:00
endmatch
2023-10-02 08:55:41 -05:00
code output_registered
output_registered = false;
branch;
output_registered = true;
endcode
2023-11-27 03:35:29 -06:00
match add
select add->type.in($add, $sub)
choice <IdString> AB {\A, \B}
define <IdString> BA (AB == \A ? \B : \A)
2023-10-02 08:55:41 -05:00
// One input to the adder is fed by the multiplier
2023-11-27 03:35:29 -06:00
index <SigSpec> port(add, AB) === port(mul, \Y)
2023-10-02 08:55:41 -05:00
// Save the other input port, it needs to be fed by the flip-flop
2023-11-27 03:35:29 -06:00
set add_ba BA
2023-10-02 08:55:41 -05:00
// 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)
2023-11-27 03:35:29 -06:00
endmatch
match mux
2023-10-02 08:55:41 -05:00
if mux_in_pattern
2023-11-27 03:35:29 -06:00
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)
2023-10-02 08:55:41 -05:00
filter nusers(port(mux, \Y)) == (output_registered ? 2 : 3)
2023-11-27 03:35:29 -06:00
set mux_ab AB
endmatch
match ff
select ff->type.in($dff, $adff, $dffe, $adffe)
2023-10-02 08:55:41 -05:00
select param(ff, \CLK_POLARITY).as_bool()
index <SigSpec> port(ff, \D) === mux_in_pattern ? port(mux, \Y) : port(add, \Y);
2023-11-27 03:35:29 -06:00
index <SigSpec> port(ff, \Q) === port(add, add_ba)
2023-10-02 08:55:41 -05:00
filter nusers(port(ff, \Q)) == (output_registered ? 3 : 2)
2023-11-27 03:35:29 -06:00
endmatch
code
accept;
endcode