24 #include "mlir/Dialect/Arith/IR/Arith.h"
25 #include "mlir/Pass/Pass.h"
26 #include "mlir/Pass/PassManager.h"
27 #include "mlir/Transforms/DialectConversion.h"
28 #include "llvm/Support/MathExtras.h"
32 #define GEN_PASS_DEF_HANDSHAKETODC
33 #include "circt/Conversion/Passes.h.inc"
37 using namespace circt;
41 using namespace handshaketodc;
47 DCTuple(Value token, Value
data) : token(token),
data(
data) {}
48 DCTuple(dc::UnpackOp unpack)
49 : token(unpack.getToken()),
data(unpack.getOutput()) {}
55 static DCTuple unpack(OpBuilder &b, Value v) {
56 if (isa<dc::ValueType>(v.getType()))
57 return DCTuple(b.create<dc::UnpackOp>(v.getLoc(), v));
58 assert(isa<dc::TokenType>(v.getType()) &&
"Expected a dc::TokenType");
59 return DCTuple(v, {});
62 static Value pack(OpBuilder &b, Value token, Value data = {}) {
65 return b.create<dc::PackOp>(token.getLoc(), token,
data);
70 auto *ctx = tuple.getContext();
71 mlir::SmallVector<hw::StructType::FieldInfo, 8> hwfields;
72 for (
auto [i,
innerType] : llvm::enumerate(tuple)) {
74 if (
auto tupleInnerType = dyn_cast<TupleType>(
innerType))
83 class DCTypeConverter :
public TypeConverter {
86 addConversion([](Type type) -> Type {
87 if (isa<NoneType>(type))
93 if (
auto tupleType = dyn_cast<TupleType>(type))
97 addConversion([](ValueType type) {
return type; });
98 addConversion([](TokenType type) {
return type; });
100 addTargetMaterialization([](mlir::OpBuilder &builder, mlir::Type resultType,
101 mlir::ValueRange inputs,
102 mlir::Location loc) -> mlir::Value {
103 if (inputs.size() != 1)
107 if (isa<dc::TokenType>(resultType) &&
108 isa<dc::ValueType>(inputs.front().getType()))
109 return unpack(builder, inputs.front()).token;
112 auto vt = dyn_cast<dc::ValueType>(resultType);
113 if (vt && !vt.getInnerType())
114 return pack(builder, inputs.front());
117 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
121 addSourceMaterialization([](mlir::OpBuilder &builder, mlir::Type resultType,
122 mlir::ValueRange inputs,
123 mlir::Location loc) -> mlir::Value {
124 if (inputs.size() != 1)
128 if (isa<dc::TokenType>(resultType) &&
129 isa<dc::ValueType>(inputs.front().getType()))
130 return unpack(builder, inputs.front()).token;
133 auto vt = dyn_cast<dc::ValueType>(resultType);
134 if (vt && !vt.getInnerType())
135 return pack(builder, inputs.front());
138 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
144 template <
typename OpTy>
148 using OpAdaptor =
typename OpTy::Adaptor;
150 DCOpConversionPattern(MLIRContext *context, TypeConverter &typeConverter,
153 convertedOps(convertedOps) {}
157 class CondBranchConversionPattern
158 :
public DCOpConversionPattern<handshake::ConditionalBranchOp> {
160 using DCOpConversionPattern<
161 handshake::ConditionalBranchOp>::DCOpConversionPattern;
162 using OpAdaptor =
typename handshake::ConditionalBranchOp::Adaptor;
165 matchAndRewrite(handshake::ConditionalBranchOp op, OpAdaptor adaptor,
166 ConversionPatternRewriter &rewriter)
const override {
167 auto condition = unpack(rewriter, adaptor.getConditionOperand());
168 auto data = unpack(rewriter, adaptor.getDataOperand());
171 auto join = rewriter.create<dc::JoinOp>(
172 op.getLoc(), ValueRange{condition.token,
data.token});
175 auto packedCondition = pack(rewriter, join, condition.data);
178 auto branch = rewriter.create<dc::BranchOp>(op.getLoc(), packedCondition);
181 llvm::SmallVector<Value, 4> packed;
182 packed.push_back(pack(rewriter, branch.getTrueToken(),
data.data));
183 packed.push_back(pack(rewriter, branch.getFalseToken(),
data.data));
185 rewriter.replaceOp(op, packed);
190 class ForkOpConversionPattern
191 :
public DCOpConversionPattern<handshake::ForkOp> {
193 using DCOpConversionPattern<handshake::ForkOp>::DCOpConversionPattern;
194 using OpAdaptor =
typename handshake::ForkOp::Adaptor;
197 matchAndRewrite(handshake::ForkOp op, OpAdaptor adaptor,
198 ConversionPatternRewriter &rewriter)
const override {
199 auto input = unpack(rewriter, adaptor.getOperand());
200 auto forkOut = rewriter.create<dc::ForkOp>(op.getLoc(), input.token,
204 llvm::SmallVector<Value, 4> packed;
205 for (
auto res : forkOut.getResults())
206 packed.push_back(pack(rewriter, res, input.data));
208 rewriter.replaceOp(op, packed);
213 class JoinOpConversion :
public DCOpConversionPattern<handshake::JoinOp> {
215 using DCOpConversionPattern<handshake::JoinOp>::DCOpConversionPattern;
216 using OpAdaptor =
typename handshake::JoinOp::Adaptor;
219 matchAndRewrite(handshake::JoinOp op, OpAdaptor adaptor,
220 ConversionPatternRewriter &rewriter)
const override {
221 llvm::SmallVector<Value, 4> inputTokens;
222 for (
auto input : adaptor.getData())
223 inputTokens.push_back(unpack(rewriter, input).token);
225 rewriter.replaceOpWithNewOp<dc::JoinOp>(op, inputTokens);
230 class MergeOpConversion :
public DCOpConversionPattern<handshake::MergeOp> {
232 using DCOpConversionPattern<handshake::MergeOp>::DCOpConversionPattern;
233 using OpAdaptor =
typename handshake::MergeOp::Adaptor;
236 matchAndRewrite(handshake::MergeOp op, OpAdaptor adaptor,
237 ConversionPatternRewriter &rewriter)
const override {
238 if (op.getNumOperands() > 2)
239 return rewriter.notifyMatchFailure(op,
"only two inputs supported");
241 SmallVector<Value, 4> tokens,
data;
243 for (
auto input : adaptor.getDataOperands()) {
244 auto up = unpack(rewriter, input);
245 tokens.push_back(up.token);
247 data.push_back(up.data);
251 Value selectedIndex = rewriter.create<dc::MergeOp>(op.getLoc(), tokens);
252 auto selectedIndexUnpacked = unpack(rewriter, selectedIndex);
257 auto dataMux = rewriter.create<arith::SelectOp>(
258 op.getLoc(), selectedIndexUnpacked.data,
data[0],
data[1]);
259 convertedOps->insert(dataMux);
262 mergeOutput = pack(rewriter, selectedIndexUnpacked.token, dataMux);
266 mergeOutput = selectedIndexUnpacked.token;
269 rewriter.replaceOp(op, mergeOutput);
274 class PackOpConversion :
public DCOpConversionPattern<handshake::PackOp> {
276 using DCOpConversionPattern<handshake::PackOp>::DCOpConversionPattern;
277 using OpAdaptor =
typename handshake::PackOp::Adaptor;
280 matchAndRewrite(handshake::PackOp op, OpAdaptor adaptor,
281 ConversionPatternRewriter &rewriter)
const override {
285 llvm::SmallVector<Value, 4> inputTokens, inputData;
286 for (
auto input : adaptor.getOperands()) {
287 DCTuple dct = unpack(rewriter, input);
288 inputTokens.push_back(dct.token);
290 inputData.push_back(dct.data);
293 auto join = rewriter.create<dc::JoinOp>(op.getLoc(), inputTokens);
294 StructType structType =
298 convertedOps->insert(packedData);
299 rewriter.replaceOp(op, pack(rewriter, join, packedData));
304 class UnpackOpConversion :
public DCOpConversionPattern<handshake::UnpackOp> {
306 using DCOpConversionPattern<handshake::UnpackOp>::DCOpConversionPattern;
307 using OpAdaptor =
typename handshake::UnpackOp::Adaptor;
310 matchAndRewrite(handshake::UnpackOp op, OpAdaptor adaptor,
311 ConversionPatternRewriter &rewriter)
const override {
314 DCTuple unpackedInput = unpack(rewriter, adaptor.getInput());
316 rewriter.create<hw::StructExplodeOp>(op.getLoc(), unpackedInput.data);
317 convertedOps->insert(unpackedData);
319 llvm::SmallVector<Value, 4> repackedInputs;
320 for (
auto outputData : unpackedData.getResults())
321 repackedInputs.push_back(pack(rewriter, unpackedInput.token, outputData));
323 rewriter.replaceOp(op, repackedInputs);
328 class ControlMergeOpConversion
329 :
public DCOpConversionPattern<handshake::ControlMergeOp> {
331 using DCOpConversionPattern<handshake::ControlMergeOp>::DCOpConversionPattern;
333 using OpAdaptor =
typename handshake::ControlMergeOp::Adaptor;
336 matchAndRewrite(handshake::ControlMergeOp op, OpAdaptor adaptor,
337 ConversionPatternRewriter &rewriter)
const override {
338 if (op.getDataOperands().size() != 2)
339 return op.emitOpError(
"expected two data operands");
341 llvm::SmallVector<Value> tokens,
data;
342 for (
auto input : adaptor.getDataOperands()) {
343 auto up = unpack(rewriter, input);
344 tokens.push_back(up.token);
346 data.push_back(up.data);
349 bool isIndexType = isa<IndexType>(op.getIndex().getType());
352 Value selectedIndex = rewriter.create<dc::MergeOp>(op.getLoc(), tokens);
353 auto mergeOpUnpacked = unpack(rewriter, selectedIndex);
354 auto selValue = mergeOpUnpacked.data;
356 Value dataSide = selectedIndex;
359 auto dataMux = rewriter.create<arith::SelectOp>(op.getLoc(), selValue,
361 convertedOps->insert(dataMux);
363 auto packed = pack(rewriter, mergeOpUnpacked.token, dataMux);
371 selValue = rewriter.create<arith::IndexCastOp>(
372 op.getLoc(), rewriter.getIndexType(), selValue);
373 convertedOps->insert(selValue.getDefiningOp());
374 selectedIndex = pack(rewriter, mergeOpUnpacked.token, selValue);
378 selValue = rewriter.create<arith::ExtUIOp>(
379 op.getLoc(), op.getIndex().getType(), selValue);
380 convertedOps->insert(selValue.getDefiningOp());
381 selectedIndex = pack(rewriter, mergeOpUnpacked.token, selValue);
384 rewriter.replaceOp(op, {dataSide, selectedIndex});
389 class SyncOpConversion :
public DCOpConversionPattern<handshake::SyncOp> {
391 using DCOpConversionPattern<handshake::SyncOp>::DCOpConversionPattern;
392 using OpAdaptor =
typename handshake::SyncOp::Adaptor;
395 matchAndRewrite(handshake::SyncOp op, OpAdaptor adaptor,
396 ConversionPatternRewriter &rewriter)
const override {
397 llvm::SmallVector<Value, 4> inputTokens;
398 llvm::SmallVector<Value, 4> inputData;
399 for (
auto input : adaptor.getOperands()) {
400 auto unpacked = unpack(rewriter, input);
401 inputTokens.push_back(unpacked.token);
402 inputData.push_back(unpacked.data);
405 auto syncToken = rewriter.create<dc::JoinOp>(op.getLoc(), inputTokens);
408 llvm::SmallVector<Value, 4> wrappedInputs;
409 for (
auto inputData : inputData)
410 wrappedInputs.push_back(pack(rewriter, syncToken, inputData));
412 rewriter.replaceOp(op, wrappedInputs);
418 class ConstantOpConversion
419 :
public DCOpConversionPattern<handshake::ConstantOp> {
421 using DCOpConversionPattern<handshake::ConstantOp>::DCOpConversionPattern;
422 using OpAdaptor =
typename handshake::ConstantOp::Adaptor;
425 matchAndRewrite(handshake::ConstantOp op, OpAdaptor adaptor,
426 ConversionPatternRewriter &rewriter)
const override {
428 auto token = rewriter.create<dc::SourceOp>(op.getLoc());
430 rewriter.create<arith::ConstantOp>(op.getLoc(), adaptor.getValue());
431 convertedOps->insert(cst);
432 rewriter.replaceOp(op, pack(rewriter, token, cst));
437 struct UnitRateConversionPattern :
public ConversionPattern {
439 UnitRateConversionPattern(MLIRContext *context, TypeConverter &converter,
441 : ConversionPattern(converter, MatchAnyOpTypeTag(), 1, context),
442 joinedOps(joinedOps) {}
443 using ConversionPattern::ConversionPattern;
448 matchAndRewrite(Operation *op, ArrayRef<Value> operands,
449 ConversionPatternRewriter &rewriter)
const override {
450 llvm::SmallVector<Value> inputData;
453 if (operands.empty()) {
454 if (!op->hasTrait<OpTrait::ConstantLike>())
455 return op->emitOpError(
456 "no-operand operation which isn't constant-like. Too dangerous "
457 "to assume semantics - won't convert");
461 outToken = rewriter.create<dc::SourceOp>(op->getLoc());
463 llvm::SmallVector<Value> inputTokens;
464 for (
auto input : operands) {
465 auto dct = unpack(rewriter, input);
466 inputData.push_back(dct.data);
467 inputTokens.push_back(dct.token);
470 assert(!inputTokens.empty() &&
"Expected at least one input token");
471 outToken = rewriter.create<dc::JoinOp>(op->getLoc(), inputTokens);
475 auto opName = op->getName();
476 if (opName.getStringRef() ==
"handshake.select") {
477 opName = OperationName(
"arith.select", getContext());
478 }
else if (opName.getStringRef() ==
"handshake.constant") {
479 opName = OperationName(
"arith.constant", getContext());
483 OperationState state(op->getLoc(), opName, inputData, op->getResultTypes(),
484 op->getAttrs(), op->getSuccessors());
486 Operation *newOp = rewriter.create(state);
487 joinedOps->insert(newOp);
490 llvm::SmallVector<Value> results;
491 for (
auto result : newOp->getResults())
492 results.push_back(pack(rewriter, outToken, result));
494 rewriter.replaceOp(op, results);
502 class SinkOpConversionPattern
503 :
public DCOpConversionPattern<handshake::SinkOp> {
505 using DCOpConversionPattern<handshake::SinkOp>::DCOpConversionPattern;
506 using OpAdaptor =
typename handshake::SinkOp::Adaptor;
509 matchAndRewrite(handshake::SinkOp op, OpAdaptor adaptor,
510 ConversionPatternRewriter &rewriter)
const override {
511 auto input = unpack(rewriter, adaptor.getOperand());
512 rewriter.replaceOpWithNewOp<dc::SinkOp>(op, input.token);
517 class SourceOpConversionPattern
518 :
public DCOpConversionPattern<handshake::SourceOp> {
520 using DCOpConversionPattern<handshake::SourceOp>::DCOpConversionPattern;
521 using OpAdaptor =
typename handshake::SourceOp::Adaptor;
524 matchAndRewrite(handshake::SourceOp op, OpAdaptor adaptor,
525 ConversionPatternRewriter &rewriter)
const override {
526 rewriter.replaceOpWithNewOp<dc::SourceOp>(op);
531 class BufferOpConversion :
public DCOpConversionPattern<handshake::BufferOp> {
533 using DCOpConversionPattern<handshake::BufferOp>::DCOpConversionPattern;
534 using OpAdaptor =
typename handshake::BufferOp::Adaptor;
537 matchAndRewrite(handshake::BufferOp op, OpAdaptor adaptor,
538 ConversionPatternRewriter &rewriter)
const override {
539 rewriter.getI32IntegerAttr(1);
540 rewriter.replaceOpWithNewOp<dc::BufferOp>(
541 op, adaptor.getOperand(),
static_cast<size_t>(op.getNumSlots()),
542 op.getInitValuesAttr());
550 using OpAdaptor =
typename handshake::ReturnOp::Adaptor;
553 matchAndRewrite(handshake::ReturnOp op, OpAdaptor adaptor,
554 ConversionPatternRewriter &rewriter)
const override {
558 auto outputOp = *hwModule.getBodyBlock()->getOps<hw::OutputOp>().begin();
559 outputOp->setOperands(adaptor.getOperands());
560 outputOp->moveAfter(&hwModule.getBodyBlock()->back());
561 rewriter.eraseOp(op);
566 class MuxOpConversionPattern :
public DCOpConversionPattern<handshake::MuxOp> {
568 using DCOpConversionPattern<handshake::MuxOp>::DCOpConversionPattern;
569 using OpAdaptor =
typename handshake::MuxOp::Adaptor;
572 matchAndRewrite(handshake::MuxOp op, OpAdaptor adaptor,
573 ConversionPatternRewriter &rewriter)
const override {
574 auto select = unpack(rewriter, adaptor.getSelectOperand());
575 auto selectData = select.data;
576 auto selectToken = select.token;
577 bool isIndexType = isa<IndexType>(selectData.getType());
579 bool withData = !isa<NoneType>(op.getResult().getType());
581 llvm::SmallVector<DCTuple> inputs;
582 for (
auto input : adaptor.getDataOperands())
583 inputs.push_back(unpack(rewriter, input));
586 Value controlMux = inputs.front().token;
591 dataMux = inputs[0].data;
593 llvm::SmallVector<Value> controlMuxInputs = {inputs.front().token};
594 for (
auto [i, input] :
595 llvm::enumerate(llvm::make_range(inputs.begin() + 1, inputs.end()))) {
600 Value inputData = input.data;
601 Value inputControl = input.token;
603 cmpIndex = rewriter.create<arith::ConstantIndexOp>(op.getLoc(), i);
605 size_t width = cast<IntegerType>(selectData.getType()).getWidth();
606 cmpIndex = rewriter.create<arith::ConstantIntOp>(op.getLoc(), i, width);
608 auto inputSelected = rewriter.create<arith::CmpIOp>(
609 op.getLoc(), arith::CmpIPredicate::eq, selectData, cmpIndex);
610 dataMux = rewriter.create<arith::SelectOp>(op.getLoc(), inputSelected,
614 convertedOps->insert(cmpIndex.getDefiningOp());
615 convertedOps->insert(dataMux.getDefiningOp());
616 convertedOps->insert(inputSelected);
621 auto inputSelectedControl = pack(rewriter, selectToken, inputSelected);
622 controlMux = rewriter.create<dc::SelectOp>(
623 op.getLoc(), inputSelectedControl, inputControl, controlMux);
624 convertedOps->insert(controlMux.getDefiningOp());
629 op, pack(rewriter, controlMux, withData ? dataMux : Value{}));
634 static hw::ModulePortInfo getModulePortInfoHS(
const TypeConverter &tc,
636 SmallVector<hw::PortInfo> inputs, outputs;
637 auto ft = funcOp.getFunctionType();
638 funcOp.resolveArgAndResNames();
641 for (
auto [index, type] : llvm::enumerate(ft.getInputs()))
642 inputs.push_back({{funcOp.getArgName(index), tc.convertType(type),
648 for (
auto [index, type] : llvm::enumerate(ft.getResults()))
649 outputs.push_back({{funcOp.getResName(index), tc.convertType(type),
654 return hw::ModulePortInfo{inputs, outputs};
659 using DCOpConversionPattern<handshake::FuncOp>::DCOpConversionPattern;
660 using OpAdaptor =
typename handshake::FuncOp::Adaptor;
670 ConversionPatternRewriter &rewriter)
const override {
671 ModulePortInfo ports = getModulePortInfoHS(*getTypeConverter(), op);
673 if (op.isExternal()) {
675 op.getLoc(), rewriter.getStringAttr(op.getName()), ports);
676 convertedOps->insert(mod);
679 op.getLoc(), rewriter.getStringAttr(op.getName()), ports);
681 auto ®ion = op->getRegions().front();
683 Region &moduleRegion = hwModule->getRegions().front();
684 rewriter.mergeBlocks(®ion.getBlocks().front(), hwModule.getBodyBlock(),
685 hwModule.getBodyBlock()->getArguments());
686 TypeConverter::SignatureConversion result(moduleRegion.getNumArguments());
687 (void)getTypeConverter()->convertSignatureArgs(
688 TypeRange(moduleRegion.getArgumentTypes()), result);
689 rewriter.applySignatureConversion(hwModule.getBodyBlock(), result);
690 convertedOps->insert(hwModule);
693 rewriter.eraseOp(op);
700 class ESIInstanceConversionPattern
703 ESIInstanceConversionPattern(MLIRContext *context,
708 matchAndRewrite(ESIInstanceOp op, OpAdaptor adaptor,
709 ConversionPatternRewriter &rewriter)
const override {
710 Location loc = op.getLoc();
711 SmallVector<Value> operands;
712 for (
size_t i = ESIInstanceOp::NumFixedOperands, e = op.getNumOperands();
715 rewriter.create<dc::FromESIOp>(loc, adaptor.getOperands()[i]));
716 operands.push_back(adaptor.getClk());
717 operands.push_back(adaptor.getRst());
720 Operation *targetModule = symCache.
getDefinition(op.getModuleAttr());
722 auto inst = rewriter.create<hw::InstanceOp>(loc, targetModule,
723 op.getInstNameAttr(), operands);
724 SmallVector<Value> esiResults(
725 llvm::map_range(inst.getResults(), [&](Value v) {
726 return rewriter.create<dc::ToESIOp>(loc, v);
728 rewriter.replaceOp(op, esiResults);
737 void addClkRst(
hw::HWModuleOp mod, StringRef clkName, StringRef rstName) {
738 auto *ctx = mod.getContext();
740 size_t numInputs = mod.getNumInputPorts();
754 for (
size_t portNum = 0, e = mod.getNumPorts(); portNum < e; ++portNum) {
755 auto attrs = dyn_cast_or_null<DictionaryAttr>(mod.getPortAttrs(portNum));
762 class HandshakeToDCPass
763 :
public circt::impl::HandshakeToDCBase<HandshakeToDCPass> {
766 void runOnOperation()
override {
767 mlir::ModuleOp mod = getOperation();
768 auto patternBuilder = [&](TypeConverter &typeConverter,
773 patterns.add<ReturnOpConversion>(typeConverter, mod.getContext());
778 patternBuilder,
nullptr);
786 mlir::Operation *op, circt::HandshakeToDCOptions options,
787 llvm::function_ref<
void(TypeConverter &typeConverter,
791 llvm::function_ref<
void(mlir::ConversionTarget &)> configureTarget) {
803 mlir::MLIRContext *ctx = op->getContext();
804 ConversionTarget target(*ctx);
805 target.addIllegalDialect<handshake::HandshakeDialect>();
806 target.addLegalDialect<dc::DCDialect>();
807 target.addLegalOp<mlir::ModuleOp, handshake::ESIInstanceOp,
hw::HWModuleOp,
812 configureTarget(target);
820 target.markUnknownOpDynamicallyLegal([&](Operation *op) {
821 return convertedOps.contains(op) ||
826 DCTypeConverter typeConverter;
833 .add<BufferOpConversion, CondBranchConversionPattern,
834 SinkOpConversionPattern, SourceOpConversionPattern,
835 MuxOpConversionPattern, ForkOpConversionPattern, JoinOpConversion,
836 PackOpConversion, UnpackOpConversion, MergeOpConversion,
837 ControlMergeOpConversion, ConstantOpConversion, SyncOpConversion>(
838 ctx, typeConverter, &convertedOps);
842 patterns.add<UnitRateConversionPattern>(ctx, typeConverter, &convertedOps);
845 patternBuilder(typeConverter, convertedOps,
patterns);
846 if (failed(applyPartialConversion(op, target, std::move(
patterns))))
850 for (
auto &op : convertedOps)
851 if (
auto mod = dyn_cast<hw::HWModuleOp>(op); mod)
852 addClkRst(mod, options.clkName, options.rstName);
858 ConversionTarget globalLoweringTarget(*ctx);
859 globalLoweringTarget.addIllegalDialect<handshake::HandshakeDialect>();
860 globalLoweringTarget.addLegalDialect<dc::DCDialect, hw::HWDialect>();
861 RewritePatternSet globalPatterns(ctx);
862 globalPatterns.add<ESIInstanceConversionPattern>(ctx, symbolCache);
863 if (failed(applyPartialConversion(op, globalLoweringTarget,
864 std::move(globalPatterns))))
865 return op->emitOpError() <<
"error during conversion";
assert(baseType &&"element must be base type")
static Type tupleToStruct(TupleType tuple)
void addDefinitions(mlir::Operation *top)
Populate the symbol cache with all symbol-defining operations within the 'top' operation.
This stores lookup tables to make manipulating and working with the IR more efficient.
mlir::Operation * getDefinition(mlir::Attribute attr) const override
Lookup a definition for 'symbol' in the cache.
void freeze()
Mark the cache as frozen, which allows it to be shared across threads.
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
mlir::Type innerType(mlir::Type type)
DenseSet< Operation * > ConvertedOps
LogicalResult runHandshakeToDC(mlir::Operation *op, HandshakeToDCOptions options, llvm::function_ref< void(TypeConverter &typeConverter, ConvertedOps &convertedOps, RewritePatternSet &patterns)> patternBuilder, llvm::function_ref< void(mlir::ConversionTarget &)> configureTarget={})
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
This holds a decoded list of input/inout and output ports for a module or instance.
Creates a new Calyx component for each FuncOp in the program.