From b4787c787fae2bac97d3e23ce91c430e6971a2cc Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Fri, 31 Jan 2025 10:17:34 -0800 Subject: [PATCH 1/3] Calculate cell fanout (post-synthesis) --- Makefile | 1 + passes/cmds/cell_fanout.cc | 160 +++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 passes/cmds/cell_fanout.cc diff --git a/Makefile b/Makefile index 8e14538b9b9..5dad366e951 100644 --- a/Makefile +++ b/Makefile @@ -724,6 +724,7 @@ OBJS += passes/cmds/clean_zerowidth.o OBJS += passes/cmds/selectconst.o OBJS += passes/cmds/setattr.o OBJS += passes/cmds/splitcells.o +OBJS += passes/cmds/cell_fanout.o OBJS += passes/cmds/splitfanout.o OBJS += passes/cmds/splitnets.o OBJS += passes/cmds/tee.o diff --git a/passes/cmds/cell_fanout.cc b/passes/cmds/cell_fanout.cc new file mode 100644 index 00000000000..d03c6022515 --- /dev/null +++ b/passes/cmds/cell_fanout.cc @@ -0,0 +1,160 @@ +#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::Design *design, dict> &sig2CellsInFanout, + dict> &sig2CellsInFanin) +{ + if (!design->top_module()) + return; + if (design->top_module()->cells().size() == 0) + return; + for (auto module : design->selected_modules()) { + SigMap sigmap(module); + 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::Design *design, dict> &rhsSig2LhsSig, + dict &lhsSig2rhsSig) +{ + for (auto module : design->selected_modules()) { + SigMap sigmap(module); + 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]); + } + } + } + } +} + +struct AnnotateCellFanout : public ScriptPass { + AnnotateCellFanout() : ScriptPass("annotate_cell_fanout", "Annotate the cell fanout on the cell") {} + void script() override {} + + void execute(std::vector, RTLIL::Design *design) override + { + if (design == nullptr) { + log_error("No design object"); + return; + } + if (!design->top_module()) { + log_error("No top module"); + return; + } + log("Running annotate_cell_fanout pass\n"); + log_flush(); + // Precompute cell output sigspec to cell map + dict> sig2CellsInFanin; + dict> sig2CellsInFanout; + sigCellDrivers(design, sig2CellsInFanout, sig2CellsInFanin); + // Precompute lhs2rhs and rhs2lhs sigspec map + dict lhsSig2RhsSig; + dict> rhsSig2LhsSig; + lhs2rhs_rhs2lhs(design, rhsSig2LhsSig, lhsSig2RhsSig); + + // Accumulate fanout from cell connections + dict sigFanout; + for (auto itrSig : sig2CellsInFanout) { + SigSpec sigspec = itrSig.first; + std::set &cells = itrSig.second; + sigFanout[sigspec] = cells.size(); + } + + // Accumulate fanout from assign stmts connections + for (auto itrSig : rhsSig2LhsSig) { + SigSpec sigspec = itrSig.first; + std::set &fanout = itrSig.second; + if (sigFanout.count(sigspec)) { + sigFanout[sigspec] += fanout.size(); + } else { + sigFanout[sigspec] = fanout.size(); + } + } + + // Collect max fanout from all the output bits of a cell + dict cellFanout; + for (auto itrSig : sigFanout) { + SigSpec sigspec = itrSig.first; + int fanout = itrSig.second; + std::set &cells = sig2CellsInFanin[sigspec]; + for (Cell *cell : cells) { + if (cellFanout.count(cell)) { + cellFanout[cell] = std::max(fanout, cellFanout[cell]); + } else { + cellFanout[cell] = fanout; + } + } + } + + // Find cells with no fanout info (connected to output ports, or not connected) + std::set noFanoutInfo; + for (auto module : design->selected_modules()) { + for (auto cell : module->selected_cells()) { + if (!cellFanout.count(cell)) { + noFanoutInfo.insert(cell); + } + } + } + // Set those cells to fanout 1 + for (auto cell : noFanoutInfo) { + cellFanout[cell] = 1; + } + + // Add attribute with fanout info to every cell + for (auto itrCell : cellFanout) { + Cell *cell = itrCell.first; + int fanout = itrCell.second; + cell->set_string_attribute("$FANOUT", std::to_string(fanout)); + } + + log("End annotate_cell_fanout pass\n"); + log_flush(); + } +} SplitNetlist; + +PRIVATE_NAMESPACE_END From 4861aefcd8bcbe042914d1601bf0e06d56a1a3ae Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Fri, 31 Jan 2025 13:28:48 -0800 Subject: [PATCH 2/3] Fix test --- passes/cmds/cell_fanout.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/passes/cmds/cell_fanout.cc b/passes/cmds/cell_fanout.cc index d03c6022515..29136d75dff 100644 --- a/passes/cmds/cell_fanout.cc +++ b/passes/cmds/cell_fanout.cc @@ -82,10 +82,6 @@ struct AnnotateCellFanout : public ScriptPass { log_error("No design object"); return; } - if (!design->top_module()) { - log_error("No top module"); - return; - } log("Running annotate_cell_fanout pass\n"); log_flush(); // Precompute cell output sigspec to cell map From 8213dd1dcf4984a107492afc0b0d5a487a618511 Mon Sep 17 00:00:00 2001 From: Alain Dargelas Date: Fri, 31 Jan 2025 15:29:33 -0800 Subject: [PATCH 3/3] Code review --- Makefile | 2 +- passes/cmds/{cell_fanout.cc => annotate_cell_fanout.cc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename passes/cmds/{cell_fanout.cc => annotate_cell_fanout.cc} (100%) diff --git a/Makefile b/Makefile index 5dad366e951..62f7f339eb1 100644 --- a/Makefile +++ b/Makefile @@ -724,7 +724,7 @@ OBJS += passes/cmds/clean_zerowidth.o OBJS += passes/cmds/selectconst.o OBJS += passes/cmds/setattr.o OBJS += passes/cmds/splitcells.o -OBJS += passes/cmds/cell_fanout.o +OBJS += passes/cmds/annotate_cell_fanout.o OBJS += passes/cmds/splitfanout.o OBJS += passes/cmds/splitnets.o OBJS += passes/cmds/tee.o diff --git a/passes/cmds/cell_fanout.cc b/passes/cmds/annotate_cell_fanout.cc similarity index 100% rename from passes/cmds/cell_fanout.cc rename to passes/cmds/annotate_cell_fanout.cc