From 2e7e1d2e721bdcaf331a1f9407cbeabf1a48bb85 Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Wed, 19 Feb 2025 16:51:21 -0800 Subject: [PATCH 1/8] Obs clean WIP --- passes/silimate/obs_clean.cc | 208 +++++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 passes/silimate/obs_clean.cc diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc new file mode 100644 index 000000000..c73c81953 --- /dev/null +++ b/passes/silimate/obs_clean.cc @@ -0,0 +1,208 @@ +#include "kernel/sigtools.h" +#include "kernel/yosys.h" +#include + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +// Signal cell driver(s), precompute a cell output signal to a cell map +void sigCellDrivers(RTLIL::Module *module, SigMap &sigmap, dict> &sig2CellsInFanout, + dict> &sig2CellsInFanin) +{ + for (auto cell : module->selected_cells()) { + for (auto &conn : cell->connections()) { + IdString portName = conn.first; + RTLIL::SigSpec actual = conn.second; + if (cell->output(portName)) { + sig2CellsInFanin[actual].insert(cell); + for (int i = 0; i < actual.size(); i++) { + SigSpec bit_sig = actual.extract(i, 1); + sig2CellsInFanin[sigmap(bit_sig)].insert(cell); + } + } else { + sig2CellsInFanout[sigmap(actual)].insert(cell); + for (int i = 0; i < actual.size(); i++) { + SigSpec bit_sig = actual.extract(i, 1); + if (!bit_sig.is_fully_const()) { + sig2CellsInFanout[sigmap(bit_sig)].insert(cell); + } + } + } + } + } +} + +// Assign statements fanin, fanout, traces the lhs2rhs and rhs2lhs sigspecs and precompute maps +void lhs2rhs_rhs2lhs(RTLIL::Module *module, SigMap &sigmap, dict> &rhsSig2LhsSig, + dict &lhsSig2rhsSig) +{ + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { + RTLIL::SigSpec lhs = it->first; + RTLIL::SigSpec rhs = it->second; + std::vector lhsBits; + for (int i = 0; i < lhs.size(); i++) { + SigSpec bit_sig = lhs.extract(i, 1); + lhsBits.push_back(bit_sig); + } + std::vector rhsBits; + for (int i = 0; i < rhs.size(); i++) { + SigSpec bit_sig = rhs.extract(i, 1); + if (bit_sig.is_fully_const()) { + continue; + } + rhsBits.push_back(bit_sig); + } + + for (uint32_t i = 0; i < lhsBits.size(); i++) { + if (i < rhsBits.size()) { + rhsSig2LhsSig[sigmap(rhsBits[i])].insert(sigmap(lhsBits[i])); + lhsSig2rhsSig[sigmap(lhsBits[i])] = sigmap(rhsBits[i]); + } + } + } +} + +void collectTransitiveFanin(RTLIL::SigSpec &sig, dict> &sig2CellsInFanin, + dict &lhsSig2RhsSig, std::set &visitedCells, + std::set &visitedSigSpec) +{ + if (sig.is_fully_const()) { + return; + } + if (visitedSigSpec.count(sig)) { + return; + } + visitedSigSpec.insert(sig); + + if (sig2CellsInFanin.count(sig)) { + for (Cell *cell : sig2CellsInFanin[sig]) { + if (visitedCells.count(cell)) { + continue; + } + visitedCells.insert(cell); + for (auto &conn : cell->connections()) { + IdString portName = conn.first; + RTLIL::SigSpec actual = conn.second; + if (cell->input(portName)) { + if (!actual.is_chunk()) { + for (auto it = actual.chunks().rbegin(); it != actual.chunks().rend(); ++it) { + RTLIL::SigSpec sub_actual = *it; + collectTransitiveFanin(sub_actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, + visitedSigSpec); + } + } else { + collectTransitiveFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + } + } + } + } + } + if (lhsSig2RhsSig.count(sig)) { + RTLIL::SigSpec rhs = lhsSig2RhsSig[sig]; + collectTransitiveFanin(rhs, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + } +} + +void observabilityClean(RTLIL::Module *module, dict> &sig2CellsInFanin, + dict &lhsSig2RhsSig) +{ + if (module->get_bool_attribute(ID::keep)) + return; + std::set visitedCells; + std::set visitedSigSpec; + + for (auto elt : sig2CellsInFanin) { + RTLIL::SigSpec po = elt.first; + RTLIL::Wire *w = po[0].wire; + if (w && !w->port_output) { + continue; + } + collectTransitiveFanin(po, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + } + + for (auto elt : lhsSig2RhsSig) { + RTLIL::SigSpec po = elt.first; + RTLIL::Wire *w = po[0].wire; + if (w && !w->port_output) { + continue; + } + collectTransitiveFanin(po, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + } + + pool newConnections; + for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { + RTLIL::SigSpec lhs = it->first; + if (visitedSigSpec.count(lhs)) { + newConnections.insert(*it); + continue; + } + } + + module->connections_.clear(); + for (auto conn : newConnections) { + module->connect(conn); + } + + pool wiresToRemove; + for (auto wire : module->wires()) { + RTLIL::SigSpec sig = wire; + if (visitedSigSpec.count(sig)) { + continue; + } + RTLIL::Wire *w = sig[0].wire; + if (w->port_id) { + continue; + } + if (w->get_bool_attribute(ID::keep)) + continue; + wiresToRemove.insert(w); + } + + module->remove(wiresToRemove); + + std::set cellsToRemove; + for (auto cell : module->cells()) { + if (visitedCells.count(cell)) { + continue; + } + if (cell->has_keep_attr()) + continue; + cellsToRemove.insert(cell); + } + + for (auto cell : cellsToRemove) { + module->remove(cell); + } +} + +struct ObsClean : public ScriptPass { + ObsClean() : ScriptPass("obs_clean", "Observability-based cleanup") {} + void script() override {} + + void execute(std::vector, RTLIL::Design *design) override + { + if (design == nullptr) { + log_error("No design object"); + return; + } + log("Running obs_clean pass\n"); + log_flush(); + for (auto module : design->selected_modules()) { + SigMap sigmap(module); + // Precompute cell output sigspec to cell map + dict> sig2CellsInFanin; + dict> sig2CellsInFanout; + sigCellDrivers(module, sigmap, sig2CellsInFanout, sig2CellsInFanin); + // Precompute lhs2rhs and rhs2lhs sigspec map + dict lhsSig2RhsSig; + dict> rhsSig2LhsSig; + lhs2rhs_rhs2lhs(module, sigmap, rhsSig2LhsSig, lhsSig2RhsSig); + // Actual cleanup + observabilityClean(module, sig2CellsInFanin, lhsSig2RhsSig); + } + log("End obs_clean pass\n"); + log_flush(); + } +} SplitNetlist; + +PRIVATE_NAMESPACE_END From 767b498603aa751e2de7b14e53dd6a97907d336d Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Thu, 20 Feb 2025 10:30:04 -0800 Subject: [PATCH 2/8] Fixes --- passes/silimate/Makefile.inc | 1 + passes/silimate/obs_clean.cc | 58 ++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index d265df524..70139e2b0 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -10,3 +10,4 @@ OBJS += passes/silimate/segv.o OBJS += passes/silimate/selectconst.o OBJS += passes/silimate/splitfanout.o OBJS += passes/silimate/splitnetlist.o +OBJS += passes/silimate/obs_clean.o \ No newline at end of file diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index c73c81953..c660552b6 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -47,9 +47,6 @@ void lhs2rhs_rhs2lhs(RTLIL::Module *module, SigMap &sigmap, dict rhsBits; for (int i = 0; i < rhs.size(); i++) { SigSpec bit_sig = rhs.extract(i, 1); - if (bit_sig.is_fully_const()) { - continue; - } rhsBits.push_back(bit_sig); } @@ -62,13 +59,11 @@ void lhs2rhs_rhs2lhs(RTLIL::Module *module, SigMap &sigmap, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig, std::set &visitedCells, std::set &visitedSigSpec) { - if (sig.is_fully_const()) { - return; - } if (visitedSigSpec.count(sig)) { return; } @@ -84,14 +79,10 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, dictinput(portName)) { - if (!actual.is_chunk()) { - for (auto it = actual.chunks().rbegin(); it != actual.chunks().rend(); ++it) { - RTLIL::SigSpec sub_actual = *it; - collectTransitiveFanin(sub_actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, - visitedSigSpec); - } - } else { - collectTransitiveFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + for (int i = 0; i < actual.size(); i++) { + SigSpec bit_sig = actual.extract(i, 1); + collectTransitiveFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } } @@ -100,9 +91,14 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig) { @@ -118,6 +114,10 @@ void observabilityClean(RTLIL::Module *module, dict newConnections; @@ -134,7 +138,14 @@ void observabilityClean(RTLIL::Module *module, dictfirst; if (visitedSigSpec.count(lhs)) { newConnections.insert(*it); - continue; + } else { + for (int i = 0; i < lhs.size(); i++) { + SigSpec bit_sig = lhs.extract(i, 1); + if (visitedSigSpec.count(bit_sig)) { + newConnections.insert(*it); + break; + } + } } } @@ -149,13 +160,22 @@ void observabilityClean(RTLIL::Module *module, dictport_id) { + bool bitVisited = false; + for (int i = 0; i < sig.size(); i++) { + SigSpec bit_sig = sig.extract(i, 1); + if (visitedSigSpec.count(bit_sig)) { + bitVisited = true; + break; + } + } + if (bitVisited) + continue; + if (wire->port_id) { continue; } - if (w->get_bool_attribute(ID::keep)) + if (wire->get_bool_attribute(ID::keep)) continue; - wiresToRemove.insert(w); + wiresToRemove.insert(wire); } module->remove(wiresToRemove); From 1abb8192df32e1b6aa39c85bf89a7e8cf3807f16 Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Thu, 20 Feb 2025 11:28:50 -0800 Subject: [PATCH 3/8] Skip modules with memories and processes --- passes/silimate/obs_clean.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index c660552b6..76f15bc9c 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -208,6 +208,10 @@ struct ObsClean : public ScriptPass { log("Running obs_clean pass\n"); log_flush(); for (auto module : design->selected_modules()) { + if (module->has_processes_warn()) + continue; + if (module->has_memories_warn()) + continue; SigMap sigmap(module); // Precompute cell output sigspec to cell map dict> sig2CellsInFanin; From adcbc7f8a61cd3da91284c798e2ef64d6e98a497 Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Thu, 20 Feb 2025 15:25:54 -0800 Subject: [PATCH 4/8] use sigmap --- passes/silimate/obs_clean.cc | 109 ++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 34 deletions(-) diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index 76f15bc9c..9bc3efea7 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -39,38 +39,56 @@ void lhs2rhs_rhs2lhs(RTLIL::Module *module, SigMap &sigmap, dictconnections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; RTLIL::SigSpec rhs = it->second; - std::vector lhsBits; - for (int i = 0; i < lhs.size(); i++) { - SigSpec bit_sig = lhs.extract(i, 1); - lhsBits.push_back(bit_sig); + if (lhs.is_chunk()) { + std::cout << "lhs ischunck: " << lhs.size() << std::endl; + } else { + std::cout << "lhs isnotchunck: " << lhs.size() << std::endl; } - std::vector rhsBits; - for (int i = 0; i < rhs.size(); i++) { - SigSpec bit_sig = rhs.extract(i, 1); - rhsBits.push_back(bit_sig); + if (rhs.is_chunk()) { + std::cout << "rhs ischunck: " << rhs.size() << std::endl; + } else { + std::cout << "rhs isnotchunck" << std::endl; } - - for (uint32_t i = 0; i < lhsBits.size(); i++) { - if (i < rhsBits.size()) { - rhsSig2LhsSig[sigmap(rhsBits[i])].insert(sigmap(lhsBits[i])); - lhsSig2rhsSig[sigmap(lhsBits[i])] = sigmap(rhsBits[i]); + if (!lhs.is_chunk()) { + std::vector lhsBits; + for (int i = 0; i < lhs.size(); i++) { + SigSpec bit_sig = lhs.extract(i, 1); + lhsBits.push_back(bit_sig); + std::cout << "li:" << i << std::endl; } + std::vector rhsBits; + for (int i = 0; i < rhs.size(); i++) { + SigSpec bit_sig = rhs.extract(i, 1); + rhsBits.push_back(bit_sig); + std::cout << "ri:" << i << std::endl; + } + + for (uint32_t i = 0; i < lhsBits.size(); i++) { + if (i < rhsBits.size()) { + std::cout << "lri:" << i << std::endl; + rhsSig2LhsSig[sigmap(rhsBits[i])].insert(sigmap(lhsBits[i])); + lhsSig2rhsSig[sigmap(lhsBits[i])] = sigmap(rhsBits[i]); + } + } + } else { + rhsSig2LhsSig[sigmap(rhs)].insert(sigmap(lhs)); + lhsSig2rhsSig[sigmap(lhs)] = sigmap(rhs); } } } // Collect transitive fanin of a sig -void collectTransitiveFanin(RTLIL::SigSpec &sig, dict> &sig2CellsInFanin, +void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap& sigmap, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig, std::set &visitedCells, std::set &visitedSigSpec) { - if (visitedSigSpec.count(sig)) { + if (visitedSigSpec.count(sigmap(sig))) { return; } - visitedSigSpec.insert(sig); + visitedSigSpec.insert(sigmap(sig)); - if (sig2CellsInFanin.count(sig)) { - for (Cell *cell : sig2CellsInFanin[sig]) { + if (sig2CellsInFanin.count(sigmap(sig))) { + for (Cell *cell : sig2CellsInFanin[sigmap(sig)]) { if (visitedCells.count(cell)) { continue; } @@ -79,27 +97,30 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, dictinput(portName)) { - collectTransitiveFanin(actual, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(actual, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < actual.size(); i++) { SigSpec bit_sig = actual.extract(i, 1); - collectTransitiveFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } } } } - if (lhsSig2RhsSig.count(sig)) { - RTLIL::SigSpec rhs = lhsSig2RhsSig[sig]; - collectTransitiveFanin(rhs, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + std::cout << "HERE\n"; + if (lhsSig2RhsSig.count(sigmap(sig))) { + std::cout << "THERE\n"; + RTLIL::SigSpec rhs = lhsSig2RhsSig[sigmap(sig)]; + collectTransitiveFanin(rhs, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < rhs.size(); i++) { + std::cout << "THERE: " << i << "\n"; SigSpec bit_sig = rhs.extract(i, 1); - collectTransitiveFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } } -// Only keep the cells and wires that are visited using the transitive fanin reached from output ports -void observabilityClean(RTLIL::Module *module, dict> &sig2CellsInFanin, +// Only keep the cells and wires that are visited using the transitive fanin reached from output ports or keep signals +void observabilityClean(RTLIL::Module *module, SigMap& sigmap, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig) { if (module->get_bool_attribute(ID::keep)) @@ -110,39 +131,59 @@ void observabilityClean(RTLIL::Module *module, dictport_output) { + if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) { continue; } - collectTransitiveFanin(po, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(po, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < po.size(); i++) { SigSpec bit_sig = po.extract(i, 1); - collectTransitiveFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } for (auto elt : lhsSig2RhsSig) { RTLIL::SigSpec po = elt.first; RTLIL::Wire *w = po[0].wire; - if (w && !w->port_output) { + if (w && (!w->port_output) && (!w->get_bool_attribute(ID::keep))) { continue; } - collectTransitiveFanin(po, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + if (po.is_chunk()) { + std::cout << "po ischunck" << std::endl; + } else { + std::cout << "po isnotchunck" << std::endl; + } + if (w) + std::cout << "Name: " << w->name.c_str() << std::endl; + else + std::cout << "No Name: " << std::endl; + std::cout << "PO size: " << po.size() << std::endl; + collectTransitiveFanin(po, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < po.size(); i++) { SigSpec bit_sig = po.extract(i, 1); - collectTransitiveFanin(bit_sig, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } pool newConnections; for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; + RTLIL::SigSpec sigmaplhs = sigmap(lhs); + if (!sigmaplhs.is_fully_const()) { + lhs = sigmaplhs; + } if (visitedSigSpec.count(lhs)) { newConnections.insert(*it); + std::cout << "New connection\n"; } else { for (int i = 0; i < lhs.size(); i++) { SigSpec bit_sig = lhs.extract(i, 1); + RTLIL::SigSpec sigmapbit_sig = sigmap(bit_sig); + //if (!sigmapbit_sig.is_fully_const()) { + bit_sig = sigmapbit_sig; + //} if (visitedSigSpec.count(bit_sig)) { newConnections.insert(*it); + std::cout << "New connection\n"; break; } } @@ -157,7 +198,7 @@ void observabilityClean(RTLIL::Module *module, dict wiresToRemove; for (auto wire : module->wires()) { RTLIL::SigSpec sig = wire; - if (visitedSigSpec.count(sig)) { + if (visitedSigSpec.count(sigmap(sig))) { continue; } bool bitVisited = false; @@ -222,7 +263,7 @@ struct ObsClean : public ScriptPass { dict> rhsSig2LhsSig; lhs2rhs_rhs2lhs(module, sigmap, rhsSig2LhsSig, lhsSig2RhsSig); // Actual cleanup - observabilityClean(module, sig2CellsInFanin, lhsSig2RhsSig); + observabilityClean(module, sigmap, sig2CellsInFanin, lhsSig2RhsSig); } log("End obs_clean pass\n"); log_flush(); From 04edcc0bafccde23464e11cb1d5eba8881fc98e5 Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Thu, 20 Feb 2025 16:49:02 -0800 Subject: [PATCH 5/8] Cleanup and sigmap fix --- passes/silimate/obs_clean.cc | 51 +++++++++--------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index 9bc3efea7..15ab8e205 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -39,46 +39,33 @@ void lhs2rhs_rhs2lhs(RTLIL::Module *module, SigMap &sigmap, dictconnections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; RTLIL::SigSpec rhs = it->second; - if (lhs.is_chunk()) { - std::cout << "lhs ischunck: " << lhs.size() << std::endl; - } else { - std::cout << "lhs isnotchunck: " << lhs.size() << std::endl; - } - if (rhs.is_chunk()) { - std::cout << "rhs ischunck: " << rhs.size() << std::endl; - } else { - std::cout << "rhs isnotchunck" << std::endl; - } if (!lhs.is_chunk()) { std::vector lhsBits; for (int i = 0; i < lhs.size(); i++) { SigSpec bit_sig = lhs.extract(i, 1); lhsBits.push_back(bit_sig); - std::cout << "li:" << i << std::endl; } std::vector rhsBits; for (int i = 0; i < rhs.size(); i++) { SigSpec bit_sig = rhs.extract(i, 1); rhsBits.push_back(bit_sig); - std::cout << "ri:" << i << std::endl; } for (uint32_t i = 0; i < lhsBits.size(); i++) { if (i < rhsBits.size()) { - std::cout << "lri:" << i << std::endl; rhsSig2LhsSig[sigmap(rhsBits[i])].insert(sigmap(lhsBits[i])); - lhsSig2rhsSig[sigmap(lhsBits[i])] = sigmap(rhsBits[i]); - } + lhsSig2rhsSig[lhsBits[i]] = sigmap(rhsBits[i]); + } } } else { rhsSig2LhsSig[sigmap(rhs)].insert(sigmap(lhs)); - lhsSig2rhsSig[sigmap(lhs)] = sigmap(rhs); + lhsSig2rhsSig[lhs] = sigmap(rhs); } } } // Collect transitive fanin of a sig -void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap& sigmap, dict> &sig2CellsInFanin, +void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap &sigmap, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig, std::set &visitedCells, std::set &visitedSigSpec) { @@ -100,19 +87,17 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap& sigmap, dict> &sig2CellsInFanin, +void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict> &sig2CellsInFanin, dict &lhsSig2RhsSig) { if (module->get_bool_attribute(ID::keep)) @@ -147,16 +132,6 @@ void observabilityClean(RTLIL::Module *module, SigMap& sigmap, dictport_output) && (!w->get_bool_attribute(ID::keep))) { continue; } - if (po.is_chunk()) { - std::cout << "po ischunck" << std::endl; - } else { - std::cout << "po isnotchunck" << std::endl; - } - if (w) - std::cout << "Name: " << w->name.c_str() << std::endl; - else - std::cout << "No Name: " << std::endl; - std::cout << "PO size: " << po.size() << std::endl; collectTransitiveFanin(po, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < po.size(); i++) { SigSpec bit_sig = po.extract(i, 1); @@ -164,7 +139,7 @@ void observabilityClean(RTLIL::Module *module, SigMap& sigmap, dict newConnections; + std::vector newConnections; for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; RTLIL::SigSpec sigmaplhs = sigmap(lhs); @@ -172,18 +147,16 @@ void observabilityClean(RTLIL::Module *module, SigMap& sigmap, dict Date: Mon, 24 Feb 2025 10:19:54 -0800 Subject: [PATCH 6/8] Disable wire removal --- passes/silimate/obs_clean.cc | 99 ++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 39 deletions(-) diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index 15ab8e205..c3e5c33cc 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -14,7 +14,7 @@ void sigCellDrivers(RTLIL::Module *module, SigMap &sigmap, dictoutput(portName)) { - sig2CellsInFanin[actual].insert(cell); + sig2CellsInFanin[sigmap(actual)].insert(cell); for (int i = 0; i < actual.size(); i++) { SigSpec bit_sig = actual.extract(i, 1); sig2CellsInFanin[sigmap(bit_sig)].insert(cell); @@ -106,7 +106,7 @@ void collectTransitiveFanin(RTLIL::SigSpec &sig, SigMap &sigmap, dict> &sig2CellsInFanin, - dict &lhsSig2RhsSig) + dict &lhsSig2RhsSig, bool unused_wires) { if (module->get_bool_attribute(ID::keep)) return; @@ -119,9 +119,11 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dictport_output) && (!w->get_bool_attribute(ID::keep))) { continue; } - collectTransitiveFanin(po, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + RTLIL::SigSpec spo = sigmap(po); + collectTransitiveFanin(spo, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < po.size(); i++) { SigSpec bit_sig = po.extract(i, 1); + bit_sig = sigmap(bit_sig); collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } @@ -132,9 +134,11 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dictport_output) && (!w->get_bool_attribute(ID::keep))) { continue; } - collectTransitiveFanin(po, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); + RTLIL::SigSpec spo = sigmap(po); + collectTransitiveFanin(spo, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); for (int i = 0; i < po.size(); i++) { SigSpec bit_sig = po.extract(i, 1); + bit_sig = sigmap(bit_sig); collectTransitiveFanin(bit_sig, sigmap, sig2CellsInFanin, lhsSig2RhsSig, visitedCells, visitedSigSpec); } } @@ -142,20 +146,12 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict newConnections; for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; - RTLIL::SigSpec sigmaplhs = sigmap(lhs); - if (!sigmaplhs.is_fully_const()) { - lhs = sigmaplhs; - } - if (visitedSigSpec.count(lhs)) { + if (visitedSigSpec.count(sigmap(lhs))) { newConnections.push_back(*it); } else { for (int i = 0; i < lhs.size(); i++) { SigSpec bit_sig = lhs.extract(i, 1); - RTLIL::SigSpec sigmapbit_sig = sigmap(bit_sig); - // if (!sigmapbit_sig.is_fully_const()) { - bit_sig = sigmapbit_sig; - //} - if (visitedSigSpec.count(bit_sig)) { + if (visitedSigSpec.count(sigmap(bit_sig))) { newConnections.push_back(*it); break; } @@ -168,31 +164,33 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dictconnect(conn); } - pool wiresToRemove; - for (auto wire : module->wires()) { - RTLIL::SigSpec sig = wire; - if (visitedSigSpec.count(sigmap(sig))) { - continue; - } - bool bitVisited = false; - for (int i = 0; i < sig.size(); i++) { - SigSpec bit_sig = sig.extract(i, 1); - if (visitedSigSpec.count(bit_sig)) { - bitVisited = true; - break; + if (unused_wires) { + pool wiresToRemove; + for (auto wire : module->wires()) { + RTLIL::SigSpec sig = wire; + if (visitedSigSpec.count(sigmap(sig))) { + continue; } + bool bitVisited = false; + for (int i = 0; i < sig.size(); i++) { + SigSpec bit_sig = sig.extract(i, 1); + if (visitedSigSpec.count(bit_sig)) { + bitVisited = true; + break; + } + } + if (bitVisited) + continue; + if (wire->port_id) { + continue; + } + if (wire->get_bool_attribute(ID::keep)) + continue; + wiresToRemove.insert(wire); } - if (bitVisited) - continue; - if (wire->port_id) { - continue; - } - if (wire->get_bool_attribute(ID::keep)) - continue; - wiresToRemove.insert(wire); - } - module->remove(wiresToRemove); + module->remove(wiresToRemove); + } std::set cellsToRemove; for (auto cell : module->cells()) { @@ -212,9 +210,31 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict, RTLIL::Design *design) override + void help() override { + log("\n"); + log(" obs_clean [options] [selection]\n"); + log("\n"); + log("This pass performs an obversability-based logic removal.\n"); + log("\n"); + log(" -wires\n"); + log(" Also removes dangling wires. This option prevents formal verifciation at this time.\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + bool unused_wires = false; + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + if (args[argidx] == "-wires") { + unused_wires = true; + continue; + } + break; + } + extra_args(args, argidx, design); + if (design == nullptr) { log_error("No design object"); return; @@ -226,6 +246,7 @@ struct ObsClean : public ScriptPass { continue; if (module->has_memories_warn()) continue; + SigMap sigmap(module); // Precompute cell output sigspec to cell map dict> sig2CellsInFanin; @@ -236,7 +257,7 @@ struct ObsClean : public ScriptPass { dict> rhsSig2LhsSig; lhs2rhs_rhs2lhs(module, sigmap, rhsSig2LhsSig, lhsSig2RhsSig); // Actual cleanup - observabilityClean(module, sigmap, sig2CellsInFanin, lhsSig2RhsSig); + observabilityClean(module, sigmap, sig2CellsInFanin, lhsSig2RhsSig, unused_wires); } log("End obs_clean pass\n"); log_flush(); From b3dc7efe79c41749ede4f562731948f11af0bbad Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Mon, 24 Feb 2025 11:22:29 -0800 Subject: [PATCH 7/8] Comments --- passes/silimate/obs_clean.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/passes/silimate/obs_clean.cc b/passes/silimate/obs_clean.cc index c3e5c33cc..32d469401 100644 --- a/passes/silimate/obs_clean.cc +++ b/passes/silimate/obs_clean.cc @@ -113,6 +113,7 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict visitedCells; std::set visitedSigSpec; + // Collect observable logic (connected to one output) for (auto elt : sig2CellsInFanin) { RTLIL::SigSpec po = elt.first; RTLIL::Wire *w = po[0].wire; @@ -143,6 +144,7 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict newConnections; for (auto it = module->connections().begin(); it != module->connections().end(); ++it) { RTLIL::SigSpec lhs = it->first; @@ -165,6 +167,8 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dict wiresToRemove; for (auto wire : module->wires()) { RTLIL::SigSpec sig = wire; @@ -192,6 +196,7 @@ void observabilityClean(RTLIL::Module *module, SigMap &sigmap, dictremove(wiresToRemove); } + // Remove unused cells std::set cellsToRemove; for (auto cell : module->cells()) { if (visitedCells.count(cell)) { @@ -242,6 +247,7 @@ struct ObsClean : public ScriptPass { log("Running obs_clean pass\n"); log_flush(); for (auto module : design->selected_modules()) { + // We cannot safely perform this analysis when processes or memories are present if (module->has_processes_warn()) continue; if (module->has_memories_warn()) From 18393156dbbf2a1673b8f4955e54feb54c734462 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Mon, 24 Feb 2025 16:18:05 -0800 Subject: [PATCH 8/8] Update Makefile.inc --- passes/silimate/Makefile.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index 70139e2b0..c936b0f54 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -5,9 +5,9 @@ OBJS += passes/silimate/annotate_logic_depth.o OBJS += passes/silimate/breaksop.o OBJS += passes/silimate/bus_rebuild.o OBJS += passes/silimate/longloop_select.o +OBJS += passes/silimate/obs_clean.o OBJS += passes/silimate/opt_balance_tree.o OBJS += passes/silimate/segv.o OBJS += passes/silimate/selectconst.o OBJS += passes/silimate/splitfanout.o OBJS += passes/silimate/splitnetlist.o -OBJS += passes/silimate/obs_clean.o \ No newline at end of file