From cf606998847a286a52f01d748372df396b59dd2b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marcelina=20Ko=C5=9Bcielnicka?= Date: Wed, 22 Jul 2020 13:34:11 +0200 Subject: [PATCH] synth_ice40: Use opt_dff. The main part is converting ice40_dsp to recognize the new FF types created in opt_dff instead of trying to recognize the mux patterns on its own. The fsm call has been moved upwards because the passes cannot deal with $dffe/$sdff*, and other optimizations don't help it much anyway. --- passes/pmgen/ice40_dsp.cc | 38 ++--- passes/pmgen/ice40_dsp.pmg | 295 ++++++++-------------------------- techlibs/ice40/Makefile.inc | 1 - techlibs/ice40/ice40_ffssr.cc | 131 --------------- techlibs/ice40/ice40_opt.cc | 4 +- techlibs/ice40/synth_ice40.cc | 12 +- tests/arch/ice40/fsm.ys | 2 +- 7 files changed, 93 insertions(+), 390 deletions(-) delete mode 100644 techlibs/ice40/ice40_ffssr.cc diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index fff04074b..c46f5d58f 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -31,15 +31,15 @@ void create_ice40_dsp(ice40_dsp_pm &pm) log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); - log_debug("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAholdmux, "--"), log_id(st.ffArstmux, "--")); - log_debug("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBholdmux, "--"), log_id(st.ffBrstmux, "--")); - log_debug("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDholdmux, "--")); + log_debug("ffA: %s\n", log_id(st.ffA, "--")); + log_debug("ffB: %s\n", log_id(st.ffB, "--")); + log_debug("ffCD: %s\n", log_id(st.ffCD, "--")); log_debug("mul: %s\n", log_id(st.mul, "--")); log_debug("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); log_debug("ffH: %s\n", log_id(st.ffH, "--")); log_debug("add: %s\n", log_id(st.add, "--")); log_debug("mux: %s\n", log_id(st.mux, "--")); - log_debug("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOholdmux, "--"), log_id(st.ffOrstmux, "--")); + log_debug("ffO: %s\n", log_id(st.ffO, "--")); log_debug("\n"); if (GetSize(st.sigA) > 16) { @@ -97,16 +97,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam(ID(D_REG), st.ffCD ? State::S1 : State::S0); SigSpec AHOLD, BHOLD, CDHOLD; - if (st.ffAholdmux) - AHOLD = st.ffAholdpol ? st.ffAholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffAholdmux->getPort(ID::S)); + if (st.ffA && st.ffA->hasPort(ID::EN)) + AHOLD = st.ffA->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffA->getPort(ID::EN)) : st.ffA->getPort(ID::EN); else AHOLD = State::S0; - if (st.ffBholdmux) - BHOLD = st.ffBholdpol ? st.ffBholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBholdmux->getPort(ID::S)); + if (st.ffB && st.ffB->hasPort(ID::EN)) + BHOLD = st.ffB->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffB->getPort(ID::EN)) : st.ffB->getPort(ID::EN); else BHOLD = State::S0; - if (st.ffCDholdmux) - CDHOLD = st.ffCDholdpol ? st.ffCDholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffCDholdmux->getPort(ID::S)); + if (st.ffCD && st.ffCD->hasPort(ID::EN)) + CDHOLD = st.ffCD->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffCD->getPort(ID::EN)) : st.ffCD->getPort(ID::EN); else CDHOLD = State::S0; cell->setPort(ID(AHOLD), AHOLD); @@ -115,12 +115,12 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort(ID(DHOLD), CDHOLD); SigSpec IRSTTOP, IRSTBOT; - if (st.ffArstmux) - IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffArstmux->getPort(ID::S)); + if (st.ffA && st.ffA->hasPort(ID::ARST)) + IRSTTOP = st.ffA->getParam(ID::ARST_POLARITY).as_bool() ? st.ffA->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffA->getPort(ID::ARST)); else IRSTTOP = State::S0; - if (st.ffBrstmux) - IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffBrstmux->getPort(ID::S)); + if (st.ffB && st.ffB->hasPort(ID::ARST)) + IRSTBOT = st.ffB->getParam(ID::ARST_POLARITY).as_bool() ? st.ffB->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffB->getPort(ID::ARST)); else IRSTBOT = State::S0; cell->setPort(ID(IRSTTOP), IRSTTOP); @@ -207,16 +207,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm) } SigSpec OHOLD; - if (st.ffOholdmux) - OHOLD = st.ffOholdpol ? st.ffOholdmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOholdmux->getPort(ID::S)); + if (st.ffO && st.ffO->hasPort(ID::EN)) + OHOLD = st.ffO->getParam(ID::EN_POLARITY).as_bool() ? pm.module->Not(NEW_ID, st.ffO->getPort(ID::EN)) : st.ffO->getPort(ID::EN); else OHOLD = State::S0; cell->setPort(ID(OHOLDTOP), OHOLD); cell->setPort(ID(OHOLDBOT), OHOLD); SigSpec ORST; - if (st.ffOrstmux) - ORST = st.ffOrstpol ? st.ffOrstmux->getPort(ID::S) : pm.module->Not(NEW_ID, st.ffOrstmux->getPort(ID::S)); + if (st.ffO && st.ffO->hasPort(ID::ARST)) + ORST = st.ffO->getParam(ID::ARST_POLARITY).as_bool() ? st.ffO->getPort(ID::ARST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::ARST)); else ORST = State::S0; cell->setPort(ID(ORSTTOP), ORST); @@ -228,6 +228,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm) acc_reset = st.mux->getPort(ID::S); else acc_reset = pm.module->Not(NEW_ID, st.mux->getPort(ID::S)); + } else if (st.ffO && st.ffO->hasPort(ID::SRST)) { + acc_reset = st.ffO->getParam(ID::SRST_POLARITY).as_bool() ? st.ffO->getPort(ID::SRST) : pm.module->Not(NEW_ID, st.ffO->getPort(ID::SRST)); } cell->setPort(ID(OLOADTOP), acc_reset); cell->setPort(ID(OLOADBOT), acc_reset); diff --git a/passes/pmgen/ice40_dsp.pmg b/passes/pmgen/ice40_dsp.pmg index 2456a49dc..7a01cbd51 100644 --- a/passes/pmgen/ice40_dsp.pmg +++ b/passes/pmgen/ice40_dsp.pmg @@ -6,20 +6,16 @@ state sigA sigB sigCD sigH sigO state add mux state addAB muxAB -state ffAholdpol ffBholdpol ffCDholdpol ffOholdpol -state ffArstpol ffBrstpol ffCDrstpol ffOrstpol - -state ffA ffAholdmux ffArstmux ffB ffBholdmux ffBrstmux ffCD ffCDholdmux -state ffFJKG ffH ffO ffOholdmux ffOrstmux +state ffA ffB ffCD +state ffFJKG ffH ffO // subpattern +state argSdff state argQ argD -state ffholdpol ffrstpol -state ffoffset udata dffD dffQ udata dffclock -udata dff dffholdmux dffrstmux -udata dffholdpol dffrstpol dffclock_pol +udata dff +udata dffclock_pol match mul select mul->type.in($mul, \SB_MAC16) @@ -64,7 +60,7 @@ code sigA sigB sigH log_assert(nusers(O.extract_end(i)) <= 1); endcode -code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol +code argQ ffA sigA clock clock_pol if (mul->type != \SB_MAC16 || !param(mul, \A_REG).as_bool()) { argQ = sigA; subpattern(in_dffe); @@ -72,20 +68,12 @@ code argQ ffA ffAholdmux ffArstmux ffAholdpol ffArstpol sigA clock clock_pol ffA = dff; clock = dffclock; clock_pol = dffclock_pol; - if (dffrstmux) { - ffArstmux = dffrstmux; - ffArstpol = dffrstpol; - } - if (dffholdmux) { - ffAholdmux = dffholdmux; - ffAholdpol = dffholdpol; - } sigA = dffD; } } endcode -code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol +code argQ ffB sigB clock clock_pol if (mul->type != \SB_MAC16 || !param(mul, \B_REG).as_bool()) { argQ = sigB; subpattern(in_dffe); @@ -93,47 +81,44 @@ code argQ ffB ffBholdmux ffBrstmux ffBholdpol ffBrstpol sigB clock clock_pol ffB = dff; clock = dffclock; clock_pol = dffclock_pol; - if (dffrstmux) { - ffBrstmux = dffrstmux; - ffBrstpol = dffrstpol; - } - if (dffholdmux) { - ffBholdmux = dffholdmux; - ffBholdpol = dffholdpol; - } sigB = dffD; } } endcode -code argD ffFJKG sigH clock clock_pol +code argD argSdff ffFJKG sigH clock clock_pol if (nusers(sigH) == 2 && (mul->type != \SB_MAC16 || (!param(mul, \TOP_8x8_MULT_REG).as_bool() && !param(mul, \BOT_8x8_MULT_REG).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool() && !param(mul, \PIPELINE_16x16_MULT_REG1).as_bool()))) { argD = sigH; + argSdff = false; subpattern(out_dffe); if (dff) { // F/J/K/G do not have a CE-like (hold) input - if (dffholdmux) + if (dff->hasPort(\EN)) goto reject_ffFJKG; // Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT) // shared with A and B - if ((ffArstmux != NULL) != (dffrstmux != NULL)) - goto reject_ffFJKG; - if ((ffBrstmux != NULL) != (dffrstmux != NULL)) - goto reject_ffFJKG; - if (ffArstmux) { - if (port(ffArstmux, \S) != port(dffrstmux, \S)) - goto reject_ffFJKG; - if (ffArstpol != dffrstpol) + if (ffA) { + if (ffA->hasPort(\ARST) != dff->hasPort(\ARST)) goto reject_ffFJKG; + if (ffA->hasPort(\ARST)) { + if (port(ffA, \ARST) != port(dff, \ARST)) + goto reject_ffFJKG; + if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY)) + goto reject_ffFJKG; + } } - if (ffBrstmux) { - if (port(ffBrstmux, \S) != port(dffrstmux, \S)) - goto reject_ffFJKG; - if (ffBrstpol != dffrstpol) + if (ffB) { + if (ffB->hasPort(\ARST) != dff->hasPort(\ARST)) goto reject_ffFJKG; + if (ffB->hasPort(\ARST)) { + if (port(ffB, \ARST) != port(dff, \ARST)) + goto reject_ffFJKG; + if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY)) + goto reject_ffFJKG; + } } ffFJKG = dff; @@ -146,23 +131,24 @@ reject_ffFJKG: ; } endcode -code argD ffH sigH sigO clock clock_pol +code argD argSdff ffH sigH sigO clock clock_pol if (ffFJKG && nusers(sigH) == 2 && (mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) { argD = sigH; + argSdff = false; subpattern(out_dffe); if (dff) { // H does not have a CE-like (hold) input - if (dffholdmux) + if (dff->hasPort(\EN)) goto reject_ffH; // Reset signal of H (IRSTBOT) shared with B - if ((ffBrstmux != NULL) != (dffrstmux != NULL)) + if (ffB->hasPort(\ARST) != dff->hasPort(\ARST)) goto reject_ffH; - if (ffBrstmux) { - if (port(ffBrstmux, \S) != port(dffrstmux, \S)) + if (ffB->hasPort(\ARST)) { + if (port(ffB, \ARST) != port(dff, \ARST)) goto reject_ffH; - if (ffBrstpol != dffrstpol) + if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY)) goto reject_ffH; } @@ -226,7 +212,7 @@ code sigO sigO = port(mux, \Y); endcode -code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_pol cd_signed o_lo +code argD argSdff ffO sigO sigCD clock clock_pol cd_signed o_lo if (mul->type != \SB_MAC16 || // Ensure that register is not already used ((param(mul, \TOPOUTPUT_SELECT).as_int() != 1 && param(mul, \BOTOUTPUT_SELECT).as_int() != 1) && @@ -238,6 +224,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p // First try entire sigO if (nusers(sigO) == 2) { argD = sigO; + argSdff = !mux; subpattern(out_dffe); } @@ -245,6 +232,7 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p if (!dff && GetSize(sigO) > 16) { argD = sigO.extract(0, 16); if (nusers(argD) == 2) { + argSdff = !mux; subpattern(out_dffe); o_lo = dff; } @@ -254,14 +242,6 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p ffO = dff; clock = dffclock; clock_pol = dffclock_pol; - if (dffrstmux) { - ffOrstmux = dffrstmux; - ffOrstpol = dffrstpol; - } - if (dffholdmux) { - ffOholdmux = dffholdmux; - ffOholdpol = dffholdpol; - } sigO.replace(sigO.extract(0, GetSize(dffQ)), dffQ); } @@ -273,39 +253,44 @@ code argD ffO ffOholdmux ffOrstmux ffOholdpol ffOrstpol sigO sigCD clock clock_p reject; sigCD = port(mux, muxAB == \B ? \A : \B); + cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool(); + } else if (dff && dff->hasPort(\SRST)) { + if (sigCD != sigO) + reject; + sigCD = param(dff, \SRST_VALUE); + cd_signed = add && param(add, \A_SIGNED).as_bool() && param(add, \B_SIGNED).as_bool(); } } endcode -code argQ ffCD ffCDholdmux ffCDholdpol ffCDrstpol sigCD clock clock_pol +code argQ ffCD sigCD clock clock_pol if (!sigCD.empty() && sigCD != sigO && (mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) { argQ = sigCD; subpattern(in_dffe); if (dff) { - if (dffholdmux) { - ffCDholdmux = dffholdmux; - ffCDholdpol = dffholdpol; - } - // Reset signal of C (IRSTTOP) and D (IRSTBOT) // shared with A and B - if ((ffArstmux != NULL) != (dffrstmux != NULL)) - goto reject_ffCD; - if ((ffBrstmux != NULL) != (dffrstmux != NULL)) - goto reject_ffCD; - if (ffArstmux) { - if (port(ffArstmux, \S) != port(dffrstmux, \S)) - goto reject_ffCD; - if (ffArstpol != dffrstpol) + if (ffA) { + if (ffA->hasPort(\ARST) != dff->hasPort(\ARST)) goto reject_ffCD; + if (ffA->hasPort(\ARST)) { + if (port(ffA, \ARST) != port(dff, \ARST)) + goto reject_ffCD; + if (param(ffA, \ARST_POLARITY) != param(dff, \ARST_POLARITY)) + goto reject_ffCD; + } } - if (ffBrstmux) { - if (port(ffBrstmux, \S) != port(dffrstmux, \S)) - goto reject_ffCD; - if (ffBrstpol != dffrstpol) + if (ffB) { + if (ffB->hasPort(\ARST) != dff->hasPort(\ARST)) goto reject_ffCD; + if (ffB->hasPort(\ARST)) { + if (port(ffB, \ARST) != port(dff, \ARST)) + goto reject_ffCD; + if (param(ffB, \ARST_POLARITY) != param(dff, \ARST_POLARITY)) + goto reject_ffCD; + } } ffCD = dff; @@ -347,7 +332,7 @@ code endcode match ff - select ff->type.in($dff) + select ff->type.in($dff, $dffe) // DSP48E1 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() @@ -357,8 +342,6 @@ match ff // Check that the rest of argQ is present filter GetSize(port(ff, \Q)) >= offset + GetSize(argQ) filter port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - - set ffoffset offset endmatch code argQ argD @@ -378,72 +361,13 @@ code argQ argD 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 false /* TODO: ice40 resets are actually async */ - - if !argD.empty() - select ffrstmux->type.in($mux) - index port(ffrstmux, \Y) === argD - - choice BA {\B, \A} - // DSP48E1 only supports reset to zero - select port(ffrstmux, BA).is_fully_zero() - - define 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 ffholdmux if argQ has at - // least 3 users (ff, , ffrstmux) and - // dffD only has two (ff, ffrstmux) - if (!(nusers(argQ) >= 3 && nusers(dffD) == 2)) - argD = SigSpec(); - } - else - dffrstmux = nullptr; -endcode - -match ffholdmux - if !argD.empty() - select ffholdmux->type.in($mux) - index port(ffholdmux, \Y) === argD - choice BA {\B, \A} - index port(ffholdmux, BA) === argQ - define pol (BA == \B) - set ffholdpol pol - semioptional -endmatch - -code argD - if (ffholdmux) { - dffholdmux = ffholdmux; - dffholdpol = ffholdpol; - argD = port(ffholdmux, ffholdpol ? \A : \B); - dffD.replace(port(ffholdmux, \Y), argD); - } - else - dffholdmux = nullptr; -endcode - // ####################### subpattern out_dffe -arg argD argQ clock clock_pol +arg argD argSdff argQ clock clock_pol code dff = nullptr; @@ -452,101 +376,19 @@ code reject; endcode -match ffholdmux - select ffholdmux->type.in($mux) - // ffholdmux output must have two users: ffholdmux and ff.D - select nusers(port(ffholdmux, \Y)) == 2 - - choice BA {\B, \A} - // keep-last-value net must have at least three users: ffholdmux, ff, downstream sink(s) - select nusers(port(ffholdmux, BA)) >= 3 - - slice offset GetSize(port(ffholdmux, \Y)) - define AB (BA == \B ? \A : \B) - index port(ffholdmux, AB)[offset] === argD[0] - - // Check that the rest of argD is present - filter GetSize(port(ffholdmux, AB)) >= offset + GetSize(argD) - filter port(ffholdmux, AB).extract(offset, GetSize(argD)) == argD - - set ffoffset offset - define pol (BA == \B) - set ffholdpol pol - - semioptional -endmatch - -code argD argQ - dffholdmux = ffholdmux; - if (ffholdmux) { - SigSpec AB = port(ffholdmux, ffholdpol ? \A : \B); - SigSpec Y = port(ffholdmux, \Y); - argQ = argD; - argD.replace(AB, Y); - argQ.replace(AB, port(ffholdmux, ffholdpol ? \B : \A)); - - dffholdmux = ffholdmux; - dffholdpol = ffholdpol; - } -endcode - -match ffrstmux - if false /* TODO: ice40 resets are actually async */ - - select ffrstmux->type.in($mux) - // ffrstmux output must have two users: ffrstmux and ff.D - select nusers(port(ffrstmux, \Y)) == 2 - - choice BA {\B, \A} - // DSP48E1 only supports reset to zero - select port(ffrstmux, BA).is_fully_zero() - - slice offset GetSize(port(ffrstmux, \Y)) - define AB (BA == \B ? \A : \B) - index port(ffrstmux, AB)[offset] === argD[0] - - // Check that offset is consistent - filter !ffholdmux || ffoffset == offset - // Check that the rest of argD is present - filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD) - filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD - - set ffoffset offset - define pol (AB == \A) - set ffrstpol pol - - semioptional -endmatch - -code argD argQ - dffrstmux = ffrstmux; - if (ffrstmux) { - SigSpec AB = port(ffrstmux, ffrstpol ? \A : \B); - SigSpec Y = port(ffrstmux, \Y); - argD.replace(AB, Y); - - dffrstmux = ffrstmux; - dffrstpol = ffrstpol; - } -endcode - match ff - select ff->type.in($dff) + select ff->type.in($dff, $dffe, $sdff, $sdffce) // SB_MAC16 does not support clock inversion select param(ff, \CLK_POLARITY).as_bool() slice offset GetSize(port(ff, \D)) index port(ff, \D)[offset] === argD[0] - // Check that offset is consistent - filter (!ffholdmux && !ffrstmux) || ffoffset == offset + // Only allow sync reset if requested. + filter argSdff || ff->type.in($dff, $dffe) // Check that the rest of argD is present filter GetSize(port(ff, \D)) >= offset + GetSize(argD) filter port(ff, \D).extract(offset, GetSize(argD)) == argD - // Check that FF.Q is connected to CE-mux - filter !ffholdmux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ - - set ffoffset offset endmatch code argQ @@ -559,10 +401,8 @@ code argQ } SigSpec D = port(ff, \D); SigSpec Q = port(ff, \Q); - if (!ffholdmux) { - argQ = argD; - argQ.replace(D, Q); - } + argQ = argD; + argQ.replace(D, Q); for (auto c : argQ.chunks()) { Const init = c.wire->attributes.at(\init, State::Sx); @@ -575,7 +415,4 @@ code argQ dffclock = port(ff, \CLK); dffclock_pol = param(ff, \CLK_POLARITY).as_bool(); } - // No enable/reset mux possible without flop - else if (dffholdmux || dffrstmux) - reject; endcode diff --git a/techlibs/ice40/Makefile.inc b/techlibs/ice40/Makefile.inc index 4f4faf6d5..8ce3cb024 100644 --- a/techlibs/ice40/Makefile.inc +++ b/techlibs/ice40/Makefile.inc @@ -1,7 +1,6 @@ OBJS += techlibs/ice40/synth_ice40.o OBJS += techlibs/ice40/ice40_braminit.o -OBJS += techlibs/ice40/ice40_ffssr.o OBJS += techlibs/ice40/ice40_opt.o GENFILES += techlibs/ice40/brams_init1.vh diff --git a/techlibs/ice40/ice40_ffssr.cc b/techlibs/ice40/ice40_ffssr.cc deleted file mode 100644 index 492029b77..000000000 --- a/techlibs/ice40/ice40_ffssr.cc +++ /dev/null @@ -1,131 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct Ice40FfssrPass : public Pass { - Ice40FfssrPass() : Pass("ice40_ffssr", "iCE40: merge synchronous set/reset into FF cells") { } - void help() override - { - log("\n"); - log(" ice40_ffssr [options] [selection]\n"); - log("\n"); - log("Merge synchronous set/reset $_MUX_ cells into iCE40 FFs.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing ICE40_FFSSR pass (merge synchronous set/reset into FF cells).\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) - { - // if (args[argidx] == "-singleton") { - // singleton_mode = true; - // continue; - // } - break; - } - extra_args(args, argidx, design); - - pool sb_dff_types; - sb_dff_types.insert(ID(SB_DFF)); - sb_dff_types.insert(ID(SB_DFFE)); - sb_dff_types.insert(ID(SB_DFFN)); - sb_dff_types.insert(ID(SB_DFFNE)); - - for (auto module : design->selected_modules()) - { - log("Merging set/reset $_MUX_ cells into SB_FFs in %s.\n", log_id(module)); - - SigMap sigmap(module); - dict sr_muxes; - vector ff_cells; - - for (auto cell : module->selected_cells()) - { - if (sb_dff_types.count(cell->type)) { - ff_cells.push_back(cell); - continue; - } - - if (cell->type != ID($_MUX_)) - continue; - - SigBit bit_a = sigmap(cell->getPort(ID::A)); - SigBit bit_b = sigmap(cell->getPort(ID::B)); - - if (bit_a.wire == nullptr || bit_b.wire == nullptr) - sr_muxes[sigmap(cell->getPort(ID::Y))] = cell; - } - - for (auto cell : ff_cells) - { - if (cell->get_bool_attribute(ID(dont_touch))) - continue; - - SigSpec sig_d = cell->getPort(ID::D); - - if (GetSize(sig_d) < 1) - continue; - - SigBit bit_d = sigmap(sig_d[0]); - - if (sr_muxes.count(bit_d) == 0) - continue; - - Cell *mux_cell = sr_muxes.at(bit_d); - SigBit bit_a = sigmap(mux_cell->getPort(ID::A)); - SigBit bit_b = sigmap(mux_cell->getPort(ID::B)); - SigBit bit_s = sigmap(mux_cell->getPort(ID::S)); - - log(" Merging %s (A=%s, B=%s, S=%s) into %s (%s).\n", log_id(mux_cell), - log_signal(bit_a), log_signal(bit_b), log_signal(bit_s), log_id(cell), log_id(cell->type)); - - SigBit sr_val, sr_sig; - if (bit_a.wire == nullptr) { - bit_d = bit_b; - sr_val = bit_a; - sr_sig = module->NotGate(NEW_ID, bit_s); - } else { - log_assert(bit_b.wire == nullptr); - bit_d = bit_a; - sr_val = bit_b; - sr_sig = bit_s; - } - - if (sr_val == State::S1) { - cell->type = cell->type.str() + "SS"; - cell->setPort(ID::S, sr_sig); - cell->setPort(ID::D, bit_d); - } else { - cell->type = cell->type.str() + "SR"; - cell->setPort(ID::R, sr_sig); - cell->setPort(ID::D, bit_d); - } - } - } - } -} Ice40FfssrPass; - -PRIVATE_NAMESPACE_END diff --git a/techlibs/ice40/ice40_opt.cc b/techlibs/ice40/ice40_opt.cc index 1a70fa8c0..d28607904 100644 --- a/techlibs/ice40/ice40_opt.cc +++ b/techlibs/ice40/ice40_opt.cc @@ -215,7 +215,7 @@ struct Ice40OptPass : public Pass { log(" \n"); log(" opt_expr -mux_undef -undriven [-full]\n"); log(" opt_merge\n"); - log(" opt_rmdff\n"); + log(" opt_dff\n"); log(" opt_clean\n"); log(" while \n"); log("\n"); @@ -247,7 +247,7 @@ struct Ice40OptPass : public Pass { Pass::call(design, "opt_expr " + opt_expr_args); Pass::call(design, "opt_merge"); - Pass::call(design, "opt_rmdff"); + Pass::call(design, "opt_dff"); Pass::call(design, "opt_clean"); if (design->scratchpad_get_bool("opt.did_something") == false) diff --git a/techlibs/ice40/synth_ice40.cc b/techlibs/ice40/synth_ice40.cc index 4ddb6ca70..ae6d3539c 100644 --- a/techlibs/ice40/synth_ice40.cc +++ b/techlibs/ice40/synth_ice40.cc @@ -293,6 +293,10 @@ struct SynthIce40Pass : public ScriptPass run("opt_clean"); run("check"); run("opt"); + run("fsm"); + run("opt"); + run("opt_dff"); + run("opt"); run("wreduce"); run("peepopt"); run("opt_clean"); @@ -316,8 +320,6 @@ struct SynthIce40Pass : public ScriptPass } run("alumacc"); run("opt"); - run("fsm"); - run("opt -fast"); run("memory -nomap"); run("opt_clean"); } @@ -354,11 +356,6 @@ struct SynthIce40Pass : public ScriptPass if (check_label("map_ffs")) { - if (!nodffe) - run("dff2dffe -direct-match $_DFF_*"); - if (min_ce_use >= 0) { - run("opt_merge"); - } if (nodffe) run(stringf("dfflegalize -cell $_DFF_?_ 0 -cell $_DFF_?P?_ 0 -cell $_SDFF_?P?_ 0 -cell $_DLATCH_?_ x")); else @@ -366,7 +363,6 @@ struct SynthIce40Pass : public ScriptPass run("techmap -map +/ice40/ff_map.v"); run("opt_expr -mux_undef"); run("simplemap"); - run("ice40_ffssr"); run("ice40_opt -full"); } diff --git a/tests/arch/ice40/fsm.ys b/tests/arch/ice40/fsm.ys index 223ba070e..e3b746202 100644 --- a/tests/arch/ice40/fsm.ys +++ b/tests/arch/ice40/fsm.ys @@ -12,5 +12,5 @@ cd fsm # Constrain all select calls below inside the top module select -assert-count 4 t:SB_DFF select -assert-count 2 t:SB_DFFESR -select -assert-count 15 t:SB_LUT4 +select -assert-max 15 t:SB_LUT4 select -assert-none t:SB_DFFESR t:SB_DFF t:SB_LUT4 %% t:* %D -- 2.30.2