From f271dfaf4dca3f8e148972ad2eefc68b8652e4e2 Mon Sep 17 00:00:00 2001 From: jpwatt Date: Tue, 21 Apr 2026 13:37:47 -1000 Subject: [PATCH 01/10] Add ClampedSymAttr helper --- compiler/cpp/circt_util.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/cpp/circt_util.cpp b/compiler/cpp/circt_util.cpp index d040af3..580f0bd 100644 --- a/compiler/cpp/circt_util.cpp +++ b/compiler/cpp/circt_util.cpp @@ -439,6 +439,11 @@ mlir::StringAttr StringToStringAttr(const std::string &str) return mlir::StringAttr::get(g_compiler->GetMlirContext(), str); } +mlir::StringAttr ClampedSymAttr(const std::string &str) +{ + return StringToStringAttr(g_compiler->ClampStringLength(str)); +} + mlir::IntegerType GetIntegerType(const size_t width, mlir::IntegerType::SignednessSemantics signedness) { return mlir::IntegerType::get(g_compiler->GetMlirContext(), width, signedness); From 6f6857581e88c4fc6f1050634a2cd8986ee8b9f9 Mon Sep 17 00:00:00 2001 From: jpwatt Date: Tue, 21 Apr 2026 14:35:37 -1000 Subject: [PATCH 02/10] Clamp instance names in more places --- compiler/cpp/circt_util.cpp | 2 +- compiler/cpp/verilog.cpp | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/cpp/circt_util.cpp b/compiler/cpp/circt_util.cpp index 580f0bd..28d87db 100644 --- a/compiler/cpp/circt_util.cpp +++ b/compiler/cpp/circt_util.cpp @@ -592,7 +592,7 @@ mlir::StringAttr GetFullyQualifiedStringAttr(const ObjectPath &containerPath, co ObjectPath pathWithField = containerPath; pathWithField.push_back("__field__" + fieldName); - return StringToStringAttr(FixupStringCirct(SerializePath(pathWithField, '_'))); + return StringToStringAttr(g_compiler->ClampStringLength(FixupStringCirct(SerializePath(pathWithField, '_')))); } circt::hw::InnerSymAttr GetFullyQualifiedInnerSymAttr(const ObjectPath &containerPath, const std::string &fieldName) diff --git a/compiler/cpp/verilog.cpp b/compiler/cpp/verilog.cpp index 7e5fb98..0d55f1b 100644 --- a/compiler/cpp/verilog.cpp +++ b/compiler/cpp/verilog.cpp @@ -495,7 +495,9 @@ std::string GetRegisterBaseName(const Program &program, const size_t registerInd return prefix + std::to_string(registerIndex) + "_" + regDesc._name; } -std::string GetBasicBlockInstanceName(const BasicBlock &basicBlock) { return GetBasicBlockName(basicBlock) + "Impl"; } +std::string GetBasicBlockInstanceName(const BasicBlock &basicBlock) { + return g_compiler->ClampStringLength((basicBlock) + "Impl"); +} class VerilogCompiler; @@ -1641,7 +1643,8 @@ class VerilogCompiler const mlir::Location location = RegDescToLocation(regDesc); circt::kanagawa::ContainerInstanceOp::create(opb, - location, circt::hw::InnerSymAttr::get(StringToStringAttr(containerInstancePath.back())), + location, + circt::hw::InnerSymAttr::get(ClampedSymAttr(containerInstancePath.back())), circt::hw::InnerRefAttr::get(StringToStringAttr(GetCirctDesignName()), leafContainerNameAttr)); // Write clock and reset ports @@ -2810,7 +2813,8 @@ class VerilogCompiler opb.setInsertionPointToEnd(parentContainer.getBodyBlock()); circt::kanagawa::ContainerInstanceOp::create(opb, - location, circt::hw::InnerSymAttr::get(StringToStringAttr(containerInstancePath.back())), + location, + circt::hw::InnerSymAttr::get(ClampedSymAttr(containerInstancePath.back())), circt::hw::InnerRefAttr::get(StringToStringAttr(GetCirctDesignName()), leafContainerNameAttr)); // Write clock and reset ports @@ -5621,7 +5625,7 @@ class VerilogCompiler ModuleInstanceHelper instance(*this, LocationToCirctLocation(basicBlock._location)); - instance.SetModuleName(GetModuleNamePrefix() + GetBasicBlockName(basicBlock)); + instance.SetModuleName(g_compiler->ClampStringLength(GetModuleNamePrefix() + GetBasicBlockName(basicBlock))); instance.SetInstanceName(GetBasicBlockInstanceName(basicBlock)); instance.AddPort("clk", circt::hw::ModulePort::Direction::Input, GetClockType(), "clk"); @@ -7635,7 +7639,7 @@ class VerilogCompiler const std::set acquiredSemaphores = GetAcquiredSemaphores(basicBlock); const std::set releasedSemaphores = GetReleasedSemaphores(basicBlock); - const std::string fullModuleName = GetModuleNamePrefix() + GetBasicBlockName(basicBlock); + const std::string fullModuleName = g_compiler->ClampStringLength(GetModuleNamePrefix() + GetBasicBlockName(basicBlock)); JsonValue jsonBasicBlock = JsonValue::CreateObject(); JsonValue jsonPorts = JsonValue::CreateArray(); @@ -8228,7 +8232,7 @@ class VerilogCompiler mlir::Value inputSliceWire = circt::sv::LogicOp::create(opb, mlirBbLocation, sliceType, StringToStringAttr(inputWireName), GetFullyQualifiedInnerSymAttr(basicBlock.GetObjectPath(), inputWireName)); - + SafeInsert(offsetToInputWire, sliceOffset, inputSliceWire); sparseConcat.Insert(sliceOffset, @@ -11426,7 +11430,7 @@ class VerilogCompiler basicBlockPorts.push_back(pi._portInfo); } - const std::string moduleName = GetModuleNamePrefix() + GetBasicBlockName(basicBlock); + const std::string moduleName = g_compiler->ClampStringLength(GetModuleNamePrefix() + GetBasicBlockName(basicBlock)); _compileContext._hwModule = circt::hw::HWModuleOp::create(opb, mlirBbLocation, opb.getStringAttr(moduleName), basicBlockPorts); @@ -11999,7 +12003,8 @@ class VerilogCompiler opb.setInsertionPointToEnd(parentContainer.getBodyBlock()); circt::kanagawa::ContainerInstanceOp instance = circt::kanagawa::ContainerInstanceOp::create(opb, - GetUnknownLocation(), circt::hw::InnerSymAttr::get(StringToStringAttr(path.back())), + GetUnknownLocation(), + circt::hw::InnerSymAttr::get(ClampedSymAttr(path.back())), circt::hw::InnerRefAttr::get(StringToStringAttr(GetCirctDesignName()), containerNameAttr)); SafeInsert(_pathToContainerInstance, path, ContainerAndInstance(container, instance)); @@ -12090,7 +12095,7 @@ class VerilogCompiler std::string GenericContainerName(const ObjectPath &path) { - return path.empty() ? _coreModule->Name() : FixupString(SerializePath(path)); + return path.empty() ? _coreModule->Name() : g_compiler->ClampStringLength((SerializePath(path))); } }; From 21a0291903882c5b1038184ec0e8d006823e1b35 Mon Sep 17 00:00:00 2001 From: jpwatt Date: Tue, 21 Apr 2026 14:42:37 -1000 Subject: [PATCH 03/10] fix typos --- compiler/cpp/verilog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/cpp/verilog.cpp b/compiler/cpp/verilog.cpp index 0d55f1b..8d82a07 100644 --- a/compiler/cpp/verilog.cpp +++ b/compiler/cpp/verilog.cpp @@ -496,7 +496,7 @@ std::string GetRegisterBaseName(const Program &program, const size_t registerInd } std::string GetBasicBlockInstanceName(const BasicBlock &basicBlock) { - return g_compiler->ClampStringLength((basicBlock) + "Impl"); + return g_compiler->ClampStringLength(GetBasicBlockName(basicBlock) + "Impl"); } class VerilogCompiler; @@ -8232,7 +8232,7 @@ class VerilogCompiler mlir::Value inputSliceWire = circt::sv::LogicOp::create(opb, mlirBbLocation, sliceType, StringToStringAttr(inputWireName), GetFullyQualifiedInnerSymAttr(basicBlock.GetObjectPath(), inputWireName)); - + SafeInsert(offsetToInputWire, sliceOffset, inputSliceWire); sparseConcat.Insert(sliceOffset, @@ -12095,7 +12095,7 @@ class VerilogCompiler std::string GenericContainerName(const ObjectPath &path) { - return path.empty() ? _coreModule->Name() : g_compiler->ClampStringLength((SerializePath(path))); + return path.empty() ? _coreModule->Name() : g_compiler->ClampStringLength(FixupString(SerializePath(path))); } }; From 961085fd4d29be9ce7ee906724b1efc8900215c8 Mon Sep 17 00:00:00 2001 From: jpwatt Date: Wed, 22 Apr 2026 10:59:37 -1000 Subject: [PATCH 04/10] Declare ClampedSymAttr in header --- compiler/cpp/circt_util.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/cpp/circt_util.h b/compiler/cpp/circt_util.h index 3272670..faf3aa3 100644 --- a/compiler/cpp/circt_util.h +++ b/compiler/cpp/circt_util.h @@ -69,6 +69,8 @@ mlir::Value LiteralToValue(const Literal& l, circt::OpBuilder& opb, const mlir:: mlir::StringAttr StringToStringAttr(const std::string& str); +mlir::StringAttr ClampedSymAttr(const std::string& str); + size_t GetMlirTypeWidth(const mlir::Type& type); size_t GetMlirValueWidth(const mlir::Value& v); From fd079bc9784a4e6e1a3076a604a304c0bff8af41 Mon Sep 17 00:00:00 2001 From: James Watt Date: Thu, 23 Apr 2026 19:22:49 -0700 Subject: [PATCH 05/10] make ClampStringLength indempotent, return no-op if already clamped --- compiler/cpp/compiler.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/compiler/cpp/compiler.cpp b/compiler/cpp/compiler.cpp index bd3a5cb..7407abe 100644 --- a/compiler/cpp/compiler.cpp +++ b/compiler/cpp/compiler.cpp @@ -1902,6 +1902,33 @@ std::string Compiler::ClampStringLength(const std::string& stringIn) if (result.size() > limit) { + // If input already clamped, return a no-op. Avoids generating different strings for the same input on different passes + if (const size_t underscore = stringIn.rfind('_'); underscore != std::string::npos) + { + const std::string suffix = stringIn.substr(underscore + 1); + if (!suffix.empty() && std::all_of(suffix.begin(), suffix.end(), [](char c) { return std::isdigit(static_cast(c)); })) + { + try + { + const size_t parsedHash = std::stoull(suffix); + const auto existing = _clampStringMap.find(parsedHash); + if (existing != _clampStringMap.end()) + { + std::ostringstream expected; + expected << existing->second.substr(0, limit) << "_" << parsedHash; + if (expected.str() == stringIn) + { + return stringIn; + } + } + } + catch (const std::exception&) + { + // not a hash suffix; fall through + } + } + } + // Compute a hash code of the full string std::hash hasher; From 1cb7fb66ead76d06d34ee907306336d5f0e55652 Mon Sep 17 00:00:00 2001 From: James Watt Date: Wed, 29 Apr 2026 13:46:14 -0700 Subject: [PATCH 06/10] clean up un-needed changes --- compiler/cpp/verilog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/verilog.cpp b/compiler/cpp/verilog.cpp index 8d82a07..991c187 100644 --- a/compiler/cpp/verilog.cpp +++ b/compiler/cpp/verilog.cpp @@ -12095,7 +12095,7 @@ class VerilogCompiler std::string GenericContainerName(const ObjectPath &path) { - return path.empty() ? _coreModule->Name() : g_compiler->ClampStringLength(FixupString(SerializePath(path))); + return path.empty() ? _coreModule->Name() : FixupString(SerializePath(path)); } }; From 7394c8a5cb3a3e9dbeb1262563042480c8551227 Mon Sep 17 00:00:00 2001 From: James Watt Date: Wed, 29 Apr 2026 13:48:14 -0700 Subject: [PATCH 07/10] Clean up un-needed changes --- compiler/cpp/compiler.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/compiler/cpp/compiler.cpp b/compiler/cpp/compiler.cpp index 7407abe..bd3a5cb 100644 --- a/compiler/cpp/compiler.cpp +++ b/compiler/cpp/compiler.cpp @@ -1902,33 +1902,6 @@ std::string Compiler::ClampStringLength(const std::string& stringIn) if (result.size() > limit) { - // If input already clamped, return a no-op. Avoids generating different strings for the same input on different passes - if (const size_t underscore = stringIn.rfind('_'); underscore != std::string::npos) - { - const std::string suffix = stringIn.substr(underscore + 1); - if (!suffix.empty() && std::all_of(suffix.begin(), suffix.end(), [](char c) { return std::isdigit(static_cast(c)); })) - { - try - { - const size_t parsedHash = std::stoull(suffix); - const auto existing = _clampStringMap.find(parsedHash); - if (existing != _clampStringMap.end()) - { - std::ostringstream expected; - expected << existing->second.substr(0, limit) << "_" << parsedHash; - if (expected.str() == stringIn) - { - return stringIn; - } - } - } - catch (const std::exception&) - { - // not a hash suffix; fall through - } - } - } - // Compute a hash code of the full string std::hash hasher; From fd562b8ea9244694909101c85eeb512a0ad7201c Mon Sep 17 00:00:00 2001 From: James Watt Date: Wed, 29 Apr 2026 13:50:56 -0700 Subject: [PATCH 08/10] Fix inner sym lookups --- compiler/cpp/circt_util.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/cpp/circt_util.cpp b/compiler/cpp/circt_util.cpp index 28d87db..c5d4bf1 100644 --- a/compiler/cpp/circt_util.cpp +++ b/compiler/cpp/circt_util.cpp @@ -366,7 +366,7 @@ mlir::Value GetPathOp(circt::OpBuilder &opb, const ObjectPath &srcPath, const Ob while (currPath != commonRoot) { - const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(StringToStringAttr(currPath.back())); + const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(ClampedSymAttr(currPath.back())); const mlir::Attribute step = circt::kanagawa::PathStepAttr::get( g_compiler->GetMlirContext(), circt::kanagawa::PathDirection::Parent, @@ -384,7 +384,7 @@ mlir::Value GetPathOp(circt::OpBuilder &opb, const ObjectPath &srcPath, const Ob const std::string stepName = dstPath[currPath.size()]; - const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(StringToStringAttr(stepName)); + const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(ClampedSymAttr(stepName)); const mlir::Attribute step = circt::kanagawa::PathStepAttr::get( g_compiler->GetMlirContext(), circt::kanagawa::PathDirection::Child, @@ -592,7 +592,7 @@ mlir::StringAttr GetFullyQualifiedStringAttr(const ObjectPath &containerPath, co ObjectPath pathWithField = containerPath; pathWithField.push_back("__field__" + fieldName); - return StringToStringAttr(g_compiler->ClampStringLength(FixupStringCirct(SerializePath(pathWithField, '_')))); + return StringToStringAttr(FixupStringCirct(SerializePath(pathWithField, '_'))); } circt::hw::InnerSymAttr GetFullyQualifiedInnerSymAttr(const ObjectPath &containerPath, const std::string &fieldName) @@ -2185,7 +2185,7 @@ mlir::Value ModuleDeclarationHelper::GetPort(circt::OpBuilder &opb, const Object while (currPath != commonRoot) { - const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(StringToStringAttr(currPath.back())); + const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(ClampedSymAttr(currPath.back())); const mlir::Attribute step = circt::kanagawa::PathStepAttr::get( g_compiler->GetMlirContext(), circt::kanagawa::PathDirection::Parent, @@ -2203,7 +2203,7 @@ mlir::Value ModuleDeclarationHelper::GetPort(circt::OpBuilder &opb, const Object const std::string stepName = dstPath[currPath.size()]; - const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(StringToStringAttr(stepName)); + const mlir::FlatSymbolRefAttr symbolRef = mlir::FlatSymbolRefAttr::get(ClampedSymAttr(stepName)); const mlir::Attribute step = circt::kanagawa::PathStepAttr::get( g_compiler->GetMlirContext(), circt::kanagawa::PathDirection::Child, From f32bf50c0b6395f26ce0d538f9938141e25a8b08 Mon Sep 17 00:00:00 2001 From: James Watt Date: Wed, 29 Apr 2026 16:50:13 -0700 Subject: [PATCH 09/10] Clamp concatenated names --- compiler/cpp/circt_util.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/cpp/circt_util.cpp b/compiler/cpp/circt_util.cpp index c5d4bf1..f4cfa2d 100644 --- a/compiler/cpp/circt_util.cpp +++ b/compiler/cpp/circt_util.cpp @@ -592,7 +592,7 @@ mlir::StringAttr GetFullyQualifiedStringAttr(const ObjectPath &containerPath, co ObjectPath pathWithField = containerPath; pathWithField.push_back("__field__" + fieldName); - return StringToStringAttr(FixupStringCirct(SerializePath(pathWithField, '_'))); + return ClampedSymAttr(FixupStringCirct(SerializePath(pathWithField, '_'))); } circt::hw::InnerSymAttr GetFullyQualifiedInnerSymAttr(const ObjectPath &containerPath, const std::string &fieldName) From 665c063a8d8c78d75bf42ac07ba908837854a8dd Mon Sep 17 00:00:00 2001 From: James Watt Date: Wed, 29 Apr 2026 18:05:21 -0700 Subject: [PATCH 10/10] clamp more concatenated strings --- compiler/cpp/verilog.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/compiler/cpp/verilog.cpp b/compiler/cpp/verilog.cpp index 991c187..62b6755 100644 --- a/compiler/cpp/verilog.cpp +++ b/compiler/cpp/verilog.cpp @@ -495,8 +495,8 @@ std::string GetRegisterBaseName(const Program &program, const size_t registerInd return prefix + std::to_string(registerIndex) + "_" + regDesc._name; } -std::string GetBasicBlockInstanceName(const BasicBlock &basicBlock) { - return g_compiler->ClampStringLength(GetBasicBlockName(basicBlock) + "Impl"); +std::string GetBasicBlockInstanceName(const BasicBlock &basicBlock) { + return g_compiler->ClampStringLength(GetBasicBlockName(basicBlock) + "Impl"); } class VerilogCompiler; @@ -1643,7 +1643,7 @@ class VerilogCompiler const mlir::Location location = RegDescToLocation(regDesc); circt::kanagawa::ContainerInstanceOp::create(opb, - location, + location, circt::hw::InnerSymAttr::get(ClampedSymAttr(containerInstancePath.back())), circt::hw::InnerRefAttr::get(StringToStringAttr(GetCirctDesignName()), leafContainerNameAttr)); @@ -2813,7 +2813,7 @@ class VerilogCompiler opb.setInsertionPointToEnd(parentContainer.getBodyBlock()); circt::kanagawa::ContainerInstanceOp::create(opb, - location, + location, circt::hw::InnerSymAttr::get(ClampedSymAttr(containerInstancePath.back())), circt::hw::InnerRefAttr::get(StringToStringAttr(GetCirctDesignName()), leafContainerNameAttr)); @@ -5537,7 +5537,7 @@ class VerilogCompiler str << "global_out_" << regDesc._name << "_" << registerIndex << "_" << writeIndex; - return str.str(); + return g_compiler->ClampStringLength(str.str()); } std::string GetGlobalValidOutName(const size_t registerIndex, const size_t writeIndex) const @@ -5546,7 +5546,7 @@ class VerilogCompiler result += "_valid"; - return result; + return g_compiler->ClampStringLength(result); } std::string GetGlobalInName(const size_t registerIndex) const @@ -5559,7 +5559,7 @@ class VerilogCompiler str << "global_in_" << regDesc._name << "_" << registerIndex; - return str.str(); + return g_compiler->ClampStringLength(str.str()); } std::string GetGlobalInNextName(const size_t registerIndex) const @@ -5572,7 +5572,7 @@ class VerilogCompiler str << "global_in_" << regDesc._name << "_" << registerIndex << "_next"; - return str.str(); + return g_compiler->ClampStringLength(str.str()); } // Returns the name of the variable that holds a global view value @@ -12411,7 +12411,8 @@ void ModuleInstanceHelper::Generate(circt::OpBuilder *const opbIn) // Use a name hint to ensure the wire generated from this verbatim op // doesn't conflict with a name of a variable declared in another verbatim op verbatimOp->setAttr("sv.namehint", - StringToStringAttr(_instanceName + "_" + port.name.str() + "__circt")); + StringToStringAttr(g_compiler->ClampStringLength( + _instanceName + "_" + port.name.str() + "__circt"))); const mlir::Value input = isClockType ? circt::seq::ToClockOp::create(opb, _location, GetClockType(),