diff options
Diffstat (limited to 'passes/pmgen/xilinx_dsp.pmg')
-rw-r--r-- | passes/pmgen/xilinx_dsp.pmg | 159 |
1 files changed, 103 insertions, 56 deletions
diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 686efd8c4..6e726d1c2 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -2,12 +2,13 @@ pattern xilinx_dsp state <std::function<SigSpec(const SigSpec&)>> unextend state <SigBit> clock -state <SigSpec> sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP +state <SigSpec> sigA sigffAcemuxY sigB sigffBcemuxY sigC sigffCcemuxY sigD sigffDcemuxY sigM sigP state <IdString> postAddAB postAddMuxAB -state <bool> ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffMrstpol ffPcepol ffPrstpol -state <int> ffPoffset +state <bool> ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state <bool> ffArstpol ffADrstpol ffBrstpol ffCrstpol ffDrstpol ffMrstpol ffPrstpol -state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux +state <Cell*> ffAD ffADcemux ffADrstmux ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffC ffCcemux ffCrstmux +state <Cell*> ffD ffDcemux ffDrstmux ffM ffMcemux ffMrstmux ffP ffPcemux ffPrstmux // subpattern state <SigSpec> argQ argD @@ -54,7 +55,7 @@ code unextend sigA sigB sigC sigD sigM sigM = P; endcode -code argQ ffAD ffADmux ffADcepol sigA clock +code argQ ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol sigA clock if (param(dsp, \ADREG).as_int() == 0) { argQ = sigA; subpattern(in_dffe); @@ -62,8 +63,10 @@ code argQ ffAD ffADmux ffADcepol sigA clock ffAD = dff; clock = dffclock; if (dffcemux) { - ffADmux = dffcemux; + ffADcemux = dffcemux; + ffADrstmux = dffrstmux; ffADcepol = dffcepol; + ffADrstpol = dffrstpol; } sigA = dffD; } @@ -100,7 +103,7 @@ code sigA sigD } endcode -code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol +code argQ ffA ffAcemux ffArstmux ffAcepol ffArstpol sigA clock ffAD ffADcemux ffADrstmux ffADcepol ffADrstpol // Only search for ffA if there was a pre-adder // (otherwise ffA would have been matched as ffAD) if (preAdd) { @@ -111,8 +114,10 @@ code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol ffA = dff; clock = dffclock; if (dffcemux) { - ffAmux = dffcemux; + ffAcemux = dffcemux; + ffArstmux = dffrstmux; ffAcepol = dffcepol; + ffArstpol = dffrstpol; } sigA = dffD; } @@ -121,14 +126,16 @@ code argQ ffA ffAmux ffAcepol sigA clock ffAD ffADmux ffADcepol // And if there wasn't a pre-adder, // move AD register to A else if (ffAD) { - log_assert(!ffA && !ffAmux); + log_assert(!ffA && !ffAcemux && !ffArstmux); std::swap(ffA, ffAD); - std::swap(ffAmux, ffADmux); + std::swap(ffAcemux, ffADcemux); + std::swap(ffArstmux, ffADrstmux); ffAcepol = ffADcepol; + ffArstpol = ffADrstpol; } endcode -code argQ ffB ffBmux ffBcepol sigB clock +code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock if (param(dsp, \BREG).as_int() == 0) { argQ = sigB; subpattern(in_dffe); @@ -136,15 +143,17 @@ code argQ ffB ffBmux ffBcepol sigB clock ffB = dff; clock = dffclock; if (dffcemux) { - ffBmux = dffcemux; + ffBcemux = dffcemux; + ffBrstmux = dffrstmux; ffBcepol = dffcepol; + ffBrstpol = dffrstpol; } sigB = dffD; } } endcode -code argQ ffD ffDmux ffDcepol sigD clock +code argQ ffD ffDcemux ffDrstmux ffDcepol ffDrstpol sigD clock if (param(dsp, \DREG).as_int() == 0) { argQ = sigD; subpattern(in_dffe); @@ -152,8 +161,10 @@ code argQ ffD ffDmux ffDcepol sigD clock ffD = dff; clock = dffclock; if (dffcemux) { - ffDmux = dffcemux; + ffDcemux = dffcemux; + ffDrstmux = dffrstmux; ffDcepol = dffcepol; + ffDrstpol = dffrstpol; } sigD = dffD; } @@ -255,16 +266,18 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -code argQ ffC ffCmux ffCcepol sigC clock - if (param(dsp, \CREG).as_int() == 0) { +code argQ ffC ffCcemux ffCrstmux ffCcepol ffCrstpol sigC clock + if (param(dsp, \CREG).as_int() == 0 && sigC != sigP) { argQ = sigC; subpattern(in_dffe); if (dff) { ffC = dff; clock = dffclock; if (dffcemux) { - ffCmux = dffcemux; + ffCcemux = dffcemux; + ffCrstmux = dffrstmux; ffCcepol = dffcepol; + ffCrstpol = dffrstpol; } sigC = dffD; } @@ -278,67 +291,102 @@ endcode // ####################### subpattern in_dffe -arg argQ clock ffcepol +arg argD argQ clock + +code + dff = nullptr; + for (auto c : argQ.chunks()) { + if (!c.wire) + reject; + if (c.wire->get_bool_attribute(\keep)) + reject; + } +endcode match ff select ff->type.in($dff) // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() - filter GetSize(port(ff, \Q)) >= GetSize(argQ) - slice offset GetSize(port(ff, \Q)) - filter offset+GetSize(argQ) <= GetSize(port(ff, \Q)) - filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - semioptional + + slice offset GetSize(port(ff, \D)) + index <SigBit> port(ff, \Q)[offset] === argQ[0] + set ffoffset offset endmatch -code argQ - if (ff) { - for (auto c : argQ.chunks()) - if (c.wire->get_bool_attribute(\keep)) - reject; +code argQ argD +{ + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + } - if (clock != SigBit()) { - if (port(ff, \CLK) != clock) - reject; - } - dffclock = port(ff, \CLK); + SigSpec Q = port(ff, \Q); + if (ffoffset + GetSize(argQ) > GetSize(Q)) + reject; + for (int i = 1; i < GetSize(argQ); i++) + if (Q[ffoffset+i] != argQ[i]) + reject; - dff = ff; - dffD = argQ; - dffD.replace(port(ff, \Q), port(ff, \D)); - // Only search for ffcemux if argQ has at - // least 3 users (ff, <upstream>, ffcemux) and - // its ff.D only has two (ff, ffcemux) + dff = ff; + dffclock = port(ff, \CLK); + dffD = argQ; + argD = port(ff, \D); + argQ = Q; + dffD.replace(argQ, argD); + // Only search for ffrstmux if dffD only + // has two (ff, ffrstmux) users + if (nusers(dffD) > 2) + argD = SigSpec(); +} +endcode + +match ffrstmux + if !argD.empty() + select ffrstmux->type.in($mux) + index <SigSpec> port(ffrstmux, \Y) === argD + + choice <IdString> BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define <bool> pol (BA == \B) + set ffrstpol pol + semioptional +endmatch + +code argD + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, ffrstpol ? \A : \B); + dffD.replace(port(ffrstmux, \Y), argD); + + // Only search for ffrstmux if argQ has at + // least 3 users (ff, <upstream>, ffrstmux) and + // dffD only has two (ff, ffrstmux) if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) - argQ = SigSpec(); - } - else { - dff = nullptr; - argQ = SigSpec(); + argD = SigSpec(); } + else + dffrstmux = nullptr; endcode match ffcemux - if !argQ.empty() + if !argD.empty() select ffcemux->type.in($mux) - index <SigSpec> port(ffcemux, \Y) === port(ff, \D) - filter GetSize(port(ffcemux, \Y)) >= GetSize(dffD) - slice offset GetSize(port(ffcemux, \Y)) - filter offset+GetSize(dffD) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, \Y).extract(offset, GetSize(dffD)) == dffD + index <SigSpec> port(ffcemux, \Y) === argD choice <IdString> AB {\A, \B} - filter offset+GetSize(argQ) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, AB).extract(offset, GetSize(argQ)) == argQ + index <SigSpec> port(ffcemux, AB) === argQ define <bool> pol (AB == \A) set ffcepol pol semioptional endmatch -code +code argD if (ffcemux) { dffcemux = ffcemux; dffcepol = ffcepol; - dffD = port(ffcemux, dffcepol ? \B : \A); + dffD.replace(port(ffcemux, \Y), argD); } else dffcemux = nullptr; @@ -379,7 +427,6 @@ code argD argQ SigSpec BA = port(ffcemux, ffcepol ? \B : \A); if (ffoffset + GetSize(argD) > GetSize(BA)) reject; - for (int i = 1; i < GetSize(argD); i++) if (BA[ffoffset+i] != argD[i]) reject; @@ -440,7 +487,7 @@ match ff select param(ff, \CLK_POLARITY).as_bool() slice offset GetSize(port(ff, \D)) - index <SigSpec> port(ff, \D)[offset] === argD[0] + index <SigBit> port(ff, \D)[offset] === argD[0] filter (!ffcemux && !ffrstmux) || ffoffset == offset set ffoffset offset |