1414#include " circt/Support/Namespace.h"
1515#include " mlir/IR/PatternMatch.h"
1616#include " mlir/Pass/Pass.h"
17+ #include " mlir/Transforms/RegionUtils.h"
1718#include " llvm/Support/Debug.h"
1819
1920#define DEBUG_TYPE " convert-to-arcs"
@@ -22,13 +23,17 @@ using namespace circt;
2223using namespace arc ;
2324using namespace hw ;
2425using llvm::MapVector;
26+ using llvm::SmallSetVector;
2527
2628static bool isArcBreakingOp (Operation *op) {
29+ if (isa<TapOp>(op))
30+ return false ;
2731 return op->hasTrait <OpTrait::ConstantLike>() ||
2832 isa<hw::InstanceOp, seq::CompRegOp, MemoryOp, MemoryReadPortOp,
2933 ClockedOpInterface, seq::InitialOp, seq::ClockGateOp,
3034 sim::DPICallOp>(op) ||
31- op->getNumResults () > 1 ;
35+ op->getNumResults () > 1 || op->getNumRegions () > 0 ||
36+ !mlir::isMemoryEffectFree (op);
3237}
3338
3439static LogicalResult convertInitialValue (seq::CompRegOp reg,
@@ -102,8 +107,6 @@ LogicalResult Converter::runOnModule(HWModuleOp module) {
102107 for (Operation &op : *module .getBodyBlock ()) {
103108 if (isa<seq::InitialOp>(&op))
104109 continue ;
105- if (op.getNumRegions () > 0 )
106- return op.emitOpError (" has regions; not supported by ConvertToArcs" );
107110 if (!isArcBreakingOp (&op) && !isa<hw::OutputOp>(&op))
108111 continue ;
109112 arcBreakerIndices[&op] = arcBreakers.size ();
@@ -132,32 +135,40 @@ LogicalResult Converter::runOnModule(HWModuleOp module) {
132135}
133136
134137LogicalResult Converter::analyzeFanIn () {
135- SmallVector<std::tuple<Operation *, unsigned >> worklist;
138+ SmallVector<std::tuple<Operation *, SmallVector<Value, 2 >>> worklist;
139+ SetVector<Value> seenOperands;
140+ auto addToWorklist = [&](Operation *op) {
141+ seenOperands.clear ();
142+ for (auto operand : op->getOperands ())
143+ seenOperands.insert (operand);
144+ mlir::getUsedValuesDefinedAbove (op->getRegions (), seenOperands);
145+ worklist.emplace_back (op, seenOperands.getArrayRef ());
146+ };
136147
137148 // Seed the worklist and fanin masks with the arc breaking operations.
138149 faninMasks.clear ();
139150 for (auto *op : arcBreakers) {
140151 unsigned index = arcBreakerIndices.lookup (op);
141152 auto mask = APInt::getOneBitSet (arcBreakers.size (), index);
142153 faninMasks[op] = mask;
143- worklist. push_back ({op, 0 } );
154+ addToWorklist (op );
144155 }
145156
146157 // Establish a post-order among the operations.
147158 DenseSet<Operation *> seen;
148159 DenseSet<Operation *> finished;
149160 postOrder.clear ();
150161 while (!worklist.empty ()) {
151- auto &[op, operandIdx ] = worklist.back ();
152- if (operandIdx == op-> getNumOperands ()) {
162+ auto &[op, operands ] = worklist.back ();
163+ if (operands. empty ()) {
153164 if (!isArcBreakingOp (op) && !isa<hw::OutputOp>(op))
154165 postOrder.push_back (op);
155166 finished.insert (op);
156167 seen.erase (op);
157168 worklist.pop_back ();
158169 continue ;
159170 }
160- auto operand = op-> getOperand (operandIdx++ ); // advance to next operand
171+ auto operand = operands. pop_back_val ( ); // advance to next operand
161172 auto *definingOp = operand.getDefiningOp ();
162173 if (!definingOp || isArcBreakingOp (definingOp) ||
163174 finished.contains (definingOp))
@@ -166,7 +177,7 @@ LogicalResult Converter::analyzeFanIn() {
166177 definingOp->emitError (" combinational loop detected" );
167178 return failure ();
168179 }
169- worklist. push_back ({ definingOp, 0 } );
180+ addToWorklist ( definingOp);
170181 }
171182 LLVM_DEBUG (llvm::dbgs () << " - Sorted " << postOrder.size () << " ops\n " );
172183
@@ -177,6 +188,8 @@ LogicalResult Converter::analyzeFanIn() {
177188 for (auto *op : llvm::reverse (postOrder)) {
178189 auto mask = APInt::getZero (arcBreakers.size ());
179190 for (auto *user : op->getUsers ()) {
191+ while (user->getParentOp () != op->getParentOp ())
192+ user = user->getParentOp ();
180193 auto it = faninMasks.find (user);
181194 if (it != faninMasks.end ())
182195 mask |= it->second ;
0 commit comments