mirror of https://github.com/llvm/circt.git
[SV] Add NonProceduralOp trait (#735)
* [SV] Add NonProceduralOp trait * add tests * add wire op * clang-format * clang-format
This commit is contained in:
parent
98fc54cfa8
commit
565d4595c4
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.";
|
||||
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -85,3 +85,43 @@ rtl.module @CaseZ(%arg8: i8) {
|
|||
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>
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue