15 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
16 #include "mlir/IR/PatternMatch.h"
17 #include "mlir/IR/Visitors.h"
18 #include "mlir/Pass/Pass.h"
22 #define GEN_PASS_DEF_PROCESSLOWERING
23 #include "circt/Dialect/LLHD/Transforms/Passes.h.inc"
28 using namespace circt;
32 struct ProcessLoweringPass
33 :
public circt::llhd::impl::ProcessLoweringBase<ProcessLoweringPass> {
34 void runOnOperation()
override;
41 static LogicalResult checkSignalsAreObserved(OperandRange obs, Value value) {
43 if (llvm::is_contained(obs, value))
46 if (Operation *op = value.getDefiningOp()) {
50 if (llvm::none_of(op->getOperands(), [](Value arg) {
51 return isa<hw::InOutType>(arg.getType());
59 return success(llvm::all_of(op->getOperands(), [&](Value arg) {
60 return !isa<hw::InOutType>(arg.getType()) ||
61 succeeded(checkSignalsAreObserved(obs, arg));
71 static LogicalResult isProcValidToLower(llhd::ProcessOp op) {
72 size_t numBlocks = op.getBody().getBlocks().size();
75 if (!isa<llhd::HaltOp>(op.getBody().back().getTerminator()))
76 return op.emitOpError(
"during process-lowering: entry block is required "
77 "to be terminated by llhd.halt");
82 Block &first = op.getBody().front();
83 Block &last = op.getBody().back();
85 if (!last.getArguments().empty())
86 return op.emitOpError(
87 "during process-lowering: the second block (containing the "
88 "llhd.wait) is not allowed to have arguments");
90 if (!isa<cf::BranchOp>(first.getTerminator()))
91 return op.emitOpError(
"during process-lowering: the first block has to "
92 "be terminated by a cf.br operation");
94 if (
auto wait = dyn_cast<llhd::WaitOp>(last.getTerminator())) {
97 return wait.emitOpError(
98 "during process-lowering: llhd.wait terminators with optional time "
99 "argument cannot be lowered to structural LLHD");
103 WalkResult result = op.walk([&wait](llhd::PrbOp prbOp) -> WalkResult {
104 if (failed(checkSignalsAreObserved(wait.getObs(), prbOp.getSignal())))
105 return wait.emitOpError(
106 "during process-lowering: the wait terminator is required to "
107 "have all probed signals as arguments");
109 return WalkResult::advance();
111 return failure(result.wasInterrupted());
114 return op.emitOpError(
"during process-lowering: the second block must be "
115 "terminated by llhd.wait");
118 return op.emitOpError(
119 "process-lowering only supports processes with either one basic block "
120 "terminated by a llhd.halt operation or two basic blocks where the first "
121 "one contains a cf.br terminator and the second one is terminated by a "
122 "llhd.wait operation");
125 void ProcessLoweringPass::runOnOperation() {
126 ModuleOp module = getOperation();
128 WalkResult result = module.walk([](llhd::ProcessOp op) -> WalkResult {
130 if (failed(isProcValidToLower(op)))
131 return WalkResult::interrupt();
136 if (op.getBody().getBlocks().size() == 2) {
137 Block &first = op.getBody().front();
138 Block &second = op.getBody().back();
140 first.getTerminator()->erase();
142 first.getOperations().splice(first.end(), second.getOperations());
144 second.dropAllReferences();
145 second.dropAllDefinedValueUses();
150 op.getBody().front().getTerminator()->erase();
152 IRRewriter rewriter(op);
153 rewriter.inlineBlockBefore(&op.getBody().front(), op);
156 return WalkResult::advance();
159 if (result.wasInterrupted())
164 std::unique_ptr<OperationPass<ModuleOp>>
166 return std::make_unique<ProcessLoweringPass>();
std::unique_ptr< OperationPass< ModuleOp > > createProcessLoweringPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.