From 88f6df3a4212c1ed8dc21075450071ed26941717 Mon Sep 17 00:00:00 2001 From: woshiren Date: Wed, 27 May 2026 21:53:22 +0800 Subject: [PATCH] [Sim] Add Sim dialect declarations and reads for externally controlled configuration bits --- include/circt/Dialect/Sim/SimOps.td | 30 +++++++++++++++++++++++++++++ lib/Dialect/Sim/SimOps.cpp | 12 ++++++++++++ test/Dialect/Sim/round-trip.mlir | 13 +++++++++++++ test/Dialect/Sim/sim-errors.mlir | 16 +++++++++++++++ 4 files changed, 71 insertions(+) diff --git a/include/circt/Dialect/Sim/SimOps.td b/include/circt/Dialect/Sim/SimOps.td index 265ee5732c8a..01d1d7ab0014 100644 --- a/include/circt/Dialect/Sim/SimOps.td +++ b/include/circt/Dialect/Sim/SimOps.td @@ -45,6 +45,36 @@ def DPIDirection : I32EnumAttr<"DPIDirection", // Simulation Operations //===----------------------------------------------------------------------===// +def ConfigDeclOp : SimOp<"config.decl", + [Symbol, HasParent<"mlir::ModuleOp">]> { + let summary = "Declare an externally controlled simulation value"; + let description = [{ + Declares a named configuration value for simulation-related behavior. The + concrete mechanism used to override the value is backend-defined and may be + a preprocessor macro, a plusarg, a parameter, or another backend-specific + facility. If no override is provided, the configuration value has the given + default value. + }]; + + let arguments = (ins SymbolNameAttr:$sym_name, BoolAttr:$defaultValue); + let assemblyFormat = "$sym_name `default` $defaultValue attr-dict"; +} + +def ConfigGetOp : SimOp<"config.get", + [Pure, DeclareOpInterfaceMethods]> { + let summary = "Read an externally controlled simulation value"; + let description = [{ + Reads a named configuration value declared by `sim.config.decl`. The result + is an SSA value that can be used to guard simulation, verification, or other + behavior. The operation does not prescribe whether the value is provided by + a compile-time, elaboration-time, or runtime mechanism. + }]; + + let arguments = (ins FlatSymbolRefAttr:$config); + let results = (outs I1:$result); + let assemblyFormat = "$config attr-dict"; +} + def PlusArgsTestOp : SimOp<"plusargs.test", [Pure]> { let summary = "SystemVerilog `$test$plusargs` call"; diff --git a/lib/Dialect/Sim/SimOps.cpp b/lib/Dialect/Sim/SimOps.cpp index d1e17bbfccc3..ec63a48bc03b 100644 --- a/lib/Dialect/Sim/SimOps.cpp +++ b/lib/Dialect/Sim/SimOps.cpp @@ -204,6 +204,18 @@ LogicalResult DPIFuncOp::verify() { return success(); } +LogicalResult +sim::ConfigGetOp::verifySymbolUses(SymbolTableCollection &symbolTable) { + auto referencedOp = + symbolTable.lookupNearestSymbolFrom(*this, getConfigAttr()); + if (!referencedOp) + return emitError("cannot find config declaration '") << getConfig() << "'"; + if (!isa(referencedOp)) + return emitError("config must reference 'sim.config.decl' but got '") + << referencedOp->getName() << "'"; + return success(); +} + LogicalResult sim::DPICallOp::verifySymbolUses(SymbolTableCollection &symbolTable) { auto referencedOp = diff --git a/test/Dialect/Sim/round-trip.mlir b/test/Dialect/Sim/round-trip.mlir index 2e1062037272..2fa313cb22e2 100644 --- a/test/Dialect/Sim/round-trip.mlir +++ b/test/Dialect/Sim/round-trip.mlir @@ -8,6 +8,19 @@ hw.module @plusargs_value() { %1, %2 = sim.plusargs.value "bar" : i5 } +// CHECK-LABEL: sim.config.decl @PRINTF_COND default true +sim.config.decl @PRINTF_COND default true +// CHECK-LABEL: sim.config.decl @STOP_COND default false +sim.config.decl @STOP_COND default false + +// CHECK-LABEL: hw.module @config_get +hw.module @config_get() { + // CHECK: sim.config.get @PRINTF_COND + %0 = sim.config.get @PRINTF_COND + // CHECK: sim.config.get @STOP_COND + %1 = sim.config.get @STOP_COND +} + // CHECK-LABEL: sim.func.dpi @dpi(out arg0 : i1, in %arg1 : i1, return ret : i1) sim.func.dpi @dpi(out arg0: i1, in %arg1: i1, return ret: i1) // CHECK-LABEL: sim.func.dpi @dpi_inout(in %arg0 : i1, inout %arg1 : i1) diff --git a/test/Dialect/Sim/sim-errors.mlir b/test/Dialect/Sim/sim-errors.mlir index 2d97b4bce9fd..d59b87e60c91 100644 --- a/test/Dialect/Sim/sim-errors.mlir +++ b/test/Dialect/Sim/sim-errors.mlir @@ -140,3 +140,19 @@ hw.module @queue_from_array(in %uparr: !hw.array<5xi33>) { // expected-error @below {{'sim.queue.from_array' op sim::Queue element type 'i32' doesn't match hw::ArrayType element type 'i33'}} sim.queue.from_array %uparr : !hw.array<5xi33> -> } + +// ----- + +hw.module @config_get() { + // expected-error @below {{cannot find config declaration 'PRINTF_COND'}} + sim.config.get @PRINTF_COND +} + +// ----- + +sv.macro.decl @PRINTF_COND + +hw.module @config_get() { + // expected-error @below {{config must reference 'sim.config.decl' but got 'sv.macro.decl'}} + sim.config.get @PRINTF_COND +}