From 02cf9933b9e5c0bff360db13c3577c0a75cdb5b9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 9 Sep 2019 21:39:42 -0700 Subject: [PATCH] Support subtraction as well --- passes/pmgen/xilinx_dsp.cc | 235 +++++++++++++++++++------------------ 1 file changed, 123 insertions(+), 112 deletions(-) diff --git a/passes/pmgen/xilinx_dsp.cc b/passes/pmgen/xilinx_dsp.cc index 23f342a2b..7bac1b974 100644 --- a/passes/pmgen/xilinx_dsp.cc +++ b/passes/pmgen/xilinx_dsp.cc @@ -59,10 +59,11 @@ static Cell* addDsp(Module *module) { void pack_xilinx_simd(Module *module, const std::vector &selected_cells) { - std::deque simd12, simd24; + std::deque simd12_add, simd12_sub; + std::deque simd24_add, simd24_sub; for (auto cell : selected_cells) { - if (!cell->type.in("$add")) + if (!cell->type.in("$add", "$sub")) continue; SigSpec Y = cell->getPort("\\Y"); if (!Y.is_chunk()) @@ -78,24 +79,26 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) continue; if (GetSize(B) > 12) continue; - simd12.push_back(cell); + if (cell->type == "$add") + simd12_add.push_back(cell); + else if (cell->type == "$sub") + simd12_sub.push_back(cell); } else if (GetSize(Y) <= 25) { if (GetSize(A) > 24) continue; if (GetSize(B) > 24) continue; - simd24.push_back(cell); + if (cell->type == "$add") + simd24_add.push_back(cell); + else if (cell->type == "$sub") + simd24_sub.push_back(cell); } else log_abort(); } - SigSpec AB; - SigSpec C; - SigSpec P; - SigSpec CARRYOUT; - auto f12 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + auto f12 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { SigSpec A = lane->getPort("\\A"); SigSpec B = lane->getPort("\\B"); SigSpec Y = lane->getPort("\\Y"); @@ -110,84 +113,86 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) P.append(Y.extract(0, 12)); CARRYOUT.append(Y[12]); }; - while (simd12.size() > 1) { - AB = SigSpec(); - C = SigSpec(); - P = SigSpec(); - CARRYOUT = SigSpec(); - - Cell *lane1 = simd12.front(); - simd12.pop_front(); - Cell *lane2 = simd12.front(); - simd12.pop_front(); - Cell *lane3 = nullptr; - Cell *lane4 = nullptr; - - if (!simd12.empty()) { - lane3 = simd12.front(); + auto g12 = [&f12,module](std::deque &simd12) { + while (simd12.size() > 1) { + SigSpec AB, C, P, CARRYOUT; + + Cell *lane1 = simd12.front(); + simd12.pop_front(); + Cell *lane2 = simd12.front(); simd12.pop_front(); + Cell *lane3 = nullptr; + Cell *lane4 = nullptr; + if (!simd12.empty()) { - lane4 = simd12.front(); + lane3 = simd12.front(); simd12.pop_front(); + if (!simd12.empty()) { + lane4 = simd12.front(); + simd12.pop_front(); + } } - } - log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); - - Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("FOUR12")); - // X = A:B - // Y = 0 - // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); - - log_assert(lane1); - log_assert(lane2); - f12(lane1); - f12(lane2); - if (lane3) { - f12(lane3); - if (lane4) - f12(lane4); + log("Analysing %s.%s for Xilinx DSP SIMD12 packing.\n", log_id(module), log_id(lane1)); + + Cell *cell = addDsp(module); + cell->setParam("\\USE_SIMD", Const("FOUR12")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); + + log_assert(lane1); + log_assert(lane2); + f12(AB, C, P, CARRYOUT, lane1); + f12(AB, C, P, CARRYOUT, lane2); + if (lane3) { + f12(AB, C, P, CARRYOUT, lane3); + if (lane4) + f12(AB, C, P, CARRYOUT, lane4); + else { + AB.append(Const(0, 12)); + C.append(Const(0, 12)); + P.append(module->addWire(NEW_ID, 12)); + CARRYOUT.append(module->addWire(NEW_ID, 1)); + } + } else { - AB.append(Const(0, 12)); - C.append(Const(0, 12)); - P.append(module->addWire(NEW_ID, 12)); - CARRYOUT.append(module->addWire(NEW_ID, 1)); + AB.append(Const(0, 24)); + C.append(Const(0, 24)); + P.append(module->addWire(NEW_ID, 24)); + CARRYOUT.append(module->addWire(NEW_ID, 2)); } + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + if (lane1->type == "$sub") + cell->setPort("\\ALUMODE", Const::from_string("0011")); + + module->remove(lane1); + module->remove(lane2); + if (lane3) module->remove(lane3); + if (lane4) module->remove(lane4); + + module->design->select(module, cell); } - else { - AB.append(Const(0, 24)); - C.append(Const(0, 24)); - P.append(module->addWire(NEW_ID, 24)); - CARRYOUT.append(module->addWire(NEW_ID, 2)); - } - log_assert(GetSize(AB) == 48); - log_assert(GetSize(C) == 48); - log_assert(GetSize(P) == 48); - log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); - - module->remove(lane1); - module->remove(lane2); - if (lane3) module->remove(lane3); - if (lane4) module->remove(lane4); - - module->design->select(module, cell); - } + }; + g12(simd12_add); + g12(simd12_sub); - auto f24 = [&AB,&C,&P,&CARRYOUT,module](Cell *lane) { + auto f24 = [module](SigSpec &AB, SigSpec &C, SigSpec &P, SigSpec &CARRYOUT, Cell *lane) { SigSpec A = lane->getPort("\\A"); SigSpec B = lane->getPort("\\B"); SigSpec Y = lane->getPort("\\Y"); A.extend_u0(24, lane->getParam("\\A_SIGNED").as_bool()); B.extend_u0(24, lane->getParam("\\B_SIGNED").as_bool()); - AB.append(A); - C.append(B); + AB.append(B); if (GetSize(Y) < 25) Y.append(module->addWire(NEW_ID, 25-GetSize(Y))); else @@ -196,45 +201,51 @@ void pack_xilinx_simd(Module *module, const std::vector &selected_cells) CARRYOUT.append(module->addWire(NEW_ID)); // TWO24 uses every other bit CARRYOUT.append(Y[24]); }; - while (simd24.size() > 1) { - AB = SigSpec(); - C = SigSpec(); - P = SigSpec(); - CARRYOUT = SigSpec(); - - Cell *lane1 = simd24.front(); - simd24.pop_front(); - Cell *lane2 = simd24.front(); - simd24.pop_front(); - - log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); - - Cell *cell = addDsp(module); - cell->setParam("\\USE_SIMD", Const("TWO24")); - // X = A:B - // Y = 0 - // Z = C - cell->setPort("\\OPMODE", Const::from_string("0110011")); - - log_assert(lane1); - log_assert(lane2); - f24(lane1); - f24(lane2); - log_assert(GetSize(AB) == 48); - log_assert(GetSize(C) == 48); - log_assert(GetSize(P) == 48); - log_assert(GetSize(CARRYOUT) == 4); - cell->setPort("\\A", AB.extract(18, 30)); - cell->setPort("\\B", AB.extract(0, 18)); - cell->setPort("\\C", C); - cell->setPort("\\P", P); - cell->setPort("\\CARRYOUT", CARRYOUT); - - module->remove(lane1); - module->remove(lane2); - - module->design->select(module, cell); - } + auto g24 = [&f24,module](std::deque &simd24) { + while (simd24.size() > 1) { + SigSpec AB; + SigSpec C; + SigSpec P; + SigSpec CARRYOUT; + + Cell *lane1 = simd24.front(); + simd24.pop_front(); + Cell *lane2 = simd24.front(); + simd24.pop_front(); + + log("Analysing %s.%s for Xilinx DSP SIMD24 packing.\n", log_id(module), log_id(lane1)); + + Cell *cell = addDsp(module); + cell->setParam("\\USE_SIMD", Const("TWO24")); + // X = A:B + // Y = 0 + // Z = C + cell->setPort("\\OPMODE", Const::from_string("0110011")); + + log_assert(lane1); + log_assert(lane2); + f24(AB, C, P, CARRYOUT, lane1); + f24(AB, C, P, CARRYOUT, lane2); + log_assert(GetSize(AB) == 48); + log_assert(GetSize(C) == 48); + log_assert(GetSize(P) == 48); + log_assert(GetSize(CARRYOUT) == 4); + cell->setPort("\\A", AB.extract(18, 30)); + cell->setPort("\\B", AB.extract(0, 18)); + cell->setPort("\\C", C); + cell->setPort("\\P", P); + cell->setPort("\\CARRYOUT", CARRYOUT); + if (lane1->type == "$sub") + cell->setPort("\\ALUMODE", Const::from_string("0011")); + + module->remove(lane1); + module->remove(lane2); + + module->design->select(module, cell); + } + }; + g24(simd24_add); + g24(simd24_sub); } -- 2.30.2