diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 5c0f7191a..7e01ff134 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -95,7 +95,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { - dict> sigbit_to_shiftx_offset; + dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -108,18 +108,25 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell->getParam("\\Y_WIDTH") != 1) continue; int j = 0; for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0); log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } else if (cell->type == "$pmux") { - if (cell->getParam("\\WIDTH") != 1) continue; - auto a_bit = sigmap(cell->getPort("\\A")).as_bit(); - sigbit_to_shiftx_offset[a_bit] = std::make_pair(cell, 0); - int j = cell->getParam("\\S_WIDTH").as_int(); - for (auto bit : sigmap(cell->getPort("\\B"))) - sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j--); + int width = cell->getParam("\\WIDTH").as_int(); + int j = 0; + for (auto bit : cell->getPort("\\A")) + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); + j = cell->getParam("\\S_WIDTH").as_int(); + int k = 0; + for (auto bit : sigmap(cell->getPort("\\B"))) { + printf("%d\n", bit.offset); + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); + if (k == width) { + k = 0; + --j; + } + } log_assert(j == 0); - } } } @@ -140,6 +147,9 @@ struct ShregmapTechXilinx7 : ShregmapTech virtual bool analyze(vector &taps, const vector &qbits) override { + log("analyze() with %zu taps", taps.size()); + for (auto t : taps) log(" %d", t); + log("\n"); if (GetSize(taps) == 1) return taps[0] >= opts.minlen-1; @@ -147,6 +157,7 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; Cell *shiftx = nullptr; + int group = 0; for (int i = 0; i < GetSize(taps); ++i) { // Check taps are sequential if (i != taps[i]) @@ -159,8 +170,8 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; } else { - shiftx = it->second.first; - int offset = it->second.second; + int offset; + std::tie(shiftx,offset,group) = it->second; if (offset != i) return false; } @@ -170,11 +181,15 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; } else { - if (shiftx != it->second.first) + Cell *shiftx_ = std::get<0>(it->second); + if (shiftx_ != shiftx) return false; - int offset = it->second.second; + int offset = std::get<1>(it->second); if (offset != i) return false; + int group_ = std::get<2>(it->second); + if (group_ != group) + return false; } } } @@ -214,10 +229,12 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\D", cell->getPort("\\D")); newcell->setPort("\\E", cell->getPort("\\E")); - Cell* shiftx = it->second.first; - RTLIL::SigSpec l_wire; + Cell* shiftx = std::get<0>(it->second); + RTLIL::SigSpec l_wire, q_wire; if (shiftx->type == "$shiftx") { l_wire = shiftx->getPort("\\B"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } else if (shiftx->type == "$pmux") { // Create a new encoder, out of a $pmux, that takes @@ -229,14 +246,17 @@ struct ShregmapTechXilinx7 : ShregmapTech b_port.append(RTLIL::Const(i, clog2taps)); l_wire = cell->module->addWire(NEW_ID, clog2taps); cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, shiftx->getPort("\\S"), l_wire); + int group = std::get<2>(it->second); + RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); + q_wire = y_wire[group]; + y_wire[group] = cell->module->addWire(NEW_ID); + shiftx->setPort("\\Y", y_wire); } else log_abort(); - newcell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\Q", q_wire); newcell->setPort("\\L", l_wire); - cell->module->remove(shiftx); - return false; } };