diff options
author | Eddie Hung <eddie@fpgeh.com> | 2019-09-10 20:51:48 -0700 |
---|---|---|
committer | Eddie Hung <eddie@fpgeh.com> | 2019-09-10 20:51:48 -0700 |
commit | af147d14300a8fbff2db8d823cf3622ec5a81ca6 (patch) | |
tree | 74b6b9ae835396085a86c1d30d2075f9a1fa9bda /passes | |
parent | c6df55a9e7c9827a6b971cc885b83fdb69b269d3 (diff) | |
download | yosys-af147d14300a8fbff2db8d823cf3622ec5a81ca6.tar.gz yosys-af147d14300a8fbff2db8d823cf3622ec5a81ca6.tar.bz2 yosys-af147d14300a8fbff2db8d823cf3622ec5a81ca6.zip |
Add support for RSTP
Diffstat (limited to 'passes')
-rw-r--r-- | passes/pmgen/xilinx_dsp.cc | 16 | ||||
-rw-r--r-- | 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<SigBit, Cell*> &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<SigBit, Cell*> &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 <std::function<SigSpec(const SigSpec&)>> unextend state <SigBit> clock state <SigSpec> sigA sigffAmuxY sigB sigffBmuxY sigC sigffCmuxY sigD sigffDmuxY sigM sigP state <IdString> postAddAB postAddMuxAB -state <bool> ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol +state <bool> ffAcepol ffADcepol ffBcepol ffCcepol ffDcepol ffMcepol ffPcepol ffPrstpol state <int> ffPoffset -state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux +state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPcemux ffPrstmux // subpattern state <SigSpec> argQ argD -state <bool> ffcepol -state <Cell*> ffmux +state <bool> ffcepol ffrstpol udata <SigSpec> dffD dffQ udata <SigBit> dffclock -udata <Cell*> dff dffcemux -udata <bool> dffcepol +udata <Cell*> dff dffcemux dffrstmux +udata <bool> 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 <IdString> 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 <IdString> BA {\B, \A} + // DSP48E1 only supports reset to zero + select port(ffrstmux, BA).is_fully_zero() + + define <IdString> AB (BA == \B ? \A : \B) + // keep-last-value net must have exactly 2 users: ffrstmux, ffcemux/<upstream> + 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 <bool> 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 <SigSpec> port(ff_enable, \D) === argD - index <SigSpec> port(ff_enable, \Q) === port(ffmux, ffcepol ? \A : \B) + index <SigSpec> 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 |