From d4bfebd0da6fcbddcbab2aecc279ecfacc9bfa67 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Sun, 19 Apr 2026 20:00:09 -0700 Subject: [PATCH 1/4] offsets supported in reg_rename --- passes/silimate/reg_rename.cc | 68 ++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 1ca2d8775..706a87fc8 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -25,6 +25,11 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +struct RegInfo { + int width = 0; + int offset = 0; +}; + struct RegRenameInstance { std::string vcd_scope; Module *module; @@ -58,7 +63,7 @@ struct RegRenameInstance { // Processes registers in a given module hierarchy // and renames to allow for correct register annotation - void process_registers(dict, int> &vcd_reg_widths) + void process_registers(dict, RegInfo> &vcd_reg_widths) { if (debug) log("Processing registers in scope: %s (module: %s)\n", @@ -115,9 +120,12 @@ struct RegRenameInstance { Wire *oldWire = conn.second.as_wire(); if (oldWire->port_input || oldWire->port_output) continue; - // Lookup wire width from VCD + // Lookup wire information from VCD std::string regName = RTLIL::unescape_id(wireName); - int wireWidth = vcd_reg_widths[{vcd_scope, regName}]; + RegInfo regInfo = vcd_reg_widths[{vcd_scope, regName}]; + + int wireWidth = regInfo.width; + int wireOffset = regInfo.offset; if (wireWidth == 0) { log_warning("Unable to find matching register %s in VCD for cell %s in scope %s\n", regName.c_str(), cellName.c_str(), vcd_scope.c_str()); @@ -125,9 +133,11 @@ struct RegRenameInstance { } // Validate bit index - if (bitIndex >= wireWidth) { - log_warning("Bit index %d exceeds wire width %d for '%s'\n", - bitIndex, wireWidth, wireName.c_str()); + int maxIndex = wireOffset + wireWidth - 1; + int minIndex = wireOffset; + if (bitIndex < minIndex || bitIndex > maxIndex) { + log_warning("Bit index %d is invalid for wire indices [%d:%d] for '%s'\n", + bitIndex, maxIndex, minIndex, wireName.c_str()); continue; } @@ -146,9 +156,10 @@ struct RegRenameInstance { targetWire = module->wire(wireId); if (!targetWire) { if (debug) - log("Creating wire %s[%d:0] in scope %s\n", - wireName.c_str(), wireWidth - 1, vcd_scope.c_str()); + log("Creating wire %s[%d:%d] in scope %s\n", + wireName.c_str(), maxIndex, minIndex, vcd_scope.c_str()); targetWire = module->addWire(wireId, wireWidth); + targetWire->start_offset = wireOffset; } targetWireCache[wireId] = targetWire; } @@ -161,10 +172,11 @@ struct RegRenameInstance { log("Connecting %s to %s[%d]\n", log_id(oldWire), wireName.c_str(), bitIndex); - // Record the mapping for each bit of the old wire to the target wire + // Record the mapping for each bit of the old wire to the target wire. + // Translate HDL bit index to RTLIL (0-based) index by subtracting wireOffset. + int normalizedIndex = bitIndex - wireOffset; for (int i = 0; i < GetSize(oldWire); i++) - bit_map[SigBit(oldWire, i)] = SigBit(targetWire, bitIndex + i); - + bit_map[SigBit(oldWire, i)] = SigBit(targetWire, normalizedIndex + i); wireRemoveCache.insert(oldWire); } } @@ -186,7 +198,7 @@ struct RegRenameInstance { module->remove(wireRemoveCache); } - void process_all(dict, int> &vcd_reg_widths) + void process_all(dict, RegInfo> &vcd_reg_widths) { process_registers(vcd_reg_widths); for (auto &it : children) @@ -248,7 +260,7 @@ struct RegRenamePass : public Pass { log_error("No top module found!\n"); // Extract pre-optimization signal widths from VCD file - dict, int> vcd_reg_widths; + dict, RegInfo> vcd_reg_widths; if (!vcd_filename.empty()) { log("Reading VCD file: %s\n", vcd_filename.c_str()); try { @@ -266,18 +278,34 @@ struct RegRenamePass : public Pass { for (auto &var : fst.getVars()) { std::string vcd_scope = var.scope; std::string signal_name = var.name; + std::string signal_bits = ""; - // Remove bracket notation if present to preserve register name - if (auto pos = signal_name.rfind('['); pos != std::string::npos) - signal_name.erase(pos); + // Use the bracket notation to extract the bit range and construct true reg name. + size_t bit_pos = signal_name.rfind('['); + if (bit_pos != std::string::npos) { + signal_bits = signal_name.substr(bit_pos); + signal_name.erase(bit_pos); + } + + // Extract the LSB and MSB indices if present. + int msb = 0; + int lsb = 0; + size_t colon_pos = signal_bits.find(':'); + if (colon_pos != std::string::npos) { + msb = std::stoi(signal_bits.substr(1, colon_pos - 1)); + lsb = std::stoi(signal_bits.substr(colon_pos + 1)); + } + int width = var.width; + int offset = std::min(msb, lsb); // Map the register's vcd scope and name to - // its original width for later lookup. + // its original width and offset for later lookup. signal_name = RTLIL::unescape_id(signal_name); - vcd_reg_widths[{vcd_scope, signal_name}] = var.width; + vcd_reg_widths[{vcd_scope, signal_name}] = {width, offset}; if (debug) - log("Found signal '%s' in scope '%s' with width %d\n", - signal_name.c_str(), vcd_scope.c_str(), var.width); + log("Found signal '%s' in scope '%s' with range [%d:%d] (width %d)\n", + signal_name.c_str(), vcd_scope.c_str(), + offset + width - 1, offset, width); } log("Extracted %d signal widths from VCD\n", GetSize(vcd_reg_widths)); } catch (const std::exception &e) { From 3b7613d8588c5b7166b114c123e5eaebd89e8cdd Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Sun, 19 Apr 2026 21:30:12 -0700 Subject: [PATCH 2/4] guard for multiple drivers --- passes/silimate/reg_rename.cc | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 706a87fc8..3e2a13b58 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -74,6 +74,7 @@ struct RegRenameInstance { // Map of old bits to new bits of a renamed reg wire dict bit_map; + pool claimed_bits; // Caches of target wires and wires to remove dict targetWireCache; @@ -168,15 +169,32 @@ struct RegRenameInstance { if (targetWire == oldWire) continue; + // Record the mapping for each bit of the old wire to the target wire. + int normalizedIndex = bitIndex - wireOffset; + + // Check for conflicts with other cells (multiple drivers guard) + bool conflict = false; + for (int i = 0; i < GetSize(oldWire); i++) { + if (claimed_bits.count(SigBit(targetWire, normalizedIndex + i))) { + conflict = true; + break; + } + } + if (conflict) { + log_warning("Skipping cell %s: target %s[%d] already driven by another cell\n", + log_id(cell->name), wireName.c_str(), bitIndex); + continue; + } + + // Record the mapping for each bit of the old wire to the target wire. if (debug) log("Connecting %s to %s[%d]\n", log_id(oldWire), wireName.c_str(), bitIndex); - - // Record the mapping for each bit of the old wire to the target wire. - // Translate HDL bit index to RTLIL (0-based) index by subtracting wireOffset. - int normalizedIndex = bitIndex - wireOffset; - for (int i = 0; i < GetSize(oldWire); i++) - bit_map[SigBit(oldWire, i)] = SigBit(targetWire, normalizedIndex + i); + for (int i = 0; i < GetSize(oldWire); i++) { + SigBit target(targetWire, normalizedIndex + i); + bit_map[SigBit(oldWire, i)] = target; + claimed_bits.insert(target); + } wireRemoveCache.insert(oldWire); } } From 9e05fb7606d3f7f2f4b164704ef693fbb9f4926e Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 20 Apr 2026 09:40:40 -0700 Subject: [PATCH 3/4] comments --- passes/silimate/reg_rename.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index 3e2a13b58..f6e226040 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -25,6 +25,7 @@ USING_YOSYS_NAMESPACE PRIVATE_NAMESPACE_BEGIN +// Struct stores the width and index offset of a register in VCD file. struct RegInfo { int width = 0; int offset = 0; @@ -169,7 +170,6 @@ struct RegRenameInstance { if (targetWire == oldWire) continue; - // Record the mapping for each bit of the old wire to the target wire. int normalizedIndex = bitIndex - wireOffset; // Check for conflicts with other cells (multiple drivers guard) @@ -186,10 +186,12 @@ struct RegRenameInstance { continue; } - // Record the mapping for each bit of the old wire to the target wire. + // Create the new connection. if (debug) log("Connecting %s to %s[%d]\n", log_id(oldWire), wireName.c_str(), bitIndex); + + // Record the mapping for each bit of the old wire to the target wire. for (int i = 0; i < GetSize(oldWire); i++) { SigBit target(targetWire, normalizedIndex + i); bit_map[SigBit(oldWire, i)] = target; From 8653fea8752ae0d8aefb42138fb870ef4e495df0 Mon Sep 17 00:00:00 2001 From: Stan Lee Date: Mon, 20 Apr 2026 09:45:07 -0700 Subject: [PATCH 4/4] fix --- passes/silimate/reg_rename.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/passes/silimate/reg_rename.cc b/passes/silimate/reg_rename.cc index f6e226040..b12692803 100644 --- a/passes/silimate/reg_rename.cc +++ b/passes/silimate/reg_rename.cc @@ -311,9 +311,11 @@ struct RegRenamePass : public Pass { int msb = 0; int lsb = 0; size_t colon_pos = signal_bits.find(':'); - if (colon_pos != std::string::npos) { + if (colon_pos != std::string::npos) { // range case msb = std::stoi(signal_bits.substr(1, colon_pos - 1)); lsb = std::stoi(signal_bits.substr(colon_pos + 1)); + } else if (!signal_bits.empty()) { // single index case + msb = lsb = std::stoi(signal_bits.substr(1)); } int width = var.width; int offset = std::min(msb, lsb);