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
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<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)
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<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);
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<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()) {
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) {