From af147d14300a8fbff2db8d823cf3622ec5a81ca6 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 10 Sep 2019 20:51:48 -0700 Subject: [PATCH] Add support for RSTP --- passes/pmgen/xilinx_dsp.cc | 16 ++++++-- passes/pmgen/xilinx_dsp.pmg | 80 +++++++++++++++++++++++++++---------- 2 files changed, 70 insertions(+), 26 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index a5fa67083..fe82b1307 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -273,7 +273,8 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) log("postAdd: %s\n", log_id(st.postAdd, "--")); log("postAddMux: %s\n", log_id(st.postAddMux, "--")); log("ffP: %s\n", log_id(st.ffP, "--")); - log("ffPmux: %s\n", log_id(st.ffPmux, "--")); + log("ffPcemux: %s\n", log_id(st.ffPcemux, "--")); + log("ffPrstmux: %s\n", log_id(st.ffPrstmux, "--")); #endif log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp)); @@ -431,10 +432,17 @@ void pack_xilinx_dsp(dict &bit_to_driver, xilinx_dsp_pm &pm) pm.autoremove(st.ffM); } if (st.ffP) { - if (st.ffPmux) { - SigSpec S = st.ffPmux->getPort("\\S"); + if (st.ffPrstmux) { + SigSpec S = st.ffPrstmux->getPort("\\S"); + cell->setPort("\\RSTP", st.ffPrstpol ? S : pm.module->Not(NEW_ID, S)); + st.ffPrstmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + } + else + cell->setPort("\\RSTP", State::S1); + if (st.ffPcemux) { + SigSpec S = st.ffPcemux->getPort("\\S"); cell->setPort("\\CEP", st.ffPcepol ? S : pm.module->Not(NEW_ID, S)); - st.ffPmux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); + st.ffPcemux->connections_.at("\\Y").replace(P, pm.module->addWire(NEW_ID, GetSize(P))); } else cell->setPort("\\CEP", State::S1); diff --git a/passes/pmgen/xilinx_dsp.pmg b/passes/pmgen/xilinx_dsp.pmg index ee9ea1312..05837d057 100644 --- a/passes/pmgen/xilinx_dsp.pmg +++ b/passes/pmgen/xilinx_dsp.pmg @@ -4,19 +4,18 @@ state > unextend state clock state sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state postAddAB postAddMuxAB -state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol ffPrstpol state ffPoffset -state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux +state ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPcemux ffPrstmux // subpattern state argQ argD -state ffcepol -state ffmux +state ffcepol ffrstpol udata dffD dffQ udata dffclock -udata dff dffcemux -udata dffcepol +udata dff dffcemux dffrstmux +udata dffcepol dffrstpol match dsp select dsp->type.in(\DSP48E1) @@ -213,11 +212,11 @@ code sigC sigP } endcode -code argD ffP ffPmux ffPcepol sigP clock +code argD ffP ffPcemux ffPrstmux ffPcepol ffPrstpol 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 and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPcemux if ((ffMmux && !postAdd && nusers(sigP) == 3) || - // Otherwise new-value net must have exactly two users: dsp and ffPmux + // Otherwise new-value net must have exactly two users: dsp and ffPcemux ((!ffMmux || postAdd) && nusers(sigP) == 2)) { argD = sigP; subpattern(out_dffe); @@ -225,8 +224,10 @@ code argD ffP ffPmux ffPcepol sigP clock ffP = dff; clock = dffclock; if (dffcemux) { - ffPmux = dffcemux; + ffPcemux = dffcemux; ffPcepol = dffcepol; + ffPrstmux = dffrstmux; + ffPrstpol = dffrstpol; } sigP = dffQ; } @@ -343,8 +344,8 @@ endcode // ####################### subpattern out_dffe -arg argD clock ffcepol -arg unextend ffmux +arg argD argQ clock +arg unextend match ffcemux select ffcemux->type.in($mux) @@ -356,14 +357,11 @@ match ffcemux // new-value net must have exactly two users: (upstream) and ffcemux select nusers(port(ffcemux, BA)) == 2 - slice offset GetSize(port(ffcemux, \Y)) - filter offset+GetSize(argD) <= GetSize(port(ffcemux, \Y)) - filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD - define AB (BA == \B ? \A : \B) // keep-last-value net must have at least three users: ffcemux, ff, downstream sink(s) select nusers(port(ffcemux, AB)) >= 3 + slice offset GetSize(port(ffcemux, \Y)) filter GetSize(unextend(port(ffcemux, BA))) <= GetSize(argD) filter unextend(port(ffcemux, BA)) == argD.extract(0, GetSize(unextend(port(ffcemux, BA)))) // Remaining bits on argD must not have any other users @@ -374,24 +372,62 @@ match ffcemux semioptional endmatch -code argD ffmux +code argD argQ if (ffcemux) { dffcemux = ffcemux; dffcepol = ffcepol; argD = port(ffcemux, \Y); - ffmux = ffcemux; + argQ = port(ffcemux, ffcepol ? \A : \B); } else dffcemux = nullptr; endcode +match ffrstmux + if !argQ.empty() + select ffrstmux->type.in($mux) + // ffrstmux output must have two users: ffrstmux and ff.D + select nusers(port(ffrstmux, \Y)) == 2 + filter GetSize(port(ffrstmux, \Y)) >= GetSize(argD) + + choice BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define AB (BA == \B ? \A : \B) + // keep-last-value net must have exactly 2 users: ffrstmux, ffcemux/ + select nusers(port(ffrstmux, AB)) == 2 + + slice offset GetSize(port(ffrstmux, \Y)) + filter GetSize(port(ffrstmux, AB)) <= GetSize(argD) + filter port(ffrstmux, AB) == argD.extract(0, GetSize(port(ffrstmux, AB))) + // Remaining bits on argD must not have any other users + filter nusers(argD.extract_end(GetSize(port(ffrstmux, AB)))) <= 1 + + define pol (AB == \A) + set ffrstpol pol + semioptional +endmatch + +code argD argQ + if (ffrstmux) { + dffrstmux = ffrstmux; + dffrstpol = ffrstpol; + argD = port(ffrstmux, \Y); + } + else { + dffrstmux = nullptr; + argQ = SigSpec(); + } +endcode + match ff_enable - if ffmux + if !argQ.empty() select ff_enable->type.in($dff) // DSP48E1 does not support clock inversion select param(ff_enable, \CLK_POLARITY).as_bool() index port(ff_enable, \D) === argD - index port(ff_enable, \Q) === port(ffmux, ffcepol ? \A : \B) + index port(ff_enable, \Q) === argQ endmatch match ff @@ -421,7 +457,7 @@ code } dffclock = port(dff, \CLK); } - // No enable mux possible without flop - else if (ffmux) + // No enable/reset mux possible without flop + else if (ffcemux || ffrstmux) reject; endcode -- 2.30.2