13#include "../PassDetails.h"
24#include "mlir/Transforms/DialectConversion.h"
25#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
27#include "llvm/ADT/StringExtras.h"
28#include "llvm/ADT/TypeSwitch.h"
29#include "llvm/Support/JSON.h"
33#define GEN_PASS_DEF_LOWERESITOHW
34#include "circt/Dialect/ESI/ESIPasses.h.inc"
50 PipelineStageLowering(
ESIHWBuilder &builder, MLIRContext *ctxt)
52 using OpConversionPattern::OpConversionPattern;
55 matchAndRewrite(PipelineStageOp stage, OpAdaptor adaptor,
56 ConversionPatternRewriter &rewriter)
const final;
63LogicalResult PipelineStageLowering::matchAndRewrite(
64 PipelineStageOp stage, OpAdaptor adaptor,
65 ConversionPatternRewriter &rewriter)
const {
66 auto loc = stage.getLoc();
67 auto chPort = dyn_cast<ChannelType>(stage.getInput().getType());
69 return rewriter.notifyMatchFailure(stage,
"stage had wrong type");
70 Operation *symTable = stage->getParentWithTrait<OpTrait::SymbolTable>();
71 auto stageModule = builder.declareStage(symTable, stage);
75 ArrayAttr stageParams =
76 builder.getStageParameterList(rewriter.getUI32IntegerAttr(width));
84 UnwrapValidReadyOp::create(rewriter, loc, stage.getInput(), wrapReady);
86 StringRef pipeStageName =
"pipelineStage";
87 if (
auto name = stage->getAttrOfType<StringAttr>(
"name"))
88 pipeStageName = name.getValue();
92 llvm::SmallVector<Value> operands = {stage.getClk(), stage.getRst()};
93 operands.push_back(
unwrap.getRawOutput());
94 operands.push_back(
unwrap.getValid());
95 operands.push_back(stageReady);
96 auto stageInst = hw::InstanceOp::create(rewriter, loc, stageModule,
97 pipeStageName, operands, stageParams);
98 auto stageInstResults = stageInst.getResults();
102 wrapReady.
setValue(stageInstResults[0]);
104 x = stageInstResults[1];
105 xValid = stageInstResults[2];
108 auto wrap = WrapValidReadyOp::create(rewriter, loc, chPort,
109 rewriter.getI1Type(), x, xValid);
113 rewriter.replaceOp(stage,
wrap.getChanOutput());
121 using OpConversionPattern::OpConversionPattern;
124 matchAndRewrite(NullSourceOp nullop, OpAdaptor adaptor,
125 ConversionPatternRewriter &rewriter)
const final;
129LogicalResult NullSourceOpLowering::matchAndRewrite(
130 NullSourceOp nullop, OpAdaptor adaptor,
131 ConversionPatternRewriter &rewriter)
const {
132 auto chanType = cast<ChannelType>(nullop.getOut().getType());
134 Location loc = nullop.getLoc();
135 int64_t width = hw::getBitWidth(
innerType);
137 return rewriter.notifyMatchFailure(
138 nullop,
"NullOp lowering only supports hw types");
140 rewriter.getI1Type(), 0);
145 if (chanType.getSignaling() == ChannelSignaling::ValidOnly) {
146 auto wrap = WrapValidOnlyOp::create(rewriter, loc, typedZero, valid);
147 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
148 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
150 auto wrap = WrapValidReadyOp::create(rewriter, loc, typedZero, valid);
151 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
152 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
163 using OpConversionPattern::OpConversionPattern;
166 matchAndRewrite(SnoopValidReadyOp op, SnoopValidReadyOpAdaptor operands,
167 ConversionPatternRewriter &rewriter)
const override {
168 Operation *defOp = op.getInput().getDefiningOp();
170 return rewriter.notifyMatchFailure(op,
171 "snoop input is not defined by an op");
172 auto wrap = dyn_cast<WrapValidReadyOp>(defOp);
174 return rewriter.notifyMatchFailure(
175 defOp,
"Snoop input must be a wrap.vr operation");
178 Value valid =
wrap.getValid();
183 auto *unwrapOpOperand =
184 ChannelType::getSingleConsumer(
wrap.getChanOutput());
186 if (unwrapOpOperand &&
187 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
189 auto unwrap = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
190 ready =
unwrap.getReady();
194 assert(!unwrapOpOperand &&
195 "Expected no consumer or consumer should be an unwrap");
197 rewriter.getI1Type(), 0);
200 rewriter.replaceOp(op, {valid, ready,
data});
210struct RemoveSnoopTransactionOp
213 using OpConversionPattern::OpConversionPattern;
216 matchAndRewrite(SnoopTransactionOp op, SnoopTransactionOpAdaptor operands,
217 ConversionPatternRewriter &rewriter)
const override {
218 Operation *defOp = op.getInput().getDefiningOp();
220 return rewriter.notifyMatchFailure(op,
221 "snoop input is not defined by an op");
224 if (
auto wrapVR = dyn_cast<WrapValidReadyOp>(defOp)) {
225 Value
data = wrapVR.getRawInput();
226 Value valid = wrapVR.getValid();
230 auto *unwrapOpOperand =
231 ChannelType::getSingleConsumer(wrapVR.getChanOutput());
233 if (unwrapOpOperand &&
234 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
236 auto unwrapVR = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
237 ready = unwrapVR.getReady();
240 assert(!unwrapOpOperand &&
241 "Expected no consumer or consumer should be an unwrap");
243 rewriter.getI1Type(), 0);
248 comb::AndOp::create(rewriter, op.getLoc(), valid, ready);
250 rewriter.replaceOp(op, {transaction,
data});
255 if (
auto wrapFIFO = dyn_cast<WrapFIFOOp>(defOp)) {
256 Value
data = wrapFIFO.getData();
257 Value
empty = wrapFIFO.getEmpty();
261 auto *unwrapOpOperand =
262 ChannelType::getSingleConsumer(wrapFIFO.getChanOutput());
264 if (unwrapOpOperand && isa<UnwrapFIFOOp>(unwrapOpOperand->getOwner())) {
266 auto unwrapFIFO = cast<UnwrapFIFOOp>(unwrapOpOperand->getOwner());
267 rden = unwrapFIFO.getRden();
270 assert(!unwrapOpOperand &&
271 "Expected no consumer or consumer should be an unwrap");
273 rewriter.getI1Type(), 0);
277 auto notEmpty = comb::XorOp::create(
278 rewriter, op.getLoc(),
empty,
280 rewriter.getBoolAttr(
true)));
282 comb::AndOp::create(rewriter, op.getLoc(), notEmpty, rden);
284 rewriter.replaceOp(op, {transaction,
data});
289 if (
auto wrapVO = dyn_cast<WrapValidOnlyOp>(defOp)) {
290 Value
data = wrapVO.getRawInput();
291 Value valid = wrapVO.getValid();
293 rewriter.replaceOp(op, {valid,
data});
297 return rewriter.notifyMatchFailure(
299 "Snoop input must be a wrap.vr, wrap.fifo, or wrap.vo operation");
307template <
typename Op>
313 matchAndRewrite(Op op,
typename Op::Adaptor adaptor,
314 ConversionPatternRewriter &rewriter)
const final {
315 if (failed(Op::canonicalize(op, rewriter)))
316 return rewriter.notifyMatchFailure(op->getLoc(),
"canonicalizer failed");
323struct ESItoHWPass :
public circt::esi::impl::LowerESItoHWBase<ESItoHWPass> {
324 void runOnOperation()
override;
333 using OpConversionPattern::OpConversionPattern;
336 matchAndRewrite(WrapSVInterfaceOp
wrap, OpAdaptor adaptor,
337 ConversionPatternRewriter &rewriter)
const final;
342WrapInterfaceLower::matchAndRewrite(WrapSVInterfaceOp
wrap, OpAdaptor adaptor,
343 ConversionPatternRewriter &rewriter)
const {
344 auto operands = adaptor.getOperands();
345 if (operands.size() != 1)
346 return rewriter.notifyMatchFailure(
wrap, [&operands](Diagnostic &d) {
347 d <<
"wrap.iface has 1 argument. Got " << operands.size() <<
"operands";
349 auto sinkModport = dyn_cast<GetModportOp>(operands[0].getDefiningOp());
353 dyn_cast<InterfaceInstanceOp>(sinkModport.getIface().getDefiningOp());
357 auto loc =
wrap.getLoc();
358 auto validSignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
361 dataSignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
364 WrapValidReadyOp::create(rewriter, loc, dataSignal, validSignal);
365 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
367 rewriter.replaceOp(
wrap, {wrapVR.getChanOutput()});
377 using OpConversionPattern::OpConversionPattern;
380 matchAndRewrite(UnwrapSVInterfaceOp
wrap, OpAdaptor adaptor,
381 ConversionPatternRewriter &rewriter)
const final;
385LogicalResult UnwrapInterfaceLower::matchAndRewrite(
386 UnwrapSVInterfaceOp
unwrap, OpAdaptor adaptor,
387 ConversionPatternRewriter &rewriter)
const {
388 auto operands = adaptor.getOperands();
389 if (operands.size() != 2)
390 return rewriter.notifyMatchFailure(
unwrap, [&operands](Diagnostic &d) {
391 d <<
"Unwrap.iface has 2 arguments. Got " << operands.size()
395 auto sourceModport = dyn_cast<GetModportOp>(operands[1].getDefiningOp());
399 dyn_cast<InterfaceInstanceOp>(sourceModport.getIface().getDefiningOp());
403 auto loc =
unwrap.getLoc();
404 auto readySignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
407 UnwrapValidReadyOp::create(rewriter, loc, operands[0], readySignal);
408 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
411 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
413 unwrapVR.getRawOutput());
426 using OpConversionPattern::OpConversionPattern;
429 matchAndRewrite(CosimToHostEndpointOp, OpAdaptor adaptor,
430 ConversionPatternRewriter &rewriter)
const final;
437LogicalResult CosimToHostLowering::matchAndRewrite(
438 CosimToHostEndpointOp ep, OpAdaptor adaptor,
439 ConversionPatternRewriter &rewriter)
const {
440 auto loc = ep.getLoc();
441 auto *ctxt = rewriter.getContext();
444 Value toHost = adaptor.getToHost();
445 Type type = toHost.getType();
446 auto chanTy = dyn_cast<ChannelType>(type);
450 SmallVector<Attribute, 8> params;
451 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
452 params.push_back(ParamDeclAttr::get(
"TO_HOST_TYPE_ID",
getTypeID(type)));
453 params.push_back(ParamDeclAttr::get(
454 "TO_HOST_SIZE_BITS", rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
457 auto sendReady = bb.get(rewriter.getI1Type());
458 UnwrapValidReadyOp unwrapSend =
459 UnwrapValidReadyOp::create(rewriter, loc, toHost, sendReady);
461 Value rawSendData = unwrapSend.getRawOutput();
464 if (WindowType windowType = dyn_cast_or_null<WindowType>(chanTy.getInner()))
465 rawSendData = UnwrapWindow::create(rewriter, loc, rawSendData);
467 Value castedSendData;
470 rewriter, loc, rewriter.getIntegerType(width), rawSendData);
473 rewriter, loc, rewriter.getIntegerType(1), rewriter.getBoolAttr(
false));
476 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
477 HWModuleExternOp endpoint =
478 builder.declareCosimEndpointToHostModule(symTable);
484 unwrapSend.getValid(),
488 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
489 ArrayAttr::get(ctxt, params));
490 sendReady.setValue(cosimEpModule.getResult(0));
493 rewriter.eraseOp(ep);
501struct CosimFromHostLowering
507 using OpConversionPattern::OpConversionPattern;
510 matchAndRewrite(CosimFromHostEndpointOp, OpAdaptor adaptor,
511 ConversionPatternRewriter &rewriter)
const final;
518LogicalResult CosimFromHostLowering::matchAndRewrite(
519 CosimFromHostEndpointOp ep, OpAdaptor adaptor,
520 ConversionPatternRewriter &rewriter)
const {
521 auto loc = ep.getLoc();
522 auto *ctxt = rewriter.getContext();
525 ChannelType type = ep.getFromHost().getType();
526 WindowType windowType = dyn_cast<WindowType>(type.getInner());
530 SmallVector<Attribute, 8> params;
531 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
532 params.push_back(ParamDeclAttr::get(
"FROM_HOST_TYPE_ID",
getTypeID(type)));
534 ParamDeclAttr::get(
"FROM_HOST_SIZE_BITS",
535 rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
538 auto recvReady = bb.get(rewriter.getI1Type());
541 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
542 HWModuleExternOp endpoint =
543 builder.declareCosimEndpointFromHostModule(symTable);
546 Value operands[] = {adaptor.getClk(), adaptor.getRst(), recvReady};
548 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
549 ArrayAttr::get(ctxt, params));
552 Value recvDataFromCosim = cosimEpModule.getResult(1);
553 Value recvValidFromCosim = cosimEpModule.getResult(0);
554 Value castedRecvData;
555 Type castToType = windowType ? windowType.getLoweredType() : type.getInner();
561 rewriter, loc, rewriter.getIntegerType(0),
562 rewriter.getIntegerAttr(rewriter.getIntegerType(0), 0));
567 WrapWindow::create(rewriter, loc, windowType, castedRecvData);
569 WrapValidReadyOp wrapRecv = WrapValidReadyOp::create(
570 rewriter, loc, castedRecvData, recvValidFromCosim);
571 recvReady.setValue(wrapRecv.getReady());
574 rewriter.replaceOp(ep, wrapRecv.getChanOutput());
585 using OpConversionPattern::OpConversionPattern;
586 constexpr static StringRef manifestRomName =
"__ESI_Manifest_ROM";
589 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
590 ConversionPatternRewriter &rewriter)
const override;
593 LogicalResult createRomModule(CompressedManifestOp op,
594 ConversionPatternRewriter &rewriter)
const;
598LogicalResult ManifestRomLowering::createRomModule(
599 CompressedManifestOp op, ConversionPatternRewriter &rewriter)
const {
600 Location loc = op.getLoc();
601 auto mlirModBody = op->getParentOfType<mlir::ModuleOp>();
602 rewriter.setInsertionPointToStart(mlirModBody.getBody());
606 if (Operation *existingExtern = mlirModBody.lookupSymbol(manifestRomName)) {
607 if (!isa<hw::HWModuleExternOp>(existingExtern))
608 return rewriter.notifyMatchFailure(
610 "Found " + manifestRomName +
" but it wasn't an HWModuleExternOp");
611 rewriter.eraseOp(existingExtern);
616 {{rewriter.getStringAttr(
"clk"), rewriter.getType<seq::ClockType>(),
617 ModulePort::Direction::Input}},
618 {{rewriter.getStringAttr(
"address"), rewriter.getIntegerType(29),
619 ModulePort::Direction::Input}},
620 {{rewriter.getStringAttr(
"data"), rewriter.getI64Type(),
621 ModulePort::Direction::Output}},
623 auto rom = HWModuleOp::create(rewriter, loc,
624 rewriter.getStringAttr(manifestRomName), ports);
625 Block *romBody = rom.getBodyBlock();
626 rewriter.setInsertionPointToStart(romBody);
627 Value
clk = romBody->getArgument(0);
628 Value inputAddress = romBody->getArgument(1);
631 ArrayRef<uint8_t> maniBytes = op.getCompressedManifest().getData();
632 SmallVector<uint64_t> words;
633 words.push_back(maniBytes.size());
635 for (
size_t i = 0; i < maniBytes.size() - 7; i += 8) {
637 for (
size_t b = 0; b < 8; ++b)
638 word |=
static_cast<uint64_t
>(maniBytes[i + b]) << (8 * b);
639 words.push_back(word);
641 size_t overHang = maniBytes.size() % 8;
644 for (
size_t i = 0; i < overHang; ++i)
645 word |=
static_cast<uint64_t
>(maniBytes[maniBytes.size() - overHang + i])
647 words.push_back(word);
652 SmallVector<Attribute> wordAttrs;
653 for (uint64_t word : words)
654 wordAttrs.push_back(rewriter.getI64IntegerAttr(word));
655 auto manifestConstant = hw::AggregateConstantOp::create(
657 hw::UnpackedArrayType::get(rewriter.getI64Type(), words.size()),
658 rewriter.getArrayAttr(wordAttrs));
660 sv::RegOp::create(rewriter, loc, manifestConstant.getType());
664 size_t addrBits = llvm::Log2_64_Ceil(words.size());
669 sv::ArrayIndexInOutOp::create(rewriter, loc, manifestReg, inputAddresReg);
672 if (
auto *term = romBody->getTerminator())
673 rewriter.eraseOp(term);
674 hw::OutputOp::create(rewriter, loc, ValueRange{readDataReg});
678LogicalResult ManifestRomLowering::matchAndRewrite(
679 CompressedManifestOp op, OpAdaptor adaptor,
680 ConversionPatternRewriter &rewriter)
const {
681 LogicalResult ret = createRomModule(op, rewriter);
682 rewriter.eraseOp(op);
689struct CosimManifestLowering :
public ManifestRomLowering {
691 using ManifestRomLowering::ManifestRomLowering;
694 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
695 ConversionPatternRewriter &rewriter)
const final;
699LogicalResult CosimManifestLowering::matchAndRewrite(
700 CompressedManifestOp op, OpAdaptor adaptor,
701 ConversionPatternRewriter &rewriter)
const {
702 MLIRContext *ctxt = rewriter.getContext();
703 Location loc = op.getLoc();
707 LogicalResult ret = createRomModule(op, rewriter);
712 Attribute params[] = {
713 ParamDeclAttr::get(
"COMPRESSED_MANIFEST_SIZE", rewriter.getI32Type())};
715 {{rewriter.getStringAttr(
"compressed_manifest"),
716 rewriter.getType<hw::ArrayType>(
717 rewriter.getI8Type(),
718 ParamDeclRefAttr::get(
719 rewriter.getStringAttr(
"COMPRESSED_MANIFEST_SIZE"),
720 rewriter.getI32Type())),
721 ModulePort::Direction::Input},
724 rewriter.setInsertionPointToEnd(
725 op->getParentOfType<mlir::ModuleOp>().getBody());
726 auto cosimManifestExternModule = HWModuleExternOp::create(
727 rewriter, loc, rewriter.getStringAttr(
"Cosim_Manifest"), ports,
728 "Cosim_Manifest", ArrayAttr::get(ctxt, params));
731 auto manifestMod = hw::HWModuleOp::create(
732 rewriter, loc, rewriter.getStringAttr(
"__ESIManifest"), portInfo,
735 SmallVector<Attribute> bytes;
736 for (uint8_t b : op.getCompressedManifest().getData())
737 bytes.push_back(rewriter.getI8IntegerAttr(b));
738 auto manifestConstant = hw::AggregateConstantOp::create(
740 hw::ArrayType::get(rewriter.getI8Type(), bytes.size()),
741 rewriter.getArrayAttr(bytes));
743 sv::LogicOp::create(rewriter, loc, manifestConstant.getType());
744 sv::AssignOp::create(rewriter, loc, manifestLogic, manifestConstant);
745 auto manifest = sv::ReadInOutOp::create(rewriter, loc, manifestLogic);
748 hw::InstanceOp::create(rewriter, loc, cosimManifestExternModule,
749 "__manifest", ArrayRef<Value>({manifest}),
750 rewriter.getArrayAttr({ParamDeclAttr::get(
751 "COMPRESSED_MANIFEST_SIZE",
752 rewriter.getI32IntegerAttr(bytes.size()))}));
755 rewriter.setInsertionPoint(op);
756 hw::InstanceOp::create(rewriter, loc, manifestMod,
"__manifest",
757 ArrayRef<Value>({}));
759 rewriter.eraseOp(op);
766 return type.walk([](ChannelType) {
return WalkResult::interrupt(); })
778 SmallVector<Operation *> channelOps;
779 DenseSet<OperationName> seenOpNames;
780 RewritePatternSet canonPatterns(ctxt);
781 top->walk([&](Operation *op) {
785 channelOps.push_back(op);
786 if (std::optional<mlir::RegisteredOperationName> info =
787 op->getRegisteredInfo();
788 info && seenOpNames.insert(op->getName()).second)
789 info->getCanonicalizationPatterns(canonPatterns, ctxt);
791 mlir::GreedyRewriteConfig config;
792 config.setStrictness(mlir::GreedyRewriteStrictness::ExistingAndNewOps);
793 (void)mlir::applyOpPatternsGreedily(
794 channelOps, mlir::FrozenRewritePatternSet(std::move(canonPatterns)),
808 constexpr unsigned maxReported = 10;
809 unsigned numReported = 0;
810 auto *esiDialect = ctxt->getLoadedDialect<ESIDialect>();
811 top->walk([&](Operation *op) {
815 return WalkResult::advance();
818 if (op->getDialect() == esiDialect) {
819 op->emitError(
"lower-esi-to-hw left behind a channel operation");
820 if (++numReported >= maxReported)
821 return WalkResult::interrupt();
822 return WalkResult::advance();
831 for (Region ®ion : op->getRegions())
832 for (Block &block : region)
834 if (hasChannelType) {
835 op->emitError(
"lower-esi-to-hw left behind a channel-typed value");
836 if (++numReported >= maxReported)
837 return WalkResult::interrupt();
839 return WalkResult::advance();
841 return numReported == 0;
844void ESItoHWPass::runOnOperation() {
845 auto top = getOperation();
846 auto *ctxt = &getContext();
849 ConversionTarget noBundlesTarget(*ctxt);
850 noBundlesTarget.markUnknownOpDynamicallyLegal(
851 [](Operation *) {
return true; });
852 noBundlesTarget.addIllegalOp<PackBundleOp>();
853 noBundlesTarget.addIllegalOp<UnpackBundleOp>();
854 RewritePatternSet bundlePatterns(&getContext());
855 bundlePatterns.add<CanonicalizerOpLowering<PackBundleOp>>(&getContext());
856 bundlePatterns.add<CanonicalizerOpLowering<UnpackBundleOp>>(&getContext());
857 if (failed(applyPartialConversion(getOperation(), noBundlesTarget,
858 std::move(bundlePatterns)))) {
864 ConversionTarget pass1Target(*ctxt);
865 pass1Target.addLegalDialect<comb::CombDialect>();
866 pass1Target.addLegalDialect<HWDialect>();
867 pass1Target.addLegalDialect<SVDialect>();
868 pass1Target.addLegalDialect<seq::SeqDialect>();
869 pass1Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
870 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp,
871 WrapWindow, UnwrapWindow>();
872 pass1Target.addLegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
874 pass1Target.addIllegalOp<WrapSVInterfaceOp, UnwrapSVInterfaceOp>();
875 pass1Target.addIllegalOp<PipelineStageOp>();
876 pass1Target.addIllegalOp<CompressedManifestOp>();
880 RewritePatternSet pass1Patterns(ctxt);
881 pass1Patterns.insert<PipelineStageLowering>(esiBuilder, ctxt);
882 pass1Patterns.insert<WrapInterfaceLower>(ctxt);
883 pass1Patterns.insert<UnwrapInterfaceLower>(ctxt);
884 pass1Patterns.insert<CosimToHostLowering>(esiBuilder);
885 pass1Patterns.insert<CosimFromHostLowering>(esiBuilder);
886 pass1Patterns.insert<NullSourceOpLowering>(ctxt);
889 pass1Patterns.insert<CosimManifestLowering>(ctxt);
891 pass1Patterns.insert<ManifestRomLowering>(ctxt);
897 applyPartialConversion(top, pass1Target, std::move(pass1Patterns)))) {
903 ConversionTarget pass2Target(*ctxt);
904 pass2Target.addLegalDialect<comb::CombDialect>();
905 pass2Target.addLegalDialect<HWDialect>();
906 pass2Target.addLegalDialect<SVDialect>();
907 pass2Target.addIllegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
908 pass2Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
909 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp>();
910 RewritePatternSet pass2Patterns(ctxt);
911 pass2Patterns.insert<RemoveSnoopOp>(ctxt);
912 pass2Patterns.insert<RemoveSnoopTransactionOp>(ctxt);
914 applyPartialConversion(top, pass2Target, std::move(pass2Patterns)))) {
930 return std::make_unique<ESItoHWPass>();
assert(baseType &&"element must be base type")
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
static bool typeContainsChannel(Type type)
Returns true if type is an ESI channel or an aggregate (e.g.
static bool verifyNoChannelsRemain(Operation *top, MLIRContext *ctxt)
Verify that no ESI channel ops or channel-typed values remain under top, which the channel lowering i...
static bool anyTypeContainsChannel(TypeRange types)
Returns true if any of types is or contains an ESI channel.
static void canonicalizeChannelOps(Operation *top, MLIRContext *ctxt)
Greedily canonicalize every op whose type involves an ESI channel.
static EvaluatorValuePtr unwrap(OMEvaluatorValue c)
static InstancePath empty
Instantiate one of these and use it to build typed backedges.
Backedge is a wrapper class around a Value.
void setValue(mlir::Value)
Trait marking an ESI op that operates on ESI types (e.g.
Assist the lowering steps for conversions which need to create auxiliary IR.
static constexpr char validStr[]
static constexpr char readyStr[]
static constexpr char dataStr[]
create(cls, result_type, reset=None, reset_value=None, name=None, sym_name=None, **kwargs)
uint64_t getWidth(Type t)
StringAttr getTypeID(Type t)
std::unique_ptr< OperationPass< ModuleOp > > createESItoHWPass()
mlir::Type innerType(mlir::Type type)
int64_t getBitWidth(mlir::Type type)
Return the hardware bit width of a type.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
Generic pattern for removing an op during pattern conversion.
This holds a decoded list of input/inout and output ports for a module or instance.
This holds the name, type, direction of a module's ports.