13 #include "mlir/IR/PatternMatch.h"
14 #include "mlir/Pass/Pass.h"
15 #include "mlir/Transforms/GreedyPatternRewriteDriver.h"
17 #define DEBUG_TYPE "arc-latency-retiming"
21 #define GEN_PASS_DEF_LATENCYRETIMING
22 #include "circt/Dialect/Arc/ArcPasses.h.inc"
26 using namespace circt;
34 struct LatencyRetimingStatistics {
35 unsigned numOpsRemoved = 0;
36 unsigned latencyUnitsSaved = 0;
42 LatencyRetimingPattern(MLIRContext *context,
SymbolCache &symCache,
43 LatencyRetimingStatistics &statistics)
45 statistics(statistics) {}
47 LogicalResult matchAndRewrite(StateOp op,
48 PatternRewriter &rewriter)
const final;
52 LatencyRetimingStatistics &statistics;
58 LatencyRetimingPattern::matchAndRewrite(StateOp op,
59 PatternRewriter &rewriter)
const {
60 unsigned minPrevLatency = UINT_MAX;
61 SetVector<StateOp> predecessors;
63 if (op.getReset() || op.getEnable())
66 for (
auto input : op.getInputs()) {
67 auto predState = input.getDefiningOp<StateOp>();
71 if (predState->hasAttr(
"name") || predState->hasAttr(
"names"))
77 if (predState.getLatency() != 0 && op.getLatency() != 0 &&
78 predState.getClock() != op.getClock())
81 if (predState.getEnable() || predState.getReset())
84 if (llvm::any_of(predState->getUsers(),
85 [&](
auto *user) { return user != op; }))
88 predecessors.insert(predState);
89 minPrevLatency = std::min(minPrevLatency, predState.getLatency());
92 if (minPrevLatency == 0 || minPrevLatency == UINT_MAX)
95 op.setLatency(op.getLatency() + minPrevLatency);
96 for (
auto prevStateOp : predecessors) {
97 if (!op.getClock() && !op->getParentOfType<ClockDomainOp>())
98 op.getClockMutable().assign(prevStateOp.getClock());
100 statistics.latencyUnitsSaved += minPrevLatency;
101 auto newLatency = prevStateOp.getLatency() - minPrevLatency;
102 prevStateOp.setLatency(newLatency);
107 prevStateOp.getClockMutable().clear();
108 if (cast<DefineOp>(symCache.getDefinition(prevStateOp.getArcAttr()))
110 rewriter.replaceOp(prevStateOp, prevStateOp.getInputs());
111 ++statistics.numOpsRemoved;
114 statistics.latencyUnitsSaved -= minPrevLatency;
124 struct LatencyRetimingPass
125 : arc::impl::LatencyRetimingBase<LatencyRetimingPass> {
126 void runOnOperation()
override;
130 void LatencyRetimingPass::runOnOperation() {
134 LatencyRetimingStatistics statistics;
136 RewritePatternSet
patterns(&getContext());
137 patterns.add<LatencyRetimingPattern>(&getContext(), cache, statistics);
139 if (failed(applyPatternsAndFoldGreedily(getOperation(), std::move(
patterns))))
140 return signalPassFailure();
142 numOpsRemoved = statistics.numOpsRemoved;
143 latencyUnitsSaved = statistics.latencyUnitsSaved;
147 return std::make_unique<LatencyRetimingPass>();
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
Default symbol cache implementation; stores associations between names (StringAttr's) to mlir::Operat...
std::unique_ptr< mlir::Pass > createLatencyRetimingPass()
This file defines an intermediate representation for circuits acting as an abstraction for constraint...