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();
1401 auto loc = op.getLoc();
1404 if (isa<IntegerType>(inputType)) {
1405 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1406 int32_t resultWidth = hw::getBitWidth(resultType);
1407 if (resultWidth < 0)
1410 int32_t high = low + resultWidth;
1411 int32_t lsbPad = std::clamp(-low, 0, resultWidth);
1412 int32_t msbPad = std::clamp(high - inputWidth, 0, resultWidth - lsbPad);
1413 int32_t extractWidth = resultWidth - lsbPad - msbPad;
1415 SmallVector<Value> sbv;
1419 if (extractWidth > 0)
1421 loc, rewriter.getIntegerType(extractWidth), input,
1428 if (res.getType() != resultType)
1429 res = rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, res);
1431 rewriter.replaceOp(op, res);
1436 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1438 int32_t idxWidth = llvm::Log2_64_Ceil(arrTy.getNumElements());
1439 int32_t inputWidth = arrTy.getNumElements();
1443 if (low < 0 || low >= inputWidth) {
1447 rewriter.replaceOp(op, zeros);
1452 rewriter.getIntegerType(idxWidth), low));
1458 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1459 resArrTy && resArrTy.getElementType() ==
elementType) {
1460 int32_t resultWidth = resArrTy.getNumElements();
1461 int32_t high = low + resultWidth;
1463 int32_t lsbPad = std::clamp(-low, 0, resultWidth);
1464 int32_t msbPad = std::clamp(high - inputWidth, 0, resultWidth - lsbPad);
1465 int32_t extractWidth = resultWidth - lsbPad - msbPad;
1467 SmallVector<Value> toConcat;
1473 toConcat.push_back(zeros);
1476 if (extractWidth > 0)
1478 loc, hw::ArrayType::get(
elementType, extractWidth), input,
1480 rewriter.getIntegerType(idxWidth),
1481 std::max(low, 0))));
1488 toConcat.push_back(zeros);
1502 using OpConversionPattern::OpConversionPattern;
1505 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1506 ConversionPatternRewriter &rewriter)
const override {
1508 Type resultType = typeConverter->convertType(op.getResult().getType());
1510 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1512 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1513 int64_t width = hw::getBitWidth(inputType);
1518 rewriter, op.getLoc(),
1519 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1520 adaptor.getLowBit());
1521 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1522 op, resultType, adaptor.getInput(), lowBit);
1526 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1528 rewriter, op.getLoc(),
1529 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1530 adaptor.getLowBit());
1534 if (arrType.getElementType() !=
1535 cast<llhd::RefType>(resultType).getNestedType()) {
1536 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1537 op, resultType, adaptor.getInput(), lowBit);
1541 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1551 using OpConversionPattern::OpConversionPattern;
1554 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1555 ConversionPatternRewriter &rewriter)
const override {
1556 Type resultType = typeConverter->convertType(op.getResult().getType());
1557 Type inputType = adaptor.getInput().getType();
1559 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1560 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1561 intType.getWidth(), op->getLoc());
1562 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1563 adaptor.getInput(), amount);
1565 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1569 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1570 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1571 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1574 bool isSingleElementExtract = arrType.getElementType() == resultType;
1576 if (isSingleElementExtract)
1577 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1581 adaptor.getInput(), idx);
1591 using OpConversionPattern::OpConversionPattern;
1594 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1595 ConversionPatternRewriter &rewriter)
const override {
1597 Type resultType = typeConverter->convertType(op.getResult().getType());
1599 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1601 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1602 int64_t width = hw::getBitWidth(inputType);
1607 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1608 llvm::Log2_64_Ceil(width), op->getLoc());
1609 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1610 op, resultType, adaptor.getInput(), amount);
1614 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1615 Value idx = adjustIntegerWidth(
1616 rewriter, adaptor.getLowBit(),
1617 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1619 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1620 bool isSingleElementExtract =
1621 arrType.getElementType() == resultNestedType;
1623 if (isSingleElementExtract)
1624 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1627 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1628 op, resultType, adaptor.getInput(), idx);
1638 using OpConversionPattern::OpConversionPattern;
1641 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1642 ConversionPatternRewriter &rewriter)
const override {
1643 Type resultType = typeConverter->convertType(op.getResult().getType());
1645 adaptor.getElements());
1651 using OpConversionPattern::OpConversionPattern;
1654 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1655 ConversionPatternRewriter &rewriter)
const override {
1656 Type resultType = typeConverter->convertType(op.getResult().getType());
1658 adaptor.getFields());
1664 using OpConversionPattern::OpConversionPattern;
1667 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1668 ConversionPatternRewriter &rewriter)
const override {
1670 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1675struct StructExtractRefOpConversion
1677 using OpConversionPattern::OpConversionPattern;
1680 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1681 ConversionPatternRewriter &rewriter)
const override {
1682 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1683 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1689 using OpConversionPattern::OpConversionPattern;
1692 matchAndRewrite(UnionCreateOp op, OpAdaptor adaptor,
1693 ConversionPatternRewriter &rewriter)
const override {
1694 Type resultType = typeConverter->convertType(op.getResult().getType());
1695 rewriter.replaceOpWithNewOp<hw::UnionCreateOp>(
1696 op, resultType, adaptor.getFieldNameAttr(), adaptor.getInput());
1702 using OpConversionPattern::OpConversionPattern;
1705 matchAndRewrite(UnionExtractOp op, OpAdaptor adaptor,
1706 ConversionPatternRewriter &rewriter)
const override {
1707 rewriter.replaceOpWithNewOp<hw::UnionExtractOp>(op, adaptor.getInput(),
1708 adaptor.getFieldNameAttr());
1713struct UnionExtractRefOpConversion
1715 using OpConversionPattern::OpConversionPattern;
1718 matchAndRewrite(UnionExtractRefOp op, OpAdaptor adaptor,
1719 ConversionPatternRewriter &rewriter)
const override {
1720 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1721 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1727 using OpConversionPattern::OpConversionPattern;
1729 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1730 ConversionPatternRewriter &rewriter)
const override {
1731 Type resultType = typeConverter->convertType(op.getInput().getType());
1734 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1735 adaptor.getInput(), max);
1741 using OpConversionPattern::OpConversionPattern;
1743 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1744 ConversionPatternRewriter &rewriter)
const override {
1745 Type resultType = typeConverter->convertType(op.getInput().getType());
1748 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1749 adaptor.getInput(), zero);
1755 using OpConversionPattern::OpConversionPattern;
1757 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1758 ConversionPatternRewriter &rewriter)
const override {
1760 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1766 using OpConversionPattern::OpConversionPattern;
1768 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1769 ConversionPatternRewriter &rewriter)
const override {
1770 Type resultType = typeConverter->convertType(op.getInput().getType());
1771 if (isa_and_nonnull<IntegerType>(resultType)) {
1774 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1775 adaptor.getInput(), zero);
1778 if (isa_and_nonnull<FloatType>(resultType)) {
1779 Value zero = arith::ConstantOp::create(
1780 rewriter, op->getLoc(), rewriter.getFloatAttr(resultType, 0.0));
1781 rewriter.replaceOpWithNewOp<arith::CmpFOp>(op, arith::CmpFPredicate::ONE,
1782 adaptor.getInput(), zero);
1785 if (isa_and_nonnull<llhd::TimeType>(resultType)) {
1787 llhd::TimeToIntOp::create(rewriter, op->getLoc(), adaptor.getInput());
1789 rewriter.getI64Type(), 0);
1790 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1794 if (isa_and_nonnull<hw::StructType, hw::ArrayType, hw::UnionType>(
1796 int64_t width = hw::getBitWidth(resultType);
1799 auto intTy = rewriter.getIntegerType(width);
1800 Value input = rewriter.createOrFold<
hw::BitcastOp>(op->getLoc(), intTy,
1801 adaptor.getInput());
1803 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1812 using OpConversionPattern::OpConversionPattern;
1814 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1815 ConversionPatternRewriter &rewriter)
const override {
1817 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1820 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1826 using OpConversionPattern::OpConversionPattern;
1828 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1829 ConversionPatternRewriter &rewriter)
const override {
1831 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1834 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1840 using OpConversionPattern::OpConversionPattern;
1842 matchAndRewrite(NegRealOp op, OpAdaptor adaptor,
1843 ConversionPatternRewriter &rewriter)
const override {
1844 rewriter.replaceOpWithNewOp<arith::NegFOp>(op, adaptor.getInput());
1849template <
typename SourceOp,
typename TargetOp>
1852 using OpAdaptor =
typename SourceOp::Adaptor;
1855 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1856 ConversionPatternRewriter &rewriter)
const override {
1857 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1858 adaptor.getRhs(),
false);
1863template <
typename SourceOp,
typename TargetOp>
1866 using OpAdaptor =
typename SourceOp::Adaptor;
1869 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1870 ConversionPatternRewriter &rewriter)
const override {
1871 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1878 using OpConversionPattern::OpConversionPattern;
1880 matchAndRewrite(HypotBIOp op, OpAdaptor adaptor,
1881 ConversionPatternRewriter &rewriter)
const override {
1882 Value lhs = adaptor.getLhs();
1883 Value rhs = adaptor.getRhs();
1884 ImplicitLocOpBuilder b(op->getLoc(), rewriter);
1885 auto left = arith::MulFOp::create(b, lhs, lhs);
1886 auto right = arith::MulFOp::create(b, rhs, rhs);
1887 auto sum = arith::AddFOp::create(b, left, right);
1888 auto out = math::SqrtOp::create(b, sum);
1889 rewriter.replaceOp(op, out);
1894template <
typename SourceOp,
typename TargetOp>
1897 using OpAdaptor =
typename SourceOp::Adaptor;
1900 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1901 ConversionPatternRewriter &rewriter)
const override {
1902 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getValue());
1907template <
typename SourceOp, ICmpPredicate pred>
1910 using OpAdaptor =
typename SourceOp::Adaptor;
1913 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1914 ConversionPatternRewriter &rewriter)
const override {
1916 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1918 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1919 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1925 using OpConversionPattern::OpConversionPattern;
1928 matchAndRewrite(NullOp op, OpAdaptor adaptor,
1929 ConversionPatternRewriter &rewriter)
const override {
1930 Type ptrTy = getTypeConverter()->convertType(op.getResult().getType());
1932 return rewriter.notifyMatchFailure(op,
"failed to convert null type");
1933 rewriter.replaceOpWithNewOp<LLVM::ZeroOp>(op, ptrTy);
1938template <
typename SourceOp, LLVM::ICmpPredicate pred>
1941 using OpAdaptor =
typename SourceOp::Adaptor;
1944 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1945 ConversionPatternRewriter &rewriter)
const override {
1946 rewriter.replaceOpWithNewOp<LLVM::ICmpOp>(op, pred, adaptor.getLhs(),
1952template <
typename SourceOp, arith::CmpFPredicate pred>
1955 using OpAdaptor =
typename SourceOp::Adaptor;
1958 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1959 ConversionPatternRewriter &rewriter)
const override {
1961 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1963 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1964 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1969template <
typename SourceOp,
bool withoutX>
1972 using OpAdaptor =
typename SourceOp::Adaptor;
1975 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1976 ConversionPatternRewriter &rewriter)
const override {
1982 unsigned bitWidth = op.getLhs().getType().getWidth();
1983 auto ignoredBits = APInt::getZero(bitWidth);
1984 auto detectIgnoredBits = [&](Value value) {
1985 auto constOp = value.getDefiningOp<ConstantOp>();
1988 auto constValue = constOp.getValue();
1990 ignoredBits |= constValue.getZBits();
1992 ignoredBits |= constValue.getUnknownBits();
1994 detectIgnoredBits(op.getLhs());
1995 detectIgnoredBits(op.getRhs());
1999 Value lhs = adaptor.getLhs();
2000 Value rhs = adaptor.getRhs();
2001 if (!ignoredBits.isZero()) {
2002 ignoredBits.flipAllBits();
2004 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
2005 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
2008 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
2018 using OpConversionPattern::OpConversionPattern;
2021 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
2022 ConversionPatternRewriter &rewriter)
const override {
2023 Location loc = op.getLoc();
2024 Type resultType = typeConverter->convertType(op.getResult().getType());
2026 op.emitError(
"conversion result type is not currently supported");
2029 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
2030 int64_t resultBw = hw::getBitWidth(resultType);
2031 if (inputBw == -1 || resultBw == -1) {
2032 if (isSupportedDpiOpenArrayCast(op.getInput().getType(),
2033 op.getResult().getType())) {
2034 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2035 op, resultType, adaptor.getInput());
2038 if (hasOpenArrayBoundaryType(op.getInput().getType()) ||
2039 hasOpenArrayBoundaryType(op.getResult().getType())) {
2040 op.emitError(
"unsupported DPI open-array conversion from ")
2041 << op.getInput().getType() <<
" to " << op.getResult().getType();
2048 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
2049 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
2052 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
2053 rewriter.replaceOp(op, result);
2058template <
typename SourceOp>
2061 using OpAdaptor =
typename SourceOp::Adaptor;
2062 using ConversionPattern::typeConverter;
2065 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2066 ConversionPatternRewriter &rewriter)
const override {
2067 auto type = typeConverter->convertType(op.getResult().getType());
2068 if (type == adaptor.getInput().getType())
2069 rewriter.replaceOp(op, adaptor.getInput());
2071 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
2077template <
typename SourceOp>
2080 using OpAdaptor =
typename SourceOp::Adaptor;
2081 using ConversionPattern::typeConverter;
2084 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2085 ConversionPatternRewriter &rewriter)
const override {
2086 rewriter.replaceOp(op, adaptor.getInput());
2092 using OpConversionPattern::OpConversionPattern;
2095 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
2096 ConversionPatternRewriter &rewriter)
const override {
2097 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
2098 op.getType().getWidth());
2104 using OpConversionPattern::OpConversionPattern;
2107 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
2108 ConversionPatternRewriter &rewriter)
const override {
2109 auto targetWidth = op.getType().getWidth();
2110 auto inputWidth = op.getInput().getType().getWidth();
2113 rewriter, op.getLoc(),
2114 rewriter.getIntegerType(targetWidth - inputWidth), 0);
2117 op, ValueRange{zeroExt, adaptor.getInput()});
2123 using OpConversionPattern::OpConversionPattern;
2126 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
2127 ConversionPatternRewriter &rewriter)
const override {
2128 auto type = typeConverter->convertType(op.getType());
2130 comb::createOrFoldSExt(rewriter, op.getLoc(), adaptor.getInput(), type);
2131 rewriter.replaceOp(op, value);
2137 using OpConversionPattern::OpConversionPattern;
2140 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
2141 ConversionPatternRewriter &rewriter)
const override {
2142 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
2143 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2149 using OpConversionPattern::OpConversionPattern;
2152 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
2153 ConversionPatternRewriter &rewriter)
const override {
2154 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
2155 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2161 using OpConversionPattern::OpConversionPattern;
2164 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
2165 ConversionPatternRewriter &rewriter)
const override {
2166 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
2172 using OpConversionPattern::OpConversionPattern;
2175 matchAndRewrite(StringToIntOp op, OpAdaptor adaptor,
2176 ConversionPatternRewriter &rewriter)
const override {
2177 Type resultTy = typeConverter->convertType(op.getType());
2180 rewriter.replaceOpWithNewOp<sim::StringToIntOp>(op, resultTy,
2181 adaptor.getInput());
2186struct FormatStringToStringOpConversion
2188 using OpConversionPattern::OpConversionPattern;
2191 matchAndRewrite(FormatStringToStringOp op, OpAdaptor adaptor,
2192 ConversionPatternRewriter &rewriter)
const override {
2193 rewriter.replaceOpWithNewOp<sim::FormatToStringOp>(op,
2194 adaptor.getFmtstring());
2200 using OpConversionPattern::OpConversionPattern;
2203 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
2204 ConversionPatternRewriter &rewriter)
const override {
2205 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
2206 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2212 using OpConversionPattern::OpConversionPattern;
2215 matchAndRewrite(ConvertRealOp op, OpAdaptor adaptor,
2216 ConversionPatternRewriter &rewriter)
const override {
2217 op.getInput().getType().getWidth() < op.getResult().getType().getWidth()
2218 ? rewriter.replaceOpWithNewOp<arith::ExtFOp>(
2219 op, typeConverter->convertType(op.getType()), adaptor.getInput())
2220 : rewriter.replaceOpWithNewOp<arith::TruncFOp>(
2221 op, typeConverter->
convertType(op.getType()), adaptor.getInput());
2226template <
typename SourceOp>
2229 using OpAdaptor =
typename SourceOp::Adaptor;
2232 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2233 ConversionPatternRewriter &rewriter)
const override {
2235 ConversionPattern::typeConverter->convertType(op.getResult().getType());
2236 rewriter.replaceOpWithNewOp<arith::BitcastOp>(op, resultTy,
2237 adaptor.getValue());
2247 using OpConversionPattern::OpConversionPattern;
2250 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
2251 ConversionPatternRewriter &rewriter)
const override {
2252 SmallVector<Type> convResTypes;
2253 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2256 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
2257 op, convResTypes, op.getInstanceName(), op.getModuleName(),
2258 adaptor.getOperands(), op.getArgNames(),
2259 op.getResultNames(),
2260 rewriter.getArrayAttr({}),
nullptr);
2267 using OpConversionPattern::OpConversionPattern;
2270 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
2271 ConversionPatternRewriter &rewriter)
const override {
2272 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
2278 using OpConversionPattern::OpConversionPattern;
2281 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
2282 ConversionPatternRewriter &rewriter)
const override {
2283 SmallVector<Type> convResTypes;
2284 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2286 rewriter.replaceOpWithNewOp<func::CallOp>(
2287 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
2292struct FuncDPICallOpConversion
2294 using OpConversionPattern::OpConversionPattern;
2297 matchAndRewrite(moore::FuncDPICallOp op, OpAdaptor adaptor,
2298 ConversionPatternRewriter &rewriter)
const override {
2299 SmallVector<Type> convResTypes;
2300 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2302 rewriter.replaceOpWithNewOp<sim::DPICallOp>(
2303 op, convResTypes, op.getCalleeAttr(), Value(),
2304 Value(), adaptor.getInputs());
2310 using OpConversionPattern::OpConversionPattern;
2313 matchAndRewrite(moore::DPIFuncOp op, OpAdaptor adaptor,
2314 ConversionPatternRewriter &rewriter)
const override {
2316 auto toDPIDir = [](moore::DPIArgDirection dir) -> sim::DPIDirection {
2318 case moore::DPIArgDirection::In:
2319 return sim::DPIDirection::Input;
2320 case moore::DPIArgDirection::Out:
2321 return sim::DPIDirection::Output;
2322 case moore::DPIArgDirection::InOut:
2323 return sim::DPIDirection::InOut;
2324 case moore::DPIArgDirection::Return:
2325 return sim::DPIDirection::Return;
2327 llvm_unreachable(
"unknown DPIArgDirection");
2331 auto dirs = op.getDpiArgDirs();
2332 auto names = op.getDpiArgNames();
2333 SmallVector<Type> argTypes;
2334 op.getDPIArgTypes(argTypes);
2336 SmallVector<sim::DPIArgument> dpiArguments;
2337 for (
auto [dirAttr, nameAttr, mooreType] :
2338 llvm::zip(dirs, names, argTypes)) {
2339 auto dir = toDPIDir(cast<moore::DPIArgDirectionAttr>(dirAttr).getValue());
2340 auto name = cast<StringAttr>(nameAttr);
2341 Type coreType = typeConverter->convertType(mooreType);
2343 return op.emitOpError(
"argument '")
2344 << name <<
"' has unsupported type " << mooreType;
2345 dpiArguments.push_back({name, coreType, dir});
2348 auto coreDPIFuncType =
2349 sim::DPIFunctionType::get(rewriter.getContext(), dpiArguments);
2350 auto simFunc = sim::DPIFuncOp::create(
2351 rewriter, op.getLoc(), op.getSymNameAttr(), coreDPIFuncType,
2352 op.getArgumentLocsAttr(), op.getVerilogNameAttr());
2353 SymbolTable::setSymbolVisibility(simFunc,
2354 SymbolTable::getSymbolVisibility(op));
2355 rewriter.eraseOp(op);
2360struct UnrealizedConversionCastConversion
2362 using OpConversionPattern::OpConversionPattern;
2365 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
2366 ConversionPatternRewriter &rewriter)
const override {
2367 SmallVector<Type> convResTypes;
2368 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2373 if (convResTypes == adaptor.getOperands().getTypes()) {
2374 rewriter.replaceOp(op, adaptor.getOperands());
2378 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2379 op, convResTypes, adaptor.getOperands());
2385 using OpConversionPattern::OpConversionPattern;
2388 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
2389 ConversionPatternRewriter &rewriter)
const override {
2390 Type resultType = typeConverter->convertType(op.getResult().getType());
2394 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2395 resultType.getIntOrFloatBitWidth(), op->getLoc());
2396 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
2403 using OpConversionPattern::OpConversionPattern;
2406 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
2407 ConversionPatternRewriter &rewriter)
const override {
2408 Type resultType = typeConverter->convertType(op.getResult().getType());
2412 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2413 resultType.getIntOrFloatBitWidth(), op->getLoc());
2415 op, resultType, adaptor.getValue(), amount,
false);
2421 using OpConversionPattern::OpConversionPattern;
2424 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
2425 ConversionPatternRewriter &rewriter)
const override {
2426 Type resultType = typeConverter->convertType(op.getResult().getType());
2428 Location loc = op->getLoc();
2433 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
2434 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
2437 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
2445 using OpConversionPattern::OpConversionPattern;
2448 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
2449 ConversionPatternRewriter &rewriter)
const override {
2450 Type resultType = typeConverter->convertType(op.getResult().getType());
2454 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
2455 op, resultType, adaptor.getLhs(), adaptor.getRhs());
2461 using OpConversionPattern::OpConversionPattern;
2464 matchAndRewrite(Clog2BIOp op, OpAdaptor adaptor,
2465 ConversionPatternRewriter &rewriter)
const override {
2466 Type resultType = typeConverter->convertType(op.getResult().getType());
2467 Location loc = op.getLoc();
2468 unsigned width = resultType.getIntOrFloatBitWidth();
2469 Value value = adaptor.getValue();
2478 Value valueMinusOne = comb::SubOp::create(rewriter, loc, value, one,
false);
2480 mlir::math::CountLeadingZerosOp::create(rewriter, loc, valueMinusOne);
2481 Value bitLength = comb::SubOp::create(rewriter, loc, bitWidth, clz,
false);
2483 Value isZero = comb::ICmpOp::create(rewriter, loc, comb::ICmpPredicate::eq,
2484 value, zero,
false);
2485 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, isZero, zero, bitLength,
2492 using OpConversionPattern::OpConversionPattern;
2495 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
2496 ConversionPatternRewriter &rewriter)
const override {
2497 Type resultType = typeConverter->convertType(op.getResult().getType());
2501 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2502 resultType.getIntOrFloatBitWidth(), op->getLoc());
2504 op, resultType, adaptor.getValue(), amount,
false);
2510 using OpConversionPattern::OpConversionPattern;
2513 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
2514 ConversionPatternRewriter &rewriter)
const override {
2515 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
2520struct AssignedVariableOpConversion
2522 using OpConversionPattern::OpConversionPattern;
2525 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
2526 ConversionPatternRewriter &rewriter)
const override {
2527 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
2528 adaptor.getNameAttr());
2534static llhd::TimeAttr
2535getBlockingOrContinuousAssignDelay(mlir::MLIRContext *
context) {
2536 return llhd::TimeAttr::get(
context, 0U,
"ns", 0, 1);
2539template <
typename OpTy>
2542 using OpAdaptor =
typename OpTy::Adaptor;
2545 matchAndRewrite(OpTy op, OpAdaptor adaptor,
2546 ConversionPatternRewriter &rewriter)
const override {
2549 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
2550 std::is_same_v<OpTy, BlockingAssignOp>) {
2551 delay = llhd::ConstantTimeOp::create(
2552 rewriter, op->getLoc(),
2553 getBlockingOrContinuousAssignDelay(op->getContext()));
2554 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
2556 delay = llhd::ConstantTimeOp::create(
2557 rewriter, op->getLoc(),
2558 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
2561 delay = adaptor.getDelay();
2564 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
2565 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
2571 using OpConversionPattern::OpConversionPattern;
2574 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
2575 ConversionPatternRewriter &rewriter)
const override {
2580 auto type = typeConverter->convertType(op.getType());
2582 auto hasNoWriteEffect = [](Region ®ion) {
2583 auto result = region.walk([](Operation *operation) {
2584 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
2585 if (!memOp.hasEffect<MemoryEffects::Write>() &&
2586 !memOp.hasEffect<MemoryEffects::Free>())
2587 return WalkResult::advance();
2589 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
2590 return WalkResult::advance();
2592 return WalkResult::interrupt();
2594 return !result.wasInterrupted();
2597 if (hasNoWriteEffect(op.getTrueRegion()) &&
2598 hasNoWriteEffect(op.getFalseRegion())) {
2599 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
2600 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
2602 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
2603 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
2605 Value convTrueVal = typeConverter->materializeTargetConversion(
2606 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
2607 Value convFalseVal = typeConverter->materializeTargetConversion(
2608 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
2610 rewriter.eraseOp(trueTerm);
2611 rewriter.eraseOp(falseTerm);
2613 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
2614 convTrueVal, convFalseVal);
2619 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
2620 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
2621 ifOp.getThenRegion().end());
2622 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
2623 ifOp.getElseRegion().end());
2624 rewriter.replaceOp(op, ifOp);
2630 using OpConversionPattern::OpConversionPattern;
2633 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
2634 ConversionPatternRewriter &rewriter)
const override {
2635 Operation *parent = op->getParentOp();
2636 if (isa<llhd::GlobalSignalOp>(parent))
2637 rewriter.replaceOpWithNewOp<llhd::YieldOp>(op, adaptor.getResult());
2638 else if (isa<scf::ExecuteRegionOp, scf::ForOp, scf::IfOp,
2639 scf::IndexSwitchOp, scf::WhileOp>(parent))
2640 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
2642 return rewriter.notifyMatchFailure(
2643 op,
"yield parent has not been converted to a legal region op yet");
2648template <
typename SourceOp>
2651 using OpAdaptor =
typename SourceOp::Adaptor;
2654 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2655 ConversionPatternRewriter &rewriter)
const override {
2656 rewriter.modifyOpInPlace(op,
2657 [&]() { op->setOperands(adaptor.getOperands()); });
2662template <
typename MooreOpTy,
typename VerifOpTy>
2665 using OpAdaptor =
typename MooreOpTy::Adaptor;
2668 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
2669 ConversionPatternRewriter &rewriter)
const override {
2671 op.getLabel().has_value()
2672 ? StringAttr::get(op->getContext(), op.getLabel().value())
2673 : StringAttr::
get(op->getContext());
2674 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
2685 using OpConversionPattern::OpConversionPattern;
2688 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2689 ConversionPatternRewriter &rewriter)
const override {
2690 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2696 using OpConversionPattern::OpConversionPattern;
2699 matchAndRewrite(FormatStringOp op, OpAdaptor adaptor,
2700 ConversionPatternRewriter &rewriter)
const override {
2702 op.getPadding().value_or(IntPadding::Space) == IntPadding::Space ? 32
2704 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2705 auto widthAttr = adaptor.getWidthAttr();
2707 bool isLeftAligned =
2708 op.getAlignment().value_or(IntAlign::Right) == IntAlign::Left;
2709 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2711 rewriter.replaceOpWithNewOp<sim::FormatStringOp>(
2712 op, adaptor.getString(), isLeftAlignedAttr, padCharAttr, widthAttr);
2718 using OpConversionPattern::OpConversionPattern;
2721 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2722 ConversionPatternRewriter &rewriter)
const override {
2723 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2724 adaptor.getInputs());
2729struct FormatHierPathOpConversion
2731 using OpConversionPattern::OpConversionPattern;
2734 matchAndRewrite(FormatHierPathOp op, OpAdaptor adaptor,
2735 ConversionPatternRewriter &rewriter)
const override {
2736 rewriter.replaceOpWithNewOp<sim::FormatHierPathOp>(op,
2737 adaptor.getUseEscapes());
2743 using OpConversionPattern::OpConversionPattern;
2746 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2747 ConversionPatternRewriter &rewriter)
const override {
2749 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2750 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2751 auto widthAttr = adaptor.getSpecifierWidthAttr();
2753 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2754 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2756 switch (op.getFormat()) {
2757 case IntFormat::Decimal:
2758 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2759 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2760 adaptor.getIsSignedAttr());
2762 case IntFormat::Binary:
2763 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2764 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2766 case IntFormat::Octal:
2767 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2768 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2770 case IntFormat::HexLower:
2771 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2772 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2773 isLeftAlignedAttr, padCharAttr, widthAttr);
2775 case IntFormat::HexUpper:
2776 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2777 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2778 padCharAttr, widthAttr);
2781 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2786 using OpConversionPattern::OpConversionPattern;
2789 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2790 ConversionPatternRewriter &rewriter)
const override {
2791 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2793 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2794 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2795 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2797 switch (op.getFormat()) {
2798 case RealFormat::General:
2799 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2800 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2803 case RealFormat::Float:
2804 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2805 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2808 case RealFormat::Exponential:
2809 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2810 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2817struct FormatCharOpConversion
2819 using OpConversionPattern::OpConversionPattern;
2821 matchAndRewrite(moore::FormatCharOp op, OpAdaptor adaptor,
2822 ConversionPatternRewriter &rewriter)
const override {
2823 rewriter.replaceOpWithNewOp<sim::FormatCharOp>(op, adaptor.getValue());
2829 using OpConversionPattern::OpConversionPattern;
2832 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2833 ConversionPatternRewriter &rewriter)
const override {
2834 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2840 using OpConversionPattern::OpConversionPattern;
2843 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2844 ConversionPatternRewriter &rewriter)
const override {
2845 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2851 using OpConversionPattern::OpConversionPattern;
2854 matchAndRewrite(StringGetOp op, OpAdaptor adaptor,
2855 ConversionPatternRewriter &rewriter)
const override {
2856 rewriter.replaceOpWithNewOp<sim::StringGetOp>(op, adaptor.getStr(),
2857 adaptor.getIndex());
2863 using OpConversionPattern::OpConversionPattern;
2866 matchAndRewrite(QueueSizeBIOp op, OpAdaptor adaptor,
2867 ConversionPatternRewriter &rewriter)
const override {
2868 rewriter.replaceOpWithNewOp<sim::QueueSizeOp>(op, adaptor.getQueue());
2873struct DynQueueExtractOpConversion
2875 using OpConversionPattern::OpConversionPattern;
2878 matchAndRewrite(DynQueueExtractOp op, OpAdaptor adaptor,
2879 ConversionPatternRewriter &rewriter)
const override {
2880 bool isSingleElementExtract =
2881 op.getInput().getType().getElementType() == op.getResult().getType();
2883 if (isSingleElementExtract) {
2884 rewriter.replaceOpWithNewOp<sim::QueueGetOp>(op, adaptor.getInput(),
2885 adaptor.getLowerIdx());
2887 rewriter.replaceOpWithNewOp<sim::QueueSliceOp>(
2888 op, adaptor.getInput(), adaptor.getLowerIdx(), adaptor.getUpperIdx());
2904probeRefAndDriveWithResult(OpBuilder &builder, Location loc, Value ref,
2905 const std::function<Value(Value)> &func) {
2907 Value v = llhd::ProbeOp::create(builder, loc, ref);
2910 Value delay = llhd::ConstantTimeOp::create(
2911 builder, loc, getBlockingOrContinuousAssignDelay(builder.getContext()));
2913 llhd::DriveOp::create(builder, loc, ref, func(v), delay, Value{});
2917 using OpConversionPattern::OpConversionPattern;
2920 matchAndRewrite(QueuePushBackOp op, OpAdaptor adaptor,
2921 ConversionPatternRewriter &rewriter)
const override {
2922 probeRefAndDriveWithResult(
2923 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2924 return sim::QueuePushBackOp::create(rewriter, op->getLoc(), queue,
2925 adaptor.getElement());
2928 rewriter.eraseOp(op);
2933struct QueuePushFrontOpConversion
2935 using OpConversionPattern::OpConversionPattern;
2938 matchAndRewrite(QueuePushFrontOp op, OpAdaptor adaptor,
2939 ConversionPatternRewriter &rewriter)
const override {
2941 probeRefAndDriveWithResult(
2942 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2943 return sim::QueuePushFrontOp::create(rewriter, op->getLoc(), queue,
2944 adaptor.getElement());
2947 rewriter.eraseOp(op);
2953 using OpConversionPattern::OpConversionPattern;
2956 matchAndRewrite(QueuePopBackOp op, OpAdaptor adaptor,
2957 ConversionPatternRewriter &rewriter)
const override {
2959 probeRefAndDriveWithResult(
2960 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2962 sim::QueuePopBackOp::create(rewriter, op->getLoc(), queue);
2963 popped = popBack.getPopped();
2964 return popBack.getOutQueue();
2966 rewriter.replaceOp(op, popped);
2973 using OpConversionPattern::OpConversionPattern;
2976 matchAndRewrite(QueuePopFrontOp op, OpAdaptor adaptor,
2977 ConversionPatternRewriter &rewriter)
const override {
2979 probeRefAndDriveWithResult(
2980 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2982 sim::QueuePopFrontOp::create(rewriter, op->getLoc(), queue);
2983 popped = popFront.getPopped();
2984 return popFront.getOutQueue();
2986 rewriter.replaceOp(op, popped);
2993 using OpConversionPattern::OpConversionPattern;
2996 matchAndRewrite(QueueClearOp op, OpAdaptor adaptor,
2997 ConversionPatternRewriter &rewriter)
const override {
2998 auto refType = cast<llhd::RefType>(adaptor.getQueue().getType());
2999 auto queueType = refType.getNestedType();
3001 sim::QueueEmptyOp::create(rewriter, op->getLoc(), queueType);
3004 Value delay = llhd::ConstantTimeOp::create(
3005 rewriter, op.getLoc(),
3006 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3008 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getQueue(), emptyQueue,
3011 rewriter.eraseOp(op);
3017 using OpConversionPattern::OpConversionPattern;
3020 matchAndRewrite(QueueInsertOp op, OpAdaptor adaptor,
3021 ConversionPatternRewriter &rewriter)
const override {
3022 probeRefAndDriveWithResult(
3023 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
3025 sim::QueueInsertOp::create(rewriter, op->getLoc(), queue,
3026 adaptor.getIndex(), adaptor.getItem());
3028 return insert.getOutQueue();
3030 rewriter.eraseOp(op);
3037 using OpConversionPattern::OpConversionPattern;
3040 matchAndRewrite(QueueDeleteOp op, OpAdaptor adaptor,
3041 ConversionPatternRewriter &rewriter)
const override {
3042 probeRefAndDriveWithResult(
3043 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
3044 auto delOp = sim::QueueDeleteOp::create(rewriter, op->getLoc(), queue,
3045 adaptor.getIndex());
3047 return delOp.getOutQueue();
3049 rewriter.eraseOp(op);
3056 using OpConversionPattern::OpConversionPattern;
3059 matchAndRewrite(QueueResizeOp op, OpAdaptor adaptor,
3060 ConversionPatternRewriter &rewriter)
const override {
3062 rewriter.replaceOpWithNewOp<sim::QueueResizeOp>(
3063 op, getTypeConverter()->convertType(op.getResult().getType()),
3064 adaptor.getInput());
3070 using OpConversionPattern::OpConversionPattern;
3072 matchAndRewrite(QueueSetOp op, OpAdaptor adaptor,
3073 ConversionPatternRewriter &rewriter)
const override {
3074 probeRefAndDriveWithResult(
3075 rewriter, op->getLoc(), adaptor.getQueue(), [&](Value queue) {
3077 sim::QueueSetOp::create(rewriter, op.getLoc(), queue,
3078 adaptor.getIndex(), adaptor.getItem());
3079 return setOp.getOutQueue();
3081 rewriter.eraseOp(op);
3090static Value buildUArrayElementEq(ConversionPatternRewriter &rewriter,
3091 Location loc, Value lhs, Value rhs, Type type,
3092 UArrayCmpPredicate pred) {
3093 bool isEq = pred == UArrayCmpPredicate::eq;
3095 if (isa<mlir::FloatType>(type))
3096 return arith::CmpFOp::create(
3098 isEq ? arith::CmpFPredicate::OEQ : arith::CmpFPredicate::UNE, lhs, rhs);
3100 if (int64_t width = hw::getBitWidth(type); width != -1) {
3101 auto intTy = rewriter.getIntegerType(width);
3104 return comb::ICmpOp::create(rewriter, loc,
3105 isEq ? ICmpPredicate::eq : ICmpPredicate::ne,
3109 if (isa<sim::DynamicStringType>(type))
3110 return sim::StringCmpOp::create(rewriter, loc,
3111 isEq ? sim::StringCmpPredicate::eq
3112 :
sim::StringCmpPredicate::ne,
3115 if (isa<sim::QueueType>(type)) {
3116 auto pred = sim::UArrayCmpPredicateAttr::get(
3117 rewriter.getContext(),
3118 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3119 return sim::QueueCmpOp::create(rewriter, loc, pred, lhs, rhs);
3122 if (isa<sim::AssocArrayType>(type)) {
3123 auto pred = sim::UArrayCmpPredicateAttr::get(
3124 rewriter.getContext(),
3125 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3126 return sim::AssocArrayCmpOp::create(rewriter, loc, pred, lhs, rhs);
3129 auto arrayTy = dyn_cast<hw::ArrayType>(type);
3133 unsigned size = arrayTy.getNumElements();
3137 unsigned idxWidth = size == 1 ? 1 : llvm::Log2_64_Ceil(size);
3138 auto idxTy = rewriter.getIntegerType(idxWidth);
3140 SmallVector<Value> elemEqs;
3141 elemEqs.reserve(size);
3142 for (
unsigned i = 0; i < size; ++i) {
3146 Value elemEq = buildUArrayElementEq(rewriter, loc, lhsElem, rhsElem,
3147 arrayTy.getElementType(), pred);
3150 elemEqs.push_back(elemEq);
3153 return (isEq ? comb::AndOp::create(rewriter, loc, elemEqs,
true)
3155 :
comb::OrOp::create(rewriter, loc, elemEqs, true)
3160 using OpConversionPattern::OpConversionPattern;
3163 matchAndRewrite(QueueCmpOp op, OpAdaptor adaptor,
3164 ConversionPatternRewriter &rewriter)
const override {
3169 Value lhs = adaptor.getLhs();
3171 buildUArrayElementEq(rewriter, op.getLoc(), lhs, adaptor.getRhs(),
3172 lhs.getType(), op.getPredicate());
3173 rewriter.replaceOp(op, result);
3178struct QueueFromUnpackedArrayOpConversion
3180 using OpConversionPattern::OpConversionPattern;
3183 matchAndRewrite(QueueFromUnpackedArrayOp op, OpAdaptor adaptor,
3184 ConversionPatternRewriter &rewriter)
const override {
3185 rewriter.replaceOpWithNewOp<sim::QueueFromArrayOp>(
3186 op, getTypeConverter()->convertType(op.getResult().getType()),
3187 adaptor.getInput());
3193 using OpConversionPattern::OpConversionPattern;
3196 matchAndRewrite(QueueConcatOp op, OpAdaptor adaptor,
3197 ConversionPatternRewriter &rewriter)
const override {
3198 rewriter.replaceOpWithNewOp<sim::QueueConcatOp>(
3199 op, getTypeConverter()->convertType(op.getResult().getType()),
3200 adaptor.getInputs());
3205struct AssocArrayExtractOpConversion
3207 using OpConversionPattern::OpConversionPattern;
3209 matchAndRewrite(AssocArrayExtractOp op, OpAdaptor adaptor,
3210 ConversionPatternRewriter &rewriter)
const override {
3211 Type resultType = getTypeConverter()->convertType(op.getResult().getType());
3219 sim::AssocArrayGetOp::create(rewriter, op.getLoc(), resultType,
3220 adaptor.getInput(), adaptor.getIndex());
3221 Value exists = sim::AssocArrayExistsOp::create(
3222 rewriter, op.getLoc(), adaptor.getInput(), adaptor.getIndex());
3224 Value existsBit = comb::ICmpOp::create(
3225 rewriter, op.getLoc(), comb::ICmpPredicate::ne, exists, zeroI32,
false);
3226 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, existsBit, raw, zero,
false);
3232 using OpConversionPattern::OpConversionPattern;
3234 matchAndRewrite(UArrayCmpOp op, OpAdaptor adaptor,
3235 ConversionPatternRewriter &rewriter)
const override {
3236 Value lhs = adaptor.getLhs();
3237 Value rhs = adaptor.getRhs();
3238 auto pred = op.getPredicate();
3239 Value eq = buildUArrayElementEq(rewriter, op.getLoc(), lhs, rhs,
3240 lhs.getType(), pred);
3243 return rewriter.notifyMatchFailure(
3244 op,
"unpacked array element type does not support comparison");
3246 rewriter.replaceOp(op, eq);
3252 using OpConversionPattern::OpConversionPattern;
3254 matchAndRewrite(AssocArraySetOp op, OpAdaptor adaptor,
3255 ConversionPatternRewriter &rewriter)
const override {
3256 probeRefAndDriveWithResult(
3257 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3258 return sim::AssocArraySetOp::create(rewriter, op.getLoc(), array,
3263 rewriter.eraseOp(op);
3268struct AssocArrayDeleteOpConversion
3270 using OpConversionPattern::OpConversionPattern;
3272 matchAndRewrite(AssocArrayDeleteOp op, OpAdaptor adaptor,
3273 ConversionPatternRewriter &rewriter)
const override {
3274 probeRefAndDriveWithResult(
3275 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3276 return sim::AssocArrayDeleteOp::create(rewriter, op.getLoc(), array,
3280 rewriter.eraseOp(op);
3285struct AssocArrayClearOpConversion
3287 using OpConversionPattern::OpConversionPattern;
3289 matchAndRewrite(AssocArrayClearOp op, OpAdaptor adaptor,
3290 ConversionPatternRewriter &rewriter)
const override {
3291 auto refType = cast<llhd::RefType>(adaptor.getAssocArray().getType());
3292 Value emptyArray = sim::AssocArrayEmptyOp::create(rewriter, op->getLoc(),
3293 refType.getNestedType());
3294 Value delay = llhd::ConstantTimeOp::create(
3295 rewriter, op.getLoc(),
3296 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3297 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getAssocArray(),
3298 emptyArray, delay, Value{});
3299 rewriter.eraseOp(op);
3304struct AssocArraySizeOpConversion
3306 using OpConversionPattern::OpConversionPattern;
3308 matchAndRewrite(AssocArraySizeOp op, OpAdaptor adaptor,
3309 ConversionPatternRewriter &rewriter)
const override {
3311 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3312 rewriter.replaceOpWithNewOp<sim::AssocArraySizeOp>(op, array);
3317struct AssocArrayExistsOpConversion
3319 using OpConversionPattern::OpConversionPattern;
3321 matchAndRewrite(AssocArrayExistsOp op, OpAdaptor adaptor,
3322 ConversionPatternRewriter &rewriter)
const override {
3324 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3325 rewriter.replaceOpWithNewOp<sim::AssocArrayExistsOp>(op, array,
3326 adaptor.getIndex());
3331template <
typename MooreOpTy,
typename SimOpTy>
3334 using OpAdaptor =
typename MooreOpTy::Adaptor;
3336 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3337 ConversionPatternRewriter &rewriter)
const override {
3339 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3340 auto endpointOp = SimOpTy::create(rewriter, op.getLoc(), array);
3342 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3345 comb::ICmpOp::create(rewriter, op.getLoc(), comb::ICmpPredicate::ne,
3346 endpointOp->getResult(0), zero,
false);
3348 comb::MuxOp::create(rewriter, op.getLoc(), foundBit,
3349 endpointOp->getResult(1), curIndex,
false);
3350 Value delay = llhd::ConstantTimeOp::create(
3351 rewriter, op.getLoc(),
3352 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3353 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(), newIndex,
3355 rewriter.replaceOp(op, endpointOp->getResult(0));
3360template <
typename MooreOpTy,
typename SimOpTy>
3363 using OpAdaptor =
typename MooreOpTy::Adaptor;
3365 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3366 ConversionPatternRewriter &rewriter)
const override {
3368 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3370 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3371 auto stepOp = SimOpTy::create(rewriter, op.getLoc(), array, curIndex);
3372 Value delay = llhd::ConstantTimeOp::create(
3373 rewriter, op.getLoc(),
3374 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3375 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(),
3376 stepOp->getResult(1), delay, Value{});
3377 rewriter.replaceOp(op, stepOp->getResult(0));
3382using AssocArrayFirstOpConversion =
3383 AssocArrayEndpointOpConversion<AssocArrayFirstOp, sim::AssocArrayFirstOp>;
3384using AssocArrayLastOpConversion =
3385 AssocArrayEndpointOpConversion<AssocArrayLastOp, sim::AssocArrayLastOp>;
3386using AssocArrayNextOpConversion =
3387 AssocArrayStepOpConversion<AssocArrayNextOp, sim::AssocArrayNextOp>;
3388using AssocArrayPrevOpConversion =
3389 AssocArrayStepOpConversion<AssocArrayPrevOp, sim::AssocArrayPrevOp>;
3392 using OpConversionPattern::OpConversionPattern;
3395 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
3396 ConversionPatternRewriter &rewriter)
const override {
3397 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3398 op, adaptor.getMessage());
3404 using OpConversionPattern::OpConversionPattern;
3406 matchAndRewrite(FDisplayBIOp op, OpAdaptor adaptor,
3407 ConversionPatternRewriter &rewriter)
const override {
3408 auto stream = sim::SVChannelToOutputStreamOp::create(rewriter, op.getLoc(),
3410 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3411 op, adaptor.getMessage(), stream.getStream());
3417 using OpConversionPattern::OpConversionPattern;
3419 matchAndRewrite(FOpenBIOp op, OpAdaptor adaptor,
3420 ConversionPatternRewriter &rewriter)
const override {
3421 sim::SVFOpenModeAttr simMode;
3422 if (
auto modeAttr = op.getModeAttr()) {
3423 auto mapMode = [](moore::FOpenMode m) -> sim::SVFOpenMode {
3425 case moore::FOpenMode::Read:
3426 return sim::SVFOpenMode::Read;
3427 case moore::FOpenMode::Write:
3428 return sim::SVFOpenMode::Write;
3429 case moore::FOpenMode::Append:
3430 return sim::SVFOpenMode::Append;
3431 case moore::FOpenMode::ReadUpdate:
3432 return sim::SVFOpenMode::ReadUpdate;
3433 case moore::FOpenMode::WriteUpdate:
3434 return sim::SVFOpenMode::WriteUpdate;
3435 case moore::FOpenMode::AppendUpdate:
3436 return sim::SVFOpenMode::AppendUpdate;
3438 llvm_unreachable(
"unknown FOpenMode");
3440 simMode = sim::SVFOpenModeAttr::get(op.getContext(),
3441 mapMode(modeAttr.getValue()));
3443 rewriter.replaceOpWithNewOp<sim::SVFOpenOp>(op, adaptor.getFilename(),
3449struct PlusArgsTestBIOpConversion
3451 using OpConversionPattern::OpConversionPattern;
3453 matchAndRewrite(PlusArgsTestBIOp op, OpAdaptor adaptor,
3454 ConversionPatternRewriter &rewriter)
const override {
3455 rewriter.replaceOpWithNewOp<sim::PlusArgsTestOp>(op, rewriter.getI1Type(),
3456 op.getFormatStringAttr());
3461struct PlusArgsValueBIOpConversion
3463 using OpConversionPattern::OpConversionPattern;
3465 matchAndRewrite(PlusArgsValueBIOp op, OpAdaptor adaptor,
3466 ConversionPatternRewriter &rewriter)
const override {
3467 auto resultType = typeConverter->convertType(op.getResult().getType());
3469 return rewriter.notifyMatchFailure(op,
"unsupported result type");
3470 rewriter.replaceOpWithNewOp<sim::PlusArgsValueOp>(
3471 op, rewriter.getI1Type(), resultType, op.getFormatStringAttr());
3477 using OpConversionPattern::OpConversionPattern;
3480 matchAndRewrite(FCloseBIOp op, OpAdaptor adaptor,
3481 ConversionPatternRewriter &rewriter)
const override {
3482 rewriter.replaceOpWithNewOp<sim::SVFCloseOp>(op, adaptor.getFd());
3488 using OpConversionPattern::OpConversionPattern;
3491 matchAndRewrite(FFlushBIOp op, OpAdaptor adaptor,
3492 ConversionPatternRewriter &rewriter)
const override {
3493 if (!adaptor.getFd()) {
3494 rewriter.replaceOpWithNewOp<sim::SVFFlushAllOp>(op);
3496 auto stream = sim::SVChannelToOutputStreamOp::create(
3497 rewriter, op.getLoc(), adaptor.getFd());
3498 rewriter.replaceOpWithNewOp<sim::FlushOp>(op, stream);
3505 using OpConversionPattern::OpConversionPattern;
3508 matchAndRewrite(StringCmpOp op, OpAdaptor adaptor,
3509 ConversionPatternRewriter &rewriter)
const override {
3510 sim::StringCmpPredicate pred;
3511 switch (op.getPredicate()) {
3512 case moore::StringCmpPredicate::eq:
3513 pred = sim::StringCmpPredicate::eq;
3515 case moore::StringCmpPredicate::ne:
3516 pred = sim::StringCmpPredicate::ne;
3518 case moore::StringCmpPredicate::lt:
3519 pred = sim::StringCmpPredicate::lt;
3521 case moore::StringCmpPredicate::le:
3522 pred = sim::StringCmpPredicate::le;
3524 case moore::StringCmpPredicate::gt:
3525 pred = sim::StringCmpPredicate::gt;
3527 case moore::StringCmpPredicate::ge:
3528 pred = sim::StringCmpPredicate::ge;
3531 rewriter.replaceOpWithNewOp<sim::StringCmpOp>(op, pred, adaptor.getLhs(),
3538 using OpConversionPattern::OpConversionPattern;
3541 matchAndRewrite(ReadMemBIOp op, OpAdaptor adaptor,
3542 ConversionPatternRewriter &rewriter)
const override {
3543 auto loc = op.getLoc();
3544 Value memory = llhd::ProbeOp::create(rewriter, loc, adaptor.getDest());
3545 Value loaded = sim::SVReadMemOp::create(
3546 rewriter, loc, memory.getType(), adaptor.getFilename(), memory,
3547 rewriter.getBoolAttr(op.getBase() == MemBase::Binary),
3548 adaptor.getStartAddr(), adaptor.getFinishAddr(), adaptor.getSliceLeft(),
3549 adaptor.getSliceRight(), op.getDimLowsAttr(), op.getDimDescendingAttr(),
3550 op.getEnumValuesAttr());
3551 Value delay = llhd::ConstantTimeOp::create(
3553 llhd::TimeAttr::get(rewriter.getContext(), 0U,
"ns", 0, 1));
3554 rewriter.replaceOpWithNewOp<llhd::DriveOp>(op, adaptor.getDest(), loaded,
3567static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
3568 ConversionPatternRewriter &rewriter) {
3569 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
3574static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
3575 ConversionPatternRewriter &rewriter) {
3576 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
3582static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
3583 ConversionPatternRewriter &rewriter) {
3585 std::string severityString;
3587 switch (op.getSeverity()) {
3588 case (Severity::Fatal):
3589 severityString =
"Fatal: ";
3591 case (Severity::Error):
3592 severityString =
"Error: ";
3594 case (Severity::Warning):
3595 severityString =
"Warning: ";
3597 case (Severity::Info):
3598 severityString =
"Info: ";
3603 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
3604 auto message = sim::FormatStringConcatOp::create(
3605 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
3606 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
3620 UrandomRangeBIOp::Adaptor adaptor,
3621 ConversionPatternRewriter &rewriter,
3622 FunctionCache &funcCache) {
3623 auto loc = op.getLoc();
3624 auto i32Ty = rewriter.getI32Type();
3625 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
3626 auto fn = funcCache.getOrCreate(rewriter,
"__circt_urandom_range",
3627 {i32Ty, i32Ty, ptrTy}, {i32Ty});
3630 if (
auto seedRef = adaptor.getSeed()) {
3633 seedPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, i32Ty, one);
3634 auto seedVal = llhd::ProbeOp::create(rewriter, loc, seedRef);
3635 LLVM::StoreOp::create(rewriter, loc, seedVal, seedPtr);
3637 seedPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
3640 auto call = func::CallOp::create(
3642 ValueRange{adaptor.getMinval(), adaptor.getMaxval(), seedPtr});
3645 if (adaptor.getSeed()) {
3646 auto newSeed = LLVM::LoadOp::create(rewriter, loc, i32Ty, seedPtr);
3647 auto epsilon = llhd::ConstantTimeOp::create(
3649 llhd::TimeAttr::get(rewriter.getContext(), 0,
"ns", 0, 1));
3650 llhd::DriveOp::create(rewriter, loc, adaptor.getSeed(), newSeed, epsilon,
3654 rewriter.replaceOp(op, call.getResult(0));
3660 FinishMessageBIOp::Adaptor adaptor,
3661 ConversionPatternRewriter &rewriter) {
3663 rewriter.eraseOp(op);
3672static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
3673 ConversionPatternRewriter &rewriter) {
3674 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
3679static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
3680 ConversionPatternRewriter &rewriter) {
3681 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
3686static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
3687 ConversionPatternRewriter &rewriter) {
3688 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
3697 const TypeConverter &converter) {
3698 target.addIllegalDialect<MooreDialect>();
3699 target.addLegalDialect<comb::CombDialect>();
3700 target.addLegalDialect<hw::HWDialect>();
3701 target.addLegalDialect<seq::SeqDialect>();
3702 target.addLegalDialect<llhd::LLHDDialect>();
3703 target.addLegalDialect<ltl::LTLDialect>();
3704 target.addLegalDialect<mlir::BuiltinDialect>();
3705 target.addLegalDialect<mlir::math::MathDialect>();
3706 target.addLegalDialect<sim::SimDialect>();
3707 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3708 target.addLegalDialect<mlir::ub::UBDialect>();
3709 target.addLegalDialect<verif::VerifDialect>();
3710 target.addLegalDialect<arith::ArithDialect>();
3712 target.addLegalOp<debug::ScopeOp>();
3714 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
3715 UnrealizedConversionCastOp, hw::OutputOp,
3716 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
3717 debug::VariableOp, arith::SelectOp>(
3718 [&](Operation *op) {
return converter.isLegal(op); });
3720 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
3721 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
3722 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
3725 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
3726 return converter.isSignatureLegal(op.getFunctionType());
3730 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
3731 converter.isLegal(&op.getBody());
3736 typeConverter.addConversion([&](IntType type) {
3737 return IntegerType::get(type.getContext(), type.getWidth());
3740 typeConverter.addConversion([&](RealType type) -> mlir::Type {
3741 MLIRContext *ctx = type.getContext();
3742 switch (type.getWidth()) {
3743 case moore::RealWidth::f32:
3744 return mlir::Float32Type::get(ctx);
3745 case moore::RealWidth::f64:
3746 return mlir::Float64Type::get(ctx);
3750 typeConverter.addConversion(
3751 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
3753 typeConverter.addConversion([&](FormatStringType type) {
3754 return sim::FormatStringType::get(type.getContext());
3757 typeConverter.addConversion([&](StringType type) {
3758 return sim::DynamicStringType::get(type.getContext());
3761 typeConverter.addConversion([&](QueueType type) {
3762 return sim::QueueType::get(type.getContext(),
3763 typeConverter.convertType(type.getElementType()),
3767 typeConverter.addConversion([&](sim::QueueType type) -> std::optional<Type> {
3768 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3769 return sim::QueueType::get(type.getContext(),
elementType,
3774 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
3775 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3776 return hw::ArrayType::get(
elementType, type.getSize());
3780 typeConverter.addConversion([&](AssocArrayType type) -> std::optional<Type> {
3781 auto elementType = typeConverter.convertType(type.getElementType());
3782 auto indexType = typeConverter.convertType(type.getIndexType());
3785 return sim::AssocArrayType::get(type.getContext(),
elementType, indexType);
3791 typeConverter.addConversion(
3792 [&](UnpackedArrayType type) -> std::optional<Type> {
3793 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3794 return hw::ArrayType::get(
elementType, type.getSize());
3798 typeConverter.addConversion([&](OpenArrayType type) -> std::optional<Type> {
3799 return LLVM::LLVMPointerType::get(type.getContext());
3802 typeConverter.addConversion(
3803 [&](OpenUnpackedArrayType type) -> std::optional<Type> {
3804 return LLVM::LLVMPointerType::get(type.getContext());
3807 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
3808 SmallVector<hw::StructType::FieldInfo> fields;
3809 for (
auto field : type.getMembers()) {
3810 hw::StructType::FieldInfo info;
3811 info.type = typeConverter.convertType(field.type);
3814 info.name = field.name;
3815 fields.push_back(info);
3817 return hw::StructType::get(type.getContext(), fields);
3825 typeConverter.addConversion(
3826 [&](UnpackedStructType type) -> std::optional<Type> {
3827 SmallVector<hw::StructType::FieldInfo> fields;
3828 for (
auto field : type.getMembers()) {
3829 hw::StructType::FieldInfo info;
3830 info.type = typeConverter.convertType(field.type);
3833 info.name = field.name;
3834 fields.push_back(info);
3836 return hw::StructType::get(type.getContext(), fields);
3840 typeConverter.addConversion([&](UnionType type) -> std::optional<Type> {
3841 SmallVector<hw::UnionType::FieldInfo> fields;
3842 for (
auto field : type.getMembers()) {
3843 hw::UnionType::FieldInfo info;
3844 info.type = typeConverter.convertType(field.type);
3847 info.name = field.name;
3849 fields.push_back(info);
3851 auto result = hw::UnionType::get(type.getContext(), fields);
3856 typeConverter.addConversion(
3857 [&](UnpackedUnionType type) -> std::optional<Type> {
3858 SmallVector<hw::UnionType::FieldInfo> fields;
3859 for (
auto field : type.getMembers()) {
3860 hw::UnionType::FieldInfo info;
3861 info.type = typeConverter.convertType(field.type);
3864 info.name = field.name;
3866 fields.push_back(info);
3868 return hw::UnionType::get(type.getContext(), fields);
3872 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
3873 return LLVM::LLVMPointerType::get(type.getContext());
3877 typeConverter.addConversion(
3878 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
3881 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
3882 return LLVM::LLVMPointerType::get(type.getContext());
3886 typeConverter.addConversion([&](NullType type) -> std::optional<Type> {
3887 return LLVM::LLVMPointerType::get(type.getContext());
3890 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
3891 if (isa<OpenArrayType, OpenUnpackedArrayType>(type.getNestedType()))
3892 return LLVM::LLVMPointerType::get(type.getContext());
3893 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3894 return llhd::RefType::get(innerType);
3899 typeConverter.addConversion([](IntegerType type) {
return type; });
3900 typeConverter.addConversion([](FloatType type) {
return type; });
3901 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
3902 typeConverter.addConversion([](sim::FormatStringType type) {
return type; });
3903 typeConverter.addConversion([](sim::AssocArrayType type) {
return type; });
3904 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
3905 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
3906 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
3907 typeConverter.addConversion([](debug::StructType type) {
return type; });
3909 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
3910 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3911 return llhd::RefType::get(innerType);
3915 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
3916 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3917 return hw::ArrayType::get(
elementType, type.getNumElements());
3921 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
3922 SmallVector<hw::StructType::FieldInfo> fields;
3923 for (
auto field : type.getElements()) {
3924 hw::StructType::FieldInfo info;
3925 info.type = typeConverter.convertType(field.type);
3928 info.name = field.name;
3929 fields.push_back(info);
3931 return hw::StructType::get(type.getContext(), fields);
3934 typeConverter.addConversion([&](hw::UnionType type) -> std::optional<Type> {
3935 SmallVector<hw::UnionType::FieldInfo> fields;
3936 for (
auto field : type.getElements()) {
3937 hw::UnionType::FieldInfo info;
3938 info.type = typeConverter.convertType(field.type);
3941 info.name = field.name;
3942 info.offset = field.offset;
3943 fields.push_back(info);
3945 return hw::UnionType::get(type.getContext(), fields);
3948 typeConverter.addTargetMaterialization(
3949 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3950 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3951 if (inputs.size() != 1 || !inputs[0])
3953 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3958 typeConverter.addSourceMaterialization(
3959 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3960 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3961 if (inputs.size() != 1)
3963 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3970 TypeConverter &typeConverter,
3971 ClassTypeCache &classCache,
3972 FunctionCache &funcCache) {
3977 classCache, funcCache);
3978 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
3979 patterns.getContext(), classCache);
3983 ClassUpcastOpConversion,
3986 VariableOpConversion,
3990 ConversionOpConversion,
3991 BitcastConversion<PackedToSBVOp>,
3992 BitcastConversion<SBVToPackedOp>,
3993 NoOpConversion<LogicToIntOp>,
3994 NoOpConversion<IntToLogicOp>,
3995 NoOpConversion<ToBuiltinIntOp>,
3996 NoOpConversion<FromBuiltinIntOp>,
4000 SIntToRealOpConversion,
4001 UIntToRealOpConversion,
4002 IntToStringOpConversion,
4003 StringToIntOpConversion,
4004 FormatStringToStringOpConversion,
4005 RealToIntOpConversion,
4006 ConvertRealOpConversion,
4007 RealBitcastOpConversion<RealtobitsBIOp>,
4008 RealBitcastOpConversion<BitstorealBIOp>,
4009 RealBitcastOpConversion<ShortrealtobitsBIOp>,
4010 RealBitcastOpConversion<BitstoshortrealBIOp>,
4016 ReplicateOpConversion,
4018 ExtractOpConversion,
4019 DynExtractOpConversion,
4020 DynExtractRefOpConversion,
4022 StructExtractOpConversion,
4023 StructExtractRefOpConversion,
4024 ExtractRefOpConversion,
4025 StructCreateOpConversion,
4026 UnionCreateOpConversion,
4027 UnionExtractOpConversion,
4028 UnionExtractRefOpConversion,
4029 ConditionalOpConversion,
4030 ArrayCreateOpConversion,
4031 UArrayCmpOpConversion,
4034 ConstantStringOpConv,
4037 ReduceAndOpConversion,
4038 ReduceOrOpConversion,
4039 ReduceXorOpConversion,
4040 BoolCastOpConversion,
4045 BinaryOpConversion<AddOp, comb::AddOp>,
4046 BinaryOpConversion<SubOp, comb::SubOp>,
4047 BinaryOpConversion<MulOp, comb::MulOp>,
4048 BinaryOpConversion<DivUOp, comb::DivUOp>,
4049 BinaryOpConversion<DivSOp, comb::DivSOp>,
4050 BinaryOpConversion<ModUOp, comb::ModUOp>,
4051 BinaryOpConversion<ModSOp, comb::ModSOp>,
4052 BinaryOpConversion<AndOp, comb::AndOp>,
4053 BinaryOpConversion<OrOp, comb::OrOp>,
4054 BinaryOpConversion<XorOp, comb::XorOp>,
4057 NegRealOpConversion,
4060 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
4061 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
4062 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
4063 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
4064 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
4067 RealMathFunc<LnBIOp, math::LogOp>,
4068 RealMathFunc<Log10BIOp, math::Log10Op>,
4069 RealMathFunc<ExpBIOp, math::ExpOp>,
4070 RealMathFunc<SqrtBIOp, math::SqrtOp>,
4071 BinaryRealOpConversion<MinBIOp, arith::MinimumFOp>,
4072 BinaryRealOpConversion<MaxBIOp, arith::MaximumFOp>,
4073 RealMathFunc<AbsBIOp, math::AbsFOp>,
4074 RealMathFunc<FloorBIOp, math::FloorOp>,
4075 RealMathFunc<CeilBIOp, math::CeilOp>,
4076 RealMathFunc<SinBIOp, math::SinOp>,
4077 RealMathFunc<CosBIOp, math::CosOp>,
4078 RealMathFunc<TanBIOp, math::TanOp>,
4079 RealMathFunc<AsinBIOp, math::AsinOp>,
4080 RealMathFunc<AcosBIOp, math::AcosOp>,
4081 RealMathFunc<AtanBIOp, math::AtanOp>,
4082 BinaryRealOpConversion<Atan2BIOp, math::Atan2Op>,
4083 HypotBIOpConversion,
4084 RealMathFunc<SinhBIOp, math::SinhOp>,
4085 RealMathFunc<CoshBIOp, math::CoshOp>,
4086 RealMathFunc<TanhBIOp, math::TanhOp>,
4087 RealMathFunc<AsinhBIOp, math::AsinhOp>,
4088 RealMathFunc<AcoshBIOp, math::AcoshOp>,
4089 RealMathFunc<AtanhBIOp, math::AtanhOp>,
4092 PowUOpConversion, PowSOpConversion,
4093 Clog2BIOpConversion,
4096 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
4097 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
4098 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
4099 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
4100 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
4101 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
4102 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
4103 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
4104 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
4105 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
4106 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
4107 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
4108 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
4109 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
4110 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::UNE>,
4111 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
4112 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
4113 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
4114 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
4115 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
4116 CaseXZEqOpConversion<CaseZEqOp, true>,
4117 CaseXZEqOpConversion<CaseXZEqOp, false>,
4118 HandleCmpOpConversion<HandleEqOp, LLVM::ICmpPredicate::eq>,
4119 HandleCmpOpConversion<HandleNeOp, LLVM::ICmpPredicate::ne>,
4122 SVModuleOpConversion,
4123 InstanceOpConversion,
4124 ProcedureOpConversion,
4125 CoroutineOpConversion,
4126 CallCoroutineOpConversion,
4127 WaitEventOpConversion,
4135 AssignOpConversion<ContinuousAssignOp>,
4136 AssignOpConversion<DelayedContinuousAssignOp>,
4137 AssignOpConversion<BlockingAssignOp>,
4138 AssignOpConversion<NonBlockingAssignOp>,
4139 AssignOpConversion<DelayedNonBlockingAssignOp>,
4140 AssignedVariableOpConversion,
4143 HWInstanceOpConversion,
4146 DPIFuncOpConversion,
4147 FuncDPICallOpConversion,
4148 UnrealizedConversionCastConversion,
4149 InPlaceOpConversion<debug::ArrayOp>,
4150 InPlaceOpConversion<debug::StructOp>,
4151 InPlaceOpConversion<debug::VariableOp>,
4154 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
4155 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
4156 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
4159 FormatLiteralOpConversion,
4160 FormatStringOpConversion,
4161 FormatConcatOpConversion,
4162 FormatHierPathOpConversion,
4163 FormatIntOpConversion,
4164 FormatRealOpConversion,
4165 FormatCharOpConversion,
4166 DisplayBIOpConversion,
4167 FDisplayBIOpConversion,
4170 FOpenBIOpConversion,
4171 FCloseBIOpConversion,
4172 FFlushBIOpConversion,
4173 ReadMemBIOpConversion,
4176 PlusArgsTestBIOpConversion,
4177 PlusArgsValueBIOpConversion,
4180 StringLenOpConversion,
4181 StringConcatOpConversion,
4182 StringGetOpConversion,
4183 StringCmpOpConversion,
4186 QueueSizeBIOpConversion,
4187 QueuePushBackOpConversion,
4188 QueuePushFrontOpConversion,
4189 QueuePopBackOpConversion,
4190 QueuePopFrontOpConversion,
4191 QueueDeleteOpConversion,
4192 QueueInsertOpConversion,
4193 QueueClearOpConversion,
4194 DynQueueExtractOpConversion,
4195 QueueResizeOpConversion,
4196 QueueSetOpConversion,
4197 QueueCmpOpConversion,
4198 QueueFromUnpackedArrayOpConversion,
4199 QueueConcatOpConversion,
4202 AssocArrayExtractOpConversion,
4203 AssocArraySetOpConversion,
4204 AssocArrayDeleteOpConversion,
4205 AssocArrayClearOpConversion,
4206 AssocArraySizeOpConversion,
4207 AssocArrayExistsOpConversion,
4208 AssocArrayFirstOpConversion,
4209 AssocArrayLastOpConversion,
4210 AssocArrayNextOpConversion,
4211 AssocArrayPrevOpConversion
4212 >(typeConverter,
patterns.getContext());
4235 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
4237 hw::populateHWModuleLikeTypeConversionPattern(
4238 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
4239 populateSCFToControlFlowConversionPatterns(
patterns);
4248struct MooreToCorePass
4249 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
4250 void runOnOperation()
override;
4256 return std::make_unique<MooreToCorePass>();
4260void MooreToCorePass::runOnOperation() {
4261 MLIRContext &
context = getContext();
4262 ModuleOp
module = getOperation();
4263 ClassTypeCache classCache;
4264 auto &symbolTable = getAnalysis<SymbolTable>();
4265 FunctionCache funcCache(symbolTable);
4267 IRRewriter rewriter(module);
4268 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
4270 TypeConverter typeConverter;
4273 ConversionTarget target(
context);
4278 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
4281 if (failed(applyFullConversion(module, target, std::move(
patterns))))
4282 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.