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)
51 : OpConversionPattern(ctxt), builder(builder) {}
52 using OpConversionPattern::OpConversionPattern;
55 matchAndRewrite(PipelineStageOp stage, OpAdaptor adaptor,
56 ConversionPatternRewriter &rewriter)
const final;
59 ESIHWBuilder &builder;
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);
76 rewriter.getUI32IntegerAttr(width),
77 rewriter.getUI32IntegerAttr(chPort.getDataDelay()));
82 circt::BackedgeBuilder back(rewriter, loc);
83 circt::Backedge wrapReady = back.get(rewriter.getI1Type());
85 UnwrapValidReadyOp::create(rewriter, loc, stage.getInput(), wrapReady);
87 StringRef pipeStageName =
"pipelineStage";
88 if (
auto name = stage->getAttrOfType<StringAttr>(
"name"))
89 pipeStageName = name.getValue();
92 circt::Backedge stageReady = back.get(rewriter.getI1Type());
93 llvm::SmallVector<Value> operands = {stage.getClk(), stage.getRst()};
94 operands.push_back(
unwrap.getRawOutput());
95 operands.push_back(
unwrap.getValid());
96 operands.push_back(stageReady);
97 auto stageInst = hw::InstanceOp::create(rewriter, loc, stageModule,
98 pipeStageName, operands, stageParams);
99 auto stageInstResults = stageInst.getResults();
103 wrapReady.
setValue(stageInstResults[0]);
105 x = stageInstResults[1];
106 xValid = stageInstResults[2];
109 auto wrap = WrapValidReadyOp::create(rewriter, loc, chPort,
110 rewriter.getI1Type(), x, xValid);
114 rewriter.replaceOp(stage,
wrap.getChanOutput());
119struct NullSourceOpLowering :
public OpConversionPattern<NullSourceOp> {
121 NullSourceOpLowering(MLIRContext *ctxt) : OpConversionPattern(ctxt) {}
122 using OpConversionPattern::OpConversionPattern;
125 matchAndRewrite(NullSourceOp nullop, OpAdaptor adaptor,
126 ConversionPatternRewriter &rewriter)
const final;
130LogicalResult NullSourceOpLowering::matchAndRewrite(
131 NullSourceOp nullop, OpAdaptor adaptor,
132 ConversionPatternRewriter &rewriter)
const {
133 auto chanType = cast<ChannelType>(nullop.getOut().getType());
135 Location loc = nullop.getLoc();
136 int64_t width = hw::getBitWidth(
innerType);
138 return rewriter.notifyMatchFailure(
139 nullop,
"NullOp lowering only supports hw types");
141 rewriter.getI1Type(), 0);
146 if (chanType.getSignaling() == ChannelSignaling::ValidOnly) {
147 auto wrap = WrapValidOnlyOp::create(rewriter, loc, typedZero, valid,
148 chanType.getDataDelay());
149 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
150 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
152 auto wrap = WrapValidReadyOp::create(rewriter, loc, typedZero, valid,
153 chanType.getDataDelay());
154 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
155 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
164struct RemoveSnoopOp :
public OpConversionPattern<SnoopValidReadyOp> {
166 using OpConversionPattern::OpConversionPattern;
169 matchAndRewrite(SnoopValidReadyOp op, SnoopValidReadyOpAdaptor operands,
170 ConversionPatternRewriter &rewriter)
const override {
171 Operation *defOp = op.getInput().getDefiningOp();
173 return rewriter.notifyMatchFailure(op,
174 "snoop input is not defined by an op");
175 auto wrap = dyn_cast<WrapValidReadyOp>(defOp);
177 return rewriter.notifyMatchFailure(
178 defOp,
"Snoop input must be a wrap.vr operation");
181 Value valid =
wrap.getValid();
186 auto *unwrapOpOperand =
187 ChannelType::getSingleConsumer(
wrap.getChanOutput());
189 if (unwrapOpOperand &&
190 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
192 auto unwrap = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
193 ready =
unwrap.getReady();
197 assert(!unwrapOpOperand &&
198 "Expected no consumer or consumer should be an unwrap");
200 rewriter.getI1Type(), 0);
203 rewriter.replaceOp(op, {valid, ready,
data});
213struct RemoveSnoopTransactionOp
214 :
public OpConversionPattern<SnoopTransactionOp> {
216 using OpConversionPattern::OpConversionPattern;
219 matchAndRewrite(SnoopTransactionOp op, SnoopTransactionOpAdaptor operands,
220 ConversionPatternRewriter &rewriter)
const override {
221 Operation *defOp = op.getInput().getDefiningOp();
223 return rewriter.notifyMatchFailure(op,
224 "snoop input is not defined by an op");
227 if (
auto wrapVR = dyn_cast<WrapValidReadyOp>(defOp)) {
228 Value
data = wrapVR.getRawInput();
229 Value valid = wrapVR.getValid();
233 auto *unwrapOpOperand =
234 ChannelType::getSingleConsumer(wrapVR.getChanOutput());
236 if (unwrapOpOperand &&
237 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
239 auto unwrapVR = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
240 ready = unwrapVR.getReady();
243 assert(!unwrapOpOperand &&
244 "Expected no consumer or consumer should be an unwrap");
246 rewriter.getI1Type(), 0);
251 comb::AndOp::create(rewriter, op.getLoc(), valid, ready);
253 rewriter.replaceOp(op, {transaction,
data});
258 if (
auto wrapFIFO = dyn_cast<WrapFIFOOp>(defOp)) {
259 Value
data = wrapFIFO.getData();
260 Value
empty = wrapFIFO.getEmpty();
264 auto *unwrapOpOperand =
265 ChannelType::getSingleConsumer(wrapFIFO.getChanOutput());
267 if (unwrapOpOperand && isa<UnwrapFIFOOp>(unwrapOpOperand->getOwner())) {
269 auto unwrapFIFO = cast<UnwrapFIFOOp>(unwrapOpOperand->getOwner());
270 rden = unwrapFIFO.getRden();
273 assert(!unwrapOpOperand &&
274 "Expected no consumer or consumer should be an unwrap");
276 rewriter.getI1Type(), 0);
280 auto notEmpty = comb::XorOp::create(
281 rewriter, op.getLoc(),
empty,
283 rewriter.getBoolAttr(
true)));
285 comb::AndOp::create(rewriter, op.getLoc(), notEmpty, rden);
287 rewriter.replaceOp(op, {transaction,
data});
292 if (
auto wrapVO = dyn_cast<WrapValidOnlyOp>(defOp)) {
293 Value
data = wrapVO.getRawInput();
294 Value valid = wrapVO.getValid();
296 rewriter.replaceOp(op, {valid,
data});
300 return rewriter.notifyMatchFailure(
302 "Snoop input must be a wrap.vr, wrap.fifo, or wrap.vo operation");
310template <
typename Op>
311struct CanonicalizerOpLowering :
public OpConversionPattern<Op> {
313 CanonicalizerOpLowering(MLIRContext *ctxt) : OpConversionPattern<Op>(ctxt) {}
316 matchAndRewrite(Op op,
typename Op::Adaptor adaptor,
317 ConversionPatternRewriter &rewriter)
const final {
318 if (failed(Op::canonicalize(op, rewriter)))
319 return rewriter.notifyMatchFailure(op->getLoc(),
"canonicalizer failed");
326struct ESItoHWPass :
public circt::esi::impl::LowerESItoHWBase<ESItoHWPass> {
327 void runOnOperation()
override;
334struct CosimToHostLowering :
public OpConversionPattern<CosimToHostEndpointOp> {
336 CosimToHostLowering(ESIHWBuilder &b)
337 : OpConversionPattern(b.getContext(), 1), builder(b) {}
339 using OpConversionPattern::OpConversionPattern;
342 matchAndRewrite(CosimToHostEndpointOp, OpAdaptor adaptor,
343 ConversionPatternRewriter &rewriter)
const final;
346 ESIHWBuilder &builder;
350LogicalResult CosimToHostLowering::matchAndRewrite(
351 CosimToHostEndpointOp ep, OpAdaptor adaptor,
352 ConversionPatternRewriter &rewriter)
const {
353 auto loc = ep.getLoc();
354 auto *ctxt = rewriter.getContext();
355 circt::BackedgeBuilder bb(rewriter, loc);
357 Value toHost = adaptor.getToHost();
358 Type type = toHost.getType();
359 auto chanTy = dyn_cast<ChannelType>(type);
363 SmallVector<Attribute, 8> params;
364 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
365 params.push_back(ParamDeclAttr::get(
"TO_HOST_TYPE_ID",
getTypeID(type)));
366 params.push_back(ParamDeclAttr::get(
367 "TO_HOST_SIZE_BITS", rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
370 auto sendReady = bb.get(rewriter.getI1Type());
371 UnwrapValidReadyOp unwrapSend =
372 UnwrapValidReadyOp::create(rewriter, loc, toHost, sendReady);
374 Value rawSendData = unwrapSend.getRawOutput();
377 if (WindowType windowType = dyn_cast_or_null<WindowType>(chanTy.getInner()))
378 rawSendData = UnwrapWindow::create(rewriter, loc, rawSendData);
380 Value castedSendData;
383 rewriter, loc, rewriter.getIntegerType(width), rawSendData);
386 rewriter, loc, rewriter.getIntegerType(1), rewriter.getBoolAttr(
false));
389 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
390 HWModuleExternOp endpoint =
397 unwrapSend.getValid(),
401 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
402 ArrayAttr::get(ctxt, params));
403 sendReady.setValue(cosimEpModule.getResult(0));
406 rewriter.eraseOp(ep);
414struct CosimFromHostLowering
415 :
public OpConversionPattern<CosimFromHostEndpointOp> {
417 CosimFromHostLowering(ESIHWBuilder &b)
418 : OpConversionPattern(b.getContext(), 1), builder(b) {}
420 using OpConversionPattern::OpConversionPattern;
423 matchAndRewrite(CosimFromHostEndpointOp, OpAdaptor adaptor,
424 ConversionPatternRewriter &rewriter)
const final;
427 ESIHWBuilder &builder;
431LogicalResult CosimFromHostLowering::matchAndRewrite(
432 CosimFromHostEndpointOp ep, OpAdaptor adaptor,
433 ConversionPatternRewriter &rewriter)
const {
434 auto loc = ep.getLoc();
435 auto *ctxt = rewriter.getContext();
436 circt::BackedgeBuilder bb(rewriter, loc);
438 ChannelType type = ep.getFromHost().getType();
439 WindowType windowType = dyn_cast<WindowType>(type.getInner());
443 SmallVector<Attribute, 8> params;
444 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
445 params.push_back(ParamDeclAttr::get(
"FROM_HOST_TYPE_ID",
getTypeID(type)));
447 ParamDeclAttr::get(
"FROM_HOST_SIZE_BITS",
448 rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
451 auto recvReady = bb.get(rewriter.getI1Type());
454 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
455 HWModuleExternOp endpoint =
459 Value operands[] = {adaptor.getClk(), adaptor.getRst(), recvReady};
461 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
462 ArrayAttr::get(ctxt, params));
465 Value recvDataFromCosim = cosimEpModule.getResult(1);
466 Value recvValidFromCosim = cosimEpModule.getResult(0);
467 Value castedRecvData;
468 Type castToType = windowType ? windowType.getLoweredType() : type.getInner();
474 rewriter, loc, rewriter.getIntegerType(0),
475 rewriter.getIntegerAttr(rewriter.getIntegerType(0), 0));
480 WrapWindow::create(rewriter, loc, windowType, castedRecvData);
482 WrapValidReadyOp wrapRecv = WrapValidReadyOp::create(
483 rewriter, loc, castedRecvData, recvValidFromCosim, type.getDataDelay());
484 recvReady.setValue(wrapRecv.getReady());
487 rewriter.replaceOp(ep, wrapRecv.getChanOutput());
496struct ManifestRomLowering :
public OpConversionPattern<CompressedManifestOp> {
498 using OpConversionPattern::OpConversionPattern;
499 constexpr static StringRef manifestRomName =
"__ESI_Manifest_ROM";
502 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
503 ConversionPatternRewriter &rewriter)
const override;
506 LogicalResult createRomModule(CompressedManifestOp op,
507 ConversionPatternRewriter &rewriter)
const;
511LogicalResult ManifestRomLowering::createRomModule(
512 CompressedManifestOp op, ConversionPatternRewriter &rewriter)
const {
513 Location loc = op.getLoc();
514 auto mlirModBody = op->getParentOfType<mlir::ModuleOp>();
515 rewriter.setInsertionPointToStart(mlirModBody.getBody());
519 if (Operation *existingExtern = mlirModBody.lookupSymbol(manifestRomName)) {
520 if (!isa<hw::HWModuleExternOp>(existingExtern))
521 return rewriter.notifyMatchFailure(
523 "Found " + manifestRomName +
" but it wasn't an HWModuleExternOp");
524 rewriter.eraseOp(existingExtern);
529 {{rewriter.getStringAttr(
"clk"), rewriter.getType<seq::ClockType>(),
530 ModulePort::Direction::Input}},
531 {{rewriter.getStringAttr(
"address"), rewriter.getIntegerType(29),
532 ModulePort::Direction::Input}},
533 {{rewriter.getStringAttr(
"data"), rewriter.getI64Type(),
534 ModulePort::Direction::Output}},
536 auto rom = HWModuleOp::create(rewriter, loc,
537 rewriter.getStringAttr(manifestRomName), ports);
538 Block *romBody = rom.getBodyBlock();
539 rewriter.setInsertionPointToStart(romBody);
540 Value
clk = romBody->getArgument(0);
541 Value inputAddress = romBody->getArgument(1);
544 ArrayRef<uint8_t> maniBytes = op.getCompressedManifest().getData();
545 SmallVector<uint64_t> words;
546 words.push_back(maniBytes.size());
548 for (
size_t i = 0; i < maniBytes.size() - 7; i += 8) {
550 for (
size_t b = 0; b < 8; ++b)
551 word |=
static_cast<uint64_t
>(maniBytes[i + b]) << (8 * b);
552 words.push_back(word);
554 size_t overHang = maniBytes.size() % 8;
557 for (
size_t i = 0; i < overHang; ++i)
558 word |=
static_cast<uint64_t
>(maniBytes[maniBytes.size() - overHang + i])
560 words.push_back(word);
565 SmallVector<Attribute> wordAttrs;
566 for (uint64_t word : words)
567 wordAttrs.push_back(rewriter.getI64IntegerAttr(word));
568 auto manifestConstant = hw::AggregateConstantOp::create(
570 hw::UnpackedArrayType::get(rewriter.getI64Type(), words.size()),
571 rewriter.getArrayAttr(wordAttrs));
577 size_t addrBits = llvm::Log2_64_Ceil(words.size());
582 sv::ArrayIndexInOutOp::create(rewriter, loc, manifestReg, inputAddresReg);
585 if (
auto *term = romBody->getTerminator())
586 rewriter.eraseOp(term);
587 hw::OutputOp::create(rewriter, loc, ValueRange{readDataReg});
591LogicalResult ManifestRomLowering::matchAndRewrite(
592 CompressedManifestOp op, OpAdaptor adaptor,
593 ConversionPatternRewriter &rewriter)
const {
594 LogicalResult ret = createRomModule(op, rewriter);
595 rewriter.eraseOp(op);
602struct CosimManifestLowering :
public ManifestRomLowering {
604 using ManifestRomLowering::ManifestRomLowering;
607 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
608 ConversionPatternRewriter &rewriter)
const final;
612LogicalResult CosimManifestLowering::matchAndRewrite(
613 CompressedManifestOp op, OpAdaptor adaptor,
614 ConversionPatternRewriter &rewriter)
const {
615 MLIRContext *ctxt = rewriter.getContext();
616 Location loc = op.getLoc();
620 LogicalResult ret = createRomModule(op, rewriter);
625 Attribute params[] = {
626 ParamDeclAttr::get(
"COMPRESSED_MANIFEST_SIZE", rewriter.getI32Type()),
627 ParamDeclAttr::get(
"ESI_VERSION", rewriter.getI32Type())};
629 {{rewriter.getStringAttr(
"compressed_manifest"),
630 rewriter.getType<hw::ArrayType>(
631 rewriter.getI8Type(),
632 ParamDeclRefAttr::get(
633 rewriter.getStringAttr(
"COMPRESSED_MANIFEST_SIZE"),
634 rewriter.getI32Type())),
635 ModulePort::Direction::Input},
638 rewriter.setInsertionPointToEnd(
639 op->getParentOfType<mlir::ModuleOp>().getBody());
640 auto cosimManifestExternModule = HWModuleExternOp::create(
641 rewriter, loc, rewriter.getStringAttr(
"Cosim_Manifest"), ports,
642 "Cosim_Manifest", ArrayAttr::get(ctxt, params));
644 hw::ModulePortInfo portInfo({});
645 auto manifestMod = hw::HWModuleOp::create(
646 rewriter, loc, rewriter.getStringAttr(
"__ESIManifest"), portInfo,
647 [&](OpBuilder &rewriter,
const hw::HWModulePortAccessor &) {
649 SmallVector<Attribute> bytes;
650 for (uint8_t b : op.getCompressedManifest().getData())
651 bytes.push_back(rewriter.getI8IntegerAttr(b));
652 auto manifestConstant = hw::AggregateConstantOp::create(
654 hw::ArrayType::get(rewriter.getI8Type(), bytes.size()),
655 rewriter.getArrayAttr(bytes));
657 sv::VarOp::create(rewriter, loc, manifestConstant.getType());
658 sv::VarAssignOp::create(rewriter, loc, manifestLogic, manifestConstant);
659 auto manifest = sv::ReadInOutOp::create(rewriter, loc, manifestLogic);
662 hw::InstanceOp::create(
663 rewriter, loc, cosimManifestExternModule,
"__manifest",
664 ArrayRef<Value>({manifest}),
665 rewriter.getArrayAttr({
666 ParamDeclAttr::get(
"COMPRESSED_MANIFEST_SIZE",
667 rewriter.getI32IntegerAttr(bytes.size())),
668 ParamDeclAttr::get(
"ESI_VERSION",
673 rewriter.setInsertionPoint(op);
674 hw::InstanceOp::create(rewriter, loc, manifestMod,
"__manifest",
675 ArrayRef<Value>({}));
677 rewriter.eraseOp(op);
684 return type.walk([](ChannelType) {
return WalkResult::interrupt(); })
696 SmallVector<Operation *> channelOps;
697 DenseSet<OperationName> seenOpNames;
698 RewritePatternSet canonPatterns(ctxt);
699 top->walk([&](Operation *op) {
703 channelOps.push_back(op);
704 if (std::optional<mlir::RegisteredOperationName> info =
705 op->getRegisteredInfo();
706 info && seenOpNames.insert(op->getName()).second)
707 info->getCanonicalizationPatterns(canonPatterns, ctxt);
709 mlir::GreedyRewriteConfig config;
710 config.setStrictness(mlir::GreedyRewriteStrictness::ExistingAndNewOps);
711 (void)mlir::applyOpPatternsGreedily(
712 channelOps, mlir::FrozenRewritePatternSet(std::move(canonPatterns)),
726 constexpr unsigned maxReported = 10;
727 unsigned numReported = 0;
728 auto *esiDialect = ctxt->getLoadedDialect<ESIDialect>();
729 top->walk([&](Operation *op) {
733 return WalkResult::advance();
736 if (op->getDialect() == esiDialect) {
737 op->emitError(
"lower-esi-to-hw left behind a channel operation");
738 if (++numReported >= maxReported)
739 return WalkResult::interrupt();
740 return WalkResult::advance();
749 for (Region ®ion : op->getRegions())
750 for (Block &block : region)
752 if (hasChannelType) {
753 op->emitError(
"lower-esi-to-hw left behind a channel-typed value");
754 if (++numReported >= maxReported)
755 return WalkResult::interrupt();
757 return WalkResult::advance();
759 return numReported == 0;
762void ESItoHWPass::runOnOperation() {
763 auto top = getOperation();
764 auto *ctxt = &getContext();
767 ConversionTarget noBundlesTarget(*ctxt);
768 noBundlesTarget.markUnknownOpDynamicallyLegal(
769 [](Operation *) {
return true; });
770 noBundlesTarget.addIllegalOp<PackBundleOp>();
771 noBundlesTarget.addIllegalOp<UnpackBundleOp>();
772 RewritePatternSet bundlePatterns(&getContext());
773 bundlePatterns.add<CanonicalizerOpLowering<PackBundleOp>>(&getContext());
774 bundlePatterns.add<CanonicalizerOpLowering<UnpackBundleOp>>(&getContext());
775 if (failed(applyPartialConversion(getOperation(), noBundlesTarget,
776 std::move(bundlePatterns)))) {
782 ConversionTarget pass1Target(*ctxt);
783 pass1Target.addLegalDialect<comb::CombDialect>();
784 pass1Target.addLegalDialect<HWDialect>();
785 pass1Target.addLegalDialect<SVDialect>();
786 pass1Target.addLegalDialect<seq::SeqDialect>();
787 pass1Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
788 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp,
789 WrapWindow, UnwrapWindow>();
790 pass1Target.addLegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
792 pass1Target.addIllegalOp<PipelineStageOp>();
793 pass1Target.addIllegalOp<CompressedManifestOp>();
796 ESIHWBuilder esiBuilder(top);
797 RewritePatternSet pass1Patterns(ctxt);
798 pass1Patterns.insert<PipelineStageLowering>(esiBuilder, ctxt);
799 pass1Patterns.insert<CosimToHostLowering>(esiBuilder);
800 pass1Patterns.insert<CosimFromHostLowering>(esiBuilder);
801 pass1Patterns.insert<NullSourceOpLowering>(ctxt);
804 pass1Patterns.insert<CosimManifestLowering>(ctxt);
806 pass1Patterns.insert<ManifestRomLowering>(ctxt);
808 pass1Patterns.insert<RemoveOpLowering<CompressedManifestOp>>(ctxt);
812 applyPartialConversion(top, pass1Target, std::move(pass1Patterns)))) {
818 ConversionTarget pass2Target(*ctxt);
819 pass2Target.addLegalDialect<comb::CombDialect>();
820 pass2Target.addLegalDialect<HWDialect>();
821 pass2Target.addLegalDialect<SVDialect>();
822 pass2Target.addIllegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
823 pass2Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
824 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp>();
825 RewritePatternSet pass2Patterns(ctxt);
826 pass2Patterns.insert<RemoveSnoopOp>(ctxt);
827 pass2Patterns.insert<RemoveSnoopTransactionOp>(ctxt);
829 applyPartialConversion(top, pass2Target, std::move(pass2Patterns)))) {
845 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
void setValue(mlir::Value)
Trait marking an ESI op that operates on ESI types (e.g.
hw::HWModuleExternOp declareCosimEndpointFromHostModule(Operation *symTable)
hw::HWModuleExternOp declareCosimEndpointToHostModule(Operation *symTable)
Write an 'ExternModuleOp' to use a hand-coded SystemVerilog module.
ArrayAttr getStageParameterList(Attribute widthValue, Attribute dataDelayValue)
Get the parameter list for the stage module.
hw::HWModuleExternOp declareStage(Operation *symTable, PipelineStageOp)
Write an 'ExternModuleOp' to use a hand-coded SystemVerilog module.
create(cls, result_type, reset=None, reset_value=None, name=None, sym_name=None, **kwargs)
create(data_type, name=None, sym_name=None)
uint64_t getWidth(Type t)
StringAttr getTypeID(Type t)
std::unique_ptr< OperationPass< ModuleOp > > createESItoHWPass()
constexpr uint64_t esiApiVersion
ESI ABI version.
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.