From 04bc287271354d3a1770ae7a9f8f1de9341b9253 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 15:51:14 -0700 Subject: [PATCH] Refactor using subpattern in_dffe --- passes/pmgen/xilinx_dsp.pmg | 386 ++++++++++++++---------------------- 1 file changed, 146 insertions(+), 240 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index 6b981bc13..e611bfb3b 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -7,11 +7,21 @@ state postAddAB postAddMuxAB state ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol state ffPoffset +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux + +// subpattern +state dffQ +state dffenpol_ +udata dffD +udata dffclock +udata dff dffmux +udata dffenpol + match dsp select dsp->type.in(\DSP48E1) endmatch -code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM +code unextend sigA sigB sigC sigD sigM unextend = [](const SigSpec &sig) { int i; for (i = GetSize(sig)-1; i > 0; i--) @@ -39,60 +49,24 @@ code unextend sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY si log_assert(nusers(P.extract_end(i)) <= 1); //if (GetSize(sigM) <= 10) // reject; - - sigffAmuxY = SigSpec(); - sigffBmuxY = SigSpec(); - sigffCmuxY = SigSpec(); - sigffDmuxY = SigSpec(); endcode -match ffAD - if param(dsp, \ADREG).as_int() == 0 - select ffAD->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffAD, \CLK_POLARITY).as_bool() - filter GetSize(port(ffAD, \Q)) >= GetSize(sigA) - slice offset GetSize(port(ffAD, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffAD, \Q)) - filter port(ffAD, \Q).extract(offset, GetSize(sigA)) == sigA - optional -endmatch - -code sigA sigffAmuxY clock - if (ffAD) { - for (auto b : port(ffAD, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - clock = port(ffAD, \CLK).as_bit(); - - SigSpec A = sigA; - A.replace(port(ffAD, \Q), port(ffAD, \D)); - // Only search for ffAmux if ffA.Q has at - // least 3 users (ffA, dsp, ffAmux) and - // its ffA.D only has two (ffA, ffAmux) - if (nusers(sigA) >= 3 && nusers(A) == 2) - sigffAmuxY = sigA; - sigA = std::move(A); +code dffQ ffAD ffADmux ffADenpol sigA clock + if (param(dsp, \ADREG).as_int() == 0) { + dffQ = sigA; + subpattern(in_dffe); + if (dff) { + ffAD = dff; + clock = dffclock; + if (dffmux) { + ffADmux = dffmux; + ffADenpol = dffenpol; + } + sigA = dffD; + } } endcode -match ffADmux - if !sigffAmuxY.empty() - select ffADmux->type.in($mux) - index port(ffADmux, \Y) === port(ffAD, \D) - filter GetSize(port(ffADmux, \Y)) >= GetSize(sigA) - slice offset GetSize(port(ffADmux, \Y)) - filter offset+GetSize(sigA) <= GetSize(port(ffADmux, \Y)) - filter port(ffADmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice AB {\A, \B} - filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffADmux, \Y)) - filter port(ffADmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (AB == \A) - set ffADenpol pol - optional -endmatch - match preAdd if sigD.empty() || sigD.is_fully_zero() // Ensure that preAdder not already used @@ -123,169 +97,66 @@ code sigA sigD } endcode -match ffA - if !preAdd - if param(dsp, \AREG).as_int() == 0 - select ffA->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffA, \CLK_POLARITY).as_bool() - filter GetSize(port(ffA, \Q)) >= GetSize(sigA) - slice offset GetSize(port(ffA, \Q)) - filter offset+GetSize(sigA) <= GetSize(port(ffA, \Q)) - filter port(ffA, \Q).extract(offset, GetSize(sigA)) == sigA - optional -endmatch - -code sigA sigffAmuxY clock - if (ffA) { - for (auto b : port(ffA, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - clock = port(ffA, \CLK).as_bit(); - - SigSpec A = sigA; - A.replace(port(ffA, \Q), port(ffA, \D)); - // Only search for ffAmux if ffA.Q has at - // least 3 users (ffA, dsp, ffAmux) and - // its ffA.D only has two (ffA, ffAmux) - if (nusers(sigA) >= 3 && nusers(A) == 2) - sigffAmuxY = sigA; - sigA = std::move(A); - } - else if (!preAdd) { - sigffAmuxY = SigSpec(); +code dffQ ffA ffAmux ffAenpol sigA clock ffAD ffADmux ffADenpol + // Only search for ffA if there was a pre-adder + // (otherwise ffA would have been matched as ffAD) + if (preAdd) { + if (param(dsp, \AREG).as_int() == 0) { + dffQ = sigA; + subpattern(in_dffe); + if (dff) { + ffA = dff; + clock = dffclock; + if (dffmux) { + ffAmux = dffmux; + ffAenpol = dffenpol; + } + sigA = dffD; + } + } } -endcode - -match ffAmux - if !sigffAmuxY.empty() - select ffAmux->type.in($mux) - index port(ffAmux, \Y) === port(ffA, \D) - filter GetSize(port(ffAmux, \Y)) >= GetSize(sigA) - slice offset GetSize(port(ffAmux, \Y)) - filter offset+GetSize(sigA) <= GetSize(port(ffAmux, \Y)) - filter port(ffAmux, \Y).extract(offset, GetSize(sigA)) == sigA - choice AB {\A, \B} - filter offset+GetSize(sigffAmuxY) <= GetSize(port(ffAmux, \Y)) - filter port(ffAmux, AB).extract(offset, GetSize(sigffAmuxY)) == sigffAmuxY - define pol (AB == \A) - set ffAenpol pol - optional -endmatch - -code ffA ffAmux ffAenpol ffAD ffADmux - // Move AD register to A if no pre-adder - if (!ffA && !preAdd && ffAD) { - ffA = ffAD; - ffAmux = ffADmux; + // And if there wasn't a pre-adder, + // move AD register to A + else if (ffAD) { + log_assert(!ffA && !ffAmux); + std::swap(ffA, ffAD); + std::swap(ffAmux, ffADmux); ffAenpol = ffADenpol; - - ffAD = nullptr; - ffADmux = nullptr; } endcode -match ffB - if param(dsp, \BREG).as_int() == 0 - select ffB->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffB, \CLK_POLARITY).as_bool() - filter GetSize(port(ffB, \Q)) >= GetSize(sigB) - slice offset GetSize(port(ffB, \Q)) - filter offset+GetSize(sigB) <= GetSize(port(ffB, \Q)) - filter port(ffB, \Q).extract(offset, GetSize(sigB)) == sigB - optional -endmatch - -code sigB sigffBmuxY clock - if (ffB) { - for (auto b : port(ffB, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffB, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec B = sigB; - B.replace(port(ffB, \Q), port(ffB, \D)); - // Only search for ffBmux if ffB.Q has at - // least 3 users (ffB, dsp, ffBmux) and - // its ffB.D only has two (ffB, ffBmux) - if (nusers(sigB) >= 3 && nusers(B) == 2) - sigffBmuxY = sigB; - sigB = std::move(B); +code dffQ ffB ffBmux ffBenpol sigB clock + if (param(dsp, \BREG).as_int() == 0) { + dffQ = sigB; + subpattern(in_dffe); + if (dff) { + ffB = dff; + clock = dffclock; + if (dffmux) { + ffBmux = dffmux; + ffBenpol = dffenpol; + } + sigB = dffD; + } } endcode -match ffBmux - if !sigffBmuxY.empty() - select ffBmux->type.in($mux) - index port(ffBmux, \Y) === port(ffB, \D) - filter GetSize(port(ffBmux, \Y)) >= GetSize(sigB) - slice offset GetSize(port(ffBmux, \Y)) - filter offset+GetSize(sigB) <= GetSize(port(ffBmux, \Y)) - filter port(ffBmux, \Y).extract(offset, GetSize(sigB)) == sigB - choice AB {\A, \B} - filter offset+GetSize(sigffBmuxY) <= GetSize(port(ffBmux, \Y)) - filter port(ffBmux, AB).extract(offset, GetSize(sigffBmuxY)) == sigffBmuxY - define pol (AB == \A) - set ffBenpol pol - optional -endmatch - -match ffD - if param(dsp, \DREG).as_int() == 0 - select ffD->type.in($dff) - // DSP48E1 does not support clock inversion - select param(ffD, \CLK_POLARITY).as_bool() - filter GetSize(port(ffD, \Q)) >= GetSize(sigD) - slice offset GetSize(port(ffD, \Q)) - filter offset+GetSize(sigD) <= GetSize(port(ffD, \Q)) - filter port(ffD, \Q).extract(offset, GetSize(sigD)) == sigD - optional -endmatch - -code sigD sigffDmuxY clock - if (ffD) { - for (auto b : port(ffD, \Q)) - if (b.wire->get_bool_attribute(\keep)) - reject; - - SigBit c = port(ffD, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec D = sigD; - D.replace(port(ffD, \Q), port(ffD, \D)); - // Only search for ffDmux if ffD.Q has at - // least 3 users (ffD, dsp, ffDmux) and - // its ffD.D only has two (ffD, ffDmux) - if (nusers(sigD) >= 3 && nusers(D) == 2) - sigffDmuxY = sigD; - sigD = std::move(D); +code dffQ ffD ffDmux ffDenpol sigD clock + if (param(dsp, \DREG).as_int() == 0) { + dffQ = sigD; + subpattern(in_dffe); + if (dff) { + ffD = dff; + clock = dffclock; + if (dffmux) { + ffDmux = dffmux; + ffDenpol = dffenpol; + } + sigD = dffD; + } } endcode -match ffDmux - if !sigffDmuxY.empty() - select ffDmux->type.in($mux) - index port(ffDmux, \Y) === port(ffD, \D) - filter GetSize(port(ffDmux, \Y)) >= GetSize(sigD) - slice offset GetSize(port(ffDmux, \Y)) - filter offset+GetSize(sigD) <= GetSize(port(ffDmux, \Y)) - filter port(ffDmux, \Y).extract(offset, GetSize(sigD)) == sigD - choice AB {\A, \B} - filter offset+GetSize(sigffDmuxY) <= GetSize(port(ffDmux, \Y)) - filter port(ffDmux, AB).extract(offset, GetSize(sigffDmuxY)) == sigffDmuxY - define pol (AB == \A) - set ffDenpol pol - optional -endmatch - match ffMmux if param(dsp, \MREG).as_int() == 0 if nusers(sigM) == 2 @@ -496,56 +367,91 @@ code sigC sigC = port(postAddMux, postAddMuxAB == \A ? \B : \A); endcode -match ffC - if param(dsp, \CREG).as_int() == 0 - select ffC->type.in($dff) +code dffQ ffC ffCmux ffCenpol sigC clock + if (param(dsp, \CREG).as_int() == 0) { + dffQ = sigC; + subpattern(in_dffe); + if (dff) { + ffC = dff; + clock = dffclock; + if (dffmux) { + ffCmux = dffmux; + ffCenpol = dffenpol; + } + sigC = dffD; + } + } +endcode + +code + accept; +endcode + +subpattern in_dffe +arg dffQ clock dffenpol_ + +code + dff = nullptr; + dffmux = nullptr; +endcode + +match ff + select ff->type.in($dff) // DSP48E1 does not support clock inversion - select param(ffC, \CLK_POLARITY).as_bool() - filter GetSize(port(ffC, \Q)) >= GetSize(sigD) - slice offset GetSize(port(ffC, \Q)) - filter offset+GetSize(sigC) <= GetSize(port(ffC, \Q)) - filter port(ffC, \Q).extract(offset, GetSize(sigC)) == sigC - optional + select param(ff, \CLK_POLARITY).as_bool() + filter GetSize(port(ff, \Q)) >= GetSize(dffQ) + slice offset GetSize(port(ff, \Q)) + filter offset+GetSize(dffQ) <= GetSize(port(ff, \Q)) + filter port(ff, \Q).extract(offset, GetSize(dffQ)) == dffQ + semioptional endmatch -code sigC sigffCmuxY clock - if (ffC) { - for (auto b : port(ffC, \Q)) +code dffQ + if (ff) { + for (auto b : dffQ) if (b.wire->get_bool_attribute(\keep)) reject; - SigBit c = port(ffC, \CLK).as_bit(); - if (clock != SigBit() && c != clock) - reject; - clock = c; - - SigSpec C = sigC; - C.replace(port(ffC, \Q), port(ffC, \D)); - // Only search for ffCmux if ffC.Q has at - // least 3 users (ffC, dsp, ffCmux) and - // its ffC.D only has two (ffC, ffCmux) - if (nusers(sigC) >= 3 && nusers(C) == 2) - sigffCmuxY = sigC; - sigC = std::move(C); + if (clock != SigBit()) { + if (port(ff, \CLK) != clock) + reject; + } + else + dffclock = port(ff, \CLK); + + dff = ff; + dffD = dffQ; + dffD.replace(port(ff, \Q), port(ff, \D)); + // Only search for ffmux if ff.Q has at + // least 3 users (ff, dsp, ffmux) and + // its ff.D only has two (ff, ffmux) + if (!(nusers(dffQ) >= 3 && nusers(dffD) == 2)) + dffQ = SigSpec(); } + else + dffQ = SigSpec(); endcode -match ffCmux - if !sigffCmuxY.empty() - select ffCmux->type.in($mux) - index port(ffCmux, \Y) === port(ffC, \D) - filter GetSize(port(ffCmux, \Y)) >= GetSize(sigC) - slice offset GetSize(port(ffCmux, \Y)) - filter offset+GetSize(sigC) <= GetSize(port(ffCmux, \Y)) - filter port(ffCmux, \Y).extract(offset, GetSize(sigC)) == sigC +match ffmux + if !dffQ.empty() + select ffmux->type.in($mux) + index port(ffmux, \Y) === port(ff, \D) + filter GetSize(port(ffmux, \Y)) >= GetSize(dffD) + slice offset GetSize(port(ffmux, \Y)) + filter offset+GetSize(dffD) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, \Y).extract(offset, GetSize(dffD)) == dffD choice AB {\A, \B} - filter offset+GetSize(sigffCmuxY) <= GetSize(port(ffCmux, \Y)) - filter port(ffCmux, AB).extract(offset, GetSize(sigffCmuxY)) == sigffCmuxY + filter offset+GetSize(dffQ) <= GetSize(port(ffmux, \Y)) + filter port(ffmux, AB).extract(offset, GetSize(dffQ)) == dffQ define pol (AB == \A) - set ffCenpol pol - optional + set dffenpol_ pol + semioptional endmatch code - accept; + if (ffmux) { + dffmux = ffmux; + dffenpol = dffenpol_; + dffD = port(ffmux, dffenpol ? \B : \A); + } endcode -- 2.30.2