16 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
17 #include "mlir/IR/Visitors.h"
20 using namespace circt;
24 struct ProcessLoweringPass
25 :
public llhd::ProcessLoweringBase<ProcessLoweringPass> {
26 void runOnOperation()
override;
33 static LogicalResult checkSignalsAreObserved(OperandRange obs, Value
value) {
35 if (llvm::is_contained(obs,
value))
38 if (Operation *op =
value.getDefiningOp()) {
42 if (llvm::none_of(op->getOperands(), [](Value arg) {
43 return arg.getType().isa<llhd::SigType>();
51 return success(llvm::all_of(op->getOperands(), [&](Value arg) {
52 return !arg.getType().isa<llhd::SigType>() ||
53 succeeded(checkSignalsAreObserved(obs, arg));
63 static LogicalResult isProcValidToLower(llhd::ProcOp op) {
64 size_t numBlocks = op.getBody().getBlocks().size();
67 if (!isa<llhd::HaltOp>(op.getBody().back().getTerminator()))
68 return op.emitOpError(
"during process-lowering: entry block is required "
69 "to be terminated by llhd.halt");
74 Block &first = op.getBody().front();
75 Block &last = op.getBody().back();
77 if (last.getArguments().size() != 0)
78 return op.emitOpError(
79 "during process-lowering: the second block (containing the "
80 "llhd.wait) is not allowed to have arguments");
82 if (!isa<cf::BranchOp>(first.getTerminator()))
83 return op.emitOpError(
"during process-lowering: the first block has to "
84 "be terminated by a cf.br operation");
86 if (
auto wait = dyn_cast<llhd::WaitOp>(last.getTerminator())) {
89 return wait.emitOpError(
90 "during process-lowering: llhd.wait terminators with optional time "
91 "argument cannot be lowered to structural LLHD");
95 WalkResult result = op.walk([&wait](llhd::PrbOp prbOp) -> WalkResult {
96 if (failed(checkSignalsAreObserved(wait.getObs(), prbOp.getSignal())))
97 return wait.emitOpError(
98 "during process-lowering: the wait terminator is required to "
99 "have all probed signals as arguments");
101 return WalkResult::advance();
103 return failure(result.wasInterrupted());
106 return op.emitOpError(
"during process-lowering: the second block must be "
107 "terminated by llhd.wait");
110 return op.emitOpError(
111 "process-lowering only supports processes with either one basic block "
112 "terminated by a llhd.halt operation or two basic blocks where the first "
113 "one contains a cf.br terminator and the second one is terminated by a "
114 "llhd.wait operation");
117 void ProcessLoweringPass::runOnOperation() {
118 ModuleOp module = getOperation();
120 WalkResult result = module.walk([](llhd::ProcOp op) -> WalkResult {
122 if (failed(isProcValidToLower(op)))
123 return WalkResult::interrupt();
128 llhd::EntityOp entity =
129 builder.create<llhd::EntityOp>(op.getLoc(), op.getFunctionType(),
130 op.getIns(), ArrayAttr(),
134 entity.setName(op.getName());
137 entity.getBody().takeBody(op.getBody());
141 if (entity.getBody().getBlocks().size() == 2) {
142 Block &first = entity.getBody().front();
143 Block &second = entity.getBody().back();
145 first.getTerminator()->dropAllReferences();
146 first.getTerminator()->erase();
148 first.getOperations().splice(first.end(), second.getOperations());
150 second.dropAllReferences();
151 second.dropAllDefinedValueUses();
156 op->dropAllReferences();
157 op->dropAllDefinedValueUses();
161 Operation *terminator = entity.getBody().front().getTerminator();
162 terminator->dropAllReferences();
163 terminator->dropAllUses();
166 return WalkResult::advance();
169 if (result.wasInterrupted())
174 std::unique_ptr<OperationPass<ModuleOp>>
176 return std::make_unique<ProcessLoweringPass>();
std::unique_ptr< OperationPass< ModuleOp > > createProcessLoweringPass()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...