3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-06-06 06:03:23 +00:00

call splitnets for the whole design

This commit is contained in:
Alain Dargelas 2025-03-06 16:21:11 -08:00
parent d4e4ece9fe
commit 81ab3b5fed

View file

@ -522,50 +522,48 @@ void calculateFanout(RTLIL::Module *module, SigMap &sigmap, dict<RTLIL::SigSpec,
} }
// Bulk call to splitnets, filters bad requests and separates out types (Wires, ports) for proper processing // Bulk call to splitnets, filters bad requests and separates out types (Wires, ports) for proper processing
void splitNets(Design *design, std::set<std::string> &netsToSplitS, std::vector<RTLIL::SigSpec> &sigsToSplit, bool formalFriendly, bool debug, void splitNets(Design *design, std::map<Module *, std::vector<RTLIL::SigSpec>> &sigsToSplit, bool formalFriendly, bool inputPort = false)
bool inputPort = false)
{ {
std::string wires; std::string wires;
std::string inputs; std::string inputs;
std::string outputs; std::string outputs;
for (RTLIL::SigSpec sigToSplit : sigsToSplit) { // Memorize selection
Wire *parentWire = getParentWire(sigToSplit); Pass::call(design, "select -set presplitnets %");
if (!parentWire) // Clear selection
continue; Pass::call(design, "select -none");
std::string parent = parentWire->name.c_str(); std::set<Wire *> selected;
if (parent == "") { for (std::map<Module *, std::vector<RTLIL::SigSpec>>::iterator itr = sigsToSplit.begin(); itr != sigsToSplit.end(); itr++) {
continue; Module *module = itr->first;
} for (RTLIL::SigSpec sigToSplit : itr->second) {
if (parentWire->width == 1) Wire *parentWire = getParentWire(sigToSplit);
continue; if (!parentWire)
parent = substringuntil(parent, '['); continue;
if (netsToSplitS.find(parent) == netsToSplitS.end()) { if (selected.find(parentWire) != selected.end())
netsToSplitS.insert(parent); continue;
if (debug) { selected.insert(parentWire);
std::cout << "splitnets: " << parent << std::endl;
}
if ((!parentWire->port_input) && (!parentWire->port_output)) if ((!parentWire->port_input) && (!parentWire->port_output))
wires += " w:" + parent; design->select(module, parentWire);
if (!formalFriendly) { if (!formalFriendly) {
// Formal verification does not like ports to be split. // Formal verification does not like ports to be split.
// This option will prevent some buffering to happen on high fanout input/output ports, // This option will prevent some buffering to happen on high fanout input/output ports,
// but it will make formal happy. // but it will make formal happy.
if (inputPort) { if (inputPort) {
if (parentWire->port_input) if (parentWire->port_input)
inputs += " i:" + parent; design->select(module, parentWire);
} else { } else {
if (parentWire->port_output) if (parentWire->port_output)
outputs += " o:" + parent; design->select(module, parentWire);
} }
} }
} }
} }
if (!wires.empty()) { if (formalFriendly) {
Pass::call(design, "splitnets" + wires); // Wire Pass::call(design, "splitnets");
} } else {
if (!inputs.empty() || !outputs.empty()) { Pass::call(design, "splitnets -ports");
Pass::call(design, "splitnets -ports_only" + inputs + outputs); // Input port
} }
// Restore selection
Pass::call(design, "select @presplitnets");
} }
struct AnnotateCellFanout : public ScriptPass { struct AnnotateCellFanout : public ScriptPass {
@ -640,52 +638,68 @@ struct AnnotateCellFanout : public ScriptPass {
log_error("Fanout cannot be limited to less than 2\n"); log_error("Fanout cannot be limited to less than 2\n");
return; return;
} }
// Collect all the high fanout signals to split
std::map<Module *, std::vector<SigSpec>> signalsToSplit;
std::map<Module *, std::vector<SigSpec>> portsToSplit;
// Split all the high fanout nets for the whole design
for (auto module : design->selected_modules()) { for (auto module : design->selected_modules()) {
bool fixedFanout = false; // Calculate fanout
std::map<Cell *, Wire *> insertedBuffers; SigMap sigmap(module);
{ dict<Cell *, int> cellFanout;
// Calculate fanout dict<SigSpec, int> sigFanout;
SigMap sigmap(module); dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanout;
dict<Cell *, int> cellFanout; calculateFanout(module, sigmap, sig2CellsInFanout, cellFanout, sigFanout);
dict<SigSpec, int> sigFanout;
dict<RTLIL::SigSpec, std::set<Cell *>> sig2CellsInFanout;
calculateFanout(module, sigmap, sig2CellsInFanout, cellFanout, sigFanout);
std::set<std::string> netsToSplitS; // Split cells output nets with high fanout
// Split cells output nets with high fanout std::vector<RTLIL::SigSpec> cellOutputsToSplit;
std::vector<RTLIL::SigSpec> cellOutputsToSplit; for (auto itrCell : cellFanout) {
for (auto itrCell : cellFanout) { Cell *cell = itrCell.first;
Cell *cell = itrCell.first; int fanout = itrCell.second;
int fanout = itrCell.second; if (limit > 0 && (fanout > limit)) {
if (limit > 0 && (fanout > limit)) { int nbOutputs = 0;
for (auto &conn : cell->connections()) { for (auto &conn : cell->connections()) {
IdString portName = conn.first; IdString portName = conn.first;
RTLIL::SigSpec actual = conn.second; if (cell->output(portName)) {
if (cell->output(portName)) { nbOutputs++;
RTLIL::SigSpec cellOutSig = sigmap(actual);
cellOutputsToSplit.push_back(cellOutSig);
}
} }
} }
} for (auto &conn : cell->connections()) {
splitNets(design, netsToSplitS, cellOutputsToSplit, formalFriendly, debug); IdString portName = conn.first;
RTLIL::SigSpec actual = conn.second;
if (buffer_inputs) { if (cell->output(portName)) {
// Split module input nets with high fanout RTLIL::SigSpec cellOutSig = sigmap(actual);
std::vector<RTLIL::SigSpec> wiresToSplit; cellOutputsToSplit.push_back(cellOutSig);
for (Wire *wire : module->wires()) {
if (wire->port_input) {
SigSpec inp = sigmap(wire);
int fanout = sigFanout[inp];
if (limit > 0 && (fanout > limit)) {
wiresToSplit.push_back(inp);
}
} }
} }
splitNets(design, netsToSplitS, wiresToSplit, formalFriendly, debug, true);
} }
} }
signalsToSplit.emplace(module, cellOutputsToSplit);
if (buffer_inputs) {
// Split module input nets with high fanout
std::vector<RTLIL::SigSpec> wiresToSplit;
for (Wire *wire : module->wires()) {
if (wire->port_input) {
SigSpec inp = sigmap(wire);
int fanout = sigFanout[inp];
if (limit > 0 && (fanout > limit)) {
wiresToSplit.push_back(inp);
}
}
}
portsToSplit.emplace(module, wiresToSplit);
}
}
splitNets(design, signalsToSplit, formalFriendly);
splitNets(design, portsToSplit, formalFriendly, true);
// Fix the high fanout nets
for (auto module : design->selected_modules()) {
bool fixedFanout = false;
// All the buffers inserted in the module
std::map<Cell *, Wire *> insertedBuffers;
{ {
// Fix high fanout // Fix high fanout
SigMap sigmap(module); SigMap sigmap(module);