mirror of
https://github.com/YosysHQ/yosys
synced 2025-08-04 10:20:24 +00:00
Add HOLD/RST support for SB_MAC16
This commit is contained in:
parent
2766465a2b
commit
429c9852ce
2 changed files with 120 additions and 73 deletions
|
@ -33,13 +33,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
log("\n");
|
log("\n");
|
||||||
log("ffA: %s %s %s\n", log_id(st.ffA, "--"), log_id(st.ffAcemux, "--"), log_id(st.ffArstmux, "--"));
|
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("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("mul: %s\n", log_id(st.mul, "--"));
|
||||||
log("ffFJKG: %s n/a %s\n", log_id(st.ffFJKG, "--"), log_id(st.ffFJKGrstmux, "--"));
|
log("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
|
||||||
log("ffH: %s n/a %s\n", log_id(st.ffH, "--"), log_id(st.ffHrstmux, "--"));
|
log("ffH: %s\n", log_id(st.ffH, "--"));
|
||||||
log("add: %s\n", log_id(st.add, "--"));
|
log("add: %s\n", log_id(st.add, "--"));
|
||||||
log("mux: %s\n", log_id(st.mux, "--"));
|
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
|
#endif
|
||||||
|
|
||||||
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
|
log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul));
|
||||||
|
@ -98,13 +98,35 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0);
|
cell->setParam("\\C_REG", st.ffCD ? State::S1 : State::S0);
|
||||||
cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0);
|
cell->setParam("\\D_REG", st.ffCD ? State::S1 : State::S0);
|
||||||
|
|
||||||
cell->setPort("\\AHOLD", State::S0);
|
SigSpec AHOLD, BHOLD, CDHOLD;
|
||||||
cell->setPort("\\BHOLD", State::S0);
|
if (st.ffAcemux)
|
||||||
cell->setPort("\\CHOLD", State::S0);
|
AHOLD = st.ffAcepol ? pm.module->Not(NEW_ID, st.ffAcemux->getPort("\\S")) : st.ffAcemux->getPort("\\S");
|
||||||
cell->setPort("\\DHOLD", State::S0);
|
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);
|
||||||
|
|
||||||
cell->setPort("\\IRSTTOP", State::S0);
|
SigSpec IRSTTOP, IRSTBOT;
|
||||||
cell->setPort("\\IRSTBOT", State::S0);
|
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())
|
if (st.clock != SigBit())
|
||||||
{
|
{
|
||||||
|
@ -187,11 +209,21 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setPort("\\ADDSUBBOT", State::S0);
|
cell->setPort("\\ADDSUBBOT", State::S0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort("\\ORSTTOP", State::S0);
|
SigSpec OHOLD;
|
||||||
cell->setPort("\\ORSTBOT", State::S0);
|
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);
|
SigSpec ORST;
|
||||||
cell->setPort("\\OHOLDBOT", State::S0);
|
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;
|
SigSpec acc_reset = State::S0;
|
||||||
if (st.mux) {
|
if (st.mux) {
|
||||||
|
@ -200,7 +232,6 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
else
|
else
|
||||||
acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S"));
|
acc_reset = pm.module->Not(NEW_ID, st.mux->getPort("\\S"));
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->setPort("\\OLOADTOP", acc_reset);
|
cell->setPort("\\OLOADTOP", acc_reset);
|
||||||
cell->setPort("\\OLOADBOT", acc_reset);
|
cell->setPort("\\OLOADBOT", acc_reset);
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ state <IdString> addAB muxAB
|
||||||
state <bool> ffAcepol ffBcepol ffCDcepol ffOcepol
|
state <bool> ffAcepol ffBcepol ffCDcepol ffOcepol
|
||||||
state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
|
state <bool> ffArstpol ffBrstpol ffCDrstpol ffOrstpol
|
||||||
|
|
||||||
state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux ffCDrstmux
|
state <Cell*> ffA ffAcemux ffArstmux ffB ffBcemux ffBrstmux ffCD ffCDcemux
|
||||||
state <Cell*> ffFJKG ffFJKGrstmux ffH ffHrstmux ffO ffOcemux ffOrstmux
|
state <Cell*> ffFJKG ffH ffO ffOcemux ffOrstmux
|
||||||
|
|
||||||
// subpattern
|
// subpattern
|
||||||
state <SigSpec> argQ argD
|
state <SigSpec> argQ argD
|
||||||
|
@ -105,75 +105,79 @@ code argQ ffB ffBcemux ffBrstmux ffBcepol ffBrstpol sigB clock clock_pol
|
||||||
}
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
code argD ffFJKG ffFJKGrstmux sigH sigO clock clock_pol
|
code argD ffFJKG sigH sigO clock clock_pol
|
||||||
if (nusers(sigH) == 2 &&
|
if (nusers(sigH) == 2 &&
|
||||||
(mul->type != \SB_MAC16 ||
|
(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()))) {
|
(!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;
|
argD = sigH;
|
||||||
subpattern(out_dffe);
|
subpattern(out_dffe);
|
||||||
if (dff) {
|
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
|
// F/J/K/G do not have a CE-like (hold) input
|
||||||
if (dffcemux)
|
if (dffcemux)
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
|
|
||||||
// Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
|
// Reset signal of F/J (IRSTTOP) and K/G (IRSTBOT)
|
||||||
// shared with A and B
|
// shared with A and B
|
||||||
if ((ffArstmux != NULL) != (ffFJKGrstmux != NULL))
|
if ((ffArstmux != NULL) != (dffrstmux != NULL))
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
if ((ffBrstmux != NULL) != (ffFJKGrstmux != NULL))
|
if ((ffBrstmux != NULL) != (dffrstmux != NULL))
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
if (ffArstmux) {
|
if (ffArstmux) {
|
||||||
if (port(ffArstmux, \S) != port(ffFJKGrstmux, \S))
|
if (port(ffArstmux, \S) != port(dffrstmux, \S))
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
if (ffArstpol != dffrstpol)
|
if (ffArstpol != dffrstpol)
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
}
|
}
|
||||||
if (ffBrstmux) {
|
if (ffBrstmux) {
|
||||||
if (port(ffBrstmux, \S) != port(ffFJKGrstmux, \S))
|
if (port(ffBrstmux, \S) != port(dffrstmux, \S))
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
if (ffBrstpol != dffrstpol)
|
if (ffBrstpol != dffrstpol)
|
||||||
reject;
|
goto reject_ffFJKG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ffFJKG = dff;
|
||||||
|
clock = dffclock;
|
||||||
|
clock_pol = dffclock_pol;
|
||||||
sigH = dffQ;
|
sigH = dffQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
reject_ffFJKG: ;
|
||||||
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
code argD ffH ffHrstmux sigH sigO clock clock_pol
|
code argD ffH sigH sigO clock clock_pol
|
||||||
if (nusers(sigH) == 2 &&
|
if (ffFJKG && nusers(sigH) == 2 &&
|
||||||
(mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
|
(mul->type != \SB_MAC16 || !param(mul, \PIPELINE_16x16_MULT_REG2).as_bool())) {
|
||||||
argD = sigH;
|
argD = sigH;
|
||||||
subpattern(out_dffe);
|
subpattern(out_dffe);
|
||||||
if (dff) {
|
if (dff) {
|
||||||
|
// H does not have a CE-like (hold) input
|
||||||
|
if (dffcemux)
|
||||||
|
goto reject_ffH;
|
||||||
|
|
||||||
|
// Reset signal of H (IRSTBOT) shared with B
|
||||||
|
if ((ffBrstmux != NULL) != (dffrstmux != NULL))
|
||||||
|
goto reject_ffH;
|
||||||
|
if (ffBrstmux) {
|
||||||
|
if (port(ffBrstmux, \S) != port(dffrstmux, \S))
|
||||||
|
goto reject_ffH;
|
||||||
|
if (ffBrstpol != dffrstpol)
|
||||||
|
goto reject_ffH;
|
||||||
|
}
|
||||||
|
|
||||||
ffH = dff;
|
ffH = dff;
|
||||||
clock = dffclock;
|
clock = dffclock;
|
||||||
clock_pol = dffclock_pol;
|
clock_pol = dffclock_pol;
|
||||||
if (dffrstmux)
|
|
||||||
ffHrstmux = dffrstmux;
|
|
||||||
// H does not have a CE-like (hold) input
|
|
||||||
if (dffcemux)
|
|
||||||
reject;
|
|
||||||
|
|
||||||
// Reset signal of H (IRSTBOT) shared with B
|
|
||||||
if ((ffBrstmux != NULL) != (ffHrstmux != NULL))
|
|
||||||
reject;
|
|
||||||
if (ffBrstmux) {
|
|
||||||
if (port(ffBrstmux, \S) != port(ffHrstmux, \S))
|
|
||||||
reject;
|
|
||||||
if (ffBrstpol != dffrstpol)
|
|
||||||
reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
sigH = dffQ;
|
sigH = dffQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
reject_ffH: ;
|
||||||
|
}
|
||||||
|
|
||||||
sigO = sigH;
|
sigO = sigH;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
@ -274,26 +278,46 @@ code argD ffO ffOcemux ffOrstmux ffOcepol ffOrstpol sigO sigCD clock clock_pol c
|
||||||
}
|
}
|
||||||
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() &&
|
if (!sigCD.empty() &&
|
||||||
(mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
|
(mul->type != \SB_MAC16 || (!param(mul, \C_REG).as_bool() && !param(mul, \D_REG).as_bool()))) {
|
||||||
argQ = sigCD;
|
argQ = sigCD;
|
||||||
subpattern(in_dffe);
|
subpattern(in_dffe);
|
||||||
if (dff) {
|
if (dff) {
|
||||||
ffCD = dff;
|
|
||||||
clock = dffclock;
|
|
||||||
clock_pol = dffclock_pol;
|
|
||||||
if (dffrstmux) {
|
|
||||||
ffCDrstmux = dffrstmux;
|
|
||||||
ffCDrstpol = dffrstpol;
|
|
||||||
}
|
|
||||||
if (dffcemux) {
|
if (dffcemux) {
|
||||||
ffCDcemux = dffcemux;
|
ffCDcemux = dffcemux;
|
||||||
ffCDcepol = dffcepol;
|
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;
|
sigCD = dffD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
reject_ffCD: ;
|
||||||
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
code sigCD
|
code sigCD
|
||||||
|
@ -418,6 +442,9 @@ arg argD argQ clock clock_pol
|
||||||
|
|
||||||
code
|
code
|
||||||
dff = nullptr;
|
dff = nullptr;
|
||||||
|
for (auto c : argD.chunks())
|
||||||
|
if (c.wire->get_bool_attribute(\keep))
|
||||||
|
reject;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match ffcemux
|
match ffcemux
|
||||||
|
@ -434,7 +461,7 @@ match ffcemux
|
||||||
index <SigBit> port(ffcemux, BA)[offset] === argD[0]
|
index <SigBit> port(ffcemux, BA)[offset] === argD[0]
|
||||||
|
|
||||||
// Check that the rest of argD is present
|
// 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
|
filter port(ffcemux, BA).extract(offset, GetSize(argD)) == argD
|
||||||
|
|
||||||
set ffoffset offset
|
set ffoffset offset
|
||||||
|
@ -448,12 +475,6 @@ code argD argQ
|
||||||
dffcemux = ffcemux;
|
dffcemux = ffcemux;
|
||||||
if (ffcemux) {
|
if (ffcemux) {
|
||||||
SigSpec BA = port(ffcemux, ffcepol ? \B : \A);
|
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);
|
SigSpec Y = port(ffcemux, \Y);
|
||||||
argQ = argD;
|
argQ = argD;
|
||||||
argD.replace(BA, Y);
|
argD.replace(BA, Y);
|
||||||
|
@ -480,7 +501,7 @@ match ffrstmux
|
||||||
// Check that offset is consistent
|
// Check that offset is consistent
|
||||||
filter !ffcemux || ffoffset == offset
|
filter !ffcemux || ffoffset == offset
|
||||||
// Check that the rest of argD is present
|
// 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
|
filter port(ffrstmux, AB).extract(offset, GetSize(argD)) == argD
|
||||||
|
|
||||||
set ffoffset offset
|
set ffoffset offset
|
||||||
|
@ -519,8 +540,6 @@ match ff
|
||||||
filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
|
filter !ffcemux || port(ff, \Q).extract(offset, GetSize(argQ)) == argQ
|
||||||
|
|
||||||
set ffoffset offset
|
set ffoffset offset
|
||||||
|
|
||||||
semioptional
|
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code argQ
|
code argQ
|
||||||
|
@ -531,7 +550,6 @@ code argQ
|
||||||
if (param(ff, \CLK_POLARITY).as_bool() != clock_pol)
|
if (param(ff, \CLK_POLARITY).as_bool() != clock_pol)
|
||||||
reject;
|
reject;
|
||||||
}
|
}
|
||||||
|
|
||||||
SigSpec D = port(ff, \D);
|
SigSpec D = port(ff, \D);
|
||||||
SigSpec Q = port(ff, \Q);
|
SigSpec Q = port(ff, \Q);
|
||||||
if (!ffcemux) {
|
if (!ffcemux) {
|
||||||
|
@ -540,8 +558,6 @@ code argQ
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto c : argQ.chunks()) {
|
for (auto c : argQ.chunks()) {
|
||||||
if (c.wire->get_bool_attribute(\keep))
|
|
||||||
reject;
|
|
||||||
Const init = c.wire->attributes.at(\init, State::Sx);
|
Const init = c.wire->attributes.at(\init, State::Sx);
|
||||||
if (!init.is_fully_undef() && !init.is_fully_zero())
|
if (!init.is_fully_undef() && !init.is_fully_zero())
|
||||||
reject;
|
reject;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue