[SV] Add NonProceduralOp trait (#735)

* [SV] Add NonProceduralOp trait

* add tests

* add wire op

* clang-format

* clang-format
This commit is contained in:
Hideto Ueno 2021-03-09 00:08:08 +09:00 committed by GitHub
parent 98fc54cfa8
commit 565d4595c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 74 additions and 5 deletions

View File

@ -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"

View File

@ -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<OpAsmOpInterface>]> {
def WireOp : SVOp<"wire", [DeclareOpInterfaceMethods<OpAsmOpInterface>,
NonProceduralOp]> {
let summary = "Define a new wire";
let description = [{
Declare a SystemVerilog Net Declaration of 'wire' type.

View File

@ -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 <typename ConcreteType>
@ -46,6 +48,17 @@ public:
}
};
/// This class verifies that the specified op is not located in a procedural
/// region.
template <typename ConcreteType>
class NonProceduralOp
: public mlir::OpTrait::TraitBase<ConcreteType, NonProceduralOp> {
public:
static LogicalResult verifyTrait(Operation *op) {
return verifyInNonProceduralRegion(op);
}
};
} // namespace sv
} // namespace circt

View File

@ -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.";

View File

@ -35,6 +35,13 @@ LogicalResult sv::verifyInProceduralRegion(Operation *op) {
return failure();
}
LogicalResult sv::verifyInNonProceduralRegion(Operation *op) {
if (!op->getParentOp()->hasTrait<sv::ProceduralRegion>())
return success();
op->emitError() << op->getName() << " should be in a non-procedural region";
return failure();
}
//===----------------------------------------------------------------------===//
// ImplicitSSAName Custom Directive
//===----------------------------------------------------------------------===//

View File

@ -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<i1>
}
}