From 93b16219110d3175ffee1874e6fa0a3cb25383f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 15:57:07 -0700 Subject: [PATCH] Cope with undoing #895 --- passes/techmap/shregmap.cc | 40 +++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 39ca60b80..bd75cd95e 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -96,6 +96,7 @@ struct ShregmapTechGreenpak4 : ShregmapTech struct ShregmapTechXilinx7 : ShregmapTech { dict> sigbit_to_shiftx_offset; + dict sigbit_to_eq_input; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -113,16 +114,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } else if (cell->type == "$mux") { int j = 0; - for (auto bit : cell->getPort("\\A")) + for (auto bit : sigmap(cell->getPort("\\A"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); j = 0; for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } else if (cell->type == "$pmux") { + if (!cell->get_bool_attribute("\\shiftx_compatible")) continue; int width = cell->getParam("\\WIDTH").as_int(); int j = 0; - for (auto bit : cell->getPort("\\A")) + for (auto bit : sigmap(cell->getPort("\\A"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++); j = cell->getParam("\\S_WIDTH").as_int(); int k = 0; @@ -135,6 +137,15 @@ struct ShregmapTechXilinx7 : ShregmapTech } log_assert(j == 0); } + else if (cell->type == "$eq") { + auto b_wire = cell->getPort("\\B"); + // Keep track of $eq cells that compare against the value 1 + // in anticipation that they drive the select (S) port of a $pmux + if (b_wire.is_fully_const() && b_wire.as_int() == 1) { + auto y_wire = sigmap(cell->getPort("\\Y").as_bit()); + sigbit_to_eq_input[y_wire] = cell->getPort("\\A"); + } + } } } @@ -239,19 +250,20 @@ struct ShregmapTechXilinx7 : ShregmapTech shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } else if (shiftx->type == "$pmux") { - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - int clog2taps = ceil(log2(taps.size())); - RTLIL::SigSpec b_port; - for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) - b_port.append(RTLIL::Const(i, clog2taps)); - l_wire = cell->module->addWire(NEW_ID, clog2taps); - RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, shiftx->getParam("\\S_WIDTH").as_int()); - cell->module->connect(s_wire.extract(0, shiftx->getParam("\\S_WIDTH").as_int()), shiftx->getPort("\\S")); - cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, s_wire, l_wire); - int group = std::get<2>(it->second); + // If the 'A' port is fully undef, then opt_expr -mux_undef + // has not been applied, so find the second-to-last bit of + // the 'S' port (corresponding to $eq cell comparing for 1) + // otherwise use the last bit of 'S' + const auto& s_wire_bits = shiftx->getPort("\\S").bits(); + SigBit s1; + if (shiftx->getPort("\\A").is_fully_undef()) + s1 = s_wire_bits[s_wire_bits.size() - 2]; + else + s1 = s_wire_bits[s_wire_bits.size() - 1]; RTLIL::SigSpec y_wire = shiftx->getPort("\\Y"); + l_wire = sigbit_to_eq_input.at(s1); + log_assert(l_wire.size() == ceil(log2(taps.size()))); + int group = std::get<2>(it->second); q_wire = y_wire[group]; y_wire[group] = cell->module->addWire(NEW_ID); shiftx->setPort("\\Y", y_wire);