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;
101struct FunctionCache {
102 FunctionCache(SymbolTable &symbolTable) : symbolTable(symbolTable) {}
108 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
109 function_ref<func::FuncOp()> createFn) {
110 auto &slot = map[name];
113 if (
auto fn = symbolTable.lookup<func::FuncOp>(name))
115 auto mod = cast<ModuleOp>(symbolTable.getOp());
116 OpBuilder::InsertionGuard g(builder);
117 builder.setInsertionPointToStart(mod.getBody());
119 symbolTable.insert(slot);
125 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
126 TypeRange argTypes, TypeRange resultTypes) {
127 return getOrCreate(builder, name, [&] {
128 auto mod = cast<ModuleOp>(symbolTable.getOp());
129 auto fnTy = builder.getFunctionType(argTypes, resultTypes);
130 auto fn = func::FuncOp::create(builder, mod.getLoc(), name, fnTy);
137 SymbolTable &symbolTable;
138 llvm::StringMap<func::FuncOp> map;
143static LLVM::LLVMStructType getOrCreateOpaqueStruct(MLIRContext *ctx,
144 SymbolRefAttr className) {
145 return LLVM::LLVMStructType::getIdentified(ctx, className.getRootReference());
148static LogicalResult resolveClassStructBody(ClassDeclOp op,
149 TypeConverter
const &typeConverter,
150 ClassTypeCache &cache) {
152 auto classSym = SymbolRefAttr::get(op.getSymNameAttr());
153 auto structInfo = cache.getStructInfo(classSym);
159 ClassTypeCache::ClassStructInfo structBody;
160 SmallVector<Type> structBodyMembers;
163 unsigned derivedStartIdx = 0;
165 if (
auto baseClass = op.getBaseAttr()) {
167 ModuleOp mod = op->getParentOfType<ModuleOp>();
168 auto *opSym = mod.lookupSymbol(baseClass);
169 auto classDeclOp = cast<ClassDeclOp>(opSym);
171 if (failed(resolveClassStructBody(classDeclOp, typeConverter, cache)))
175 auto baseClassStruct = cache.getStructInfo(baseClass);
176 structBodyMembers.push_back(baseClassStruct->classBody);
180 for (
auto &kv : baseClassStruct->propertyPath) {
181 SmallVector<unsigned, 2> path;
183 path.append(kv.second.begin(), kv.second.end());
184 structBody.setFieldPath(kv.first, path);
189 unsigned iterator = derivedStartIdx;
190 auto &block = op.getBody().front();
191 for (Operation &child : block) {
192 if (
auto prop = dyn_cast<ClassPropertyDeclOp>(child)) {
193 Type mooreTy = prop.getPropertyType();
194 Type llvmTy = typeConverter.convertType(mooreTy);
196 return prop.emitOpError()
197 <<
"failed to convert property type " << mooreTy;
199 structBodyMembers.push_back(llvmTy);
202 SmallVector<unsigned, 2> path{iterator};
203 structBody.setFieldPath(prop.getSymName(), path);
209 auto llvmStructTy = getOrCreateOpaqueStruct(op.getContext(), classSym);
211 if (!structBodyMembers.empty() &&
212 failed(llvmStructTy.setBody(structBodyMembers,
false)))
213 return op.emitOpError() <<
"Failed to set LLVM Struct body";
215 structBody.classBody = llvmStructTy;
216 cache.setClassInfo(classSym, structBody);
222static LogicalResult resolveClassStructBody(ModuleOp mod, SymbolRefAttr op,
223 TypeConverter
const &typeConverter,
224 ClassTypeCache &cache) {
225 auto classDeclOp = cast<ClassDeclOp>(*mod.lookupSymbol(op));
226 return resolveClassStructBody(classDeclOp, typeConverter, cache);
233static Value adjustIntegerWidth(OpBuilder &builder, Value value,
234 uint32_t targetWidth, Location loc) {
235 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
236 if (intWidth == targetWidth)
239 if (intWidth < targetWidth) {
241 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
242 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
246 intWidth - targetWidth);
248 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
249 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
253 builder.getIntegerType(targetWidth), -1);
254 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
258static FailureOr<hw::ModulePortInfo>
259getModulePortInfo(
const TypeConverter &typeConverter, SVModuleOp op) {
261 size_t resultNum = 0;
262 auto moduleTy = op.getModuleType();
263 SmallVector<hw::PortInfo> ports;
264 ports.reserve(moduleTy.getNumPorts());
266 for (
auto port : moduleTy.getPorts()) {
267 Type portTy = typeConverter.convertType(port.type);
269 return op.emitOpError(
"port '")
270 << port.name <<
"' has unsupported type " << port.type
271 <<
" that cannot be converted to hardware type";
273 if (port.dir == hw::ModulePort::Direction::Output) {
275 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
283 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
289struct DpiArrayCastInfo {
292 bool isPacked =
false;
296static std::optional<DpiArrayCastInfo> getDpiArrayCastInfo(Type type) {
297 DpiArrayCastInfo
info;
298 if (
auto refType = dyn_cast<RefType>(type)) {
300 type = refType.getNestedType();
303 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
304 info.isPacked =
true;
305 info.elementType = arrayType.getElementType();
308 if (
auto arrayType = dyn_cast<OpenArrayType>(type)) {
310 info.isPacked =
true;
311 info.elementType = arrayType.getElementType();
314 if (
auto arrayType = dyn_cast<UnpackedArrayType>(type)) {
315 info.elementType = arrayType.getElementType();
318 if (
auto arrayType = dyn_cast<OpenUnpackedArrayType>(type)) {
320 info.elementType = arrayType.getElementType();
326static bool hasOpenArrayBoundaryType(Type type) {
327 if (isa<OpenArrayType, OpenUnpackedArrayType>(type))
329 if (
auto refType = dyn_cast<RefType>(type))
330 return isa<OpenArrayType, OpenUnpackedArrayType>(refType.getNestedType());
334static bool isSupportedDpiOpenArrayCast(Type source, Type target) {
335 auto sourceInfo = getDpiArrayCastInfo(source);
336 auto targetInfo = getDpiArrayCastInfo(target);
337 if (!sourceInfo || !targetInfo)
342 return sourceInfo->isRef == targetInfo->isRef &&
343 sourceInfo->isPacked == targetInfo->isPacked &&
344 sourceInfo->elementType == targetInfo->elementType &&
345 (targetInfo->isOpen && !sourceInfo->isOpen);
353 using OpConversionPattern::OpConversionPattern;
356 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
357 ConversionPatternRewriter &rewriter)
const override {
358 rewriter.setInsertionPoint(op);
361 auto portInfo = getModulePortInfo(*typeConverter, op);
362 if (failed(portInfo))
365 auto hwModuleOp = hw::HWModuleOp::create(rewriter, op.getLoc(),
366 op.getSymNameAttr(), *portInfo);
369 SymbolTable::setSymbolVisibility(hwModuleOp,
370 SymbolTable::getSymbolVisibility(op));
371 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
373 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
375 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
376 hwModuleOp.getBodyRegion().end());
379 rewriter.eraseOp(op);
385 using OpConversionPattern::OpConversionPattern;
388 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
389 ConversionPatternRewriter &rewriter)
const override {
390 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
396 using OpConversionPattern::OpConversionPattern;
399 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
400 ConversionPatternRewriter &rewriter)
const override {
401 auto instName = op.getInstanceNameAttr();
402 auto moduleName = op.getModuleNameAttr();
405 rewriter.setInsertionPoint(op);
406 auto instOp = hw::InstanceOp::create(
407 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
408 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
409 rewriter.getArrayAttr({}),
nullptr,
413 op.replaceAllUsesWith(instOp.getResults());
414 rewriter.eraseOp(op);
419static void getValuesToObserve(Region *region,
420 function_ref<
void(Value)> setInsertionPoint,
421 const TypeConverter *typeConverter,
422 ConversionPatternRewriter &rewriter,
423 SmallVector<Value> &observeValues) {
424 SmallDenseSet<Value> alreadyObserved;
425 Location loc = region->getLoc();
427 auto probeIfSignal = [&](Value value) -> Value {
428 if (!isa<llhd::RefType>(value.getType()))
430 return llhd::ProbeOp::create(rewriter, loc, value);
433 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
434 [&](Operation *operation) {
435 for (
auto value : operation->getOperands()) {
436 if (isa<BlockArgument>(value))
437 value = rewriter.getRemappedValue(value);
439 if (region->isAncestor(value.getParentRegion()))
441 if (
auto *defOp = value.getDefiningOp();
442 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
444 if (!alreadyObserved.insert(value).second)
447 OpBuilder::InsertionGuard g(rewriter);
448 if (
auto remapped = rewriter.getRemappedValue(value)) {
449 setInsertionPoint(remapped);
450 observeValues.push_back(probeIfSignal(remapped));
452 setInsertionPoint(value);
453 auto type = typeConverter->convertType(value.getType());
454 auto converted = typeConverter->materializeTargetConversion(
455 rewriter, loc, type, value);
456 observeValues.push_back(probeIfSignal(converted));
463 using OpConversionPattern::OpConversionPattern;
466 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
467 ConversionPatternRewriter &rewriter)
const override {
469 SmallVector<Value> observedValues;
470 if (op.getKind() == ProcedureKind::AlwaysComb ||
471 op.getKind() == ProcedureKind::AlwaysLatch) {
472 auto setInsertionPoint = [&](Value value) {
473 rewriter.setInsertionPoint(op);
475 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
476 rewriter, observedValues);
479 auto loc = op.getLoc();
480 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
485 if (op.getKind() == ProcedureKind::Initial ||
486 op.getKind() == ProcedureKind::Final) {
488 if (op.getKind() == ProcedureKind::Initial)
489 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
491 newOp = llhd::FinalOp::create(rewriter, loc);
492 auto &body = newOp->getRegion(0);
493 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
495 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
496 rewriter.setInsertionPoint(returnOp);
497 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
499 rewriter.eraseOp(op);
504 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
509 rewriter.createBlock(&newOp.getBody());
510 auto *block = &op.getBody().front();
511 cf::BranchOp::create(rewriter, loc, block);
512 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
513 newOp.getBody().end());
521 if (op.getKind() == ProcedureKind::AlwaysComb ||
522 op.getKind() == ProcedureKind::AlwaysLatch) {
523 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
524 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
525 ValueRange{}, block);
532 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
533 rewriter.setInsertionPoint(returnOp);
534 cf::BranchOp::create(rewriter, loc, block);
535 rewriter.eraseOp(returnOp);
538 rewriter.eraseOp(op);
548 using OpConversionPattern::OpConversionPattern;
551 matchAndRewrite(CoroutineOp op, OpAdaptor adaptor,
552 ConversionPatternRewriter &rewriter)
const override {
553 auto funcType = op.getFunctionType();
554 TypeConverter::SignatureConversion sigConversion(funcType.getNumInputs());
555 for (
auto [i, type] :
llvm::enumerate(funcType.getInputs())) {
556 auto converted = typeConverter->convertType(type);
559 sigConversion.addInputs(i, converted);
561 SmallVector<Type> resultTypes;
562 if (failed(typeConverter->convertTypes(funcType.getResults(), resultTypes)))
565 auto newFuncType = FunctionType::get(
566 rewriter.getContext(), sigConversion.getConvertedTypes(), resultTypes);
567 auto newOp = llhd::CoroutineOp::create(rewriter, op.getLoc(),
568 op.getSymName(), newFuncType);
569 newOp.setSymVisibilityAttr(op.getSymVisibilityAttr());
570 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
571 newOp.getBody().end());
572 if (failed(rewriter.convertRegionTypes(&newOp.getBody(), *typeConverter,
578 llvm::make_early_inc_range(newOp.getBody().getOps<ReturnOp>())) {
579 rewriter.setInsertionPoint(returnOp);
580 rewriter.replaceOpWithNewOp<llhd::ReturnOp>(returnOp, ValueRange{});
583 rewriter.eraseOp(op);
589 using OpConversionPattern::OpConversionPattern;
592 matchAndRewrite(CallCoroutineOp op, OpAdaptor adaptor,
593 ConversionPatternRewriter &rewriter)
const override {
594 SmallVector<Type> convResTypes;
595 if (failed(typeConverter->convertTypes(op.getResultTypes(), convResTypes)))
597 rewriter.replaceOpWithNewOp<llhd::CallCoroutineOp>(
598 op, convResTypes, adaptor.getCallee(), adaptor.getOperands());
604 using OpConversionPattern::OpConversionPattern;
607 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
608 ConversionPatternRewriter &rewriter)
const override {
642 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
648 if (op.getBody().front().empty()) {
651 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
655 auto *waitBlock = rewriter.createBlock(resumeBlock);
656 auto *checkBlock = rewriter.createBlock(resumeBlock);
658 auto loc = op.getLoc();
659 rewriter.setInsertionPoint(op);
660 cf::BranchOp::create(rewriter, loc, waitBlock);
670 SmallVector<Value> valuesBefore;
671 rewriter.setInsertionPointToEnd(waitBlock);
672 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
673 bool allDetectsAreAnyChange =
true;
675 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
676 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
677 allDetectsAreAnyChange =
false;
678 valuesBefore.push_back(detectOp.getInput());
679 rewriter.eraseOp(detectOp);
685 SmallVector<Value> observeValues;
686 auto setInsertionPointAfterDef = [&](Value value) {
687 if (
auto *op = value.getDefiningOp())
688 rewriter.setInsertionPointAfter(op);
689 if (
auto arg = dyn_cast<BlockArgument>(value))
690 rewriter.setInsertionPointToStart(value.getParentBlock());
693 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
694 typeConverter, rewriter, observeValues);
699 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
700 observeValues, ValueRange{}, checkBlock);
701 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
702 rewriter.eraseOp(clonedOp);
706 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
707 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
709 rewriter.eraseOp(op);
713 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
714 assert(before.getType() == after.getType() &&
715 "mismatched types after clone op");
716 auto beforeType = cast<IntType>(before.getType());
720 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
721 constexpr int LSB = 0;
723 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
725 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
726 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
729 auto intType = rewriter.getIntegerType(beforeType.getWidth());
730 before = typeConverter->materializeTargetConversion(rewriter, loc,
732 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
735 if (edge == Edge::AnyChange)
736 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
739 SmallVector<Value> disjuncts;
742 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
744 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
746 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
747 disjuncts.push_back(posedge);
750 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
752 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
754 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
755 disjuncts.push_back(posedge);
758 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
765 SmallVector<Value> triggers;
766 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
767 if (!allDetectsAreAnyChange) {
768 if (!isa<IntType>(before.getType()))
769 return detectOp->emitError() <<
"requires int operand";
771 rewriter.setInsertionPoint(detectOp);
773 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
774 if (detectOp.getCondition()) {
775 auto condition = typeConverter->materializeTargetConversion(
776 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
778 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
780 triggers.push_back(trigger);
783 rewriter.eraseOp(detectOp);
786 rewriter.setInsertionPointToEnd(checkBlock);
787 if (triggers.empty()) {
792 cf::BranchOp::create(rewriter, loc, resumeBlock);
798 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
799 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
808static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
809 ConversionPatternRewriter &rewriter) {
811 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
812 rewriter.setInsertionPoint(op);
813 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
814 adaptor.getDelay(), ValueRange{},
815 ValueRange{}, resumeBlock);
816 rewriter.setInsertionPointToStart(resumeBlock);
821static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
822 ConversionPatternRewriter &rewriter) {
823 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
832 ConversionPatternRewriter &rewriter) {
834 if (isa<mlir::LLVM::LLVMPointerType>(type))
835 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
838 if (isa<llhd::TimeType>(type)) {
840 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
841 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
845 if (
auto floatType = dyn_cast<FloatType>(type)) {
846 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
847 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
851 if (
auto strType = dyn_cast<sim::DynamicStringType>(type))
852 return sim::StringConstantOp::create(rewriter, loc, strType,
"");
855 if (
auto queueType = dyn_cast<sim::QueueType>(type))
856 return sim::QueueEmptyOp::create(rewriter, loc, queueType);
859 int64_t width = hw::getBitWidth(type);
867 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
870struct ClassPropertyRefOpConversion
872 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
873 ClassTypeCache &cache)
877 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
878 ConversionPatternRewriter &rewriter)
const override {
879 Location loc = op.getLoc();
880 MLIRContext *ctx = rewriter.getContext();
883 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
885 Value instRef = adaptor.getInstance();
889 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
890 SymbolRefAttr classSym = classRefTy.getClassSym();
891 ModuleOp mod = op->getParentOfType<ModuleOp>();
892 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
893 return rewriter.notifyMatchFailure(op,
894 "Could not resolve class struct for " +
895 classSym.getRootReference().str());
897 auto structInfo = cache.getStructInfo(classSym);
898 assert(structInfo &&
"class struct info must exist");
899 auto structTy = structInfo->classBody;
902 auto propSym = op.getProperty();
903 auto pathOpt = structInfo->getFieldPath(propSym);
905 return rewriter.notifyMatchFailure(op,
906 "no GEP path for property " + propSym);
908 auto i32Ty = IntegerType::get(ctx, 32);
909 SmallVector<Value> idxVals;
910 for (
unsigned idx : *pathOpt)
911 idxVals.push_back(LLVM::ConstantOp::create(
912 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
915 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
917 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
920 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
924 rewriter.replaceOp(op, fieldRef);
929 ClassTypeCache &cache;
933 using OpConversionPattern::OpConversionPattern;
936 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
937 ConversionPatternRewriter &rewriter)
const override {
939 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
940 Type srcTy = adaptor.getInstance().getType();
943 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
946 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
947 rewriter.replaceOp(op, adaptor.getInstance());
950 return rewriter.notifyMatchFailure(
951 op,
"Upcast applied to non-opaque pointers!");
957 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
958 ClassTypeCache &cache, FunctionCache &funcCache)
960 funcCache(funcCache) {}
963 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
964 ConversionPatternRewriter &rewriter)
const override {
965 Location loc = op.getLoc();
966 MLIRContext *ctx = rewriter.getContext();
968 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
969 auto sym = handleTy.getClassSym();
971 ModuleOp mod = op->getParentOfType<ModuleOp>();
973 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
974 return op.emitError() <<
"Could not resolve class struct for " << sym;
976 auto structTy = cache.getStructInfo(sym)->classBody;
981 for (
auto memberTy : structTy.getBody()) {
982 if (!LLVM::isCompatibleType(memberTy) &&
983 !memberTy.hasTrait<DataLayoutTypeInterface::Trait>()) {
984 return op.emitError()
985 <<
"class struct has member types with no data layout";
991 uint64_t byteSize = dl.getTypeSize(structTy);
992 auto i64Ty = IntegerType::get(ctx, 64);
993 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
994 rewriter.getI64IntegerAttr(byteSize));
997 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
998 auto mallocFn = funcCache.getOrCreate(rewriter,
"malloc", {i64Ty}, {ptrTy});
1000 func::CallOp::create(rewriter, loc, mallocFn, ValueRange{cSize});
1004 rewriter.replaceOp(op, call.getResult(0));
1009 ClassTypeCache &cache;
1010 FunctionCache &funcCache;
1014 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
1015 ClassTypeCache &cache)
1019 matchAndRewrite(ClassDeclOp op, OpAdaptor,
1020 ConversionPatternRewriter &rewriter)
const override {
1022 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
1025 rewriter.eraseOp(op);
1030 ClassTypeCache &cache;
1034 using OpConversionPattern::OpConversionPattern;
1037 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
1038 ConversionPatternRewriter &rewriter)
const override {
1039 auto loc = op.getLoc();
1040 auto resultType = typeConverter->convertType(op.getResult().getType());
1042 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
1045 Value init = adaptor.getInitial();
1047 auto refType = dyn_cast<llhd::RefType>(resultType);
1049 return rewriter.notifyMatchFailure(
1050 op.getLoc(),
"variable type did not convert to llhd::RefType");
1056 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
1057 op.getNameAttr(), init);
1063 using OpConversionPattern::OpConversionPattern;
1066 matchAndRewrite(NetOp op, OpAdaptor adaptor,
1067 ConversionPatternRewriter &rewriter)
const override {
1068 auto loc = op.getLoc();
1070 auto resultType = typeConverter->convertType(op.getResult().getType());
1072 return rewriter.notifyMatchFailure(loc,
"invalid net type");
1074 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
1080 createInitialValue(op.getKind(), rewriter, loc, width,
elementType);
1081 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
1082 op, resultType, op.getNameAttr(), init);
1084 if (
auto assignedValue = adaptor.getAssignment()) {
1085 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
1086 llvm::StringRef(
"ns"), 0, 1);
1087 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
1088 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
1095 static mlir::Value createInitialValue(NetKind kind,
1096 ConversionPatternRewriter &rewriter,
1097 Location loc, int64_t width,
1108 if (kind == NetKind::Supply1 || kind == NetKind::Tri1)
1109 return APInt::getAllOnes(width);
1110 return APInt::getZero(width);
1118static LogicalResult
convert(GlobalVariableOp op,
1119 GlobalVariableOp::Adaptor adaptor,
1120 ConversionPatternRewriter &rewriter,
1121 const TypeConverter &typeConverter) {
1122 auto type = typeConverter.convertType(op.getType());
1123 auto sig = llhd::GlobalSignalOp::create(rewriter, op.getLoc(),
1124 op.getSymNameAttr(), type);
1125 sig.getInitRegion().takeBody(op.getInitRegion());
1126 rewriter.eraseOp(op);
1131static LogicalResult
convert(GetGlobalVariableOp op,
1132 GetGlobalVariableOp::Adaptor adaptor,
1133 ConversionPatternRewriter &rewriter,
1134 const TypeConverter &typeConverter) {
1135 auto type = typeConverter.convertType(op.getType());
1136 rewriter.replaceOpWithNewOp<llhd::GetGlobalSignalOp>(op, type,
1137 op.getGlobalNameAttr());
1146 using OpConversionPattern::OpConversionPattern;
1149 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
1150 ConversionPatternRewriter &rewriter)
const override {
1152 auto value = op.getValue().toAPInt(
false);
1153 auto type = rewriter.getIntegerType(value.getBitWidth());
1155 op, type, rewriter.getIntegerAttr(type, value));
1161 using OpConversionPattern::OpConversionPattern;
1164 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
1165 ConversionPatternRewriter &rewriter)
const override {
1166 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
1172 using OpConversionPattern::OpConversionPattern;
1175 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
1176 ConversionPatternRewriter &rewriter)
const override {
1177 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
1178 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
1179 StringRef(
"fs"), 0, 0));
1185 using OpConversionPattern::OpConversionPattern;
1187 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
1188 ConversionPatternRewriter &rewriter)
const override {
1189 const auto resultType =
1190 typeConverter->convertType(op.getResult().getType());
1191 const auto intType = mlir::cast<IntegerType>(resultType);
1193 const auto str = op.getValue();
1194 const unsigned byteWidth = intType.getWidth();
1195 APInt value(byteWidth, 0);
1198 const size_t maxChars =
1199 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
1200 for (
size_t i = 0; i < maxChars; i++) {
1201 const size_t pos = str.size() - 1 - i;
1202 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
1203 value |= APInt(byteWidth, asciiChar) << (8 * i);
1207 op, resultType, rewriter.getIntegerAttr(resultType, value));
1213 using OpConversionPattern::OpConversionPattern;
1215 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1216 ConversionPatternRewriter &rewriter)
const override {
1217 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1223 using OpConversionPattern::OpConversionPattern;
1225 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1226 ConversionPatternRewriter &rewriter)
const override {
1227 Type resultType = typeConverter->convertType(op.getResult().getType());
1229 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1230 adaptor.getValue());
1236 using OpConversionPattern::OpConversionPattern;
1239 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1240 ConversionPatternRewriter &rewriter)
const override {
1243 Type resultType = typeConverter->convertType(op.getResult().getType());
1244 Type inputType = adaptor.getInput().getType();
1245 int32_t low = adaptor.getLowBit();
1247 if (isa<IntegerType>(inputType)) {
1248 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1249 int32_t resultWidth = hw::getBitWidth(resultType);
1250 int32_t high = low + resultWidth;
1252 SmallVector<Value> toConcat;
1255 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
1257 if (low < inputWidth && high > 0) {
1258 int32_t lowIdx = std::max(low, 0);
1261 rewriter.getIntegerType(
1262 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
1263 adaptor.getInput(), lowIdx);
1264 toConcat.push_back(middle);
1267 int32_t diff = high - inputWidth;
1271 toConcat.push_back(val);
1276 rewriter.replaceOp(op, concat);
1280 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1281 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
1282 int32_t inputWidth = arrTy.getNumElements();
1284 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1285 resArrTy && resArrTy != arrTy.getElementType()) {
1286 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
1287 if (elementWidth < 0)
1290 int32_t high = low + resArrTy.getNumElements();
1291 int32_t resWidth = resArrTy.getNumElements();
1293 SmallVector<Value> toConcat;
1296 rewriter, op.getLoc(),
1297 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1300 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1302 toConcat.push_back(res);
1305 if (low < inputWidth && high > 0) {
1306 int32_t lowIdx = std::max(0, low);
1308 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
1312 arrTy.getElementType(),
1313 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1314 adaptor.getInput(), lowIdxVal);
1315 toConcat.push_back(middle);
1318 int32_t diff = high - inputWidth;
1321 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1323 rewriter, op.getLoc(),
1324 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1325 toConcat.push_back(val);
1330 rewriter.replaceOp(op, concat);
1335 if (low < 0 || low >= inputWidth) {
1336 int32_t bw = hw::getBitWidth(resultType);
1342 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
1343 rewriter.replaceOp(op, bitcast);
1348 rewriter.getIntegerType(width),
1349 adaptor.getLowBit());
1350 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
1359 using OpConversionPattern::OpConversionPattern;
1362 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1363 ConversionPatternRewriter &rewriter)
const override {
1365 Type resultType = typeConverter->convertType(op.getResult().getType());
1367 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1369 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1370 int64_t width = hw::getBitWidth(inputType);
1375 rewriter, op.getLoc(),
1376 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1377 adaptor.getLowBit());
1378 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1379 op, resultType, adaptor.getInput(), lowBit);
1383 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1385 rewriter, op.getLoc(),
1386 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1387 adaptor.getLowBit());
1391 if (arrType.getElementType() !=
1392 cast<llhd::RefType>(resultType).getNestedType()) {
1393 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1394 op, resultType, adaptor.getInput(), lowBit);
1398 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1408 using OpConversionPattern::OpConversionPattern;
1411 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1412 ConversionPatternRewriter &rewriter)
const override {
1413 Type resultType = typeConverter->convertType(op.getResult().getType());
1414 Type inputType = adaptor.getInput().getType();
1416 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1417 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1418 intType.getWidth(), op->getLoc());
1419 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1420 adaptor.getInput(), amount);
1422 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1426 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1427 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1428 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1431 bool isSingleElementExtract = arrType.getElementType() == resultType;
1433 if (isSingleElementExtract)
1434 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1438 adaptor.getInput(), idx);
1448 using OpConversionPattern::OpConversionPattern;
1451 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1452 ConversionPatternRewriter &rewriter)
const override {
1454 Type resultType = typeConverter->convertType(op.getResult().getType());
1456 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1458 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1459 int64_t width = hw::getBitWidth(inputType);
1464 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1465 llvm::Log2_64_Ceil(width), op->getLoc());
1466 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1467 op, resultType, adaptor.getInput(), amount);
1471 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1472 Value idx = adjustIntegerWidth(
1473 rewriter, adaptor.getLowBit(),
1474 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1476 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1477 bool isSingleElementExtract =
1478 arrType.getElementType() == resultNestedType;
1480 if (isSingleElementExtract)
1481 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1484 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1485 op, resultType, adaptor.getInput(), idx);
1495 using OpConversionPattern::OpConversionPattern;
1498 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1499 ConversionPatternRewriter &rewriter)
const override {
1500 Type resultType = typeConverter->convertType(op.getResult().getType());
1502 adaptor.getElements());
1508 using OpConversionPattern::OpConversionPattern;
1511 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1512 ConversionPatternRewriter &rewriter)
const override {
1513 Type resultType = typeConverter->convertType(op.getResult().getType());
1515 adaptor.getFields());
1521 using OpConversionPattern::OpConversionPattern;
1524 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1525 ConversionPatternRewriter &rewriter)
const override {
1527 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1532struct StructExtractRefOpConversion
1534 using OpConversionPattern::OpConversionPattern;
1537 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1538 ConversionPatternRewriter &rewriter)
const override {
1539 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1540 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1546 using OpConversionPattern::OpConversionPattern;
1549 matchAndRewrite(UnionCreateOp op, OpAdaptor adaptor,
1550 ConversionPatternRewriter &rewriter)
const override {
1551 Type resultType = typeConverter->convertType(op.getResult().getType());
1552 rewriter.replaceOpWithNewOp<hw::UnionCreateOp>(
1553 op, resultType, adaptor.getFieldNameAttr(), adaptor.getInput());
1559 using OpConversionPattern::OpConversionPattern;
1562 matchAndRewrite(UnionExtractOp op, OpAdaptor adaptor,
1563 ConversionPatternRewriter &rewriter)
const override {
1564 rewriter.replaceOpWithNewOp<hw::UnionExtractOp>(op, adaptor.getInput(),
1565 adaptor.getFieldNameAttr());
1570struct UnionExtractRefOpConversion
1572 using OpConversionPattern::OpConversionPattern;
1575 matchAndRewrite(UnionExtractRefOp op, OpAdaptor adaptor,
1576 ConversionPatternRewriter &rewriter)
const override {
1577 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1578 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1584 using OpConversionPattern::OpConversionPattern;
1586 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1587 ConversionPatternRewriter &rewriter)
const override {
1588 Type resultType = typeConverter->convertType(op.getInput().getType());
1591 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1592 adaptor.getInput(), max);
1598 using OpConversionPattern::OpConversionPattern;
1600 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1601 ConversionPatternRewriter &rewriter)
const override {
1602 Type resultType = typeConverter->convertType(op.getInput().getType());
1605 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1606 adaptor.getInput(), zero);
1612 using OpConversionPattern::OpConversionPattern;
1614 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1615 ConversionPatternRewriter &rewriter)
const override {
1617 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1623 using OpConversionPattern::OpConversionPattern;
1625 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1626 ConversionPatternRewriter &rewriter)
const override {
1627 Type resultType = typeConverter->convertType(op.getInput().getType());
1628 if (isa_and_nonnull<IntegerType>(resultType)) {
1631 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1632 adaptor.getInput(), zero);
1635 if (isa_and_nonnull<FloatType>(resultType)) {
1636 Value zero = arith::ConstantOp::create(
1637 rewriter, op->getLoc(), rewriter.getFloatAttr(resultType, 0.0));
1638 rewriter.replaceOpWithNewOp<arith::CmpFOp>(op, arith::CmpFPredicate::ONE,
1639 adaptor.getInput(), zero);
1647 using OpConversionPattern::OpConversionPattern;
1649 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1650 ConversionPatternRewriter &rewriter)
const override {
1652 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1655 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1661 using OpConversionPattern::OpConversionPattern;
1663 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1664 ConversionPatternRewriter &rewriter)
const override {
1666 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1669 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1675 using OpConversionPattern::OpConversionPattern;
1677 matchAndRewrite(NegRealOp op, OpAdaptor adaptor,
1678 ConversionPatternRewriter &rewriter)
const override {
1679 rewriter.replaceOpWithNewOp<arith::NegFOp>(op, adaptor.getInput());
1684template <
typename SourceOp,
typename TargetOp>
1687 using OpAdaptor =
typename SourceOp::Adaptor;
1690 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1691 ConversionPatternRewriter &rewriter)
const override {
1692 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1693 adaptor.getRhs(),
false);
1698template <
typename SourceOp,
typename TargetOp>
1701 using OpAdaptor =
typename SourceOp::Adaptor;
1704 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1705 ConversionPatternRewriter &rewriter)
const override {
1706 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1712template <
typename SourceOp, ICmpPredicate pred>
1715 using OpAdaptor =
typename SourceOp::Adaptor;
1718 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1719 ConversionPatternRewriter &rewriter)
const override {
1721 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1723 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1724 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1729template <
typename SourceOp, arith::CmpFPredicate pred>
1732 using OpAdaptor =
typename SourceOp::Adaptor;
1735 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1736 ConversionPatternRewriter &rewriter)
const override {
1738 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1740 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1741 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1746template <
typename SourceOp,
bool withoutX>
1749 using OpAdaptor =
typename SourceOp::Adaptor;
1752 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1753 ConversionPatternRewriter &rewriter)
const override {
1759 unsigned bitWidth = op.getLhs().getType().getWidth();
1760 auto ignoredBits = APInt::getZero(bitWidth);
1761 auto detectIgnoredBits = [&](Value value) {
1762 auto constOp = value.getDefiningOp<ConstantOp>();
1765 auto constValue = constOp.getValue();
1767 ignoredBits |= constValue.getZBits();
1769 ignoredBits |= constValue.getUnknownBits();
1771 detectIgnoredBits(op.getLhs());
1772 detectIgnoredBits(op.getRhs());
1776 Value lhs = adaptor.getLhs();
1777 Value rhs = adaptor.getRhs();
1778 if (!ignoredBits.isZero()) {
1779 ignoredBits.flipAllBits();
1781 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1782 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1785 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1795 using OpConversionPattern::OpConversionPattern;
1798 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1799 ConversionPatternRewriter &rewriter)
const override {
1800 Location loc = op.getLoc();
1801 Type resultType = typeConverter->convertType(op.getResult().getType());
1803 op.emitError(
"conversion result type is not currently supported");
1806 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1807 int64_t resultBw = hw::getBitWidth(resultType);
1808 if (inputBw == -1 || resultBw == -1) {
1809 if (isSupportedDpiOpenArrayCast(op.getInput().getType(),
1810 op.getResult().getType())) {
1811 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1812 op, resultType, adaptor.getInput());
1815 if (hasOpenArrayBoundaryType(op.getInput().getType()) ||
1816 hasOpenArrayBoundaryType(op.getResult().getType())) {
1817 op.emitError(
"unsupported DPI open-array conversion from ")
1818 << op.getInput().getType() <<
" to " << op.getResult().getType();
1825 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1826 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1829 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1830 rewriter.replaceOp(op, result);
1835template <
typename SourceOp>
1838 using OpAdaptor =
typename SourceOp::Adaptor;
1839 using ConversionPattern::typeConverter;
1842 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1843 ConversionPatternRewriter &rewriter)
const override {
1844 auto type = typeConverter->convertType(op.getResult().getType());
1845 if (type == adaptor.getInput().getType())
1846 rewriter.replaceOp(op, adaptor.getInput());
1848 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1854template <
typename SourceOp>
1857 using OpAdaptor =
typename SourceOp::Adaptor;
1858 using ConversionPattern::typeConverter;
1861 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1862 ConversionPatternRewriter &rewriter)
const override {
1863 rewriter.replaceOp(op, adaptor.getInput());
1869 using OpConversionPattern::OpConversionPattern;
1872 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1873 ConversionPatternRewriter &rewriter)
const override {
1874 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1875 op.getType().getWidth());
1881 using OpConversionPattern::OpConversionPattern;
1884 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1885 ConversionPatternRewriter &rewriter)
const override {
1886 auto targetWidth = op.getType().getWidth();
1887 auto inputWidth = op.getInput().getType().getWidth();
1890 rewriter, op.getLoc(),
1891 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1894 op, ValueRange{zeroExt, adaptor.getInput()});
1900 using OpConversionPattern::OpConversionPattern;
1903 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1904 ConversionPatternRewriter &rewriter)
const override {
1905 auto type = typeConverter->convertType(op.getType());
1907 comb::createOrFoldSExt(rewriter, op.getLoc(), adaptor.getInput(), type);
1908 rewriter.replaceOp(op, value);
1914 using OpConversionPattern::OpConversionPattern;
1917 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
1918 ConversionPatternRewriter &rewriter)
const override {
1919 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
1920 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1926 using OpConversionPattern::OpConversionPattern;
1929 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
1930 ConversionPatternRewriter &rewriter)
const override {
1931 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
1932 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1938 using OpConversionPattern::OpConversionPattern;
1941 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
1942 ConversionPatternRewriter &rewriter)
const override {
1943 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
1949 using OpConversionPattern::OpConversionPattern;
1952 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
1953 ConversionPatternRewriter &rewriter)
const override {
1954 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
1955 op, typeConverter->convertType(op.getType()), adaptor.getInput());
1961 using OpConversionPattern::OpConversionPattern;
1964 matchAndRewrite(ConvertRealOp op, OpAdaptor adaptor,
1965 ConversionPatternRewriter &rewriter)
const override {
1966 op.getInput().getType().getWidth() < op.getResult().getType().getWidth()
1967 ? rewriter.replaceOpWithNewOp<arith::ExtFOp>(
1968 op, typeConverter->convertType(op.getType()), adaptor.getInput())
1969 : rewriter.replaceOpWithNewOp<arith::TruncFOp>(
1970 op, typeConverter->
convertType(op.getType()), adaptor.getInput());
1980 using OpConversionPattern::OpConversionPattern;
1983 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1984 ConversionPatternRewriter &rewriter)
const override {
1985 SmallVector<Type> convResTypes;
1986 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1989 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1990 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1991 adaptor.getOperands(), op.getArgNames(),
1992 op.getResultNames(),
1993 rewriter.getArrayAttr({}),
nullptr);
2000 using OpConversionPattern::OpConversionPattern;
2003 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
2004 ConversionPatternRewriter &rewriter)
const override {
2005 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
2011 using OpConversionPattern::OpConversionPattern;
2014 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
2015 ConversionPatternRewriter &rewriter)
const override {
2016 SmallVector<Type> convResTypes;
2017 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2019 rewriter.replaceOpWithNewOp<func::CallOp>(
2020 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
2025struct UnrealizedConversionCastConversion
2027 using OpConversionPattern::OpConversionPattern;
2030 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
2031 ConversionPatternRewriter &rewriter)
const override {
2032 SmallVector<Type> convResTypes;
2033 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2038 if (convResTypes == adaptor.getOperands().getTypes()) {
2039 rewriter.replaceOp(op, adaptor.getOperands());
2043 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2044 op, convResTypes, adaptor.getOperands());
2050 using OpConversionPattern::OpConversionPattern;
2053 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
2054 ConversionPatternRewriter &rewriter)
const override {
2055 Type resultType = typeConverter->convertType(op.getResult().getType());
2059 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2060 resultType.getIntOrFloatBitWidth(), op->getLoc());
2061 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
2068 using OpConversionPattern::OpConversionPattern;
2071 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
2072 ConversionPatternRewriter &rewriter)
const override {
2073 Type resultType = typeConverter->convertType(op.getResult().getType());
2077 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2078 resultType.getIntOrFloatBitWidth(), op->getLoc());
2080 op, resultType, adaptor.getValue(), amount,
false);
2086 using OpConversionPattern::OpConversionPattern;
2089 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
2090 ConversionPatternRewriter &rewriter)
const override {
2091 Type resultType = typeConverter->convertType(op.getResult().getType());
2093 Location loc = op->getLoc();
2098 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
2099 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
2102 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
2110 using OpConversionPattern::OpConversionPattern;
2113 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
2114 ConversionPatternRewriter &rewriter)
const override {
2115 Type resultType = typeConverter->convertType(op.getResult().getType());
2119 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
2120 op, resultType, adaptor.getLhs(), adaptor.getRhs());
2126 using OpConversionPattern::OpConversionPattern;
2129 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
2130 ConversionPatternRewriter &rewriter)
const override {
2131 Type resultType = typeConverter->convertType(op.getResult().getType());
2135 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2136 resultType.getIntOrFloatBitWidth(), op->getLoc());
2138 op, resultType, adaptor.getValue(), amount,
false);
2144 using OpConversionPattern::OpConversionPattern;
2147 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
2148 ConversionPatternRewriter &rewriter)
const override {
2149 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
2154struct AssignedVariableOpConversion
2156 using OpConversionPattern::OpConversionPattern;
2159 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
2160 ConversionPatternRewriter &rewriter)
const override {
2161 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
2162 adaptor.getNameAttr());
2168static llhd::TimeAttr
2169getBlockingOrContinuousAssignDelay(mlir::MLIRContext *
context) {
2170 return llhd::TimeAttr::get(
context, 0U,
"ns", 0, 1);
2173template <
typename OpTy>
2176 using OpAdaptor =
typename OpTy::Adaptor;
2179 matchAndRewrite(OpTy op, OpAdaptor adaptor,
2180 ConversionPatternRewriter &rewriter)
const override {
2183 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
2184 std::is_same_v<OpTy, BlockingAssignOp>) {
2185 delay = llhd::ConstantTimeOp::create(
2186 rewriter, op->getLoc(),
2187 getBlockingOrContinuousAssignDelay(op->getContext()));
2188 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
2190 delay = llhd::ConstantTimeOp::create(
2191 rewriter, op->getLoc(),
2192 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
2195 delay = adaptor.getDelay();
2198 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
2199 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
2205 using OpConversionPattern::OpConversionPattern;
2208 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
2209 ConversionPatternRewriter &rewriter)
const override {
2214 auto type = typeConverter->convertType(op.getType());
2216 auto hasNoWriteEffect = [](Region ®ion) {
2217 auto result = region.walk([](Operation *operation) {
2218 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
2219 if (!memOp.hasEffect<MemoryEffects::Write>() &&
2220 !memOp.hasEffect<MemoryEffects::Free>())
2221 return WalkResult::advance();
2223 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
2224 return WalkResult::advance();
2226 return WalkResult::interrupt();
2228 return !result.wasInterrupted();
2231 if (hasNoWriteEffect(op.getTrueRegion()) &&
2232 hasNoWriteEffect(op.getFalseRegion())) {
2233 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
2234 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
2236 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
2237 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
2239 Value convTrueVal = typeConverter->materializeTargetConversion(
2240 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
2241 Value convFalseVal = typeConverter->materializeTargetConversion(
2242 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
2244 rewriter.eraseOp(trueTerm);
2245 rewriter.eraseOp(falseTerm);
2247 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
2248 convTrueVal, convFalseVal);
2253 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
2254 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
2255 ifOp.getThenRegion().end());
2256 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
2257 ifOp.getElseRegion().end());
2258 rewriter.replaceOp(op, ifOp);
2264 using OpConversionPattern::OpConversionPattern;
2267 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
2268 ConversionPatternRewriter &rewriter)
const override {
2269 if (isa<llhd::GlobalSignalOp>(op->getParentOp()))
2270 rewriter.replaceOpWithNewOp<llhd::YieldOp>(op, adaptor.getResult());
2272 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
2277template <
typename SourceOp>
2280 using OpAdaptor =
typename SourceOp::Adaptor;
2283 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2284 ConversionPatternRewriter &rewriter)
const override {
2285 rewriter.modifyOpInPlace(op,
2286 [&]() { op->setOperands(adaptor.getOperands()); });
2291template <
typename MooreOpTy,
typename VerifOpTy>
2294 using OpAdaptor =
typename MooreOpTy::Adaptor;
2297 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
2298 ConversionPatternRewriter &rewriter)
const override {
2300 op.getLabel().has_value()
2301 ? StringAttr::get(op->getContext(), op.getLabel().value())
2302 : StringAttr::
get(op->getContext());
2303 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
2314 using OpConversionPattern::OpConversionPattern;
2317 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2318 ConversionPatternRewriter &rewriter)
const override {
2319 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2325 using OpConversionPattern::OpConversionPattern;
2328 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2329 ConversionPatternRewriter &rewriter)
const override {
2330 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2331 adaptor.getInputs());
2336struct FormatHierPathOpConversion
2338 using OpConversionPattern::OpConversionPattern;
2341 matchAndRewrite(FormatHierPathOp op, OpAdaptor adaptor,
2342 ConversionPatternRewriter &rewriter)
const override {
2343 rewriter.replaceOpWithNewOp<sim::FormatHierPathOp>(op,
2344 adaptor.getUseEscapes());
2350 using OpConversionPattern::OpConversionPattern;
2353 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2354 ConversionPatternRewriter &rewriter)
const override {
2356 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2357 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2358 auto widthAttr = adaptor.getSpecifierWidthAttr();
2360 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2361 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2363 switch (op.getFormat()) {
2364 case IntFormat::Decimal:
2365 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2366 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2367 adaptor.getIsSignedAttr());
2369 case IntFormat::Binary:
2370 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2371 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2373 case IntFormat::Octal:
2374 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2375 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2377 case IntFormat::HexLower:
2378 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2379 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2380 isLeftAlignedAttr, padCharAttr, widthAttr);
2382 case IntFormat::HexUpper:
2383 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2384 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2385 padCharAttr, widthAttr);
2388 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2393 using OpConversionPattern::OpConversionPattern;
2396 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2397 ConversionPatternRewriter &rewriter)
const override {
2398 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2400 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2401 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2402 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2404 switch (op.getFormat()) {
2405 case RealFormat::General:
2406 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2407 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2410 case RealFormat::Float:
2411 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2412 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2415 case RealFormat::Exponential:
2416 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2417 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2425 using OpConversionPattern::OpConversionPattern;
2428 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2429 ConversionPatternRewriter &rewriter)
const override {
2430 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2436 using OpConversionPattern::OpConversionPattern;
2439 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2440 ConversionPatternRewriter &rewriter)
const override {
2441 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2447 using OpConversionPattern::OpConversionPattern;
2450 matchAndRewrite(StringGetOp op, OpAdaptor adaptor,
2451 ConversionPatternRewriter &rewriter)
const override {
2452 rewriter.replaceOpWithNewOp<sim::StringGetOp>(op, adaptor.getStr(),
2453 adaptor.getIndex());
2459 using OpConversionPattern::OpConversionPattern;
2462 matchAndRewrite(QueueSizeBIOp op, OpAdaptor adaptor,
2463 ConversionPatternRewriter &rewriter)
const override {
2464 rewriter.replaceOpWithNewOp<sim::QueueSizeOp>(op, adaptor.getQueue());
2469struct DynQueueExtractOpConversion
2471 using OpConversionPattern::OpConversionPattern;
2474 matchAndRewrite(DynQueueExtractOp op, OpAdaptor adaptor,
2475 ConversionPatternRewriter &rewriter)
const override {
2476 bool isSingleElementExtract =
2477 op.getInput().getType().getElementType() == op.getResult().getType();
2479 if (isSingleElementExtract) {
2480 rewriter.replaceOpWithNewOp<sim::QueueGetOp>(op, adaptor.getInput(),
2481 adaptor.getLowerIdx());
2483 rewriter.replaceOpWithNewOp<sim::QueueSliceOp>(
2484 op, adaptor.getInput(), adaptor.getLowerIdx(), adaptor.getUpperIdx());
2500probeRefAndDriveWithResult(OpBuilder &builder, Location loc, Value ref,
2501 const std::function<Value(Value)> &func) {
2503 Value v = llhd::ProbeOp::create(builder, loc, ref);
2506 Value delay = llhd::ConstantTimeOp::create(
2507 builder, loc, getBlockingOrContinuousAssignDelay(builder.getContext()));
2509 llhd::DriveOp::create(builder, loc, ref, func(v), delay, Value{});
2513 using OpConversionPattern::OpConversionPattern;
2516 matchAndRewrite(QueuePushBackOp op, OpAdaptor adaptor,
2517 ConversionPatternRewriter &rewriter)
const override {
2518 probeRefAndDriveWithResult(
2519 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2520 return sim::QueuePushBackOp::create(rewriter, op->getLoc(), queue,
2521 adaptor.getElement());
2524 rewriter.eraseOp(op);
2529struct QueuePushFrontOpConversion
2531 using OpConversionPattern::OpConversionPattern;
2534 matchAndRewrite(QueuePushFrontOp op, OpAdaptor adaptor,
2535 ConversionPatternRewriter &rewriter)
const override {
2537 probeRefAndDriveWithResult(
2538 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2539 return sim::QueuePushFrontOp::create(rewriter, op->getLoc(), queue,
2540 adaptor.getElement());
2543 rewriter.eraseOp(op);
2549 using OpConversionPattern::OpConversionPattern;
2552 matchAndRewrite(QueuePopBackOp op, OpAdaptor adaptor,
2553 ConversionPatternRewriter &rewriter)
const override {
2555 probeRefAndDriveWithResult(
2556 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2558 sim::QueuePopBackOp::create(rewriter, op->getLoc(), queue);
2559 popped = popBack.getPopped();
2560 return popBack.getOutQueue();
2562 rewriter.replaceOp(op, popped);
2569 using OpConversionPattern::OpConversionPattern;
2572 matchAndRewrite(QueuePopFrontOp op, OpAdaptor adaptor,
2573 ConversionPatternRewriter &rewriter)
const override {
2575 probeRefAndDriveWithResult(
2576 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2578 sim::QueuePopFrontOp::create(rewriter, op->getLoc(), queue);
2579 popped = popFront.getPopped();
2580 return popFront.getOutQueue();
2582 rewriter.replaceOp(op, popped);
2589 using OpConversionPattern::OpConversionPattern;
2592 matchAndRewrite(QueueClearOp op, OpAdaptor adaptor,
2593 ConversionPatternRewriter &rewriter)
const override {
2594 auto refType = cast<llhd::RefType>(adaptor.getQueue().getType());
2595 auto queueType = refType.getNestedType();
2597 sim::QueueEmptyOp::create(rewriter, op->getLoc(), queueType);
2600 Value delay = llhd::ConstantTimeOp::create(
2601 rewriter, op.getLoc(),
2602 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
2604 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getQueue(), emptyQueue,
2607 rewriter.eraseOp(op);
2613 using OpConversionPattern::OpConversionPattern;
2616 matchAndRewrite(QueueInsertOp op, OpAdaptor adaptor,
2617 ConversionPatternRewriter &rewriter)
const override {
2618 probeRefAndDriveWithResult(
2619 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2621 sim::QueueInsertOp::create(rewriter, op->getLoc(), queue,
2622 adaptor.getIndex(), adaptor.getItem());
2624 return insert.getOutQueue();
2626 rewriter.eraseOp(op);
2633 using OpConversionPattern::OpConversionPattern;
2636 matchAndRewrite(QueueDeleteOp op, OpAdaptor adaptor,
2637 ConversionPatternRewriter &rewriter)
const override {
2638 probeRefAndDriveWithResult(
2639 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2640 auto delOp = sim::QueueDeleteOp::create(rewriter, op->getLoc(), queue,
2641 adaptor.getIndex());
2643 return delOp.getOutQueue();
2645 rewriter.eraseOp(op);
2652 using OpConversionPattern::OpConversionPattern;
2655 matchAndRewrite(QueueResizeOp op, OpAdaptor adaptor,
2656 ConversionPatternRewriter &rewriter)
const override {
2658 rewriter.replaceOpWithNewOp<sim::QueueResizeOp>(
2659 op, getTypeConverter()->convertType(op.getResult().getType()),
2660 adaptor.getInput());
2666 using OpConversionPattern::OpConversionPattern;
2668 matchAndRewrite(QueueSetOp op, OpAdaptor adaptor,
2669 ConversionPatternRewriter &rewriter)
const override {
2670 probeRefAndDriveWithResult(
2671 rewriter, op->getLoc(), adaptor.getQueue(), [&](Value queue) {
2673 sim::QueueSetOp::create(rewriter, op.getLoc(), queue,
2674 adaptor.getIndex(), adaptor.getItem());
2675 return setOp.getOutQueue();
2677 rewriter.eraseOp(op);
2683 using OpConversionPattern::OpConversionPattern;
2686 matchAndRewrite(QueueCmpOp op, OpAdaptor adaptor,
2687 ConversionPatternRewriter &rewriter)
const override {
2695 auto unpackedPred = adaptor.getPredicateAttr().getValue();
2696 sim::QueueCmpPredicate queuePred;
2697 switch (unpackedPred) {
2698 case circt::moore::UArrayCmpPredicate::eq:
2699 queuePred = sim::QueueCmpPredicate::eq;
2701 case circt::moore::UArrayCmpPredicate::ne:
2702 queuePred = sim::QueueCmpPredicate::ne;
2706 auto cmpPred = sim::QueueCmpPredicateAttr::get(getContext(), queuePred);
2708 rewriter.replaceOpWithNewOp<sim::QueueCmpOp>(op, cmpPred, adaptor.getLhs(),
2714struct QueueFromUnpackedArrayOpConversion
2716 using OpConversionPattern::OpConversionPattern;
2719 matchAndRewrite(QueueFromUnpackedArrayOp op, OpAdaptor adaptor,
2720 ConversionPatternRewriter &rewriter)
const override {
2721 rewriter.replaceOpWithNewOp<sim::QueueFromArrayOp>(
2722 op, getTypeConverter()->convertType(op.getResult().getType()),
2723 adaptor.getInput());
2729 using OpConversionPattern::OpConversionPattern;
2732 matchAndRewrite(QueueConcatOp op, OpAdaptor adaptor,
2733 ConversionPatternRewriter &rewriter)
const override {
2734 rewriter.replaceOpWithNewOp<sim::QueueConcatOp>(
2735 op, getTypeConverter()->convertType(op.getResult().getType()),
2736 adaptor.getInputs());
2742 using OpConversionPattern::OpConversionPattern;
2745 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
2746 ConversionPatternRewriter &rewriter)
const override {
2747 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
2748 op, adaptor.getMessage());
2760static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
2761 ConversionPatternRewriter &rewriter) {
2762 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
2767static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
2768 ConversionPatternRewriter &rewriter) {
2769 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
2775static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
2776 ConversionPatternRewriter &rewriter) {
2778 std::string severityString;
2780 switch (op.getSeverity()) {
2781 case (Severity::Fatal):
2782 severityString =
"Fatal: ";
2784 case (Severity::Error):
2785 severityString =
"Error: ";
2787 case (Severity::Warning):
2788 severityString =
"Warning: ";
2790 case (Severity::Info):
2791 severityString =
"Info: ";
2796 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
2797 auto message = sim::FormatStringConcatOp::create(
2798 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
2799 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
2813 UrandomRangeBIOp::Adaptor adaptor,
2814 ConversionPatternRewriter &rewriter,
2815 FunctionCache &funcCache) {
2816 auto loc = op.getLoc();
2817 auto i32Ty = rewriter.getI32Type();
2818 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
2819 auto fn = funcCache.getOrCreate(rewriter,
"__circt_urandom_range",
2820 {i32Ty, i32Ty, ptrTy}, {i32Ty});
2823 if (
auto seedRef = adaptor.getSeed()) {
2826 seedPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, i32Ty, one);
2827 auto seedVal = llhd::ProbeOp::create(rewriter, loc, seedRef);
2828 LLVM::StoreOp::create(rewriter, loc, seedVal, seedPtr);
2830 seedPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
2833 auto call = func::CallOp::create(
2835 ValueRange{adaptor.getMinval(), adaptor.getMaxval(), seedPtr});
2838 if (adaptor.getSeed()) {
2839 auto newSeed = LLVM::LoadOp::create(rewriter, loc, i32Ty, seedPtr);
2840 auto epsilon = llhd::ConstantTimeOp::create(
2842 llhd::TimeAttr::get(rewriter.getContext(), 0,
"ns", 0, 1));
2843 llhd::DriveOp::create(rewriter, loc, adaptor.getSeed(), newSeed, epsilon,
2847 rewriter.replaceOp(op, call.getResult(0));
2853 FinishMessageBIOp::Adaptor adaptor,
2854 ConversionPatternRewriter &rewriter) {
2856 rewriter.eraseOp(op);
2865static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
2866 ConversionPatternRewriter &rewriter) {
2867 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
2872static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
2873 ConversionPatternRewriter &rewriter) {
2874 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
2879static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
2880 ConversionPatternRewriter &rewriter) {
2881 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
2890 const TypeConverter &converter) {
2891 target.addIllegalDialect<MooreDialect>();
2892 target.addLegalDialect<comb::CombDialect>();
2893 target.addLegalDialect<hw::HWDialect>();
2894 target.addLegalDialect<seq::SeqDialect>();
2895 target.addLegalDialect<llhd::LLHDDialect>();
2896 target.addLegalDialect<ltl::LTLDialect>();
2897 target.addLegalDialect<mlir::BuiltinDialect>();
2898 target.addLegalDialect<mlir::math::MathDialect>();
2899 target.addLegalDialect<sim::SimDialect>();
2900 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
2901 target.addLegalDialect<verif::VerifDialect>();
2902 target.addLegalDialect<arith::ArithDialect>();
2904 target.addLegalOp<debug::ScopeOp>();
2906 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
2907 UnrealizedConversionCastOp, hw::OutputOp,
2908 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
2910 [&](Operation *op) {
return converter.isLegal(op); });
2912 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
2913 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
2914 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
2917 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
2918 return converter.isSignatureLegal(op.getFunctionType());
2922 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
2923 converter.isLegal(&op.getBody());
2928 typeConverter.addConversion([&](IntType type) {
2929 return IntegerType::get(type.getContext(), type.getWidth());
2932 typeConverter.addConversion([&](RealType type) -> mlir::Type {
2933 MLIRContext *ctx = type.getContext();
2934 switch (type.getWidth()) {
2935 case moore::RealWidth::f32:
2936 return mlir::Float32Type::get(ctx);
2937 case moore::RealWidth::f64:
2938 return mlir::Float64Type::get(ctx);
2942 typeConverter.addConversion(
2943 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
2945 typeConverter.addConversion([&](FormatStringType type) {
2946 return sim::FormatStringType::get(type.getContext());
2949 typeConverter.addConversion([&](StringType type) {
2950 return sim::DynamicStringType::get(type.getContext());
2953 typeConverter.addConversion([&](QueueType type) {
2954 return sim::QueueType::get(type.getContext(),
2955 typeConverter.convertType(type.getElementType()),
2959 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
2960 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2961 return hw::ArrayType::get(
elementType, type.getSize());
2968 typeConverter.addConversion(
2969 [&](UnpackedArrayType type) -> std::optional<Type> {
2970 if (
auto elementType = typeConverter.convertType(type.getElementType()))
2971 return hw::ArrayType::get(
elementType, type.getSize());
2975 typeConverter.addConversion([&](OpenArrayType type) -> std::optional<Type> {
2976 return LLVM::LLVMPointerType::get(type.getContext());
2979 typeConverter.addConversion(
2980 [&](OpenUnpackedArrayType type) -> std::optional<Type> {
2981 return LLVM::LLVMPointerType::get(type.getContext());
2984 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
2985 SmallVector<hw::StructType::FieldInfo> fields;
2986 for (
auto field : type.getMembers()) {
2987 hw::StructType::FieldInfo info;
2988 info.type = typeConverter.convertType(field.type);
2991 info.name = field.name;
2992 fields.push_back(info);
2994 return hw::StructType::get(type.getContext(), fields);
3002 typeConverter.addConversion(
3003 [&](UnpackedStructType type) -> std::optional<Type> {
3004 SmallVector<hw::StructType::FieldInfo> fields;
3005 for (
auto field : type.getMembers()) {
3006 hw::StructType::FieldInfo info;
3007 info.type = typeConverter.convertType(field.type);
3010 info.name = field.name;
3011 fields.push_back(info);
3013 return hw::StructType::get(type.getContext(), fields);
3017 typeConverter.addConversion([&](UnionType type) -> std::optional<Type> {
3018 SmallVector<hw::UnionType::FieldInfo> fields;
3019 for (
auto field : type.getMembers()) {
3020 hw::UnionType::FieldInfo info;
3021 info.type = typeConverter.convertType(field.type);
3024 info.name = field.name;
3026 fields.push_back(info);
3028 auto result = hw::UnionType::get(type.getContext(), fields);
3033 typeConverter.addConversion(
3034 [&](UnpackedUnionType type) -> std::optional<Type> {
3035 SmallVector<hw::UnionType::FieldInfo> fields;
3036 for (
auto field : type.getMembers()) {
3037 hw::UnionType::FieldInfo info;
3038 info.type = typeConverter.convertType(field.type);
3041 info.name = field.name;
3043 fields.push_back(info);
3045 return hw::UnionType::get(type.getContext(), fields);
3049 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
3050 return LLVM::LLVMPointerType::get(type.getContext());
3054 typeConverter.addConversion(
3055 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
3058 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
3059 return LLVM::LLVMPointerType::get(type.getContext());
3062 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
3063 if (isa<OpenArrayType, OpenUnpackedArrayType>(type.getNestedType()))
3064 return LLVM::LLVMPointerType::get(type.getContext());
3065 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3066 return llhd::RefType::get(innerType);
3071 typeConverter.addConversion([](IntegerType type) {
return type; });
3072 typeConverter.addConversion([](FloatType type) {
return type; });
3073 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
3074 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
3075 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
3076 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
3077 typeConverter.addConversion([](debug::StructType type) {
return type; });
3079 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
3080 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3081 return llhd::RefType::get(innerType);
3085 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
3086 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3087 return hw::ArrayType::get(
elementType, type.getNumElements());
3091 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
3092 SmallVector<hw::StructType::FieldInfo> fields;
3093 for (
auto field : type.getElements()) {
3094 hw::StructType::FieldInfo info;
3095 info.type = typeConverter.convertType(field.type);
3098 info.name = field.name;
3099 fields.push_back(info);
3101 return hw::StructType::get(type.getContext(), fields);
3104 typeConverter.addConversion([&](hw::UnionType type) -> std::optional<Type> {
3105 SmallVector<hw::UnionType::FieldInfo> fields;
3106 for (
auto field : type.getElements()) {
3107 hw::UnionType::FieldInfo info;
3108 info.type = typeConverter.convertType(field.type);
3111 info.name = field.name;
3112 info.offset = field.offset;
3113 fields.push_back(info);
3115 return hw::UnionType::get(type.getContext(), fields);
3118 typeConverter.addTargetMaterialization(
3119 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3120 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3121 if (inputs.size() != 1 || !inputs[0])
3123 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3128 typeConverter.addSourceMaterialization(
3129 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3130 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3131 if (inputs.size() != 1)
3133 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3140 TypeConverter &typeConverter,
3141 ClassTypeCache &classCache,
3142 FunctionCache &funcCache) {
3147 classCache, funcCache);
3148 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
3149 patterns.getContext(), classCache);
3153 ClassUpcastOpConversion,
3155 VariableOpConversion,
3159 ConversionOpConversion,
3160 BitcastConversion<PackedToSBVOp>,
3161 BitcastConversion<SBVToPackedOp>,
3162 NoOpConversion<LogicToIntOp>,
3163 NoOpConversion<IntToLogicOp>,
3164 NoOpConversion<ToBuiltinIntOp>,
3165 NoOpConversion<FromBuiltinIntOp>,
3169 SIntToRealOpConversion,
3170 UIntToRealOpConversion,
3171 IntToStringOpConversion,
3172 RealToIntOpConversion,
3173 ConvertRealOpConversion,
3179 ReplicateOpConversion,
3181 ExtractOpConversion,
3182 DynExtractOpConversion,
3183 DynExtractRefOpConversion,
3185 StructExtractOpConversion,
3186 StructExtractRefOpConversion,
3187 ExtractRefOpConversion,
3188 StructCreateOpConversion,
3189 UnionCreateOpConversion,
3190 UnionExtractOpConversion,
3191 UnionExtractRefOpConversion,
3192 ConditionalOpConversion,
3193 ArrayCreateOpConversion,
3196 ConstantStringOpConv,
3199 ReduceAndOpConversion,
3200 ReduceOrOpConversion,
3201 ReduceXorOpConversion,
3202 BoolCastOpConversion,
3207 BinaryOpConversion<AddOp, comb::AddOp>,
3208 BinaryOpConversion<SubOp, comb::SubOp>,
3209 BinaryOpConversion<MulOp, comb::MulOp>,
3210 BinaryOpConversion<DivUOp, comb::DivUOp>,
3211 BinaryOpConversion<DivSOp, comb::DivSOp>,
3212 BinaryOpConversion<ModUOp, comb::ModUOp>,
3213 BinaryOpConversion<ModSOp, comb::ModSOp>,
3214 BinaryOpConversion<AndOp, comb::AndOp>,
3215 BinaryOpConversion<OrOp, comb::OrOp>,
3216 BinaryOpConversion<XorOp, comb::XorOp>,
3219 NegRealOpConversion,
3222 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
3223 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
3224 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
3225 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
3226 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
3229 PowUOpConversion, PowSOpConversion,
3232 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
3233 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
3234 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
3235 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
3236 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
3237 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
3238 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
3239 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
3240 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
3241 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
3242 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
3243 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
3244 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
3245 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
3246 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::ONE>,
3247 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
3248 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
3249 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
3250 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
3251 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
3252 CaseXZEqOpConversion<CaseZEqOp, true>,
3253 CaseXZEqOpConversion<CaseXZEqOp, false>,
3256 SVModuleOpConversion,
3257 InstanceOpConversion,
3258 ProcedureOpConversion,
3259 CoroutineOpConversion,
3260 CallCoroutineOpConversion,
3261 WaitEventOpConversion,
3269 AssignOpConversion<ContinuousAssignOp>,
3270 AssignOpConversion<DelayedContinuousAssignOp>,
3271 AssignOpConversion<BlockingAssignOp>,
3272 AssignOpConversion<NonBlockingAssignOp>,
3273 AssignOpConversion<DelayedNonBlockingAssignOp>,
3274 AssignedVariableOpConversion,
3277 HWInstanceOpConversion,
3280 UnrealizedConversionCastConversion,
3281 InPlaceOpConversion<debug::ArrayOp>,
3282 InPlaceOpConversion<debug::StructOp>,
3283 InPlaceOpConversion<debug::VariableOp>,
3286 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
3287 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
3288 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
3291 FormatLiteralOpConversion,
3292 FormatConcatOpConversion,
3293 FormatHierPathOpConversion,
3294 FormatIntOpConversion,
3295 FormatRealOpConversion,
3296 DisplayBIOpConversion,
3299 StringLenOpConversion,
3300 StringConcatOpConversion,
3301 StringGetOpConversion,
3304 QueueSizeBIOpConversion,
3305 QueuePushBackOpConversion,
3306 QueuePushFrontOpConversion,
3307 QueuePopBackOpConversion,
3308 QueuePopFrontOpConversion,
3309 QueueDeleteOpConversion,
3310 QueueInsertOpConversion,
3311 QueueClearOpConversion,
3312 DynQueueExtractOpConversion,
3313 QueueResizeOpConversion,
3314 QueueSetOpConversion,
3315 QueueCmpOpConversion,
3316 QueueFromUnpackedArrayOpConversion,
3317 QueueConcatOpConversion
3318 >(typeConverter,
patterns.getContext());
3341 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
3343 hw::populateHWModuleLikeTypeConversionPattern(
3344 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
3345 populateSCFToControlFlowConversionPatterns(
patterns);
3354struct MooreToCorePass
3355 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
3356 void runOnOperation()
override;
3362 return std::make_unique<MooreToCorePass>();
3366void MooreToCorePass::runOnOperation() {
3367 MLIRContext &
context = getContext();
3368 ModuleOp
module = getOperation();
3369 ClassTypeCache classCache;
3370 auto &symbolTable = getAnalysis<SymbolTable>();
3371 FunctionCache funcCache(symbolTable);
3373 IRRewriter rewriter(module);
3374 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
3376 TypeConverter typeConverter;
3379 ConversionTarget target(
context);
3384 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
3387 if (failed(applyFullConversion(module, target, std::move(
patterns))))
3388 signalPassFailure();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static FIRRTLBaseType convertType(FIRRTLBaseType type)
Returns null type if no conversion is needed.
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 populateOpConversion(ConversionPatternSet &patterns, TypeConverter &typeConverter, ClassTypeCache &classCache, FunctionCache &funcCache)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
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.