mirror of
https://github.com/YosysHQ/yosys
synced 2025-06-13 09:26:16 +00:00
Fix broken ice40_dsp
This commit is contained in:
parent
38e73a3788
commit
888ae1d05e
2 changed files with 85 additions and 113 deletions
|
@ -28,6 +28,7 @@ PRIVATE_NAMESPACE_BEGIN
|
||||||
void create_ice40_dsp(ice40_dsp_pm &pm)
|
void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
{
|
{
|
||||||
auto &st = pm.st_ice40_dsp;
|
auto &st = pm.st_ice40_dsp;
|
||||||
|
Cell* ffO = st.ffO ? st.ffO : st.ffO_lo;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
log("\n");
|
log("\n");
|
||||||
|
@ -37,8 +38,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
log("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
|
log("ffFJKG: %s\n", log_id(st.ffFJKG, "--"));
|
||||||
log("addAB: %s\n", log_id(st.addAB, "--"));
|
log("addAB: %s\n", log_id(st.addAB, "--"));
|
||||||
log("muxAB: %s\n", log_id(st.muxAB, "--"));
|
log("muxAB: %s\n", log_id(st.muxAB, "--"));
|
||||||
log("ffO_lo: %s\n", log_id(st.ffO_lo, "--"));
|
log("ffO: %s\n", log_id(ffO, "--"));
|
||||||
log("ffO_hi: %s\n", log_id(st.ffO_hi, "--"));
|
|
||||||
#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));
|
||||||
|
@ -118,10 +118,8 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
if (st.ffFJKG)
|
if (st.ffFJKG)
|
||||||
log(" ffFJKG:%s", log_id(st.ffFJKG));
|
log(" ffFJKG:%s", log_id(st.ffFJKG));
|
||||||
|
|
||||||
if (st.ffO_lo)
|
if (ffO)
|
||||||
log(" ffO_lo:%s", log_id(st.ffO_lo));
|
log(" ffO:%s", log_id(ffO));
|
||||||
if (st.ffO_hi)
|
|
||||||
log(" ffO_hi:%s", log_id(st.ffO_hi));
|
|
||||||
|
|
||||||
log("\n");
|
log("\n");
|
||||||
}
|
}
|
||||||
|
@ -167,9 +165,9 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
bool accum = false;
|
bool accum = false;
|
||||||
if (st.addAB) {
|
if (st.addAB) {
|
||||||
if (st.addA)
|
if (st.addA)
|
||||||
accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == st.sigO);
|
accum = (ffO && st.addAB->getPort("\\B") == st.sigO);
|
||||||
else if (st.addB)
|
else if (st.addB)
|
||||||
accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == st.sigO);
|
accum = (ffO && st.addAB->getPort("\\A") == st.sigO);
|
||||||
else log_abort();
|
else log_abort();
|
||||||
if (accum)
|
if (accum)
|
||||||
log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
||||||
|
@ -207,12 +205,10 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0);
|
cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffFJKG ? State::S1 : State::S0);
|
||||||
cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);
|
cell->setParam("\\PIPELINE_16x16_MULT_REG2", State::S0);
|
||||||
|
|
||||||
cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO_hi ? 1 : (st.addAB ? 0 : 3), 2));
|
|
||||||
cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
|
cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2));
|
||||||
cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1);
|
cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1);
|
||||||
cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));
|
cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2));
|
||||||
|
|
||||||
cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffO_lo ? 1 : (st.addAB ? 0 : 3), 2));
|
|
||||||
cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
|
cell->setParam("\\BOTADDSUB_LOWERINPUT", Const(2, 2));
|
||||||
cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1);
|
cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1);
|
||||||
cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));
|
cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2));
|
||||||
|
@ -221,20 +217,26 @@ void create_ice40_dsp(ice40_dsp_pm &pm)
|
||||||
cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool());
|
cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool());
|
||||||
cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool());
|
cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool());
|
||||||
|
|
||||||
|
if (ffO) {
|
||||||
|
if (st.ffO)
|
||||||
|
cell->setParam("\\TOPOUTPUT_SELECT", Const(1, 2));
|
||||||
|
else
|
||||||
|
cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2));
|
||||||
|
|
||||||
|
ffO->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O)));
|
||||||
|
cell->setParam("\\BOTOUTPUT_SELECT", Const(1, 2));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cell->setParam("\\TOPOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2));
|
||||||
|
cell->setParam("\\BOTOUTPUT_SELECT", Const(st.addAB ? 0 : 3, 2));
|
||||||
|
}
|
||||||
|
|
||||||
if (cell != st.mul)
|
if (cell != st.mul)
|
||||||
pm.autoremove(st.mul);
|
pm.autoremove(st.mul);
|
||||||
else
|
else
|
||||||
pm.blacklist(st.mul);
|
pm.blacklist(st.mul);
|
||||||
pm.autoremove(st.ffFJKG);
|
pm.autoremove(st.ffFJKG);
|
||||||
pm.autoremove(st.addAB);
|
pm.autoremove(st.addAB);
|
||||||
if (st.ffO_lo) {
|
|
||||||
SigSpec O = st.sigO.extract(0,std::min(16,st.ffO_lo->getParam("\\WIDTH").as_int()));
|
|
||||||
st.ffO_lo->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O)));
|
|
||||||
}
|
|
||||||
if (st.ffO_hi) {
|
|
||||||
SigSpec O = st.sigO.extract_end(16);
|
|
||||||
st.ffO_hi->connections_.at("\\Q").replace(O, pm.module->addWire(NEW_ID, GetSize(O)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Ice40DspPass : public Pass {
|
struct Ice40DspPass : public Pass {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pattern ice40_dsp
|
pattern ice40_dsp
|
||||||
|
|
||||||
state <SigBit> clock
|
state <SigBit> clock
|
||||||
state <bool> clock_pol
|
state <bool> clock_pol cd_signed
|
||||||
state <std::set<SigBit>> sigAset sigBset
|
state <std::set<SigBit>> sigAset sigBset
|
||||||
state <SigSpec> sigA sigB sigCD sigH sigO sigOused
|
state <SigSpec> sigA sigB sigCD sigH sigO sigOused
|
||||||
state <Cell*> addAB muxAB
|
state <Cell*> addAB muxAB
|
||||||
|
@ -21,13 +21,22 @@ code sigAset sigBset
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
code sigH
|
code sigH
|
||||||
|
SigSpec O;
|
||||||
if (mul->type == $mul)
|
if (mul->type == $mul)
|
||||||
sigH = mul->getPort(\Y);
|
O = mul->getPort(\Y);
|
||||||
else if (mul->type == \SB_MAC16)
|
else if (mul->type == \SB_MAC16)
|
||||||
sigH = mul->getPort(\O);
|
O = mul->getPort(\O);
|
||||||
else log_abort();
|
else log_abort();
|
||||||
if (GetSize(sigH) <= 10)
|
if (GetSize(O) <= 10)
|
||||||
reject;
|
reject;
|
||||||
|
// Only care about those bits that are used
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < GetSize(O); i++) {
|
||||||
|
if (nusers(O[i]) <= 1)
|
||||||
|
break;
|
||||||
|
sigH.append(O[i]);
|
||||||
|
}
|
||||||
|
log_assert(nusers(O.extract_end(i)) <= 1);
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match ffA
|
match ffA
|
||||||
|
@ -136,17 +145,16 @@ match addB
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code addAB sigCD sigO
|
code addAB sigCD sigO cd_signed
|
||||||
bool CD_SIGNED = false;
|
|
||||||
if (addA) {
|
if (addA) {
|
||||||
addAB = addA;
|
addAB = addA;
|
||||||
sigCD = port(addAB, \B);
|
sigCD = port(addAB, \B);
|
||||||
CD_SIGNED = param(addAB, \B_SIGNED).as_bool();
|
cd_signed = param(addAB, \B_SIGNED).as_bool();
|
||||||
}
|
}
|
||||||
if (addB) {
|
else if (addB) {
|
||||||
addAB = addB;
|
addAB = addB;
|
||||||
sigCD = port(addAB, \A);
|
sigCD = port(addAB, \A);
|
||||||
CD_SIGNED = param(addAB, \A_SIGNED).as_bool();
|
cd_signed = param(addAB, \A_SIGNED).as_bool();
|
||||||
}
|
}
|
||||||
if (addAB) {
|
if (addAB) {
|
||||||
if (mul->type == \SB_MAC16) {
|
if (mul->type == \SB_MAC16) {
|
||||||
|
@ -167,7 +175,6 @@ code addAB sigCD sigO
|
||||||
reject;
|
reject;
|
||||||
|
|
||||||
sigO = port(addAB, \Y);
|
sigO = port(addAB, \Y);
|
||||||
sigCD.extend_u0(32, CD_SIGNED);
|
|
||||||
}
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
@ -186,105 +193,63 @@ match muxB
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code muxAB
|
code muxAB sigO
|
||||||
if (muxA)
|
if (muxA)
|
||||||
muxAB = muxA;
|
muxAB = muxA;
|
||||||
else if (muxB)
|
else if (muxB)
|
||||||
muxAB = muxB;
|
muxAB = muxB;
|
||||||
|
if (muxAB)
|
||||||
|
sigO = port(muxAB, \Y);
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
// Extract the bits of P that actually have a consumer
|
match ffO
|
||||||
// (as opposed to being a dummy)
|
// Ensure that register is not already used
|
||||||
code sigOused
|
if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1)
|
||||||
for (int i = 0; i < GetSize(sigO); i++)
|
// Ensure that OLOADTOP/OLOADBOT is unused or zero
|
||||||
if (!sigO[i].wire || nusers(sigO[i]) == 1)
|
if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero())
|
||||||
sigOused.append(State::Sx);
|
if nusers(sigO) == 2
|
||||||
else
|
select ffO->type.in($dff)
|
||||||
sigOused.append(sigO[i]);
|
filter GetSize(port(ffO, \D)) >= GetSize(sigO)
|
||||||
endcode
|
slice offset GetSize(port(ffO, \D))
|
||||||
|
filter offset+GetSize(sigO) <= GetSize(port(ffO, \D)) && port(ffO, \D).extract(offset, GetSize(sigO)) == sigO
|
||||||
|
optional
|
||||||
|
endmatch
|
||||||
|
|
||||||
match ffO_lo
|
match ffO_lo
|
||||||
if nusers(sigOused.extract(0,std::min(16,GetSize(sigOused)))) == 2
|
if !ffO && GetSize(sigO) > 16
|
||||||
|
// Ensure that register is not already used
|
||||||
|
if mul->type != \SB_MAC16 || (mul->parameters.at(\TOPOUTPUT_SELECT, 0).as_int() != 1 && mul->parameters.at(\BOTOUTPUT_SELECT, 0).as_int() != 1)
|
||||||
|
// Ensure that OLOADTOP/OLOADBOT is unused or zero
|
||||||
|
if mul->type != \SB_MAC16 || (mul->connections_.at(\OLOADTOP, State::S0).is_fully_zero() && mul->connections_.at(\OLOADBOT, State::S0).is_fully_zero())
|
||||||
|
if nusers(sigO.extract(0, 16)) == 2
|
||||||
select ffO_lo->type.in($dff)
|
select ffO_lo->type.in($dff)
|
||||||
|
filter GetSize(port(ffO_lo, \D)) >= 16
|
||||||
|
slice offset GetSize(port(ffO_lo, \D))
|
||||||
|
filter offset+GetSize(sigO) <= GetSize(port(ffO_lo, \D)) && port(ffO_lo, \D).extract(offset, 16) == sigO.extract(0, 16)
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code
|
code clock clock_pol sigO sigCD cd_signed
|
||||||
if (ffO_lo) {
|
Cell* ff = nullptr;
|
||||||
SigSpec O = sigOused.extract(0,std::min(16,param(ffO_lo, \WIDTH).as_int()));
|
if (ffO)
|
||||||
O.remove_const();
|
ff = ffO;
|
||||||
auto ffO_loSet = port(ffO_lo, \D).to_sigbit_set();
|
else if (ffO_lo)
|
||||||
auto Oset = O.to_sigbit_set();
|
ff = ffO_lo;
|
||||||
if (!std::includes(ffO_loSet.begin(), ffO_loSet.end(), Oset.begin(), Oset.end()))
|
if (ff) {
|
||||||
|
for (auto b : port(ff, \Q))
|
||||||
|
if (b.wire->get_bool_attribute(\keep))
|
||||||
|
reject;
|
||||||
|
|
||||||
|
SigBit c = port(ff, \CLK).as_bit();
|
||||||
|
bool cp = param(ff, \CLK_POLARITY).as_bool();
|
||||||
|
|
||||||
|
if (clock != SigBit() && (c != clock || cp != clock_pol))
|
||||||
reject;
|
reject;
|
||||||
}
|
|
||||||
endcode
|
|
||||||
|
|
||||||
match ffO_hi
|
clock = c;
|
||||||
if GetSize(sigOused) > 16
|
clock_pol = cp;
|
||||||
if nusers(sigOused.extract_end(16)) == 2
|
|
||||||
select ffO_hi->type.in($dff)
|
|
||||||
optional
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
code
|
sigO.replace(port(ff, \D), port(ff, \Q));
|
||||||
if (ffO_hi) {
|
|
||||||
SigSpec O = sigOused.extract_end(16);
|
|
||||||
O.remove_const();
|
|
||||||
auto ffO_hiSet = port(ffO_hi, \D).to_sigbit_set();
|
|
||||||
auto Oset = O.to_sigbit_set();
|
|
||||||
if (!std::includes(ffO_hiSet.begin(), ffO_hiSet.end(), Oset.begin(), Oset.end()))
|
|
||||||
reject;
|
|
||||||
}
|
|
||||||
endcode
|
|
||||||
|
|
||||||
code clock clock_pol sigO sigCD
|
|
||||||
if (ffO_lo || ffO_hi) {
|
|
||||||
if (mul->type == \SB_MAC16) {
|
|
||||||
// Ensure that register is not already used
|
|
||||||
if (param(mul, \TOPOUTPUT_SELECT).as_int() == 1 ||
|
|
||||||
param(mul, \BOTOUTPUT_SELECT).as_int() == 1)
|
|
||||||
reject;
|
|
||||||
|
|
||||||
// Ensure that OLOADTOP/OLOADBOT is unused or zero
|
|
||||||
if ((mul->hasPort(\OLOADTOP) && !port(mul, \OLOADTOP).is_fully_zero())
|
|
||||||
|| (mul->hasPort(\OLOADBOT) && !port(mul, \OLOADBOT).is_fully_zero()))
|
|
||||||
reject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ffO_lo) {
|
|
||||||
for (auto b : port(ffO_lo, \Q))
|
|
||||||
if (b.wire->get_bool_attribute(\keep))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
SigBit c = port(ffO_lo, \CLK).as_bit();
|
|
||||||
bool cp = param(ffO_lo, \CLK_POLARITY).as_bool();
|
|
||||||
|
|
||||||
if (clock != SigBit() && (c != clock || cp != clock_pol))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
clock = c;
|
|
||||||
clock_pol = cp;
|
|
||||||
|
|
||||||
sigO.replace(port(ffO_lo, \D), port(ffO_lo, \Q));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ffO_hi) {
|
|
||||||
for (auto b : port(ffO_hi, \Q))
|
|
||||||
if (b.wire->get_bool_attribute(\keep))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
SigBit c = port(ffO_hi, \CLK).as_bit();
|
|
||||||
bool cp = param(ffO_hi, \CLK_POLARITY).as_bool();
|
|
||||||
|
|
||||||
if (clock != SigBit() && (c != clock || cp != clock_pol))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
clock = c;
|
|
||||||
clock_pol = cp;
|
|
||||||
|
|
||||||
sigO.replace(port(ffO_hi, \D), port(ffO_hi, \Q));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loading value into output register is not
|
// Loading value into output register is not
|
||||||
// supported unless using accumulator
|
// supported unless using accumulator
|
||||||
|
@ -296,8 +261,13 @@ code clock clock_pol sigO sigCD
|
||||||
else if (muxB)
|
else if (muxB)
|
||||||
sigCD = port(muxAB, \A);
|
sigCD = port(muxAB, \A);
|
||||||
else log_abort();
|
else log_abort();
|
||||||
sigCD.extend_u0(32, addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool());
|
|
||||||
|
cd_signed = addAB && param(addAB, \A_SIGNED).as_bool() && param(addAB, \B_SIGNED).as_bool();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sigCD.extend_u0(32, cd_signed);
|
||||||
|
endcode
|
||||||
|
|
||||||
|
code
|
||||||
accept;
|
accept;
|
||||||
endcode
|
endcode
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue