From 565d4595c481ac77510366e3c25f7e27592ff0bb Mon Sep 17 00:00:00 2001 From: Hideto Ueno Date: Tue, 9 Mar 2021 00:08:08 +0900 Subject: [PATCH] [SV] Add NonProceduralOp trait (#735) * [SV] Add NonProceduralOp trait * add tests * add wire op * clang-format * clang-format --- include/circt/Dialect/SV/SV.td | 4 +++ include/circt/Dialect/SV/SVInOutOps.td | 3 +- include/circt/Dialect/SV/SVOps.h | 13 ++++++++ include/circt/Dialect/SV/SVStatements.td | 12 ++++--- lib/Dialect/SV/SVOps.cpp | 7 +++++ test/Dialect/SV/errors.mlir | 40 ++++++++++++++++++++++++ 6 files changed, 74 insertions(+), 5 deletions(-) diff --git a/include/circt/Dialect/SV/SV.td b/include/circt/Dialect/SV/SV.td index 2c57a99686..5ad817fd9b 100644 --- a/include/circt/Dialect/SV/SV.td +++ b/include/circt/Dialect/SV/SV.td @@ -42,6 +42,10 @@ def ProceduralOp : NativeOpTrait<"ProceduralOp"> { let cppNamespace = "::circt::sv"; } +def NonProceduralOp : NativeOpTrait<"NonProceduralOp"> { + let cppNamespace = "::circt::sv"; +} + include "SVTypes.td" include "SVExpressions.td" include "SVInOutOps.td" diff --git a/include/circt/Dialect/SV/SVInOutOps.td b/include/circt/Dialect/SV/SVInOutOps.td index d1f37b7472..50778b50f3 100644 --- a/include/circt/Dialect/SV/SVInOutOps.td +++ b/include/circt/Dialect/SV/SVInOutOps.td @@ -26,7 +26,8 @@ def ConnectOp : SVOp<"connect", [InOutTypeConstraint<"src", "dest">]> { } // Note that net declarations like 'wire' should not appear in an always block. -def WireOp : SVOp<"wire", [DeclareOpInterfaceMethods]> { +def WireOp : SVOp<"wire", [DeclareOpInterfaceMethods, + NonProceduralOp]> { let summary = "Define a new wire"; let description = [{ Declare a SystemVerilog Net Declaration of 'wire' type. diff --git a/include/circt/Dialect/SV/SVOps.h b/include/circt/Dialect/SV/SVOps.h index 7dc7d546ab..a4d51f50c6 100644 --- a/include/circt/Dialect/SV/SVOps.h +++ b/include/circt/Dialect/SV/SVOps.h @@ -26,6 +26,8 @@ namespace sv { bool isExpression(Operation *op); /// Return true if the specified operation is in a procedural region. LogicalResult verifyInProceduralRegion(Operation *op); +/// Return true if the specified operation is not in a procedural region. +LogicalResult verifyInNonProceduralRegion(Operation *op); /// Signals that an operations regions are procedural. template @@ -46,6 +48,17 @@ public: } }; +/// This class verifies that the specified op is not located in a procedural +/// region. +template +class NonProceduralOp + : public mlir::OpTrait::TraitBase { +public: + static LogicalResult verifyTrait(Operation *op) { + return verifyInNonProceduralRegion(op); + } +}; + } // namespace sv } // namespace circt diff --git a/include/circt/Dialect/SV/SVStatements.td b/include/circt/Dialect/SV/SVStatements.td index b2cc0093df..38ea2851a7 100644 --- a/include/circt/Dialect/SV/SVStatements.td +++ b/include/circt/Dialect/SV/SVStatements.td @@ -16,7 +16,8 @@ def HasRegionTerminator : SingleBlockImplicitTerminator<"YieldOp">; // Control flow like-operations //===----------------------------------------------------------------------===// -def IfDefOp : SVOp<"ifdef", [HasRegionTerminator, NoRegionArguments]> { +def IfDefOp : SVOp<"ifdef", [HasRegionTerminator, NoRegionArguments, + NonProceduralOp]> { let summary = "'ifdef MACRO' block"; let description = [{ @@ -148,7 +149,8 @@ def EventControlAttr : I32EnumAttr<"EventControl", "edge control trigger", def AlwaysOp : SVOp<"always", [HasRegionTerminator, NoRegionArguments, - RecursiveSideEffects, ProceduralRegion]> { + RecursiveSideEffects, ProceduralRegion, + NonProceduralOp]> { let summary = "'always @' block"; let description = "See SV Spec 9.2, and 9.4.2.2."; @@ -190,7 +192,8 @@ def ResetTypeAttr : I32EnumAttr<"ResetType", "reset type", def AlwaysFFOp : SVOp<"alwaysff", [HasRegionTerminator, NoRegionArguments, - RecursiveSideEffects, ProceduralRegion]> { + RecursiveSideEffects, ProceduralRegion, + NonProceduralOp]> { let summary = "'alwaysff @' block with optional reset"; let description = [{ alwaysff blocks represent always_ff verilog nodes, which enforce inference @@ -233,7 +236,8 @@ def AlwaysFFOp : SVOp<"alwaysff", [HasRegionTerminator, NoRegionArguments, def InitialOp : SVOp<"initial", [HasRegionTerminator, NoRegionArguments, - RecursiveSideEffects, ProceduralRegion]> { + RecursiveSideEffects, ProceduralRegion, + NonProceduralOp]> { let summary = "'initial' block"; let description = "See SV Spec 9.2.1."; diff --git a/lib/Dialect/SV/SVOps.cpp b/lib/Dialect/SV/SVOps.cpp index 0ecc2efbca..ad11edf4e2 100644 --- a/lib/Dialect/SV/SVOps.cpp +++ b/lib/Dialect/SV/SVOps.cpp @@ -35,6 +35,13 @@ LogicalResult sv::verifyInProceduralRegion(Operation *op) { return failure(); } +LogicalResult sv::verifyInNonProceduralRegion(Operation *op) { + if (!op->getParentOp()->hasTrait()) + return success(); + op->emitError() << op->getName() << " should be in a non-procedural region"; + return failure(); +} + //===----------------------------------------------------------------------===// // ImplicitSSAName Custom Directive //===----------------------------------------------------------------------===// diff --git a/test/Dialect/SV/errors.mlir b/test/Dialect/SV/errors.mlir index 97085eff0f..e20396460a 100644 --- a/test/Dialect/SV/errors.mlir +++ b/test/Dialect/SV/errors.mlir @@ -84,4 +84,44 @@ rtl.module @CaseZ(%arg8: i8) { sv.fwrite "z" sv.yield } +} + +// ----- +rtl.module @Initial() { + sv.initial { + // expected-error @+1 {{sv.initial should be in a non-procedural region}} + sv.initial {} + } +} + +// ----- +rtl.module @IfDef() { + sv.initial { + // expected-error @+1 {{sv.ifdef should be in a non-procedural region}} + sv.ifdef "SYNTHESIS" {} + } +} + +// ----- +rtl.module @Always(%arg0: i1) { + sv.initial { + // expected-error @+1 {{sv.always should be in a non-procedural region}} + sv.always posedge %arg0 {} + } +} + +// ----- +rtl.module @AlwaysFF(%arg0: i1) { + sv.initial { + // expected-error @+1 {{sv.alwaysff should be in a non-procedural region}} + sv.alwaysff (posedge %arg0) {} + } +} + +// ----- +rtl.module @Wire() { + sv.initial { + // expected-error @+1 {{sv.wire should be in a non-procedural region}} + %wire = sv.wire : !rtl.inout + } } \ No newline at end of file