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