Skip to content

Commit

Permalink
[SV] Add sv.reserve_names op to disallow names (#7024)
Browse files Browse the repository at this point in the history
Introduce an op to specific a list of names which Export Verilog should never use anywhere. Applies to module names, port names, reg/wire/logic names, etc.
  • Loading branch information
teqdruid authored May 14, 2024
1 parent 6fb270b commit f1a822e
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 0 deletions.
16 changes: 16 additions & 0 deletions include/circt/Dialect/SV/SVStatements.td
Original file line number Diff line number Diff line change
Expand Up @@ -879,3 +879,19 @@ def MacroDefOp : SVOp<"macro.def",
MacroDeclOp getReferencedMacro(const hw::HWSymbolCache *cache);
}];
}


//===----------------------------------------------------------------------===//
// SV output control.
//===----------------------------------------------------------------------===//

def ReserveNamesOp : SVOp<"reserve_names", [
HasParent<"mlir::ModuleOp">
]> {
let summary = "Disallow a set of names to be used during emission";

let arguments = (ins StrArrayAttr:$reservedNames);
let assemblyFormat = [{
$reservedNames attr-dict
}];
}
3 changes: 3 additions & 0 deletions lib/Conversion/ExportVerilog/ExportVerilog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6344,6 +6344,9 @@ void SharedEmitterState::gatherFiles(bool separateModules) {
.Case<MacroDeclOp>([&](auto op) {
symbolCache.addDefinition(op.getSymNameAttr(), op);
})
.Case<sv::ReserveNamesOp>([](auto op) {
// This op was already used in gathering used names.
})
.Case<om::ClassLike>([&](auto op) {
symbolCache.addDefinition(op.getSymNameAttr(), op);
})
Expand Down
7 changes: 7 additions & 0 deletions lib/Conversion/ExportVerilog/ExportVerilogInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct LoweringOptions;

namespace ExportVerilog {
class GlobalNameResolver;
struct NameCollisionResolver;

/// Check if the value is from read of a wire or reg or is a port.
bool isSimpleReadOrPort(Value v);
Expand Down Expand Up @@ -57,6 +58,9 @@ struct GlobalNameTable {
return it != enumPrefixes.end() ? it->second : StringAttr();
}

// Add the set of reserved names to a resolver.
void addReservedNames(NameCollisionResolver &nameResolver) const;

private:
friend class GlobalNameResolver;
GlobalNameTable() {}
Expand All @@ -76,6 +80,9 @@ struct GlobalNameTable {
// This contains prefixes for any typedecl'd enum types. Keys are type-aliases
// of enum types.
DenseMap<Type, StringAttr> enumPrefixes;

/// List of names which are marked as reserved for any name.
DenseSet<StringAttr> reservedNames;
};

//===----------------------------------------------------------------------===//
Expand Down
17 changes: 17 additions & 0 deletions lib/Conversion/ExportVerilog/LegalizeNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@ using namespace sv;
using namespace hw;
using namespace ExportVerilog;

//===----------------------------------------------------------------------===//
// GlobalNameTable
//===----------------------------------------------------------------------===//

void GlobalNameTable::addReservedNames(NameCollisionResolver &resolver) const {
for (auto &name : reservedNames)
resolver.insertUsedName(name);
}

//===----------------------------------------------------------------------===//
// NameCollisionResolver
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -134,6 +143,8 @@ static void legalizeModuleLocalNames(HWModuleOp module,
const GlobalNameTable &globalNameTable) {
// A resolver for a local name collison.
NameCollisionResolver nameResolver(options);
globalNameTable.addReservedNames(nameResolver);

// Register names used by parameters.
for (auto param : module.getParameters())
nameResolver.insertUsedName(globalNameTable.getParameterVerilogName(
Expand Down Expand Up @@ -237,6 +248,12 @@ GlobalNameResolver::GlobalNameResolver(mlir::ModuleOp topLevel,
op.emitError("name \"")
<< name << "\" is not allowed in Verilog output";
globalNameResolver.insertUsedName(name);
} else if (auto reservedNamesOp = dyn_cast<sv::ReserveNamesOp>(op)) {
for (StringAttr name :
reservedNamesOp.getReservedNames().getAsRange<StringAttr>()) {
globalNameTable.reservedNames.insert(name);
globalNameResolver.insertUsedName(name);
}
}
}

Expand Down
8 changes: 8 additions & 0 deletions test/Conversion/ExportVerilog/sv-dialect.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
sv.macro.decl @SYNTHESIS
sv.macro.decl @VERILATOR

// CHECK-NOT: module ReservedName1(
// CHECK-NOT: input reservedName2{{$}}
// CHECK-NOT: reg reservedName3;
sv.reserve_names ["ReservedName1", "reservedName2", "reservedName3"]
hw.module @ReservedName1 (in %reservedName2 : i1) {
%reservedName3 = sv.reg : !hw.inout<i1>
}

// CHECK-LABEL: module M1
// CHECK-NEXT: #(parameter [41:0] param1) (
hw.module @M1<param1: i42>(in %clock : i1, in %cond : i1, in %val : i8) {
Expand Down

0 comments on commit f1a822e

Please sign in to comment.