CIRCT 20.0.0git
Loading...
Searching...
No Matches
LockFunctions.cpp
Go to the documentation of this file.
1//===- LockFunctions.cpp - lock functions pass ------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Contains the definitions of the lock functions pass.
10//
11//===----------------------------------------------------------------------===//
12
16#include "mlir/IR/PatternMatch.h"
17#include "mlir/Pass/Pass.h"
18#include "mlir/Rewrite/FrozenRewritePatternSet.h"
19#include "mlir/Transforms/DialectConversion.h"
20
21namespace circt {
22namespace handshake {
23#define GEN_PASS_DEF_HANDSHAKELOCKFUNCTIONS
24#include "circt/Dialect/Handshake/HandshakePasses.h.inc"
25} // namespace handshake
26} // namespace circt
27
28using namespace circt;
29using namespace handshake;
30using namespace mlir;
31
32/// Adds a locking mechanism around the region.
33static LogicalResult lockRegion(Region &r, OpBuilder &rewriter) {
34 Block *entry = &r.front();
35 Location loc = r.getLoc();
36
37 if (entry->getNumArguments() == 0)
38 return r.getParentOp()->emitError("cannot lock a region without arguments");
39
40 auto *ret = r.front().getTerminator();
41 if (ret->getNumOperands() == 0)
42 return r.getParentOp()->emitError("cannot lock a region without results");
43
44 rewriter.setInsertionPointToStart(entry);
45 BackedgeBuilder bebuilder(rewriter, loc);
46 auto backEdge = bebuilder.get(rewriter.getNoneType());
47
48 auto buff = rewriter.create<handshake::BufferOp>(loc, backEdge, 1,
49 BufferTypeEnum::seq);
50
51 // Dummy value that causes a buffer initialization, but itself does not have a
52 // semantic meaning.
53 buff->setAttr("initValues", rewriter.getI64ArrayAttr({0}));
54
55 SmallVector<Value> inSyncOperands =
56 llvm::to_vector_of<Value>(entry->getArguments());
57 inSyncOperands.push_back(buff);
58 auto sync = rewriter.create<SyncOp>(loc, inSyncOperands);
59
60 // replace all func arg usages with the synced ones
61 // TODO is this UB?
62 for (auto &&[arg, synced] :
63 llvm::drop_end(llvm::zip(inSyncOperands, sync.getResults())))
64 arg.replaceAllUsesExcept(synced, sync);
65
66 rewriter.setInsertionPoint(ret);
67 SmallVector<Value> endJoinOperands = llvm::to_vector(ret->getOperands());
68 // Add the axilirary control signal output to the end-join
69 endJoinOperands.push_back(sync.getResults().back());
70 auto endJoin = rewriter.create<JoinOp>(loc, endJoinOperands);
71
72 backEdge.setValue(endJoin);
73 return success();
74}
75
76namespace {
77
78struct HandshakeLockFunctionsPass
79 : public circt::handshake::impl::HandshakeLockFunctionsBase<
80 HandshakeLockFunctionsPass> {
81 void runOnOperation() override {
82 handshake::FuncOp op = getOperation();
83 if (op.isExternal())
84 return;
85
86 OpBuilder builder(op);
87 if (failed(lockRegion(op.getRegion(), builder)))
88 signalPassFailure();
89 };
90};
91} // namespace
92
93std::unique_ptr<mlir::Pass>
95 return std::make_unique<HandshakeLockFunctionsPass>();
96}
static LogicalResult lockRegion(Region &r, OpBuilder &rewriter)
Adds a locking mechanism around the region.
Instantiate one of these and use it to build typed backedges.
Backedge get(mlir::Type resultType, mlir::LocationAttr optionalLoc={})
Create a typed backedge.
std::unique_ptr< mlir::Pass > createHandshakeLockFunctionsPass()
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.