From 4a1af73ec06e49ccb5564452318b4b86e6f72b17 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Fri, 16 Jan 2026 16:32:04 -0800 Subject: [PATCH 01/19] activity pass and a vcd writer bug fix --- passes/sat/sim.cc | 2 +- passes/silimate/Makefile.inc | 1 + passes/silimate/reg_rename.cc | 86 +++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 passes/silimate/reg_rename.cc diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 5c1f81a97..8add396f7 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -2335,7 +2335,7 @@ struct VCDWriter : public OutputWriter } if (!worker->timescale.empty()) - vcdfile << stringf("$timescale %s $end\n", worker->timescale); + vcdfile << stringf("$timescale 1%s $end\n", worker->timescale); worker->top->write_output_header( [this](IdString name) { vcdfile << stringf("$scope module %s $end\n", log_id(name)); }, diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index d259475b9..0dec65cad 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -9,6 +9,7 @@ OBJS += passes/silimate/l2j_frontend.o OBJS += passes/silimate/lut2bmux.o OBJS += passes/silimate/obs_clean.o OBJS += passes/silimate/opt_balance_tree.o +OBJS += passes/silimate/reg_rename.o OBJS += passes/silimate/segv.o OBJS += passes/silimate/splitfanout.o OBJS += passes/silimate/splitlarge.o diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc new file mode 100644 index 000000000..1af1f0109 --- /dev/null +++ b/passes/silimate/reg_rename.cc @@ -0,0 +1,86 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2026 Stan Lee + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +#include "kernel/yosys.h" + +USING_YOSYS_NAMESPACE +PRIVATE_NAMESPACE_BEGIN + +struct RegRenamePass : public Pass { + RegRenamePass() : Pass("reg_rename", "renames register output wires to the correct register name") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" reg_rename\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing reg_rename pass\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + // No options currently. When adding in the future make sure to update docstring with [options] + break; + } + extra_args(args, argidx, design); + + uint32_t count = 0; + uint32_t moduleCount = design->selected_modules().size(); + for (auto module : design->selected_modules()) { + for (auto cell : module->selected_cells()) { + + // Rename the register output wire to the register name with + // "_reg" suffix removed. + if (cell->name.ends_with("_reg")) { + IdString registerName = cell->name.substr(0, cell->name.size() - 4); + for (auto conn : cell->connections()) { + if (conn.first == ID::Q && conn.second.is_wire()) { + Wire *wire = conn.second.as_wire(); + + // Skip if this wire is a module port (input/output) + if (wire->port_input || wire->port_output) { + log("Skipping port wire %s in register renaming for cell %s in module %s\n", + wire->name.c_str(), log_id(cell), log_id(module)); + continue; + } + + // Skip if we already renamed the wire + if (wire->name == registerName) { + continue; + } + + // Rename register + log("Renaming register wire %s to %s for cell %s in module %s\n", + wire->name.c_str(), registerName.c_str(), log_id(cell), log_id(module)); + module->rename(wire, registerName); + count++; + } + } + } + } + } + log("Renamed %d registers in %d modules\n", count, moduleCount); + log_flush(); + } +} RegRenamePass; + +PRIVATE_NAMESPACE_END From 15026033a3347e7d00fcca222e47bd3f9720b8e9 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 19 Jan 2026 11:19:41 -0800 Subject: [PATCH 02/19] annotate original register width --- passes/sat/sim.cc | 5 ++- passes/silimate/Makefile.inc | 1 + passes/silimate/reg_width.cc | 67 ++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 passes/silimate/reg_width.cc diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index 8add396f7..9f01ad944 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -257,8 +257,11 @@ struct SimInstance if ((shared->fst) && !(shared->hide_internal && wire->name[0] == '$')) { fstHandle id = shared->fst->getHandle(scope + "." + RTLIL::unescape_id(wire->name)); - if (id==0 && wire->name.isPublic()) + if (id==0 && wire->name.isPublic()) { log_warning("Unable to find wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name))); + } else { + log("Found wire %s in input file.\n", (scope + "." + RTLIL::unescape_id(wire->name))); + } fst_handles[wire] = id; } diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index 0dec65cad..9de3e0204 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -10,6 +10,7 @@ OBJS += passes/silimate/lut2bmux.o OBJS += passes/silimate/obs_clean.o OBJS += passes/silimate/opt_balance_tree.o OBJS += passes/silimate/reg_rename.o +OBJS += passes/silimate/reg_width.o OBJS += passes/silimate/segv.o OBJS += passes/silimate/splitfanout.o OBJS += passes/silimate/splitlarge.o diff --git a/passes/silimate/reg_width.cc b/passes/silimate/reg_width.cc new file mode 100644 index 000000000..19a58fd6f --- /dev/null +++ b/passes/silimate/reg_width.cc @@ -0,0 +1,67 @@ +/* + * yosys -- Yosys Open SYnthesis Suite + * + * Copyright (C) 2012 Claire Xenia Wolf + * 2026 Stan Lee + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + + #include "kernel/yosys.h" + #include + + USING_YOSYS_NAMESPACE + PRIVATE_NAMESPACE_BEGIN + + struct RegWidthPass : public Pass { + RegWidthPass() : Pass("reg_width", "annotates multi-bit registers with their width") { } + void help() override + { + // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| + log("\n"); + log(" reg_width\n"); + log("\n"); + } + void execute(std::vector args, RTLIL::Design *design) override + { + log_header(design, "Executing reg_width pass\n"); + + size_t argidx; + for (argidx = 1; argidx < args.size(); argidx++) { + // No options currently. When adding in the future make sure to update docstring with [options] + break; + } + extra_args(args, argidx, design); + + // Data structure used to keep track of multi-bit registers. + // Relevant for correct register annotation. + for (auto module : design->selected_modules()) { + log("Processing module %s\n", module->name.c_str()); + for (auto cell : module->selected_cells()) { + if (cell->name.ends_with("_reg")) { + std::string width = std::to_string(cell->getParam(ID::WIDTH).as_int()); + if (width != "1") { // only care about multi-bit registers + cell->set_string_attribute("$ORIG_REG_WIDTH", width); + log("Annotating register %s with width %s\n", cell->name.c_str(), width); + } + } + } + } + + log_flush(); + } + } RegWidthPass; + + PRIVATE_NAMESPACE_END + \ No newline at end of file From e678e2a0c3ebd0e16340cb08985140ac10b66111 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 19 Jan 2026 11:20:11 -0800 Subject: [PATCH 03/19] every step except wire connecting --- passes/silimate/reg_rename.cc | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 1af1f0109..a22aa06cd 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -19,6 +19,7 @@ */ #include "kernel/yosys.h" +#include USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN @@ -45,13 +46,35 @@ struct RegRenamePass : public Pass { uint32_t count = 0; uint32_t moduleCount = design->selected_modules().size(); + + // Data structure used to keep track of multi-bit registers. + // Relevant for correct register annotation. + + + // Regex to match register output wires + // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg + std::regex reg_regex("(.*)_reg(?:\\[(\\d+)\\])?$"); for (auto module : design->selected_modules()) { for (auto cell : module->selected_cells()) { - // Rename the register output wire to the register name with - // "_reg" suffix removed. - if (cell->name.ends_with("_reg")) { - IdString registerName = cell->name.substr(0, cell->name.size() - 4); + // Rename register output wires to corresponding testbench names + std::smatch match; + std::string name = cell->name.c_str(); + if (std::regex_match(name, match, reg_regex)) { + + + std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); + log("Original register width for cell %s: %s\n", cell->name.c_str(), origRegWidth.c_str()); + + // baseName is the part before _reg + std::string baseName = match[1].str(); + std::string registerName = baseName; + if (match.size() > 2 && match[2].matched) { + // indexStr is the NUMBER in .*_reg[NUMBER] + std::string indexStr = match[2].str(); + registerName += indexStr; + } + for (auto conn : cell->connections()) { if (conn.first == ID::Q && conn.second.is_wire()) { Wire *wire = conn.second.as_wire(); @@ -70,7 +93,7 @@ struct RegRenamePass : public Pass { // Rename register log("Renaming register wire %s to %s for cell %s in module %s\n", - wire->name.c_str(), registerName.c_str(), log_id(cell), log_id(module)); + wire->name.c_str(), registerName, log_id(cell), log_id(module)); module->rename(wire, registerName); count++; } From 186fc15f8fde0a7921c04d229c01c67335e22d31 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 19 Jan 2026 12:10:48 -0800 Subject: [PATCH 04/19] passes simple test --- passes/silimate/reg_rename.cc | 79 +++++++++++++++++++++++++++++++---- 1 file changed, 70 insertions(+), 9 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index a22aa06cd..9baf36321 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -24,6 +24,17 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct CellTracker { + Cell *cell; + int index; +}; + +struct RegTracker { + std::map renamedRegs; + std::string origRegWidth; + Module *module; +}; + struct RegRenamePass : public Pass { RegRenamePass() : Pass("reg_rename", "renames register output wires to the correct register name") { } void help() override @@ -49,7 +60,7 @@ struct RegRenamePass : public Pass { // Data structure used to keep track of multi-bit registers. // Relevant for correct register annotation. - + std::map regTrackers; // Regex to match register output wires // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg @@ -62,23 +73,23 @@ struct RegRenamePass : public Pass { std::string name = cell->name.c_str(); if (std::regex_match(name, match, reg_regex)) { - - std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); - log("Original register width for cell %s: %s\n", cell->name.c_str(), origRegWidth.c_str()); - // baseName is the part before _reg std::string baseName = match[1].str(); std::string registerName = baseName; - if (match.size() > 2 && match[2].matched) { + + // Check if the register is a multi-bit register + bool isMultiBit = match.size() > 2 && match[2].matched; + std::string indexStr; + if (isMultiBit) { // indexStr is the NUMBER in .*_reg[NUMBER] - std::string indexStr = match[2].str(); - registerName += indexStr; + indexStr = match[2].str(); + registerName += "_" + indexStr; } for (auto conn : cell->connections()) { if (conn.first == ID::Q && conn.second.is_wire()) { Wire *wire = conn.second.as_wire(); - + // Skip if this wire is a module port (input/output) if (wire->port_input || wire->port_output) { log("Skipping port wire %s in register renaming for cell %s in module %s\n", @@ -94,6 +105,15 @@ struct RegRenamePass : public Pass { // Rename register log("Renaming register wire %s to %s for cell %s in module %s\n", wire->name.c_str(), registerName, log_id(cell), log_id(module)); + + // Log relevant information for multi-bit registers for wire reconstruction + if (isMultiBit) { + std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); + regTrackers[baseName].origRegWidth = origRegWidth; + regTrackers[baseName].renamedRegs[registerName] = CellTracker{cell, std::stoi(indexStr)}; + regTrackers[baseName].module = module; + } + module->rename(wire, registerName); count++; } @@ -101,6 +121,47 @@ struct RegRenamePass : public Pass { } } } + + for (const auto &[baseName, regTracker] : regTrackers) { + + // Get the module for this register + Module *mod = regTracker.module; + + // Create a new wire for the multi-bit register + int width = std::stoi(regTracker.origRegWidth); + log("Creating new wire %s for register %s with width %d\n", baseName.c_str(), baseName.c_str(), width); + Wire *newWire = mod->addWire(baseName, width); + + pool oldWires; + + // Connect the renamed registers to the corresponding index of the new wire + for (const auto &[renamedRegName, cellTracker] : regTracker.renamedRegs) { + + // Get the old wire (the Q output that was renamed) + Wire *oldWire = cellTracker.cell->getPort(ID::Q).as_wire(); + + // Get the index of the renamed register + int index = cellTracker.index; + log("Connecting renamed register %s to index %d\n", renamedRegName.c_str(), index); + + // Connect the renamed register to the corresponding index of the new wire + mod->connect(SigSpec(newWire, index, 1), cellTracker.cell->getPort(ID::Q)); + + // Replace all uses of oldWire with newWire[index] throughout the module + auto rewriter = [&](SigSpec &sig) { + sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); + }; + mod->rewrite_sigspecs(rewriter); + + // Add the old wire to the list of old wires to delete + oldWires.insert(oldWire); + } + + // Delete the old wires + mod->remove(oldWires); + } + + log("Renamed %d registers in %d modules\n", count, moduleCount); log_flush(); } From 6303eed1b45daefb5f16c82f6dae05c8884bb43d Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 19 Jan 2026 12:22:22 -0800 Subject: [PATCH 05/19] works hierarchy --- passes/silimate/reg_rename.cc | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 9baf36321..47bd04f16 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -60,7 +60,8 @@ struct RegRenamePass : public Pass { // Data structure used to keep track of multi-bit registers. // Relevant for correct register annotation. - std::map regTrackers; + // Key is (Module*, baseName) to handle hierarchical designs where multiple modules may have same register names + std::map, RegTracker> regTrackers; // Regex to match register output wires // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg @@ -109,9 +110,10 @@ struct RegRenamePass : public Pass { // Log relevant information for multi-bit registers for wire reconstruction if (isMultiBit) { std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); - regTrackers[baseName].origRegWidth = origRegWidth; - regTrackers[baseName].renamedRegs[registerName] = CellTracker{cell, std::stoi(indexStr)}; - regTrackers[baseName].module = module; + auto key = std::make_pair(module, baseName); + regTrackers[key].origRegWidth = origRegWidth; + regTrackers[key].renamedRegs[registerName] = CellTracker{cell, std::stoi(indexStr)}; + regTrackers[key].module = module; } module->rename(wire, registerName); @@ -122,14 +124,13 @@ struct RegRenamePass : public Pass { } } - for (const auto &[baseName, regTracker] : regTrackers) { - - // Get the module for this register - Module *mod = regTracker.module; + for (const auto &[key, regTracker] : regTrackers) { + auto [mod, baseName] = key; // Create a new wire for the multi-bit register int width = std::stoi(regTracker.origRegWidth); - log("Creating new wire %s for register %s with width %d\n", baseName.c_str(), baseName.c_str(), width); + log("Creating new wire %s for register %s with width %d in module %s\n", + baseName.c_str(), baseName.c_str(), width, log_id(mod)); Wire *newWire = mod->addWire(baseName, width); pool oldWires; @@ -142,9 +143,9 @@ struct RegRenamePass : public Pass { // Get the index of the renamed register int index = cellTracker.index; - log("Connecting renamed register %s to index %d\n", renamedRegName.c_str(), index); + log("Connecting renamed register %s to index %d of %s\n", renamedRegName.c_str(), index, baseName.c_str()); - // Connect the renamed register to the corresponding index of the new wire + // Connect the renamed register to the corresponding index of the new wiret mod->connect(SigSpec(newWire, index, 1), cellTracker.cell->getPort(ID::Q)); // Replace all uses of oldWire with newWire[index] throughout the module From c471014878077d5522879df245c6323ab7835519 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 19 Jan 2026 12:58:36 -0800 Subject: [PATCH 06/19] slightly cleaner --- passes/silimate/reg_rename.cc | 77 ++++++++++++++++------------------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 47bd04f16..fe1119e57 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -24,15 +24,9 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -struct CellTracker { - Cell *cell; - int index; -}; - -struct RegTracker { - std::map renamedRegs; - std::string origRegWidth; - Module *module; +struct RegWires { + std::vector> oldWires; + int origRegWidth; }; struct RegRenamePass : public Pass { @@ -61,7 +55,8 @@ struct RegRenamePass : public Pass { // Data structure used to keep track of multi-bit registers. // Relevant for correct register annotation. // Key is (Module*, baseName) to handle hierarchical designs where multiple modules may have same register names - std::map, RegTracker> regTrackers; + // Value is a vector of (Wire*, index) pairs to connect the renamed registers to the corresponding index of the new wire + std::map, RegWires> regWireMap; // Regex to match register output wires // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg @@ -111,9 +106,8 @@ struct RegRenamePass : public Pass { if (isMultiBit) { std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); auto key = std::make_pair(module, baseName); - regTrackers[key].origRegWidth = origRegWidth; - regTrackers[key].renamedRegs[registerName] = CellTracker{cell, std::stoi(indexStr)}; - regTrackers[key].module = module; + regWireMap[key].oldWires.push_back(std::make_pair(wire, std::stoi(indexStr))); + regWireMap[key].origRegWidth = std::stoi(origRegWidth); } module->rename(wire, registerName); @@ -124,45 +118,44 @@ struct RegRenamePass : public Pass { } } - for (const auto &[key, regTracker] : regTrackers) { - auto [mod, baseName] = key; + // Iterate over regWireMap to create new wires and connect renamed registers to it. + // Only applies to multi-bit registers. + for (const auto &[key, regWires] : regWireMap) { + auto [mod, baseName] = key; // module and original register name in RTL - // Create a new wire for the multi-bit register - int width = std::stoi(regTracker.origRegWidth); - log("Creating new wire %s for register %s with width %d in module %s\n", - baseName.c_str(), baseName.c_str(), width, log_id(mod)); - Wire *newWire = mod->addWire(baseName, width); + // Create a new wire for the multi-bit register + int width = regWires.origRegWidth; + log("Creating new wire %s for register %s with width %d in module %s\n", + baseName.c_str(), baseName.c_str(), width, log_id(mod)); + Wire *newWire = mod->addWire(baseName, width); - pool oldWires; + // Initialize a pool of old wire to remove from the netlist + pool oldWires; - // Connect the renamed registers to the corresponding index of the new wire - for (const auto &[renamedRegName, cellTracker] : regTracker.renamedRegs) { + // Connect the renamed registers to the corresponding index of the new wire + for (const auto &[oldWire, index] : regWires.oldWires) { - // Get the old wire (the Q output that was renamed) - Wire *oldWire = cellTracker.cell->getPort(ID::Q).as_wire(); + // Get the old wire (the Q output that was renamed) + log("Connecting renamed register %s to index %d of %s\n", oldWire->name.c_str(), index, baseName.c_str()); - // Get the index of the renamed register - int index = cellTracker.index; - log("Connecting renamed register %s to index %d of %s\n", renamedRegName.c_str(), index, baseName.c_str()); + // Connect the renamed register to the corresponding index of the new wiret + mod->connect(SigSpec(newWire, index, 1), oldWire); - // Connect the renamed register to the corresponding index of the new wiret - mod->connect(SigSpec(newWire, index, 1), cellTracker.cell->getPort(ID::Q)); + // Replace all uses of oldWire with newWire[index] throughout the module + auto rewriter = [&](SigSpec &sig) { + sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); + }; + mod->rewrite_sigspecs(rewriter); - // Replace all uses of oldWire with newWire[index] throughout the module - auto rewriter = [&](SigSpec &sig) { - sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); - }; - mod->rewrite_sigspecs(rewriter); + // Add the old wire to the list of old wires to delete + oldWires.insert(oldWire); + } - // Add the old wire to the list of old wires to delete - oldWires.insert(oldWire); + // Delete the old wires + mod->remove(oldWires); } - // Delete the old wires - mod->remove(oldWires); - } - - + // End log("Renamed %d registers in %d modules\n", count, moduleCount); log_flush(); } From 80364c608ee01b3aef9059a423f7f897dc37de88 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 11:29:56 -0800 Subject: [PATCH 07/19] significantly cleaner --- passes/silimate/reg_rename.cc | 107 +++++++++++++--------------------- 1 file changed, 42 insertions(+), 65 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index fe1119e57..6478473b5 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -62,6 +62,7 @@ struct RegRenamePass : public Pass { // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg std::regex reg_regex("(.*)_reg(?:\\[(\\d+)\\])?$"); for (auto module : design->selected_modules()) { + pool wiresToRemove; // pool of wires to remove from the netlist for (auto cell : module->selected_cells()) { // Rename register output wires to corresponding testbench names @@ -71,88 +72,64 @@ struct RegRenamePass : public Pass { // baseName is the part before _reg std::string baseName = match[1].str(); - std::string registerName = baseName; - // Check if the register is a multi-bit register + // Check if the register is a multi-bit register (look for [NUMBER] match in regex) bool isMultiBit = match.size() > 2 && match[2].matched; std::string indexStr; - if (isMultiBit) { - // indexStr is the NUMBER in .*_reg[NUMBER] - indexStr = match[2].str(); - registerName += "_" + indexStr; - } - for (auto conn : cell->connections()) { if (conn.first == ID::Q && conn.second.is_wire()) { - Wire *wire = conn.second.as_wire(); + Wire *oldWire = conn.second.as_wire(); // Skip if this wire is a module port (input/output) - if (wire->port_input || wire->port_output) { + if (oldWire->port_input || oldWire->port_output) { log("Skipping port wire %s in register renaming for cell %s in module %s\n", - wire->name.c_str(), log_id(cell), log_id(module)); + oldWire->name.c_str(), log_id(cell), log_id(module)); continue; } - // Skip if we already renamed the wire - if (wire->name == registerName) { - continue; - } - - // Rename register - log("Renaming register wire %s to %s for cell %s in module %s\n", - wire->name.c_str(), registerName, log_id(cell), log_id(module)); - - // Log relevant information for multi-bit registers for wire reconstruction + // Different cases for multi-bit and single-bit registers if (isMultiBit) { - std::string origRegWidth = cell->get_string_attribute("$ORIG_REG_WIDTH"); - auto key = std::make_pair(module, baseName); - regWireMap[key].oldWires.push_back(std::make_pair(wire, std::stoi(indexStr))); - regWireMap[key].origRegWidth = std::stoi(origRegWidth); - } + + // Index of the register and original register width + int index = std::stoi(match[2].str()); + int origRegWidth = std::stoi(cell->get_string_attribute("$ORIG_REG_WIDTH")); + + // Get or create the multi-bit wire + Wire *newWire = module->wire(RTLIL::escape_id(baseName)); + if (newWire == nullptr) { + // Wire doesn't exist, create it + log("Creating multi-bit wire %s with width %d in module %s\n", + baseName.c_str(), origRegWidth, log_id(module)); + newWire = module->addWire(RTLIL::escape_id(baseName), origRegWidth); + } + + log("Connecting register wire %s to bit %d of %s in module %s\n", + oldWire->name.c_str(), index, baseName.c_str(), log_id(module)); - module->rename(wire, registerName); - count++; + // Replace all uses of oldWire with newWire[index] + auto rewriter = [&](SigSpec &sig) { + sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); + }; + module->rewrite_sigspecs(rewriter); + + // Mark old wire for deletion + wiresToRemove.insert(oldWire); + count++; + + } else { + if (oldWire->name != baseName) { + // Rename single-bit register to correct name from RTL + log("Renaming register wire %s to %s for cell %s in module %s\n", + oldWire->name.c_str(), baseName, log_id(cell), log_id(module)); + module->rename(oldWire, baseName); + count++; + } + } } } } } - } - - // Iterate over regWireMap to create new wires and connect renamed registers to it. - // Only applies to multi-bit registers. - for (const auto &[key, regWires] : regWireMap) { - auto [mod, baseName] = key; // module and original register name in RTL - - // Create a new wire for the multi-bit register - int width = regWires.origRegWidth; - log("Creating new wire %s for register %s with width %d in module %s\n", - baseName.c_str(), baseName.c_str(), width, log_id(mod)); - Wire *newWire = mod->addWire(baseName, width); - - // Initialize a pool of old wire to remove from the netlist - pool oldWires; - - // Connect the renamed registers to the corresponding index of the new wire - for (const auto &[oldWire, index] : regWires.oldWires) { - - // Get the old wire (the Q output that was renamed) - log("Connecting renamed register %s to index %d of %s\n", oldWire->name.c_str(), index, baseName.c_str()); - - // Connect the renamed register to the corresponding index of the new wiret - mod->connect(SigSpec(newWire, index, 1), oldWire); - - // Replace all uses of oldWire with newWire[index] throughout the module - auto rewriter = [&](SigSpec &sig) { - sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); - }; - mod->rewrite_sigspecs(rewriter); - - // Add the old wire to the list of old wires to delete - oldWires.insert(oldWire); - } - - // Delete the old wires - mod->remove(oldWires); + module->remove(wiresToRemove); } // End From 0ea4bb8a2d5362743a57606632827eb55cf2aee3 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 11:55:54 -0800 Subject: [PATCH 08/19] comment --- passes/silimate/reg_rename.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 6478473b5..d2597092e 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -30,7 +30,7 @@ struct RegWires { }; struct RegRenamePass : public Pass { - RegRenamePass() : Pass("reg_rename", "renames register output wires to the correct register name") { } + RegRenamePass() : Pass("reg_rename", "renames register output wires to the correct register name and creates new wires for multi-bit registers for correct VCD register annotations.") { } void help() override { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| @@ -90,21 +90,22 @@ struct RegRenamePass : public Pass { // Different cases for multi-bit and single-bit registers if (isMultiBit) { - // Index of the register and original register width + // Index of the register int index = std::stoi(match[2].str()); - int origRegWidth = std::stoi(cell->get_string_attribute("$ORIG_REG_WIDTH")); // Get or create the multi-bit wire Wire *newWire = module->wire(RTLIL::escape_id(baseName)); if (newWire == nullptr) { - // Wire doesn't exist, create it + // Wire doesn't exist, create it with the original register width + int origRegWidth = std::stoi(cell->get_string_attribute("$ORIG_REG_WIDTH")); log("Creating multi-bit wire %s with width %d in module %s\n", baseName.c_str(), origRegWidth, log_id(module)); newWire = module->addWire(RTLIL::escape_id(baseName), origRegWidth); } + // Log that the new wire is being connected to the register log("Connecting register wire %s to bit %d of %s in module %s\n", - oldWire->name.c_str(), index, baseName.c_str(), log_id(module)); + newWire->name.c_str(), index, baseName.c_str(), log_id(module)); // Replace all uses of oldWire with newWire[index] auto rewriter = [&](SigSpec &sig) { @@ -113,9 +114,10 @@ struct RegRenamePass : public Pass { module->rewrite_sigspecs(rewriter); // Mark old wire for deletion + log("Marking old wire %s for deletion in module %s\n", + oldWire->name.c_str(), log_id(module)); wiresToRemove.insert(oldWire); count++; - } else { if (oldWire->name != baseName) { // Rename single-bit register to correct name from RTL From a5106da7332d0adbf4a9d6d092579e3ddefadb0b Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 11:56:57 -0800 Subject: [PATCH 09/19] line reduction --- passes/silimate/reg_rename.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index d2597092e..e4db42f2e 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -50,7 +50,6 @@ struct RegRenamePass : public Pass { extra_args(args, argidx, design); uint32_t count = 0; - uint32_t moduleCount = design->selected_modules().size(); // Data structure used to keep track of multi-bit registers. // Relevant for correct register annotation. @@ -135,7 +134,7 @@ struct RegRenamePass : public Pass { } // End - log("Renamed %d registers in %d modules\n", count, moduleCount); + log("Renamed %d registers in %d modules\n", count, design->selected_modules().size()); log_flush(); } } RegRenamePass; From 60a81a26769f7ef4b16ea60998595ff5770bf15c Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 15:35:13 -0800 Subject: [PATCH 10/19] reg rename pass reads from vcd for original widths --- passes/silimate/Makefile.inc | 1 - passes/silimate/reg_rename.cc | 73 +++++++++++++++++++++++++++-------- passes/silimate/reg_width.cc | 67 -------------------------------- 3 files changed, 57 insertions(+), 84 deletions(-) delete mode 100644 passes/silimate/reg_width.cc diff --git a/passes/silimate/Makefile.inc b/passes/silimate/Makefile.inc index 9de3e0204..0dec65cad 100644 --- a/passes/silimate/Makefile.inc +++ b/passes/silimate/Makefile.inc @@ -10,7 +10,6 @@ OBJS += passes/silimate/lut2bmux.o OBJS += passes/silimate/obs_clean.o OBJS += passes/silimate/opt_balance_tree.o OBJS += passes/silimate/reg_rename.o -OBJS += passes/silimate/reg_width.o OBJS += passes/silimate/segv.o OBJS += passes/silimate/splitfanout.o OBJS += passes/silimate/splitlarge.o diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index e4db42f2e..4485a7b7d 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -19,6 +19,7 @@ */ #include "kernel/yosys.h" +#include "kernel/fstdata.h" #include USING_YOSYS_NAMESPACE @@ -35,31 +36,61 @@ struct RegRenamePass : public Pass { { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" reg_rename\n"); + log(" reg_rename [options]\n"); + log("\n"); + log(" -vcd \n"); + log(" vcd file to extract original register width from\n"); log("\n"); } void execute(std::vector args, RTLIL::Design *design) override { log_header(design, "Executing reg_rename pass\n"); + + std::string vcd_filename; size_t argidx; for (argidx = 1; argidx < args.size(); argidx++) { - // No options currently. When adding in the future make sure to update docstring with [options] + if (args[argidx] == "-vcd" && argidx+1 < args.size()) { + vcd_filename = args[++argidx]; + continue; + } break; } extra_args(args, argidx, design); - uint32_t count = 0; - - // Data structure used to keep track of multi-bit registers. - // Relevant for correct register annotation. - // Key is (Module*, baseName) to handle hierarchical designs where multiple modules may have same register names - // Value is a vector of (Wire*, index) pairs to connect the renamed registers to the corresponding index of the new wire - std::map, RegWires> regWireMap; + // Populate data strucutre with register widths from VCD file + dict vcd_reg_widths; + if (!vcd_filename.empty()) { + log("Reading VCD file: %s\n", vcd_filename.c_str()); + try { + FstData fst(vcd_filename); + // Iterate through all variables in the VCD file + for (auto &var : fst.getVars()) { + // Only process register variables + if (var.is_reg) { + std::string reg_name = var.name; + // Remove bracket notation if present + if (auto pos = reg_name.find('['); pos != std::string::npos) + reg_name.erase(pos); + // Add RTLIL backslash prefix if not present + if (reg_name.empty() || reg_name[0] != '\\') + reg_name = "\\" + reg_name; + vcd_reg_widths[reg_name] = var.width; + log("Found register '%s' with width %d\n", reg_name.c_str(), var.width); + } + } + log("Extracted %d register widths from VCD file\n", GetSize(vcd_reg_widths)); + } catch (const std::exception &e) { + log_error("Failed to read VCD file '%s': %s\n", vcd_filename.c_str(), e.what()); + } + } else { + log_error("No VCD file provided. Please provide a VCD file with the -vcd option.\n"); + } // Regex to match register output wires // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg std::regex reg_regex("(.*)_reg(?:\\[(\\d+)\\])?$"); + uint32_t count = 0; for (auto module : design->selected_modules()) { pool wiresToRemove; // pool of wires to remove from the netlist for (auto cell : module->selected_cells()) { @@ -96,7 +127,10 @@ struct RegRenamePass : public Pass { Wire *newWire = module->wire(RTLIL::escape_id(baseName)); if (newWire == nullptr) { // Wire doesn't exist, create it with the original register width - int origRegWidth = std::stoi(cell->get_string_attribute("$ORIG_REG_WIDTH")); + int origRegWidth = vcd_reg_widths[baseName]; + if (origRegWidth == 0) { + log_warning("Register '%s' not found in VCD file or has width 0\n", baseName.c_str()); + } log("Creating multi-bit wire %s with width %d in module %s\n", baseName.c_str(), origRegWidth, log_id(module)); newWire = module->addWire(RTLIL::escape_id(baseName), origRegWidth); @@ -118,12 +152,19 @@ struct RegRenamePass : public Pass { wiresToRemove.insert(oldWire); count++; } else { - if (oldWire->name != baseName) { - // Rename single-bit register to correct name from RTL - log("Renaming register wire %s to %s for cell %s in module %s\n", - oldWire->name.c_str(), baseName, log_id(cell), log_id(module)); - module->rename(oldWire, baseName); - count++; + IdString target_name = RTLIL::escape_id(baseName); + if (oldWire->name != target_name) { + // Check if target name already exists + if (module->wire(target_name)) { + log("Skipping rename: wire %s already exists in module %s\n", + target_name.c_str(), log_id(module)); + } else { + // Rename single-bit register to correct name from RTL + log("Renaming register wire %s to %s for cell %s in module %s\n", + oldWire->name.c_str(), target_name.c_str(), log_id(cell), log_id(module)); + module->rename(oldWire, target_name); + count++; + } } } } diff --git a/passes/silimate/reg_width.cc b/passes/silimate/reg_width.cc deleted file mode 100644 index 19a58fd6f..000000000 --- a/passes/silimate/reg_width.cc +++ /dev/null @@ -1,67 +0,0 @@ -/* - * yosys -- Yosys Open SYnthesis Suite - * - * Copyright (C) 2012 Claire Xenia Wolf - * 2026 Stan Lee - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - - #include "kernel/yosys.h" - #include - - USING_YOSYS_NAMESPACE - PRIVATE_NAMESPACE_BEGIN - - struct RegWidthPass : public Pass { - RegWidthPass() : Pass("reg_width", "annotates multi-bit registers with their width") { } - void help() override - { - // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| - log("\n"); - log(" reg_width\n"); - log("\n"); - } - void execute(std::vector args, RTLIL::Design *design) override - { - log_header(design, "Executing reg_width pass\n"); - - size_t argidx; - for (argidx = 1; argidx < args.size(); argidx++) { - // No options currently. When adding in the future make sure to update docstring with [options] - break; - } - extra_args(args, argidx, design); - - // Data structure used to keep track of multi-bit registers. - // Relevant for correct register annotation. - for (auto module : design->selected_modules()) { - log("Processing module %s\n", module->name.c_str()); - for (auto cell : module->selected_cells()) { - if (cell->name.ends_with("_reg")) { - std::string width = std::to_string(cell->getParam(ID::WIDTH).as_int()); - if (width != "1") { // only care about multi-bit registers - cell->set_string_attribute("$ORIG_REG_WIDTH", width); - log("Annotating register %s with width %s\n", cell->name.c_str(), width); - } - } - } - } - - log_flush(); - } - } RegWidthPass; - - PRIVATE_NAMESPACE_END - \ No newline at end of file From 45bd3f4515336c7791b380edb1ce5ee79b789833 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 15:50:43 -0800 Subject: [PATCH 11/19] change splitcells pass to remove some bracket from register names in blast mode --- passes/cmds/splitcells.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc index c5d12413b..bafa27154 100644 --- a/passes/cmds/splitcells.cc +++ b/passes/cmds/splitcells.cc @@ -169,9 +169,14 @@ struct SplitcellsWorker int slice_msb = slices[i]-1; int slice_lsb = slices[i-1]; - IdString slice_name = module->uniquify(cell->name.str() + (slice_msb == slice_lsb ? - stringf("%c%d%c", format[0], slice_lsb, format[1]) : - stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1]))); + std::string base_name = cell->name.str(); + if (blast) { + base_name = base_name.substr(0, base_name.find('[')); + } + + IdString slice_name = module->uniquify(base_name + (slice_msb == slice_lsb ? + stringf("%c%d%c", format[0], slice_lsb, format[1]) : + stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1]))); Cell *slice = module->addCell(slice_name, cell); From 29061d30518f96a49fc1a9b021667ba09da78dbf Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 15:55:05 -0800 Subject: [PATCH 12/19] leave no room for err --- passes/cmds/splitcells.cc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc index bafa27154..92f1e25e3 100644 --- a/passes/cmds/splitcells.cc +++ b/passes/cmds/splitcells.cc @@ -170,14 +170,16 @@ struct SplitcellsWorker int slice_lsb = slices[i-1]; std::string base_name = cell->name.str(); + IdString slice_name; if (blast) { - base_name = base_name.substr(0, base_name.find('[')); + slice_name = module->uniquify(cell->name.str().substr(0, cell->name.str().find('[')) + stringf( + "%c%d%c", format[0], slice_lsb, format[1])); + } else { + slice_name = module->uniquify(base_name + (slice_msb == slice_lsb ? + stringf("%c%d%c", format[0], slice_lsb, format[1]) : + stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1]))); } - IdString slice_name = module->uniquify(base_name + (slice_msb == slice_lsb ? - stringf("%c%d%c", format[0], slice_lsb, format[1]) : - stringf("%c%d%c%d%c", format[0], slice_msb, format[2], slice_lsb, format[1]))); - Cell *slice = module->addCell(slice_name, cell); for (IdString portname : splitports) { From d2e8f9b8a830abac1fb1c30fe3af7b17f06785e8 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Tue, 20 Jan 2026 21:45:13 -0800 Subject: [PATCH 13/19] first round fixes --- passes/silimate/reg_rename.cc | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 4485a7b7d..67d65ef5d 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -25,11 +25,6 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN -struct RegWires { - std::vector> oldWires; - int origRegWidth; -}; - struct RegRenamePass : public Pass { RegRenamePass() : Pass("reg_rename", "renames register output wires to the correct register name and creates new wires for multi-bit registers for correct VCD register annotations.") { } void help() override @@ -58,7 +53,7 @@ struct RegRenamePass : public Pass { } extra_args(args, argidx, design); - // Populate data strucutre with register widths from VCD file + // Populate data structure with register widths from VCD file dict vcd_reg_widths; if (!vcd_filename.empty()) { log("Reading VCD file: %s\n", vcd_filename.c_str()); From 31e32af4a82fdfc6c9f50b223711eac3ff190610 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 08:54:43 -0800 Subject: [PATCH 14/19] greptile --- passes/cmds/splitcells.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/cmds/splitcells.cc b/passes/cmds/splitcells.cc index 92f1e25e3..759e9775b 100644 --- a/passes/cmds/splitcells.cc +++ b/passes/cmds/splitcells.cc @@ -172,7 +172,12 @@ struct SplitcellsWorker std::string base_name = cell->name.str(); IdString slice_name; if (blast) { - slice_name = module->uniquify(cell->name.str().substr(0, cell->name.str().find('[')) + stringf( + // Strip existing brackets from cell name + size_t bracket_pos = base_name.find('['); + if (bracket_pos != std::string::npos) { + base_name = base_name.substr(0, bracket_pos); + } + slice_name = module->uniquify(base_name + stringf( "%c%d%c", format[0], slice_lsb, format[1])); } else { slice_name = module->uniquify(base_name + (slice_msb == slice_lsb ? From e824c8e0d66102baa8de3bd6c11423faaf1eea75 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 09:00:46 -0800 Subject: [PATCH 15/19] ready for review --- passes/silimate/reg_rename.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 67d65ef5d..27a453384 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -125,6 +125,7 @@ struct RegRenamePass : public Pass { int origRegWidth = vcd_reg_widths[baseName]; if (origRegWidth == 0) { log_warning("Register '%s' not found in VCD file or has width 0\n", baseName.c_str()); + continue; } log("Creating multi-bit wire %s with width %d in module %s\n", baseName.c_str(), origRegWidth, log_id(module)); @@ -132,15 +133,15 @@ struct RegRenamePass : public Pass { } // Log that the new wire is being connected to the register - log("Connecting register wire %s to bit %d of %s in module %s\n", - newWire->name.c_str(), index, baseName.c_str(), log_id(module)); - + log("Connecting register wire %s[%d] to bit %d of %s in module %s\n", + newWire->name.c_str(), index, index, baseName.c_str(), log_id(module)); + // Replace all uses of oldWire with newWire[index] auto rewriter = [&](SigSpec &sig) { sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); }; module->rewrite_sigspecs(rewriter); - + // Mark old wire for deletion log("Marking old wire %s for deletion in module %s\n", oldWire->name.c_str(), log_id(module)); From 0018037c16961473e73a3e9c1393a8dcf1bb0574 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 12:25:28 -0800 Subject: [PATCH 16/19] minor changes --- passes/silimate/reg_rename.cc | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 27a453384..a65f34b06 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -116,7 +116,13 @@ struct RegRenamePass : public Pass { if (isMultiBit) { // Index of the register - int index = std::stoi(match[2].str()); + try { + int index = std::stoi(match[2].str()); + } catch (const std::exception &e) { + log_warning("Failed to convert index %s to integer in register %s: %s\n", + match[2].str().c_str(), cell->name.c_str(), e.what()); + continue; + } // Get or create the multi-bit wire Wire *newWire = module->wire(RTLIL::escape_id(baseName)); @@ -134,7 +140,7 @@ struct RegRenamePass : public Pass { // Log that the new wire is being connected to the register log("Connecting register wire %s[%d] to bit %d of %s in module %s\n", - newWire->name.c_str(), index, index, baseName.c_str(), log_id(module)); + newWire->name.c_str(), index, index, log_id(cell), log_id(module)); // Replace all uses of oldWire with newWire[index] auto rewriter = [&](SigSpec &sig) { From 269b70c0f90187718b91bdf6d779e347f35b1645 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 12:32:38 -0800 Subject: [PATCH 17/19] compiles --- passes/silimate/reg_rename.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index a65f34b06..e1ec01cec 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -116,11 +116,12 @@ struct RegRenamePass : public Pass { if (isMultiBit) { // Index of the register + int index = 0; try { - int index = std::stoi(match[2].str()); + index = std::stoi(match[2].str()); } catch (const std::exception &e) { log_warning("Failed to convert index %s to integer in register %s: %s\n", - match[2].str().c_str(), cell->name.c_str(), e.what()); + match[2].str().c_str(), log_id(cell), e.what()); continue; } From f14eb4a7bbd517be518d837960d6d90e491956d3 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 15:13:55 -0800 Subject: [PATCH 18/19] only check reg cells --- passes/silimate/reg_rename.cc | 134 +++++++++++++++++----------------- 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index e1ec01cec..f5869fc52 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -90,83 +90,87 @@ struct RegRenamePass : public Pass { pool wiresToRemove; // pool of wires to remove from the netlist for (auto cell : module->selected_cells()) { - // Rename register output wires to corresponding testbench names - std::smatch match; - std::string name = cell->name.c_str(); - if (std::regex_match(name, match, reg_regex)) { + // Only check register cell + if (RTLIL::builtin_ff_cell_types().count(cell->type)) { - // baseName is the part before _reg - std::string baseName = match[1].str(); + // Rename register output wires to corresponding testbench names + std::smatch match; + std::string name = cell->name.c_str(); + if (std::regex_match(name, match, reg_regex)) { - // Check if the register is a multi-bit register (look for [NUMBER] match in regex) - bool isMultiBit = match.size() > 2 && match[2].matched; - std::string indexStr; - for (auto conn : cell->connections()) { - if (conn.first == ID::Q && conn.second.is_wire()) { - Wire *oldWire = conn.second.as_wire(); + // baseName is the part before _reg + std::string baseName = match[1].str(); - // Skip if this wire is a module port (input/output) - if (oldWire->port_input || oldWire->port_output) { - log("Skipping port wire %s in register renaming for cell %s in module %s\n", - oldWire->name.c_str(), log_id(cell), log_id(module)); - continue; - } + // Check if the register is a multi-bit register (look for [NUMBER] match in regex) + bool isMultiBit = match.size() > 2 && match[2].matched; + std::string indexStr; + for (auto conn : cell->connections()) { + if (conn.first == ID::Q && conn.second.is_wire()) { + Wire *oldWire = conn.second.as_wire(); - // Different cases for multi-bit and single-bit registers - if (isMultiBit) { - - // Index of the register - int index = 0; - try { - index = std::stoi(match[2].str()); - } catch (const std::exception &e) { - log_warning("Failed to convert index %s to integer in register %s: %s\n", - match[2].str().c_str(), log_id(cell), e.what()); + // Skip if this wire is a module port (input/output) + if (oldWire->port_input || oldWire->port_output) { + log("Skipping port wire %s in register renaming for cell %s in module %s\n", + oldWire->name.c_str(), log_id(cell), log_id(module)); continue; } - // Get or create the multi-bit wire - Wire *newWire = module->wire(RTLIL::escape_id(baseName)); - if (newWire == nullptr) { - // Wire doesn't exist, create it with the original register width - int origRegWidth = vcd_reg_widths[baseName]; - if (origRegWidth == 0) { - log_warning("Register '%s' not found in VCD file or has width 0\n", baseName.c_str()); + // Different cases for multi-bit and single-bit registers + if (isMultiBit) { + + // Index of the register + int index = 0; + try { + index = std::stoi(match[2].str()); + } catch (const std::exception &e) { + log_warning("Failed to convert index %s to integer in register %s: %s\n", + match[2].str().c_str(), log_id(cell), e.what()); continue; } - log("Creating multi-bit wire %s with width %d in module %s\n", - baseName.c_str(), origRegWidth, log_id(module)); - newWire = module->addWire(RTLIL::escape_id(baseName), origRegWidth); - } - // Log that the new wire is being connected to the register - log("Connecting register wire %s[%d] to bit %d of %s in module %s\n", - newWire->name.c_str(), index, index, log_id(cell), log_id(module)); + // Get or create the multi-bit wire + Wire *newWire = module->wire(RTLIL::escape_id(baseName)); + if (newWire == nullptr) { + // Wire doesn't exist, create it with the original register width + int origRegWidth = vcd_reg_widths[baseName]; + if (origRegWidth == 0) { + log_warning("Register '%s' not found in VCD file or has width 0\n", baseName.c_str()); + continue; + } + log("Creating multi-bit wire %s with width %d in module %s\n", + baseName.c_str(), origRegWidth, log_id(module)); + newWire = module->addWire(RTLIL::escape_id(baseName), origRegWidth); + } - // Replace all uses of oldWire with newWire[index] - auto rewriter = [&](SigSpec &sig) { - sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); - }; - module->rewrite_sigspecs(rewriter); + // Log that the new wire is being connected to the register + log("Connecting register wire %s[%d] to bit %d of %s in module %s\n", + newWire->name.c_str(), index, index, log_id(cell), log_id(module)); - // Mark old wire for deletion - log("Marking old wire %s for deletion in module %s\n", - oldWire->name.c_str(), log_id(module)); - wiresToRemove.insert(oldWire); - count++; - } else { - IdString target_name = RTLIL::escape_id(baseName); - if (oldWire->name != target_name) { - // Check if target name already exists - if (module->wire(target_name)) { - log("Skipping rename: wire %s already exists in module %s\n", - target_name.c_str(), log_id(module)); - } else { - // Rename single-bit register to correct name from RTL - log("Renaming register wire %s to %s for cell %s in module %s\n", - oldWire->name.c_str(), target_name.c_str(), log_id(cell), log_id(module)); - module->rename(oldWire, target_name); - count++; + // Replace all uses of oldWire with newWire[index] + auto rewriter = [&](SigSpec &sig) { + sig.replace(SigBit(oldWire), SigSpec(newWire, index, 1)); + }; + module->rewrite_sigspecs(rewriter); + + // Mark old wire for deletion + log("Marking old wire %s for deletion in module %s\n", + oldWire->name.c_str(), log_id(module)); + wiresToRemove.insert(oldWire); + count++; + } else { + IdString target_name = RTLIL::escape_id(baseName); + if (oldWire->name != target_name) { + // Check if target name already exists + if (module->wire(target_name)) { + log("Skipping rename: wire %s already exists in module %s\n", + target_name.c_str(), log_id(module)); + } else { + // Rename single-bit register to correct name from RTL + log("Renaming register wire %s to %s for cell %s in module %s\n", + oldWire->name.c_str(), target_name.c_str(), log_id(cell), log_id(module)); + module->rename(oldWire, target_name); + count++; + } } } } From f026cebaf62c9f60031ac8fd9823a11d7ea4d2f6 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Wed, 21 Jan 2026 15:16:45 -0800 Subject: [PATCH 19/19] address comments --- passes/silimate/reg_rename.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index f5869fc52..d73b2dede 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -82,7 +82,7 @@ struct RegRenamePass : public Pass { log_error("No VCD file provided. Please provide a VCD file with the -vcd option.\n"); } - // Regex to match register output wires + // Regex to match registers to output wires // .*_reg[NUMBER] or .*_reg, can match NUMBER and part before _reg std::regex reg_regex("(.*)_reg(?:\\[(\\d+)\\])?$"); uint32_t count = 0;