21 #include "mlir/Transforms/DialectConversion.h"
23 using namespace circt;
28 struct PrepareSchedulingPass
29 :
public IbisPrepareSchedulingBase<PrepareSchedulingPass> {
30 void runOnOperation()
override;
34 pipeline::UnscheduledPipelineOp prepareSBlock(IsolatedStaticBlockOp sblock);
39 LogicalResult attachOperatorTypes(pipeline::UnscheduledPipelineOp pipeline);
43 pipeline::UnscheduledPipelineOp
44 PrepareSchedulingPass::prepareSBlock(IsolatedStaticBlockOp sblock) {
45 Location loc = sblock.getLoc();
46 Block *bodyBlock = sblock.getBodyBlock();
47 auto b = OpBuilder::atBlockBegin(bodyBlock);
48 auto ph = b.create<ibis::PipelineHeaderOp>(loc);
52 auto sblockRet = cast<BlockReturnOp>(bodyBlock->getTerminator());
53 auto retTypes = sblockRet.getOperandTypes();
56 SmallVector<Attribute> inNames, outNames;
57 for (
size_t i = 0, e = bodyBlock->getNumArguments(); i < e; ++i)
58 inNames.push_back(b.getStringAttr(
"in" + std::to_string(i)));
59 for (
size_t i = 0, e = retTypes.size(); i < e; ++i)
60 outNames.push_back(b.getStringAttr(
"out" + std::to_string(i)));
62 auto pipeline = b.create<pipeline::UnscheduledPipelineOp>(
63 loc, retTypes, bodyBlock->getArguments(), b.getArrayAttr(inNames),
64 b.getArrayAttr(outNames), ph.getClock(), ph.getReset(), ph.getGo(),
66 b.setInsertionPointToEnd(pipeline.getEntryStage());
74 auto pipelineRet = b.create<pipeline::ReturnOp>(loc, sblockRet.getOperands());
75 for (
size_t i = 0, e = retTypes.size(); i < e; ++i)
76 sblockRet.setOperand(i, pipeline.getResult(i));
80 for (
auto [sbArg, plArg] :
81 llvm::zip(bodyBlock->getArguments(),
82 pipeline.getEntryStage()->getArguments())) {
83 sbArg.replaceAllUsesExcept(plArg, pipeline);
90 llvm::SmallVector<Operation *> opsToMove;
91 llvm::transform(bodyBlock->getOperations(), std::back_inserter(opsToMove),
92 [&](Operation &op) { return &op; });
94 ArrayRef(opsToMove.begin(), opsToMove.end()).drop_front(2).drop_back())
95 op->moveBefore(pipelineRet);
100 LogicalResult PrepareSchedulingPass::attachOperatorTypes(
101 pipeline::UnscheduledPipelineOp pipeline) {
102 for (Operation &op : *pipeline.getEntryStage()) {
103 if (op.hasAttr(
"ssp.operator_type"))
107 if (isa<pipeline::ReturnOp>(op) || op.hasTrait<OpTrait::ConstantLike>())
125 void PrepareSchedulingPass::runOnOperation() {
126 pipeline::UnscheduledPipelineOp pipeline = prepareSBlock(getOperation());
127 if (failed(attachOperatorTypes(pipeline)))
128 return signalPassFailure();
132 return std::make_unique<PrepareSchedulingPass>();
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
static constexpr const char * kIbisOperatorLibName
std::unique_ptr< mlir::Pass > createPrepareSchedulingPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.