From 0379a8b28701d1d7fb371b96c9b0f8e895af099f Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Thu, 14 Nov 2024 15:50:40 -0800 Subject: [PATCH] Prevent crashes and diagnostics --- passes/cmds/activity.cc | 6 +- passes/cmds/reconstructbusses.cc | 150 ++++++++++++++++++------------- passes/cmds/splitnetlist.cc | 24 +++++ 3 files changed, 114 insertions(+), 66 deletions(-) diff --git a/passes/cmds/activity.cc b/passes/cmds/activity.cc index d17e7edad..fdc2495a5 100644 --- a/passes/cmds/activity.cc +++ b/passes/cmds/activity.cc @@ -84,7 +84,7 @@ struct ActivityProp { DutyMap.emplace(bit, duties[i]); nbBitsWithActivity++; } else { - log_warning("Zeroing out activity for module: %s, wire: %s, wire_size: %d, activ_size: %ld", + log_warning("Zeroing out activity for module: %s, wire: %s, wire_size: %d, activ_size: %ld\n", module->name.c_str(), wire->name.c_str(), GetSize(sig), activities.size()); ActivityMap.emplace(bit, "0.0"); DutyMap.emplace(bit, "0.0"); @@ -107,7 +107,7 @@ struct ActivityProp { } else { RTLIL::SigSpec sigspec(bit); if (!sigspec.is_fully_const()) { - log_warning("No activity found for : %s/%s/%s", module->name.c_str(), cell->name.c_str(), port_name.c_str()); + log_warning("No activity found for : %s/%s/%s\n", module->name.c_str(), cell->name.c_str(), port_name.c_str()); } // constants have no activity cell_ports_activity += port_name + "=" + "0.0 "; @@ -120,7 +120,7 @@ struct ActivityProp { } else { RTLIL::SigSpec sigspec(bit); if (!sigspec.is_fully_const()) { - log_warning("No dutycycle found for : %s/%s/%s", module->name.c_str(), cell->name.c_str(), port_name.c_str()); + log_warning("No dutycycle found for : %s/%s/%s\n", module->name.c_str(), cell->name.c_str(), port_name.c_str()); } // constant 1 has duty cycle 1, constant 0 has duty cycle 0 cell_ports_duty += port_name + "=" + (sigspec.as_bool() ? "1.0" : "0.0") + " "; diff --git a/passes/cmds/reconstructbusses.cc b/passes/cmds/reconstructbusses.cc index 60bb49775..bffd7fbbe 100644 --- a/passes/cmds/reconstructbusses.cc +++ b/passes/cmds/reconstructbusses.cc @@ -6,9 +6,14 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN struct ReconstructBusses : public ScriptPass { - ReconstructBusses() : ScriptPass("reconstructbusses", "Reconstruct busses from wires with the same prefix following the convention: __") {} + ReconstructBusses() + : ScriptPass("reconstructbusses", "Reconstruct busses from wires with the same prefix following the convention: __") + { + } void script() override {} + bool is_digits(const std::string &str) { return std::all_of(str.begin(), str.end(), ::isdigit); } + void execute(std::vector, RTLIL::Design *design) override { if (design == nullptr) { @@ -17,6 +22,8 @@ struct ReconstructBusses : public ScriptPass { } log("Running reconstructbusses pass\n"); log_flush(); + log("Creating bus groups\n"); + log_flush(); for (auto module : design->modules()) { // Collect all wires with a common prefix dict> wire_groups; @@ -32,7 +39,19 @@ struct ReconstructBusses : public ScriptPass { // Result: "add_Y" std::string::iterator end = prefix.end() - 1; if ((*end) == '_') { - // Last character is an _, it is a bit blasted index + // Last character is an _, check that it is a bit blasted index: + bool valid_index = false; + std::string ch_name = prefix.substr(0, prefix.size() - 1); + if (ch_name.find("_") != std::string::npos) { + std::string ch_index_str = ch_name.substr(ch_name.find_last_of('_') + 1); + if ((!ch_index_str.empty() && is_digits(ch_index_str))) { + valid_index = true; + } + } + if (!valid_index) { + continue; + } + end--; for (; end != prefix.begin(); end--) { if ((*end) != '_') { @@ -43,12 +62,17 @@ struct ReconstructBusses : public ScriptPass { break; } } - + if (end == prefix.begin()) + // Last _ didn't mean there was another _ + continue; std::string no_bitblast_prefix; std::copy(prefix.begin(), end, std::back_inserter(no_bitblast_prefix)); wire_groups[no_bitblast_prefix].push_back(wire); } } + log("Found %ld groups\n", wire_groups.size()); + log("Creating busses\n"); + log_flush(); std::map wirenames_to_remove; pool wires_to_remove; // Reconstruct vectors @@ -56,25 +80,6 @@ struct ReconstructBusses : public ScriptPass { std::string prefix = it.first; std::vector &wires = it.second; - // Sort wires by their bit index (assuming the suffix is __) - std::sort(wires.begin(), wires.end(), [](RTLIL::Wire *a, RTLIL::Wire *b) { - std::string a_name = a->name.str(); - std::string b_name = b->name.str(); - std::string::iterator a_end = a_name.end() - 1; - std::string::iterator b_end = b_name.end() - 1; - if (((*a_end) == '_') && ((*b_end) == '_')) { - a_name = a_name.substr(0, a_name.size() - 1); - b_name = b_name.substr(0, b_name.size() - 1); - std::string a_index_str = a_name.substr(a_name.find_last_of('_') + 1); - std::string b_index_str = b_name.substr(b_name.find_last_of('_') + 1); - int a_index = std::stoi(a_index_str); - int b_index = std::stoi(b_index_str); - return a_index > b_index; // Descending order for correct concatenation - } else { - return false; - } - }); - // Create a new vector wire int width = wires.size(); RTLIL::Wire *new_wire = module->addWire(prefix, width); @@ -93,7 +98,8 @@ struct ReconstructBusses : public ScriptPass { wires_to_remove.insert(wire); } } - + log("Reconnecting cells\n"); + log_flush(); // Reconnect cells for (auto cell : module->cells()) { for (auto &conn : cell->connections_) { @@ -104,20 +110,26 @@ struct ReconstructBusses : public ScriptPass { // std::cout << "Conn:" << chunk.wire->name.c_str() << std::endl; // Find the connections that match the wire group prefix std::string lhs_name = chunk.wire->name.c_str(); - std::map::iterator itr = wirenames_to_remove.find(lhs_name); + std::map::iterator itr = wirenames_to_remove.find(lhs_name); if (itr != wirenames_to_remove.end()) { std::string ch_name = chunk.wire->name.c_str(); - std::string::iterator ch_end = ch_name.end() - 1; - if ((*ch_end) == '_') { - ch_name = ch_name.substr(0, ch_name.size() - 1); - std::string ch_index_str = ch_name.substr(ch_name.find_last_of('_') + 1); - // std::cout << "ch_name: " << ch_name << std::endl; - if (!ch_index_str.empty()) { - // Create a new connection sigspec that matches the previous bit index - int ch_index = std::stoi(ch_index_str); - RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1); - new_sig.append(bit); - modified = true; + if (!ch_name.empty()) { + std::string::iterator ch_end = ch_name.end() - 1; + if ((*ch_end) == '_') { + ch_name = ch_name.substr(0, ch_name.size() - 1); + if (ch_name.find("_") != std::string::npos) { + std::string ch_index_str = + ch_name.substr(ch_name.find_last_of('_') + 1); + // std::cout << "ch_name: " << ch_name << std::endl; + if ((!ch_index_str.empty() && is_digits(ch_index_str))) { + // Create a new connection sigspec that matches the previous + // bit index + int ch_index = std::stoi(ch_index_str); + RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1); + new_sig.append(bit); + modified = true; + } + } } } } else { @@ -130,9 +142,9 @@ struct ReconstructBusses : public ScriptPass { conn.second = new_sig; } } - + log("Reconnecting top connections\n"); + log_flush(); // Reconnect top connections before removing the old wires - // std::cout << "Wire to remove: " << wire_name << std::endl; for (auto &conn : module->connections()) { RTLIL::SigSpec lhs = conn.first; RTLIL::SigSpec rhs = conn.second; @@ -146,31 +158,38 @@ struct ReconstructBusses : public ScriptPass { while (lit != lhs.chunks().rend()) { RTLIL::SigChunk sub_lhs = *lit; std::string conn_lhs = sub_lhs.wire->name.c_str(); - std::string conn_rhs = sub_rhs.wire->name.c_str(); - // The connection LHS matches a wire that is replaced by a bus - // std::cout << "Conn: " << conn_lhs << " to: " << conn_rhs << std::endl; - std::map::iterator itr = wirenames_to_remove.find(conn_lhs); - if (itr != wirenames_to_remove.end()) { - std::string::iterator conn_lhs_end = conn_lhs.end() - 1; - if ((*conn_lhs_end) == '_') { - conn_lhs = conn_lhs.substr(0, conn_lhs.size() - 1); - std::string ch_index_str = conn_lhs.substr(conn_lhs.find_last_of('_') + 1); - if (!ch_index_str.empty()) { - // std::cout << "Conn LHS: " << conn_lhs << std::endl; - // std::string conn_rhs = sub_rhs.wire->name.c_str(); - // std::cout << "Conn RHS: " << conn_rhs << std::endl; - int ch_index = std::stoi(ch_index_str); - // Create the LHS sigspec of the desired bit - RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1); - if (sub_rhs.size() > 1) { - // If RHS has width > 1, replace with the bitblasted RHS corresponding to the - // connected bit - RTLIL::SigSpec rhs_bit = RTLIL::SigSpec(sub_rhs.wire, ch_index, 1); - // And connect it - module->connect(bit, rhs_bit); - } else { - // Else, directly connect - module->connect(bit, sub_rhs); + if (!conn_lhs.empty()) { + // std::cout << "Conn LHS: " << conn_lhs << std::endl; + // std::string conn_rhs = sub_rhs.wire->name.c_str(); + // std::cout << "Conn RHS: " << conn_rhs << std::endl; + + std::map::iterator itr = wirenames_to_remove.find(conn_lhs); + if (itr != wirenames_to_remove.end()) { + std::string::iterator conn_lhs_end = conn_lhs.end() - 1; + if ((*conn_lhs_end) == '_') { + conn_lhs = conn_lhs.substr(0, conn_lhs.size() - 1); + if (conn_lhs.find("_") != std::string::npos) { + std::string ch_index_str = conn_lhs.substr(conn_lhs.find_last_of('_') + 1); + if (!ch_index_str.empty() && is_digits(ch_index_str)) { + int ch_index = std::stoi(ch_index_str); + // Create the LHS sigspec of the desired bit + RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, ch_index, 1); + if (sub_rhs.size() > 1) { + // If RHS has width > 1, replace with the bitblasted RHS + // corresponding to the connected bit + RTLIL::SigSpec rhs_bit = + RTLIL::SigSpec(sub_rhs.wire, ch_index, 1); + // And connect it + module->connect(bit, rhs_bit); + } else { + // Else, directly connect + module->connect(bit, sub_rhs); + } + } else { + // Else, directly connect + RTLIL::SigSpec bit = RTLIL::SigSpec(itr->second, 0, 1); + module->connect(bit, sub_rhs); + } } } } @@ -180,12 +199,17 @@ struct ReconstructBusses : public ScriptPass { rit++; } } - // Remove old wires + log("Removing old wires\n"); + log_flush(); module->remove(wires_to_remove); // Update module port list + log("Re-creating ports\n"); + log_flush(); module->fixup_ports(); } + log("End reconstructbusses pass\n"); + log_flush(); } } ReconstructBusses; diff --git a/passes/cmds/splitnetlist.cc b/passes/cmds/splitnetlist.cc index cd51ae250..12d81b74f 100644 --- a/passes/cmds/splitnetlist.cc +++ b/passes/cmds/splitnetlist.cc @@ -51,6 +51,10 @@ void recordTransFanin(RTLIL::SigSpec &sig, dict // Signal cell driver(s), precompute a cell output signal to a cell map void sigCellDrivers(RTLIL::Design *design, dict *> &sig2CellsInFanin) { + if (!design->top_module()) + return; + if (design->top_module()->cells().size() == 0) + return; for (auto cell : design->top_module()->cells()) { for (auto &conn : cell->connections()) { IdString portName = conn.first; @@ -95,6 +99,10 @@ void sigCellDrivers(RTLIL::Design *design, dict // Assign statements fanin, traces the lhs to rhs sigspecs and precompute a map void lhs2rhs(RTLIL::Design *design, dict &lhsSig2rhsSig) { + if (!design->top_module()) + return; + if (design->top_module()->connections().size() == 0) + return; for (auto it = design->top_module()->connections().begin(); it != design->top_module()->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; RTLIL::SigSpec rhs = it->second; @@ -145,9 +153,15 @@ struct SplitNetlist : public ScriptPass { log_error("No design object"); return; } + log("Running splitnetlist pass\n"); + log_flush(); + log("Mapping signals to cells\n"); + log_flush(); // Precompute cell output sigspec to cell map dict *> sig2CellsInFanin; sigCellDrivers(design, sig2CellsInFanin); + log("Mapping assignments\n"); + log_flush(); // Precompute lhs to rhs sigspec map dict lhsSig2RhsSig; lhs2rhs(design, lhsSig2RhsSig); @@ -160,6 +174,12 @@ struct SplitNetlist : public ScriptPass { typedef std::map CellName_ObjectMap; CellName_ObjectMap cellName_ObjectMap; // Record logic cone by output sharing the same prefix + if (!design->top_module()) + return; + if (design->top_module()->wires().size() == 0) + return; + log("Cells grouping\n"); + log_flush(); for (auto wire : design->top_module()->wires()) { if (!wire->port_output) continue; @@ -219,6 +239,8 @@ struct SplitNetlist : public ScriptPass { } } // Create submod attributes for the submod command + log("Creating submods\n"); + log_flush(); for (CellName_ObjectMap::iterator itr = cellName_ObjectMap.begin(); itr != cellName_ObjectMap.end(); itr++) { // std::cout << "Cluster name: " << itr->first << std::endl; CellsAndSigs &components = itr->second; @@ -233,6 +255,8 @@ struct SplitNetlist : public ScriptPass { } // Execute the submod command Pass::call(design, "submod -copy"); + log("End splitnetlist pass\n"); + log_flush(); } } SplitNetlist;