offsets supported in reg_rename

This commit is contained in:
Stan Lee 2026-04-19 20:00:09 -07:00
parent a19dfc535c
commit d4bfebd0da
1 changed files with 48 additions and 20 deletions

View File

@ -25,6 +25,11 @@
USING_YOSYS_NAMESPACE USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN PRIVATE_NAMESPACE_BEGIN
struct RegInfo {
int width = 0;
int offset = 0;
};
struct RegRenameInstance { struct RegRenameInstance {
std::string vcd_scope; std::string vcd_scope;
Module *module; Module *module;
@ -58,7 +63,7 @@ struct RegRenameInstance {
// Processes registers in a given module hierarchy // Processes registers in a given module hierarchy
// and renames to allow for correct register annotation // and renames to allow for correct register annotation
void process_registers(dict<std::pair<std::string, std::string>, int> &vcd_reg_widths) void process_registers(dict<std::pair<std::string, std::string>, RegInfo> &vcd_reg_widths)
{ {
if (debug) if (debug)
log("Processing registers in scope: %s (module: %s)\n", log("Processing registers in scope: %s (module: %s)\n",
@ -115,9 +120,12 @@ struct RegRenameInstance {
Wire *oldWire = conn.second.as_wire(); Wire *oldWire = conn.second.as_wire();
if (oldWire->port_input || oldWire->port_output) continue; 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); 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) { if (wireWidth == 0) {
log_warning("Unable to find matching register %s in VCD for cell %s in scope %s\n", 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()); regName.c_str(), cellName.c_str(), vcd_scope.c_str());
@ -125,9 +133,11 @@ struct RegRenameInstance {
} }
// Validate bit index // Validate bit index
if (bitIndex >= wireWidth) { int maxIndex = wireOffset + wireWidth - 1;
log_warning("Bit index %d exceeds wire width %d for '%s'\n", int minIndex = wireOffset;
bitIndex, wireWidth, wireName.c_str()); 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; continue;
} }
@ -146,9 +156,10 @@ struct RegRenameInstance {
targetWire = module->wire(wireId); targetWire = module->wire(wireId);
if (!targetWire) { if (!targetWire) {
if (debug) if (debug)
log("Creating wire %s[%d:0] in scope %s\n", log("Creating wire %s[%d:%d] in scope %s\n",
wireName.c_str(), wireWidth - 1, vcd_scope.c_str()); wireName.c_str(), maxIndex, minIndex, vcd_scope.c_str());
targetWire = module->addWire(wireId, wireWidth); targetWire = module->addWire(wireId, wireWidth);
targetWire->start_offset = wireOffset;
} }
targetWireCache[wireId] = targetWire; targetWireCache[wireId] = targetWire;
} }
@ -161,10 +172,11 @@ struct RegRenameInstance {
log("Connecting %s to %s[%d]\n", log("Connecting %s to %s[%d]\n",
log_id(oldWire), wireName.c_str(), bitIndex); 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++) 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); wireRemoveCache.insert(oldWire);
} }
} }
@ -186,7 +198,7 @@ struct RegRenameInstance {
module->remove(wireRemoveCache); module->remove(wireRemoveCache);
} }
void process_all(dict<std::pair<std::string, std::string>, int> &vcd_reg_widths) void process_all(dict<std::pair<std::string, std::string>, RegInfo> &vcd_reg_widths)
{ {
process_registers(vcd_reg_widths); process_registers(vcd_reg_widths);
for (auto &it : children) for (auto &it : children)
@ -248,7 +260,7 @@ struct RegRenamePass : public Pass {
log_error("No top module found!\n"); log_error("No top module found!\n");
// Extract pre-optimization signal widths from VCD file // Extract pre-optimization signal widths from VCD file
dict<std::pair<std::string, std::string>, int> vcd_reg_widths; dict<std::pair<std::string, std::string>, RegInfo> vcd_reg_widths;
if (!vcd_filename.empty()) { if (!vcd_filename.empty()) {
log("Reading VCD file: %s\n", vcd_filename.c_str()); log("Reading VCD file: %s\n", vcd_filename.c_str());
try { try {
@ -266,18 +278,34 @@ struct RegRenamePass : public Pass {
for (auto &var : fst.getVars()) { for (auto &var : fst.getVars()) {
std::string vcd_scope = var.scope; std::string vcd_scope = var.scope;
std::string signal_name = var.name; std::string signal_name = var.name;
std::string signal_bits = "";
// Remove bracket notation if present to preserve register name // Use the bracket notation to extract the bit range and construct true reg name.
if (auto pos = signal_name.rfind('['); pos != std::string::npos) size_t bit_pos = signal_name.rfind('[');
signal_name.erase(pos); 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 // 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); 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) if (debug)
log("Found signal '%s' in scope '%s' with width %d\n", log("Found signal '%s' in scope '%s' with range [%d:%d] (width %d)\n",
signal_name.c_str(), vcd_scope.c_str(), var.width); 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)); log("Extracted %d signal widths from VCD\n", GetSize(vcd_reg_widths));
} catch (const std::exception &e) { } catch (const std::exception &e) {