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

Separate into 2 passes

This commit is contained in:
Alain Dargelas 2025-03-07 14:11:25 -08:00
parent c54c3f66b7
commit 52b1cbf456

View file

@ -522,15 +522,16 @@ 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::map<Module *, std::vector<RTLIL::SigSpec>> &sigsToSplit, bool formalFriendly) void splitNets(Design *design, std::map<Module *, std::vector<RTLIL::SigSpec>> &sigsToSplit)
{ {
std::string wires; std::string wires;
std::string inputs; std::string inputs;
std::string outputs; std::string outputs;
// Memorize selection // Memorize previous selection
Pass::call(design, "select -set presplitnets %"); Pass::call(design, "select -set presplitnets %");
// Clear selection // Clear selection
Pass::call(design, "select -none"); Pass::call(design, "select -none");
// Select all the wires to split
std::set<Wire *> selected; std::set<Wire *> selected;
for (std::map<Module *, std::vector<RTLIL::SigSpec>>::iterator itr = sigsToSplit.begin(); itr != sigsToSplit.end(); itr++) { for (std::map<Module *, std::vector<RTLIL::SigSpec>>::iterator itr = sigsToSplit.begin(); itr != sigsToSplit.end(); itr++) {
Module *module = itr->first; Module *module = itr->first;
@ -541,87 +542,53 @@ void splitNets(Design *design, std::map<Module *, std::vector<RTLIL::SigSpec>> &
if (selected.find(parentWire) != selected.end()) if (selected.find(parentWire) != selected.end())
continue; continue;
selected.insert(parentWire); selected.insert(parentWire);
if (formalFriendly) { design->select(module, parentWire);
// Formal verification does not like ports to be split.
// This option will prevent some buffering to happen on high fanout input/output ports,
// but it will make formal happy.
if ((!parentWire->port_input) && (!parentWire->port_output))
design->select(module, parentWire);
} else {
design->select(module, parentWire);
}
} }
} }
Pass::call(design, std::string("splitnets") + (formalFriendly ? "" : " -ports")); // Split the wires
// Restore selection Pass::call(design, std::string("splitnets -ports"));
// Restore previous selection
Pass::call(design, "select @presplitnets"); Pass::call(design, "select @presplitnets");
} }
struct AnnotateCellFanout : public ScriptPass { // Split high fanout nets
AnnotateCellFanout() : ScriptPass("annotate_cell_fanout", "Annotate the cell fanout on the cell") {} struct SplitHighFanoutNets : public ScriptPass {
SplitHighFanoutNets() : ScriptPass("split_high_fanout_nets", "Split high fanout nets") {}
void script() override {} void script() override {}
void help() override void help() override
{ {
log("\n"); log("\n");
log(" annotate_cell_fanout [options] [selection]\n"); log(" split_high_fanout_nets [options] [selection]\n");
log("\n"); log("\n");
log("This pass annotates cell fanout and optionally inserts balanced buffer trees to limit fanout.\n"); log("Split high fanout nets.\n");
log("\n"); log("\n");
log(" -limit <limit>\n"); log(" -limit <limit>\n");
log(" Limits the fanout by inserting balanced buffer trees.\n"); log(" Limits the fanout by inserting balanced buffer trees.\n");
log(" -formal\n");
log(" For formal verification to pass, will prevent splitnets passes on ports, even if they have large fanout.\n");
log(" -inputs\n"); log(" -inputs\n");
log(" Fix module inputs fanout.\n"); log(" Fix module inputs fanout.\n");
log(" -clocks\n");
log(" Fix module clocks fanout.\n");
log(" -resets\n");
log(" Fix module resets fanout.\n");
log(" -debug\n");
log(" Debug trace.\n");
log("\n"); log("\n");
} }
void execute(std::vector<std::string> args, RTLIL::Design *design) override void execute(std::vector<std::string> args, RTLIL::Design *design) override
{ {
int limit = -1; int limit = -1;
bool formalFriendly = false;
bool buffer_inputs = false; bool buffer_inputs = false;
bool buffer_clocks = false;
bool buffer_resets = false;
bool debug = false;
if (design == nullptr) { if (design == nullptr) {
log_error("No design object\n"); log_error("No design object\n");
return; return;
} }
log("Running annotate_cell_fanout pass\n"); log("Running split_high_fanout_nets pass\n");
log_flush(); log_flush();
size_t argidx; size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) { for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-debug") {
debug = true;
continue;
}
if (args[argidx] == "-limit") { if (args[argidx] == "-limit") {
limit = std::atoi(args[++argidx].c_str()); limit = std::atoi(args[++argidx].c_str());
continue; continue;
} }
if (args[argidx] == "-formal") {
formalFriendly = true;
continue;
}
if (args[argidx] == "-inputs") { if (args[argidx] == "-inputs") {
buffer_inputs = true; buffer_inputs = true;
continue; continue;
} }
if (args[argidx] == "-clocks") {
buffer_clocks = true;
continue;
}
if (args[argidx] == "-resets") {
buffer_resets = true;
continue;
}
break; break;
} }
extra_args(args, argidx, design); extra_args(args, argidx, design);
@ -679,7 +646,76 @@ struct AnnotateCellFanout : public ScriptPass {
signalsToSplit.emplace(module, netsToSplit); signalsToSplit.emplace(module, netsToSplit);
} }
// Split all the high fanout nets in one pass for the whole design // Split all the high fanout nets in one pass for the whole design
splitNets(design, signalsToSplit, formalFriendly); splitNets(design, signalsToSplit);
}
} SplitHighFanoutNets;
// Annotate cell fanout and optionally insert balanced buffer trees to limit fanout
struct AnnotateCellFanout : public ScriptPass {
AnnotateCellFanout() : ScriptPass("annotate_cell_fanout", "Annotate the cell fanout on the cell") {}
void script() override {}
void help() override
{
log("\n");
log(" annotate_cell_fanout [options] [selection]\n");
log("\n");
log("This pass annotates cell fanout and optionally inserts balanced buffer trees to limit fanout.\n");
log("\n");
log(" -limit <limit>\n");
log(" Limits the fanout by inserting balanced buffer trees.\n");
log(" -inputs\n");
log(" Fix module inputs fanout.\n");
log(" -clocks\n");
log(" Fix module clocks fanout.\n");
log(" -resets\n");
log(" Fix module resets fanout.\n");
log(" -debug\n");
log(" Debug trace.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
int limit = -1;
bool buffer_inputs = false;
bool buffer_clocks = false;
bool buffer_resets = false;
bool debug = false;
if (design == nullptr) {
log_error("No design object\n");
return;
}
log("Running annotate_cell_fanout pass\n");
log_flush();
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
if (args[argidx] == "-debug") {
debug = true;
continue;
}
if (args[argidx] == "-limit") {
limit = std::atoi(args[++argidx].c_str());
continue;
}
if (args[argidx] == "-inputs") {
buffer_inputs = true;
continue;
}
if (args[argidx] == "-clocks") {
buffer_clocks = true;
continue;
}
if (args[argidx] == "-resets") {
buffer_resets = true;
continue;
}
break;
}
extra_args(args, argidx, design);
if ((limit != -1) && (limit < 2)) {
log_error("Fanout cannot be limited to less than 2\n");
return;
}
// Fix the high fanout nets // Fix the high fanout nets
for (auto module : design->selected_modules()) { for (auto module : design->selected_modules()) {
@ -810,6 +846,6 @@ struct AnnotateCellFanout : public ScriptPass {
log("End annotate_cell_fanout pass\n"); log("End annotate_cell_fanout pass\n");
log_flush(); log_flush();
} }
} SplitNetlist; } AnnotateCellFanout;
PRIVATE_NAMESPACE_END PRIVATE_NAMESPACE_END