diff options
author | Eddie Hung <eddie@fpgeh.com> | 2019-09-10 18:27:05 -0700 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2019-09-10 18:27:05 -0700 |
commit | 8b8a68b38a43a082b76747934d98c6e488d1f6e4 (patch) | |
tree | bf3d35a8f891d9e82270c4ee52151702b9b50133 /passes/pmgen | |
parent | e64e650f9c077094e7fd15c7e149f5b9ec4773d7 (diff) | |
download | yosys-8b8a68b38a43a082b76747934d98c6e488d1f6e4.tar.gz yosys-8b8a68b38a43a082b76747934d98c6e488d1f6e4.tar.bz2 yosys-8b8a68b38a43a082b76747934d98c6e488d1f6e4.zip |
Refactor MREG and PREG to out_dffe subpattern
Diffstat (limited to 'passes/pmgen')
-rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 277 |
1 files changed, 122 insertions, 155 deletions
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 07432dfc7..09e59c184 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -7,12 +7,12 @@ state <IdString> postAddAB postAddMuxAB state <bool> ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol state <int> ffPoffset -state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux +state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux // subpattern -state <SigSpec> argQ +state <SigSpec> argQ argD state <bool> ffenpol -udata <SigSpec> dffD +udata <SigSpec> dffD dffQ udata <SigBit> dffclock udata <Cell*> dff dffmux udata <bool> dffenpol @@ -159,76 +159,20 @@ code argQ ffD ffDmux ffDenpol sigD clock } endcode -match ffMmux - if param(dsp, \MREG).as_int() == 0 - if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" - if nusers(sigM) == 2 - select ffMmux->type.in($mux) - choice <IdString> BA {\B, \A} - // new-value net must have exactly two users: dsp and ffMmux - select nusers(port(ffMmux, BA)) == 2 - define <IdString> AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffMmux, ffM, downstream sink(s) - select nusers(port(ffMmux, AB)) >= 3 - // ffMmux output must have two users: ffMmux and ffM.D - select nusers(port(ffMmux, \Y)) == 2 - filter GetSize(unextend(port(ffMmux, BA))) <= GetSize(sigM) - filter unextend(port(ffMmux, BA)) == sigM.extract(0, GetSize(unextend(port(ffMmux, BA)))) - // Remaining bits on sigM must not have any other users - filter nusers(sigM.extract_end(GetSize(unextend(port(ffMmux, BA))))) <= 1 - define <bool> pol (AB == \A) - set ffMenpol pol - optional -endmatch - -code sigM - if (ffMmux) - sigM = port(ffMmux, \Y); -endcode - -match ffM_enable - if ffMmux - if nusers(sigM) == 2 - select ffM_enable->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffM_enable, \CLK_POLARITY).as_bool() - index <SigSpec> port(ffM_enable, \D) === sigM - index <SigSpec> port(ffM_enable, \Q) === port(ffMmux, ffMenpol ? \A : \B) -endmatch - -match ffM - if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY" - if !ffM_enable - if param(dsp, \MREG).as_int() == 0 - if nusers(sigM) == 2 - select ffM->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffM, \CLK_POLARITY).as_bool() - index <SigSpec> port(ffM, \D) === sigM - optional -endmatch - -code ffM clock sigM sigP - if (ffM_enable) { - log_assert(!ffM); - ffM = ffM_enable; - } - if (ffM) { - sigM = port(ffM, \Q); - - for (auto b : sigM) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffM, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; +code argD ffM ffMmux ffMenpol sigM sigP clock + if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) { + argD = sigM; + subpattern(out_dffe); + if (dff) { + ffM = dff; + clock = dffclock; + if (dffmux) { + ffMmux = dffmux; + ffMenpol = dffenpol; + } + sigM = dffQ; + } } - // No enable mux possible without flop - else if (ffMmux) - reject; - sigP = sigM; endcode @@ -268,90 +212,25 @@ code sigC sigP } endcode -match ffPmux - if param(dsp, \PREG).as_int() == 0 - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux - if !ffMmux || postAdd || nusers(sigP) == 3 - // Otherwise new-value net must have exactly two users: dsp and ffPmux - if (ffMmux && !postAdd) || nusers(sigP) == 2 - - select ffPmux->type.in($mux) - // ffPmux output must have two users: ffPmux and ffP.D - select nusers(port(ffPmux, \Y)) == 2 - filter GetSize(port(ffPmux, \Y)) >= GetSize(sigP) - - slice offset GetSize(port(ffPmux, \Y)) - filter offset+GetSize(sigP) <= GetSize(port(ffPmux, \Y)) - choice <IdString> BA {\B, \A} - filter port(ffPmux, BA).extract(offset, GetSize(sigP)) == sigP - - define <IdString> AB (BA == \B ? \A : \B) - // keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s) - filter nusers(port(ffPmux, AB)) >= 3 - define <bool> pol (AB == \A) - set ffPenpol pol - set ffPoffset offset - optional -endmatch - -code sigP - if (ffPmux) - sigP.replace(port(ffPmux, ffPenpol ? \B : \A), port(ffPmux, \Y)); -endcode - -match ffP_enable - if ffPmux - if nusers(sigP) == 2 - select ffP_enable->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffP_enable, \CLK_POLARITY).as_bool() - index <SigSpec> port(ffP_enable, \D) === port(ffPmux, \Y) - index <SigSpec> port(ffP_enable, \Q) === port(ffPmux, ffPenpol ? \A : \B) - filter GetSize(port(ffP_enable, \D)) >= GetSize(sigP) - filter ffPoffset+GetSize(sigP) <= GetSize(port(ffP_enable, \D)) - filter port(ffP_enable, \D).extract(ffPoffset, GetSize(sigP)) == sigP -endmatch - -match ffP - if !ffP_enable - if param(dsp, \PREG).as_int() == 0 - // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux - if !ffMmux || postAdd || nusers(sigP) == 3 - // Otherwise new-value net must have exactly two users: dsp and ffPmux - if (ffMmux && !postAdd) || nusers(sigP) == 2 - - select ffP->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffP, \CLK_POLARITY).as_bool() - filter GetSize(port(ffP, \D)) >= GetSize(sigP) - slice offset GetSize(port(ffP, \D)) - filter offset+GetSize(sigP) <= GetSize(port(ffP, \D)) - filter port(ffP, \D).extract(offset, GetSize(sigP)) == sigP - optional -endmatch - -code ffP sigP clock - if (ffP_enable) { - log_assert(!ffP); - ffP = ffP_enable; - } - if (ffP) { - for (auto b : port(ffP, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffP, \CLK).as_bit(); - - if (clock != SigBit() && c != clock) - reject; - - clock = c; - - sigP.replace(port(ffP, \D), port(ffP, \Q)); +code argD ffP ffPmux ffPenpol sigP clock + if (param(dsp, \PREG).as_int() == 0) { + // If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux + if ((ffMmux && !postAdd && nusers(sigP) == 3) || + // Otherwise new-value net must have exactly two users: dsp and ffPmux + ((!ffMmux || postAdd) && nusers(sigP) == 2)) { + argD = sigP; + subpattern(out_dffe); + if (dff) { + ffP = dff; + clock = dffclock; + if (dffmux) { + ffPmux = dffmux; + ffPenpol = dffenpol; + } + sigP = dffQ; + } + } } - // No enable mux possible without flop - else if (ffPmux) - reject; endcode match postAddMux @@ -391,6 +270,8 @@ code accept; endcode +// ####################### + subpattern in_dffe arg argQ clock ffenpol @@ -457,3 +338,89 @@ code else dffmux = nullptr; endcode + +// ####################### + +subpattern out_dffe +arg argD clock ffenpol +arg unextend + +match ffmux + select ffmux->type.in($mux) + // ffmux output must have two users: ffmux and ff.D + select nusers(port(ffmux, \Y)) == 2 + filter GetSize(port(ffmux, \Y)) >= GetSize(argD) + + choice <IdString> BA {\B, \A} + // new-value net must have exactly two users: (upstream) and ffmux + select nusers(port(ffmux, BA)) == 2 + + slice offset GetSize(port(ffmux, \Y)) + filter offset+GetSize(argD) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, BA).extract(offset, GetSize(argD)) == argD + + define <IdString> AB (BA == \B ? \A : \B) + // keep-last-value net must have at least three users: ffmux, ff, downstream sink(s) + select nusers(port(ffmux, AB)) >= 3 + + filter GetSize(unextend(port(ffmux, BA))) <= GetSize(argD) + filter unextend(port(ffmux, BA)) == argD.extract(0, GetSize(unextend(port(ffmux, BA)))) + // Remaining bits on argD must not have any other users + filter nusers(argD.extract_end(GetSize(unextend(port(ffmux, BA))))) <= 1 + + define <bool> pol (AB == \A) + set ffenpol pol + semioptional +endmatch + +code argD + if (ffmux) { + dffmux = ffmux; + dffenpol = ffenpol; + argD = port(ffmux, \Y); + } + else + dffmux = nullptr; +endcode + +match ff_enable + if ffmux + select ff_enable->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff_enable, \CLK_POLARITY).as_bool() + index <SigSpec> port(ff_enable, \D) === argD + index <SigSpec> port(ff_enable, \Q) === port(ffmux, ffenpol ? \A : \B) +endmatch + +match ff + if !ff_enable + select ff->type.in($dff) + // DSP48E1 does not support clock inversion + select param(ff, \CLK_POLARITY).as_bool() + index <SigSpec> port(ff, \D) === argD + semioptional +endmatch + +code + if (ff_enable) + dff = ff_enable; + else + dff = ff; + log_dump("ffM", dff, dffmux); + if (dff) { + dffQ = port(dff, \Q); + + for (auto b : dffQ) + if (b.wire->get_bool_attribute(\keep)) + reject; + + if (clock != SigBit()) { + if (port(dff, \CLK) != clock) + reject; + } + dffclock = port(dff, \CLK); + } + // No enable mux possible without flop + else if (ffmux) + reject; +endcode |