From 26ecbc1aee1dca1c186ab2b51835d74f67bc3e75 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 08:10:02 -0700 Subject: Add shregmap -init_msb_first and use in synth_xilinx --- passes/techmap/shregmap.cc | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f20863ba0..6cd9082dc 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -34,7 +34,7 @@ struct ShregmapOptions { int minlen, maxlen; int keep_before, keep_after; - bool zinit, init, params, ffe; + bool zinit, init, params, ffe, init_msb_first; dict> ffcells; ShregmapTech *tech; @@ -48,6 +48,7 @@ struct ShregmapOptions init = false; params = false; ffe = false; + init_msb_first = false; tech = nullptr; } }; @@ -307,6 +308,8 @@ struct ShregmapWorker initval.push_back(State::S0); remove_init.insert(bit); } + if (opts.init_msb_first) + std::reverse(initval.begin(), initval.end()); first_cell->setParam("\\INIT", initval); } @@ -442,9 +445,13 @@ struct ShregmapPass : public Pass { log("\n"); log(" -init\n"); log(" map initialized registers to the shift reg, add an INIT parameter to\n"); - log(" generated cells with the initialization value. (first bit to shift out\n"); + log(" generated cells with the initialization value. (First bit to shift out\n"); log(" in LSB position)\n"); log("\n"); + log(" -init_msb_first\n"); + log(" same as -init, but INIT parameter to have first bit to shift out\n"); + log(" in MSB position.\n"); + log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); log("\n"); @@ -515,6 +522,11 @@ struct ShregmapPass : public Pass { opts.init = true; continue; } + if (args[argidx] == "-init_msb_first") { + opts.init = true; + opts.init_msb_first = true; + continue; + } if (args[argidx] == "-params") { opts.params = true; continue; -- cgit v1.2.3 From 8af9979aab5f1434ee7d0e56a85324d78e2fd9f9 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 14 Mar 2019 09:01:48 -0700 Subject: Revert "Add shregmap -init_msb_first and use in synth_xilinx" This reverts commit 26ecbc1aee1dca1c186ab2b51835d74f67bc3e75. --- passes/techmap/shregmap.cc | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 6cd9082dc..f20863ba0 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -34,7 +34,7 @@ struct ShregmapOptions { int minlen, maxlen; int keep_before, keep_after; - bool zinit, init, params, ffe, init_msb_first; + bool zinit, init, params, ffe; dict> ffcells; ShregmapTech *tech; @@ -48,7 +48,6 @@ struct ShregmapOptions init = false; params = false; ffe = false; - init_msb_first = false; tech = nullptr; } }; @@ -308,8 +307,6 @@ struct ShregmapWorker initval.push_back(State::S0); remove_init.insert(bit); } - if (opts.init_msb_first) - std::reverse(initval.begin(), initval.end()); first_cell->setParam("\\INIT", initval); } @@ -445,13 +442,9 @@ struct ShregmapPass : public Pass { log("\n"); log(" -init\n"); log(" map initialized registers to the shift reg, add an INIT parameter to\n"); - log(" generated cells with the initialization value. (First bit to shift out\n"); + log(" generated cells with the initialization value. (first bit to shift out\n"); log(" in LSB position)\n"); log("\n"); - log(" -init_msb_first\n"); - log(" same as -init, but INIT parameter to have first bit to shift out\n"); - log(" in MSB position.\n"); - log("\n"); log(" -tech greenpak4\n"); log(" map to greenpak4 shift registers.\n"); log("\n"); @@ -522,11 +515,6 @@ struct ShregmapPass : public Pass { opts.init = true; continue; } - if (args[argidx] == "-init_msb_first") { - opts.init = true; - opts.init_msb_first = true; - continue; - } if (args[argidx] == "-params") { opts.params = true; continue; -- cgit v1.2.3 From 06f8f2654abdef8684bfe4f373ac42cb8c62ee2a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 15 Mar 2019 19:13:40 -0700 Subject: Working --- passes/techmap/shregmap.cc | 583 +++++++++++++++++++++++++++------------------ 1 file changed, 356 insertions(+), 227 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f20863ba0..4b8f8a828 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -26,7 +26,9 @@ PRIVATE_NAMESPACE_BEGIN struct ShregmapTech { virtual ~ShregmapTech() { } - virtual bool analyze(vector &taps) = 0; + virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {} + virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {} + virtual bool analyze(vector &taps, const vector &qbits) = 0; virtual bool fixup(Cell *cell, dict &taps) = 0; }; @@ -54,7 +56,7 @@ struct ShregmapOptions struct ShregmapTechGreenpak4 : ShregmapTech { - bool analyze(vector &taps) + bool analyze(vector &taps, const vector &/*qbits*/) { if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) { taps.clear(); @@ -91,302 +93,423 @@ struct ShregmapTechGreenpak4 : ShregmapTech } }; -struct ShregmapWorker +struct ShregmapTechXilinx7 : ShregmapTech { - Module *module; - SigMap sigmap; - + dict sigbit_to_shiftx; const ShregmapOptions &opts; - int dff_count, shreg_count; - pool remove_cells; - pool remove_init; + ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + virtual void init(const Module* module, const SigMap &sigmap) override + { + for (auto i : module->cells_) { + auto cell = i.second; + if (cell->type != "$shiftx") continue; + if (cell->getParam("\\Y_WIDTH") != 1) continue; + for (auto bit : sigmap(cell->getPort("\\A"))) + sigbit_to_shiftx[bit] = cell; + } + } - void make_sigbit_chain_next_prev() + virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override { - for (auto wire : module->wires()) - { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) - sigbit_with_non_chain_users.insert(bit); - } + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return; + if (cell->type == "$shiftx" && port == "\\A") + return; + it->second = nullptr; + } - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (initval[i] == State::S0 && !opts.zinit) - sigbit_init[initsig[i]] = false; - else if (initval[i] == State::S1) - sigbit_init[initsig[i]] = true; - } - } + virtual bool analyze(vector &taps, const vector &qbits) override + { + if (GetSize(taps) == 1) + return taps[0] >= opts.minlen-1; - for (auto cell : module->cells()) - { - if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) - { - IdString d_port = opts.ffcells.at(cell->type).first; - IdString q_port = opts.ffcells.at(cell->type).second; - - SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); - SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); - - if (opts.init || sigbit_init.count(q_bit) == 0) - { - if (sigbit_chain_next.count(d_bit)) { - sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; - - sigbit_chain_prev[q_bit] = cell; - continue; + if (taps.back() < opts.minlen-1) + return false; + + Cell *shiftx = nullptr; + int offset = 0; + for (int i = 0; i < GetSize(taps); ++i) { + // Check taps are sequential + if (i != taps[i]) + return false; + // Check taps are not connected to a shift register, + // or sequential to the same shift register + auto it = sigbit_to_shiftx.find(qbits[i]); + if (i == 0) { + if (it != sigbit_to_shiftx.end()) { + shiftx = it->second; + // NULL indicates there are non-shiftx users + if (shiftx == nullptr) + return false; + offset = qbits[i].offset; + } + } + else { + if (it == sigbit_to_shiftx.end()) { + if (shiftx != nullptr) + return false; + } + else { + if (shiftx != it->second) + return false; + if (qbits[i].offset != offset + i) + return false; } } - - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) - sigbit_with_non_chain_users.insert(bit); } + + return true; } - void find_chain_start_cells() + virtual bool fixup(Cell *cell, dict &taps) override { - for (auto it : sigbit_chain_next) - { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; + const auto &tap = *taps.begin(); + auto bit = tap.second; + auto it = sigbit_to_shiftx.find(bit); + if (it == sigbit_to_shiftx.end()) + return true; - if (sigbit_chain_prev.count(it.first) != 0) - { - Cell *c1 = sigbit_chain_prev.at(it.first); - Cell *c2 = it.second; + Cell* shiftx = it->second; - if (c1->type != c2->type) - goto start_cell; + auto module = cell->module; - if (c1->parameters != c2->parameters) - goto start_cell; + auto cell_q = cell->getPort("\\Q").as_bit(); - IdString d_port = opts.ffcells.at(c1->type).first; - IdString q_port = opts.ffcells.at(c1->type).second; + auto shiftx_a = shiftx->getPort("\\A").bits(); + int offset = 0; + for (auto bit : shiftx_a) { + if (bit == cell_q) + break; + ++offset; + } + offset -= taps.size() - 1; + log_assert(offset >= 0); + for (size_t i = offset; i < offset + taps.size(); ++i) + shiftx_a[i] = cell_q; + // FIXME: Hack to ensure that $shiftx gets optimised away + // Without this, Yosys will refuse to optimise away a $shiftx + // where \\A 's width is not perfectly \\B_WIDTH ** 2 + auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); + shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); + shiftx->setPort("\\A", shiftx_a); + shiftx->setParam("\\A_WIDTH", shiftx_a.size()); + + auto length = module->addWire(NEW_ID, ceil(log2(taps.size()))); + module->addSub(NEW_ID, shiftx->getPort("\\B"), RTLIL::Const(offset, ceil(log2(offset))), length); + cell->setPort("\\L", length); - auto c1_conn = c1->connections(); - auto c2_conn = c1->connections(); - c1_conn.erase(d_port); - c1_conn.erase(q_port); + return true; + } +}; - c2_conn.erase(d_port); - c2_conn.erase(q_port); - if (c1_conn != c2_conn) - goto start_cell; +struct ShregmapWorker +{ + Module *module; + SigMap sigmap; - continue; - } + const ShregmapOptions &opts; + int dff_count, shreg_count; - start_cell: - chain_start_cells.insert(it.second); - } - } + pool remove_cells; + pool remove_init; + + dict sigbit_init; + dict sigbit_chain_next; + dict sigbit_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; - vector create_chain(Cell *start_cell) + void make_sigbit_chain_next_prev() + { + for (auto wire : module->wires()) { - vector chain; + if (wire->port_output || wire->get_bool_attribute("\\keep")) { + for (auto bit : sigmap(wire)) + sigbit_with_non_chain_users.insert(bit); + } + + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (initval[i] == State::S0 && !opts.zinit) + sigbit_init[initsig[i]] = false; + else if (initval[i] == State::S1) + sigbit_init[initsig[i]] = true; + } + } - Cell *c = start_cell; - while (c != nullptr) - { - chain.push_back(c); + for (auto cell : module->cells()) + { + if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) + { + IdString d_port = opts.ffcells.at(cell->type).first; + IdString q_port = opts.ffcells.at(cell->type).second; - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); + SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); + SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); - if (sigbit_chain_next.count(q_bit) == 0) - break; + if (opts.init || sigbit_init.count(q_bit) == 0) + { + if (sigbit_chain_next.count(d_bit)) { + sigbit_with_non_chain_users.insert(d_bit); + } else + sigbit_chain_next[d_bit] = cell; - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; + sigbit_chain_prev[q_bit] = cell; + continue; } - - return chain; + } + + for (auto conn : cell->connections()) + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) { + sigbit_with_non_chain_users.insert(bit); + if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first); + } } + } - void process_chain(vector &chain) + void find_chain_start_cells() + { + for (auto it : sigbit_chain_next) { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) + goto start_cell; - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) - { - int depth = GetSize(chain) - opts.keep_after - cursor; + if (sigbit_chain_prev.count(it.first) != 0) + { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); + if (c1->type != c2->type) + goto start_cell; - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; + if (c1->parameters != c2->parameters) + goto start_cell; - if (opts.tech) - { - vector qbits; - vector taps; + IdString d_port = opts.ffcells.at(c1->type).first; + IdString q_port = opts.ffcells.at(c1->type).second; - for (int i = 0; i < depth; i++) - { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); - if (sigbit_with_non_chain_users.count(qbit)) - taps.push_back(i); - } - - while (depth > 0) - { - if (taps.empty() || taps.back() < depth-1) - taps.push_back(depth-1); + c1_conn.erase(d_port); + c1_conn.erase(q_port); - if (opts.tech->analyze(taps)) - break; + c2_conn.erase(d_port); + c2_conn.erase(q_port); - taps.pop_back(); - depth--; - } + if (c1_conn != c2_conn) + goto start_cell; - depth = 0; - for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); - log_assert(depth < tap+1); - depth = tap+1; - } - } + continue; + } - if (depth < 2) { - cursor++; - continue; - } +start_cell: + chain_start_cells.insert(it.second); + } + } - Cell *last_cell = chain[cursor+depth-1]; + vector create_chain(Cell *start_cell) + { + vector chain; - log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); - dff_count += depth; - shreg_count += 1; + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - string shreg_cell_type_str = "$__SHREG"; - if (opts.params) { - shreg_cell_type_str += "_"; - } else { - if (first_cell->type[1] != '_') - shreg_cell_type_str += "_"; - shreg_cell_type_str += first_cell->type.substr(1); - } + if (sigbit_chain_next.count(q_bit) == 0) + break; - if (opts.init) { - vector initval; - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - if (sigbit_init.count(bit) == 0) - initval.push_back(State::Sx); - else if (sigbit_init.at(bit)) - initval.push_back(State::S1); - else - initval.push_back(State::S0); - remove_init.insert(bit); - } - first_cell->setParam("\\INIT", initval); - } + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; + } - if (opts.zinit) - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - remove_init.insert(bit); - } + return chain; + } - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; + void process_chain(vector &chain) + { + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; - if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; - first_cell->type = shreg_cell_type_str; - first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam("\\DEPTH", depth); + if (opts.tech) + { + vector qbits; + vector taps; - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); + for (int i = 0; i < depth; i++) + { + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); } - } - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); - - for (auto wire : module->wires()) + while (depth > 0) { - if (wire->attributes.count("\\init") == 0) - continue; + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + if (opts.tech->analyze(taps, qbits)) + break; + + taps.pop_back(); + depth--; + } - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; + depth = 0; + for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); + log_assert(depth < tap+1); + depth = tap+1; + } + } + + if (depth < 2) { + cursor++; + continue; + } + + Cell *last_cell = chain[cursor+depth-1]; + + log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", + log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); + + dff_count += depth; + shreg_count += 1; + + string shreg_cell_type_str = "$__SHREG"; + if (opts.params) { + shreg_cell_type_str += "_"; + } else { + if (first_cell->type[1] != '_') + shreg_cell_type_str += "_"; + shreg_cell_type_str += first_cell->type.substr(1); + } + + if (opts.init) { + vector initval; + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + if (sigbit_init.count(bit) == 0) + initval.push_back(State::Sx); + else if (sigbit_init.at(bit)) + initval.push_back(State::S1); + else + initval.push_back(State::S0); + remove_init.insert(bit); + } + first_cell->setParam("\\INIT", initval); + } - if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); + if (opts.zinit) + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + remove_init.insert(bit); } - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); + if (opts.params) + { + int param_clkpol = -1; + int param_enpol = 2; + + if (first_cell->type == "$_DFF_N_") param_clkpol = 0; + if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + + if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + + log_assert(param_clkpol >= 0); + first_cell->setParam("\\CLKPOL", param_clkpol); + if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); + } + + first_cell->type = shreg_cell_type_str; + first_cell->setPort(q_port, last_cell->getPort(q_port)); + if (!first_cell->hasPort("\\L")) + first_cell->setPort("\\L", depth-1); + first_cell->setParam("\\DEPTH", depth); + + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + remove_cells.insert(first_cell); + + for (int i = 1; i < depth; i++) + remove_cells.insert(chain[cursor+i]); + cursor += depth; } + } + + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); - ShregmapWorker(Module *module, const ShregmapOptions &opts) : - module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) + for (auto wire : module->wires()) { - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + if (wire->attributes.count("\\init") == 0) + continue; - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); - } + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); - cleanup(); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (remove_init.count(initsig[i])) + initval[i] = State::Sx; + + if (SigSpec(initval).is_fully_undef()) + wire->attributes.erase("\\init"); } + + remove_cells.clear(); + sigbit_chain_next.clear(); + sigbit_chain_prev.clear(); + chain_start_cells.clear(); + } + + ShregmapWorker(Module *module, const ShregmapOptions &opts) : + module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) + { + if (opts.tech) + opts.tech->init(module, sigmap); + + make_sigbit_chain_next_prev(); + find_chain_start_cells(); + + for (auto c : chain_start_cells) { + vector chain = create_chain(c); + process_chain(chain); + } + + cleanup(); + } }; struct ShregmapPass : public Pass { @@ -501,6 +624,12 @@ struct ShregmapPass : public Pass { clkpol = "pos"; opts.zinit = true; opts.tech = new ShregmapTechGreenpak4; + } + else if (tech == "xilinx") { + opts.init = true; + opts.params = true; + enpol = "any_or_none"; + opts.tech = new ShregmapTechXilinx7(opts); } else { argidx--; break; -- cgit v1.2.3 From fadeadb8c87670b1cfe8f92ac9c5ac3beadcb312 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 08:51:13 -0700 Subject: Only accept <128 for variable length, only if $shiftx exclusive --- passes/techmap/shregmap.cc | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 4b8f8a828..f893461a0 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -161,6 +161,16 @@ struct ShregmapTechXilinx7 : ShregmapTech } } + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (shiftx && GetSize(taps) > 128) + return false; + + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + return true; } @@ -173,34 +183,33 @@ struct ShregmapTechXilinx7 : ShregmapTech return true; Cell* shiftx = it->second; - - auto module = cell->module; + auto shiftx_a = shiftx->getPort("\\A").bits(); auto cell_q = cell->getPort("\\Q").as_bit(); - auto shiftx_a = shiftx->getPort("\\A").bits(); int offset = 0; +#ifndef NDEBUG for (auto bit : shiftx_a) { if (bit == cell_q) break; ++offset; } offset -= taps.size() - 1; - log_assert(offset >= 0); + log_assert(offset == 0); +#endif for (size_t i = offset; i < offset + taps.size(); ++i) shiftx_a[i] = cell_q; + // FIXME: Hack to ensure that $shiftx gets optimised away // Without this, Yosys will refuse to optimise away a $shiftx // where \\A 's width is not perfectly \\B_WIDTH ** 2 + // See YosysHQ/yosys#878 auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); shiftx->setPort("\\A", shiftx_a); shiftx->setParam("\\A_WIDTH", shiftx_a.size()); - auto length = module->addWire(NEW_ID, ceil(log2(taps.size()))); - module->addSub(NEW_ID, shiftx->getPort("\\B"), RTLIL::Const(offset, ceil(log2(offset))), length); - cell->setPort("\\L", length); - + cell->setPort("\\L", shiftx->getPort("\\B")); return true; } -- cgit v1.2.3 From d6d9ef0fee3a187b884cbfd0b9a97da935666189 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 16 Mar 2019 12:49:46 -0700 Subject: Cleanup --- passes/techmap/shregmap.cc | 60 +++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f893461a0..179a331fd 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; + dict> sigbit_to_shiftx_offset; const ShregmapOptions &opts; ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {} @@ -106,19 +106,21 @@ struct ShregmapTechXilinx7 : ShregmapTech auto cell = i.second; if (cell->type != "$shiftx") continue; if (cell->getParam("\\Y_WIDTH") != 1) continue; + int j = 0; for (auto bit : sigmap(cell->getPort("\\A"))) - sigbit_to_shiftx[bit] = cell; + sigbit_to_shiftx_offset[bit] = std::make_pair(cell, j++); + log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } } virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override { - auto it = sigbit_to_shiftx.find(bit); - if (it == sigbit_to_shiftx.end()) + auto it = sigbit_to_shiftx_offset.find(bit); + if (it == sigbit_to_shiftx_offset.end()) return; if (cell->type == "$shiftx" && port == "\\A") return; - it->second = nullptr; + it->second = std::make_pair(nullptr, 0); } virtual bool analyze(vector &taps, const vector &qbits) override @@ -130,32 +132,34 @@ struct ShregmapTechXilinx7 : ShregmapTech return false; Cell *shiftx = nullptr; - int offset = 0; for (int i = 0; i < GetSize(taps); ++i) { // Check taps are sequential if (i != taps[i]) return false; // Check taps are not connected to a shift register, // or sequential to the same shift register - auto it = sigbit_to_shiftx.find(qbits[i]); + auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it != sigbit_to_shiftx.end()) { - shiftx = it->second; + if (it != sigbit_to_shiftx_offset.end()) { + shiftx = it->second.first; // NULL indicates there are non-shiftx users if (shiftx == nullptr) return false; - offset = qbits[i].offset; + int offset = it->second.second; + if (offset != i) + return false; } } else { - if (it == sigbit_to_shiftx.end()) { + if (it == sigbit_to_shiftx_offset.end()) { if (shiftx != nullptr) return false; } else { - if (shiftx != it->second) + if (shiftx != it->second.first) return false; - if (qbits[i].offset != offset + i) + int offset = it->second.second; + if (offset != i) return false; } } @@ -178,36 +182,22 @@ struct ShregmapTechXilinx7 : ShregmapTech { const auto &tap = *taps.begin(); auto bit = tap.second; - auto it = sigbit_to_shiftx.find(bit); - if (it == sigbit_to_shiftx.end()) + auto it = sigbit_to_shiftx_offset.find(bit); + // If fixed-length, no fixup necessary + if (it == sigbit_to_shiftx_offset.end()) return true; - Cell* shiftx = it->second; - auto shiftx_a = shiftx->getPort("\\A").bits(); - - auto cell_q = cell->getPort("\\Q").as_bit(); - - int offset = 0; -#ifndef NDEBUG - for (auto bit : shiftx_a) { - if (bit == cell_q) - break; - ++offset; - } - offset -= taps.size() - 1; - log_assert(offset == 0); -#endif - for (size_t i = offset; i < offset + taps.size(); ++i) - shiftx_a[i] = cell_q; + auto cell_q = cell->getPort("\\Q"); + log_assert(cell_q.is_bit()); + Cell* shiftx = it->second.first; // FIXME: Hack to ensure that $shiftx gets optimised away // Without this, Yosys will refuse to optimise away a $shiftx // where \\A 's width is not perfectly \\B_WIDTH ** 2 // See YosysHQ/yosys#878 auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); - shiftx_a.resize(1 << shiftx_bwidth, shiftx_a.back()); - shiftx->setPort("\\A", shiftx_a); - shiftx->setParam("\\A_WIDTH", shiftx_a.size()); + shiftx->setPort("\\A", cell_q.repeat(1 << shiftx_bwidth)); + shiftx->setParam("\\A_WIDTH", 1 << shiftx_bwidth); cell->setPort("\\L", shiftx->getPort("\\B")); -- cgit v1.2.3 From b94db546645e624b752203a4c4d2395dc84dff0c Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 13:35:54 -0700 Subject: shiftx NULL pointer check --- passes/techmap/shregmap.cc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 179a331fd..f3153b400 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -165,15 +165,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } } - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (shiftx && GetSize(taps) > 128) - return false; + if (shiftx) { + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (GetSize(taps) > 128) + return false; - // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + } return true; } -- cgit v1.2.3 From ed32119d133166c78870137c6ce3db781b92c2e4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 18 Mar 2019 16:12:19 -0700 Subject: Fix shregmap to correctly recognise non chain users; cleanup --- passes/techmap/shregmap.cc | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index f3153b400..d95cadde5 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -120,7 +120,7 @@ struct ShregmapTechXilinx7 : ShregmapTech return; if (cell->type == "$shiftx" && port == "\\A") return; - it->second = std::make_pair(nullptr, 0); + sigbit_to_shiftx_offset.erase(it); } virtual bool analyze(vector &taps, const vector &qbits) override @@ -140,11 +140,11 @@ struct ShregmapTechXilinx7 : ShregmapTech // or sequential to the same shift register auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it != sigbit_to_shiftx_offset.end()) { + if (it == sigbit_to_shiftx_offset.end()) { + return false; + } + else { shiftx = it->second.first; - // NULL indicates there are non-shiftx users - if (shiftx == nullptr) - return false; int offset = it->second.second; if (offset != i) return false; @@ -152,8 +152,7 @@ struct ShregmapTechXilinx7 : ShregmapTech } else { if (it == sigbit_to_shiftx_offset.end()) { - if (shiftx != nullptr) - return false; + return false; } else { if (shiftx != it->second.first) @@ -164,18 +163,17 @@ struct ShregmapTechXilinx7 : ShregmapTech } } } + log_assert(shiftx); - if (shiftx) { - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (GetSize(taps) > 128) - return false; + // Cannot implement variable-length shift registers + // greater than 128 since Q31 cannot be output onto + // fabric + if (GetSize(taps) > 128) + return false; - // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; - } + // Only map if $shiftx exclusively covers the shift register + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; return true; } -- cgit v1.2.3 From 0ea7eba5f13b20de28181a66181ee821820027db Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 13:08:43 -0700 Subject: Make output port a non chain user --- passes/techmap/shregmap.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d95cadde5..3b3170e04 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -118,7 +118,7 @@ struct ShregmapTechXilinx7 : ShregmapTech auto it = sigbit_to_shiftx_offset.find(bit); if (it == sigbit_to_shiftx_offset.end()) return; - if (cell->type == "$shiftx" && port == "\\A") + if (cell && cell->type == "$shiftx" && port == "\\A") return; sigbit_to_shiftx_offset.erase(it); } @@ -228,8 +228,10 @@ struct ShregmapWorker for (auto wire : module->wires()) { if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) + for (auto bit : sigmap(wire)) { sigbit_with_non_chain_users.insert(bit); + if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); + } } if (wire->attributes.count("\\init")) { -- cgit v1.2.3 From 4cd8f0297381c5fb9fe3b8cbb22d4240f2aaae63 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 15:05:08 -0700 Subject: shregmap -tech xilinx to delete $shiftx for var length SRL --- passes/techmap/shregmap.cc | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 3b3170e04..bd537e7c2 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -187,19 +187,12 @@ struct ShregmapTechXilinx7 : ShregmapTech if (it == sigbit_to_shiftx_offset.end()) return true; - auto cell_q = cell->getPort("\\Q"); - log_assert(cell_q.is_bit()); - Cell* shiftx = it->second.first; - // FIXME: Hack to ensure that $shiftx gets optimised away - // Without this, Yosys will refuse to optimise away a $shiftx - // where \\A 's width is not perfectly \\B_WIDTH ** 2 - // See YosysHQ/yosys#878 - auto shiftx_bwidth = shiftx->getParam("\\B_WIDTH").as_int(); - shiftx->setPort("\\A", cell_q.repeat(1 << shiftx_bwidth)); - shiftx->setParam("\\A_WIDTH", 1 << shiftx_bwidth); cell->setPort("\\L", shiftx->getPort("\\B")); + cell->setPort("\\Q", shiftx->getPort("\\Y")); + + cell->module->remove(shiftx); return true; } -- cgit v1.2.3 From 5445cd4d00349f9d04f9e78c7c2804306fac6b65 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 17:44:33 -0700 Subject: Add support for variable length Xilinx SRL > 128 --- passes/techmap/shregmap.cc | 6 ------ 1 file changed, 6 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index bd537e7c2..a060b55df 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -165,12 +165,6 @@ struct ShregmapTechXilinx7 : ShregmapTech } log_assert(shiftx); - // Cannot implement variable-length shift registers - // greater than 128 since Q31 cannot be output onto - // fabric - if (GetSize(taps) > 128) - return false; - // Only map if $shiftx exclusively covers the shift register if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; -- cgit v1.2.3 From 505e4c2d59ed81a1779644b7aaf61aee799c8f67 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Tue, 19 Mar 2019 21:58:05 -0700 Subject: Revert $__SHREG_ to orig; use $__XILINX_SHREG for variable length --- passes/techmap/shregmap.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a060b55df..1729418e6 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -176,19 +176,30 @@ struct ShregmapTechXilinx7 : ShregmapTech { const auto &tap = *taps.begin(); auto bit = tap.second; + auto it = sigbit_to_shiftx_offset.find(bit); // If fixed-length, no fixup necessary if (it == sigbit_to_shiftx_offset.end()) return true; + auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); + newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); + newcell->setParam("\\INIT", cell->getParam("\\INIT")); + newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); + newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL")); + + newcell->setPort("\\C", cell->getPort("\\C")); + newcell->setPort("\\D", cell->getPort("\\D")); + newcell->setPort("\\E", cell->getPort("\\E")); + Cell* shiftx = it->second.first; - cell->setPort("\\L", shiftx->getPort("\\B")); - cell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\L", shiftx->getPort("\\B")); + newcell->setPort("\\Q", shiftx->getPort("\\Y")); cell->module->remove(shiftx); - return true; + return false; } }; @@ -442,8 +453,6 @@ start_cell: first_cell->type = shreg_cell_type_str; first_cell->setPort(q_port, last_cell->getPort(q_port)); - if (!first_cell->hasPort("\\L")) - first_cell->setPort("\\L", depth-1); first_cell->setParam("\\DEPTH", depth); if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) -- cgit v1.2.3 From 2b911e270ba8012aa85f342838ed31b54568f257 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 20 Mar 2019 12:28:39 -0700 Subject: Fix spacing --- passes/techmap/shregmap.cc | 478 ++++++++++++++++++++++----------------------- 1 file changed, 239 insertions(+), 239 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 1729418e6..028f4ba35 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -206,307 +206,307 @@ struct ShregmapTechXilinx7 : ShregmapTech struct ShregmapWorker { - Module *module; - SigMap sigmap; + Module *module; + SigMap sigmap; - const ShregmapOptions &opts; - int dff_count, shreg_count; - - pool remove_cells; - pool remove_init; + const ShregmapOptions &opts; + int dff_count, shreg_count; - dict sigbit_init; - dict sigbit_chain_next; - dict sigbit_chain_prev; - pool sigbit_with_non_chain_users; - pool chain_start_cells; + pool remove_cells; + pool remove_init; - void make_sigbit_chain_next_prev() - { - for (auto wire : module->wires()) - { - if (wire->port_output || wire->get_bool_attribute("\\keep")) { - for (auto bit : sigmap(wire)) { - sigbit_with_non_chain_users.insert(bit); - if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); - } - } - - if (wire->attributes.count("\\init")) { - SigSpec initsig = sigmap(wire); - Const initval = wire->attributes.at("\\init"); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (initval[i] == State::S0 && !opts.zinit) - sigbit_init[initsig[i]] = false; - else if (initval[i] == State::S1) - sigbit_init[initsig[i]] = true; - } - } + dict sigbit_init; + dict sigbit_chain_next; + dict sigbit_chain_prev; + pool sigbit_with_non_chain_users; + pool chain_start_cells; - for (auto cell : module->cells()) + void make_sigbit_chain_next_prev() { - if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) - { - IdString d_port = opts.ffcells.at(cell->type).first; - IdString q_port = opts.ffcells.at(cell->type).second; + for (auto wire : module->wires()) + { + if (wire->port_output || wire->get_bool_attribute("\\keep")) { + for (auto bit : sigmap(wire)) { + sigbit_with_non_chain_users.insert(bit); + if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {}); + } + } - SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); - SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); + if (wire->attributes.count("\\init")) { + SigSpec initsig = sigmap(wire); + Const initval = wire->attributes.at("\\init"); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (initval[i] == State::S0 && !opts.zinit) + sigbit_init[initsig[i]] = false; + else if (initval[i] == State::S1) + sigbit_init[initsig[i]] = true; + } + } - if (opts.init || sigbit_init.count(q_bit) == 0) + for (auto cell : module->cells()) { - if (sigbit_chain_next.count(d_bit)) { - sigbit_with_non_chain_users.insert(d_bit); - } else - sigbit_chain_next[d_bit] = cell; + if (opts.ffcells.count(cell->type) && !cell->get_bool_attribute("\\keep")) + { + IdString d_port = opts.ffcells.at(cell->type).first; + IdString q_port = opts.ffcells.at(cell->type).second; + + SigBit d_bit = sigmap(cell->getPort(d_port).as_bit()); + SigBit q_bit = sigmap(cell->getPort(q_port).as_bit()); + + if (opts.init || sigbit_init.count(q_bit) == 0) + { + if (sigbit_chain_next.count(d_bit)) { + sigbit_with_non_chain_users.insert(d_bit); + } else + sigbit_chain_next[d_bit] = cell; + + sigbit_chain_prev[q_bit] = cell; + continue; + } + } - sigbit_chain_prev[q_bit] = cell; - continue; + for (auto conn : cell->connections()) + if (cell->input(conn.first)) + for (auto bit : sigmap(conn.second)) { + sigbit_with_non_chain_users.insert(bit); + if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first); + } } - } - - for (auto conn : cell->connections()) - if (cell->input(conn.first)) - for (auto bit : sigmap(conn.second)) { - sigbit_with_non_chain_users.insert(bit); - if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first); - } } - } - void find_chain_start_cells() - { - for (auto it : sigbit_chain_next) + void find_chain_start_cells() { - if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) - goto start_cell; + for (auto it : sigbit_chain_next) + { + if (opts.tech == nullptr && sigbit_with_non_chain_users.count(it.first)) + goto start_cell; - if (sigbit_chain_prev.count(it.first) != 0) - { - Cell *c1 = sigbit_chain_prev.at(it.first); - Cell *c2 = it.second; + if (sigbit_chain_prev.count(it.first) != 0) + { + Cell *c1 = sigbit_chain_prev.at(it.first); + Cell *c2 = it.second; - if (c1->type != c2->type) - goto start_cell; + if (c1->type != c2->type) + goto start_cell; - if (c1->parameters != c2->parameters) - goto start_cell; + if (c1->parameters != c2->parameters) + goto start_cell; - IdString d_port = opts.ffcells.at(c1->type).first; - IdString q_port = opts.ffcells.at(c1->type).second; + IdString d_port = opts.ffcells.at(c1->type).first; + IdString q_port = opts.ffcells.at(c1->type).second; - auto c1_conn = c1->connections(); - auto c2_conn = c1->connections(); + auto c1_conn = c1->connections(); + auto c2_conn = c1->connections(); - c1_conn.erase(d_port); - c1_conn.erase(q_port); + c1_conn.erase(d_port); + c1_conn.erase(q_port); - c2_conn.erase(d_port); - c2_conn.erase(q_port); + c2_conn.erase(d_port); + c2_conn.erase(q_port); - if (c1_conn != c2_conn) - goto start_cell; + if (c1_conn != c2_conn) + goto start_cell; - continue; - } + continue; + } -start_cell: - chain_start_cells.insert(it.second); + start_cell: + chain_start_cells.insert(it.second); + } } - } - vector create_chain(Cell *start_cell) - { - vector chain; - - Cell *c = start_cell; - while (c != nullptr) + vector create_chain(Cell *start_cell) { - chain.push_back(c); + vector chain; - IdString q_port = opts.ffcells.at(c->type).second; - SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); + Cell *c = start_cell; + while (c != nullptr) + { + chain.push_back(c); - if (sigbit_chain_next.count(q_bit) == 0) - break; + IdString q_port = opts.ffcells.at(c->type).second; + SigBit q_bit = sigmap(c->getPort(q_port).as_bit()); - c = sigbit_chain_next.at(q_bit); - if (chain_start_cells.count(c) != 0) - break; - } + if (sigbit_chain_next.count(q_bit) == 0) + break; - return chain; - } + c = sigbit_chain_next.at(q_bit); + if (chain_start_cells.count(c) != 0) + break; + } - void process_chain(vector &chain) - { - if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) - return; + return chain; + } - int cursor = opts.keep_before; - while (cursor < GetSize(chain) - opts.keep_after) + void process_chain(vector &chain) { - int depth = GetSize(chain) - opts.keep_after - cursor; + if (GetSize(chain) < opts.keep_before + opts.minlen + opts.keep_after) + return; - if (opts.maxlen > 0) - depth = std::min(opts.maxlen, depth); + int cursor = opts.keep_before; + while (cursor < GetSize(chain) - opts.keep_after) + { + int depth = GetSize(chain) - opts.keep_after - cursor; - Cell *first_cell = chain[cursor]; - IdString q_port = opts.ffcells.at(first_cell->type).second; - dict taps_dict; + if (opts.maxlen > 0) + depth = std::min(opts.maxlen, depth); - if (opts.tech) - { - vector qbits; - vector taps; + Cell *first_cell = chain[cursor]; + IdString q_port = opts.ffcells.at(first_cell->type).second; + dict taps_dict; - for (int i = 0; i < depth; i++) - { - Cell *cell = chain[cursor+i]; - auto qbit = sigmap(cell->getPort(q_port)); - qbits.push_back(qbit); + if (opts.tech) + { + vector qbits; + vector taps; - if (sigbit_with_non_chain_users.count(qbit)) - taps.push_back(i); - } + for (int i = 0; i < depth; i++) + { + Cell *cell = chain[cursor+i]; + auto qbit = sigmap(cell->getPort(q_port)); + qbits.push_back(qbit); - while (depth > 0) - { - if (taps.empty() || taps.back() < depth-1) - taps.push_back(depth-1); + if (sigbit_with_non_chain_users.count(qbit)) + taps.push_back(i); + } - if (opts.tech->analyze(taps, qbits)) - break; + while (depth > 0) + { + if (taps.empty() || taps.back() < depth-1) + taps.push_back(depth-1); - taps.pop_back(); - depth--; - } + if (opts.tech->analyze(taps, qbits)) + break; - depth = 0; - for (auto tap : taps) { - taps_dict[tap] = qbits.at(tap); - log_assert(depth < tap+1); - depth = tap+1; - } - } - - if (depth < 2) { - cursor++; - continue; - } - - Cell *last_cell = chain[cursor+depth-1]; - - log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", - log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); - - dff_count += depth; - shreg_count += 1; - - string shreg_cell_type_str = "$__SHREG"; - if (opts.params) { - shreg_cell_type_str += "_"; - } else { - if (first_cell->type[1] != '_') - shreg_cell_type_str += "_"; - shreg_cell_type_str += first_cell->type.substr(1); - } - - if (opts.init) { - vector initval; - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - if (sigbit_init.count(bit) == 0) - initval.push_back(State::Sx); - else if (sigbit_init.at(bit)) - initval.push_back(State::S1); - else - initval.push_back(State::S0); - remove_init.insert(bit); - } - first_cell->setParam("\\INIT", initval); - } + taps.pop_back(); + depth--; + } - if (opts.zinit) - for (int i = depth-1; i >= 0; i--) { - SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); - remove_init.insert(bit); - } + depth = 0; + for (auto tap : taps) { + taps_dict[tap] = qbits.at(tap); + log_assert(depth < tap+1); + depth = tap+1; + } + } - if (opts.params) - { - int param_clkpol = -1; - int param_enpol = 2; + if (depth < 2) { + cursor++; + continue; + } - if (first_cell->type == "$_DFF_N_") param_clkpol = 0; - if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + Cell *last_cell = chain[cursor+depth-1]; - if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; - if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; - if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; - if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; + log("Converting %s.%s ... %s.%s to a shift register with depth %d.\n", + log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), depth); - log_assert(param_clkpol >= 0); - first_cell->setParam("\\CLKPOL", param_clkpol); - if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); - } + dff_count += depth; + shreg_count += 1; - first_cell->type = shreg_cell_type_str; - first_cell->setPort(q_port, last_cell->getPort(q_port)); - first_cell->setParam("\\DEPTH", depth); + string shreg_cell_type_str = "$__SHREG"; + if (opts.params) { + shreg_cell_type_str += "_"; + } else { + if (first_cell->type[1] != '_') + shreg_cell_type_str += "_"; + shreg_cell_type_str += first_cell->type.substr(1); + } - if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) - remove_cells.insert(first_cell); + if (opts.init) { + vector initval; + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + if (sigbit_init.count(bit) == 0) + initval.push_back(State::Sx); + else if (sigbit_init.at(bit)) + initval.push_back(State::S1); + else + initval.push_back(State::S0); + remove_init.insert(bit); + } + first_cell->setParam("\\INIT", initval); + } - for (int i = 1; i < depth; i++) - remove_cells.insert(chain[cursor+i]); - cursor += depth; - } - } + if (opts.zinit) + for (int i = depth-1; i >= 0; i--) { + SigBit bit = sigmap(chain[cursor+i]->getPort(q_port).as_bit()); + remove_init.insert(bit); + } - void cleanup() - { - for (auto cell : remove_cells) - module->remove(cell); + if (opts.params) + { + int param_clkpol = -1; + int param_enpol = 2; - for (auto wire : module->wires()) - { - if (wire->attributes.count("\\init") == 0) - continue; + if (first_cell->type == "$_DFF_N_") param_clkpol = 0; + if (first_cell->type == "$_DFF_P_") param_clkpol = 1; + + if (first_cell->type == "$_DFFE_NN_") param_clkpol = 0, param_enpol = 0; + if (first_cell->type == "$_DFFE_NP_") param_clkpol = 0, param_enpol = 1; + if (first_cell->type == "$_DFFE_PN_") param_clkpol = 1, param_enpol = 0; + if (first_cell->type == "$_DFFE_PP_") param_clkpol = 1, param_enpol = 1; - SigSpec initsig = sigmap(wire); - Const &initval = wire->attributes.at("\\init"); + log_assert(param_clkpol >= 0); + first_cell->setParam("\\CLKPOL", param_clkpol); + if (opts.ffe) first_cell->setParam("\\ENPOL", param_enpol); + } + + first_cell->type = shreg_cell_type_str; + first_cell->setPort(q_port, last_cell->getPort(q_port)); + first_cell->setParam("\\DEPTH", depth); - for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) - if (remove_init.count(initsig[i])) - initval[i] = State::Sx; + if (opts.tech != nullptr && !opts.tech->fixup(first_cell, taps_dict)) + remove_cells.insert(first_cell); - if (SigSpec(initval).is_fully_undef()) - wire->attributes.erase("\\init"); + for (int i = 1; i < depth; i++) + remove_cells.insert(chain[cursor+i]); + cursor += depth; + } } - remove_cells.clear(); - sigbit_chain_next.clear(); - sigbit_chain_prev.clear(); - chain_start_cells.clear(); - } + void cleanup() + { + for (auto cell : remove_cells) + module->remove(cell); + + for (auto wire : module->wires()) + { + if (wire->attributes.count("\\init") == 0) + continue; - ShregmapWorker(Module *module, const ShregmapOptions &opts) : - module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) - { - if (opts.tech) - opts.tech->init(module, sigmap); + SigSpec initsig = sigmap(wire); + Const &initval = wire->attributes.at("\\init"); - make_sigbit_chain_next_prev(); - find_chain_start_cells(); + for (int i = 0; i < GetSize(initsig) && i < GetSize(initval); i++) + if (remove_init.count(initsig[i])) + initval[i] = State::Sx; - for (auto c : chain_start_cells) { - vector chain = create_chain(c); - process_chain(chain); + if (SigSpec(initval).is_fully_undef()) + wire->attributes.erase("\\init"); + } + + remove_cells.clear(); + sigbit_chain_next.clear(); + sigbit_chain_prev.clear(); + chain_start_cells.clear(); } - cleanup(); - } + ShregmapWorker(Module *module, const ShregmapOptions &opts) : + module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0) + { + if (opts.tech) + opts.tech->init(module, sigmap); + + make_sigbit_chain_next_prev(); + find_chain_start_cells(); + + for (auto c : chain_start_cells) { + vector chain = create_chain(c); + process_chain(chain); + } + + cleanup(); + } }; struct ShregmapPass : public Pass { -- cgit v1.2.3 From 5597270b9e2331d8836c8c24a073aadc1e19584a Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 21 Mar 2019 10:20:27 -0700 Subject: Opt --- passes/techmap/shregmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 028f4ba35..d5221d46f 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -102,7 +102,7 @@ struct ShregmapTechXilinx7 : ShregmapTech virtual void init(const Module* module, const SigMap &sigmap) override { - for (auto i : module->cells_) { + for (const auto &i : module->cells_) { auto cell = i.second; if (cell->type != "$shiftx") continue; if (cell->getParam("\\Y_WIDTH") != 1) continue; -- cgit v1.2.3 From 03d108cd1f785fd32394746221fb81380b051ed1 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 17:46:49 -0700 Subject: Working for 1 bit --- passes/techmap/shregmap.cc | 60 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 49 insertions(+), 11 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d5221d46f..5c0f7191a 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -104,12 +104,23 @@ struct ShregmapTechXilinx7 : ShregmapTech { for (const auto &i : module->cells_) { auto cell = i.second; - if (cell->type != "$shiftx") continue; - 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++); - log_assert(j == cell->getParam("\\A_WIDTH").as_int()); + if (cell->type == "$shiftx") { + 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++); + 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--); + log_assert(j == 0); + + } } } @@ -118,8 +129,12 @@ struct ShregmapTechXilinx7 : ShregmapTech auto it = sigbit_to_shiftx_offset.find(bit); if (it == sigbit_to_shiftx_offset.end()) return; - if (cell && cell->type == "$shiftx" && port == "\\A") - return; + if (cell) { + if (cell->type == "$shiftx" && port == "\\A") + return; + if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) + return; + } sigbit_to_shiftx_offset.erase(it); } @@ -166,8 +181,15 @@ struct ShregmapTechXilinx7 : ShregmapTech log_assert(shiftx); // Only map if $shiftx exclusively covers the shift register - if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) - return false; + if (shiftx->type == "$shiftx") { + if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) + return false; + } + else if (shiftx->type == "$pmux") { + if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) + return false; + } + else log_abort(); return true; } @@ -193,9 +215,25 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\E", cell->getPort("\\E")); Cell* shiftx = it->second.first; + RTLIL::SigSpec l_wire; + if (shiftx->type == "$shiftx") { + l_wire = shiftx->getPort("\\B"); + } + 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); + cell->module->addPmux(NEW_ID, RTLIL::Const(0, clog2taps), b_port, shiftx->getPort("\\S"), l_wire); + } + else log_abort(); - newcell->setPort("\\L", shiftx->getPort("\\B")); newcell->setPort("\\Q", shiftx->getPort("\\Y")); + newcell->setPort("\\L", l_wire); cell->module->remove(shiftx); -- cgit v1.2.3 From 456295eb6686316dd6090ed32787bd91dc6e8d61 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 18:32:42 -0700 Subject: Fixes for multibit --- passes/techmap/shregmap.cc | 56 +++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 18 deletions(-) (limited to 'passes/techmap') 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; } }; -- cgit v1.2.3 From 0895093c7ce91e13c7fa8e878ae41f8877b3870d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 19:14:04 -0700 Subject: Leftover printf --- passes/techmap/shregmap.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 7e01ff134..d9a4aba99 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,7 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech 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; -- cgit v1.2.3 From 098bd5758fe2e4cb7efa44503a1c498b0a2ace5e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 22 Mar 2019 23:22:19 -0700 Subject: Add support for SHREGMAP+$mux, also fine tune $pmux --- passes/techmap/shregmap.cc | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index d9a4aba99..fb48094ec 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -111,6 +111,14 @@ struct ShregmapTechXilinx7 : ShregmapTech sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0); log_assert(j == cell->getParam("\\A_WIDTH").as_int()); } + else if (cell->type == "$mux") { + int j = 0; + for (auto bit : 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") { int width = cell->getParam("\\WIDTH").as_int(); int j = 0; @@ -140,6 +148,8 @@ struct ShregmapTechXilinx7 : ShregmapTech return; if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) return; + if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) + return; } sigbit_to_shiftx_offset.erase(it); } @@ -203,6 +213,10 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) return false; } + else if (shiftx->type == "$mux") { + if (GetSize(taps) != 2) + return false; + } else log_abort(); return true; @@ -243,14 +257,23 @@ struct ShregmapTechXilinx7 : ShregmapTech RTLIL::SigSpec b_port; for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) b_port.append(RTLIL::Const(i, clog2taps)); + for (int i = (1 << clog2taps); i > shiftx->getParam("\\S_WIDTH").as_int(); i--) + b_port.append(RTLIL::Const(RTLIL::Sx, 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); + RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, (1 << clog2taps)); + 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); 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 if (shiftx->type == "$mux") { + l_wire = shiftx->getPort("\\S"); + q_wire = shiftx->getPort("\\Y"); + shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); + } else log_abort(); newcell->setPort("\\Q", q_wire); -- cgit v1.2.3 From bf83c074c82756b1cd23a9c3998b6c4d535dae29 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sat, 23 Mar 2019 16:09:38 -0700 Subject: Cope with SHREG not having E port; Revert $pmux fine tune --- passes/techmap/shregmap.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index fb48094ec..7cf52c19a 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -240,7 +240,8 @@ struct ShregmapTechXilinx7 : ShregmapTech newcell->setPort("\\C", cell->getPort("\\C")); newcell->setPort("\\D", cell->getPort("\\D")); - newcell->setPort("\\E", cell->getPort("\\E")); + if (cell->hasPort("\\E")) + newcell->setPort("\\E", cell->getPort("\\E")); Cell* shiftx = std::get<0>(it->second); RTLIL::SigSpec l_wire, q_wire; @@ -257,10 +258,8 @@ struct ShregmapTechXilinx7 : ShregmapTech RTLIL::SigSpec b_port; for (int i = shiftx->getParam("\\S_WIDTH").as_int(); i > 0; i--) b_port.append(RTLIL::Const(i, clog2taps)); - for (int i = (1 << clog2taps); i > shiftx->getParam("\\S_WIDTH").as_int(); i--) - b_port.append(RTLIL::Const(RTLIL::Sx, clog2taps)); l_wire = cell->module->addWire(NEW_ID, clog2taps); - RTLIL::SigSpec s_wire = cell->module->addWire(NEW_ID, (1 << 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); -- cgit v1.2.3 From aa693d5723ef1438d42cd35a26673703b1eff79f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 3 Apr 2019 08:35:32 -0700 Subject: Remove handling for $pmux, since #895 --- passes/techmap/shregmap.cc | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 7cf52c19a..408e3f8c7 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,22 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } - else if (cell->type == "$pmux") { - 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"))) { - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); - if (k == width) { - k = 0; - --j; - } - } - log_assert(j == 0); - } } } @@ -146,8 +130,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; - if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) - return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -209,10 +191,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } - else if (shiftx->type == "$pmux") { - if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) - return false; - } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -250,24 +228,6 @@ struct ShregmapTechXilinx7 : ShregmapTech 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 - // 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); - 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 if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); -- cgit v1.2.3 From 19271bd996a79cb4be1db658fcf18227ee0a1dff Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 14:42:25 -0700 Subject: abc -dff now implies "-D 0" otherwise retiming doesn't happen --- passes/techmap/abc.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 21b70f492..c828ad8ed 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1674,6 +1674,8 @@ struct AbcPass : public Pass { } if (arg == "-dff") { dff_mode = true; + if (delay_target.empty()) + delay_target = "-D 0"; continue; } if (arg == "-clk" && argidx+1 < args.size()) { -- cgit v1.2.3 From 3c253818cab2013dc4db55732d3e21cfa0dc3f19 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 15:30:19 -0700 Subject: "&nf -D 0" fails => use "-D 1" instead --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index c828ad8ed..4876f3009 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1675,7 +1675,7 @@ struct AbcPass : public Pass { if (arg == "-dff") { dff_mode = true; if (delay_target.empty()) - delay_target = "-D 0"; + delay_target = "-D 1"; continue; } if (arg == "-clk" && argidx+1 < args.size()) { -- cgit v1.2.3 From d55902300772d90aee09555d412079e17fd4bde7 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 16:28:14 -0700 Subject: Fix S0 -> S1 --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 4876f3009..e2a152348 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1728,7 +1728,7 @@ struct AbcPass : public Pass { signal_init[initsig[i]] = State::S0; break; case State::S1: - signal_init[initsig[i]] = State::S0; + signal_init[initsig[i]] = State::S1; break; default: break; -- cgit v1.2.3 From 1d526b7f061fb7e7961fa4d0b318b27cfda469d4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Fri, 5 Apr 2019 17:35:49 -0700 Subject: Call shregmap twice -- once for variable, another for fixed --- passes/techmap/shregmap.cc | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index 408e3f8c7..a805ac5a6 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -138,11 +138,8 @@ 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; + return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]); if (taps.back() < opts.minlen-1) return false; @@ -150,38 +147,31 @@ struct ShregmapTechXilinx7 : ShregmapTech Cell *shiftx = nullptr; int group = 0; for (int i = 0; i < GetSize(taps); ++i) { + auto it = sigbit_to_shiftx_offset.find(qbits[i]); + if (it == sigbit_to_shiftx_offset.end()) + return false; + // Check taps are sequential if (i != taps[i]) return false; // Check taps are not connected to a shift register, // or sequential to the same shift register - auto it = sigbit_to_shiftx_offset.find(qbits[i]); if (i == 0) { - if (it == sigbit_to_shiftx_offset.end()) { + int offset; + std::tie(shiftx,offset,group) = it->second; + if (offset != i) return false; - } - else { - int offset; - std::tie(shiftx,offset,group) = it->second; - if (offset != i) - return false; - } } else { - if (it == sigbit_to_shiftx_offset.end()) { + Cell *shiftx_ = std::get<0>(it->second); + if (shiftx_ != shiftx) + return false; + int offset = std::get<1>(it->second); + if (offset != i) + return false; + int group_ = std::get<2>(it->second); + if (group_ != group) return false; - } - else { - Cell *shiftx_ = std::get<0>(it->second); - if (shiftx_ != shiftx) - return false; - int offset = std::get<1>(it->second); - if (offset != i) - return false; - int group_ = std::get<2>(it->second); - if (group_ != group) - return false; - } } } log_assert(shiftx); @@ -206,9 +196,7 @@ struct ShregmapTechXilinx7 : ShregmapTech auto bit = tap.second; auto it = sigbit_to_shiftx_offset.find(bit); - // If fixed-length, no fixup necessary - if (it == sigbit_to_shiftx_offset.end()) - return true; + log_assert(it != sigbit_to_shiftx_offset.end()); auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); -- cgit v1.2.3 From d3930ca79eb11952d8e64588e46b0788845997c4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 12:01:06 -0700 Subject: Revert "Remove handling for $pmux, since #895" This reverts commit aa693d5723ef1438d42cd35a26673703b1eff79f. --- passes/techmap/shregmap.cc | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index a805ac5a6..39ca60b80 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -119,6 +119,22 @@ struct ShregmapTechXilinx7 : ShregmapTech for (auto bit : sigmap(cell->getPort("\\B"))) sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++); } + else if (cell->type == "$pmux") { + 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"))) { + sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); + if (k == width) { + k = 0; + --j; + } + } + log_assert(j == 0); + } } } @@ -130,6 +146,8 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; + if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) + return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -181,6 +199,10 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } + else if (shiftx->type == "$pmux") { + if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) + return false; + } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -216,6 +238,24 @@ struct ShregmapTechXilinx7 : ShregmapTech 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 + // 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); + 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 if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); -- cgit v1.2.3 From 93b16219110d3175ffee1874e6fa0a3cb25383f8 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 15:57:07 -0700 Subject: Cope with undoing #895 --- passes/techmap/shregmap.cc | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) (limited to 'passes/techmap') 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); -- cgit v1.2.3 From 6797f6b6c4660622dbde27ced83fdd37a874f00d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Mon, 8 Apr 2019 16:24:20 -0700 Subject: $_XILINX_SHREG_ to preserve src attribute --- passes/techmap/shregmap.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'passes/techmap') diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index bd75cd95e..ec43b5654 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -232,6 +232,7 @@ struct ShregmapTechXilinx7 : ShregmapTech log_assert(it != sigbit_to_shiftx_offset.end()); auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_"); + newcell->set_src_attribute(cell->get_src_attribute()); newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH")); newcell->setParam("\\INIT", cell->getParam("\\INIT")); newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL")); -- cgit v1.2.3 From 78d35a86c0e94f1c5e1606f9953d1f340132f02e Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 08:31:35 -0700 Subject: Revert ""&nf -D 0" fails => use "-D 1" instead" This reverts commit 3c253818cab2013dc4db55732d3e21cfa0dc3f19. --- passes/techmap/abc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index e2a152348..f94fc7589 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1675,7 +1675,7 @@ struct AbcPass : public Pass { if (arg == "-dff") { dff_mode = true; if (delay_target.empty()) - delay_target = "-D 1"; + delay_target = "-D 0"; continue; } if (arg == "-clk" && argidx+1 < args.size()) { -- cgit v1.2.3 From 5f4024ffd2a59e3c0c7edce4057c47d3a005e18f Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Wed, 10 Apr 2019 08:31:40 -0700 Subject: Revert "abc -dff now implies "-D 0" otherwise retiming doesn't happen" This reverts commit 19271bd996a79cb4be1db658fcf18227ee0a1dff. --- passes/techmap/abc.cc | 2 -- 1 file changed, 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index f94fc7589..3adbe0a04 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -1674,8 +1674,6 @@ struct AbcPass : public Pass { } if (arg == "-dff") { dff_mode = true; - if (delay_target.empty()) - delay_target = "-D 0"; continue; } if (arg == "-clk" && argidx+1 < args.size()) { -- cgit v1.2.3 From 09e7eb7aed85bac33fb570d2286be5689de59b31 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:09:13 -0700 Subject: Spelling fixes --- passes/techmap/pmuxtree.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc index b7a22dc3b..6a923f481 100644 --- a/passes/techmap/pmuxtree.cc +++ b/passes/techmap/pmuxtree.cc @@ -71,9 +71,9 @@ struct PmuxtreePass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" pmuxtree [options] [selection]\n"); + log(" pmuxtree [selection]\n"); log("\n"); - log("This pass transforms $pmux cells to a trees of $mux cells.\n"); + log("This pass transforms $pmux cells to trees of $mux cells.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From e8c26f2839611f5b52c29f711670888b02066064 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:52:04 -0700 Subject: WIP --- passes/techmap/Makefile.inc | 1 + passes/techmap/pmux2shiftx.cc | 88 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) create mode 100644 passes/techmap/pmux2shiftx.cc (limited to 'passes/techmap') diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index cf9e198ad..81df499da 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,6 +37,7 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o +OBJS += passes/techmap/pmux2shiftx.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc new file mode 100644 index 000000000..6569f995f --- /dev/null +++ b/passes/techmap/pmux2shiftx.cc @@ -0,0 +1,88 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Clifford Wolf + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" +#include "kernel/sigtools.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct Pmux2ShiftxPass : public Pass { + Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } + void help() YS_OVERRIDE + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" pmux2shiftx [selection]\n"); + log("\n"); + log("This pass transforms $pmux cells to $shiftx cells.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE + { + log_header(design, "Executing PMUX2SHIFTX pass.\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + break; + } + extra_args(args, argidx, design); + + for (auto module : design->selected_modules()) + for (auto cell : module->selected_cells()) + { + if (cell->type != "$pmux") + continue; + + // Create a new encoder, out of a $pmux, that takes + // the existing pmux's 'S' input and transforms it + // back into a binary value + const int s_width = cell->getParam("\\S_WIDTH").as_int(); + const int width = cell->getParam("\\WIDTH").as_int(); + const int clog2width = ceil(log2(s_width)); + RTLIL::SigSpec shiftx_a; + RTLIL::SigSpec pmux_a; + RTLIL::SigSpec pmux_b; + RTLIL::SigSpec b_port = cell->getPort("\\B"); + if (!cell->getPort("\\A").is_fully_undef()) { + pmux_a = RTLIL::Const(RTLIL::S0, clog2width); + shiftx_a.append(cell->getPort("\\A")); + for (int i = s_width; i > 0; i--) { + shiftx_a.append(b_port.extract((i-1)*width, width)); + pmux_b.append(RTLIL::Const(i, clog2width)); + } + + } + else { + pmux_a = RTLIL::Const(RTLIL::Sx, clog2width); + for (int i = s_width-1; i >= 0; i--) { + shiftx_a.append(b_port.extract(i*width, width)); + pmux_b.append(RTLIL::Const(i, clog2width)); + } + } + RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); + RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); + module->addPmux(NEW_ID, pmux_a, pmux_b, cell->getPort("\\S"), pmux_y); + module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); + module->remove(cell); + } + } +} Pmux2ShiftxPass; + +PRIVATE_NAMESPACE_END -- cgit v1.2.3 From b1f1db2fcf0e27fbd9cb7b94ab5c9d8879ad9694 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:17:09 -0700 Subject: Fixes --- passes/techmap/pmux2shiftx.cc | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 6569f995f..9b05f8f6d 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -53,32 +53,28 @@ struct Pmux2ShiftxPass : public Pass { // Create a new encoder, out of a $pmux, that takes // the existing pmux's 'S' input and transforms it // back into a binary value - const int s_width = cell->getParam("\\S_WIDTH").as_int(); + RTLIL::SigSpec shiftx_a; + RTLIL::SigSpec pmux_s; + + int s_width = cell->getParam("\\S_WIDTH").as_int(); + if (!cell->getPort("\\A").is_fully_undef()) { + ++s_width; + shiftx_a.append(cell->getPort("\\A")); + pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); + } const int width = cell->getParam("\\WIDTH").as_int(); const int clog2width = ceil(log2(s_width)); - RTLIL::SigSpec shiftx_a; - RTLIL::SigSpec pmux_a; + RTLIL::SigSpec pmux_b; - RTLIL::SigSpec b_port = cell->getPort("\\B"); - if (!cell->getPort("\\A").is_fully_undef()) { - pmux_a = RTLIL::Const(RTLIL::S0, clog2width); - shiftx_a.append(cell->getPort("\\A")); - for (int i = s_width; i > 0; i--) { - shiftx_a.append(b_port.extract((i-1)*width, width)); - pmux_b.append(RTLIL::Const(i, clog2width)); - } + pmux_b.append(RTLIL::Const(0, clog2width)); + for (int i = s_width-1; i > 0; i--) + pmux_b.append(RTLIL::Const(i, clog2width)); + shiftx_a.append(cell->getPort("\\B")); + pmux_s.append(cell->getPort("\\S")); - } - else { - pmux_a = RTLIL::Const(RTLIL::Sx, clog2width); - for (int i = s_width-1; i >= 0; i--) { - shiftx_a.append(b_port.extract(i*width, width)); - pmux_b.append(RTLIL::Const(i, clog2width)); - } - } RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); - module->addPmux(NEW_ID, pmux_a, pmux_b, cell->getPort("\\S"), pmux_y); + module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); module->remove(cell); } -- cgit v1.2.3 From b15b410b41cca3a79bfcfc9c91f665815f31ab5b Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:18:01 -0700 Subject: Remove unused --- passes/techmap/pmux2shiftx.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 9b05f8f6d..08cb06d5f 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -73,7 +73,6 @@ struct Pmux2ShiftxPass : public Pass { pmux_s.append(cell->getPort("\\S")); RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); - RTLIL::SigSpec shiftx_s = module->addWire(NEW_ID, 1 << clog2width); module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); module->remove(cell); -- cgit v1.2.3 From f587950bde58b326e1f7319c84d5652a0dc43216 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:20:43 -0700 Subject: More unused --- passes/techmap/pmux2shiftx.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index 08cb06d5f..f8cdf5783 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -62,7 +62,6 @@ struct Pmux2ShiftxPass : public Pass { shiftx_a.append(cell->getPort("\\A")); pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); } - const int width = cell->getParam("\\WIDTH").as_int(); const int clog2width = ceil(log2(s_width)); RTLIL::SigSpec pmux_b; -- cgit v1.2.3 From 3c1f1a6605a4463117ba358fc9528c4999628b81 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 16:25:59 -0700 Subject: Fix ordering of when to insert zero index --- passes/techmap/pmux2shiftx.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc index f8cdf5783..6ffc27a4c 100644 --- a/passes/techmap/pmux2shiftx.cc +++ b/passes/techmap/pmux2shiftx.cc @@ -65,8 +65,7 @@ struct Pmux2ShiftxPass : public Pass { const int clog2width = ceil(log2(s_width)); RTLIL::SigSpec pmux_b; - pmux_b.append(RTLIL::Const(0, clog2width)); - for (int i = s_width-1; i > 0; i--) + for (int i = s_width-1; i >= 0; i--) pmux_b.append(RTLIL::Const(i, clog2width)); shiftx_a.append(cell->getPort("\\B")); pmux_s.append(cell->getPort("\\S")); -- cgit v1.2.3 From f4abc21d8ad79621cc24852bd76abf40a9d9f702 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 18 Apr 2019 17:42:12 +0200 Subject: Add "whitebox" attribute, add "read_verilog -wb" Signed-off-by: Clifford Wolf --- passes/techmap/dfflibmap.cc | 2 +- passes/techmap/techmap.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/dfflibmap.cc b/passes/techmap/dfflibmap.cc index 274177a68..b5c0498d0 100644 --- a/passes/techmap/dfflibmap.cc +++ b/passes/techmap/dfflibmap.cc @@ -664,7 +664,7 @@ struct DfflibmapPass : public Pass { logmap_all(); for (auto &it : design->modules_) - if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox")) + if (design->selected(it.second) && !it.second->get_blackbox_attribute()) dfflibmap(design, it.second, prepare_mode); cell_mappings.clear(); diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index d0e5e2236..d694e8165 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -472,7 +472,7 @@ struct TechmapWorker RTLIL::Module *tpl = map->modules_[tpl_name]; std::map parameters(cell->parameters.begin(), cell->parameters.end()); - if (tpl->get_bool_attribute("\\blackbox")) + if (tpl->get_blackbox_attribute()) continue; if (!flatten_mode) @@ -1209,7 +1209,7 @@ struct FlattenPass : public Pass { dict new_modules; for (auto mod : vector(design->modules())) - if (used_modules[mod->name] || mod->get_bool_attribute("\\blackbox")) { + if (used_modules[mod->name] || mod->get_blackbox_attribute()) { new_modules[mod->name] = mod; } else { log("Deleting now unused module %s.\n", log_id(mod)); -- cgit v1.2.3 From 9aa94370a54c016421740d2ce32ef0aa338d0dbd Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 08:46:41 -0700 Subject: ABC to call retime all the time --- passes/techmap/abc.cc | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index 3adbe0a04..aaf580eff 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -29,17 +29,17 @@ // Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025 // http://en.wikipedia.org/wiki/Topological_sorting -#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" -#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2" -#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}" -#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put" - -#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}" -#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" -#define ABC_FAST_COMMAND_LUT "strash; dretime; if" -#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}" -#define ABC_FAST_COMMAND_DFL "strash; dretime; map" +#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" +#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2" +#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}" +#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put" + +#define ABC_FAST_COMMAND_LIB "strash; dretime; retime {D}; map {D}" +#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p" +#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if" +#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}" +#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map" #include "kernel/register.h" #include "kernel/sigtools.h" @@ -731,10 +731,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin else abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL; - if (script_file.empty() && !delay_target.empty()) - for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1)) - abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8); - for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos)) abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3); -- cgit v1.2.3 From 070a2d2fd6b2d79a71be1ab5b8fe40e40e690433 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 09:55:03 -0700 Subject: Fix abc's remap_name to not ignore [^0-9] when extracting sid --- passes/techmap/abc.cc | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/abc.cc b/passes/techmap/abc.cc index aaf580eff..547115459 100644 --- a/passes/techmap/abc.cc +++ b/passes/techmap/abc.cc @@ -331,19 +331,23 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp { std::string abc_sname = abc_name.substr(1); if (abc_sname.substr(0, 5) == "ys__n") { - int sid = std::stoi(abc_sname.substr(5)); bool inv = abc_sname.back() == 'v'; - for (auto sig : signal_list) { - if (sig.id == sid && sig.bit.wire != nullptr) { - std::stringstream sstr; - sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1); - if (sig.bit.wire->width != 1) - sstr << "[" << sig.bit.offset << "]"; - if (inv) - sstr << "_inv"; - if (orig_wire != nullptr) - *orig_wire = sig.bit.wire; - return sstr.str(); + if (inv) abc_sname.pop_back(); + abc_sname.erase(0, 5); + if (abc_sname.find_last_not_of("012345689") == std::string::npos) { + int sid = std::stoi(abc_sname); + for (auto sig : signal_list) { + if (sig.id == sid && sig.bit.wire != nullptr) { + std::stringstream sstr; + sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1); + if (sig.bit.wire->width != 1) + sstr << "[" << sig.bit.offset << "]"; + if (inv) + sstr << "_inv"; + if (orig_wire != nullptr) + *orig_wire = sig.bit.wire; + return sstr.str(); + } } } } -- cgit v1.2.3 From 290a798cec4dae02886877a342b00c1ba7d5b22d Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 18 Apr 2019 10:19:45 -0700 Subject: Ignore 'whitebox' attr in flatten with "-wb" option --- passes/techmap/techmap.cc | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index d694e8165..82c815e2e 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -84,6 +84,7 @@ struct TechmapWorker bool flatten_mode; bool recursive_mode; bool autoproc_mode; + bool ignore_wb; TechmapWorker() { @@ -92,6 +93,7 @@ struct TechmapWorker flatten_mode = false; recursive_mode = false; autoproc_mode = false; + ignore_wb = false; } std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose) @@ -472,7 +474,7 @@ struct TechmapWorker RTLIL::Module *tpl = map->modules_[tpl_name]; std::map parameters(cell->parameters.begin(), cell->parameters.end()); - if (tpl->get_blackbox_attribute()) + if (tpl->get_blackbox_attribute(ignore_wb)) continue; if (!flatten_mode) @@ -1145,7 +1147,7 @@ struct FlattenPass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" flatten [selection]\n"); + log(" flatten [options] [selection]\n"); log("\n"); log("This pass flattens the design by replacing cells by their implementation. This\n"); log("pass is very similar to the 'techmap' pass. The only difference is that this\n"); @@ -1154,17 +1156,29 @@ struct FlattenPass : public Pass { log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n"); log("flattened by this command.\n"); log("\n"); + log(" -wb\n"); + log(" Ignore the 'whitebox' attribute on cell implementations.\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE { log_header(design, "Executing FLATTEN pass (flatten design).\n"); log_push(); - extra_args(args, 1, design); - TechmapWorker worker; worker.flatten_mode = true; + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-wb") { + worker.ignore_wb = true; + continue; + } + break; + } + extra_args(args, argidx, design); + + std::map> celltypeMap; for (auto module : design->modules()) celltypeMap[module->name].insert(module->name); @@ -1209,7 +1223,7 @@ struct FlattenPass : public Pass { dict new_modules; for (auto mod : vector(design->modules())) - if (used_modules[mod->name] || mod->get_blackbox_attribute()) { + if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) { new_modules[mod->name] = mod; } else { log("Deleting now unused module %s.\n", log_id(mod)); -- cgit v1.2.3 From 9dec3d997821e274b71e67c38582c29f4ae5dfac Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Thu, 11 Apr 2019 15:09:13 -0700 Subject: Spelling fixes --- passes/techmap/pmuxtree.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/pmuxtree.cc b/passes/techmap/pmuxtree.cc index b7a22dc3b..6a923f481 100644 --- a/passes/techmap/pmuxtree.cc +++ b/passes/techmap/pmuxtree.cc @@ -71,9 +71,9 @@ struct PmuxtreePass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" pmuxtree [options] [selection]\n"); + log(" pmuxtree [selection]\n"); log("\n"); - log("This pass transforms $pmux cells to a trees of $mux cells.\n"); + log("This pass transforms $pmux cells to trees of $mux cells.\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE -- cgit v1.2.3 From b7445ef3871b38360440d5c83dbac45c96b67277 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 11:10:05 +0200 Subject: Check blackbox attribute in techmap/simplemap Signed-off-by: Clifford Wolf --- passes/techmap/simplemap.cc | 2 +- passes/techmap/techmap.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/simplemap.cc b/passes/techmap/simplemap.cc index 660b60601..f3da80c66 100644 --- a/passes/techmap/simplemap.cc +++ b/passes/techmap/simplemap.cc @@ -599,7 +599,7 @@ struct SimplemapPass : public Pass { simplemap_get_mappers(mappers); for (auto mod : design->modules()) { - if (!design->selected(mod)) + if (!design->selected(mod) || mod->get_blackbox_attribute()) continue; std::vector cells = mod->cells(); for (auto cell : cells) { diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 82c815e2e..416bf4f1c 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -385,7 +385,7 @@ struct TechmapWorker { std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping"; - if (!design->selected(module)) + if (!design->selected(module) || module->get_blackbox_attribute()) return false; bool log_continue = false; -- cgit v1.2.3 From f3ad8d680a3195ab9525b0a8b3f8dbff9d5e6e24 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Sat, 20 Apr 2019 11:23:24 +0200 Subject: Add "techmap -wb", use in formal flows Signed-off-by: Clifford Wolf --- passes/techmap/techmap.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 416bf4f1c..ee319b6e6 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -385,7 +385,7 @@ struct TechmapWorker { std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping"; - if (!design->selected(module) || module->get_blackbox_attribute()) + if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb)) return false; bool log_continue = false; @@ -927,6 +927,9 @@ struct TechmapPass : public Pass { log(" -autoproc\n"); log(" Automatically call \"proc\" on implementations that contain processes.\n"); log("\n"); + log(" -wb\n"); + log(" Ignore the 'whitebox' attribute on cell implementations.\n"); + log("\n"); log(" -assert\n"); log(" this option will cause techmap to exit with an error if it can't map\n"); log(" a selected cell. only cell types that end on an underscore are accepted\n"); @@ -1070,6 +1073,10 @@ struct TechmapPass : public Pass { worker.autoproc_mode = true; continue; } + if (args[argidx] == "-wb") { + worker.ignore_wb = true; + continue; + } break; } extra_args(args, argidx, design); -- cgit v1.2.3 From d99422411f568d6d8d7de7d11346718e70012df4 Mon Sep 17 00:00:00 2001 From: Eddie Hung Date: Sun, 21 Apr 2019 14:16:34 -0700 Subject: Use new pmux2shiftx from #944, remove my old attempt --- passes/techmap/Makefile.inc | 1 - passes/techmap/pmux2shiftx.cc | 81 ------------------------------------------- passes/techmap/shregmap.cc | 52 --------------------------- 3 files changed, 134 deletions(-) delete mode 100644 passes/techmap/pmux2shiftx.cc (limited to 'passes/techmap') diff --git a/passes/techmap/Makefile.inc b/passes/techmap/Makefile.inc index 81df499da..cf9e198ad 100644 --- a/passes/techmap/Makefile.inc +++ b/passes/techmap/Makefile.inc @@ -37,7 +37,6 @@ OBJS += passes/techmap/attrmap.o OBJS += passes/techmap/zinit.o OBJS += passes/techmap/dff2dffs.o OBJS += passes/techmap/flowmap.o -OBJS += passes/techmap/pmux2shiftx.o endif GENFILES += passes/techmap/techmap.inc diff --git a/passes/techmap/pmux2shiftx.cc b/passes/techmap/pmux2shiftx.cc deleted file mode 100644 index 6ffc27a4c..000000000 --- a/passes/techmap/pmux2shiftx.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Clifford Wolf - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "kernel/yosys.h" -#include "kernel/sigtools.h" - -USING_YOSYS_NAMESPACE -PRIVATE_NAMESPACE_BEGIN - -struct Pmux2ShiftxPass : public Pass { - Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { } - void help() YS_OVERRIDE - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" pmux2shiftx [selection]\n"); - log("\n"); - log("This pass transforms $pmux cells to $shiftx cells.\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) YS_OVERRIDE - { - log_header(design, "Executing PMUX2SHIFTX pass.\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - break; - } - extra_args(args, argidx, design); - - for (auto module : design->selected_modules()) - for (auto cell : module->selected_cells()) - { - if (cell->type != "$pmux") - continue; - - // Create a new encoder, out of a $pmux, that takes - // the existing pmux's 'S' input and transforms it - // back into a binary value - RTLIL::SigSpec shiftx_a; - RTLIL::SigSpec pmux_s; - - int s_width = cell->getParam("\\S_WIDTH").as_int(); - if (!cell->getPort("\\A").is_fully_undef()) { - ++s_width; - shiftx_a.append(cell->getPort("\\A")); - pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S")))); - } - const int clog2width = ceil(log2(s_width)); - - RTLIL::SigSpec pmux_b; - for (int i = s_width-1; i >= 0; i--) - pmux_b.append(RTLIL::Const(i, clog2width)); - shiftx_a.append(cell->getPort("\\B")); - pmux_s.append(cell->getPort("\\S")); - - RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width); - module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y); - module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y")); - module->remove(cell); - } - } -} Pmux2ShiftxPass; - -PRIVATE_NAMESPACE_END diff --git a/passes/techmap/shregmap.cc b/passes/techmap/shregmap.cc index ec43b5654..a541b33be 100644 --- a/passes/techmap/shregmap.cc +++ b/passes/techmap/shregmap.cc @@ -96,7 +96,6 @@ 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) {} @@ -120,32 +119,6 @@ struct ShregmapTechXilinx7 : ShregmapTech 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 : 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; - for (auto bit : sigmap(cell->getPort("\\B"))) { - sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j, k++); - if (k == width) { - k = 0; - --j; - } - } - 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"); - } - } } } @@ -157,8 +130,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (cell) { if (cell->type == "$shiftx" && port == "\\A") return; - if (cell->type == "$pmux" && (port == "\\A" || port == "\\B")) - return; if (cell->type == "$mux" && (port == "\\A" || port == "\\B")) return; } @@ -210,10 +181,6 @@ struct ShregmapTechXilinx7 : ShregmapTech if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) return false; } - else if (shiftx->type == "$pmux") { - if (GetSize(taps) != shiftx->getParam("\\S_WIDTH").as_int() + 1) - return false; - } else if (shiftx->type == "$mux") { if (GetSize(taps) != 2) return false; @@ -250,25 +217,6 @@ struct ShregmapTechXilinx7 : ShregmapTech q_wire = shiftx->getPort("\\Y"); shiftx->setPort("\\Y", cell->module->addWire(NEW_ID)); } - else if (shiftx->type == "$pmux") { - // 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); - } else if (shiftx->type == "$mux") { l_wire = shiftx->getPort("\\S"); q_wire = shiftx->getPort("\\Y"); -- cgit v1.2.3 From 7b35d5759289f7a3139c6eaa525ef737b8d5d82b Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 02:07:36 +0200 Subject: Disable blackbox detection in techmap files Signed-off-by: Clifford Wolf --- passes/techmap/techmap.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index ee319b6e6..1a4318460 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -1036,7 +1036,7 @@ struct TechmapPass : public Pass { simplemap_get_mappers(worker.simplemap_mappers); std::vector map_files; - std::string verilog_frontend = "verilog -nooverwrite"; + std::string verilog_frontend = "verilog -nooverwrite -noblackbox"; int max_iter = -1; size_t argidx; -- cgit v1.2.3 From aeeefc32d8603b138f24824d01b29d28cb0f85cf Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 22 Apr 2019 14:18:15 +0000 Subject: attrmap: extend -remove to allow removing attributes with any value. Currently, `-remove foo` would only remove an attribute `foo = ""`, which doesn't work on an attribute like `src` that may have any value. Extend `-remove` to handle both cases. `-remove foo=""` has the old behavior, and `-remove foo` will remove the attribute with whatever value it may have, which is still compatible with the old behavior. --- passes/techmap/attrmap.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'passes/techmap') diff --git a/passes/techmap/attrmap.cc b/passes/techmap/attrmap.cc index 0b5576b06..aa48e1125 100644 --- a/passes/techmap/attrmap.cc +++ b/passes/techmap/attrmap.cc @@ -111,9 +111,10 @@ struct AttrmapMap : AttrmapAction { }; struct AttrmapRemove : AttrmapAction { + bool has_value; string name, value; bool apply(IdString &id, Const &val) YS_OVERRIDE { - return !(match_name(name, id) && match_value(value, val)); + return !(match_name(name, id) && (!has_value || match_value(value, val))); } }; @@ -235,6 +236,7 @@ struct AttrmapPass : public Pass { } auto action = new AttrmapRemove; action->name = arg1; + action->has_value = (p != string::npos); action->value = val1; actions.push_back(std::unique_ptr(action)); continue; -- cgit v1.2.3 From e158ea20979165c1bac4c5c4027cf53255e57baa Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Mon, 22 Apr 2019 17:25:52 +0200 Subject: Add log_debug() framework Signed-off-by: Clifford Wolf --- passes/techmap/techmap.cc | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) (limited to 'passes/techmap') diff --git a/passes/techmap/techmap.cc b/passes/techmap/techmap.cc index 1a4318460..ab0bd3b54 100644 --- a/passes/techmap/techmap.cc +++ b/passes/techmap/techmap.cc @@ -72,6 +72,8 @@ struct TechmapWorker pool flatten_done_list; pool flatten_keep_list; + pool log_msg_cache; + struct TechmapWireData { RTLIL::Wire *wire; RTLIL::SigSpec value; @@ -390,6 +392,7 @@ struct TechmapWorker bool log_continue = false; bool did_something = false; + LogMakeDebugHdl mkdebug; SigMap sigmap(module); @@ -547,6 +550,7 @@ struct TechmapWorker if (extmapper_name == "wrap") { std::string cmd_string = tpl->attributes.at("\\techmap_wrap").decode_string(); log("Running \"%s\" on wrapper %s.\n", cmd_string.c_str(), log_id(extmapper_module)); + mkdebug.on(); Pass::call_on_module(extmapper_design, extmapper_module, cmd_string); log_continue = true; } @@ -560,11 +564,21 @@ struct TechmapWorker goto use_wrapper_tpl; } - log("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); + auto msg = stringf("Using extmapper %s for cells of type %s.", log_id(extmapper_module), log_id(cell->type)); + if (!log_msg_cache.count(msg)) { + log_msg_cache.insert(msg); + log("%s\n", msg.c_str()); + } + log_debug("%s %s.%s (%s) to %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(extmapper_module)); } else { - log("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); + auto msg = stringf("Using extmapper %s for cells of type %s.", extmapper_name.c_str(), log_id(cell->type)); + if (!log_msg_cache.count(msg)) { + log_msg_cache.insert(msg); + log("%s\n", msg.c_str()); + } + log_debug("%s %s.%s (%s) with %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), extmapper_name.c_str()); if (extmapper_name == "simplemap") { if (simplemap_mappers.count(cell->type) == 0) @@ -662,6 +676,7 @@ struct TechmapWorker tpl = techmap_cache[key]; } else { if (parameters.size() != 0) { + mkdebug.on(); derived_name = tpl->derive(map, dict(parameters.begin(), parameters.end())); tpl = map->module(derived_name); log_continue = true; @@ -831,6 +846,7 @@ struct TechmapWorker if (log_continue) { log_header(design, "Continuing TECHMAP pass.\n"); log_continue = false; + mkdebug.off(); } while (techmap_module(map, tpl, map, handled_cells, celltypeMap, true)) { } } @@ -842,6 +858,7 @@ struct TechmapWorker if (log_continue) { log_header(design, "Continuing TECHMAP pass.\n"); log_continue = false; + mkdebug.off(); } if (extern_mode && !in_recursion) @@ -861,13 +878,18 @@ struct TechmapWorker module_queue.insert(m); } - log("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name)); + log_debug("%s %s.%s to imported %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(m_name)); cell->type = m_name; cell->parameters.clear(); } else { - log("%s %s.%s using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(tpl)); + auto msg = stringf("Using template %s for cells of type %s.", log_id(tpl), log_id(cell->type)); + if (!log_msg_cache.count(msg)) { + log_msg_cache.insert(msg); + log("%s\n", msg.c_str()); + } + log_debug("%s %s.%s (%s) using %s.\n", mapmsg_prefix.c_str(), log_id(module), log_id(cell), log_id(cell->type), log_id(tpl)); techmap_module_worker(design, module, cell, tpl); cell = NULL; } @@ -885,6 +907,7 @@ struct TechmapWorker if (log_continue) { log_header(design, "Continuing TECHMAP pass.\n"); log_continue = false; + mkdebug.off(); } return did_something; @@ -1085,7 +1108,7 @@ struct TechmapPass : public Pass { if (map_files.empty()) { std::istringstream f(stdcells_code); Frontend::frontend_call(map, &f, "", verilog_frontend); - } else + } else { for (auto &fn : map_files) if (fn.substr(0, 1) == "%") { if (!saved_designs.count(fn.substr(1))) { @@ -1104,6 +1127,9 @@ struct TechmapPass : public Pass { log_cmd_error("Can't open map file `%s'\n", fn.c_str()); Frontend::frontend_call(map, &f, fn, (fn.size() > 3 && fn.substr(fn.size()-3) == ".il") ? "ilang" : verilog_frontend); } + } + + log_header(design, "Continuing TECHMAP pass.\n"); std::map> celltypeMap; for (auto &it : map->modules_) { @@ -1211,6 +1237,7 @@ struct FlattenPass : public Pass { } } + log_suppressed(); log("No more expansions possible.\n"); if (top_mod != NULL) -- cgit v1.2.3