21#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
22#include "mlir/Dialect/Arith/IR/Arith.h"
23#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
24#include "mlir/Dialect/ControlFlow/Transforms/StructuralTypeConversions.h"
25#include "mlir/Dialect/Func/IR/FuncOps.h"
26#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
27#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
28#include "mlir/Dialect/Math/IR/Math.h"
29#include "mlir/Dialect/SCF/IR/SCF.h"
30#include "mlir/IR/BuiltinDialect.h"
31#include "mlir/IR/Iterators.h"
32#include "mlir/Interfaces/SideEffectInterfaces.h"
33#include "mlir/Pass/Pass.h"
34#include "mlir/Transforms/DialectConversion.h"
35#include "mlir/Transforms/RegionUtils.h"
36#include "llvm/ADT/TypeSwitch.h"
37#include "llvm/IR/DerivedTypes.h"
40#define GEN_PASS_DEF_CONVERTMOORETOCORE
41#include "circt/Conversion/Passes.h.inc"
48using comb::ICmpPredicate;
49using llvm::SmallDenseSet;
54struct ClassTypeCache {
55 struct ClassStructInfo {
56 LLVM::LLVMStructType classBody;
59 DenseMap<StringRef, SmallVector<unsigned, 2>> propertyPath;
63 void setFieldPath(StringRef propertyName, ArrayRef<unsigned> path) {
64 this->propertyPath[propertyName] =
65 SmallVector<unsigned, 2>(path.begin(), path.end());
69 std::optional<ArrayRef<unsigned>>
70 getFieldPath(StringRef propertySym)
const {
71 if (
auto prop = this->propertyPath.find(propertySym);
72 prop != this->propertyPath.end())
73 return ArrayRef<unsigned>(prop->second);
80 void setClassInfo(SymbolRefAttr classSym,
const ClassStructInfo &
info) {
81 auto &dst = classToStructMap[classSym];
86 std::optional<ClassStructInfo> getStructInfo(SymbolRefAttr classSym)
const {
87 if (
auto it = classToStructMap.find(classSym); it != classToStructMap.end())
96 DenseMap<Attribute, ClassStructInfo> classToStructMap;
100static LLVM::LLVMFuncOp getOrCreateMalloc(ModuleOp mod, OpBuilder &b) {
101 if (
auto f = mod.lookupSymbol<LLVM::LLVMFuncOp>(
"malloc"))
104 OpBuilder::InsertionGuard g(b);
105 b.setInsertionPointToStart(mod.getBody());
107 auto i64Ty = IntegerType::get(mod.getContext(), 64);
108 auto ptrTy = LLVM::LLVMPointerType::get(mod.getContext());
109 auto fnTy = LLVM::LLVMFunctionType::get(ptrTy, {i64Ty},
false);
111 auto fn = LLVM::LLVMFuncOp::create(b, mod.getLoc(),
"malloc", fnTy);
113 fn.setLinkage(LLVM::Linkage::External);
119static LLVM::LLVMStructType getOrCreateOpaqueStruct(MLIRContext *ctx,
120 SymbolRefAttr className) {
121 return LLVM::LLVMStructType::getIdentified(ctx, className.getRootReference());
124static LogicalResult resolveClassStructBody(ClassDeclOp op,
125 TypeConverter
const &typeConverter,
126 ClassTypeCache &cache) {
128 auto classSym = SymbolRefAttr::get(op.getSymNameAttr());
129 auto structInfo = cache.getStructInfo(classSym);
135 ClassTypeCache::ClassStructInfo structBody;
136 SmallVector<Type> structBodyMembers;
139 unsigned derivedStartIdx = 0;
141 if (
auto baseClass = op.getBaseAttr()) {
143 ModuleOp mod = op->getParentOfType<ModuleOp>();
144 auto *opSym = mod.lookupSymbol(baseClass);
145 auto classDeclOp = cast<ClassDeclOp>(opSym);
147 if (failed(resolveClassStructBody(classDeclOp, typeConverter, cache)))
151 auto baseClassStruct = cache.getStructInfo(baseClass);
152 structBodyMembers.push_back(baseClassStruct->classBody);
156 for (
auto &kv : baseClassStruct->propertyPath) {
157 SmallVector<unsigned, 2> path;
159 path.append(kv.second.begin(), kv.second.end());
160 structBody.setFieldPath(kv.first, path);
165 unsigned iterator = derivedStartIdx;
166 auto &block = op.getBody().front();
167 for (Operation &child : block) {
168 if (
auto prop = dyn_cast<ClassPropertyDeclOp>(child)) {
169 Type mooreTy = prop.getPropertyType();
170 Type llvmTy = typeConverter.convertType(mooreTy);
172 return prop.emitOpError()
173 <<
"failed to convert property type " << mooreTy;
175 structBodyMembers.push_back(llvmTy);
178 SmallVector<unsigned, 2> path{iterator};
179 structBody.setFieldPath(prop.getSymName(), path);
185 auto llvmStructTy = getOrCreateOpaqueStruct(op.getContext(), classSym);
187 if (!structBodyMembers.empty() &&
188 failed(llvmStructTy.setBody(structBodyMembers,
false)))
189 return op.emitOpError() <<
"Failed to set LLVM Struct body";
191 structBody.classBody = llvmStructTy;
192 cache.setClassInfo(classSym, structBody);
198static LogicalResult resolveClassStructBody(ModuleOp mod, SymbolRefAttr op,
199 TypeConverter
const &typeConverter,
200 ClassTypeCache &cache) {
201 auto classDeclOp = cast<ClassDeclOp>(*mod.lookupSymbol(op));
202 return resolveClassStructBody(classDeclOp, typeConverter, cache);
209static Value adjustIntegerWidth(OpBuilder &builder, Value value,
210 uint32_t targetWidth, Location loc) {
211 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
212 if (intWidth == targetWidth)
215 if (intWidth < targetWidth) {
217 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
218 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
222 intWidth - targetWidth);
224 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
225 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
229 builder.getIntegerType(targetWidth), -1);
230 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
237 size_t resultNum = 0;
238 auto moduleTy = op.getModuleType();
239 SmallVector<hw::PortInfo> ports;
240 ports.reserve(moduleTy.getNumPorts());
242 for (
auto port : moduleTy.getPorts()) {
243 Type portTy = typeConverter.convertType(port.type);
244 if (port.dir == hw::ModulePort::Direction::Output) {
246 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
254 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
266 using OpConversionPattern::OpConversionPattern;
269 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
270 ConversionPatternRewriter &rewriter)
const override {
271 rewriter.setInsertionPoint(op);
275 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getSymNameAttr(),
276 getModulePortInfo(*typeConverter, op));
279 SymbolTable::setSymbolVisibility(hwModuleOp,
280 SymbolTable::getSymbolVisibility(op));
281 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
283 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
285 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
286 hwModuleOp.getBodyRegion().end());
289 rewriter.eraseOp(op);
295 using OpConversionPattern::OpConversionPattern;
298 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
299 ConversionPatternRewriter &rewriter)
const override {
300 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
306 using OpConversionPattern::OpConversionPattern;
309 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
310 ConversionPatternRewriter &rewriter)
const override {
311 auto instName = op.getInstanceNameAttr();
312 auto moduleName = op.getModuleNameAttr();
315 rewriter.setInsertionPoint(op);
316 auto instOp = hw::InstanceOp::create(
317 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
318 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
319 rewriter.getArrayAttr({}),
nullptr,
323 op.replaceAllUsesWith(instOp.getResults());
324 rewriter.eraseOp(op);
329static void getValuesToObserve(Region *region,
330 function_ref<
void(Value)> setInsertionPoint,
331 const TypeConverter *typeConverter,
332 ConversionPatternRewriter &rewriter,
333 SmallVector<Value> &observeValues) {
334 SmallDenseSet<Value> alreadyObserved;
335 Location loc = region->getLoc();
337 auto probeIfSignal = [&](Value value) -> Value {
338 if (!isa<llhd::RefType>(value.getType()))
340 return llhd::ProbeOp::create(rewriter, loc, value);
343 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
344 [&](Operation *operation) {
345 for (
auto value : operation->getOperands()) {
346 if (isa<BlockArgument>(value))
347 value = rewriter.getRemappedValue(value);
349 if (region->isAncestor(value.getParentRegion()))
351 if (
auto *defOp = value.getDefiningOp();
352 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
354 if (!alreadyObserved.insert(value).second)
357 OpBuilder::InsertionGuard g(rewriter);
358 if (
auto remapped = rewriter.getRemappedValue(value)) {
359 setInsertionPoint(remapped);
360 observeValues.push_back(probeIfSignal(remapped));
362 setInsertionPoint(value);
363 auto type = typeConverter->convertType(value.getType());
364 auto converted = typeConverter->materializeTargetConversion(
365 rewriter, loc, type, value);
366 observeValues.push_back(probeIfSignal(converted));
373 using OpConversionPattern::OpConversionPattern;
376 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
377 ConversionPatternRewriter &rewriter)
const override {
379 SmallVector<Value> observedValues;
380 if (op.getKind() == ProcedureKind::AlwaysComb ||
381 op.getKind() == ProcedureKind::AlwaysLatch) {
382 auto setInsertionPoint = [&](Value value) {
383 rewriter.setInsertionPoint(op);
385 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
386 rewriter, observedValues);
389 auto loc = op.getLoc();
390 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
395 if (op.getKind() == ProcedureKind::Initial ||
396 op.getKind() == ProcedureKind::Final) {
398 if (op.getKind() == ProcedureKind::Initial)
399 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
401 newOp = llhd::FinalOp::create(rewriter, loc);
402 auto &body = newOp->getRegion(0);
403 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
405 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
406 rewriter.setInsertionPoint(returnOp);
407 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
409 rewriter.eraseOp(op);
414 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
419 rewriter.createBlock(&newOp.getBody());
420 auto *block = &op.getBody().front();
421 cf::BranchOp::create(rewriter, loc, block);
422 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
423 newOp.getBody().end());
431 if (op.getKind() == ProcedureKind::AlwaysComb ||
432 op.getKind() == ProcedureKind::AlwaysLatch) {
433 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
434 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
435 ValueRange{}, block);
442 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
443 rewriter.setInsertionPoint(returnOp);
444 cf::BranchOp::create(rewriter, loc, block);
445 rewriter.eraseOp(returnOp);
448 rewriter.eraseOp(op);
454 using OpConversionPattern::OpConversionPattern;
457 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
458 ConversionPatternRewriter &rewriter)
const override {
492 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
498 if (op.getBody().front().empty()) {
501 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
505 auto *waitBlock = rewriter.createBlock(resumeBlock);
506 auto *checkBlock = rewriter.createBlock(resumeBlock);
508 auto loc = op.getLoc();
509 rewriter.setInsertionPoint(op);
510 cf::BranchOp::create(rewriter, loc, waitBlock);
520 SmallVector<Value> valuesBefore;
521 rewriter.setInsertionPointToEnd(waitBlock);
522 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
523 bool allDetectsAreAnyChange =
true;
525 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
526 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
527 allDetectsAreAnyChange =
false;
528 valuesBefore.push_back(detectOp.getInput());
529 rewriter.eraseOp(detectOp);
535 SmallVector<Value> observeValues;
536 auto setInsertionPointAfterDef = [&](Value value) {
537 if (
auto *op = value.getDefiningOp())
538 rewriter.setInsertionPointAfter(op);
539 if (
auto arg = dyn_cast<BlockArgument>(value))
540 rewriter.setInsertionPointToStart(value.getParentBlock());
543 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
544 typeConverter, rewriter, observeValues);
549 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
550 observeValues, ValueRange{}, checkBlock);
551 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
552 rewriter.eraseOp(clonedOp);
556 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
557 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
559 rewriter.eraseOp(op);
563 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
564 assert(before.getType() == after.getType() &&
565 "mismatched types after clone op");
566 auto beforeType = cast<IntType>(before.getType());
570 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
571 constexpr int LSB = 0;
573 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
575 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
576 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
579 auto intType = rewriter.getIntegerType(beforeType.getWidth());
580 before = typeConverter->materializeTargetConversion(rewriter, loc,
582 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
585 if (edge == Edge::AnyChange)
586 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
589 SmallVector<Value> disjuncts;
592 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
594 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
596 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
597 disjuncts.push_back(posedge);
600 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
602 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
604 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
605 disjuncts.push_back(posedge);
608 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
615 SmallVector<Value> triggers;
616 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
617 if (!allDetectsAreAnyChange) {
618 if (!isa<IntType>(before.getType()))
619 return detectOp->emitError() <<
"requires int operand";
621 rewriter.setInsertionPoint(detectOp);
623 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
624 if (detectOp.getCondition()) {
625 auto condition = typeConverter->materializeTargetConversion(
626 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
628 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
630 triggers.push_back(trigger);
633 rewriter.eraseOp(detectOp);
636 rewriter.setInsertionPointToEnd(checkBlock);
637 if (triggers.empty()) {
642 cf::BranchOp::create(rewriter, loc, resumeBlock);
648 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
649 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
658static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
659 ConversionPatternRewriter &rewriter) {
661 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
662 rewriter.setInsertionPoint(op);
663 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
664 adaptor.getDelay(), ValueRange{},
665 ValueRange{}, resumeBlock);
666 rewriter.setInsertionPointToStart(resumeBlock);
671static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
672 ConversionPatternRewriter &rewriter) {
673 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
682 ConversionPatternRewriter &rewriter) {
684 if (isa<mlir::LLVM::LLVMPointerType>(type))
685 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
688 if (isa<llhd::TimeType>(type)) {
690 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
691 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
695 if (
auto floatType = dyn_cast<FloatType>(type)) {
696 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
697 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
701 if (
auto strType = dyn_cast<sim::DynamicStringType>(type))
702 return sim::StringConstantOp::create(rewriter, loc, strType,
"");
705 int64_t width = hw::getBitWidth(type);
713 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
716struct ClassPropertyRefOpConversion
718 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
719 ClassTypeCache &cache)
723 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
724 ConversionPatternRewriter &rewriter)
const override {
725 Location loc = op.getLoc();
726 MLIRContext *ctx = rewriter.getContext();
729 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
731 Value instRef = adaptor.getInstance();
735 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
736 SymbolRefAttr classSym = classRefTy.getClassSym();
737 ModuleOp mod = op->getParentOfType<ModuleOp>();
738 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
739 return rewriter.notifyMatchFailure(op,
740 "Could not resolve class struct for " +
741 classSym.getRootReference().str());
743 auto structInfo = cache.getStructInfo(classSym);
744 assert(structInfo &&
"class struct info must exist");
745 auto structTy = structInfo->classBody;
748 auto propSym = op.getProperty();
749 auto pathOpt = structInfo->getFieldPath(propSym);
751 return rewriter.notifyMatchFailure(op,
752 "no GEP path for property " + propSym);
754 auto i32Ty = IntegerType::get(ctx, 32);
755 SmallVector<Value> idxVals;
756 for (
unsigned idx : *pathOpt)
757 idxVals.push_back(LLVM::ConstantOp::create(
758 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
761 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
763 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
766 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
770 rewriter.replaceOp(op, fieldRef);
775 ClassTypeCache &cache;
779 using OpConversionPattern::OpConversionPattern;
782 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
783 ConversionPatternRewriter &rewriter)
const override {
785 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
786 Type srcTy = adaptor.getInstance().getType();
789 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
792 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
793 rewriter.replaceOp(op, adaptor.getInstance());
796 return rewriter.notifyMatchFailure(
797 op,
"Upcast applied to non-opaque pointers!");
803 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
804 ClassTypeCache &cache)
808 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
809 ConversionPatternRewriter &rewriter)
const override {
810 Location loc = op.getLoc();
811 MLIRContext *ctx = rewriter.getContext();
813 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
814 auto sym = handleTy.getClassSym();
816 ModuleOp mod = op->getParentOfType<ModuleOp>();
818 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
819 return op.emitError() <<
"Could not resolve class struct for " << sym;
821 auto structTy = cache.getStructInfo(sym)->classBody;
825 uint64_t byteSize = dl.getTypeSize(structTy);
826 auto i64Ty = IntegerType::get(ctx, 64);
827 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
828 rewriter.getI64IntegerAttr(byteSize));
831 auto mallocFn = getOrCreateMalloc(mod, rewriter);
832 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
834 LLVM::CallOp::create(rewriter, loc, TypeRange{ptrTy},
835 SymbolRefAttr::get(mallocFn), ValueRange{cSize});
839 rewriter.replaceOp(op, call.getResult());
844 ClassTypeCache &cache;
848 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
849 ClassTypeCache &cache)
853 matchAndRewrite(ClassDeclOp op, OpAdaptor,
854 ConversionPatternRewriter &rewriter)
const override {
856 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
859 rewriter.eraseOp(op);
864 ClassTypeCache &cache;
868 using OpConversionPattern::OpConversionPattern;
871 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
872 ConversionPatternRewriter &rewriter)
const override {
873 auto loc = op.getLoc();
874 auto resultType = typeConverter->convertType(op.getResult().getType());
876 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
879 Value init = adaptor.getInitial();
881 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
887 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
888 op.getNameAttr(), init);
894 using OpConversionPattern::OpConversionPattern;
897 matchAndRewrite(NetOp op, OpAdaptor adaptor,
898 ConversionPatternRewriter &rewriter)
const override {
899 auto loc = op.getLoc();
900 if (op.getKind() != NetKind::Wire)
901 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
903 auto resultType = typeConverter->convertType(op.getResult().getType());
905 return rewriter.notifyMatchFailure(loc,
"invalid net type");
909 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
917 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
918 op, resultType, op.getNameAttr(), init);
920 if (
auto assignedValue = adaptor.getAssignment()) {
921 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
922 llvm::StringRef(
"ns"), 0, 1);
923 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
924 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
937 using OpConversionPattern::OpConversionPattern;
940 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
941 ConversionPatternRewriter &rewriter)
const override {
943 auto value = op.getValue().toAPInt(
false);
944 auto type = rewriter.getIntegerType(value.getBitWidth());
946 op, type, rewriter.getIntegerAttr(type, value));
952 using OpConversionPattern::OpConversionPattern;
955 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
956 ConversionPatternRewriter &rewriter)
const override {
957 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
963 using OpConversionPattern::OpConversionPattern;
966 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
967 ConversionPatternRewriter &rewriter)
const override {
968 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
969 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
970 StringRef(
"fs"), 0, 0));
976 using OpConversionPattern::OpConversionPattern;
978 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
979 ConversionPatternRewriter &rewriter)
const override {
980 const auto resultType =
981 typeConverter->convertType(op.getResult().getType());
982 const auto intType = mlir::cast<IntegerType>(resultType);
984 const auto str = op.getValue();
985 const unsigned byteWidth = intType.getWidth();
986 APInt value(byteWidth, 0);
989 const size_t maxChars =
990 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
991 for (
size_t i = 0; i < maxChars; i++) {
992 const size_t pos = str.size() - 1 - i;
993 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
994 value |= APInt(byteWidth, asciiChar) << (8 * i);
998 op, resultType, rewriter.getIntegerAttr(resultType, value));
1004 using OpConversionPattern::OpConversionPattern;
1006 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1007 ConversionPatternRewriter &rewriter)
const override {
1008 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1014 using OpConversionPattern::OpConversionPattern;
1016 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1017 ConversionPatternRewriter &rewriter)
const override {
1018 Type resultType = typeConverter->convertType(op.getResult().getType());
1020 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1021 adaptor.getValue());
1027 using OpConversionPattern::OpConversionPattern;
1030 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1031 ConversionPatternRewriter &rewriter)
const override {
1034 Type resultType = typeConverter->convertType(op.getResult().getType());
1035 Type inputType = adaptor.getInput().getType();
1036 int32_t low = adaptor.getLowBit();
1038 if (isa<IntegerType>(inputType)) {
1039 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1040 int32_t resultWidth = hw::getBitWidth(resultType);
1041 int32_t high = low + resultWidth;
1043 SmallVector<Value> toConcat;
1046 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
1048 if (low < inputWidth && high > 0) {
1049 int32_t lowIdx = std::max(low, 0);
1052 rewriter.getIntegerType(
1053 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
1054 adaptor.getInput(), lowIdx);
1055 toConcat.push_back(middle);
1058 int32_t diff = high - inputWidth;
1062 toConcat.push_back(val);
1067 rewriter.replaceOp(op,
concat);
1071 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1072 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
1073 int32_t inputWidth = arrTy.getNumElements();
1075 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1076 resArrTy && resArrTy != arrTy.getElementType()) {
1077 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
1078 if (elementWidth < 0)
1081 int32_t high = low + resArrTy.getNumElements();
1082 int32_t resWidth = resArrTy.getNumElements();
1084 SmallVector<Value> toConcat;
1087 rewriter, op.getLoc(),
1088 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1091 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1093 toConcat.push_back(res);
1096 if (low < inputWidth && high > 0) {
1097 int32_t lowIdx = std::max(0, low);
1099 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
1103 arrTy.getElementType(),
1104 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1105 adaptor.getInput(), lowIdxVal);
1106 toConcat.push_back(middle);
1109 int32_t diff = high - inputWidth;
1112 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1114 rewriter, op.getLoc(),
1115 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1116 toConcat.push_back(val);
1121 rewriter.replaceOp(op,
concat);
1126 if (low < 0 || low >= inputWidth) {
1127 int32_t bw = hw::getBitWidth(resultType);
1133 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
1134 rewriter.replaceOp(op, bitcast);
1139 rewriter.getIntegerType(width),
1140 adaptor.getLowBit());
1141 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
1150 using OpConversionPattern::OpConversionPattern;
1153 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1154 ConversionPatternRewriter &rewriter)
const override {
1156 Type resultType = typeConverter->convertType(op.getResult().getType());
1158 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1160 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1161 int64_t width = hw::getBitWidth(inputType);
1166 rewriter, op.getLoc(),
1167 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1168 adaptor.getLowBit());
1169 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1170 op, resultType, adaptor.getInput(), lowBit);
1174 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1176 rewriter, op.getLoc(),
1177 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1178 adaptor.getLowBit());
1182 if (arrType.getElementType() !=
1183 cast<llhd::RefType>(resultType).getNestedType()) {
1184 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1185 op, resultType, adaptor.getInput(), lowBit);
1189 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1199 using OpConversionPattern::OpConversionPattern;
1202 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1203 ConversionPatternRewriter &rewriter)
const override {
1204 Type resultType = typeConverter->convertType(op.getResult().getType());
1205 Type inputType = adaptor.getInput().getType();
1207 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1208 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1209 intType.getWidth(), op->getLoc());
1210 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1211 adaptor.getInput(), amount);
1213 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1217 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1218 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1219 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1222 bool isSingleElementExtract = arrType.getElementType() == resultType;
1224 if (isSingleElementExtract)
1225 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1229 adaptor.getInput(), idx);
1239 using OpConversionPattern::OpConversionPattern;
1242 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1243 ConversionPatternRewriter &rewriter)
const override {
1245 Type resultType = typeConverter->convertType(op.getResult().getType());
1247 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1249 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1250 int64_t width = hw::getBitWidth(inputType);
1255 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1256 llvm::Log2_64_Ceil(width), op->getLoc());
1257 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1258 op, resultType, adaptor.getInput(), amount);
1262 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1263 Value idx = adjustIntegerWidth(
1264 rewriter, adaptor.getLowBit(),
1265 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1267 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1268 bool isSingleElementExtract =
1269 arrType.getElementType() == resultNestedType;
1271 if (isSingleElementExtract)
1272 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1275 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1276 op, resultType, adaptor.getInput(), idx);
1286 using OpConversionPattern::OpConversionPattern;
1289 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1290 ConversionPatternRewriter &rewriter)
const override {
1291 Type resultType = typeConverter->convertType(op.getResult().getType());
1293 adaptor.getElements());
1299 using OpConversionPattern::OpConversionPattern;
1302 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1303 ConversionPatternRewriter &rewriter)
const override {
1304 Type resultType = typeConverter->convertType(op.getResult().getType());
1306 adaptor.getFields());
1312 using OpConversionPattern::OpConversionPattern;
1315 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1316 ConversionPatternRewriter &rewriter)
const override {
1318 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1323struct StructExtractRefOpConversion
1325 using OpConversionPattern::OpConversionPattern;
1328 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1329 ConversionPatternRewriter &rewriter)
const override {
1330 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1331 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1337 using OpConversionPattern::OpConversionPattern;
1339 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1340 ConversionPatternRewriter &rewriter)
const override {
1341 Type resultType = typeConverter->convertType(op.getInput().getType());
1344 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1345 adaptor.getInput(), max);
1351 using OpConversionPattern::OpConversionPattern;
1353 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1354 ConversionPatternRewriter &rewriter)
const override {
1355 Type resultType = typeConverter->convertType(op.getInput().getType());
1358 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1359 adaptor.getInput(), zero);
1365 using OpConversionPattern::OpConversionPattern;
1367 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1368 ConversionPatternRewriter &rewriter)
const override {
1370 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1376 using OpConversionPattern::OpConversionPattern;
1378 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1379 ConversionPatternRewriter &rewriter)
const override {
1380 Type resultType = typeConverter->convertType(op.getInput().getType());
1381 if (isa_and_nonnull<IntegerType>(resultType)) {
1384 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1385 adaptor.getInput(), zero);
1393 using OpConversionPattern::OpConversionPattern;
1395 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1396 ConversionPatternRewriter &rewriter)
const override {
1398 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1401 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1407 using OpConversionPattern::OpConversionPattern;
1409 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1410 ConversionPatternRewriter &rewriter)
const override {
1412 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1415 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1420template <
typename SourceOp,
typename TargetOp>
1423 using OpAdaptor =
typename SourceOp::Adaptor;
1426 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1427 ConversionPatternRewriter &rewriter)
const override {
1428 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1429 adaptor.getRhs(),
false);
1434template <
typename SourceOp,
typename TargetOp>
1437 using OpAdaptor =
typename SourceOp::Adaptor;
1440 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1441 ConversionPatternRewriter &rewriter)
const override {
1442 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1448template <
typename SourceOp, ICmpPredicate pred>
1451 using OpAdaptor =
typename SourceOp::Adaptor;
1454 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1455 ConversionPatternRewriter &rewriter)
const override {
1457 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1459 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1460 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1465template <
typename SourceOp, arith::CmpFPredicate pred>
1468 using OpAdaptor =
typename SourceOp::Adaptor;
1471 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1472 ConversionPatternRewriter &rewriter)
const override {
1474 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1476 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1477 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1482template <
typename SourceOp,
bool withoutX>
1485 using OpAdaptor =
typename SourceOp::Adaptor;
1488 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1489 ConversionPatternRewriter &rewriter)
const override {
1495 unsigned bitWidth = op.getLhs().getType().getWidth();
1496 auto ignoredBits = APInt::getZero(bitWidth);
1497 auto detectIgnoredBits = [&](Value value) {
1498 auto constOp = value.getDefiningOp<ConstantOp>();
1501 auto constValue = constOp.getValue();
1503 ignoredBits |= constValue.getZBits();
1505 ignoredBits |= constValue.getUnknownBits();
1507 detectIgnoredBits(op.getLhs());
1508 detectIgnoredBits(op.getRhs());
1512 Value lhs = adaptor.getLhs();
1513 Value rhs = adaptor.getRhs();
1514 if (!ignoredBits.isZero()) {
1515 ignoredBits.flipAllBits();
1517 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1518 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1521 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1531 using OpConversionPattern::OpConversionPattern;
1534 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1535 ConversionPatternRewriter &rewriter)
const override {
1536 Location loc = op.getLoc();
1537 Type resultType = typeConverter->convertType(op.getResult().getType());
1539 op.emitError(
"conversion result type is not currently supported");
1542 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1543 int64_t resultBw = hw::getBitWidth(resultType);
1544 if (inputBw == -1 || resultBw == -1)
1548 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1549 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1552 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1553 rewriter.replaceOp(op, result);
1558template <
typename SourceOp>
1561 using OpAdaptor =
typename SourceOp::Adaptor;
1562 using ConversionPattern::typeConverter;
1565 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1566 ConversionPatternRewriter &rewriter)
const override {
1567 auto type = typeConverter->convertType(op.getResult().getType());
1568 if (type == adaptor.getInput().getType())
1569 rewriter.replaceOp(op, adaptor.getInput());
1571 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1577 using OpConversionPattern::OpConversionPattern;
1580 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1581 ConversionPatternRewriter &rewriter)
const override {
1582 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1583 op.getType().getWidth());
1589 using OpConversionPattern::OpConversionPattern;
1592 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1593 ConversionPatternRewriter &rewriter)
const override {
1594 auto targetWidth = op.getType().getWidth();
1595 auto inputWidth = op.getInput().getType().getWidth();
1598 rewriter, op.getLoc(),
1599 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1602 op, ValueRange{zeroExt, adaptor.getInput()});
1608 using OpConversionPattern::OpConversionPattern;
1611 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1612 ConversionPatternRewriter &rewriter)
const override {
1613 auto type = typeConverter->convertType(op.getType());
1615 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1616 rewriter.replaceOp(op, value);
1622 using OpConversionPattern::OpConversionPattern;
1625 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
1626 ConversionPatternRewriter &rewriter)
const override {
1627 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
1628 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1634 using OpConversionPattern::OpConversionPattern;
1637 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
1638 ConversionPatternRewriter &rewriter)
const override {
1639 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
1640 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1646 using OpConversionPattern::OpConversionPattern;
1649 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
1650 ConversionPatternRewriter &rewriter)
const override {
1651 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
1657 using OpConversionPattern::OpConversionPattern;
1660 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
1661 ConversionPatternRewriter &rewriter)
const override {
1662 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
1663 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1673 using OpConversionPattern::OpConversionPattern;
1676 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1677 ConversionPatternRewriter &rewriter)
const override {
1678 SmallVector<Type> convResTypes;
1679 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1682 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1683 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1684 adaptor.getOperands(), op.getArgNames(),
1685 op.getResultNames(),
1686 rewriter.getArrayAttr({}),
nullptr);
1693 using OpConversionPattern::OpConversionPattern;
1696 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1697 ConversionPatternRewriter &rewriter)
const override {
1698 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1704 using OpConversionPattern::OpConversionPattern;
1707 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1708 ConversionPatternRewriter &rewriter)
const override {
1709 SmallVector<Type> convResTypes;
1710 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1712 rewriter.replaceOpWithNewOp<func::CallOp>(
1713 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1718struct UnrealizedConversionCastConversion
1720 using OpConversionPattern::OpConversionPattern;
1723 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1724 ConversionPatternRewriter &rewriter)
const override {
1725 SmallVector<Type> convResTypes;
1726 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1731 if (convResTypes == adaptor.getOperands().getTypes()) {
1732 rewriter.replaceOp(op, adaptor.getOperands());
1736 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1737 op, convResTypes, adaptor.getOperands());
1743 using OpConversionPattern::OpConversionPattern;
1746 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1747 ConversionPatternRewriter &rewriter)
const override {
1748 Type resultType = typeConverter->convertType(op.getResult().getType());
1752 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1753 resultType.getIntOrFloatBitWidth(), op->getLoc());
1754 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1761 using OpConversionPattern::OpConversionPattern;
1764 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1765 ConversionPatternRewriter &rewriter)
const override {
1766 Type resultType = typeConverter->convertType(op.getResult().getType());
1770 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1771 resultType.getIntOrFloatBitWidth(), op->getLoc());
1773 op, resultType, adaptor.getValue(), amount,
false);
1779 using OpConversionPattern::OpConversionPattern;
1782 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1783 ConversionPatternRewriter &rewriter)
const override {
1784 Type resultType = typeConverter->convertType(op.getResult().getType());
1786 Location loc = op->getLoc();
1791 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1792 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1795 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1803 using OpConversionPattern::OpConversionPattern;
1806 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1807 ConversionPatternRewriter &rewriter)
const override {
1808 Type resultType = typeConverter->convertType(op.getResult().getType());
1812 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1813 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1819 using OpConversionPattern::OpConversionPattern;
1822 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1823 ConversionPatternRewriter &rewriter)
const override {
1824 Type resultType = typeConverter->convertType(op.getResult().getType());
1828 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1829 resultType.getIntOrFloatBitWidth(), op->getLoc());
1831 op, resultType, adaptor.getValue(), amount,
false);
1837 using OpConversionPattern::OpConversionPattern;
1840 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1841 ConversionPatternRewriter &rewriter)
const override {
1842 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
1847struct AssignedVariableOpConversion
1849 using OpConversionPattern::OpConversionPattern;
1852 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1853 ConversionPatternRewriter &rewriter)
const override {
1854 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1855 adaptor.getNameAttr());
1860template <
typename OpTy>
1863 using OpAdaptor =
typename OpTy::Adaptor;
1866 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1867 ConversionPatternRewriter &rewriter)
const override {
1870 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
1871 std::is_same_v<OpTy, BlockingAssignOp>) {
1873 delay = llhd::ConstantTimeOp::create(
1874 rewriter, op->getLoc(),
1875 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 0, 1));
1876 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
1878 delay = llhd::ConstantTimeOp::create(
1879 rewriter, op->getLoc(),
1880 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
1883 delay = adaptor.getDelay();
1886 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
1887 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
1893 using OpConversionPattern::OpConversionPattern;
1896 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1897 ConversionPatternRewriter &rewriter)
const override {
1902 auto type = typeConverter->convertType(op.getType());
1904 auto hasNoWriteEffect = [](Region ®ion) {
1905 auto result = region.walk([](Operation *operation) {
1906 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1907 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1908 !memOp.hasEffect<MemoryEffects::Free>())
1909 return WalkResult::advance();
1911 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1912 return WalkResult::advance();
1914 return WalkResult::interrupt();
1916 return !result.wasInterrupted();
1919 if (hasNoWriteEffect(op.getTrueRegion()) &&
1920 hasNoWriteEffect(op.getFalseRegion())) {
1921 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1922 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1924 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1925 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1927 Value convTrueVal = typeConverter->materializeTargetConversion(
1928 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1929 Value convFalseVal = typeConverter->materializeTargetConversion(
1930 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1932 rewriter.eraseOp(trueTerm);
1933 rewriter.eraseOp(falseTerm);
1935 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1936 convTrueVal, convFalseVal);
1941 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1942 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1943 ifOp.getThenRegion().end());
1944 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1945 ifOp.getElseRegion().end());
1946 rewriter.replaceOp(op, ifOp);
1952 using OpConversionPattern::OpConversionPattern;
1955 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1956 ConversionPatternRewriter &rewriter)
const override {
1957 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1962template <
typename SourceOp>
1965 using OpAdaptor =
typename SourceOp::Adaptor;
1968 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1969 ConversionPatternRewriter &rewriter)
const override {
1970 rewriter.modifyOpInPlace(op,
1971 [&]() { op->setOperands(adaptor.getOperands()); });
1976template <
typename MooreOpTy,
typename VerifOpTy>
1979 using OpAdaptor =
typename MooreOpTy::Adaptor;
1982 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1983 ConversionPatternRewriter &rewriter)
const override {
1985 op.getLabel().has_value()
1986 ? StringAttr::get(op->getContext(), op.getLabel().value())
1987 : StringAttr::
get(op->getContext());
1988 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1999 using OpConversionPattern::OpConversionPattern;
2002 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2003 ConversionPatternRewriter &rewriter)
const override {
2004 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2010 using OpConversionPattern::OpConversionPattern;
2013 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2014 ConversionPatternRewriter &rewriter)
const override {
2015 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2016 adaptor.getInputs());
2022 using OpConversionPattern::OpConversionPattern;
2025 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2026 ConversionPatternRewriter &rewriter)
const override {
2028 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2029 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2030 auto widthAttr = adaptor.getSpecifierWidthAttr();
2032 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2033 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2035 switch (op.getFormat()) {
2036 case IntFormat::Decimal:
2037 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2038 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2039 adaptor.getIsSignedAttr());
2041 case IntFormat::Binary:
2042 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2043 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2045 case IntFormat::Octal:
2046 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2047 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2049 case IntFormat::HexLower:
2050 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2051 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2052 isLeftAlignedAttr, padCharAttr, widthAttr);
2054 case IntFormat::HexUpper:
2055 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2056 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2057 padCharAttr, widthAttr);
2060 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2065 using OpConversionPattern::OpConversionPattern;
2068 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2069 ConversionPatternRewriter &rewriter)
const override {
2070 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2072 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2073 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2074 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2076 switch (op.getFormat()) {
2077 case RealFormat::General:
2078 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2079 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2082 case RealFormat::Float:
2083 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2084 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2087 case RealFormat::Exponential:
2088 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2089 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2097 using OpConversionPattern::OpConversionPattern;
2100 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2101 ConversionPatternRewriter &rewriter)
const override {
2102 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2108 using OpConversionPattern::OpConversionPattern;
2111 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2112 ConversionPatternRewriter &rewriter)
const override {
2113 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2119 using OpConversionPattern::OpConversionPattern;
2122 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
2123 ConversionPatternRewriter &rewriter)
const override {
2124 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
2125 op, adaptor.getMessage());
2137static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
2138 ConversionPatternRewriter &rewriter) {
2139 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
2144static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
2145 ConversionPatternRewriter &rewriter) {
2146 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
2152static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
2153 ConversionPatternRewriter &rewriter) {
2155 std::string severityString;
2157 switch (op.getSeverity()) {
2158 case (Severity::Fatal):
2159 severityString =
"Fatal: ";
2161 case (Severity::Error):
2162 severityString =
"Error: ";
2164 case (Severity::Warning):
2165 severityString =
"Warning: ";
2172 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
2173 auto message = sim::FormatStringConcatOp::create(
2174 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
2175 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
2181 FinishMessageBIOp::Adaptor adaptor,
2182 ConversionPatternRewriter &rewriter) {
2184 rewriter.eraseOp(op);
2193static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
2194 ConversionPatternRewriter &rewriter) {
2195 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
2200static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
2201 ConversionPatternRewriter &rewriter) {
2202 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
2207static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
2208 ConversionPatternRewriter &rewriter) {
2209 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
2218 const TypeConverter &converter) {
2219 target.addIllegalDialect<MooreDialect>();
2220 target.addLegalDialect<comb::CombDialect>();
2221 target.addLegalDialect<hw::HWDialect>();
2222 target.addLegalDialect<seq::SeqDialect>();
2223 target.addLegalDialect<llhd::LLHDDialect>();
2224 target.addLegalDialect<ltl::LTLDialect>();
2225 target.addLegalDialect<mlir::BuiltinDialect>();
2226 target.addLegalDialect<mlir::math::MathDialect>();
2227 target.addLegalDialect<sim::SimDialect>();
2228 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2229 target.addLegalDialect<verif::VerifDialect>();
2230 target.addLegalDialect<arith::ArithDialect>();
2232 target.addLegalOp<debug::ScopeOp>();
2234 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
2235 UnrealizedConversionCastOp, hw::OutputOp,
2236 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
2238 [&](Operation *op) {
return converter.isLegal(op); });
2240 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
2241 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
2242 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
2245 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
2246 return converter.isSignatureLegal(op.getFunctionType());
2250 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
2251 converter.isLegal(&op.getBody());
2256 typeConverter.addConversion([&](IntType type) {
2257 return IntegerType::get(type.getContext(), type.getWidth());
2260 typeConverter.addConversion([&](RealType type) -> mlir::Type {
2261 MLIRContext *ctx = type.getContext();
2262 switch (type.getWidth()) {
2263 case moore::RealWidth::f32:
2264 return mlir::Float32Type::get(ctx);
2265 case moore::RealWidth::f64:
2266 return mlir::Float64Type::get(ctx);
2270 typeConverter.addConversion(
2271 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
2273 typeConverter.addConversion([&](FormatStringType type) {
2274 return sim::FormatStringType::get(type.getContext());
2277 typeConverter.addConversion([&](StringType type) {
2278 return sim::DynamicStringType::get(type.getContext());
2281 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
2282 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2283 return hw::ArrayType::get(
elementType, type.getSize());
2290 typeConverter.addConversion(
2291 [&](UnpackedArrayType type) -> std::optional<Type> {
2292 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2293 return hw::ArrayType::get(
elementType, type.getSize());
2297 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
2298 SmallVector<hw::StructType::FieldInfo> fields;
2299 for (
auto field : type.getMembers()) {
2300 hw::StructType::FieldInfo info;
2301 info.type = typeConverter.convertType(field.type);
2304 info.name = field.name;
2305 fields.push_back(info);
2307 return hw::StructType::get(type.getContext(), fields);
2315 typeConverter.addConversion(
2316 [&](UnpackedStructType type) -> std::optional<Type> {
2317 SmallVector<hw::StructType::FieldInfo> fields;
2318 for (
auto field : type.getMembers()) {
2319 hw::StructType::FieldInfo info;
2320 info.type = typeConverter.convertType(field.type);
2323 info.name = field.name;
2324 fields.push_back(info);
2326 return hw::StructType::get(type.getContext(), fields);
2330 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
2331 return LLVM::LLVMPointerType::get(type.getContext());
2335 typeConverter.addConversion(
2336 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
2339 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
2340 return LLVM::LLVMPointerType::get(type.getContext());
2343 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
2344 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
2345 return llhd::RefType::get(innerType);
2350 typeConverter.addConversion([](IntegerType type) {
return type; });
2351 typeConverter.addConversion([](FloatType type) {
return type; });
2352 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
2353 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
2354 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
2355 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
2356 typeConverter.addConversion([](debug::StructType type) {
return type; });
2358 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
2359 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
2360 return llhd::RefType::get(innerType);
2364 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
2365 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2366 return hw::ArrayType::get(
elementType, type.getNumElements());
2370 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
2371 SmallVector<hw::StructType::FieldInfo> fields;
2372 for (
auto field : type.getElements()) {
2373 hw::StructType::FieldInfo info;
2374 info.type = typeConverter.convertType(field.type);
2377 info.name = field.name;
2378 fields.push_back(info);
2380 return hw::StructType::get(type.getContext(), fields);
2383 typeConverter.addTargetMaterialization(
2384 [&](mlir::OpBuilder &builder, mlir::Type resultType,
2385 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
2386 if (inputs.size() != 1 || !inputs[0])
2388 return UnrealizedConversionCastOp::create(builder, loc, resultType,
2393 typeConverter.addSourceMaterialization(
2394 [&](mlir::OpBuilder &builder, mlir::Type resultType,
2395 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
2396 if (inputs.size() != 1)
2398 return UnrealizedConversionCastOp::create(builder, loc, resultType,
2405 TypeConverter &typeConverter,
2406 ClassTypeCache &classCache) {
2412 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
2413 patterns.getContext(), classCache);
2417 ClassUpcastOpConversion,
2419 VariableOpConversion,
2423 ConversionOpConversion,
2424 BitcastConversion<PackedToSBVOp>,
2425 BitcastConversion<SBVToPackedOp>,
2426 BitcastConversion<LogicToIntOp>,
2427 BitcastConversion<IntToLogicOp>,
2428 BitcastConversion<ToBuiltinBoolOp>,
2432 SIntToRealOpConversion,
2433 UIntToRealOpConversion,
2434 IntToStringOpConversion,
2435 RealToIntOpConversion,
2441 ReplicateOpConversion,
2443 ExtractOpConversion,
2444 DynExtractOpConversion,
2445 DynExtractRefOpConversion,
2447 StructExtractOpConversion,
2448 StructExtractRefOpConversion,
2449 ExtractRefOpConversion,
2450 StructCreateOpConversion,
2451 ConditionalOpConversion,
2452 ArrayCreateOpConversion,
2455 ConstantStringOpConv,
2458 ReduceAndOpConversion,
2459 ReduceOrOpConversion,
2460 ReduceXorOpConversion,
2461 BoolCastOpConversion,
2466 BinaryOpConversion<AddOp, comb::AddOp>,
2467 BinaryOpConversion<SubOp, comb::SubOp>,
2468 BinaryOpConversion<MulOp, comb::MulOp>,
2469 BinaryOpConversion<DivUOp, comb::DivUOp>,
2470 BinaryOpConversion<DivSOp, comb::DivSOp>,
2471 BinaryOpConversion<ModUOp, comb::ModUOp>,
2472 BinaryOpConversion<ModSOp, comb::ModSOp>,
2473 BinaryOpConversion<AndOp, comb::AndOp>,
2474 BinaryOpConversion<OrOp, comb::OrOp>,
2475 BinaryOpConversion<XorOp, comb::XorOp>,
2478 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
2479 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
2480 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
2481 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
2482 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
2485 PowUOpConversion, PowSOpConversion,
2488 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
2489 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
2490 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
2491 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
2492 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
2493 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
2494 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
2495 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
2496 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
2497 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
2498 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
2499 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
2500 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
2501 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
2502 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::ONE>,
2503 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
2504 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
2505 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
2506 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
2507 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
2508 CaseXZEqOpConversion<CaseZEqOp, true>,
2509 CaseXZEqOpConversion<CaseXZEqOp, false>,
2512 SVModuleOpConversion,
2513 InstanceOpConversion,
2514 ProcedureOpConversion,
2515 WaitEventOpConversion,
2523 AssignOpConversion<ContinuousAssignOp>,
2524 AssignOpConversion<DelayedContinuousAssignOp>,
2525 AssignOpConversion<BlockingAssignOp>,
2526 AssignOpConversion<NonBlockingAssignOp>,
2527 AssignOpConversion<DelayedNonBlockingAssignOp>,
2528 AssignedVariableOpConversion,
2531 HWInstanceOpConversion,
2534 UnrealizedConversionCastConversion,
2535 InPlaceOpConversion<debug::ArrayOp>,
2536 InPlaceOpConversion<debug::StructOp>,
2537 InPlaceOpConversion<debug::VariableOp>,
2540 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
2541 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
2542 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
2545 FormatLiteralOpConversion,
2546 FormatConcatOpConversion,
2547 FormatIntOpConversion,
2548 FormatRealOpConversion,
2549 DisplayBIOpConversion,
2552 StringLenOpConversion,
2553 StringConcatOpConversion
2554 >(typeConverter,
patterns.getContext());
2572 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
2574 hw::populateHWModuleLikeTypeConversionPattern(
2575 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
2576 populateSCFToControlFlowConversionPatterns(
patterns);
2585struct MooreToCorePass
2586 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
2587 void runOnOperation()
override;
2593 return std::make_unique<MooreToCorePass>();
2597void MooreToCorePass::runOnOperation() {
2598 MLIRContext &
context = getContext();
2599 ModuleOp
module = getOperation();
2600 ClassTypeCache classCache;
2602 IRRewriter rewriter(module);
2603 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
2605 TypeConverter typeConverter;
2608 ConversionTarget target(
context);
2613 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
2616 if (failed(applyFullConversion(module, target, std::move(
patterns))))
2617 signalPassFailure();
assert(baseType &&"element must be base type")
static SmallVector< T > concat(const SmallVectorImpl< T > &a, const SmallVectorImpl< T > &b)
Returns a new vector containing the concatenation of vectors a and b.
static std::unique_ptr< Context > context
static Value createZeroValue(ImplicitLocOpBuilder &builder, FIRRTLBaseType type, SmallDenseMap< FIRRTLBaseType, Value > &cache)
Construct a zero value of the given type using the given builder.
static LogicalResult convert(StopBIOp op, StopBIOp::Adaptor adaptor, ConversionPatternRewriter &rewriter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateOpConversion(ConversionPatternSet &patterns, TypeConverter &typeConverter, ClassTypeCache &classCache)
static void populateTypeConversion(TypeConverter &typeConverter)
Extension of RewritePatternSet that allows adding matchAndRewrite functions with op adaptors and Conv...
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateArithToCombPatterns(mlir::RewritePatternSet &patterns, TypeConverter &typeConverter)
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.
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.