diff options
Diffstat (limited to 'passes/pmgen/ice40_dsp.cc')
-rw-r--r-- | passes/pmgen/ice40_dsp.cc | 135 |
1 files changed, 83 insertions, 52 deletions
diff --git a/passes/pmgen/ice40_dsp.cc b/passes/pmgen/ice40_dsp.cc index 39d033a04..31e11c742 100644 --- a/passes/pmgen/ice40_dsp.cc +++ b/passes/pmgen/ice40_dsp.cc @@ -29,15 +29,16 @@ void create_ice40_dsp(ice40_dsp_pm &pm) { auto &st = pm.st_ice40_dsp; -#if 0 +#if 1 log("\n"); - log("ffA: %s\n", log_id(st.ffA, "--")); - log("ffB: %s\n", log_id(st.ffB, "--")); - log("mul: %s\n", log_id(st.mul, "--")); - log("ffY: %s\n", log_id(st.ffY, "--")); - log("addAB: %s\n", log_id(st.addAB, "--")); - log("muxAB: %s\n", log_id(st.muxAB, "--")); - log("ffS: %s\n", log_id(st.ffS, "--")); + log("ffA: %s\n", log_id(st.ffA, "--")); + log("ffB: %s\n", log_id(st.ffB, "--")); + log("mul: %s\n", log_id(st.mul, "--")); + log("ffFJKG: %s\n", log_id(st.ffFJKG, "--")); + log("addAB: %s\n", log_id(st.addAB, "--")); + log("muxAB: %s\n", log_id(st.muxAB, "--")); + log("ffO_lo: %s\n", log_id(st.ffO_lo, "--")); + log("ffO_hi: %s\n", log_id(st.ffO_hi, "--")); #endif log("Checking %s.%s for iCE40 DSP inference.\n", log_id(pm.module), log_id(st.mul)); @@ -52,47 +53,42 @@ void create_ice40_dsp(ice40_dsp_pm &pm) return; } - if (GetSize(st.sigS) > 32) { - log(" accumulator (%s) is too large (%d > 32).\n", log_signal(st.sigS), GetSize(st.sigS)); + if (GetSize(st.sigO) > 33) { + log(" adder/accumulator (%s) is too large (%d > 33).\n", log_signal(st.sigO), GetSize(st.sigO)); return; } - if (GetSize(st.sigY) > 32) { - log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigY), GetSize(st.sigY)); + if (GetSize(st.sigH) > 32) { + log(" output (%s) is too large (%d > 32).\n", log_signal(st.sigH), GetSize(st.sigH)); return; } - bool mul_signed = st.mul->getParam("\\A_SIGNED").as_bool(); + Cell *cell = st.mul; + if (cell->type == "$mul") { + log(" replacing %s with SB_MAC16 cell.\n", log_id(st.mul->type)); - if (mul_signed) { - log(" inference of signed iCE40 DSP arithmetic is currently not supported.\n"); - return; + cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); + pm.module->swap_names(cell, st.mul); } - - log(" replacing $mul with SB_MAC16 cell.\n"); - - Cell *cell = pm.module->addCell(NEW_ID, "\\SB_MAC16"); - pm.module->swap_names(cell, st.mul); + else log_assert(cell->type == "\\SB_MAC16"); // SB_MAC16 Input Interface - SigSpec A = st.sigA; - A.extend_u0(16, mul_signed); + log_assert(GetSize(A) == 16); SigSpec B = st.sigB; - B.extend_u0(16, mul_signed); + log_assert(GetSize(B) == 16); - SigSpec CD; - if (st.muxA) - CD = st.muxA->getPort("\\B"); - if (st.muxB) - CD = st.muxB->getPort("\\A"); - CD.extend_u0(32, mul_signed); + SigSpec CD = st.sigCD; + if (CD.empty()) + CD = RTLIL::Const(0, 32); + else + log_assert(GetSize(CD) == 32); cell->setPort("\\A", A); cell->setPort("\\B", B); - cell->setPort("\\C", CD.extract(0, 16)); - cell->setPort("\\D", CD.extract(16, 16)); + cell->setPort("\\C", CD.extract(16, 16)); + cell->setPort("\\D", CD.extract(0, 16)); cell->setParam("\\A_REG", st.ffA ? State::S1 : State::S0); cell->setParam("\\B_REG", st.ffB ? State::S1 : State::S0); @@ -105,7 +101,7 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\IRSTTOP", State::S0); cell->setPort("\\IRSTBOT", State::S0); - if (st.clock_vld) + if (st.clock != SigBit()) { cell->setPort("\\CLK", st.clock); cell->setPort("\\CE", State::S1); @@ -119,11 +115,13 @@ void create_ice40_dsp(ice40_dsp_pm &pm) if (st.ffB) log(" ffB:%s", log_id(st.ffB)); - if (st.ffY) - log(" ffY:%s", log_id(st.ffY)); + if (st.ffFJKG) + log(" ffFJKG:%s", log_id(st.ffFJKG)); - if (st.ffS) - log(" ffS:%s", log_id(st.ffS)); + if (st.ffO_lo) + log(" ffO_lo:%s", log_id(st.ffO_lo)); + if (st.ffO_hi) + log(" ffO_hi:%s", log_id(st.ffO_hi)); log("\n"); } @@ -140,21 +138,43 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setPort("\\SIGNEXTOUT", pm.module->addWire(NEW_ID)); cell->setPort("\\CI", State::Sx); - cell->setPort("\\CO", pm.module->addWire(NEW_ID)); cell->setPort("\\ACCUMCI", State::Sx); cell->setPort("\\ACCUMCO", pm.module->addWire(NEW_ID)); // SB_MAC16 Output Interface - SigSpec O = st.ffS ? st.sigS : st.sigY; + SigSpec O = st.sigO; + int O_width = GetSize(O); + if (O_width == 33) { + log_assert(st.addAB); + // If we have a signed multiply-add, then perform sign extension + // TODO: Need to check CD[31:16] is sign extension of CD[15:0]? + if (st.addAB->getParam("\\A_SIGNED").as_bool() && st.addAB->getParam("\\B_SIGNED").as_bool()) + pm.module->connect(O[32], O[31]); + else + cell->setPort("\\CO", O[32]); + O.remove(O_width-1); + } + else + cell->setPort("\\CO", pm.module->addWire(NEW_ID)); + log_assert(GetSize(O) <= 32); if (GetSize(O) < 32) O.append(pm.module->addWire(NEW_ID, 32-GetSize(O))); cell->setPort("\\O", O); + bool accum = false; if (st.addAB) { - log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + if (st.addA) + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\B") == st.sigO); + else if (st.addB) + accum = (st.ffO_lo && st.ffO_hi && st.addAB->getPort("\\A") == st.sigO); + else log_abort(); + if (accum) + log(" accumulator %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); + else + log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type)); cell->setPort("\\ADDSUBTOP", st.addAB->type == "$add" ? State::S0 : State::S1); cell->setPort("\\ADDSUBBOT", st.addAB->type == "$add" ? State::S0 : State::S1); } else { @@ -182,28 +202,39 @@ void create_ice40_dsp(ice40_dsp_pm &pm) cell->setParam("\\C_REG", State::S0); cell->setParam("\\D_REG", State::S0); - cell->setParam("\\TOP_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); - cell->setParam("\\BOT_8x8_MULT_REG", st.ffY ? State::S1 : State::S0); - cell->setParam("\\PIPELINE_16x16_MULT_REG1", st.ffY ? State::S1 : State::S0); + cell->setParam("\\TOP_8x8_MULT_REG", st.ffFJKG ? State::S1 : State::S0); + cell->setParam("\\BOT_8x8_MULT_REG", 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("\\TOPOUTPUT_SELECT", Const(st.ffS ? 1 : 3, 2)); + cell->setParam("\\TOPOUTPUT_SELECT", Const(st.ffO_hi ? 1 : (st.addAB ? 0 : 3), 2)); cell->setParam("\\TOPADDSUB_LOWERINPUT", Const(2, 2)); - cell->setParam("\\TOPADDSUB_UPPERINPUT", State::S0); + cell->setParam("\\TOPADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\TOPADDSUB_CARRYSELECT", Const(3, 2)); - cell->setParam("\\BOTOUTPUT_SELECT", Const(st.ffS ? 1 : 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_UPPERINPUT", State::S0); + cell->setParam("\\BOTADDSUB_UPPERINPUT", accum ? State::S0 : State::S1); cell->setParam("\\BOTADDSUB_CARRYSELECT", Const(0, 2)); cell->setParam("\\MODE_8x8", State::S0); - cell->setParam("\\A_SIGNED", mul_signed ? State::S1 : State::S0); - cell->setParam("\\B_SIGNED", mul_signed ? State::S1 : State::S0); + cell->setParam("\\A_SIGNED", st.mul->getParam("\\A_SIGNED").as_bool()); + cell->setParam("\\B_SIGNED", st.mul->getParam("\\B_SIGNED").as_bool()); - pm.autoremove(st.mul); - pm.autoremove(st.ffY); - pm.autoremove(st.ffS); + if (cell != st.mul) + pm.autoremove(st.mul); + else + pm.blacklist(st.mul); + pm.autoremove(st.ffFJKG); + 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 { |