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 int64_t width = hw::getBitWidth(type);
709 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
712struct ClassPropertyRefOpConversion
714 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
715 ClassTypeCache &cache)
719 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
720 ConversionPatternRewriter &rewriter)
const override {
721 Location loc = op.getLoc();
722 MLIRContext *ctx = rewriter.getContext();
725 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
727 Value instRef = adaptor.getInstance();
731 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
732 SymbolRefAttr classSym = classRefTy.getClassSym();
733 ModuleOp mod = op->getParentOfType<ModuleOp>();
734 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
735 return rewriter.notifyMatchFailure(op,
736 "Could not resolve class struct for " +
737 classSym.getRootReference().str());
739 auto structInfo = cache.getStructInfo(classSym);
740 assert(structInfo &&
"class struct info must exist");
741 auto structTy = structInfo->classBody;
744 auto propSym = op.getProperty();
745 auto pathOpt = structInfo->getFieldPath(propSym);
747 return rewriter.notifyMatchFailure(op,
748 "no GEP path for property " + propSym);
750 auto i32Ty = IntegerType::get(ctx, 32);
751 SmallVector<Value> idxVals;
752 for (
unsigned idx : *pathOpt)
753 idxVals.push_back(LLVM::ConstantOp::create(
754 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
757 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
759 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
762 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
766 rewriter.replaceOp(op, fieldRef);
771 ClassTypeCache &cache;
775 using OpConversionPattern::OpConversionPattern;
778 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
779 ConversionPatternRewriter &rewriter)
const override {
781 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
782 Type srcTy = adaptor.getInstance().getType();
785 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
788 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
789 rewriter.replaceOp(op, adaptor.getInstance());
792 return rewriter.notifyMatchFailure(
793 op,
"Upcast applied to non-opaque pointers!");
799 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
800 ClassTypeCache &cache)
804 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
805 ConversionPatternRewriter &rewriter)
const override {
806 Location loc = op.getLoc();
807 MLIRContext *ctx = rewriter.getContext();
809 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
810 auto sym = handleTy.getClassSym();
812 ModuleOp mod = op->getParentOfType<ModuleOp>();
814 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
815 return op.emitError() <<
"Could not resolve class struct for " << sym;
817 auto structTy = cache.getStructInfo(sym)->classBody;
821 uint64_t byteSize = dl.getTypeSize(structTy);
822 auto i64Ty = IntegerType::get(ctx, 64);
823 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
824 rewriter.getI64IntegerAttr(byteSize));
827 auto mallocFn = getOrCreateMalloc(mod, rewriter);
828 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
830 LLVM::CallOp::create(rewriter, loc, TypeRange{ptrTy},
831 SymbolRefAttr::get(mallocFn), ValueRange{cSize});
835 rewriter.replaceOp(op, call.getResult());
840 ClassTypeCache &cache;
844 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
845 ClassTypeCache &cache)
849 matchAndRewrite(ClassDeclOp op, OpAdaptor,
850 ConversionPatternRewriter &rewriter)
const override {
852 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
855 rewriter.eraseOp(op);
860 ClassTypeCache &cache;
864 using OpConversionPattern::OpConversionPattern;
867 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
868 ConversionPatternRewriter &rewriter)
const override {
869 auto loc = op.getLoc();
870 auto resultType = typeConverter->convertType(op.getResult().getType());
872 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
875 Value init = adaptor.getInitial();
877 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
883 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
884 op.getNameAttr(), init);
890 using OpConversionPattern::OpConversionPattern;
893 matchAndRewrite(NetOp op, OpAdaptor adaptor,
894 ConversionPatternRewriter &rewriter)
const override {
895 auto loc = op.getLoc();
896 if (op.getKind() != NetKind::Wire)
897 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
899 auto resultType = typeConverter->convertType(op.getResult().getType());
901 return rewriter.notifyMatchFailure(loc,
"invalid net type");
905 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
913 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
914 op, resultType, op.getNameAttr(), init);
916 if (
auto assignedValue = adaptor.getAssignment()) {
917 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
918 llvm::StringRef(
"ns"), 0, 1);
919 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
920 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
933 using OpConversionPattern::OpConversionPattern;
936 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
937 ConversionPatternRewriter &rewriter)
const override {
939 auto value = op.getValue().toAPInt(
false);
940 auto type = rewriter.getIntegerType(value.getBitWidth());
942 op, type, rewriter.getIntegerAttr(type, value));
948 using OpConversionPattern::OpConversionPattern;
951 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
952 ConversionPatternRewriter &rewriter)
const override {
953 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
959 using OpConversionPattern::OpConversionPattern;
962 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
963 ConversionPatternRewriter &rewriter)
const override {
964 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
965 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
966 StringRef(
"fs"), 0, 0));
972 using OpConversionPattern::OpConversionPattern;
974 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
975 ConversionPatternRewriter &rewriter)
const override {
976 const auto resultType =
977 typeConverter->convertType(op.getResult().getType());
978 const auto intType = mlir::cast<IntegerType>(resultType);
980 const auto str = op.getValue();
981 const unsigned byteWidth = intType.getWidth();
982 APInt value(byteWidth, 0);
985 const size_t maxChars =
986 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
987 for (
size_t i = 0; i < maxChars; i++) {
988 const size_t pos = str.size() - 1 - i;
989 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
990 value |= APInt(byteWidth, asciiChar) << (8 * i);
994 op, resultType, rewriter.getIntegerAttr(resultType, value));
1000 using OpConversionPattern::OpConversionPattern;
1002 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1003 ConversionPatternRewriter &rewriter)
const override {
1004 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1010 using OpConversionPattern::OpConversionPattern;
1012 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1013 ConversionPatternRewriter &rewriter)
const override {
1014 Type resultType = typeConverter->convertType(op.getResult().getType());
1016 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1017 adaptor.getValue());
1023 using OpConversionPattern::OpConversionPattern;
1026 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1027 ConversionPatternRewriter &rewriter)
const override {
1030 Type resultType = typeConverter->convertType(op.getResult().getType());
1031 Type inputType = adaptor.getInput().getType();
1032 int32_t low = adaptor.getLowBit();
1034 if (isa<IntegerType>(inputType)) {
1035 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1036 int32_t resultWidth = hw::getBitWidth(resultType);
1037 int32_t high = low + resultWidth;
1039 SmallVector<Value> toConcat;
1042 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
1044 if (low < inputWidth && high > 0) {
1045 int32_t lowIdx = std::max(low, 0);
1048 rewriter.getIntegerType(
1049 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
1050 adaptor.getInput(), lowIdx);
1051 toConcat.push_back(middle);
1054 int32_t diff = high - inputWidth;
1058 toConcat.push_back(val);
1063 rewriter.replaceOp(op,
concat);
1067 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1068 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
1069 int32_t inputWidth = arrTy.getNumElements();
1071 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1072 resArrTy && resArrTy != arrTy.getElementType()) {
1073 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
1074 if (elementWidth < 0)
1077 int32_t high = low + resArrTy.getNumElements();
1078 int32_t resWidth = resArrTy.getNumElements();
1080 SmallVector<Value> toConcat;
1083 rewriter, op.getLoc(),
1084 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1087 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1089 toConcat.push_back(res);
1092 if (low < inputWidth && high > 0) {
1093 int32_t lowIdx = std::max(0, low);
1095 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
1099 arrTy.getElementType(),
1100 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1101 adaptor.getInput(), lowIdxVal);
1102 toConcat.push_back(middle);
1105 int32_t diff = high - inputWidth;
1108 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1110 rewriter, op.getLoc(),
1111 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1112 toConcat.push_back(val);
1117 rewriter.replaceOp(op,
concat);
1122 if (low < 0 || low >= inputWidth) {
1123 int32_t bw = hw::getBitWidth(resultType);
1129 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
1130 rewriter.replaceOp(op, bitcast);
1135 rewriter.getIntegerType(width),
1136 adaptor.getLowBit());
1137 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
1146 using OpConversionPattern::OpConversionPattern;
1149 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1150 ConversionPatternRewriter &rewriter)
const override {
1152 Type resultType = typeConverter->convertType(op.getResult().getType());
1154 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1156 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1157 int64_t width = hw::getBitWidth(inputType);
1162 rewriter, op.getLoc(),
1163 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1164 adaptor.getLowBit());
1165 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1166 op, resultType, adaptor.getInput(), lowBit);
1170 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1172 rewriter, op.getLoc(),
1173 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1174 adaptor.getLowBit());
1178 if (arrType.getElementType() !=
1179 cast<llhd::RefType>(resultType).getNestedType()) {
1180 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1181 op, resultType, adaptor.getInput(), lowBit);
1185 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1195 using OpConversionPattern::OpConversionPattern;
1198 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1199 ConversionPatternRewriter &rewriter)
const override {
1200 Type resultType = typeConverter->convertType(op.getResult().getType());
1201 Type inputType = adaptor.getInput().getType();
1203 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1204 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1205 intType.getWidth(), op->getLoc());
1206 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1207 adaptor.getInput(), amount);
1209 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1213 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1214 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1215 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1218 bool isSingleElementExtract = arrType.getElementType() == resultType;
1220 if (isSingleElementExtract)
1221 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1225 adaptor.getInput(), idx);
1235 using OpConversionPattern::OpConversionPattern;
1238 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1239 ConversionPatternRewriter &rewriter)
const override {
1241 Type resultType = typeConverter->convertType(op.getResult().getType());
1243 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1245 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1246 int64_t width = hw::getBitWidth(inputType);
1251 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1252 llvm::Log2_64_Ceil(width), op->getLoc());
1253 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1254 op, resultType, adaptor.getInput(), amount);
1258 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1259 Value idx = adjustIntegerWidth(
1260 rewriter, adaptor.getLowBit(),
1261 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1263 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1264 bool isSingleElementExtract =
1265 arrType.getElementType() == resultNestedType;
1267 if (isSingleElementExtract)
1268 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1271 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1272 op, resultType, adaptor.getInput(), idx);
1282 using OpConversionPattern::OpConversionPattern;
1285 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1286 ConversionPatternRewriter &rewriter)
const override {
1287 Type resultType = typeConverter->convertType(op.getResult().getType());
1289 adaptor.getElements());
1295 using OpConversionPattern::OpConversionPattern;
1298 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1299 ConversionPatternRewriter &rewriter)
const override {
1300 Type resultType = typeConverter->convertType(op.getResult().getType());
1302 adaptor.getFields());
1308 using OpConversionPattern::OpConversionPattern;
1311 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1312 ConversionPatternRewriter &rewriter)
const override {
1314 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1319struct StructExtractRefOpConversion
1321 using OpConversionPattern::OpConversionPattern;
1324 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1325 ConversionPatternRewriter &rewriter)
const override {
1326 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1327 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1333 using OpConversionPattern::OpConversionPattern;
1335 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1336 ConversionPatternRewriter &rewriter)
const override {
1337 Type resultType = typeConverter->convertType(op.getInput().getType());
1340 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1341 adaptor.getInput(), max);
1347 using OpConversionPattern::OpConversionPattern;
1349 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1350 ConversionPatternRewriter &rewriter)
const override {
1351 Type resultType = typeConverter->convertType(op.getInput().getType());
1354 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1355 adaptor.getInput(), zero);
1361 using OpConversionPattern::OpConversionPattern;
1363 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1364 ConversionPatternRewriter &rewriter)
const override {
1366 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1372 using OpConversionPattern::OpConversionPattern;
1374 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1375 ConversionPatternRewriter &rewriter)
const override {
1376 Type resultType = typeConverter->convertType(op.getInput().getType());
1377 if (isa_and_nonnull<IntegerType>(resultType)) {
1380 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1381 adaptor.getInput(), zero);
1389 using OpConversionPattern::OpConversionPattern;
1391 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1392 ConversionPatternRewriter &rewriter)
const override {
1394 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1397 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1403 using OpConversionPattern::OpConversionPattern;
1405 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1406 ConversionPatternRewriter &rewriter)
const override {
1408 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1411 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1416template <
typename SourceOp,
typename TargetOp>
1419 using OpAdaptor =
typename SourceOp::Adaptor;
1422 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1423 ConversionPatternRewriter &rewriter)
const override {
1424 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1425 adaptor.getRhs(),
false);
1430template <
typename SourceOp,
typename TargetOp>
1433 using OpAdaptor =
typename SourceOp::Adaptor;
1436 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1437 ConversionPatternRewriter &rewriter)
const override {
1438 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1444template <
typename SourceOp, ICmpPredicate pred>
1447 using OpAdaptor =
typename SourceOp::Adaptor;
1450 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1451 ConversionPatternRewriter &rewriter)
const override {
1453 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1455 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1456 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1461template <
typename SourceOp, arith::CmpFPredicate pred>
1464 using OpAdaptor =
typename SourceOp::Adaptor;
1467 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1468 ConversionPatternRewriter &rewriter)
const override {
1470 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1472 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1473 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1478template <
typename SourceOp,
bool withoutX>
1481 using OpAdaptor =
typename SourceOp::Adaptor;
1484 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1485 ConversionPatternRewriter &rewriter)
const override {
1491 unsigned bitWidth = op.getLhs().getType().getWidth();
1492 auto ignoredBits = APInt::getZero(bitWidth);
1493 auto detectIgnoredBits = [&](Value value) {
1494 auto constOp = value.getDefiningOp<ConstantOp>();
1497 auto constValue = constOp.getValue();
1499 ignoredBits |= constValue.getZBits();
1501 ignoredBits |= constValue.getUnknownBits();
1503 detectIgnoredBits(op.getLhs());
1504 detectIgnoredBits(op.getRhs());
1508 Value lhs = adaptor.getLhs();
1509 Value rhs = adaptor.getRhs();
1510 if (!ignoredBits.isZero()) {
1511 ignoredBits.flipAllBits();
1513 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1514 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1517 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1527 using OpConversionPattern::OpConversionPattern;
1530 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1531 ConversionPatternRewriter &rewriter)
const override {
1532 Location loc = op.getLoc();
1533 Type resultType = typeConverter->convertType(op.getResult().getType());
1535 op.emitError(
"conversion result type is not currently supported");
1538 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1539 int64_t resultBw = hw::getBitWidth(resultType);
1540 if (inputBw == -1 || resultBw == -1)
1544 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1545 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1548 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1549 rewriter.replaceOp(op, result);
1554template <
typename SourceOp>
1557 using OpAdaptor =
typename SourceOp::Adaptor;
1558 using ConversionPattern::typeConverter;
1561 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1562 ConversionPatternRewriter &rewriter)
const override {
1563 auto type = typeConverter->convertType(op.getResult().getType());
1564 if (type == adaptor.getInput().getType())
1565 rewriter.replaceOp(op, adaptor.getInput());
1567 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1573 using OpConversionPattern::OpConversionPattern;
1576 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1577 ConversionPatternRewriter &rewriter)
const override {
1578 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1579 op.getType().getWidth());
1585 using OpConversionPattern::OpConversionPattern;
1588 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1589 ConversionPatternRewriter &rewriter)
const override {
1590 auto targetWidth = op.getType().getWidth();
1591 auto inputWidth = op.getInput().getType().getWidth();
1594 rewriter, op.getLoc(),
1595 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1598 op, ValueRange{zeroExt, adaptor.getInput()});
1604 using OpConversionPattern::OpConversionPattern;
1607 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1608 ConversionPatternRewriter &rewriter)
const override {
1609 auto type = typeConverter->convertType(op.getType());
1611 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1612 rewriter.replaceOp(op, value);
1618 using OpConversionPattern::OpConversionPattern;
1621 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
1622 ConversionPatternRewriter &rewriter)
const override {
1623 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
1624 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1630 using OpConversionPattern::OpConversionPattern;
1633 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
1634 ConversionPatternRewriter &rewriter)
const override {
1635 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
1636 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1642 using OpConversionPattern::OpConversionPattern;
1645 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
1646 ConversionPatternRewriter &rewriter)
const override {
1647 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
1648 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1658 using OpConversionPattern::OpConversionPattern;
1661 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1662 ConversionPatternRewriter &rewriter)
const override {
1663 SmallVector<Type> convResTypes;
1664 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1667 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1668 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1669 adaptor.getOperands(), op.getArgNames(),
1670 op.getResultNames(),
1671 rewriter.getArrayAttr({}),
nullptr);
1678 using OpConversionPattern::OpConversionPattern;
1681 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1682 ConversionPatternRewriter &rewriter)
const override {
1683 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1689 using OpConversionPattern::OpConversionPattern;
1692 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1693 ConversionPatternRewriter &rewriter)
const override {
1694 SmallVector<Type> convResTypes;
1695 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1697 rewriter.replaceOpWithNewOp<func::CallOp>(
1698 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1703struct UnrealizedConversionCastConversion
1705 using OpConversionPattern::OpConversionPattern;
1708 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1709 ConversionPatternRewriter &rewriter)
const override {
1710 SmallVector<Type> convResTypes;
1711 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1716 if (convResTypes == adaptor.getOperands().getTypes()) {
1717 rewriter.replaceOp(op, adaptor.getOperands());
1721 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1722 op, convResTypes, adaptor.getOperands());
1728 using OpConversionPattern::OpConversionPattern;
1731 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1732 ConversionPatternRewriter &rewriter)
const override {
1733 Type resultType = typeConverter->convertType(op.getResult().getType());
1737 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1738 resultType.getIntOrFloatBitWidth(), op->getLoc());
1739 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1746 using OpConversionPattern::OpConversionPattern;
1749 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1750 ConversionPatternRewriter &rewriter)
const override {
1751 Type resultType = typeConverter->convertType(op.getResult().getType());
1755 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1756 resultType.getIntOrFloatBitWidth(), op->getLoc());
1758 op, resultType, adaptor.getValue(), amount,
false);
1764 using OpConversionPattern::OpConversionPattern;
1767 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1768 ConversionPatternRewriter &rewriter)
const override {
1769 Type resultType = typeConverter->convertType(op.getResult().getType());
1771 Location loc = op->getLoc();
1776 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1777 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1780 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1788 using OpConversionPattern::OpConversionPattern;
1791 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1792 ConversionPatternRewriter &rewriter)
const override {
1793 Type resultType = typeConverter->convertType(op.getResult().getType());
1797 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1798 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1804 using OpConversionPattern::OpConversionPattern;
1807 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1808 ConversionPatternRewriter &rewriter)
const override {
1809 Type resultType = typeConverter->convertType(op.getResult().getType());
1813 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1814 resultType.getIntOrFloatBitWidth(), op->getLoc());
1816 op, resultType, adaptor.getValue(), amount,
false);
1822 using OpConversionPattern::OpConversionPattern;
1825 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1826 ConversionPatternRewriter &rewriter)
const override {
1827 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
1832struct AssignedVariableOpConversion
1834 using OpConversionPattern::OpConversionPattern;
1837 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1838 ConversionPatternRewriter &rewriter)
const override {
1839 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1840 adaptor.getNameAttr());
1845template <
typename OpTy>
1848 using OpAdaptor =
typename OpTy::Adaptor;
1851 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1852 ConversionPatternRewriter &rewriter)
const override {
1855 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
1856 std::is_same_v<OpTy, BlockingAssignOp>) {
1858 delay = llhd::ConstantTimeOp::create(
1859 rewriter, op->getLoc(),
1860 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 0, 1));
1861 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
1863 delay = llhd::ConstantTimeOp::create(
1864 rewriter, op->getLoc(),
1865 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
1868 delay = adaptor.getDelay();
1871 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
1872 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
1878 using OpConversionPattern::OpConversionPattern;
1881 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1882 ConversionPatternRewriter &rewriter)
const override {
1887 auto type = typeConverter->convertType(op.getType());
1889 auto hasNoWriteEffect = [](Region ®ion) {
1890 auto result = region.walk([](Operation *operation) {
1891 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1892 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1893 !memOp.hasEffect<MemoryEffects::Free>())
1894 return WalkResult::advance();
1896 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1897 return WalkResult::advance();
1899 return WalkResult::interrupt();
1901 return !result.wasInterrupted();
1904 if (hasNoWriteEffect(op.getTrueRegion()) &&
1905 hasNoWriteEffect(op.getFalseRegion())) {
1906 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1907 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1909 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1910 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1912 Value convTrueVal = typeConverter->materializeTargetConversion(
1913 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1914 Value convFalseVal = typeConverter->materializeTargetConversion(
1915 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1917 rewriter.eraseOp(trueTerm);
1918 rewriter.eraseOp(falseTerm);
1920 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1921 convTrueVal, convFalseVal);
1926 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1927 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1928 ifOp.getThenRegion().end());
1929 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1930 ifOp.getElseRegion().end());
1931 rewriter.replaceOp(op, ifOp);
1937 using OpConversionPattern::OpConversionPattern;
1940 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1941 ConversionPatternRewriter &rewriter)
const override {
1942 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1947template <
typename SourceOp>
1950 using OpAdaptor =
typename SourceOp::Adaptor;
1953 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1954 ConversionPatternRewriter &rewriter)
const override {
1955 rewriter.modifyOpInPlace(op,
1956 [&]() { op->setOperands(adaptor.getOperands()); });
1961template <
typename MooreOpTy,
typename VerifOpTy>
1964 using OpAdaptor =
typename MooreOpTy::Adaptor;
1967 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1968 ConversionPatternRewriter &rewriter)
const override {
1970 op.getLabel().has_value()
1971 ? StringAttr::get(op->getContext(), op.getLabel().value())
1972 : StringAttr::
get(op->getContext());
1973 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1984 using OpConversionPattern::OpConversionPattern;
1987 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1988 ConversionPatternRewriter &rewriter)
const override {
1989 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
1995 using OpConversionPattern::OpConversionPattern;
1998 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1999 ConversionPatternRewriter &rewriter)
const override {
2000 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2001 adaptor.getInputs());
2007 using OpConversionPattern::OpConversionPattern;
2010 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2011 ConversionPatternRewriter &rewriter)
const override {
2013 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2014 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2015 auto widthAttr = adaptor.getSpecifierWidthAttr();
2017 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2018 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2020 switch (op.getFormat()) {
2021 case IntFormat::Decimal:
2022 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2023 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2024 adaptor.getIsSignedAttr());
2026 case IntFormat::Binary:
2027 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2028 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2030 case IntFormat::Octal:
2031 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2032 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2034 case IntFormat::HexLower:
2035 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2036 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2037 isLeftAlignedAttr, padCharAttr, widthAttr);
2039 case IntFormat::HexUpper:
2040 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2041 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2042 padCharAttr, widthAttr);
2045 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2050 using OpConversionPattern::OpConversionPattern;
2053 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2054 ConversionPatternRewriter &rewriter)
const override {
2055 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2057 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2058 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2059 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2061 switch (op.getFormat()) {
2062 case RealFormat::General:
2063 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2064 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2067 case RealFormat::Float:
2068 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2069 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2072 case RealFormat::Exponential:
2073 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2074 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2078 return rewriter.notifyMatchFailure(op,
"unsupported real format");
2084 using OpConversionPattern::OpConversionPattern;
2087 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
2088 ConversionPatternRewriter &rewriter)
const override {
2089 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
2090 op, adaptor.getMessage());
2102static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
2103 ConversionPatternRewriter &rewriter) {
2104 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
2109static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
2110 ConversionPatternRewriter &rewriter) {
2111 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
2117static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
2118 ConversionPatternRewriter &rewriter) {
2120 std::string severityString;
2122 switch (op.getSeverity()) {
2123 case (Severity::Fatal):
2124 severityString =
"Fatal: ";
2126 case (Severity::Error):
2127 severityString =
"Error: ";
2129 case (Severity::Warning):
2130 severityString =
"Warning: ";
2137 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
2138 auto message = sim::FormatStringConcatOp::create(
2139 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
2140 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
2146 FinishMessageBIOp::Adaptor adaptor,
2147 ConversionPatternRewriter &rewriter) {
2149 rewriter.eraseOp(op);
2158static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
2159 ConversionPatternRewriter &rewriter) {
2160 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
2165static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
2166 ConversionPatternRewriter &rewriter) {
2167 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
2172static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
2173 ConversionPatternRewriter &rewriter) {
2174 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
2183 const TypeConverter &converter) {
2184 target.addIllegalDialect<MooreDialect>();
2185 target.addLegalDialect<comb::CombDialect>();
2186 target.addLegalDialect<hw::HWDialect>();
2187 target.addLegalDialect<seq::SeqDialect>();
2188 target.addLegalDialect<llhd::LLHDDialect>();
2189 target.addLegalDialect<ltl::LTLDialect>();
2190 target.addLegalDialect<mlir::BuiltinDialect>();
2191 target.addLegalDialect<mlir::math::MathDialect>();
2192 target.addLegalDialect<sim::SimDialect>();
2193 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2194 target.addLegalDialect<verif::VerifDialect>();
2195 target.addLegalDialect<arith::ArithDialect>();
2197 target.addLegalOp<debug::ScopeOp>();
2199 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
2200 UnrealizedConversionCastOp, hw::OutputOp,
2201 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
2203 [&](Operation *op) {
return converter.isLegal(op); });
2205 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
2206 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
2207 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
2210 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
2211 return converter.isSignatureLegal(op.getFunctionType());
2215 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
2216 converter.isLegal(&op.getBody());
2221 typeConverter.addConversion([&](IntType type) {
2222 return IntegerType::get(type.getContext(), type.getWidth());
2225 typeConverter.addConversion([&](RealType type) -> mlir::Type {
2226 MLIRContext *ctx = type.getContext();
2227 switch (type.getWidth()) {
2228 case moore::RealWidth::f32:
2229 return mlir::Float32Type::get(ctx);
2230 case moore::RealWidth::f64:
2231 return mlir::Float64Type::get(ctx);
2235 typeConverter.addConversion(
2236 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
2238 typeConverter.addConversion([&](FormatStringType type) {
2239 return sim::FormatStringType::get(type.getContext());
2242 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
2243 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2244 return hw::ArrayType::get(
elementType, type.getSize());
2251 typeConverter.addConversion(
2252 [&](UnpackedArrayType type) -> std::optional<Type> {
2253 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2254 return hw::ArrayType::get(
elementType, type.getSize());
2258 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
2259 SmallVector<hw::StructType::FieldInfo> fields;
2260 for (
auto field : type.getMembers()) {
2261 hw::StructType::FieldInfo info;
2262 info.type = typeConverter.convertType(field.type);
2265 info.name = field.name;
2266 fields.push_back(info);
2268 return hw::StructType::get(type.getContext(), fields);
2276 typeConverter.addConversion(
2277 [&](UnpackedStructType type) -> std::optional<Type> {
2278 SmallVector<hw::StructType::FieldInfo> fields;
2279 for (
auto field : type.getMembers()) {
2280 hw::StructType::FieldInfo info;
2281 info.type = typeConverter.convertType(field.type);
2284 info.name = field.name;
2285 fields.push_back(info);
2287 return hw::StructType::get(type.getContext(), fields);
2291 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
2292 return LLVM::LLVMPointerType::get(type.getContext());
2296 typeConverter.addConversion(
2297 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
2300 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
2301 return LLVM::LLVMPointerType::get(type.getContext());
2304 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
2305 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
2306 return llhd::RefType::get(innerType);
2311 typeConverter.addConversion([](IntegerType type) {
return type; });
2312 typeConverter.addConversion([](FloatType type) {
return type; });
2313 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
2314 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
2315 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
2316 typeConverter.addConversion([](debug::StructType type) {
return type; });
2318 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
2319 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
2320 return llhd::RefType::get(innerType);
2324 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
2325 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2326 return hw::ArrayType::get(
elementType, type.getNumElements());
2330 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
2331 SmallVector<hw::StructType::FieldInfo> fields;
2332 for (
auto field : type.getElements()) {
2333 hw::StructType::FieldInfo info;
2334 info.type = typeConverter.convertType(field.type);
2337 info.name = field.name;
2338 fields.push_back(info);
2340 return hw::StructType::get(type.getContext(), fields);
2343 typeConverter.addTargetMaterialization(
2344 [&](mlir::OpBuilder &builder, mlir::Type resultType,
2345 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
2346 if (inputs.size() != 1 || !inputs[0])
2348 return UnrealizedConversionCastOp::create(builder, loc, resultType,
2353 typeConverter.addSourceMaterialization(
2354 [&](mlir::OpBuilder &builder, mlir::Type resultType,
2355 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
2356 if (inputs.size() != 1)
2358 return UnrealizedConversionCastOp::create(builder, loc, resultType,
2365 TypeConverter &typeConverter,
2366 ClassTypeCache &classCache) {
2372 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
2373 patterns.getContext(), classCache);
2377 ClassUpcastOpConversion,
2379 VariableOpConversion,
2383 ConversionOpConversion,
2384 BitcastConversion<PackedToSBVOp>,
2385 BitcastConversion<SBVToPackedOp>,
2386 BitcastConversion<LogicToIntOp>,
2387 BitcastConversion<IntToLogicOp>,
2388 BitcastConversion<ToBuiltinBoolOp>,
2392 SIntToRealOpConversion,
2393 UIntToRealOpConversion,
2394 RealToIntOpConversion,
2400 ReplicateOpConversion,
2402 ExtractOpConversion,
2403 DynExtractOpConversion,
2404 DynExtractRefOpConversion,
2406 StructExtractOpConversion,
2407 StructExtractRefOpConversion,
2408 ExtractRefOpConversion,
2409 StructCreateOpConversion,
2410 ConditionalOpConversion,
2411 ArrayCreateOpConversion,
2414 ConstantStringOpConv,
2417 ReduceAndOpConversion,
2418 ReduceOrOpConversion,
2419 ReduceXorOpConversion,
2420 BoolCastOpConversion,
2425 BinaryOpConversion<AddOp, comb::AddOp>,
2426 BinaryOpConversion<SubOp, comb::SubOp>,
2427 BinaryOpConversion<MulOp, comb::MulOp>,
2428 BinaryOpConversion<DivUOp, comb::DivUOp>,
2429 BinaryOpConversion<DivSOp, comb::DivSOp>,
2430 BinaryOpConversion<ModUOp, comb::ModUOp>,
2431 BinaryOpConversion<ModSOp, comb::ModSOp>,
2432 BinaryOpConversion<AndOp, comb::AndOp>,
2433 BinaryOpConversion<OrOp, comb::OrOp>,
2434 BinaryOpConversion<XorOp, comb::XorOp>,
2437 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
2438 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
2439 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
2440 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
2441 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
2444 PowUOpConversion, PowSOpConversion,
2447 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
2448 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
2449 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
2450 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
2451 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
2452 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
2453 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
2454 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
2455 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
2456 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
2457 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
2458 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
2459 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
2460 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
2461 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::ONE>,
2462 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
2463 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
2464 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
2465 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
2466 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
2467 CaseXZEqOpConversion<CaseZEqOp, true>,
2468 CaseXZEqOpConversion<CaseXZEqOp, false>,
2471 SVModuleOpConversion,
2472 InstanceOpConversion,
2473 ProcedureOpConversion,
2474 WaitEventOpConversion,
2482 AssignOpConversion<ContinuousAssignOp>,
2483 AssignOpConversion<DelayedContinuousAssignOp>,
2484 AssignOpConversion<BlockingAssignOp>,
2485 AssignOpConversion<NonBlockingAssignOp>,
2486 AssignOpConversion<DelayedNonBlockingAssignOp>,
2487 AssignedVariableOpConversion,
2490 HWInstanceOpConversion,
2493 UnrealizedConversionCastConversion,
2494 InPlaceOpConversion<debug::ArrayOp>,
2495 InPlaceOpConversion<debug::StructOp>,
2496 InPlaceOpConversion<debug::VariableOp>,
2499 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
2500 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
2501 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
2504 FormatLiteralOpConversion,
2505 FormatConcatOpConversion,
2506 FormatIntOpConversion,
2507 FormatRealOpConversion,
2508 DisplayBIOpConversion
2509 >(typeConverter,
patterns.getContext());
2527 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
2529 hw::populateHWModuleLikeTypeConversionPattern(
2530 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
2531 populateSCFToControlFlowConversionPatterns(
patterns);
2540struct MooreToCorePass
2541 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
2542 void runOnOperation()
override;
2548 return std::make_unique<MooreToCorePass>();
2552void MooreToCorePass::runOnOperation() {
2553 MLIRContext &
context = getContext();
2554 ModuleOp
module = getOperation();
2555 ClassTypeCache classCache;
2557 IRRewriter rewriter(module);
2558 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
2560 TypeConverter typeConverter;
2563 ConversionTarget target(
context);
2568 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
2571 if (failed(applyFullConversion(module, target, std::move(
patterns))))
2572 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.