log("\n");
log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--"));
log("ffB: %s %s %s\n", log_id(st.ffB, "--"), log_id(st.ffBcemux, "--"), log_id(st.ffBrstmux, "--"));
- log("ffCD: %s %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"), log_id(st.ffCDrstmux, "--"));
+ log("ffCD: %s %s\n", log_id(st.ffCD, "--"), log_id(st.ffCDcemux, "--"));
log("mul: %s\n", log_id(st.mul, "--"));
- log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--"));
- log("ffH: %s n/a %s\n", log_id(st.ffH, "--"), log_id(st.ffHrstmux, "--"));
+ log("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
+ log("ffH: %s\n", log_id(st.ffH, "--"));
log("add: %s\n", log_id(st.add, "--"));
log("mux: %s\n", log_id(st.mux, "--"));
- log("ffO: %s\n", log_id(st.ffO, "--"));
+ log("ffO: %s %s %s\n", log_id(st.ffO, "--"), log_id(st.ffOcemux, "--"), log_id(st.ffOrstmux, "--"));
#endif
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0);
cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0);
- cell->setPort("\\AHOLD", State::S0);
- cell->setPort("\\BHOLD", State::S0);
- cell->setPort("\\CHOLD", State::S0);
- cell->setPort("\\DHOLD", State::S0);
-
- cell->setPort("\\IRSTTOP", State::S0);
- cell->setPort("\\IRSTBOT", State::S0);
+ SigSpec AHOLD, BHOLD, CDHOLD;
+ if (st.ffAcemux)
+ AHOLD = st.ffAcepol ? pm.module->Not(NEW_ID, st.ffAcemux->getPort("\\S")) : st.ffAcemux->getPort("\\S");
+ else
+ AHOLD = State::S0;
+ if (st.ffBcemux)
+ BHOLD = st.ffBcepol ? pm.module->Not(NEW_ID, st.ffBcemux->getPort("\\S")) : st.ffBcemux->getPort("\\S");
+ else
+ BHOLD = State::S0;
+ if (st.ffCDcemux)
+ CDHOLD = st.ffCDcepol ? pm.module->Not(NEW_ID, st.ffCDcemux->getPort("\\S")) : st.ffCDcemux->getPort("\\S");
+ else
+ CDHOLD = State::S0;
+ cell->setPort("\\AHOLD", AHOLD);
+ cell->setPort("\\BHOLD", BHOLD);
+ cell->setPort("\\CHOLD", CDHOLD);
+ cell->setPort("\\DHOLD", CDHOLD);
+
+ SigSpec IRSTTOP, IRSTBOT;
+ if (st.ffArstmux)
+ IRSTTOP = st.ffArstpol ? st.ffArstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffArstmux->getPort("\\S"));
+ else
+ IRSTTOP = State::S0;
+ if (st.ffBrstmux)
+ IRSTBOT = st.ffBrstpol ? st.ffBrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffBrstmux->getPort("\\S"));
+ else
+ IRSTBOT = State::S0;
+ cell->setPort("\\IRSTTOP", IRSTTOP);
+ cell->setPort("\\IRSTBOT", IRSTBOT);
if (st.clock != SigBit())
{
cell->setPort("\\ADDSUBBOT", State::S0);
}
- cell->setPort("\\ORSTTOP", State::S0);
- cell->setPort("\\ORSTBOT", State::S0);
+ SigSpec OHOLD;
+ if (st.ffOcemux)
+ OHOLD = st.ffOcemux ? pm.module->Not(NEW_ID, st.ffOcemux->getPort("\\S")) : st.ffOcemux->getPort("\\S");
+ else
+ OHOLD = State::S0;
+ cell->setPort("\\OHOLDTOP", OHOLD);
+ cell->setPort("\\OHOLDBOT", OHOLD);
- cell->setPort("\\OHOLDTOP", State::S0);
- cell->setPort("\\OHOLDBOT", State::S0);
+ SigSpec ORST;
+ if (st.ffOrstmux)
+ ORST = st.ffOrstmux ? st.ffOrstmux->getPort("\\S") : pm.module->Not(NEW_ID, st.ffOrstmux->getPort("\\S"));
+ else
+ ORST = State::S0;
+ cell->setPort("\\ORSTTOP", ORST);
+ cell->setPort("\\ORSTBOT", ORST);
SigSpec acc_reset = State::S0;
if (st.mux) {
else
acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S"));
}
-
cell->setPort("\\OLOADTOP", acc_reset);
cell->setPort("\\OLOADBOT", acc_reset);
state <bool> ffAcepol ffBcepol ffCDcepol ffOcepol
state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
-state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux
-state <Cell*> ffFJKG ffFJKGrstmux ffH ffHrstmux ffO ffOcemux ffOrstmux
+state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux
+state <Cell*> ffFJKG ffH ffO ffOcemux ffOrstmux
// subpattern
state <SigSpec> argQ argD
}
endcode
-code argD ffFJKG ffFJKGrstmux sigH sigO clock clock_pol
+code argD ffFJKG sigH sigO 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;
subpattern(out_dffe);
if (dff) {
- ffFJKG = dff;
- clock = dffclock;
- clock_pol = dffclock_pol;
- if (dffrstmux)
- ffFJKGrstmux = dffrstmux;
// F/J/K/G do not have a CE-like (hold) input
if (dffcemux)
- reject;
+ goto reject_ffFJKG;
// Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
// shared with A and B
- if ((ffArstmux != NULL) != (ffFJKGrstmux != NULL))
- reject;
- if ((ffBrstmux != NULL) != (ffFJKGrstmux != NULL))
- reject;
+ if ((ffArstmux != NULL) != (dffrstmux != NULL))
+ goto reject_ffFJKG;
+ if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+ goto reject_ffFJKG;
if (ffArstmux) {
- if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S))
- reject;
+ if (port(ffArstmux, \S) != port(dffrstmux, \S))
+ goto reject_ffFJKG;
if (ffArstpol != dffrstpol)
- reject;
+ goto reject_ffFJKG;
}
if (ffBrstmux) {
- if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S))
- reject;
+ if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+ goto reject_ffFJKG;
if (ffBrstpol != dffrstpol)
- reject;
+ goto reject_ffFJKG;
}
+ ffFJKG = dff;
+ clock = dffclock;
+ clock_pol = dffclock_pol;
sigH = dffQ;
}
}
+
+ if (0) {
+reject_ffFJKG: ;
+ }
endcode
-code argD ffH ffHrstmux sigH sigO clock clock_pol
- if (nusers(sigH) == 2 &&
+code argD 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;
subpattern(out_dffe);
if (dff) {
- ffH = dff;
- clock = dffclock;
- clock_pol = dffclock_pol;
- if (dffrstmux)
- ffHrstmux = dffrstmux;
// H does not have a CE-like (hold) input
if (dffcemux)
- reject;
+ goto reject_ffH;
// Reset signal of H (IRSTBOT) shared with B
- if ((ffBrstmux != NULL) != (ffHrstmux != NULL))
- reject;
+ if ((ffBrstmux != NULL) != (dffrstmux != NULL))
+ goto reject_ffH;
if (ffBrstmux) {
- if (port(ffBrstmux, \S) != port(ffHrstmux, \S))
- reject;
+ if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+ goto reject_ffH;
if (ffBrstpol != dffrstpol)
- reject;
+ goto reject_ffH;
}
+ ffH = dff;
+ clock = dffclock;
+ clock_pol = dffclock_pol;
sigH = dffQ;
}
}
+ if (0) {
+reject_ffH: ;
+ }
+
sigO = sigH;
endcode
}
endcode
-code argQ ffCD ffCDcemux ffCDrstmux ffCDcepol ffCDrstpol sigCD clock clock_pol
+code argQ ffCD ffCDcemux ffCDcepol ffCDrstpol sigCD clock clock_pol
if (!sigCD.empty() &&
(mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
argQ = sigCD;
subpattern(in_dffe);
if (dff) {
- ffCD = dff;
- clock = dffclock;
- clock_pol = dffclock_pol;
- if (dffrstmux) {
- ffCDrstmux = dffrstmux;
- ffCDrstpol = dffrstpol;
- }
if (dffcemux) {
ffCDcemux = dffcemux;
ffCDcepol = dffcepol;
}
+
+ // 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)
+ goto reject_ffCD;
+ }
+ if (ffBrstmux) {
+ if (port(ffBrstmux, \S) != port(dffrstmux, \S))
+ goto reject_ffCD;
+ if (ffBrstpol != dffrstpol)
+ goto reject_ffCD;
+ }
+
+ ffCD = dff;
+ clock = dffclock;
+ clock_pol = dffclock_pol;
sigCD = dffD;
}
}
+
+ if (0) {
+reject_ffCD: ;
+ }
endcode
code sigCD
code
dff = nullptr;
+ for (auto c : argD.chunks())
+ if (c.wire->get_bool_attribute(\keep))
+ reject;
endcode
match ffcemux
index <SigBit> port(ffcemux, BA)[offset] === argD[0]
// Check that the rest of argD is present
- filter GetSize(BA) >= offset + GetSize(argD)
+ filter GetSize(port(ffcemux, BA)) >= offset + GetSize(argD)
filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD
set ffoffset offset
dffcemux = ffcemux;
if (ffcemux) {
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;
-
SigSpec Y = port(ffcemux, \Y);
argQ = argD;
argD.replace(BA, Y);
// Check that offset is consistent
filter !ffcemux || ffoffset == offset
// Check that the rest of argD is present
- filter GetSize(AB) >= offset + GetSize(argD)
+ filter GetSize(port(ffrstmux, AB)) >= offset + GetSize(argD)
filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
set ffoffset offset
filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
set ffoffset offset
-
- semioptional
endmatch
code argQ
if (param(ff, \CLK_POLARITY).as_bool() != clock_pol)
reject;
}
-
SigSpec D = port(ff, \D);
SigSpec Q = port(ff, \Q);
if (!ffcemux) {
}
for (auto c : argQ.chunks()) {
- if (c.wire->get_bool_attribute(\keep))
- reject;
Const init = c.wire->attributes.at(\init, State::Sx);
if (!init.is_fully_undef() && !init.is_fully_zero())
reject;