13#include "../PassDetails.h"
24#include "mlir/Transforms/DialectConversion.h"
26#include "llvm/ADT/StringExtras.h"
27#include "llvm/ADT/TypeSwitch.h"
28#include "llvm/Support/JSON.h"
32#define GEN_PASS_DEF_LOWERESITOHW
33#include "circt/Dialect/ESI/ESIPasses.h.inc"
49 PipelineStageLowering(
ESIHWBuilder &builder, MLIRContext *ctxt)
51 using OpConversionPattern::OpConversionPattern;
54 matchAndRewrite(PipelineStageOp stage, OpAdaptor adaptor,
55 ConversionPatternRewriter &rewriter)
const final;
62LogicalResult PipelineStageLowering::matchAndRewrite(
63 PipelineStageOp stage, OpAdaptor adaptor,
64 ConversionPatternRewriter &rewriter)
const {
65 auto loc = stage.getLoc();
66 auto chPort = dyn_cast<ChannelType>(stage.getInput().getType());
68 return rewriter.notifyMatchFailure(stage,
"stage had wrong type");
69 Operation *symTable = stage->getParentWithTrait<OpTrait::SymbolTable>();
70 auto stageModule = builder.declareStage(symTable, stage);
74 ArrayAttr stageParams =
75 builder.getStageParameterList(rewriter.getUI32IntegerAttr(width));
83 UnwrapValidReadyOp::create(rewriter, loc, stage.getInput(), wrapReady);
85 StringRef pipeStageName =
"pipelineStage";
86 if (
auto name = stage->getAttrOfType<StringAttr>(
"name"))
87 pipeStageName = name.getValue();
91 llvm::SmallVector<Value> operands = {stage.getClk(), stage.getRst()};
92 operands.push_back(
unwrap.getRawOutput());
93 operands.push_back(
unwrap.getValid());
94 operands.push_back(stageReady);
95 auto stageInst = hw::InstanceOp::create(rewriter, loc, stageModule,
96 pipeStageName, operands, stageParams);
97 auto stageInstResults = stageInst.getResults();
101 wrapReady.
setValue(stageInstResults[0]);
103 x = stageInstResults[1];
104 xValid = stageInstResults[2];
107 auto wrap = WrapValidReadyOp::create(rewriter, loc, chPort,
108 rewriter.getI1Type(), x, xValid);
112 rewriter.replaceOp(stage,
wrap.getChanOutput());
120 using OpConversionPattern::OpConversionPattern;
123 matchAndRewrite(NullSourceOp nullop, OpAdaptor adaptor,
124 ConversionPatternRewriter &rewriter)
const final;
128LogicalResult NullSourceOpLowering::matchAndRewrite(
129 NullSourceOp nullop, OpAdaptor adaptor,
130 ConversionPatternRewriter &rewriter)
const {
131 auto chanType = cast<ChannelType>(nullop.getOut().getType());
133 Location loc = nullop.getLoc();
134 int64_t width = hw::getBitWidth(
innerType);
136 return rewriter.notifyMatchFailure(
137 nullop,
"NullOp lowering only supports hw types");
139 rewriter.getI1Type(), 0);
144 if (chanType.getSignaling() == ChannelSignaling::ValidOnly) {
145 auto wrap = WrapValidOnlyOp::create(rewriter, loc, typedZero, valid);
146 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
147 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
149 auto wrap = WrapValidReadyOp::create(rewriter, loc, typedZero, valid);
150 wrap->setAttr(
"name", rewriter.getStringAttr(
"nullsource"));
151 rewriter.replaceOp(nullop, {
wrap.getChanOutput()});
160 using OpConversionPattern::OpConversionPattern;
163 matchAndRewrite(WrapValidOnlyOp
wrap, OpAdaptor adaptor,
164 ConversionPatternRewriter &rewriter)
const override {
165 if (ChannelType::hasNoConsumers(
wrap.getChanOutput())) {
166 rewriter.eraseOp(
wrap);
169 if (!ChannelType::hasOneConsumer(
wrap.getChanOutput()))
170 return rewriter.notifyMatchFailure(
171 wrap,
"ValidOnly wrap didn't have exactly one consumer.");
172 auto unwrap = dyn_cast<UnwrapValidOnlyOp>(
173 ChannelType::getSingleConsumer(
wrap.getChanOutput())->getOwner());
175 return rewriter.notifyMatchFailure(
176 wrap,
"ValidOnly wrap consumer is not an unwrap.vo.");
177 rewriter.replaceOp(
unwrap, {adaptor.getRawInput(), adaptor.getValid()});
178 rewriter.eraseOp(
wrap);
186 using OpConversionPattern::OpConversionPattern;
189 matchAndRewrite(UnwrapValidOnlyOp
unwrap, OpAdaptor adaptor,
190 ConversionPatternRewriter &rewriter)
const override {
191 auto wrap = dyn_cast_or_null<WrapValidOnlyOp>(
192 adaptor.getChanInput().getDefiningOp());
194 return rewriter.notifyMatchFailure(
195 unwrap,
"unwrap.vo input must come from a wrap.vo.");
196 if (!ChannelType::hasOneConsumer(
wrap.getChanOutput()))
197 return rewriter.notifyMatchFailure(
198 wrap,
"ValidOnly wrap didn't have exactly one consumer.");
199 rewriter.replaceOp(
unwrap, {
wrap.getRawInput(),
wrap.getValid()});
200 rewriter.eraseOp(
wrap);
208 using OpConversionPattern::OpConversionPattern;
211 matchAndRewrite(WrapValidReadyOp
wrap, OpAdaptor adaptor,
212 ConversionPatternRewriter &rewriter)
const override {
213 if (ChannelType::hasNoConsumers(
wrap.getChanOutput())) {
215 rewriter.getI1Type(), 1);
216 rewriter.replaceOp(
wrap, {
nullptr, c1});
219 if (!ChannelType::hasOneConsumer(
wrap.getChanOutput()))
220 return rewriter.notifyMatchFailure(
221 wrap,
"Wrap didn't have exactly one consumer.");
222 auto unwrap = dyn_cast<UnwrapValidReadyOp>(
223 ChannelType::getSingleConsumer(
wrap.getChanOutput())->getOwner());
225 return rewriter.notifyMatchFailure(
wrap,
226 "Wrap consumer is not an unwrap.vr.");
227 rewriter.replaceOp(
wrap, {
nullptr,
unwrap.getReady()});
228 rewriter.replaceOp(
unwrap, {adaptor.getRawInput(), adaptor.getValid()});
234struct RemoveUnwrapValidReadyOp
237 using OpConversionPattern::OpConversionPattern;
240 matchAndRewrite(UnwrapValidReadyOp
unwrap, OpAdaptor adaptor,
241 ConversionPatternRewriter &rewriter)
const override {
242 auto wrap = dyn_cast_or_null<WrapValidReadyOp>(
243 adaptor.getChanInput().getDefiningOp());
245 return rewriter.notifyMatchFailure(
246 unwrap,
"unwrap.vr input must come from a wrap.vr.");
247 if (!ChannelType::hasOneConsumer(
wrap.getChanOutput()))
248 return rewriter.notifyMatchFailure(
249 wrap,
"Wrap didn't have exactly one consumer.");
250 rewriter.replaceOp(
wrap, {
nullptr, adaptor.getReady()});
251 rewriter.replaceOp(
unwrap, {
wrap.getRawInput(),
wrap.getValid()});
263 using OpConversionPattern::OpConversionPattern;
266 matchAndRewrite(SnoopValidReadyOp op, SnoopValidReadyOpAdaptor operands,
267 ConversionPatternRewriter &rewriter)
const override {
268 Operation *defOp = op.getInput().getDefiningOp();
270 return rewriter.notifyMatchFailure(op,
271 "snoop input is not defined by an op");
272 auto wrap = dyn_cast<WrapValidReadyOp>(defOp);
274 return rewriter.notifyMatchFailure(
275 defOp,
"Snoop input must be a wrap.vr operation");
278 Value valid =
wrap.getValid();
283 auto *unwrapOpOperand =
284 ChannelType::getSingleConsumer(
wrap.getChanOutput());
286 if (unwrapOpOperand &&
287 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
289 auto unwrap = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
290 ready =
unwrap.getReady();
294 assert(!unwrapOpOperand &&
295 "Expected no consumer or consumer should be an unwrap");
297 rewriter.getI1Type(), 0);
300 rewriter.replaceOp(op, {valid, ready,
data});
310struct RemoveSnoopTransactionOp
313 using OpConversionPattern::OpConversionPattern;
316 matchAndRewrite(SnoopTransactionOp op, SnoopTransactionOpAdaptor operands,
317 ConversionPatternRewriter &rewriter)
const override {
318 Operation *defOp = op.getInput().getDefiningOp();
320 return rewriter.notifyMatchFailure(op,
321 "snoop input is not defined by an op");
324 if (
auto wrapVR = dyn_cast<WrapValidReadyOp>(defOp)) {
325 Value
data = wrapVR.getRawInput();
326 Value valid = wrapVR.getValid();
330 auto *unwrapOpOperand =
331 ChannelType::getSingleConsumer(wrapVR.getChanOutput());
333 if (unwrapOpOperand &&
334 isa<UnwrapValidReadyOp>(unwrapOpOperand->getOwner())) {
336 auto unwrapVR = cast<UnwrapValidReadyOp>(unwrapOpOperand->getOwner());
337 ready = unwrapVR.getReady();
340 assert(!unwrapOpOperand &&
341 "Expected no consumer or consumer should be an unwrap");
343 rewriter.getI1Type(), 0);
348 comb::AndOp::create(rewriter, op.getLoc(), valid, ready);
350 rewriter.replaceOp(op, {transaction,
data});
355 if (
auto wrapFIFO = dyn_cast<WrapFIFOOp>(defOp)) {
356 Value
data = wrapFIFO.getData();
357 Value
empty = wrapFIFO.getEmpty();
361 auto *unwrapOpOperand =
362 ChannelType::getSingleConsumer(wrapFIFO.getChanOutput());
364 if (unwrapOpOperand && isa<UnwrapFIFOOp>(unwrapOpOperand->getOwner())) {
366 auto unwrapFIFO = cast<UnwrapFIFOOp>(unwrapOpOperand->getOwner());
367 rden = unwrapFIFO.getRden();
370 assert(!unwrapOpOperand &&
371 "Expected no consumer or consumer should be an unwrap");
373 rewriter.getI1Type(), 0);
377 auto notEmpty = comb::XorOp::create(
378 rewriter, op.getLoc(),
empty,
380 rewriter.getBoolAttr(
true)));
382 comb::AndOp::create(rewriter, op.getLoc(), notEmpty, rden);
384 rewriter.replaceOp(op, {transaction,
data});
389 if (
auto wrapVO = dyn_cast<WrapValidOnlyOp>(defOp)) {
390 Value
data = wrapVO.getRawInput();
391 Value valid = wrapVO.getValid();
393 rewriter.replaceOp(op, {valid,
data});
397 return rewriter.notifyMatchFailure(
399 "Snoop input must be a wrap.vr, wrap.fifo, or wrap.vo operation");
407template <
typename Op>
413 matchAndRewrite(Op op,
typename Op::Adaptor adaptor,
414 ConversionPatternRewriter &rewriter)
const final {
415 if (failed(Op::canonicalize(op, rewriter)))
416 return rewriter.notifyMatchFailure(op->getLoc(),
"canonicalizer failed");
423struct ESItoHWPass :
public circt::esi::impl::LowerESItoHWBase<ESItoHWPass> {
424 void runOnOperation()
override;
433 using OpConversionPattern::OpConversionPattern;
436 matchAndRewrite(WrapSVInterfaceOp
wrap, OpAdaptor adaptor,
437 ConversionPatternRewriter &rewriter)
const final;
442WrapInterfaceLower::matchAndRewrite(WrapSVInterfaceOp
wrap, OpAdaptor adaptor,
443 ConversionPatternRewriter &rewriter)
const {
444 auto operands = adaptor.getOperands();
445 if (operands.size() != 1)
446 return rewriter.notifyMatchFailure(
wrap, [&operands](Diagnostic &d) {
447 d <<
"wrap.iface has 1 argument. Got " << operands.size() <<
"operands";
449 auto sinkModport = dyn_cast<GetModportOp>(operands[0].getDefiningOp());
453 dyn_cast<InterfaceInstanceOp>(sinkModport.getIface().getDefiningOp());
457 auto loc =
wrap.getLoc();
458 auto validSignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
461 dataSignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
464 WrapValidReadyOp::create(rewriter, loc, dataSignal, validSignal);
465 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
467 rewriter.replaceOp(
wrap, {wrapVR.getChanOutput()});
477 using OpConversionPattern::OpConversionPattern;
480 matchAndRewrite(UnwrapSVInterfaceOp
wrap, OpAdaptor adaptor,
481 ConversionPatternRewriter &rewriter)
const final;
485LogicalResult UnwrapInterfaceLower::matchAndRewrite(
486 UnwrapSVInterfaceOp
unwrap, OpAdaptor adaptor,
487 ConversionPatternRewriter &rewriter)
const {
488 auto operands = adaptor.getOperands();
489 if (operands.size() != 2)
490 return rewriter.notifyMatchFailure(
unwrap, [&operands](Diagnostic &d) {
491 d <<
"Unwrap.iface has 2 arguments. Got " << operands.size()
495 auto sourceModport = dyn_cast<GetModportOp>(operands[1].getDefiningOp());
499 dyn_cast<InterfaceInstanceOp>(sourceModport.getIface().getDefiningOp());
503 auto loc =
unwrap.getLoc();
504 auto readySignal = ReadInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
507 UnwrapValidReadyOp::create(rewriter, loc, operands[0], readySignal);
508 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
511 AssignInterfaceSignalOp::create(rewriter, loc, ifaceInstance,
513 unwrapVR.getRawOutput());
526 using OpConversionPattern::OpConversionPattern;
529 matchAndRewrite(CosimToHostEndpointOp, OpAdaptor adaptor,
530 ConversionPatternRewriter &rewriter)
const final;
537LogicalResult CosimToHostLowering::matchAndRewrite(
538 CosimToHostEndpointOp ep, OpAdaptor adaptor,
539 ConversionPatternRewriter &rewriter)
const {
540 auto loc = ep.getLoc();
541 auto *ctxt = rewriter.getContext();
544 Value toHost = adaptor.getToHost();
545 Type type = toHost.getType();
546 auto chanTy = dyn_cast<ChannelType>(type);
550 SmallVector<Attribute, 8> params;
551 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
552 params.push_back(ParamDeclAttr::get(
"TO_HOST_TYPE_ID",
getTypeID(type)));
553 params.push_back(ParamDeclAttr::get(
554 "TO_HOST_SIZE_BITS", rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
557 auto sendReady = bb.get(rewriter.getI1Type());
558 UnwrapValidReadyOp unwrapSend =
559 UnwrapValidReadyOp::create(rewriter, loc, toHost, sendReady);
561 Value rawSendData = unwrapSend.getRawOutput();
564 if (WindowType windowType = dyn_cast_or_null<WindowType>(chanTy.getInner()))
565 rawSendData = UnwrapWindow::create(rewriter, loc, rawSendData);
567 Value castedSendData;
570 rewriter, loc, rewriter.getIntegerType(width), rawSendData);
573 rewriter, loc, rewriter.getIntegerType(1), rewriter.getBoolAttr(
false));
576 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
577 HWModuleExternOp endpoint =
578 builder.declareCosimEndpointToHostModule(symTable);
584 unwrapSend.getValid(),
588 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
589 ArrayAttr::get(ctxt, params));
590 sendReady.setValue(cosimEpModule.getResult(0));
593 rewriter.eraseOp(ep);
601struct CosimFromHostLowering
607 using OpConversionPattern::OpConversionPattern;
610 matchAndRewrite(CosimFromHostEndpointOp, OpAdaptor adaptor,
611 ConversionPatternRewriter &rewriter)
const final;
618LogicalResult CosimFromHostLowering::matchAndRewrite(
619 CosimFromHostEndpointOp ep, OpAdaptor adaptor,
620 ConversionPatternRewriter &rewriter)
const {
621 auto loc = ep.getLoc();
622 auto *ctxt = rewriter.getContext();
625 ChannelType type = ep.getFromHost().getType();
626 WindowType windowType = dyn_cast<WindowType>(type.getInner());
630 SmallVector<Attribute, 8> params;
631 params.push_back(ParamDeclAttr::get(
"ENDPOINT_ID", ep.getIdAttr()));
632 params.push_back(ParamDeclAttr::get(
"FROM_HOST_TYPE_ID",
getTypeID(type)));
634 ParamDeclAttr::get(
"FROM_HOST_SIZE_BITS",
635 rewriter.getI32IntegerAttr(width > 0 ? width : 1)));
638 auto recvReady = bb.get(rewriter.getI1Type());
641 Operation *symTable = ep->getParentWithTrait<OpTrait::SymbolTable>();
642 HWModuleExternOp endpoint =
643 builder.declareCosimEndpointFromHostModule(symTable);
646 Value operands[] = {adaptor.getClk(), adaptor.getRst(), recvReady};
648 hw::InstanceOp::create(rewriter, loc, endpoint, ep.getIdAttr(), operands,
649 ArrayAttr::get(ctxt, params));
652 Value recvDataFromCosim = cosimEpModule.getResult(1);
653 Value recvValidFromCosim = cosimEpModule.getResult(0);
654 Value castedRecvData;
655 Type castToType = windowType ? windowType.getLoweredType() : type.getInner();
661 rewriter, loc, rewriter.getIntegerType(0),
662 rewriter.getIntegerAttr(rewriter.getIntegerType(0), 0));
667 WrapWindow::create(rewriter, loc, windowType, castedRecvData);
669 WrapValidReadyOp wrapRecv = WrapValidReadyOp::create(
670 rewriter, loc, castedRecvData, recvValidFromCosim);
671 recvReady.setValue(wrapRecv.getReady());
674 rewriter.replaceOp(ep, wrapRecv.getChanOutput());
685 using OpConversionPattern::OpConversionPattern;
686 constexpr static StringRef manifestRomName =
"__ESI_Manifest_ROM";
689 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
690 ConversionPatternRewriter &rewriter)
const override;
693 LogicalResult createRomModule(CompressedManifestOp op,
694 ConversionPatternRewriter &rewriter)
const;
698LogicalResult ManifestRomLowering::createRomModule(
699 CompressedManifestOp op, ConversionPatternRewriter &rewriter)
const {
700 Location loc = op.getLoc();
701 auto mlirModBody = op->getParentOfType<mlir::ModuleOp>();
702 rewriter.setInsertionPointToStart(mlirModBody.getBody());
706 if (Operation *existingExtern = mlirModBody.lookupSymbol(manifestRomName)) {
707 if (!isa<hw::HWModuleExternOp>(existingExtern))
708 return rewriter.notifyMatchFailure(
710 "Found " + manifestRomName +
" but it wasn't an HWModuleExternOp");
711 rewriter.eraseOp(existingExtern);
716 {{rewriter.getStringAttr(
"clk"), rewriter.getType<seq::ClockType>(),
717 ModulePort::Direction::Input}},
718 {{rewriter.getStringAttr(
"address"), rewriter.getIntegerType(29),
719 ModulePort::Direction::Input}},
720 {{rewriter.getStringAttr(
"data"), rewriter.getI64Type(),
721 ModulePort::Direction::Output}},
723 auto rom = HWModuleOp::create(rewriter, loc,
724 rewriter.getStringAttr(manifestRomName), ports);
725 Block *romBody = rom.getBodyBlock();
726 rewriter.setInsertionPointToStart(romBody);
727 Value
clk = romBody->getArgument(0);
728 Value inputAddress = romBody->getArgument(1);
731 ArrayRef<uint8_t> maniBytes = op.getCompressedManifest().getData();
732 SmallVector<uint64_t> words;
733 words.push_back(maniBytes.size());
735 for (
size_t i = 0; i < maniBytes.size() - 7; i += 8) {
737 for (
size_t b = 0;
b < 8; ++
b)
738 word |=
static_cast<uint64_t
>(maniBytes[i + b]) << (8 *
b);
739 words.push_back(word);
741 size_t overHang = maniBytes.size() % 8;
744 for (
size_t i = 0; i < overHang; ++i)
745 word |=
static_cast<uint64_t
>(maniBytes[maniBytes.size() - overHang + i])
747 words.push_back(word);
752 SmallVector<Attribute> wordAttrs;
753 for (uint64_t word : words)
754 wordAttrs.push_back(rewriter.getI64IntegerAttr(word));
755 auto manifestConstant = hw::AggregateConstantOp::create(
757 hw::UnpackedArrayType::get(rewriter.getI64Type(), words.size()),
758 rewriter.getArrayAttr(wordAttrs));
760 sv::RegOp::create(rewriter, loc, manifestConstant.getType());
764 size_t addrBits = llvm::Log2_64_Ceil(words.size());
769 sv::ArrayIndexInOutOp::create(rewriter, loc, manifestReg, inputAddresReg);
772 if (
auto *term = romBody->getTerminator())
773 rewriter.eraseOp(term);
774 hw::OutputOp::create(rewriter, loc, ValueRange{readDataReg});
778LogicalResult ManifestRomLowering::matchAndRewrite(
779 CompressedManifestOp op, OpAdaptor adaptor,
780 ConversionPatternRewriter &rewriter)
const {
781 LogicalResult ret = createRomModule(op, rewriter);
782 rewriter.eraseOp(op);
789struct CosimManifestLowering :
public ManifestRomLowering {
791 using ManifestRomLowering::ManifestRomLowering;
794 matchAndRewrite(CompressedManifestOp, OpAdaptor adaptor,
795 ConversionPatternRewriter &rewriter)
const final;
799LogicalResult CosimManifestLowering::matchAndRewrite(
800 CompressedManifestOp op, OpAdaptor adaptor,
801 ConversionPatternRewriter &rewriter)
const {
802 MLIRContext *ctxt = rewriter.getContext();
803 Location loc = op.getLoc();
807 LogicalResult ret = createRomModule(op, rewriter);
812 Attribute params[] = {
813 ParamDeclAttr::get(
"COMPRESSED_MANIFEST_SIZE", rewriter.getI32Type())};
815 {{rewriter.getStringAttr(
"compressed_manifest"),
816 rewriter.getType<hw::ArrayType>(
817 rewriter.getI8Type(),
818 ParamDeclRefAttr::get(
819 rewriter.getStringAttr(
"COMPRESSED_MANIFEST_SIZE"),
820 rewriter.getI32Type())),
821 ModulePort::Direction::Input},
824 rewriter.setInsertionPointToEnd(
825 op->getParentOfType<mlir::ModuleOp>().getBody());
826 auto cosimManifestExternModule = HWModuleExternOp::create(
827 rewriter, loc, rewriter.getStringAttr(
"Cosim_Manifest"), ports,
828 "Cosim_Manifest", ArrayAttr::get(ctxt, params));
831 auto manifestMod = hw::HWModuleOp::create(
832 rewriter, loc, rewriter.getStringAttr(
"__ESIManifest"), portInfo,
835 SmallVector<Attribute> bytes;
836 for (uint8_t b : op.getCompressedManifest().getData())
837 bytes.push_back(rewriter.getI8IntegerAttr(b));
838 auto manifestConstant = hw::AggregateConstantOp::create(
840 hw::ArrayType::get(rewriter.getI8Type(), bytes.size()),
841 rewriter.getArrayAttr(bytes));
843 sv::LogicOp::create(rewriter, loc, manifestConstant.getType());
844 sv::AssignOp::create(rewriter, loc, manifestLogic, manifestConstant);
845 auto manifest = sv::ReadInOutOp::create(rewriter, loc, manifestLogic);
848 hw::InstanceOp::create(rewriter, loc, cosimManifestExternModule,
849 "__manifest", ArrayRef<Value>({manifest}),
850 rewriter.getArrayAttr({ParamDeclAttr::get(
851 "COMPRESSED_MANIFEST_SIZE",
852 rewriter.getI32IntegerAttr(bytes.size()))}));
855 rewriter.setInsertionPoint(op);
856 hw::InstanceOp::create(rewriter, loc, manifestMod,
"__manifest",
857 ArrayRef<Value>({}));
859 rewriter.eraseOp(op);
862void ESItoHWPass::runOnOperation() {
863 auto top = getOperation();
864 auto *ctxt = &getContext();
867 ConversionTarget noBundlesTarget(*ctxt);
868 noBundlesTarget.markUnknownOpDynamicallyLegal(
869 [](Operation *) {
return true; });
870 noBundlesTarget.addIllegalOp<PackBundleOp>();
871 noBundlesTarget.addIllegalOp<UnpackBundleOp>();
872 RewritePatternSet bundlePatterns(&getContext());
873 bundlePatterns.add<CanonicalizerOpLowering<PackBundleOp>>(&getContext());
874 bundlePatterns.add<CanonicalizerOpLowering<UnpackBundleOp>>(&getContext());
875 if (failed(applyPartialConversion(getOperation(), noBundlesTarget,
876 std::move(bundlePatterns)))) {
882 ConversionTarget pass1Target(*ctxt);
883 pass1Target.addLegalDialect<comb::CombDialect>();
884 pass1Target.addLegalDialect<HWDialect>();
885 pass1Target.addLegalDialect<SVDialect>();
886 pass1Target.addLegalDialect<seq::SeqDialect>();
887 pass1Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
888 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp,
889 WrapWindow, UnwrapWindow>();
890 pass1Target.addLegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
892 pass1Target.addIllegalOp<WrapSVInterfaceOp, UnwrapSVInterfaceOp>();
893 pass1Target.addIllegalOp<PipelineStageOp>();
894 pass1Target.addIllegalOp<CompressedManifestOp>();
898 RewritePatternSet pass1Patterns(ctxt);
899 pass1Patterns.insert<PipelineStageLowering>(esiBuilder, ctxt);
900 pass1Patterns.insert<WrapInterfaceLower>(ctxt);
901 pass1Patterns.insert<UnwrapInterfaceLower>(ctxt);
902 pass1Patterns.insert<CosimToHostLowering>(esiBuilder);
903 pass1Patterns.insert<CosimFromHostLowering>(esiBuilder);
904 pass1Patterns.insert<NullSourceOpLowering>(ctxt);
907 pass1Patterns.insert<CosimManifestLowering>(ctxt);
909 pass1Patterns.insert<ManifestRomLowering>(ctxt);
915 applyPartialConversion(top, pass1Target, std::move(pass1Patterns)))) {
921 ConversionTarget pass2Target(*ctxt);
922 pass2Target.addLegalDialect<comb::CombDialect>();
923 pass2Target.addLegalDialect<HWDialect>();
924 pass2Target.addLegalDialect<SVDialect>();
925 pass2Target.addIllegalOp<SnoopTransactionOp, SnoopValidReadyOp>();
926 pass2Target.addLegalOp<WrapValidReadyOp, UnwrapValidReadyOp, WrapFIFOOp,
927 UnwrapFIFOOp, WrapValidOnlyOp, UnwrapValidOnlyOp>();
928 RewritePatternSet pass2Patterns(ctxt);
929 pass2Patterns.insert<RemoveSnoopOp>(ctxt);
930 pass2Patterns.insert<RemoveSnoopTransactionOp>(ctxt);
932 applyPartialConversion(top, pass2Target, std::move(pass2Patterns)))) {
938 ConversionTarget pass3Target(*ctxt);
939 pass3Target.addLegalDialect<comb::CombDialect>();
940 pass3Target.addLegalDialect<HWDialect>();
941 pass3Target.addLegalDialect<SVDialect>();
942 pass3Target.addIllegalDialect<ESIDialect>();
943 pass3Target.addLegalOp<WrapWindow, UnwrapWindow>();
945 RewritePatternSet pass3Patterns(ctxt);
946 pass3Patterns.insert<CanonicalizerOpLowering<UnwrapFIFOOp>>(ctxt);
947 pass3Patterns.insert<CanonicalizerOpLowering<WrapFIFOOp>>(ctxt);
948 pass3Patterns.insert<CanonicalizerOpLowering<UnwrapValidOnlyOp>>(ctxt);
949 pass3Patterns.insert<CanonicalizerOpLowering<WrapValidOnlyOp>>(ctxt);
950 pass3Patterns.insert<RemoveWrapValidOnlyOp>(ctxt);
951 pass3Patterns.insert<RemoveUnwrapValidOnlyOp>(ctxt);
952 pass3Patterns.insert<RemoveWrapValidReadyOp>(ctxt);
953 pass3Patterns.insert<RemoveUnwrapValidReadyOp>(ctxt);
955 applyPartialConversion(top, pass3Target, std::move(pass3Patterns))))
960 return std::make_unique<ESItoHWPass>();
assert(baseType &&"element must be base type")
return wrap(CMemoryType::get(unwrap(ctx), baseType, numElements))
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)
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.