mirror of https://github.com/llvm/circt.git
[FIRRTL] Add force operation
Add a `firrtl.force` operation which properly lowers to the corresponding `sv.force` operation. There is additional discussion in PR #1665 regarding the proliferation of these operations. If we end up replicating a lot of the SV ops in the FIRRTL dialect, we might want to look into ways to use casts and a general scheme to reuse the SV ops to work with the FIRRTL-typed values directly. This change unblocks work on the Grand Central signal driving PR for now, but we'll have to revisit these ops likely in the future.
This commit is contained in:
parent
4fd92559b0
commit
3628ee5f8e
|
@ -184,3 +184,12 @@ def WhenOp : FIRRTLOp<"when", [SingleBlock, NoTerminator, NoRegionArguments,
|
|||
}
|
||||
}];
|
||||
}
|
||||
|
||||
def ForceOp : FIRRTLOp<"force", [SameTypeOperands]> {
|
||||
let summary = "Force procedural statement";
|
||||
let description = "Maps to the corresponding `sv.force` operation.";
|
||||
let arguments = (ins FIRRTLType:$dest, FIRRTLType:$src);
|
||||
let results = (outs);
|
||||
let assemblyFormat =
|
||||
"$dest `,` $src attr-dict `:` type($dest) `,` type($src)";
|
||||
}
|
||||
|
|
|
@ -157,8 +157,8 @@ public:
|
|||
auto *thisCast = static_cast<ConcreteType *>(this);
|
||||
return TypeSwitch<Operation *, ResultType>(op)
|
||||
.template Case<AttachOp, ConnectOp, MemoryPortOp, MemoryPortAccessOp,
|
||||
PartialConnectOp, PrintFOp, SkipOp, StopOp, WhenOp,
|
||||
AssertOp, AssumeOp, CoverOp>(
|
||||
PartialConnectOp, ForceOp, PrintFOp, SkipOp, StopOp,
|
||||
WhenOp, AssertOp, AssumeOp, CoverOp>(
|
||||
[&](auto opNode) -> ResultType {
|
||||
return thisCast->visitStmt(opNode, args...);
|
||||
})
|
||||
|
@ -189,6 +189,7 @@ public:
|
|||
HANDLE(MemoryPortOp);
|
||||
HANDLE(MemoryPortAccessOp);
|
||||
HANDLE(PartialConnectOp);
|
||||
HANDLE(ForceOp);
|
||||
HANDLE(PrintFOp);
|
||||
HANDLE(SkipOp);
|
||||
HANDLE(StopOp);
|
||||
|
|
|
@ -1141,6 +1141,7 @@ struct FIRRTLLowering : public FIRRTLVisitor<FIRRTLLowering, LogicalResult> {
|
|||
LogicalResult visitStmt(SkipOp op);
|
||||
LogicalResult visitStmt(ConnectOp op);
|
||||
LogicalResult visitStmt(PartialConnectOp op);
|
||||
LogicalResult visitStmt(ForceOp op);
|
||||
LogicalResult visitStmt(PrintFOp op);
|
||||
LogicalResult visitStmt(StopOp op);
|
||||
LogicalResult visitStmt(AssertOp op);
|
||||
|
@ -2672,6 +2673,22 @@ LogicalResult FIRRTLLowering::visitStmt(PartialConnectOp op) {
|
|||
return success();
|
||||
}
|
||||
|
||||
LogicalResult FIRRTLLowering::visitStmt(ForceOp op) {
|
||||
auto srcVal = getLoweredValue(op.src());
|
||||
if (!srcVal)
|
||||
return failure();
|
||||
|
||||
auto destVal = getPossiblyInoutLoweredValue(op.dest());
|
||||
if (!destVal)
|
||||
return failure();
|
||||
|
||||
if (!destVal.getType().isa<hw::InOutType>())
|
||||
return op.emitError("destination isn't an inout type");
|
||||
|
||||
addToInitialBlock([&]() { builder.create<sv::ForceOp>(destVal, srcVal); });
|
||||
return success();
|
||||
}
|
||||
|
||||
// Printf is a macro op that lowers to an sv.ifdef.procedural, an sv.if,
|
||||
// and an sv.fwrite all nested together.
|
||||
LogicalResult FIRRTLLowering::visitStmt(PrintFOp op) {
|
||||
|
|
|
@ -845,4 +845,14 @@ firrtl.circuit "Simple" attributes {annotations = [{class =
|
|||
// CHECK: hw.output
|
||||
}
|
||||
|
||||
// CHECK-LABEL: hw.module @Force
|
||||
firrtl.module @Force(in %in: !firrtl.uint<42>) {
|
||||
// CHECK: %out = sv.wire : !hw.inout<i42>
|
||||
// CHECK: sv.initial {
|
||||
// CHECK: sv.force %out, %in : i42
|
||||
// CHECK: }
|
||||
%out = firrtl.wire : !firrtl.uint<42>
|
||||
firrtl.force %out, %in : !firrtl.uint<42>, !firrtl.uint<42>
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue