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/Dialect/UB/IR/UBOps.h"
31#include "mlir/IR/BuiltinDialect.h"
32#include "mlir/IR/Iterators.h"
33#include "mlir/Interfaces/SideEffectInterfaces.h"
34#include "mlir/Pass/Pass.h"
35#include "mlir/Transforms/DialectConversion.h"
36#include "mlir/Transforms/RegionUtils.h"
37#include "llvm/ADT/TypeSwitch.h"
38#include "llvm/IR/DerivedTypes.h"
41#define GEN_PASS_DEF_CONVERTMOORETOCORE
42#include "circt/Conversion/Passes.h.inc"
49using comb::ICmpPredicate;
50using llvm::SmallDenseSet;
55struct ClassTypeCache {
57 LLVM::GlobalOp global;
60 struct ClassStructInfo {
61 LLVM::LLVMStructType classBody;
62 LLVM::LLVMStructType headerTy;
63 TypeInfoInfo typeInfo;
65 unsigned headerFieldIndex = 0;
66 unsigned typeInfoFieldIndex = 0;
67 unsigned vtableFieldIndex = 1;
70 DenseMap<StringRef, SmallVector<unsigned, 2>> propertyPath;
74 void setFieldPath(StringRef propertyName, ArrayRef<unsigned> path) {
75 this->propertyPath[propertyName] =
76 SmallVector<unsigned, 2>(path.begin(), path.end());
80 std::optional<ArrayRef<unsigned>>
81 getFieldPath(StringRef propertySym)
const {
82 if (
auto prop = this->propertyPath.find(propertySym);
83 prop != this->propertyPath.end())
84 return ArrayRef<unsigned>(prop->second);
91 void setClassInfo(SymbolRefAttr classSym,
const ClassStructInfo &
info) {
92 auto &dst = classToStructMap[classSym];
97 std::optional<ClassStructInfo> getStructInfo(SymbolRefAttr classSym)
const {
98 if (
auto it = classToStructMap.find(classSym); it != classToStructMap.end())
103 std::optional<TypeInfoInfo> getTypeInfo(SymbolRefAttr classSym)
const {
104 if (
auto it = classToTypeInfoMap.find(classSym);
105 it != classToTypeInfoMap.end())
110 void setTypeInfo(SymbolRefAttr classSym,
const TypeInfoInfo &
info) {
111 classToTypeInfoMap[classSym] =
info;
118 DenseMap<Attribute, ClassStructInfo> classToStructMap;
119 DenseMap<Attribute, TypeInfoInfo> classToTypeInfoMap;
124struct FunctionCache {
125 FunctionCache(SymbolTable &symbolTable) : symbolTable(symbolTable) {}
131 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
132 function_ref<func::FuncOp()> createFn) {
133 auto &slot = map[name];
136 if (
auto fn = symbolTable.lookup<func::FuncOp>(name))
138 auto mod = cast<ModuleOp>(symbolTable.getOp());
139 OpBuilder::InsertionGuard g(builder);
140 builder.setInsertionPointToStart(mod.getBody());
142 symbolTable.insert(slot);
148 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
149 TypeRange argTypes, TypeRange resultTypes) {
150 return getOrCreate(builder, name, [&] {
151 auto mod = cast<ModuleOp>(symbolTable.getOp());
152 auto fnTy = builder.getFunctionType(argTypes, resultTypes);
153 auto fn = func::FuncOp::create(builder, mod.getLoc(), name, fnTy);
160 SymbolTable &symbolTable;
161 llvm::StringMap<func::FuncOp> map;
166static LLVM::LLVMStructType getOrCreateOpaqueStruct(MLIRContext *ctx,
167 SymbolRefAttr className) {
168 return LLVM::LLVMStructType::getIdentified(ctx, className.getRootReference());
172static LLVM::LLVMStructType getClassObjectHeaderType(MLIRContext *ctx) {
173 return LLVM::LLVMStructType::getLiteral(
174 ctx, SmallVector<Type>{LLVM::LLVMPointerType::get(ctx),
175 LLVM::LLVMPointerType::get(ctx)});
178static std::string getTypeInfoName(SymbolRefAttr className) {
179 return className.getRootReference().str() +
"::typeinfo";
182static FailureOr<ClassTypeCache::TypeInfoInfo>
183getOrCreateTypeInfo(ModuleOp mod, SymbolRefAttr classSym,
184 ClassTypeCache &cache) {
185 if (
auto info = cache.getTypeInfo(classSym))
188 MLIRContext *ctx = mod.getContext();
189 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
190 auto typeInfoTy = LLVM::LLVMStructType::getLiteral(ctx, {ptrTy});
192 auto globalName = getTypeInfoName(classSym);
193 auto global = mod.lookupSymbol<LLVM::GlobalOp>(globalName);
195 OpBuilder builder = OpBuilder::atBlockBegin(mod.getBody());
196 global = LLVM::GlobalOp::create(
197 builder, mod.getLoc(), typeInfoTy,
198 true, LLVM::Linkage::Internal, globalName, Attribute());
201 global.getInitializerRegion().push_back(block);
202 builder.setInsertionPointToStart(block);
204 if (
auto *classOp = mod.lookupSymbol(classSym)) {
205 auto classDecl = dyn_cast<ClassDeclOp>(classOp);
206 if (classDecl && classDecl.getBaseAttr()) {
208 getOrCreateTypeInfo(mod, classDecl.getBaseAttr(), cache);
209 if (failed(baseInfo))
212 LLVM::AddressOfOp::create(builder, mod.getLoc(), baseInfo->global);
213 auto undef = LLVM::UndefOp::create(builder, mod.getLoc(), typeInfoTy)
215 auto init = LLVM::InsertValueOp::create(builder, mod.getLoc(), undef,
216 baseAddr.getResult(),
217 ArrayRef<int64_t>{0});
218 LLVM::ReturnOp::create(builder, mod.getLoc(), init);
219 ClassTypeCache::TypeInfoInfo
info{global};
220 cache.setTypeInfo(classSym, info);
226 LLVM::UndefOp::create(builder, mod.getLoc(), typeInfoTy).getResult();
228 LLVM::ZeroOp::create(builder, mod.getLoc(), ptrTy).getResult();
229 auto init = LLVM::InsertValueOp::create(builder, mod.getLoc(), undef,
230 nullPtr, ArrayRef<int64_t>{0});
231 LLVM::ReturnOp::create(builder, mod.getLoc(), init);
234 ClassTypeCache::TypeInfoInfo
info{global};
235 cache.setTypeInfo(classSym, info);
238static LogicalResult resolveClassStructBody(ClassDeclOp op,
239 TypeConverter
const &typeConverter,
240 ClassTypeCache &cache) {
242 auto classSym = SymbolRefAttr::get(op.getSymNameAttr());
243 auto structInfo = cache.getStructInfo(classSym);
248 if (failed(getOrCreateTypeInfo(op->getParentOfType<ModuleOp>(), classSym,
250 return op.emitOpError() <<
"Failed to create RTTI for class";
253 ClassTypeCache::ClassStructInfo structBody;
254 SmallVector<Type> structBodyMembers;
255 structBody.headerTy = getClassObjectHeaderType(op.getContext());
256 structBody.typeInfo = *cache.getTypeInfo(classSym);
257 structBodyMembers.push_back(structBody.headerTy);
260 unsigned derivedStartIdx = 1;
262 if (
auto baseClass = op.getBaseAttr()) {
264 ModuleOp mod = op->getParentOfType<ModuleOp>();
265 auto *opSym = mod.lookupSymbol(baseClass);
266 auto classDeclOp = cast<ClassDeclOp>(opSym);
268 if (failed(resolveClassStructBody(classDeclOp, typeConverter, cache)))
272 auto baseClassStruct = cache.getStructInfo(baseClass);
273 structBodyMembers.push_back(baseClassStruct->classBody);
278 for (
auto &kv : baseClassStruct->propertyPath) {
279 SmallVector<unsigned, 2> path;
281 path.append(kv.second.begin(), kv.second.end());
282 structBody.setFieldPath(kv.first, path);
287 unsigned iterator = derivedStartIdx;
288 auto &block = op.getBody().front();
289 for (Operation &child : block) {
290 if (
auto prop = dyn_cast<ClassPropertyDeclOp>(child)) {
291 Type mooreTy = prop.getPropertyType();
292 Type llvmTy = typeConverter.convertType(mooreTy);
294 return prop.emitOpError()
295 <<
"failed to convert property type " << mooreTy;
297 structBodyMembers.push_back(llvmTy);
300 SmallVector<unsigned, 2> path{iterator};
301 structBody.setFieldPath(prop.getSymName(), path);
307 auto llvmStructTy = getOrCreateOpaqueStruct(op.getContext(), classSym);
309 if (!structBodyMembers.empty() &&
310 failed(llvmStructTy.setBody(structBodyMembers,
false)))
311 return op.emitOpError() <<
"Failed to set LLVM Struct body";
313 structBody.classBody = llvmStructTy;
314 cache.setClassInfo(classSym, structBody);
320static LogicalResult resolveClassStructBody(ModuleOp mod, SymbolRefAttr op,
321 TypeConverter
const &typeConverter,
322 ClassTypeCache &cache) {
323 auto classDeclOp = cast<ClassDeclOp>(*mod.lookupSymbol(op));
324 return resolveClassStructBody(classDeclOp, typeConverter, cache);
331static Value adjustIntegerWidth(OpBuilder &builder, Value value,
332 uint32_t targetWidth, Location loc) {
333 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
334 if (intWidth == targetWidth)
337 if (intWidth < targetWidth) {
339 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
340 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
344 intWidth - targetWidth);
346 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
347 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
351 builder.getIntegerType(targetWidth), -1);
352 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
356static FailureOr<hw::ModulePortInfo>
357getModulePortInfo(
const TypeConverter &typeConverter, SVModuleOp op) {
359 size_t resultNum = 0;
360 auto moduleTy = op.getModuleType();
361 SmallVector<hw::PortInfo> ports;
362 ports.reserve(moduleTy.getNumPorts());
364 for (
auto port : moduleTy.getPorts()) {
365 Type portTy = typeConverter.convertType(port.type);
367 return op.emitOpError(
"port '")
368 << port.name <<
"' has unsupported type " << port.type
369 <<
" that cannot be converted to hardware type";
371 if (port.dir == hw::ModulePort::Direction::Output) {
373 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
381 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
387struct DpiArrayCastInfo {
390 bool isPacked =
false;
394static std::optional<DpiArrayCastInfo> getDpiArrayCastInfo(Type type) {
395 DpiArrayCastInfo
info;
396 if (
auto refType = dyn_cast<RefType>(type)) {
398 type = refType.getNestedType();
401 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
402 info.isPacked =
true;
403 info.elementType = arrayType.getElementType();
406 if (
auto arrayType = dyn_cast<OpenArrayType>(type)) {
408 info.isPacked =
true;
409 info.elementType = arrayType.getElementType();
412 if (
auto arrayType = dyn_cast<UnpackedArrayType>(type)) {
413 info.elementType = arrayType.getElementType();
416 if (
auto arrayType = dyn_cast<OpenUnpackedArrayType>(type)) {
418 info.elementType = arrayType.getElementType();
424static bool hasOpenArrayBoundaryType(Type type) {
425 if (isa<OpenArrayType, OpenUnpackedArrayType>(type))
427 if (
auto refType = dyn_cast<RefType>(type))
428 return isa<OpenArrayType, OpenUnpackedArrayType>(refType.getNestedType());
432static bool isSupportedDpiOpenArrayCast(Type source, Type target) {
433 auto sourceInfo = getDpiArrayCastInfo(source);
434 auto targetInfo = getDpiArrayCastInfo(target);
435 if (!sourceInfo || !targetInfo)
440 return sourceInfo->isRef == targetInfo->isRef &&
441 sourceInfo->isPacked == targetInfo->isPacked &&
442 sourceInfo->elementType == targetInfo->elementType &&
443 (targetInfo->isOpen && !sourceInfo->isOpen);
451 using OpConversionPattern::OpConversionPattern;
454 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
455 ConversionPatternRewriter &rewriter)
const override {
456 rewriter.setInsertionPoint(op);
459 auto portInfo = getModulePortInfo(*typeConverter, op);
460 if (failed(portInfo))
463 auto hwModuleOp = hw::HWModuleOp::create(rewriter, op.getLoc(),
464 op.getSymNameAttr(), *portInfo);
467 SymbolTable::setSymbolVisibility(hwModuleOp,
468 SymbolTable::getSymbolVisibility(op));
469 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
471 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
473 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
474 hwModuleOp.getBodyRegion().end());
477 rewriter.eraseOp(op);
483 using OpConversionPattern::OpConversionPattern;
486 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
487 ConversionPatternRewriter &rewriter)
const override {
488 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
494 using OpConversionPattern::OpConversionPattern;
497 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
498 ConversionPatternRewriter &rewriter)
const override {
499 auto instName = op.getInstanceNameAttr();
500 auto moduleName = op.getModuleNameAttr();
503 rewriter.setInsertionPoint(op);
504 auto instOp = hw::InstanceOp::create(
505 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
506 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
507 rewriter.getArrayAttr({}),
nullptr,
511 op.replaceAllUsesWith(instOp.getResults());
512 rewriter.eraseOp(op);
517static void getValuesToObserve(Region *region,
518 function_ref<
void(Value)> setInsertionPoint,
519 const TypeConverter *typeConverter,
520 ConversionPatternRewriter &rewriter,
521 SmallVector<Value> &observeValues) {
522 SmallDenseSet<Value> alreadyObserved;
523 Location loc = region->getLoc();
525 auto probeIfSignal = [&](Value value) -> Value {
526 Type type = value.getType();
527 if (
auto refType = dyn_cast<llhd::RefType>(type)) {
528 if (!hw::isHWValueType(refType.getNestedType()))
530 return llhd::ProbeOp::create(rewriter, loc, value);
532 if (!hw::isHWValueType(type))
537 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
538 [&](Operation *operation) {
539 for (
auto value : operation->getOperands()) {
540 if (isa<BlockArgument>(value))
541 value = rewriter.getRemappedValue(value);
543 if (region->isAncestor(value.getParentRegion()))
545 if (
auto *defOp = value.getDefiningOp();
546 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
548 if (!alreadyObserved.insert(value).second)
551 OpBuilder::InsertionGuard g(rewriter);
552 if (
auto remapped = rewriter.getRemappedValue(value)) {
553 setInsertionPoint(remapped);
554 if (
auto observed = probeIfSignal(remapped))
555 observeValues.push_back(observed);
557 setInsertionPoint(value);
558 auto type = typeConverter->convertType(value.getType());
559 auto converted = typeConverter->materializeTargetConversion(
560 rewriter, loc, type, value);
561 if (
auto observed = probeIfSignal(converted))
562 observeValues.push_back(observed);
569 using OpConversionPattern::OpConversionPattern;
572 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
573 ConversionPatternRewriter &rewriter)
const override {
575 SmallVector<Value> observedValues;
576 if (op.getKind() == ProcedureKind::AlwaysComb ||
577 op.getKind() == ProcedureKind::AlwaysLatch) {
578 auto setInsertionPoint = [&](Value value) {
579 rewriter.setInsertionPoint(op);
581 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
582 rewriter, observedValues);
585 auto loc = op.getLoc();
586 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
591 if (op.getKind() == ProcedureKind::Initial ||
592 op.getKind() == ProcedureKind::Final) {
594 if (op.getKind() == ProcedureKind::Initial)
595 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
597 newOp = llhd::FinalOp::create(rewriter, loc);
598 auto &body = newOp->getRegion(0);
599 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
601 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
602 rewriter.setInsertionPoint(returnOp);
603 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
605 rewriter.eraseOp(op);
610 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
615 rewriter.createBlock(&newOp.getBody());
616 auto *block = &op.getBody().front();
617 cf::BranchOp::create(rewriter, loc, block);
618 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
619 newOp.getBody().end());
627 if (op.getKind() == ProcedureKind::AlwaysComb ||
628 op.getKind() == ProcedureKind::AlwaysLatch) {
629 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
630 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
631 ValueRange{}, block);
638 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
639 rewriter.setInsertionPoint(returnOp);
640 cf::BranchOp::create(rewriter, loc, block);
641 rewriter.eraseOp(returnOp);
644 rewriter.eraseOp(op);
654 using OpConversionPattern::OpConversionPattern;
657 matchAndRewrite(CoroutineOp op, OpAdaptor adaptor,
658 ConversionPatternRewriter &rewriter)
const override {
659 auto funcType = op.getFunctionType();
660 TypeConverter::SignatureConversion sigConversion(funcType.getNumInputs());
661 for (
auto [i, type] :
llvm::enumerate(funcType.getInputs())) {
662 auto converted = typeConverter->convertType(type);
665 sigConversion.addInputs(i, converted);
667 SmallVector<Type> resultTypes;
668 if (failed(typeConverter->convertTypes(funcType.getResults(), resultTypes)))
671 auto newFuncType = FunctionType::get(
672 rewriter.getContext(), sigConversion.getConvertedTypes(), resultTypes);
673 auto newOp = llhd::CoroutineOp::create(rewriter, op.getLoc(),
674 op.getSymName(), newFuncType);
675 newOp.setSymVisibilityAttr(op.getSymVisibilityAttr());
676 if (
auto dpiExport = op->getAttr(
"circt.dpi.export"))
677 newOp->setAttr(
"circt.dpi.export", dpiExport);
678 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
679 newOp.getBody().end());
680 if (failed(rewriter.convertRegionTypes(&newOp.getBody(), *typeConverter,
686 llvm::make_early_inc_range(newOp.getBody().getOps<ReturnOp>())) {
687 rewriter.setInsertionPoint(returnOp);
688 rewriter.replaceOpWithNewOp<llhd::ReturnOp>(returnOp, ValueRange{});
691 rewriter.eraseOp(op);
697 using OpConversionPattern::OpConversionPattern;
700 matchAndRewrite(CallCoroutineOp op, OpAdaptor adaptor,
701 ConversionPatternRewriter &rewriter)
const override {
702 SmallVector<Type> convResTypes;
703 if (failed(typeConverter->convertTypes(op.getResultTypes(), convResTypes)))
705 rewriter.replaceOpWithNewOp<llhd::CallCoroutineOp>(
706 op, convResTypes, adaptor.getCallee(), adaptor.getOperands());
712 using OpConversionPattern::OpConversionPattern;
715 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
716 ConversionPatternRewriter &rewriter)
const override {
750 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
756 if (op.getBody().front().empty()) {
759 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
763 auto *waitBlock = rewriter.createBlock(resumeBlock);
764 auto *checkBlock = rewriter.createBlock(resumeBlock);
766 auto loc = op.getLoc();
767 rewriter.setInsertionPoint(op);
768 cf::BranchOp::create(rewriter, loc, waitBlock);
778 SmallVector<Value> valuesBefore;
779 rewriter.setInsertionPointToEnd(waitBlock);
780 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
781 bool allDetectsAreAnyChange =
true;
783 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
784 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
785 allDetectsAreAnyChange =
false;
786 valuesBefore.push_back(detectOp.getInput());
787 rewriter.eraseOp(detectOp);
793 SmallVector<Value> observeValues;
794 auto setInsertionPointAfterDef = [&](Value value) {
795 if (
auto *op = value.getDefiningOp())
796 rewriter.setInsertionPointAfter(op);
797 if (
auto arg = dyn_cast<BlockArgument>(value))
798 rewriter.setInsertionPointToStart(value.getParentBlock());
801 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
802 typeConverter, rewriter, observeValues);
807 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
808 observeValues, ValueRange{}, checkBlock);
809 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
810 rewriter.eraseOp(clonedOp);
814 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
815 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
817 rewriter.eraseOp(op);
821 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
822 assert(before.getType() == after.getType() &&
823 "mismatched types after clone op");
824 auto beforeType = cast<IntType>(before.getType());
828 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
829 constexpr int LSB = 0;
831 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
833 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
834 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
837 auto intType = rewriter.getIntegerType(beforeType.getWidth());
838 before = typeConverter->materializeTargetConversion(rewriter, loc,
840 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
843 if (edge == Edge::AnyChange)
844 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
847 SmallVector<Value> disjuncts;
850 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
852 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
854 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
855 disjuncts.push_back(posedge);
858 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
860 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
862 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
863 disjuncts.push_back(posedge);
866 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
873 SmallVector<Value> triggers;
874 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
875 if (!allDetectsAreAnyChange) {
876 if (!isa<IntType>(before.getType()))
877 return detectOp->emitError() <<
"requires int operand";
879 rewriter.setInsertionPoint(detectOp);
881 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
882 if (detectOp.getCondition()) {
883 auto condition = typeConverter->materializeTargetConversion(
884 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
886 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
888 triggers.push_back(trigger);
891 rewriter.eraseOp(detectOp);
894 rewriter.setInsertionPointToEnd(checkBlock);
895 if (triggers.empty()) {
900 cf::BranchOp::create(rewriter, loc, resumeBlock);
906 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
907 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
916static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
917 ConversionPatternRewriter &rewriter) {
919 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
920 rewriter.setInsertionPoint(op);
921 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
922 adaptor.getDelay(), ValueRange{},
923 ValueRange{}, resumeBlock);
924 rewriter.setInsertionPointToStart(resumeBlock);
929static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
930 ConversionPatternRewriter &rewriter) {
931 rewriter.replaceOpWithNewOp<ub::UnreachableOp>(op);
940 ConversionPatternRewriter &rewriter) {
942 if (isa<mlir::LLVM::LLVMPointerType>(type))
943 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
946 if (isa<llhd::TimeType>(type)) {
948 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
949 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
953 if (
auto floatType = dyn_cast<FloatType>(type)) {
954 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
955 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
959 if (
auto strType = dyn_cast<sim::DynamicStringType>(type))
960 return sim::StringConstantOp::create(rewriter, loc, strType,
"");
963 if (
auto assocArrayType = dyn_cast<sim::AssocArrayType>(type))
964 return sim::AssocArrayEmptyOp::create(rewriter, loc, assocArrayType);
967 if (
auto queueType = dyn_cast<sim::QueueType>(type))
968 return sim::QueueEmptyOp::create(rewriter, loc, queueType);
971 if (
auto arrayType = dyn_cast<hw::ArrayType>(type)) {
972 if (hw::getBitWidth(type) == -1) {
977 SmallVector<Value> elements(arrayType.getNumElements(), zeroElement);
982 if (
auto structType = dyn_cast<hw::StructType>(type)) {
983 if (hw::getBitWidth(type) == -1) {
984 SmallVector<Value> fields;
985 for (
auto field : structType.getElements()) {
989 fields.push_back(zeroField);
996 int64_t width = hw::getBitWidth(type);
1004 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
1007struct ClassPropertyRefOpConversion
1009 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
1010 ClassTypeCache &cache)
1014 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
1015 ConversionPatternRewriter &rewriter)
const override {
1016 Location loc = op.getLoc();
1017 MLIRContext *ctx = rewriter.getContext();
1020 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
1022 Value instRef = adaptor.getInstance();
1026 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
1027 SymbolRefAttr classSym = classRefTy.getClassSym();
1028 ModuleOp mod = op->getParentOfType<ModuleOp>();
1029 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
1030 return rewriter.notifyMatchFailure(op,
1031 "Could not resolve class struct for " +
1032 classSym.getRootReference().str());
1034 auto structInfo = cache.getStructInfo(classSym);
1035 assert(structInfo &&
"class struct info must exist");
1036 auto structTy = structInfo->classBody;
1039 auto propSym = op.getProperty();
1040 auto pathOpt = structInfo->getFieldPath(propSym);
1042 return rewriter.notifyMatchFailure(op,
1043 "no GEP path for property " + propSym);
1045 auto i32Ty = IntegerType::get(ctx, 32);
1046 SmallVector<Value> idxVals;
1047 for (
unsigned idx : *pathOpt)
1048 idxVals.push_back(LLVM::ConstantOp::create(
1049 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
1052 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
1054 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
1057 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
1061 rewriter.replaceOp(op, fieldRef);
1066 ClassTypeCache &cache;
1070 using OpConversionPattern::OpConversionPattern;
1073 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
1074 ConversionPatternRewriter &rewriter)
const override {
1076 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
1077 Type srcTy = adaptor.getInstance().getType();
1080 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
1083 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
1084 rewriter.replaceOp(op, adaptor.getInstance());
1087 return rewriter.notifyMatchFailure(
1088 op,
"Upcast applied to non-opaque pointers!");
1094 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
1095 ClassTypeCache &cache, FunctionCache &funcCache)
1097 funcCache(funcCache) {}
1100 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
1101 ConversionPatternRewriter &rewriter)
const override {
1102 Location loc = op.getLoc();
1103 MLIRContext *ctx = rewriter.getContext();
1105 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
1106 auto sym = handleTy.getClassSym();
1108 ModuleOp mod = op->getParentOfType<ModuleOp>();
1110 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
1111 return op.emitError() <<
"Could not resolve class struct for " << sym;
1113 auto structTy = cache.getStructInfo(sym)->classBody;
1114 auto typeInfo = cache.getStructInfo(sym)->typeInfo;
1119 for (
auto memberTy : structTy.getBody()) {
1120 if (!LLVM::isCompatibleType(memberTy) &&
1121 !memberTy.hasTrait<DataLayoutTypeInterface::Trait>()) {
1122 return op.emitError()
1123 <<
"class struct has member types with no data layout";
1129 uint64_t byteSize = dl.getTypeSize(structTy);
1130 auto i64Ty = IntegerType::get(ctx, 64);
1131 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
1132 rewriter.getI64IntegerAttr(byteSize));
1135 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
1136 auto mallocFn = funcCache.getOrCreate(rewriter,
"malloc", {i64Ty}, {ptrTy});
1138 func::CallOp::create(rewriter, loc, mallocFn, ValueRange{cSize});
1141 LLVM::AddressOfOp::create(rewriter, loc, typeInfo.global);
1142 auto i32Ty = IntegerType::get(ctx, 32);
1143 auto headerIdx = LLVM::ConstantOp::create(
1144 rewriter, loc, i32Ty,
1145 rewriter.getI32IntegerAttr(cache.getStructInfo(sym)->headerFieldIndex));
1146 auto typeInfoIdx = LLVM::ConstantOp::create(
1147 rewriter, loc, i32Ty,
1148 rewriter.getI32IntegerAttr(
1149 cache.getStructInfo(sym)->typeInfoFieldIndex));
1151 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, call.getResult(0),
1152 ValueRange{headerIdx, typeInfoIdx});
1153 LLVM::StoreOp::create(rewriter, loc, typeInfoAddr, headerPtr);
1157 rewriter.replaceOp(op, call.getResult(0));
1162 ClassTypeCache &cache;
1163 FunctionCache &funcCache;
1167 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
1168 ClassTypeCache &cache)
1172 matchAndRewrite(ClassDeclOp op, OpAdaptor,
1173 ConversionPatternRewriter &rewriter)
const override {
1175 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
1178 rewriter.eraseOp(op);
1183 ClassTypeCache &cache;
1187 using OpConversionPattern::OpConversionPattern;
1190 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
1191 ConversionPatternRewriter &rewriter)
const override {
1192 auto loc = op.getLoc();
1193 auto resultType = typeConverter->convertType(op.getResult().getType());
1195 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
1197 auto refType = dyn_cast<llhd::RefType>(resultType);
1199 return rewriter.notifyMatchFailure(
1200 op.getLoc(),
"variable type did not convert to llhd::RefType");
1203 Value init = adaptor.getInitial();
1210 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
1211 op.getNameAttr(), init);
1217 using OpConversionPattern::OpConversionPattern;
1220 matchAndRewrite(NetOp op, OpAdaptor adaptor,
1221 ConversionPatternRewriter &rewriter)
const override {
1222 auto loc = op.getLoc();
1224 auto resultType = typeConverter->convertType(op.getResult().getType());
1226 return rewriter.notifyMatchFailure(loc,
"invalid net type");
1228 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
1234 createInitialValue(op.getKind(), rewriter, loc, width,
elementType);
1235 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
1236 op, resultType, op.getNameAttr(), init);
1238 if (
auto assignedValue = adaptor.getAssignment()) {
1239 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
1240 llvm::StringRef(
"ns"), 0, 1);
1241 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
1242 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
1249 static mlir::Value createInitialValue(NetKind kind,
1250 ConversionPatternRewriter &rewriter,
1251 Location loc, int64_t width,
1262 if (kind == NetKind::Supply1 || kind == NetKind::Tri1)
1263 return APInt::getAllOnes(width);
1264 return APInt::getZero(width);
1272static LogicalResult
convert(GlobalVariableOp op,
1273 GlobalVariableOp::Adaptor adaptor,
1274 ConversionPatternRewriter &rewriter,
1275 const TypeConverter &typeConverter) {
1276 auto type = typeConverter.convertType(op.getType());
1277 auto sig = llhd::GlobalSignalOp::create(rewriter, op.getLoc(),
1278 op.getSymNameAttr(), type);
1279 sig.getInitRegion().takeBody(op.getInitRegion());
1280 rewriter.eraseOp(op);
1285static LogicalResult
convert(GetGlobalVariableOp op,
1286 GetGlobalVariableOp::Adaptor adaptor,
1287 ConversionPatternRewriter &rewriter,
1288 const TypeConverter &typeConverter) {
1289 auto type = typeConverter.convertType(op.getType());
1290 rewriter.replaceOpWithNewOp<llhd::GetGlobalSignalOp>(op, type,
1291 op.getGlobalNameAttr());
1300 using OpConversionPattern::OpConversionPattern;
1303 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
1304 ConversionPatternRewriter &rewriter)
const override {
1306 auto value = op.getValue().toAPInt(
false);
1307 auto type = rewriter.getIntegerType(value.getBitWidth());
1309 op, type, rewriter.getIntegerAttr(type, value));
1315 using OpConversionPattern::OpConversionPattern;
1318 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
1319 ConversionPatternRewriter &rewriter)
const override {
1320 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
1326 using OpConversionPattern::OpConversionPattern;
1329 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
1330 ConversionPatternRewriter &rewriter)
const override {
1331 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
1332 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
1333 StringRef(
"fs"), 0, 0));
1339 using OpConversionPattern::OpConversionPattern;
1341 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
1342 ConversionPatternRewriter &rewriter)
const override {
1343 const auto resultType =
1344 typeConverter->convertType(op.getResult().getType());
1345 const auto intType = mlir::cast<IntegerType>(resultType);
1347 const auto str = op.getValue();
1348 const unsigned byteWidth = intType.getWidth();
1349 APInt value(byteWidth, 0);
1352 const size_t maxChars =
1353 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
1354 for (
size_t i = 0; i < maxChars; i++) {
1355 const size_t pos = str.size() - 1 - i;
1356 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
1357 value |= APInt(byteWidth, asciiChar) << (8 * i);
1361 op, resultType, rewriter.getIntegerAttr(resultType, value));
1367 using OpConversionPattern::OpConversionPattern;
1369 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1370 ConversionPatternRewriter &rewriter)
const override {
1371 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1377 using OpConversionPattern::OpConversionPattern;
1379 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1380 ConversionPatternRewriter &rewriter)
const override {
1381 Type resultType = typeConverter->convertType(op.getResult().getType());
1383 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1384 adaptor.getValue());
1390 using OpConversionPattern::OpConversionPattern;
1393 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1394 ConversionPatternRewriter &rewriter)
const override {
1397 Type resultType = typeConverter->convertType(op.getResult().getType());
1398 Value input = adaptor.getInput();
1399 Type inputType = input.getType();
1400 int32_t low = adaptor.getLowBit();
1402 if (
auto structTy = dyn_cast<hw::StructType>(inputType)) {
1403 int32_t width = hw::getBitWidth(structTy);
1407 op.getLoc(), rewriter.getIntegerType(width), input);
1408 inputType = input.getType();
1411 if (isa<IntegerType>(inputType)) {
1412 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1413 int32_t resultWidth = hw::getBitWidth(resultType);
1414 int32_t high = low + resultWidth;
1416 SmallVector<Value> toConcat;
1419 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
1421 if (low < inputWidth && high > 0) {
1422 int32_t lowIdx = std::max(low, 0);
1425 rewriter.getIntegerType(
1426 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
1428 toConcat.push_back(middle);
1431 int32_t diff = high - inputWidth;
1435 toConcat.push_back(val);
1440 rewriter.replaceOp(op, concat);
1444 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1445 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
1446 int32_t inputWidth = arrTy.getNumElements();
1448 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1449 resArrTy && resArrTy != arrTy.getElementType()) {
1450 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
1451 if (elementWidth < 0)
1454 int32_t high = low + resArrTy.getNumElements();
1455 int32_t resWidth = resArrTy.getNumElements();
1457 SmallVector<Value> toConcat;
1460 rewriter, op.getLoc(),
1461 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1464 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1466 toConcat.push_back(res);
1469 if (low < inputWidth && high > 0) {
1470 int32_t lowIdx = std::max(0, low);
1472 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
1476 arrTy.getElementType(),
1477 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1478 adaptor.getInput(), lowIdxVal);
1479 toConcat.push_back(middle);
1482 int32_t diff = high - inputWidth;
1485 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1487 rewriter, op.getLoc(),
1488 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1489 toConcat.push_back(val);
1494 rewriter.replaceOp(op, concat);
1499 if (low < 0 || low >= inputWidth) {
1500 int32_t bw = hw::getBitWidth(resultType);
1506 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
1507 rewriter.replaceOp(op, bitcast);
1512 rewriter.getIntegerType(width),
1513 adaptor.getLowBit());
1514 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
1523 using OpConversionPattern::OpConversionPattern;
1526 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1527 ConversionPatternRewriter &rewriter)
const override {
1529 Type resultType = typeConverter->convertType(op.getResult().getType());
1531 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1533 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1534 int64_t width = hw::getBitWidth(inputType);
1539 rewriter, op.getLoc(),
1540 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1541 adaptor.getLowBit());
1542 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1543 op, resultType, adaptor.getInput(), lowBit);
1547 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1549 rewriter, op.getLoc(),
1550 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1551 adaptor.getLowBit());
1555 if (arrType.getElementType() !=
1556 cast<llhd::RefType>(resultType).getNestedType()) {
1557 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1558 op, resultType, adaptor.getInput(), lowBit);
1562 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1572 using OpConversionPattern::OpConversionPattern;
1575 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1576 ConversionPatternRewriter &rewriter)
const override {
1577 Type resultType = typeConverter->convertType(op.getResult().getType());
1578 Type inputType = adaptor.getInput().getType();
1580 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1581 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1582 intType.getWidth(), op->getLoc());
1583 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1584 adaptor.getInput(), amount);
1586 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1590 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1591 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1592 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1595 bool isSingleElementExtract = arrType.getElementType() == resultType;
1597 if (isSingleElementExtract)
1598 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1602 adaptor.getInput(), idx);
1612 using OpConversionPattern::OpConversionPattern;
1615 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1616 ConversionPatternRewriter &rewriter)
const override {
1618 Type resultType = typeConverter->convertType(op.getResult().getType());
1620 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1622 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1623 int64_t width = hw::getBitWidth(inputType);
1628 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1629 llvm::Log2_64_Ceil(width), op->getLoc());
1630 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1631 op, resultType, adaptor.getInput(), amount);
1635 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1636 Value idx = adjustIntegerWidth(
1637 rewriter, adaptor.getLowBit(),
1638 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1640 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1641 bool isSingleElementExtract =
1642 arrType.getElementType() == resultNestedType;
1644 if (isSingleElementExtract)
1645 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1648 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1649 op, resultType, adaptor.getInput(), idx);
1659 using OpConversionPattern::OpConversionPattern;
1662 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1663 ConversionPatternRewriter &rewriter)
const override {
1664 Type resultType = typeConverter->convertType(op.getResult().getType());
1666 adaptor.getElements());
1672 using OpConversionPattern::OpConversionPattern;
1675 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1676 ConversionPatternRewriter &rewriter)
const override {
1677 Type resultType = typeConverter->convertType(op.getResult().getType());
1679 adaptor.getFields());
1685 using OpConversionPattern::OpConversionPattern;
1688 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1689 ConversionPatternRewriter &rewriter)
const override {
1691 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1696struct StructExtractRefOpConversion
1698 using OpConversionPattern::OpConversionPattern;
1701 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1702 ConversionPatternRewriter &rewriter)
const override {
1703 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1704 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1710 using OpConversionPattern::OpConversionPattern;
1713 matchAndRewrite(UnionCreateOp op, OpAdaptor adaptor,
1714 ConversionPatternRewriter &rewriter)
const override {
1715 Type resultType = typeConverter->convertType(op.getResult().getType());
1716 rewriter.replaceOpWithNewOp<hw::UnionCreateOp>(
1717 op, resultType, adaptor.getFieldNameAttr(), adaptor.getInput());
1723 using OpConversionPattern::OpConversionPattern;
1726 matchAndRewrite(UnionExtractOp op, OpAdaptor adaptor,
1727 ConversionPatternRewriter &rewriter)
const override {
1728 rewriter.replaceOpWithNewOp<hw::UnionExtractOp>(op, adaptor.getInput(),
1729 adaptor.getFieldNameAttr());
1734struct UnionExtractRefOpConversion
1736 using OpConversionPattern::OpConversionPattern;
1739 matchAndRewrite(UnionExtractRefOp op, OpAdaptor adaptor,
1740 ConversionPatternRewriter &rewriter)
const override {
1741 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1742 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1748 using OpConversionPattern::OpConversionPattern;
1750 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1751 ConversionPatternRewriter &rewriter)
const override {
1752 Type resultType = typeConverter->convertType(op.getInput().getType());
1755 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1756 adaptor.getInput(), max);
1762 using OpConversionPattern::OpConversionPattern;
1764 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1765 ConversionPatternRewriter &rewriter)
const override {
1766 Type resultType = typeConverter->convertType(op.getInput().getType());
1769 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1770 adaptor.getInput(), zero);
1776 using OpConversionPattern::OpConversionPattern;
1778 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1779 ConversionPatternRewriter &rewriter)
const override {
1781 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1787 using OpConversionPattern::OpConversionPattern;
1789 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1790 ConversionPatternRewriter &rewriter)
const override {
1791 Type resultType = typeConverter->convertType(op.getInput().getType());
1792 if (isa_and_nonnull<IntegerType>(resultType)) {
1795 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1796 adaptor.getInput(), zero);
1799 if (isa_and_nonnull<FloatType>(resultType)) {
1800 Value zero = arith::ConstantOp::create(
1801 rewriter, op->getLoc(), rewriter.getFloatAttr(resultType, 0.0));
1802 rewriter.replaceOpWithNewOp<arith::CmpFOp>(op, arith::CmpFPredicate::ONE,
1803 adaptor.getInput(), zero);
1806 if (isa_and_nonnull<llhd::TimeType>(resultType)) {
1808 llhd::TimeToIntOp::create(rewriter, op->getLoc(), adaptor.getInput());
1810 rewriter.getI64Type(), 0);
1811 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1815 if (isa_and_nonnull<hw::StructType, hw::ArrayType, hw::UnionType>(
1817 int64_t width = hw::getBitWidth(resultType);
1820 auto intTy = rewriter.getIntegerType(width);
1821 Value input = rewriter.createOrFold<
hw::BitcastOp>(op->getLoc(), intTy,
1822 adaptor.getInput());
1824 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1833 using OpConversionPattern::OpConversionPattern;
1835 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1836 ConversionPatternRewriter &rewriter)
const override {
1838 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1841 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1847 using OpConversionPattern::OpConversionPattern;
1849 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1850 ConversionPatternRewriter &rewriter)
const override {
1852 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1855 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1861 using OpConversionPattern::OpConversionPattern;
1863 matchAndRewrite(NegRealOp op, OpAdaptor adaptor,
1864 ConversionPatternRewriter &rewriter)
const override {
1865 rewriter.replaceOpWithNewOp<arith::NegFOp>(op, adaptor.getInput());
1870template <
typename SourceOp,
typename TargetOp>
1873 using OpAdaptor =
typename SourceOp::Adaptor;
1876 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1877 ConversionPatternRewriter &rewriter)
const override {
1878 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1879 adaptor.getRhs(),
false);
1884template <
typename SourceOp,
typename TargetOp>
1887 using OpAdaptor =
typename SourceOp::Adaptor;
1890 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1891 ConversionPatternRewriter &rewriter)
const override {
1892 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1899 using OpConversionPattern::OpConversionPattern;
1901 matchAndRewrite(HypotBIOp op, OpAdaptor adaptor,
1902 ConversionPatternRewriter &rewriter)
const override {
1903 Value lhs = adaptor.getLhs();
1904 Value rhs = adaptor.getRhs();
1905 ImplicitLocOpBuilder b(op->getLoc(), rewriter);
1906 auto left = arith::MulFOp::create(b, lhs, lhs);
1907 auto right = arith::MulFOp::create(b, rhs, rhs);
1908 auto sum = arith::AddFOp::create(b, left, right);
1909 auto out = math::SqrtOp::create(b, sum);
1910 rewriter.replaceOp(op, out);
1915template <
typename SourceOp,
typename TargetOp>
1918 using OpAdaptor =
typename SourceOp::Adaptor;
1921 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1922 ConversionPatternRewriter &rewriter)
const override {
1923 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getValue());
1928template <
typename SourceOp, ICmpPredicate pred>
1931 using OpAdaptor =
typename SourceOp::Adaptor;
1934 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1935 ConversionPatternRewriter &rewriter)
const override {
1937 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1939 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1940 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1946 using OpConversionPattern::OpConversionPattern;
1949 matchAndRewrite(NullOp op, OpAdaptor adaptor,
1950 ConversionPatternRewriter &rewriter)
const override {
1951 Type ptrTy = getTypeConverter()->convertType(op.getResult().getType());
1953 return rewriter.notifyMatchFailure(op,
"failed to convert null type");
1954 rewriter.replaceOpWithNewOp<LLVM::ZeroOp>(op, ptrTy);
1959template <
typename SourceOp, LLVM::ICmpPredicate pred>
1962 using OpAdaptor =
typename SourceOp::Adaptor;
1965 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1966 ConversionPatternRewriter &rewriter)
const override {
1967 rewriter.replaceOpWithNewOp<LLVM::ICmpOp>(op, pred, adaptor.getLhs(),
1973template <
typename SourceOp, arith::CmpFPredicate pred>
1976 using OpAdaptor =
typename SourceOp::Adaptor;
1979 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1980 ConversionPatternRewriter &rewriter)
const override {
1982 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1984 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1985 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1990template <
typename SourceOp,
bool withoutX>
1993 using OpAdaptor =
typename SourceOp::Adaptor;
1996 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1997 ConversionPatternRewriter &rewriter)
const override {
2003 unsigned bitWidth = op.getLhs().getType().getWidth();
2004 auto ignoredBits = APInt::getZero(bitWidth);
2005 auto detectIgnoredBits = [&](Value value) {
2006 auto constOp = value.getDefiningOp<ConstantOp>();
2009 auto constValue = constOp.getValue();
2011 ignoredBits |= constValue.getZBits();
2013 ignoredBits |= constValue.getUnknownBits();
2015 detectIgnoredBits(op.getLhs());
2016 detectIgnoredBits(op.getRhs());
2020 Value lhs = adaptor.getLhs();
2021 Value rhs = adaptor.getRhs();
2022 if (!ignoredBits.isZero()) {
2023 ignoredBits.flipAllBits();
2025 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
2026 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
2029 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
2039 using OpConversionPattern::OpConversionPattern;
2042 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
2043 ConversionPatternRewriter &rewriter)
const override {
2044 Location loc = op.getLoc();
2045 Type resultType = typeConverter->convertType(op.getResult().getType());
2047 op.emitError(
"conversion result type is not currently supported");
2050 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
2051 int64_t resultBw = hw::getBitWidth(resultType);
2052 if (inputBw == -1 || resultBw == -1) {
2053 if (isSupportedDpiOpenArrayCast(op.getInput().getType(),
2054 op.getResult().getType())) {
2055 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2056 op, resultType, adaptor.getInput());
2059 if (hasOpenArrayBoundaryType(op.getInput().getType()) ||
2060 hasOpenArrayBoundaryType(op.getResult().getType())) {
2061 op.emitError(
"unsupported DPI open-array conversion from ")
2062 << op.getInput().getType() <<
" to " << op.getResult().getType();
2069 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
2070 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
2073 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
2074 rewriter.replaceOp(op, result);
2079template <
typename SourceOp>
2082 using OpAdaptor =
typename SourceOp::Adaptor;
2083 using ConversionPattern::typeConverter;
2086 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2087 ConversionPatternRewriter &rewriter)
const override {
2088 auto type = typeConverter->convertType(op.getResult().getType());
2089 if (type == adaptor.getInput().getType())
2090 rewriter.replaceOp(op, adaptor.getInput());
2092 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
2098template <
typename SourceOp>
2101 using OpAdaptor =
typename SourceOp::Adaptor;
2102 using ConversionPattern::typeConverter;
2105 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2106 ConversionPatternRewriter &rewriter)
const override {
2107 rewriter.replaceOp(op, adaptor.getInput());
2113 using OpConversionPattern::OpConversionPattern;
2116 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
2117 ConversionPatternRewriter &rewriter)
const override {
2118 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
2119 op.getType().getWidth());
2125 using OpConversionPattern::OpConversionPattern;
2128 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
2129 ConversionPatternRewriter &rewriter)
const override {
2130 auto targetWidth = op.getType().getWidth();
2131 auto inputWidth = op.getInput().getType().getWidth();
2134 rewriter, op.getLoc(),
2135 rewriter.getIntegerType(targetWidth - inputWidth), 0);
2138 op, ValueRange{zeroExt, adaptor.getInput()});
2144 using OpConversionPattern::OpConversionPattern;
2147 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
2148 ConversionPatternRewriter &rewriter)
const override {
2149 auto type = typeConverter->convertType(op.getType());
2151 comb::createOrFoldSExt(rewriter, op.getLoc(), adaptor.getInput(), type);
2152 rewriter.replaceOp(op, value);
2158 using OpConversionPattern::OpConversionPattern;
2161 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
2162 ConversionPatternRewriter &rewriter)
const override {
2163 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
2164 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2170 using OpConversionPattern::OpConversionPattern;
2173 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
2174 ConversionPatternRewriter &rewriter)
const override {
2175 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
2176 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2182 using OpConversionPattern::OpConversionPattern;
2185 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
2186 ConversionPatternRewriter &rewriter)
const override {
2187 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
2193 using OpConversionPattern::OpConversionPattern;
2196 matchAndRewrite(StringToIntOp op, OpAdaptor adaptor,
2197 ConversionPatternRewriter &rewriter)
const override {
2198 Type resultTy = typeConverter->convertType(op.getType());
2201 rewriter.replaceOpWithNewOp<sim::StringToIntOp>(op, resultTy,
2202 adaptor.getInput());
2207struct FormatStringToStringOpConversion
2209 using OpConversionPattern::OpConversionPattern;
2212 matchAndRewrite(FormatStringToStringOp op, OpAdaptor adaptor,
2213 ConversionPatternRewriter &rewriter)
const override {
2214 rewriter.replaceOpWithNewOp<sim::FormatToStringOp>(op,
2215 adaptor.getFmtstring());
2221 using OpConversionPattern::OpConversionPattern;
2224 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
2225 ConversionPatternRewriter &rewriter)
const override {
2226 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
2227 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2233 using OpConversionPattern::OpConversionPattern;
2236 matchAndRewrite(ConvertRealOp op, OpAdaptor adaptor,
2237 ConversionPatternRewriter &rewriter)
const override {
2238 op.getInput().getType().getWidth() < op.getResult().getType().getWidth()
2239 ? rewriter.replaceOpWithNewOp<arith::ExtFOp>(
2240 op, typeConverter->convertType(op.getType()), adaptor.getInput())
2241 : rewriter.replaceOpWithNewOp<arith::TruncFOp>(
2242 op, typeConverter->
convertType(op.getType()), adaptor.getInput());
2247template <
typename SourceOp>
2250 using OpAdaptor =
typename SourceOp::Adaptor;
2253 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2254 ConversionPatternRewriter &rewriter)
const override {
2256 ConversionPattern::typeConverter->convertType(op.getResult().getType());
2257 rewriter.replaceOpWithNewOp<arith::BitcastOp>(op, resultTy,
2258 adaptor.getValue());
2268 using OpConversionPattern::OpConversionPattern;
2271 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
2272 ConversionPatternRewriter &rewriter)
const override {
2273 SmallVector<Type> convResTypes;
2274 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2277 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
2278 op, convResTypes, op.getInstanceName(), op.getModuleName(),
2279 adaptor.getOperands(), op.getArgNames(),
2280 op.getResultNames(),
2281 rewriter.getArrayAttr({}),
nullptr);
2288 using OpConversionPattern::OpConversionPattern;
2291 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
2292 ConversionPatternRewriter &rewriter)
const override {
2293 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
2299 using OpConversionPattern::OpConversionPattern;
2302 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
2303 ConversionPatternRewriter &rewriter)
const override {
2304 SmallVector<Type> convResTypes;
2305 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2307 rewriter.replaceOpWithNewOp<func::CallOp>(
2308 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
2313struct FuncDPICallOpConversion
2315 using OpConversionPattern::OpConversionPattern;
2318 matchAndRewrite(moore::FuncDPICallOp op, OpAdaptor adaptor,
2319 ConversionPatternRewriter &rewriter)
const override {
2320 SmallVector<Type> convResTypes;
2321 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2323 rewriter.replaceOpWithNewOp<sim::DPICallOp>(
2324 op, convResTypes, op.getCalleeAttr(), Value(),
2325 Value(), adaptor.getInputs());
2331 using OpConversionPattern::OpConversionPattern;
2334 matchAndRewrite(moore::DPIFuncOp op, OpAdaptor adaptor,
2335 ConversionPatternRewriter &rewriter)
const override {
2337 auto toDPIDir = [](moore::DPIArgDirection dir) -> sim::DPIDirection {
2339 case moore::DPIArgDirection::In:
2340 return sim::DPIDirection::Input;
2341 case moore::DPIArgDirection::Out:
2342 return sim::DPIDirection::Output;
2343 case moore::DPIArgDirection::InOut:
2344 return sim::DPIDirection::InOut;
2345 case moore::DPIArgDirection::Return:
2346 return sim::DPIDirection::Return;
2348 llvm_unreachable(
"unknown DPIArgDirection");
2352 auto dirs = op.getDpiArgDirs();
2353 auto names = op.getDpiArgNames();
2354 SmallVector<Type> argTypes;
2355 op.getDPIArgTypes(argTypes);
2357 SmallVector<sim::DPIArgument> dpiArguments;
2358 for (
auto [dirAttr, nameAttr, mooreType] :
2359 llvm::zip(dirs, names, argTypes)) {
2360 auto dir = toDPIDir(cast<moore::DPIArgDirectionAttr>(dirAttr).getValue());
2361 auto name = cast<StringAttr>(nameAttr);
2362 Type coreType = typeConverter->convertType(mooreType);
2364 return op.emitOpError(
"argument '")
2365 << name <<
"' has unsupported type " << mooreType;
2366 dpiArguments.push_back({name, coreType, dir});
2369 auto coreDPIFuncType =
2370 sim::DPIFunctionType::get(rewriter.getContext(), dpiArguments);
2371 auto simFunc = sim::DPIFuncOp::create(
2372 rewriter, op.getLoc(), op.getSymNameAttr(), coreDPIFuncType,
2373 op.getArgumentLocsAttr(), op.getVerilogNameAttr());
2374 SymbolTable::setSymbolVisibility(simFunc,
2375 SymbolTable::getSymbolVisibility(op));
2376 rewriter.eraseOp(op);
2381struct UnrealizedConversionCastConversion
2383 using OpConversionPattern::OpConversionPattern;
2386 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
2387 ConversionPatternRewriter &rewriter)
const override {
2388 SmallVector<Type> convResTypes;
2389 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2394 if (convResTypes == adaptor.getOperands().getTypes()) {
2395 rewriter.replaceOp(op, adaptor.getOperands());
2399 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2400 op, convResTypes, adaptor.getOperands());
2406 using OpConversionPattern::OpConversionPattern;
2409 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
2410 ConversionPatternRewriter &rewriter)
const override {
2411 Type resultType = typeConverter->convertType(op.getResult().getType());
2415 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2416 resultType.getIntOrFloatBitWidth(), op->getLoc());
2417 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
2424 using OpConversionPattern::OpConversionPattern;
2427 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
2428 ConversionPatternRewriter &rewriter)
const override {
2429 Type resultType = typeConverter->convertType(op.getResult().getType());
2433 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2434 resultType.getIntOrFloatBitWidth(), op->getLoc());
2436 op, resultType, adaptor.getValue(), amount,
false);
2442 using OpConversionPattern::OpConversionPattern;
2445 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
2446 ConversionPatternRewriter &rewriter)
const override {
2447 Type resultType = typeConverter->convertType(op.getResult().getType());
2449 Location loc = op->getLoc();
2454 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
2455 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
2458 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
2466 using OpConversionPattern::OpConversionPattern;
2469 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
2470 ConversionPatternRewriter &rewriter)
const override {
2471 Type resultType = typeConverter->convertType(op.getResult().getType());
2475 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
2476 op, resultType, adaptor.getLhs(), adaptor.getRhs());
2482 using OpConversionPattern::OpConversionPattern;
2485 matchAndRewrite(Clog2BIOp op, OpAdaptor adaptor,
2486 ConversionPatternRewriter &rewriter)
const override {
2487 Type resultType = typeConverter->convertType(op.getResult().getType());
2488 Location loc = op.getLoc();
2489 unsigned width = resultType.getIntOrFloatBitWidth();
2490 Value value = adaptor.getValue();
2499 Value valueMinusOne = comb::SubOp::create(rewriter, loc, value, one,
false);
2501 mlir::math::CountLeadingZerosOp::create(rewriter, loc, valueMinusOne);
2502 Value bitLength = comb::SubOp::create(rewriter, loc, bitWidth, clz,
false);
2504 Value isZero = comb::ICmpOp::create(rewriter, loc, comb::ICmpPredicate::eq,
2505 value, zero,
false);
2506 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, isZero, zero, bitLength,
2513 using OpConversionPattern::OpConversionPattern;
2516 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
2517 ConversionPatternRewriter &rewriter)
const override {
2518 Type resultType = typeConverter->convertType(op.getResult().getType());
2522 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2523 resultType.getIntOrFloatBitWidth(), op->getLoc());
2525 op, resultType, adaptor.getValue(), amount,
false);
2531 using OpConversionPattern::OpConversionPattern;
2534 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
2535 ConversionPatternRewriter &rewriter)
const override {
2536 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
2541struct AssignedVariableOpConversion
2543 using OpConversionPattern::OpConversionPattern;
2546 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
2547 ConversionPatternRewriter &rewriter)
const override {
2548 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
2549 adaptor.getNameAttr());
2555static llhd::TimeAttr
2556getBlockingOrContinuousAssignDelay(mlir::MLIRContext *
context) {
2557 return llhd::TimeAttr::get(
context, 0U,
"ns", 0, 1);
2560template <
typename OpTy>
2563 using OpAdaptor =
typename OpTy::Adaptor;
2566 matchAndRewrite(OpTy op, OpAdaptor adaptor,
2567 ConversionPatternRewriter &rewriter)
const override {
2570 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
2571 std::is_same_v<OpTy, BlockingAssignOp>) {
2572 delay = llhd::ConstantTimeOp::create(
2573 rewriter, op->getLoc(),
2574 getBlockingOrContinuousAssignDelay(op->getContext()));
2575 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
2577 delay = llhd::ConstantTimeOp::create(
2578 rewriter, op->getLoc(),
2579 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
2582 delay = adaptor.getDelay();
2585 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
2586 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
2592 using OpConversionPattern::OpConversionPattern;
2595 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
2596 ConversionPatternRewriter &rewriter)
const override {
2601 auto type = typeConverter->convertType(op.getType());
2603 auto hasNoWriteEffect = [](Region ®ion) {
2604 auto result = region.walk([](Operation *operation) {
2605 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
2606 if (!memOp.hasEffect<MemoryEffects::Write>() &&
2607 !memOp.hasEffect<MemoryEffects::Free>())
2608 return WalkResult::advance();
2610 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
2611 return WalkResult::advance();
2613 return WalkResult::interrupt();
2615 return !result.wasInterrupted();
2618 if (hasNoWriteEffect(op.getTrueRegion()) &&
2619 hasNoWriteEffect(op.getFalseRegion())) {
2620 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
2621 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
2623 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
2624 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
2626 Value convTrueVal = typeConverter->materializeTargetConversion(
2627 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
2628 Value convFalseVal = typeConverter->materializeTargetConversion(
2629 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
2631 rewriter.eraseOp(trueTerm);
2632 rewriter.eraseOp(falseTerm);
2634 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
2635 convTrueVal, convFalseVal);
2640 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
2641 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
2642 ifOp.getThenRegion().end());
2643 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
2644 ifOp.getElseRegion().end());
2645 rewriter.replaceOp(op, ifOp);
2651 using OpConversionPattern::OpConversionPattern;
2654 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
2655 ConversionPatternRewriter &rewriter)
const override {
2656 Operation *parent = op->getParentOp();
2657 if (isa<llhd::GlobalSignalOp>(parent))
2658 rewriter.replaceOpWithNewOp<llhd::YieldOp>(op, adaptor.getResult());
2659 else if (isa<scf::ExecuteRegionOp, scf::ForOp, scf::IfOp,
2660 scf::IndexSwitchOp, scf::WhileOp>(parent))
2661 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
2663 return rewriter.notifyMatchFailure(
2664 op,
"yield parent has not been converted to a legal region op yet");
2669template <
typename SourceOp>
2672 using OpAdaptor =
typename SourceOp::Adaptor;
2675 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2676 ConversionPatternRewriter &rewriter)
const override {
2677 rewriter.modifyOpInPlace(op,
2678 [&]() { op->setOperands(adaptor.getOperands()); });
2683template <
typename MooreOpTy,
typename VerifOpTy>
2686 using OpAdaptor =
typename MooreOpTy::Adaptor;
2689 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
2690 ConversionPatternRewriter &rewriter)
const override {
2692 op.getLabel().has_value()
2693 ? StringAttr::get(op->getContext(), op.getLabel().value())
2694 : StringAttr::
get(op->getContext());
2695 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
2706 using OpConversionPattern::OpConversionPattern;
2709 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2710 ConversionPatternRewriter &rewriter)
const override {
2711 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2717 using OpConversionPattern::OpConversionPattern;
2720 matchAndRewrite(FormatStringOp op, OpAdaptor adaptor,
2721 ConversionPatternRewriter &rewriter)
const override {
2723 op.getPadding().value_or(IntPadding::Space) == IntPadding::Space ? 32
2725 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2726 auto widthAttr = adaptor.getWidthAttr();
2728 bool isLeftAligned =
2729 op.getAlignment().value_or(IntAlign::Right) == IntAlign::Left;
2730 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2732 rewriter.replaceOpWithNewOp<sim::FormatStringOp>(
2733 op, adaptor.getString(), isLeftAlignedAttr, padCharAttr, widthAttr);
2739 using OpConversionPattern::OpConversionPattern;
2742 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2743 ConversionPatternRewriter &rewriter)
const override {
2744 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2745 adaptor.getInputs());
2750struct FormatHierPathOpConversion
2752 using OpConversionPattern::OpConversionPattern;
2755 matchAndRewrite(FormatHierPathOp op, OpAdaptor adaptor,
2756 ConversionPatternRewriter &rewriter)
const override {
2757 rewriter.replaceOpWithNewOp<sim::FormatHierPathOp>(op,
2758 adaptor.getUseEscapes());
2764 using OpConversionPattern::OpConversionPattern;
2767 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2768 ConversionPatternRewriter &rewriter)
const override {
2770 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2771 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2772 auto widthAttr = adaptor.getSpecifierWidthAttr();
2774 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2775 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2777 switch (op.getFormat()) {
2778 case IntFormat::Decimal:
2779 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2780 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2781 adaptor.getIsSignedAttr());
2783 case IntFormat::Binary:
2784 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2785 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2787 case IntFormat::Octal:
2788 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2789 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2791 case IntFormat::HexLower:
2792 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2793 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2794 isLeftAlignedAttr, padCharAttr, widthAttr);
2796 case IntFormat::HexUpper:
2797 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2798 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2799 padCharAttr, widthAttr);
2802 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2807 using OpConversionPattern::OpConversionPattern;
2810 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2811 ConversionPatternRewriter &rewriter)
const override {
2812 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2814 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2815 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2816 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2818 switch (op.getFormat()) {
2819 case RealFormat::General:
2820 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2821 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2824 case RealFormat::Float:
2825 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2826 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2829 case RealFormat::Exponential:
2830 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2831 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2838struct FormatCharOpConversion
2840 using OpConversionPattern::OpConversionPattern;
2842 matchAndRewrite(moore::FormatCharOp op, OpAdaptor adaptor,
2843 ConversionPatternRewriter &rewriter)
const override {
2844 rewriter.replaceOpWithNewOp<sim::FormatCharOp>(op, adaptor.getValue());
2850 using OpConversionPattern::OpConversionPattern;
2853 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2854 ConversionPatternRewriter &rewriter)
const override {
2855 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2861 using OpConversionPattern::OpConversionPattern;
2864 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2865 ConversionPatternRewriter &rewriter)
const override {
2866 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2872 using OpConversionPattern::OpConversionPattern;
2875 matchAndRewrite(StringGetOp op, OpAdaptor adaptor,
2876 ConversionPatternRewriter &rewriter)
const override {
2877 rewriter.replaceOpWithNewOp<sim::StringGetOp>(op, adaptor.getStr(),
2878 adaptor.getIndex());
2884 using OpConversionPattern::OpConversionPattern;
2887 matchAndRewrite(QueueSizeBIOp op, OpAdaptor adaptor,
2888 ConversionPatternRewriter &rewriter)
const override {
2889 rewriter.replaceOpWithNewOp<sim::QueueSizeOp>(op, adaptor.getQueue());
2894struct DynQueueExtractOpConversion
2896 using OpConversionPattern::OpConversionPattern;
2899 matchAndRewrite(DynQueueExtractOp op, OpAdaptor adaptor,
2900 ConversionPatternRewriter &rewriter)
const override {
2901 bool isSingleElementExtract =
2902 op.getInput().getType().getElementType() == op.getResult().getType();
2904 if (isSingleElementExtract) {
2905 rewriter.replaceOpWithNewOp<sim::QueueGetOp>(op, adaptor.getInput(),
2906 adaptor.getLowerIdx());
2908 rewriter.replaceOpWithNewOp<sim::QueueSliceOp>(
2909 op, adaptor.getInput(), adaptor.getLowerIdx(), adaptor.getUpperIdx());
2925probeRefAndDriveWithResult(OpBuilder &builder, Location loc, Value ref,
2926 const std::function<Value(Value)> &func) {
2928 Value v = llhd::ProbeOp::create(builder, loc, ref);
2931 Value delay = llhd::ConstantTimeOp::create(
2932 builder, loc, getBlockingOrContinuousAssignDelay(builder.getContext()));
2934 llhd::DriveOp::create(builder, loc, ref, func(v), delay, Value{});
2938 using OpConversionPattern::OpConversionPattern;
2941 matchAndRewrite(QueuePushBackOp op, OpAdaptor adaptor,
2942 ConversionPatternRewriter &rewriter)
const override {
2943 probeRefAndDriveWithResult(
2944 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2945 return sim::QueuePushBackOp::create(rewriter, op->getLoc(), queue,
2946 adaptor.getElement());
2949 rewriter.eraseOp(op);
2954struct QueuePushFrontOpConversion
2956 using OpConversionPattern::OpConversionPattern;
2959 matchAndRewrite(QueuePushFrontOp op, OpAdaptor adaptor,
2960 ConversionPatternRewriter &rewriter)
const override {
2962 probeRefAndDriveWithResult(
2963 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2964 return sim::QueuePushFrontOp::create(rewriter, op->getLoc(), queue,
2965 adaptor.getElement());
2968 rewriter.eraseOp(op);
2974 using OpConversionPattern::OpConversionPattern;
2977 matchAndRewrite(QueuePopBackOp op, OpAdaptor adaptor,
2978 ConversionPatternRewriter &rewriter)
const override {
2980 probeRefAndDriveWithResult(
2981 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2983 sim::QueuePopBackOp::create(rewriter, op->getLoc(), queue);
2984 popped = popBack.getPopped();
2985 return popBack.getOutQueue();
2987 rewriter.replaceOp(op, popped);
2994 using OpConversionPattern::OpConversionPattern;
2997 matchAndRewrite(QueuePopFrontOp op, OpAdaptor adaptor,
2998 ConversionPatternRewriter &rewriter)
const override {
3000 probeRefAndDriveWithResult(
3001 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
3003 sim::QueuePopFrontOp::create(rewriter, op->getLoc(), queue);
3004 popped = popFront.getPopped();
3005 return popFront.getOutQueue();
3007 rewriter.replaceOp(op, popped);
3014 using OpConversionPattern::OpConversionPattern;
3017 matchAndRewrite(QueueClearOp op, OpAdaptor adaptor,
3018 ConversionPatternRewriter &rewriter)
const override {
3019 auto refType = cast<llhd::RefType>(adaptor.getQueue().getType());
3020 auto queueType = refType.getNestedType();
3022 sim::QueueEmptyOp::create(rewriter, op->getLoc(), queueType);
3025 Value delay = llhd::ConstantTimeOp::create(
3026 rewriter, op.getLoc(),
3027 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3029 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getQueue(), emptyQueue,
3032 rewriter.eraseOp(op);
3038 using OpConversionPattern::OpConversionPattern;
3041 matchAndRewrite(QueueInsertOp op, OpAdaptor adaptor,
3042 ConversionPatternRewriter &rewriter)
const override {
3043 probeRefAndDriveWithResult(
3044 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
3046 sim::QueueInsertOp::create(rewriter, op->getLoc(), queue,
3047 adaptor.getIndex(), adaptor.getItem());
3049 return insert.getOutQueue();
3051 rewriter.eraseOp(op);
3058 using OpConversionPattern::OpConversionPattern;
3061 matchAndRewrite(QueueDeleteOp op, OpAdaptor adaptor,
3062 ConversionPatternRewriter &rewriter)
const override {
3063 probeRefAndDriveWithResult(
3064 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
3065 auto delOp = sim::QueueDeleteOp::create(rewriter, op->getLoc(), queue,
3066 adaptor.getIndex());
3068 return delOp.getOutQueue();
3070 rewriter.eraseOp(op);
3077 using OpConversionPattern::OpConversionPattern;
3080 matchAndRewrite(QueueResizeOp op, OpAdaptor adaptor,
3081 ConversionPatternRewriter &rewriter)
const override {
3083 rewriter.replaceOpWithNewOp<sim::QueueResizeOp>(
3084 op, getTypeConverter()->convertType(op.getResult().getType()),
3085 adaptor.getInput());
3091 using OpConversionPattern::OpConversionPattern;
3093 matchAndRewrite(QueueSetOp op, OpAdaptor adaptor,
3094 ConversionPatternRewriter &rewriter)
const override {
3095 probeRefAndDriveWithResult(
3096 rewriter, op->getLoc(), adaptor.getQueue(), [&](Value queue) {
3098 sim::QueueSetOp::create(rewriter, op.getLoc(), queue,
3099 adaptor.getIndex(), adaptor.getItem());
3100 return setOp.getOutQueue();
3102 rewriter.eraseOp(op);
3111static Value buildUArrayElementEq(ConversionPatternRewriter &rewriter,
3112 Location loc, Value lhs, Value rhs, Type type,
3113 UArrayCmpPredicate pred) {
3114 bool isEq = pred == UArrayCmpPredicate::eq;
3116 if (isa<mlir::FloatType>(type))
3117 return arith::CmpFOp::create(
3119 isEq ? arith::CmpFPredicate::OEQ : arith::CmpFPredicate::UNE, lhs, rhs);
3121 if (int64_t width = hw::getBitWidth(type); width != -1) {
3122 auto intTy = rewriter.getIntegerType(width);
3125 return comb::ICmpOp::create(rewriter, loc,
3126 isEq ? ICmpPredicate::eq : ICmpPredicate::ne,
3130 if (isa<sim::DynamicStringType>(type))
3131 return sim::StringCmpOp::create(rewriter, loc,
3132 isEq ? sim::StringCmpPredicate::eq
3133 :
sim::StringCmpPredicate::ne,
3136 if (isa<sim::QueueType>(type)) {
3137 auto pred = sim::UArrayCmpPredicateAttr::get(
3138 rewriter.getContext(),
3139 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3140 return sim::QueueCmpOp::create(rewriter, loc, pred, lhs, rhs);
3143 if (isa<sim::AssocArrayType>(type)) {
3144 auto pred = sim::UArrayCmpPredicateAttr::get(
3145 rewriter.getContext(),
3146 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3147 return sim::AssocArrayCmpOp::create(rewriter, loc, pred, lhs, rhs);
3150 auto arrayTy = dyn_cast<hw::ArrayType>(type);
3154 unsigned size = arrayTy.getNumElements();
3158 unsigned idxWidth = size == 1 ? 1 : llvm::Log2_64_Ceil(size);
3159 auto idxTy = rewriter.getIntegerType(idxWidth);
3161 SmallVector<Value> elemEqs;
3162 elemEqs.reserve(size);
3163 for (
unsigned i = 0; i < size; ++i) {
3167 Value elemEq = buildUArrayElementEq(rewriter, loc, lhsElem, rhsElem,
3168 arrayTy.getElementType(), pred);
3171 elemEqs.push_back(elemEq);
3174 return (isEq ? comb::AndOp::create(rewriter, loc, elemEqs,
true)
3176 :
comb::OrOp::create(rewriter, loc, elemEqs, true)
3181 using OpConversionPattern::OpConversionPattern;
3184 matchAndRewrite(QueueCmpOp op, OpAdaptor adaptor,
3185 ConversionPatternRewriter &rewriter)
const override {
3190 Value lhs = adaptor.getLhs();
3192 buildUArrayElementEq(rewriter, op.getLoc(), lhs, adaptor.getRhs(),
3193 lhs.getType(), op.getPredicate());
3194 rewriter.replaceOp(op, result);
3199struct QueueFromUnpackedArrayOpConversion
3201 using OpConversionPattern::OpConversionPattern;
3204 matchAndRewrite(QueueFromUnpackedArrayOp op, OpAdaptor adaptor,
3205 ConversionPatternRewriter &rewriter)
const override {
3206 rewriter.replaceOpWithNewOp<sim::QueueFromArrayOp>(
3207 op, getTypeConverter()->convertType(op.getResult().getType()),
3208 adaptor.getInput());
3214 using OpConversionPattern::OpConversionPattern;
3217 matchAndRewrite(QueueConcatOp op, OpAdaptor adaptor,
3218 ConversionPatternRewriter &rewriter)
const override {
3219 rewriter.replaceOpWithNewOp<sim::QueueConcatOp>(
3220 op, getTypeConverter()->convertType(op.getResult().getType()),
3221 adaptor.getInputs());
3226struct AssocArrayExtractOpConversion
3228 using OpConversionPattern::OpConversionPattern;
3230 matchAndRewrite(AssocArrayExtractOp op, OpAdaptor adaptor,
3231 ConversionPatternRewriter &rewriter)
const override {
3232 Type resultType = getTypeConverter()->convertType(op.getResult().getType());
3240 sim::AssocArrayGetOp::create(rewriter, op.getLoc(), resultType,
3241 adaptor.getInput(), adaptor.getIndex());
3242 Value exists = sim::AssocArrayExistsOp::create(
3243 rewriter, op.getLoc(), adaptor.getInput(), adaptor.getIndex());
3245 Value existsBit = comb::ICmpOp::create(
3246 rewriter, op.getLoc(), comb::ICmpPredicate::ne, exists, zeroI32,
false);
3247 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, existsBit, raw, zero,
false);
3253 using OpConversionPattern::OpConversionPattern;
3255 matchAndRewrite(UArrayCmpOp op, OpAdaptor adaptor,
3256 ConversionPatternRewriter &rewriter)
const override {
3257 Value lhs = adaptor.getLhs();
3258 Value rhs = adaptor.getRhs();
3259 auto pred = op.getPredicate();
3260 Value eq = buildUArrayElementEq(rewriter, op.getLoc(), lhs, rhs,
3261 lhs.getType(), pred);
3264 return rewriter.notifyMatchFailure(
3265 op,
"unpacked array element type does not support comparison");
3267 rewriter.replaceOp(op, eq);
3273 using OpConversionPattern::OpConversionPattern;
3275 matchAndRewrite(AssocArraySetOp op, OpAdaptor adaptor,
3276 ConversionPatternRewriter &rewriter)
const override {
3277 probeRefAndDriveWithResult(
3278 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3279 return sim::AssocArraySetOp::create(rewriter, op.getLoc(), array,
3284 rewriter.eraseOp(op);
3289struct AssocArrayDeleteOpConversion
3291 using OpConversionPattern::OpConversionPattern;
3293 matchAndRewrite(AssocArrayDeleteOp op, OpAdaptor adaptor,
3294 ConversionPatternRewriter &rewriter)
const override {
3295 probeRefAndDriveWithResult(
3296 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3297 return sim::AssocArrayDeleteOp::create(rewriter, op.getLoc(), array,
3301 rewriter.eraseOp(op);
3306struct AssocArrayClearOpConversion
3308 using OpConversionPattern::OpConversionPattern;
3310 matchAndRewrite(AssocArrayClearOp op, OpAdaptor adaptor,
3311 ConversionPatternRewriter &rewriter)
const override {
3312 auto refType = cast<llhd::RefType>(adaptor.getAssocArray().getType());
3313 Value emptyArray = sim::AssocArrayEmptyOp::create(rewriter, op->getLoc(),
3314 refType.getNestedType());
3315 Value delay = llhd::ConstantTimeOp::create(
3316 rewriter, op.getLoc(),
3317 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3318 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getAssocArray(),
3319 emptyArray, delay, Value{});
3320 rewriter.eraseOp(op);
3325struct AssocArraySizeOpConversion
3327 using OpConversionPattern::OpConversionPattern;
3329 matchAndRewrite(AssocArraySizeOp op, OpAdaptor adaptor,
3330 ConversionPatternRewriter &rewriter)
const override {
3332 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3333 rewriter.replaceOpWithNewOp<sim::AssocArraySizeOp>(op, array);
3338struct AssocArrayExistsOpConversion
3340 using OpConversionPattern::OpConversionPattern;
3342 matchAndRewrite(AssocArrayExistsOp op, OpAdaptor adaptor,
3343 ConversionPatternRewriter &rewriter)
const override {
3345 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3346 rewriter.replaceOpWithNewOp<sim::AssocArrayExistsOp>(op, array,
3347 adaptor.getIndex());
3352template <
typename MooreOpTy,
typename SimOpTy>
3355 using OpAdaptor =
typename MooreOpTy::Adaptor;
3357 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3358 ConversionPatternRewriter &rewriter)
const override {
3360 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3361 auto endpointOp = SimOpTy::create(rewriter, op.getLoc(), array);
3363 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3366 comb::ICmpOp::create(rewriter, op.getLoc(), comb::ICmpPredicate::ne,
3367 endpointOp->getResult(0), zero,
false);
3369 comb::MuxOp::create(rewriter, op.getLoc(), foundBit,
3370 endpointOp->getResult(1), curIndex,
false);
3371 Value delay = llhd::ConstantTimeOp::create(
3372 rewriter, op.getLoc(),
3373 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3374 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(), newIndex,
3376 rewriter.replaceOp(op, endpointOp->getResult(0));
3381template <
typename MooreOpTy,
typename SimOpTy>
3384 using OpAdaptor =
typename MooreOpTy::Adaptor;
3386 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3387 ConversionPatternRewriter &rewriter)
const override {
3389 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3391 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3392 auto stepOp = SimOpTy::create(rewriter, op.getLoc(), array, curIndex);
3393 Value delay = llhd::ConstantTimeOp::create(
3394 rewriter, op.getLoc(),
3395 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3396 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(),
3397 stepOp->getResult(1), delay, Value{});
3398 rewriter.replaceOp(op, stepOp->getResult(0));
3403using AssocArrayFirstOpConversion =
3404 AssocArrayEndpointOpConversion<AssocArrayFirstOp, sim::AssocArrayFirstOp>;
3405using AssocArrayLastOpConversion =
3406 AssocArrayEndpointOpConversion<AssocArrayLastOp, sim::AssocArrayLastOp>;
3407using AssocArrayNextOpConversion =
3408 AssocArrayStepOpConversion<AssocArrayNextOp, sim::AssocArrayNextOp>;
3409using AssocArrayPrevOpConversion =
3410 AssocArrayStepOpConversion<AssocArrayPrevOp, sim::AssocArrayPrevOp>;
3413 using OpConversionPattern::OpConversionPattern;
3416 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
3417 ConversionPatternRewriter &rewriter)
const override {
3418 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3419 op, adaptor.getMessage());
3425 using OpConversionPattern::OpConversionPattern;
3427 matchAndRewrite(FDisplayBIOp op, OpAdaptor adaptor,
3428 ConversionPatternRewriter &rewriter)
const override {
3429 auto stream = sim::SVChannelToOutputStreamOp::create(rewriter, op.getLoc(),
3431 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3432 op, adaptor.getMessage(), stream.getStream());
3438 using OpConversionPattern::OpConversionPattern;
3440 matchAndRewrite(FOpenBIOp op, OpAdaptor adaptor,
3441 ConversionPatternRewriter &rewriter)
const override {
3442 sim::SVFOpenModeAttr simMode;
3443 if (
auto modeAttr = op.getModeAttr()) {
3444 auto mapMode = [](moore::FOpenMode m) -> sim::SVFOpenMode {
3446 case moore::FOpenMode::Read:
3447 return sim::SVFOpenMode::Read;
3448 case moore::FOpenMode::Write:
3449 return sim::SVFOpenMode::Write;
3450 case moore::FOpenMode::Append:
3451 return sim::SVFOpenMode::Append;
3452 case moore::FOpenMode::ReadUpdate:
3453 return sim::SVFOpenMode::ReadUpdate;
3454 case moore::FOpenMode::WriteUpdate:
3455 return sim::SVFOpenMode::WriteUpdate;
3456 case moore::FOpenMode::AppendUpdate:
3457 return sim::SVFOpenMode::AppendUpdate;
3459 llvm_unreachable(
"unknown FOpenMode");
3461 simMode = sim::SVFOpenModeAttr::get(op.getContext(),
3462 mapMode(modeAttr.getValue()));
3464 rewriter.replaceOpWithNewOp<sim::SVFOpenOp>(op, adaptor.getFilename(),
3470struct PlusArgsTestBIOpConversion
3472 using OpConversionPattern::OpConversionPattern;
3474 matchAndRewrite(PlusArgsTestBIOp op, OpAdaptor adaptor,
3475 ConversionPatternRewriter &rewriter)
const override {
3476 rewriter.replaceOpWithNewOp<sim::PlusArgsTestOp>(op, rewriter.getI1Type(),
3477 op.getFormatStringAttr());
3482struct PlusArgsValueBIOpConversion
3484 using OpConversionPattern::OpConversionPattern;
3486 matchAndRewrite(PlusArgsValueBIOp op, OpAdaptor adaptor,
3487 ConversionPatternRewriter &rewriter)
const override {
3488 auto resultType = typeConverter->convertType(op.getResult().getType());
3490 return rewriter.notifyMatchFailure(op,
"unsupported result type");
3491 rewriter.replaceOpWithNewOp<sim::PlusArgsValueOp>(
3492 op, rewriter.getI1Type(), resultType, op.getFormatStringAttr());
3498 using OpConversionPattern::OpConversionPattern;
3501 matchAndRewrite(FCloseBIOp op, OpAdaptor adaptor,
3502 ConversionPatternRewriter &rewriter)
const override {
3503 rewriter.replaceOpWithNewOp<sim::SVFCloseOp>(op, adaptor.getFd());
3509 using OpConversionPattern::OpConversionPattern;
3512 matchAndRewrite(FFlushBIOp op, OpAdaptor adaptor,
3513 ConversionPatternRewriter &rewriter)
const override {
3514 if (!adaptor.getFd()) {
3515 rewriter.replaceOpWithNewOp<sim::SVFFlushAllOp>(op);
3517 auto stream = sim::SVChannelToOutputStreamOp::create(
3518 rewriter, op.getLoc(), adaptor.getFd());
3519 rewriter.replaceOpWithNewOp<sim::FlushOp>(op, stream);
3526 using OpConversionPattern::OpConversionPattern;
3529 matchAndRewrite(StringCmpOp op, OpAdaptor adaptor,
3530 ConversionPatternRewriter &rewriter)
const override {
3531 sim::StringCmpPredicate pred;
3532 switch (op.getPredicate()) {
3533 case moore::StringCmpPredicate::eq:
3534 pred = sim::StringCmpPredicate::eq;
3536 case moore::StringCmpPredicate::ne:
3537 pred = sim::StringCmpPredicate::ne;
3539 case moore::StringCmpPredicate::lt:
3540 pred = sim::StringCmpPredicate::lt;
3542 case moore::StringCmpPredicate::le:
3543 pred = sim::StringCmpPredicate::le;
3545 case moore::StringCmpPredicate::gt:
3546 pred = sim::StringCmpPredicate::gt;
3548 case moore::StringCmpPredicate::ge:
3549 pred = sim::StringCmpPredicate::ge;
3552 rewriter.replaceOpWithNewOp<sim::StringCmpOp>(op, pred, adaptor.getLhs(),
3559 using OpConversionPattern::OpConversionPattern;
3562 matchAndRewrite(ReadMemBIOp op, OpAdaptor adaptor,
3563 ConversionPatternRewriter &rewriter)
const override {
3564 auto loc = op.getLoc();
3565 Value memory = llhd::ProbeOp::create(rewriter, loc, adaptor.getDest());
3566 Value loaded = sim::SVReadMemOp::create(
3567 rewriter, loc, memory.getType(), adaptor.getFilename(), memory,
3568 rewriter.getBoolAttr(op.getBase() == MemBase::Binary),
3569 adaptor.getStartAddr(), adaptor.getFinishAddr(), adaptor.getSliceLeft(),
3570 adaptor.getSliceRight(), op.getDimLowsAttr(), op.getDimDescendingAttr(),
3571 op.getEnumValuesAttr());
3572 Value delay = llhd::ConstantTimeOp::create(
3574 llhd::TimeAttr::get(rewriter.getContext(), 0U,
"ns", 0, 1));
3575 rewriter.replaceOpWithNewOp<llhd::DriveOp>(op, adaptor.getDest(), loaded,
3588static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
3589 ConversionPatternRewriter &rewriter) {
3590 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
3595static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
3596 ConversionPatternRewriter &rewriter) {
3597 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
3603static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
3604 ConversionPatternRewriter &rewriter) {
3606 std::string severityString;
3608 switch (op.getSeverity()) {
3609 case (Severity::Fatal):
3610 severityString =
"Fatal: ";
3612 case (Severity::Error):
3613 severityString =
"Error: ";
3615 case (Severity::Warning):
3616 severityString =
"Warning: ";
3618 case (Severity::Info):
3619 severityString =
"Info: ";
3624 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
3625 auto message = sim::FormatStringConcatOp::create(
3626 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
3627 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
3641 UrandomRangeBIOp::Adaptor adaptor,
3642 ConversionPatternRewriter &rewriter,
3643 FunctionCache &funcCache) {
3644 auto loc = op.getLoc();
3645 auto i32Ty = rewriter.getI32Type();
3646 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
3647 auto fn = funcCache.getOrCreate(rewriter,
"__circt_urandom_range",
3648 {i32Ty, i32Ty, ptrTy}, {i32Ty});
3651 if (
auto seedRef = adaptor.getSeed()) {
3654 seedPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, i32Ty, one);
3655 auto seedVal = llhd::ProbeOp::create(rewriter, loc, seedRef);
3656 LLVM::StoreOp::create(rewriter, loc, seedVal, seedPtr);
3658 seedPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
3661 auto call = func::CallOp::create(
3663 ValueRange{adaptor.getMinval(), adaptor.getMaxval(), seedPtr});
3666 if (adaptor.getSeed()) {
3667 auto newSeed = LLVM::LoadOp::create(rewriter, loc, i32Ty, seedPtr);
3668 auto epsilon = llhd::ConstantTimeOp::create(
3670 llhd::TimeAttr::get(rewriter.getContext(), 0,
"ns", 0, 1));
3671 llhd::DriveOp::create(rewriter, loc, adaptor.getSeed(), newSeed, epsilon,
3675 rewriter.replaceOp(op, call.getResult(0));
3681 FinishMessageBIOp::Adaptor adaptor,
3682 ConversionPatternRewriter &rewriter) {
3684 rewriter.eraseOp(op);
3693static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
3694 ConversionPatternRewriter &rewriter) {
3695 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
3700static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
3701 ConversionPatternRewriter &rewriter) {
3702 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
3707static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
3708 ConversionPatternRewriter &rewriter) {
3709 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
3718 const TypeConverter &converter) {
3719 target.addIllegalDialect<MooreDialect>();
3720 target.addLegalDialect<comb::CombDialect>();
3721 target.addLegalDialect<hw::HWDialect>();
3722 target.addLegalDialect<seq::SeqDialect>();
3723 target.addLegalDialect<llhd::LLHDDialect>();
3724 target.addLegalDialect<ltl::LTLDialect>();
3725 target.addLegalDialect<mlir::BuiltinDialect>();
3726 target.addLegalDialect<mlir::math::MathDialect>();
3727 target.addLegalDialect<sim::SimDialect>();
3728 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3729 target.addLegalDialect<mlir::ub::UBDialect>();
3730 target.addLegalDialect<verif::VerifDialect>();
3731 target.addLegalDialect<arith::ArithDialect>();
3733 target.addLegalOp<debug::ScopeOp>();
3735 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
3736 UnrealizedConversionCastOp, hw::OutputOp,
3737 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
3738 debug::VariableOp, arith::SelectOp>(
3739 [&](Operation *op) {
return converter.isLegal(op); });
3741 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
3742 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
3743 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
3746 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
3747 return converter.isSignatureLegal(op.getFunctionType());
3751 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
3752 converter.isLegal(&op.getBody());
3757 typeConverter.addConversion([&](IntType type) {
3758 return IntegerType::get(type.getContext(), type.getWidth());
3761 typeConverter.addConversion([&](RealType type) -> mlir::Type {
3762 MLIRContext *ctx = type.getContext();
3763 switch (type.getWidth()) {
3764 case moore::RealWidth::f32:
3765 return mlir::Float32Type::get(ctx);
3766 case moore::RealWidth::f64:
3767 return mlir::Float64Type::get(ctx);
3771 typeConverter.addConversion(
3772 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
3774 typeConverter.addConversion([&](FormatStringType type) {
3775 return sim::FormatStringType::get(type.getContext());
3778 typeConverter.addConversion([&](StringType type) {
3779 return sim::DynamicStringType::get(type.getContext());
3782 typeConverter.addConversion([&](QueueType type) {
3783 return sim::QueueType::get(type.getContext(),
3784 typeConverter.convertType(type.getElementType()),
3788 typeConverter.addConversion([&](sim::QueueType type) -> std::optional<Type> {
3789 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3790 return sim::QueueType::get(type.getContext(),
elementType,
3795 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
3796 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3797 return hw::ArrayType::get(
elementType, type.getSize());
3801 typeConverter.addConversion([&](AssocArrayType type) -> std::optional<Type> {
3802 auto elementType = typeConverter.convertType(type.getElementType());
3803 auto indexType = typeConverter.convertType(type.getIndexType());
3806 return sim::AssocArrayType::get(type.getContext(),
elementType, indexType);
3812 typeConverter.addConversion(
3813 [&](UnpackedArrayType type) -> std::optional<Type> {
3814 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3815 return hw::ArrayType::get(
elementType, type.getSize());
3819 typeConverter.addConversion([&](OpenArrayType type) -> std::optional<Type> {
3820 return LLVM::LLVMPointerType::get(type.getContext());
3823 typeConverter.addConversion(
3824 [&](OpenUnpackedArrayType type) -> std::optional<Type> {
3825 return LLVM::LLVMPointerType::get(type.getContext());
3828 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
3829 SmallVector<hw::StructType::FieldInfo> fields;
3830 for (
auto field : type.getMembers()) {
3831 hw::StructType::FieldInfo info;
3832 info.type = typeConverter.convertType(field.type);
3835 info.name = field.name;
3836 fields.push_back(info);
3838 return hw::StructType::get(type.getContext(), fields);
3846 typeConverter.addConversion(
3847 [&](UnpackedStructType type) -> std::optional<Type> {
3848 SmallVector<hw::StructType::FieldInfo> fields;
3849 for (
auto field : type.getMembers()) {
3850 hw::StructType::FieldInfo info;
3851 info.type = typeConverter.convertType(field.type);
3854 info.name = field.name;
3855 fields.push_back(info);
3857 return hw::StructType::get(type.getContext(), fields);
3861 typeConverter.addConversion([&](UnionType type) -> std::optional<Type> {
3862 SmallVector<hw::UnionType::FieldInfo> fields;
3863 for (
auto field : type.getMembers()) {
3864 hw::UnionType::FieldInfo info;
3865 info.type = typeConverter.convertType(field.type);
3868 info.name = field.name;
3870 fields.push_back(info);
3872 auto result = hw::UnionType::get(type.getContext(), fields);
3877 typeConverter.addConversion(
3878 [&](UnpackedUnionType type) -> std::optional<Type> {
3879 SmallVector<hw::UnionType::FieldInfo> fields;
3880 for (
auto field : type.getMembers()) {
3881 hw::UnionType::FieldInfo info;
3882 info.type = typeConverter.convertType(field.type);
3885 info.name = field.name;
3887 fields.push_back(info);
3889 return hw::UnionType::get(type.getContext(), fields);
3893 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
3894 return LLVM::LLVMPointerType::get(type.getContext());
3898 typeConverter.addConversion(
3899 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
3902 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
3903 return LLVM::LLVMPointerType::get(type.getContext());
3907 typeConverter.addConversion([&](NullType type) -> std::optional<Type> {
3908 return LLVM::LLVMPointerType::get(type.getContext());
3911 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
3912 if (isa<OpenArrayType, OpenUnpackedArrayType>(type.getNestedType()))
3913 return LLVM::LLVMPointerType::get(type.getContext());
3914 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3915 return llhd::RefType::get(innerType);
3920 typeConverter.addConversion([](IntegerType type) {
return type; });
3921 typeConverter.addConversion([](FloatType type) {
return type; });
3922 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
3923 typeConverter.addConversion([](sim::FormatStringType type) {
return type; });
3924 typeConverter.addConversion([](sim::AssocArrayType type) {
return type; });
3925 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
3926 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
3927 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
3928 typeConverter.addConversion([](debug::StructType type) {
return type; });
3930 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
3931 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3932 return llhd::RefType::get(innerType);
3936 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
3937 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3938 return hw::ArrayType::get(
elementType, type.getNumElements());
3942 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
3943 SmallVector<hw::StructType::FieldInfo> fields;
3944 for (
auto field : type.getElements()) {
3945 hw::StructType::FieldInfo info;
3946 info.type = typeConverter.convertType(field.type);
3949 info.name = field.name;
3950 fields.push_back(info);
3952 return hw::StructType::get(type.getContext(), fields);
3955 typeConverter.addConversion([&](hw::UnionType type) -> std::optional<Type> {
3956 SmallVector<hw::UnionType::FieldInfo> fields;
3957 for (
auto field : type.getElements()) {
3958 hw::UnionType::FieldInfo info;
3959 info.type = typeConverter.convertType(field.type);
3962 info.name = field.name;
3963 info.offset = field.offset;
3964 fields.push_back(info);
3966 return hw::UnionType::get(type.getContext(), fields);
3969 typeConverter.addTargetMaterialization(
3970 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3971 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3972 if (inputs.size() != 1 || !inputs[0])
3974 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3979 typeConverter.addSourceMaterialization(
3980 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3981 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3982 if (inputs.size() != 1)
3984 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3991 TypeConverter &typeConverter,
3992 ClassTypeCache &classCache,
3993 FunctionCache &funcCache) {
3998 classCache, funcCache);
3999 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
4000 patterns.getContext(), classCache);
4004 ClassUpcastOpConversion,
4007 VariableOpConversion,
4011 ConversionOpConversion,
4012 BitcastConversion<PackedToSBVOp>,
4013 BitcastConversion<SBVToPackedOp>,
4014 NoOpConversion<LogicToIntOp>,
4015 NoOpConversion<IntToLogicOp>,
4016 NoOpConversion<ToBuiltinIntOp>,
4017 NoOpConversion<FromBuiltinIntOp>,
4021 SIntToRealOpConversion,
4022 UIntToRealOpConversion,
4023 IntToStringOpConversion,
4024 StringToIntOpConversion,
4025 FormatStringToStringOpConversion,
4026 RealToIntOpConversion,
4027 ConvertRealOpConversion,
4028 RealBitcastOpConversion<RealtobitsBIOp>,
4029 RealBitcastOpConversion<BitstorealBIOp>,
4030 RealBitcastOpConversion<ShortrealtobitsBIOp>,
4031 RealBitcastOpConversion<BitstoshortrealBIOp>,
4037 ReplicateOpConversion,
4039 ExtractOpConversion,
4040 DynExtractOpConversion,
4041 DynExtractRefOpConversion,
4043 StructExtractOpConversion,
4044 StructExtractRefOpConversion,
4045 ExtractRefOpConversion,
4046 StructCreateOpConversion,
4047 UnionCreateOpConversion,
4048 UnionExtractOpConversion,
4049 UnionExtractRefOpConversion,
4050 ConditionalOpConversion,
4051 ArrayCreateOpConversion,
4052 UArrayCmpOpConversion,
4055 ConstantStringOpConv,
4058 ReduceAndOpConversion,
4059 ReduceOrOpConversion,
4060 ReduceXorOpConversion,
4061 BoolCastOpConversion,
4066 BinaryOpConversion<AddOp, comb::AddOp>,
4067 BinaryOpConversion<SubOp, comb::SubOp>,
4068 BinaryOpConversion<MulOp, comb::MulOp>,
4069 BinaryOpConversion<DivUOp, comb::DivUOp>,
4070 BinaryOpConversion<DivSOp, comb::DivSOp>,
4071 BinaryOpConversion<ModUOp, comb::ModUOp>,
4072 BinaryOpConversion<ModSOp, comb::ModSOp>,
4073 BinaryOpConversion<AndOp, comb::AndOp>,
4074 BinaryOpConversion<OrOp, comb::OrOp>,
4075 BinaryOpConversion<XorOp, comb::XorOp>,
4078 NegRealOpConversion,
4081 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
4082 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
4083 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
4084 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
4085 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
4088 RealMathFunc<LnBIOp, math::LogOp>,
4089 RealMathFunc<Log10BIOp, math::Log10Op>,
4090 RealMathFunc<ExpBIOp, math::ExpOp>,
4091 RealMathFunc<SqrtBIOp, math::SqrtOp>,
4092 BinaryRealOpConversion<MinBIOp, arith::MinimumFOp>,
4093 BinaryRealOpConversion<MaxBIOp, arith::MaximumFOp>,
4094 RealMathFunc<AbsBIOp, math::AbsFOp>,
4095 RealMathFunc<FloorBIOp, math::FloorOp>,
4096 RealMathFunc<CeilBIOp, math::CeilOp>,
4097 RealMathFunc<SinBIOp, math::SinOp>,
4098 RealMathFunc<CosBIOp, math::CosOp>,
4099 RealMathFunc<TanBIOp, math::TanOp>,
4100 RealMathFunc<AsinBIOp, math::AsinOp>,
4101 RealMathFunc<AcosBIOp, math::AcosOp>,
4102 RealMathFunc<AtanBIOp, math::AtanOp>,
4103 BinaryRealOpConversion<Atan2BIOp, math::Atan2Op>,
4104 HypotBIOpConversion,
4105 RealMathFunc<SinhBIOp, math::SinhOp>,
4106 RealMathFunc<CoshBIOp, math::CoshOp>,
4107 RealMathFunc<TanhBIOp, math::TanhOp>,
4108 RealMathFunc<AsinhBIOp, math::AsinhOp>,
4109 RealMathFunc<AcoshBIOp, math::AcoshOp>,
4110 RealMathFunc<AtanhBIOp, math::AtanhOp>,
4113 PowUOpConversion, PowSOpConversion,
4114 Clog2BIOpConversion,
4117 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
4118 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
4119 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
4120 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
4121 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
4122 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
4123 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
4124 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
4125 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
4126 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
4127 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
4128 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
4129 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
4130 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
4131 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::UNE>,
4132 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
4133 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
4134 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
4135 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
4136 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
4137 CaseXZEqOpConversion<CaseZEqOp, true>,
4138 CaseXZEqOpConversion<CaseXZEqOp, false>,
4139 HandleCmpOpConversion<HandleEqOp, LLVM::ICmpPredicate::eq>,
4140 HandleCmpOpConversion<HandleNeOp, LLVM::ICmpPredicate::ne>,
4143 SVModuleOpConversion,
4144 InstanceOpConversion,
4145 ProcedureOpConversion,
4146 CoroutineOpConversion,
4147 CallCoroutineOpConversion,
4148 WaitEventOpConversion,
4156 AssignOpConversion<ContinuousAssignOp>,
4157 AssignOpConversion<DelayedContinuousAssignOp>,
4158 AssignOpConversion<BlockingAssignOp>,
4159 AssignOpConversion<NonBlockingAssignOp>,
4160 AssignOpConversion<DelayedNonBlockingAssignOp>,
4161 AssignedVariableOpConversion,
4164 HWInstanceOpConversion,
4167 DPIFuncOpConversion,
4168 FuncDPICallOpConversion,
4169 UnrealizedConversionCastConversion,
4170 InPlaceOpConversion<debug::ArrayOp>,
4171 InPlaceOpConversion<debug::StructOp>,
4172 InPlaceOpConversion<debug::VariableOp>,
4175 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
4176 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
4177 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
4180 FormatLiteralOpConversion,
4181 FormatStringOpConversion,
4182 FormatConcatOpConversion,
4183 FormatHierPathOpConversion,
4184 FormatIntOpConversion,
4185 FormatRealOpConversion,
4186 FormatCharOpConversion,
4187 DisplayBIOpConversion,
4188 FDisplayBIOpConversion,
4191 FOpenBIOpConversion,
4192 FCloseBIOpConversion,
4193 FFlushBIOpConversion,
4194 ReadMemBIOpConversion,
4197 PlusArgsTestBIOpConversion,
4198 PlusArgsValueBIOpConversion,
4201 StringLenOpConversion,
4202 StringConcatOpConversion,
4203 StringGetOpConversion,
4204 StringCmpOpConversion,
4207 QueueSizeBIOpConversion,
4208 QueuePushBackOpConversion,
4209 QueuePushFrontOpConversion,
4210 QueuePopBackOpConversion,
4211 QueuePopFrontOpConversion,
4212 QueueDeleteOpConversion,
4213 QueueInsertOpConversion,
4214 QueueClearOpConversion,
4215 DynQueueExtractOpConversion,
4216 QueueResizeOpConversion,
4217 QueueSetOpConversion,
4218 QueueCmpOpConversion,
4219 QueueFromUnpackedArrayOpConversion,
4220 QueueConcatOpConversion,
4223 AssocArrayExtractOpConversion,
4224 AssocArraySetOpConversion,
4225 AssocArrayDeleteOpConversion,
4226 AssocArrayClearOpConversion,
4227 AssocArraySizeOpConversion,
4228 AssocArrayExistsOpConversion,
4229 AssocArrayFirstOpConversion,
4230 AssocArrayLastOpConversion,
4231 AssocArrayNextOpConversion,
4232 AssocArrayPrevOpConversion
4233 >(typeConverter,
patterns.getContext());
4256 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
4258 hw::populateHWModuleLikeTypeConversionPattern(
4259 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
4260 populateSCFToControlFlowConversionPatterns(
patterns);
4269struct MooreToCorePass
4270 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
4271 void runOnOperation()
override;
4277 return std::make_unique<MooreToCorePass>();
4281void MooreToCorePass::runOnOperation() {
4282 MLIRContext &
context = getContext();
4283 ModuleOp
module = getOperation();
4284 ClassTypeCache classCache;
4285 auto &symbolTable = getAnalysis<SymbolTable>();
4286 FunctionCache funcCache(symbolTable);
4288 IRRewriter rewriter(module);
4289 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
4291 TypeConverter typeConverter;
4294 ConversionTarget target(
context);
4299 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
4302 if (failed(applyFullConversion(module, target, std::move(
patterns))))
4303 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...
create(elements, Type result_type=None)
create(elements, Type result_type=None)
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.