Skip to content

Commit a310c05

Browse files
committed
[ConvertToArcs] Allow ops with regions
Tweak the ConvertToArcs pass to allow operations with regions. The pass would just give up on these ops until now. However, in most cases we can handle these ops just fine, as long as we take care to properly gather all values used in nested operations. Also mark all side-effecting ops as arc breakers, to prevent them from being gobbled up into arc defines, where the verifier would be unhappy about them.
1 parent a71e160 commit a310c05

File tree

4 files changed

+47
-17
lines changed

4 files changed

+47
-17
lines changed

lib/Conversion/ConvertToArcs/ConvertToArcs.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
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;
2223
using namespace arc;
2324
using namespace hw;
2425
using llvm::MapVector;
26+
using llvm::SmallSetVector;
2527

2628
static 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

3439
static 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

134137
LogicalResult 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;

test/Conversion/ConvertToArcs/convert-to-arcs-errors.mlir

Lines changed: 0 additions & 8 deletions
This file was deleted.

test/Conversion/ConvertToArcs/convert-to-arcs.mlir

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,26 @@ hw.module @ObserveWires(in %in1: i32, in %in2: i32, out out: i32) {
291291
// CHECK-DAG: [[RES:%.+]]:2 = arc.call @[[ARC_NAME]]({{.*}}) :
292292
// CHECK-DAG: arc.tap [[RES]]#0 {name = "z"} : i32
293293
// CHECK: hw.output %0#1 : i32
294+
295+
// CHECK: arc.define [[ARC_ADD:@OpsWithRegions.+]](
296+
// CHECK-NEXT: comb.add
297+
298+
// CHECK: arc.define [[ARC_SUB:@OpsWithRegions.+]](
299+
// CHECK-NEXT: comb.sub
300+
301+
// CHECK: hw.module @OpsWithRegions
302+
hw.module @OpsWithRegions(in %a: i42, in %b: i42, in %c: i42, in %d: i42, out z: i42) {
303+
// CHECK-DAG: [[ADD:%.+]] = arc.call [[ARC_ADD]](%a, %b)
304+
%0 = comb.add %a, %b : i42
305+
// CHECK-DAG: [[COMB:%.+]] = llhd.combinational -> i42 {
306+
// CHECK-DAG: [[MUL:%.+]] = comb.mul [[ADD]], %c
307+
// CHECK-DAG: llhd.yield [[MUL]]
308+
%1 = llhd.combinational -> i42 {
309+
%3 = comb.mul %0, %c : i42
310+
llhd.yield %3 : i42
311+
}
312+
// CHECK-DAG: [[SUB:%.+]] = arc.call [[ARC_SUB]]([[COMB]], %d)
313+
%2 = comb.sub %1, %d : i42
314+
// CHECK: hw.output [[SUB]]
315+
hw.output %2 : i42
316+
}

tools/arcilator/arcilator.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "circt/Conversion/ArcToLLVM.h"
1515
#include "circt/Conversion/CombToArith.h"
1616
#include "circt/Conversion/ConvertToArcs.h"
17+
#include "circt/Conversion/Passes.h"
1718
#include "circt/Conversion/SeqToSV.h"
1819
#include "circt/Dialect/Arc/ArcDialect.h"
1920
#include "circt/Dialect/Arc/ArcInterfaces.h"
@@ -639,6 +640,7 @@ int main(int argc, char **argv) {
639640

640641
// Dialect passes:
641642
arc::registerPasses();
643+
registerConvertToArcs();
642644
}
643645

644646
// Register any pass manager command line options.

0 commit comments

Comments
 (0)