21#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
22#include "mlir/Dialect/Arith/IR/Arith.h"
23#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
24#include "mlir/Dialect/ControlFlow/Transforms/StructuralTypeConversions.h"
25#include "mlir/Dialect/Func/IR/FuncOps.h"
26#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
27#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
28#include "mlir/Dialect/Math/IR/Math.h"
29#include "mlir/Dialect/SCF/IR/SCF.h"
30#include "mlir/IR/BuiltinDialect.h"
31#include "mlir/IR/Iterators.h"
32#include "mlir/Interfaces/SideEffectInterfaces.h"
33#include "mlir/Pass/Pass.h"
34#include "mlir/Transforms/DialectConversion.h"
35#include "mlir/Transforms/RegionUtils.h"
36#include "llvm/ADT/TypeSwitch.h"
37#include "llvm/IR/DerivedTypes.h"
40#define GEN_PASS_DEF_CONVERTMOORETOCORE
41#include "circt/Conversion/Passes.h.inc"
48using comb::ICmpPredicate;
49using llvm::SmallDenseSet;
54struct ClassTypeCache {
56 LLVM::GlobalOp global;
59 struct ClassStructInfo {
60 LLVM::LLVMStructType classBody;
61 LLVM::LLVMStructType headerTy;
62 TypeInfoInfo typeInfo;
64 unsigned headerFieldIndex = 0;
65 unsigned typeInfoFieldIndex = 0;
66 unsigned vtableFieldIndex = 1;
69 DenseMap<StringRef, SmallVector<unsigned, 2>> propertyPath;
73 void setFieldPath(StringRef propertyName, ArrayRef<unsigned> path) {
74 this->propertyPath[propertyName] =
75 SmallVector<unsigned, 2>(path.begin(), path.end());
79 std::optional<ArrayRef<unsigned>>
80 getFieldPath(StringRef propertySym)
const {
81 if (
auto prop = this->propertyPath.find(propertySym);
82 prop != this->propertyPath.end())
83 return ArrayRef<unsigned>(prop->second);
90 void setClassInfo(SymbolRefAttr classSym,
const ClassStructInfo &
info) {
91 auto &dst = classToStructMap[classSym];
96 std::optional<ClassStructInfo> getStructInfo(SymbolRefAttr classSym)
const {
97 if (
auto it = classToStructMap.find(classSym); it != classToStructMap.end())
102 std::optional<TypeInfoInfo> getTypeInfo(SymbolRefAttr classSym)
const {
103 if (
auto it = classToTypeInfoMap.find(classSym);
104 it != classToTypeInfoMap.end())
109 void setTypeInfo(SymbolRefAttr classSym,
const TypeInfoInfo &
info) {
110 classToTypeInfoMap[classSym] =
info;
117 DenseMap<Attribute, ClassStructInfo> classToStructMap;
118 DenseMap<Attribute, TypeInfoInfo> classToTypeInfoMap;
123struct FunctionCache {
124 FunctionCache(SymbolTable &symbolTable) : symbolTable(symbolTable) {}
130 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
131 function_ref<func::FuncOp()> createFn) {
132 auto &slot = map[name];
135 if (
auto fn = symbolTable.lookup<func::FuncOp>(name))
137 auto mod = cast<ModuleOp>(symbolTable.getOp());
138 OpBuilder::InsertionGuard g(builder);
139 builder.setInsertionPointToStart(mod.getBody());
141 symbolTable.insert(slot);
147 func::FuncOp getOrCreate(OpBuilder &builder, StringRef name,
148 TypeRange argTypes, TypeRange resultTypes) {
149 return getOrCreate(builder, name, [&] {
150 auto mod = cast<ModuleOp>(symbolTable.getOp());
151 auto fnTy = builder.getFunctionType(argTypes, resultTypes);
152 auto fn = func::FuncOp::create(builder, mod.getLoc(), name, fnTy);
159 SymbolTable &symbolTable;
160 llvm::StringMap<func::FuncOp> map;
165static LLVM::LLVMStructType getOrCreateOpaqueStruct(MLIRContext *ctx,
166 SymbolRefAttr className) {
167 return LLVM::LLVMStructType::getIdentified(ctx, className.getRootReference());
171static LLVM::LLVMStructType getClassObjectHeaderType(MLIRContext *ctx) {
172 return LLVM::LLVMStructType::getLiteral(
173 ctx, SmallVector<Type>{LLVM::LLVMPointerType::get(ctx),
174 LLVM::LLVMPointerType::get(ctx)});
177static std::string getTypeInfoName(SymbolRefAttr className) {
178 return className.getRootReference().str() +
"::typeinfo";
181static FailureOr<ClassTypeCache::TypeInfoInfo>
182getOrCreateTypeInfo(ModuleOp mod, SymbolRefAttr classSym,
183 ClassTypeCache &cache) {
184 if (
auto info = cache.getTypeInfo(classSym))
187 MLIRContext *ctx = mod.getContext();
188 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
189 auto typeInfoTy = LLVM::LLVMStructType::getLiteral(ctx, {ptrTy});
191 auto globalName = getTypeInfoName(classSym);
192 auto global = mod.lookupSymbol<LLVM::GlobalOp>(globalName);
194 OpBuilder builder = OpBuilder::atBlockBegin(mod.getBody());
195 global = LLVM::GlobalOp::create(
196 builder, mod.getLoc(), typeInfoTy,
197 true, LLVM::Linkage::Internal, globalName, Attribute());
200 global.getInitializerRegion().push_back(block);
201 builder.setInsertionPointToStart(block);
203 if (
auto *classOp = mod.lookupSymbol(classSym)) {
204 auto classDecl = dyn_cast<ClassDeclOp>(classOp);
205 if (classDecl && classDecl.getBaseAttr()) {
207 getOrCreateTypeInfo(mod, classDecl.getBaseAttr(), cache);
208 if (failed(baseInfo))
211 LLVM::AddressOfOp::create(builder, mod.getLoc(), baseInfo->global);
212 auto undef = LLVM::UndefOp::create(builder, mod.getLoc(), typeInfoTy)
214 auto init = LLVM::InsertValueOp::create(builder, mod.getLoc(), undef,
215 baseAddr.getResult(),
216 ArrayRef<int64_t>{0});
217 LLVM::ReturnOp::create(builder, mod.getLoc(), init);
218 ClassTypeCache::TypeInfoInfo
info{global};
219 cache.setTypeInfo(classSym, info);
225 LLVM::UndefOp::create(builder, mod.getLoc(), typeInfoTy).getResult();
227 LLVM::ZeroOp::create(builder, mod.getLoc(), ptrTy).getResult();
228 auto init = LLVM::InsertValueOp::create(builder, mod.getLoc(), undef,
229 nullPtr, ArrayRef<int64_t>{0});
230 LLVM::ReturnOp::create(builder, mod.getLoc(), init);
233 ClassTypeCache::TypeInfoInfo
info{global};
234 cache.setTypeInfo(classSym, info);
237static LogicalResult resolveClassStructBody(ClassDeclOp op,
238 TypeConverter
const &typeConverter,
239 ClassTypeCache &cache) {
241 auto classSym = SymbolRefAttr::get(op.getSymNameAttr());
242 auto structInfo = cache.getStructInfo(classSym);
247 if (failed(getOrCreateTypeInfo(op->getParentOfType<ModuleOp>(), classSym,
249 return op.emitOpError() <<
"Failed to create RTTI for class";
252 ClassTypeCache::ClassStructInfo structBody;
253 SmallVector<Type> structBodyMembers;
254 structBody.headerTy = getClassObjectHeaderType(op.getContext());
255 structBody.typeInfo = *cache.getTypeInfo(classSym);
256 structBodyMembers.push_back(structBody.headerTy);
259 unsigned derivedStartIdx = 1;
261 if (
auto baseClass = op.getBaseAttr()) {
263 ModuleOp mod = op->getParentOfType<ModuleOp>();
264 auto *opSym = mod.lookupSymbol(baseClass);
265 auto classDeclOp = cast<ClassDeclOp>(opSym);
267 if (failed(resolveClassStructBody(classDeclOp, typeConverter, cache)))
271 auto baseClassStruct = cache.getStructInfo(baseClass);
272 structBodyMembers.push_back(baseClassStruct->classBody);
277 for (
auto &kv : baseClassStruct->propertyPath) {
278 SmallVector<unsigned, 2> path;
280 path.append(kv.second.begin(), kv.second.end());
281 structBody.setFieldPath(kv.first, path);
286 unsigned iterator = derivedStartIdx;
287 auto &block = op.getBody().front();
288 for (Operation &child : block) {
289 if (
auto prop = dyn_cast<ClassPropertyDeclOp>(child)) {
290 Type mooreTy = prop.getPropertyType();
291 Type llvmTy = typeConverter.convertType(mooreTy);
293 return prop.emitOpError()
294 <<
"failed to convert property type " << mooreTy;
296 structBodyMembers.push_back(llvmTy);
299 SmallVector<unsigned, 2> path{iterator};
300 structBody.setFieldPath(prop.getSymName(), path);
306 auto llvmStructTy = getOrCreateOpaqueStruct(op.getContext(), classSym);
308 if (!structBodyMembers.empty() &&
309 failed(llvmStructTy.setBody(structBodyMembers,
false)))
310 return op.emitOpError() <<
"Failed to set LLVM Struct body";
312 structBody.classBody = llvmStructTy;
313 cache.setClassInfo(classSym, structBody);
319static LogicalResult resolveClassStructBody(ModuleOp mod, SymbolRefAttr op,
320 TypeConverter
const &typeConverter,
321 ClassTypeCache &cache) {
322 auto classDeclOp = cast<ClassDeclOp>(*mod.lookupSymbol(op));
323 return resolveClassStructBody(classDeclOp, typeConverter, cache);
330static Value adjustIntegerWidth(OpBuilder &builder, Value value,
331 uint32_t targetWidth, Location loc) {
332 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
333 if (intWidth == targetWidth)
336 if (intWidth < targetWidth) {
338 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
339 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
343 intWidth - targetWidth);
345 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
346 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
350 builder.getIntegerType(targetWidth), -1);
351 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
355static FailureOr<hw::ModulePortInfo>
356getModulePortInfo(
const TypeConverter &typeConverter, SVModuleOp op) {
358 size_t resultNum = 0;
359 auto moduleTy = op.getModuleType();
360 SmallVector<hw::PortInfo> ports;
361 ports.reserve(moduleTy.getNumPorts());
363 for (
auto port : moduleTy.getPorts()) {
364 Type portTy = typeConverter.convertType(port.type);
366 return op.emitOpError(
"port '")
367 << port.name <<
"' has unsupported type " << port.type
368 <<
" that cannot be converted to hardware type";
370 if (port.dir == hw::ModulePort::Direction::Output) {
372 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
380 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
386struct DpiArrayCastInfo {
389 bool isPacked =
false;
393static std::optional<DpiArrayCastInfo> getDpiArrayCastInfo(Type type) {
394 DpiArrayCastInfo
info;
395 if (
auto refType = dyn_cast<RefType>(type)) {
397 type = refType.getNestedType();
400 if (
auto arrayType = dyn_cast<ArrayType>(type)) {
401 info.isPacked =
true;
402 info.elementType = arrayType.getElementType();
405 if (
auto arrayType = dyn_cast<OpenArrayType>(type)) {
407 info.isPacked =
true;
408 info.elementType = arrayType.getElementType();
411 if (
auto arrayType = dyn_cast<UnpackedArrayType>(type)) {
412 info.elementType = arrayType.getElementType();
415 if (
auto arrayType = dyn_cast<OpenUnpackedArrayType>(type)) {
417 info.elementType = arrayType.getElementType();
423static bool hasOpenArrayBoundaryType(Type type) {
424 if (isa<OpenArrayType, OpenUnpackedArrayType>(type))
426 if (
auto refType = dyn_cast<RefType>(type))
427 return isa<OpenArrayType, OpenUnpackedArrayType>(refType.getNestedType());
431static bool isSupportedDpiOpenArrayCast(Type source, Type target) {
432 auto sourceInfo = getDpiArrayCastInfo(source);
433 auto targetInfo = getDpiArrayCastInfo(target);
434 if (!sourceInfo || !targetInfo)
439 return sourceInfo->isRef == targetInfo->isRef &&
440 sourceInfo->isPacked == targetInfo->isPacked &&
441 sourceInfo->elementType == targetInfo->elementType &&
442 (targetInfo->isOpen && !sourceInfo->isOpen);
450 using OpConversionPattern::OpConversionPattern;
453 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
454 ConversionPatternRewriter &rewriter)
const override {
455 rewriter.setInsertionPoint(op);
458 auto portInfo = getModulePortInfo(*typeConverter, op);
459 if (failed(portInfo))
462 auto hwModuleOp = hw::HWModuleOp::create(rewriter, op.getLoc(),
463 op.getSymNameAttr(), *portInfo);
466 SymbolTable::setSymbolVisibility(hwModuleOp,
467 SymbolTable::getSymbolVisibility(op));
468 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
470 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
472 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
473 hwModuleOp.getBodyRegion().end());
476 rewriter.eraseOp(op);
482 using OpConversionPattern::OpConversionPattern;
485 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
486 ConversionPatternRewriter &rewriter)
const override {
487 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
493 using OpConversionPattern::OpConversionPattern;
496 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
497 ConversionPatternRewriter &rewriter)
const override {
498 auto instName = op.getInstanceNameAttr();
499 auto moduleName = op.getModuleNameAttr();
502 rewriter.setInsertionPoint(op);
503 auto instOp = hw::InstanceOp::create(
504 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
505 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
506 rewriter.getArrayAttr({}),
nullptr,
510 op.replaceAllUsesWith(instOp.getResults());
511 rewriter.eraseOp(op);
516static void getValuesToObserve(Region *region,
517 function_ref<
void(Value)> setInsertionPoint,
518 const TypeConverter *typeConverter,
519 ConversionPatternRewriter &rewriter,
520 SmallVector<Value> &observeValues) {
521 SmallDenseSet<Value> alreadyObserved;
522 Location loc = region->getLoc();
524 auto probeIfSignal = [&](Value value) -> Value {
525 if (!isa<llhd::RefType>(value.getType()))
527 return llhd::ProbeOp::create(rewriter, loc, value);
530 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
531 [&](Operation *operation) {
532 for (
auto value : operation->getOperands()) {
533 if (isa<BlockArgument>(value))
534 value = rewriter.getRemappedValue(value);
536 if (region->isAncestor(value.getParentRegion()))
538 if (
auto *defOp = value.getDefiningOp();
539 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
541 if (!alreadyObserved.insert(value).second)
544 OpBuilder::InsertionGuard g(rewriter);
545 if (
auto remapped = rewriter.getRemappedValue(value)) {
546 setInsertionPoint(remapped);
547 observeValues.push_back(probeIfSignal(remapped));
549 setInsertionPoint(value);
550 auto type = typeConverter->convertType(value.getType());
551 auto converted = typeConverter->materializeTargetConversion(
552 rewriter, loc, type, value);
553 observeValues.push_back(probeIfSignal(converted));
560 using OpConversionPattern::OpConversionPattern;
563 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
564 ConversionPatternRewriter &rewriter)
const override {
566 SmallVector<Value> observedValues;
567 if (op.getKind() == ProcedureKind::AlwaysComb ||
568 op.getKind() == ProcedureKind::AlwaysLatch) {
569 auto setInsertionPoint = [&](Value value) {
570 rewriter.setInsertionPoint(op);
572 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
573 rewriter, observedValues);
576 auto loc = op.getLoc();
577 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
582 if (op.getKind() == ProcedureKind::Initial ||
583 op.getKind() == ProcedureKind::Final) {
585 if (op.getKind() == ProcedureKind::Initial)
586 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
588 newOp = llhd::FinalOp::create(rewriter, loc);
589 auto &body = newOp->getRegion(0);
590 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
592 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
593 rewriter.setInsertionPoint(returnOp);
594 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
596 rewriter.eraseOp(op);
601 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
606 rewriter.createBlock(&newOp.getBody());
607 auto *block = &op.getBody().front();
608 cf::BranchOp::create(rewriter, loc, block);
609 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
610 newOp.getBody().end());
618 if (op.getKind() == ProcedureKind::AlwaysComb ||
619 op.getKind() == ProcedureKind::AlwaysLatch) {
620 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
621 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
622 ValueRange{}, block);
629 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
630 rewriter.setInsertionPoint(returnOp);
631 cf::BranchOp::create(rewriter, loc, block);
632 rewriter.eraseOp(returnOp);
635 rewriter.eraseOp(op);
645 using OpConversionPattern::OpConversionPattern;
648 matchAndRewrite(CoroutineOp op, OpAdaptor adaptor,
649 ConversionPatternRewriter &rewriter)
const override {
650 auto funcType = op.getFunctionType();
651 TypeConverter::SignatureConversion sigConversion(funcType.getNumInputs());
652 for (
auto [i, type] :
llvm::enumerate(funcType.getInputs())) {
653 auto converted = typeConverter->convertType(type);
656 sigConversion.addInputs(i, converted);
658 SmallVector<Type> resultTypes;
659 if (failed(typeConverter->convertTypes(funcType.getResults(), resultTypes)))
662 auto newFuncType = FunctionType::get(
663 rewriter.getContext(), sigConversion.getConvertedTypes(), resultTypes);
664 auto newOp = llhd::CoroutineOp::create(rewriter, op.getLoc(),
665 op.getSymName(), newFuncType);
666 newOp.setSymVisibilityAttr(op.getSymVisibilityAttr());
667 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
668 newOp.getBody().end());
669 if (failed(rewriter.convertRegionTypes(&newOp.getBody(), *typeConverter,
675 llvm::make_early_inc_range(newOp.getBody().getOps<ReturnOp>())) {
676 rewriter.setInsertionPoint(returnOp);
677 rewriter.replaceOpWithNewOp<llhd::ReturnOp>(returnOp, ValueRange{});
680 rewriter.eraseOp(op);
686 using OpConversionPattern::OpConversionPattern;
689 matchAndRewrite(CallCoroutineOp op, OpAdaptor adaptor,
690 ConversionPatternRewriter &rewriter)
const override {
691 SmallVector<Type> convResTypes;
692 if (failed(typeConverter->convertTypes(op.getResultTypes(), convResTypes)))
694 rewriter.replaceOpWithNewOp<llhd::CallCoroutineOp>(
695 op, convResTypes, adaptor.getCallee(), adaptor.getOperands());
701 using OpConversionPattern::OpConversionPattern;
704 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
705 ConversionPatternRewriter &rewriter)
const override {
739 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
745 if (op.getBody().front().empty()) {
748 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
752 auto *waitBlock = rewriter.createBlock(resumeBlock);
753 auto *checkBlock = rewriter.createBlock(resumeBlock);
755 auto loc = op.getLoc();
756 rewriter.setInsertionPoint(op);
757 cf::BranchOp::create(rewriter, loc, waitBlock);
767 SmallVector<Value> valuesBefore;
768 rewriter.setInsertionPointToEnd(waitBlock);
769 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
770 bool allDetectsAreAnyChange =
true;
772 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
773 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
774 allDetectsAreAnyChange =
false;
775 valuesBefore.push_back(detectOp.getInput());
776 rewriter.eraseOp(detectOp);
782 SmallVector<Value> observeValues;
783 auto setInsertionPointAfterDef = [&](Value value) {
784 if (
auto *op = value.getDefiningOp())
785 rewriter.setInsertionPointAfter(op);
786 if (
auto arg = dyn_cast<BlockArgument>(value))
787 rewriter.setInsertionPointToStart(value.getParentBlock());
790 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
791 typeConverter, rewriter, observeValues);
796 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
797 observeValues, ValueRange{}, checkBlock);
798 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
799 rewriter.eraseOp(clonedOp);
803 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
804 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
806 rewriter.eraseOp(op);
810 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
811 assert(before.getType() == after.getType() &&
812 "mismatched types after clone op");
813 auto beforeType = cast<IntType>(before.getType());
817 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
818 constexpr int LSB = 0;
820 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
822 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
823 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
826 auto intType = rewriter.getIntegerType(beforeType.getWidth());
827 before = typeConverter->materializeTargetConversion(rewriter, loc,
829 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
832 if (edge == Edge::AnyChange)
833 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
836 SmallVector<Value> disjuncts;
839 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
841 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
843 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
844 disjuncts.push_back(posedge);
847 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
849 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
851 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
852 disjuncts.push_back(posedge);
855 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
862 SmallVector<Value> triggers;
863 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
864 if (!allDetectsAreAnyChange) {
865 if (!isa<IntType>(before.getType()))
866 return detectOp->emitError() <<
"requires int operand";
868 rewriter.setInsertionPoint(detectOp);
870 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
871 if (detectOp.getCondition()) {
872 auto condition = typeConverter->materializeTargetConversion(
873 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
875 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
877 triggers.push_back(trigger);
880 rewriter.eraseOp(detectOp);
883 rewriter.setInsertionPointToEnd(checkBlock);
884 if (triggers.empty()) {
889 cf::BranchOp::create(rewriter, loc, resumeBlock);
895 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
896 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
905static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
906 ConversionPatternRewriter &rewriter) {
908 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
909 rewriter.setInsertionPoint(op);
910 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
911 adaptor.getDelay(), ValueRange{},
912 ValueRange{}, resumeBlock);
913 rewriter.setInsertionPointToStart(resumeBlock);
918static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
919 ConversionPatternRewriter &rewriter) {
920 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
929 ConversionPatternRewriter &rewriter) {
931 if (isa<mlir::LLVM::LLVMPointerType>(type))
932 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
935 if (isa<llhd::TimeType>(type)) {
937 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
938 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
942 if (
auto floatType = dyn_cast<FloatType>(type)) {
943 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
944 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
948 if (
auto strType = dyn_cast<sim::DynamicStringType>(type))
949 return sim::StringConstantOp::create(rewriter, loc, strType,
"");
952 if (
auto queueType = dyn_cast<sim::QueueType>(type))
953 return sim::QueueEmptyOp::create(rewriter, loc, queueType);
956 int64_t width = hw::getBitWidth(type);
964 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
967struct ClassPropertyRefOpConversion
969 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
970 ClassTypeCache &cache)
974 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
975 ConversionPatternRewriter &rewriter)
const override {
976 Location loc = op.getLoc();
977 MLIRContext *ctx = rewriter.getContext();
980 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
982 Value instRef = adaptor.getInstance();
986 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
987 SymbolRefAttr classSym = classRefTy.getClassSym();
988 ModuleOp mod = op->getParentOfType<ModuleOp>();
989 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
990 return rewriter.notifyMatchFailure(op,
991 "Could not resolve class struct for " +
992 classSym.getRootReference().str());
994 auto structInfo = cache.getStructInfo(classSym);
995 assert(structInfo &&
"class struct info must exist");
996 auto structTy = structInfo->classBody;
999 auto propSym = op.getProperty();
1000 auto pathOpt = structInfo->getFieldPath(propSym);
1002 return rewriter.notifyMatchFailure(op,
1003 "no GEP path for property " + propSym);
1005 auto i32Ty = IntegerType::get(ctx, 32);
1006 SmallVector<Value> idxVals;
1007 for (
unsigned idx : *pathOpt)
1008 idxVals.push_back(LLVM::ConstantOp::create(
1009 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
1012 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
1014 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
1017 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
1021 rewriter.replaceOp(op, fieldRef);
1026 ClassTypeCache &cache;
1030 using OpConversionPattern::OpConversionPattern;
1033 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
1034 ConversionPatternRewriter &rewriter)
const override {
1036 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
1037 Type srcTy = adaptor.getInstance().getType();
1040 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
1043 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
1044 rewriter.replaceOp(op, adaptor.getInstance());
1047 return rewriter.notifyMatchFailure(
1048 op,
"Upcast applied to non-opaque pointers!");
1054 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
1055 ClassTypeCache &cache, FunctionCache &funcCache)
1057 funcCache(funcCache) {}
1060 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
1061 ConversionPatternRewriter &rewriter)
const override {
1062 Location loc = op.getLoc();
1063 MLIRContext *ctx = rewriter.getContext();
1065 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
1066 auto sym = handleTy.getClassSym();
1068 ModuleOp mod = op->getParentOfType<ModuleOp>();
1070 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
1071 return op.emitError() <<
"Could not resolve class struct for " << sym;
1073 auto structTy = cache.getStructInfo(sym)->classBody;
1074 auto typeInfo = cache.getStructInfo(sym)->typeInfo;
1079 for (
auto memberTy : structTy.getBody()) {
1080 if (!LLVM::isCompatibleType(memberTy) &&
1081 !memberTy.hasTrait<DataLayoutTypeInterface::Trait>()) {
1082 return op.emitError()
1083 <<
"class struct has member types with no data layout";
1089 uint64_t byteSize = dl.getTypeSize(structTy);
1090 auto i64Ty = IntegerType::get(ctx, 64);
1091 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
1092 rewriter.getI64IntegerAttr(byteSize));
1095 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
1096 auto mallocFn = funcCache.getOrCreate(rewriter,
"malloc", {i64Ty}, {ptrTy});
1098 func::CallOp::create(rewriter, loc, mallocFn, ValueRange{cSize});
1101 LLVM::AddressOfOp::create(rewriter, loc, typeInfo.global);
1102 auto i32Ty = IntegerType::get(ctx, 32);
1103 auto headerIdx = LLVM::ConstantOp::create(
1104 rewriter, loc, i32Ty,
1105 rewriter.getI32IntegerAttr(cache.getStructInfo(sym)->headerFieldIndex));
1106 auto typeInfoIdx = LLVM::ConstantOp::create(
1107 rewriter, loc, i32Ty,
1108 rewriter.getI32IntegerAttr(
1109 cache.getStructInfo(sym)->typeInfoFieldIndex));
1111 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, call.getResult(0),
1112 ValueRange{headerIdx, typeInfoIdx});
1113 LLVM::StoreOp::create(rewriter, loc, typeInfoAddr, headerPtr);
1117 rewriter.replaceOp(op, call.getResult(0));
1122 ClassTypeCache &cache;
1123 FunctionCache &funcCache;
1127 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
1128 ClassTypeCache &cache)
1132 matchAndRewrite(ClassDeclOp op, OpAdaptor,
1133 ConversionPatternRewriter &rewriter)
const override {
1135 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
1138 rewriter.eraseOp(op);
1143 ClassTypeCache &cache;
1147 using OpConversionPattern::OpConversionPattern;
1150 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
1151 ConversionPatternRewriter &rewriter)
const override {
1152 auto loc = op.getLoc();
1153 auto resultType = typeConverter->convertType(op.getResult().getType());
1155 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
1158 Value init = adaptor.getInitial();
1160 auto refType = dyn_cast<llhd::RefType>(resultType);
1162 return rewriter.notifyMatchFailure(
1163 op.getLoc(),
"variable type did not convert to llhd::RefType");
1169 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
1170 op.getNameAttr(), init);
1176 using OpConversionPattern::OpConversionPattern;
1179 matchAndRewrite(NetOp op, OpAdaptor adaptor,
1180 ConversionPatternRewriter &rewriter)
const override {
1181 auto loc = op.getLoc();
1183 auto resultType = typeConverter->convertType(op.getResult().getType());
1185 return rewriter.notifyMatchFailure(loc,
"invalid net type");
1187 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
1193 createInitialValue(op.getKind(), rewriter, loc, width,
elementType);
1194 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
1195 op, resultType, op.getNameAttr(), init);
1197 if (
auto assignedValue = adaptor.getAssignment()) {
1198 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
1199 llvm::StringRef(
"ns"), 0, 1);
1200 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
1201 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
1208 static mlir::Value createInitialValue(NetKind kind,
1209 ConversionPatternRewriter &rewriter,
1210 Location loc, int64_t width,
1221 if (kind == NetKind::Supply1 || kind == NetKind::Tri1)
1222 return APInt::getAllOnes(width);
1223 return APInt::getZero(width);
1231static LogicalResult
convert(GlobalVariableOp op,
1232 GlobalVariableOp::Adaptor adaptor,
1233 ConversionPatternRewriter &rewriter,
1234 const TypeConverter &typeConverter) {
1235 auto type = typeConverter.convertType(op.getType());
1236 auto sig = llhd::GlobalSignalOp::create(rewriter, op.getLoc(),
1237 op.getSymNameAttr(), type);
1238 sig.getInitRegion().takeBody(op.getInitRegion());
1239 rewriter.eraseOp(op);
1244static LogicalResult
convert(GetGlobalVariableOp op,
1245 GetGlobalVariableOp::Adaptor adaptor,
1246 ConversionPatternRewriter &rewriter,
1247 const TypeConverter &typeConverter) {
1248 auto type = typeConverter.convertType(op.getType());
1249 rewriter.replaceOpWithNewOp<llhd::GetGlobalSignalOp>(op, type,
1250 op.getGlobalNameAttr());
1259 using OpConversionPattern::OpConversionPattern;
1262 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
1263 ConversionPatternRewriter &rewriter)
const override {
1265 auto value = op.getValue().toAPInt(
false);
1266 auto type = rewriter.getIntegerType(value.getBitWidth());
1268 op, type, rewriter.getIntegerAttr(type, value));
1274 using OpConversionPattern::OpConversionPattern;
1277 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
1278 ConversionPatternRewriter &rewriter)
const override {
1279 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
1285 using OpConversionPattern::OpConversionPattern;
1288 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
1289 ConversionPatternRewriter &rewriter)
const override {
1290 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
1291 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
1292 StringRef(
"fs"), 0, 0));
1298 using OpConversionPattern::OpConversionPattern;
1300 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
1301 ConversionPatternRewriter &rewriter)
const override {
1302 const auto resultType =
1303 typeConverter->convertType(op.getResult().getType());
1304 const auto intType = mlir::cast<IntegerType>(resultType);
1306 const auto str = op.getValue();
1307 const unsigned byteWidth = intType.getWidth();
1308 APInt value(byteWidth, 0);
1311 const size_t maxChars =
1312 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
1313 for (
size_t i = 0; i < maxChars; i++) {
1314 const size_t pos = str.size() - 1 - i;
1315 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
1316 value |= APInt(byteWidth, asciiChar) << (8 * i);
1320 op, resultType, rewriter.getIntegerAttr(resultType, value));
1326 using OpConversionPattern::OpConversionPattern;
1328 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1329 ConversionPatternRewriter &rewriter)
const override {
1330 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1336 using OpConversionPattern::OpConversionPattern;
1338 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1339 ConversionPatternRewriter &rewriter)
const override {
1340 Type resultType = typeConverter->convertType(op.getResult().getType());
1342 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1343 adaptor.getValue());
1349 using OpConversionPattern::OpConversionPattern;
1352 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1353 ConversionPatternRewriter &rewriter)
const override {
1356 Type resultType = typeConverter->convertType(op.getResult().getType());
1357 Type inputType = adaptor.getInput().getType();
1358 int32_t low = adaptor.getLowBit();
1360 if (isa<IntegerType>(inputType)) {
1361 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1362 int32_t resultWidth = hw::getBitWidth(resultType);
1363 int32_t high = low + resultWidth;
1365 SmallVector<Value> toConcat;
1368 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
1370 if (low < inputWidth && high > 0) {
1371 int32_t lowIdx = std::max(low, 0);
1374 rewriter.getIntegerType(
1375 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
1376 adaptor.getInput(), lowIdx);
1377 toConcat.push_back(middle);
1380 int32_t diff = high - inputWidth;
1384 toConcat.push_back(val);
1389 rewriter.replaceOp(op, concat);
1393 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1394 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
1395 int32_t inputWidth = arrTy.getNumElements();
1397 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1398 resArrTy && resArrTy != arrTy.getElementType()) {
1399 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
1400 if (elementWidth < 0)
1403 int32_t high = low + resArrTy.getNumElements();
1404 int32_t resWidth = resArrTy.getNumElements();
1406 SmallVector<Value> toConcat;
1409 rewriter, op.getLoc(),
1410 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
1413 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
1415 toConcat.push_back(res);
1418 if (low < inputWidth && high > 0) {
1419 int32_t lowIdx = std::max(0, low);
1421 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
1425 arrTy.getElementType(),
1426 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
1427 adaptor.getInput(), lowIdxVal);
1428 toConcat.push_back(middle);
1431 int32_t diff = high - inputWidth;
1434 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
1436 rewriter, op.getLoc(),
1437 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
1438 toConcat.push_back(val);
1443 rewriter.replaceOp(op, concat);
1448 if (low < 0 || low >= inputWidth) {
1449 int32_t bw = hw::getBitWidth(resultType);
1455 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
1456 rewriter.replaceOp(op, bitcast);
1461 rewriter.getIntegerType(width),
1462 adaptor.getLowBit());
1463 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
1472 using OpConversionPattern::OpConversionPattern;
1475 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1476 ConversionPatternRewriter &rewriter)
const override {
1478 Type resultType = typeConverter->convertType(op.getResult().getType());
1480 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1482 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1483 int64_t width = hw::getBitWidth(inputType);
1488 rewriter, op.getLoc(),
1489 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1490 adaptor.getLowBit());
1491 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1492 op, resultType, adaptor.getInput(), lowBit);
1496 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1498 rewriter, op.getLoc(),
1499 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1500 adaptor.getLowBit());
1504 if (arrType.getElementType() !=
1505 cast<llhd::RefType>(resultType).getNestedType()) {
1506 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1507 op, resultType, adaptor.getInput(), lowBit);
1511 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1521 using OpConversionPattern::OpConversionPattern;
1524 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1525 ConversionPatternRewriter &rewriter)
const override {
1526 Type resultType = typeConverter->convertType(op.getResult().getType());
1527 Type inputType = adaptor.getInput().getType();
1529 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1530 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1531 intType.getWidth(), op->getLoc());
1532 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1533 adaptor.getInput(), amount);
1535 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1539 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1540 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1541 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1544 bool isSingleElementExtract = arrType.getElementType() == resultType;
1546 if (isSingleElementExtract)
1547 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1551 adaptor.getInput(), idx);
1561 using OpConversionPattern::OpConversionPattern;
1564 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1565 ConversionPatternRewriter &rewriter)
const override {
1567 Type resultType = typeConverter->convertType(op.getResult().getType());
1569 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1571 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1572 int64_t width = hw::getBitWidth(inputType);
1577 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1578 llvm::Log2_64_Ceil(width), op->getLoc());
1579 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1580 op, resultType, adaptor.getInput(), amount);
1584 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1585 Value idx = adjustIntegerWidth(
1586 rewriter, adaptor.getLowBit(),
1587 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1589 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1590 bool isSingleElementExtract =
1591 arrType.getElementType() == resultNestedType;
1593 if (isSingleElementExtract)
1594 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1597 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1598 op, resultType, adaptor.getInput(), idx);
1608 using OpConversionPattern::OpConversionPattern;
1611 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1612 ConversionPatternRewriter &rewriter)
const override {
1613 Type resultType = typeConverter->convertType(op.getResult().getType());
1615 adaptor.getElements());
1621 using OpConversionPattern::OpConversionPattern;
1624 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1625 ConversionPatternRewriter &rewriter)
const override {
1626 Type resultType = typeConverter->convertType(op.getResult().getType());
1628 adaptor.getFields());
1634 using OpConversionPattern::OpConversionPattern;
1637 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1638 ConversionPatternRewriter &rewriter)
const override {
1640 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1645struct StructExtractRefOpConversion
1647 using OpConversionPattern::OpConversionPattern;
1650 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1651 ConversionPatternRewriter &rewriter)
const override {
1652 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1653 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1659 using OpConversionPattern::OpConversionPattern;
1662 matchAndRewrite(UnionCreateOp op, OpAdaptor adaptor,
1663 ConversionPatternRewriter &rewriter)
const override {
1664 Type resultType = typeConverter->convertType(op.getResult().getType());
1665 rewriter.replaceOpWithNewOp<hw::UnionCreateOp>(
1666 op, resultType, adaptor.getFieldNameAttr(), adaptor.getInput());
1672 using OpConversionPattern::OpConversionPattern;
1675 matchAndRewrite(UnionExtractOp op, OpAdaptor adaptor,
1676 ConversionPatternRewriter &rewriter)
const override {
1677 rewriter.replaceOpWithNewOp<hw::UnionExtractOp>(op, adaptor.getInput(),
1678 adaptor.getFieldNameAttr());
1683struct UnionExtractRefOpConversion
1685 using OpConversionPattern::OpConversionPattern;
1688 matchAndRewrite(UnionExtractRefOp op, OpAdaptor adaptor,
1689 ConversionPatternRewriter &rewriter)
const override {
1690 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1691 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1697 using OpConversionPattern::OpConversionPattern;
1699 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1700 ConversionPatternRewriter &rewriter)
const override {
1701 Type resultType = typeConverter->convertType(op.getInput().getType());
1704 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1705 adaptor.getInput(), max);
1711 using OpConversionPattern::OpConversionPattern;
1713 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1714 ConversionPatternRewriter &rewriter)
const override {
1715 Type resultType = typeConverter->convertType(op.getInput().getType());
1718 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1719 adaptor.getInput(), zero);
1725 using OpConversionPattern::OpConversionPattern;
1727 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1728 ConversionPatternRewriter &rewriter)
const override {
1730 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1736 using OpConversionPattern::OpConversionPattern;
1738 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1739 ConversionPatternRewriter &rewriter)
const override {
1740 Type resultType = typeConverter->convertType(op.getInput().getType());
1741 if (isa_and_nonnull<IntegerType>(resultType)) {
1744 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1745 adaptor.getInput(), zero);
1748 if (isa_and_nonnull<FloatType>(resultType)) {
1749 Value zero = arith::ConstantOp::create(
1750 rewriter, op->getLoc(), rewriter.getFloatAttr(resultType, 0.0));
1751 rewriter.replaceOpWithNewOp<arith::CmpFOp>(op, arith::CmpFPredicate::ONE,
1752 adaptor.getInput(), zero);
1760 using OpConversionPattern::OpConversionPattern;
1762 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1763 ConversionPatternRewriter &rewriter)
const override {
1765 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1768 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1774 using OpConversionPattern::OpConversionPattern;
1776 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1777 ConversionPatternRewriter &rewriter)
const override {
1779 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1782 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1788 using OpConversionPattern::OpConversionPattern;
1790 matchAndRewrite(NegRealOp op, OpAdaptor adaptor,
1791 ConversionPatternRewriter &rewriter)
const override {
1792 rewriter.replaceOpWithNewOp<arith::NegFOp>(op, adaptor.getInput());
1797template <
typename SourceOp,
typename TargetOp>
1800 using OpAdaptor =
typename SourceOp::Adaptor;
1803 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1804 ConversionPatternRewriter &rewriter)
const override {
1805 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1806 adaptor.getRhs(),
false);
1811template <
typename SourceOp,
typename TargetOp>
1814 using OpAdaptor =
typename SourceOp::Adaptor;
1817 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1818 ConversionPatternRewriter &rewriter)
const override {
1819 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1825template <
typename SourceOp, ICmpPredicate pred>
1828 using OpAdaptor =
typename SourceOp::Adaptor;
1831 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1832 ConversionPatternRewriter &rewriter)
const override {
1834 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1836 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1837 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1842template <
typename SourceOp, arith::CmpFPredicate pred>
1845 using OpAdaptor =
typename SourceOp::Adaptor;
1848 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1849 ConversionPatternRewriter &rewriter)
const override {
1851 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1853 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1854 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1859template <
typename SourceOp,
bool withoutX>
1862 using OpAdaptor =
typename SourceOp::Adaptor;
1865 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1866 ConversionPatternRewriter &rewriter)
const override {
1872 unsigned bitWidth = op.getLhs().getType().getWidth();
1873 auto ignoredBits = APInt::getZero(bitWidth);
1874 auto detectIgnoredBits = [&](Value value) {
1875 auto constOp = value.getDefiningOp<ConstantOp>();
1878 auto constValue = constOp.getValue();
1880 ignoredBits |= constValue.getZBits();
1882 ignoredBits |= constValue.getUnknownBits();
1884 detectIgnoredBits(op.getLhs());
1885 detectIgnoredBits(op.getRhs());
1889 Value lhs = adaptor.getLhs();
1890 Value rhs = adaptor.getRhs();
1891 if (!ignoredBits.isZero()) {
1892 ignoredBits.flipAllBits();
1894 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1895 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1898 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1908 using OpConversionPattern::OpConversionPattern;
1911 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1912 ConversionPatternRewriter &rewriter)
const override {
1913 Location loc = op.getLoc();
1914 Type resultType = typeConverter->convertType(op.getResult().getType());
1916 op.emitError(
"conversion result type is not currently supported");
1919 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1920 int64_t resultBw = hw::getBitWidth(resultType);
1921 if (inputBw == -1 || resultBw == -1) {
1922 if (isSupportedDpiOpenArrayCast(op.getInput().getType(),
1923 op.getResult().getType())) {
1924 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1925 op, resultType, adaptor.getInput());
1928 if (hasOpenArrayBoundaryType(op.getInput().getType()) ||
1929 hasOpenArrayBoundaryType(op.getResult().getType())) {
1930 op.emitError(
"unsupported DPI open-array conversion from ")
1931 << op.getInput().getType() <<
" to " << op.getResult().getType();
1938 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1939 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1942 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1943 rewriter.replaceOp(op, result);
1948template <
typename SourceOp>
1951 using OpAdaptor =
typename SourceOp::Adaptor;
1952 using ConversionPattern::typeConverter;
1955 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1956 ConversionPatternRewriter &rewriter)
const override {
1957 auto type = typeConverter->convertType(op.getResult().getType());
1958 if (type == adaptor.getInput().getType())
1959 rewriter.replaceOp(op, adaptor.getInput());
1961 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1967template <
typename SourceOp>
1970 using OpAdaptor =
typename SourceOp::Adaptor;
1971 using ConversionPattern::typeConverter;
1974 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1975 ConversionPatternRewriter &rewriter)
const override {
1976 rewriter.replaceOp(op, adaptor.getInput());
1982 using OpConversionPattern::OpConversionPattern;
1985 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1986 ConversionPatternRewriter &rewriter)
const override {
1987 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1988 op.getType().getWidth());
1994 using OpConversionPattern::OpConversionPattern;
1997 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1998 ConversionPatternRewriter &rewriter)
const override {
1999 auto targetWidth = op.getType().getWidth();
2000 auto inputWidth = op.getInput().getType().getWidth();
2003 rewriter, op.getLoc(),
2004 rewriter.getIntegerType(targetWidth - inputWidth), 0);
2007 op, ValueRange{zeroExt, adaptor.getInput()});
2013 using OpConversionPattern::OpConversionPattern;
2016 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
2017 ConversionPatternRewriter &rewriter)
const override {
2018 auto type = typeConverter->convertType(op.getType());
2020 comb::createOrFoldSExt(rewriter, op.getLoc(), adaptor.getInput(), type);
2021 rewriter.replaceOp(op, value);
2027 using OpConversionPattern::OpConversionPattern;
2030 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
2031 ConversionPatternRewriter &rewriter)
const override {
2032 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
2033 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2039 using OpConversionPattern::OpConversionPattern;
2042 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
2043 ConversionPatternRewriter &rewriter)
const override {
2044 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
2045 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2051 using OpConversionPattern::OpConversionPattern;
2054 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
2055 ConversionPatternRewriter &rewriter)
const override {
2056 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
2062 using OpConversionPattern::OpConversionPattern;
2065 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
2066 ConversionPatternRewriter &rewriter)
const override {
2067 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
2068 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2074 using OpConversionPattern::OpConversionPattern;
2077 matchAndRewrite(ConvertRealOp op, OpAdaptor adaptor,
2078 ConversionPatternRewriter &rewriter)
const override {
2079 op.getInput().getType().getWidth() < op.getResult().getType().getWidth()
2080 ? rewriter.replaceOpWithNewOp<arith::ExtFOp>(
2081 op, typeConverter->convertType(op.getType()), adaptor.getInput())
2082 : rewriter.replaceOpWithNewOp<arith::TruncFOp>(
2083 op, typeConverter->
convertType(op.getType()), adaptor.getInput());
2093 using OpConversionPattern::OpConversionPattern;
2096 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
2097 ConversionPatternRewriter &rewriter)
const override {
2098 SmallVector<Type> convResTypes;
2099 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2102 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
2103 op, convResTypes, op.getInstanceName(), op.getModuleName(),
2104 adaptor.getOperands(), op.getArgNames(),
2105 op.getResultNames(),
2106 rewriter.getArrayAttr({}),
nullptr);
2113 using OpConversionPattern::OpConversionPattern;
2116 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
2117 ConversionPatternRewriter &rewriter)
const override {
2118 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
2124 using OpConversionPattern::OpConversionPattern;
2127 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
2128 ConversionPatternRewriter &rewriter)
const override {
2129 SmallVector<Type> convResTypes;
2130 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2132 rewriter.replaceOpWithNewOp<func::CallOp>(
2133 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
2138struct FuncDPICallOpConversion
2140 using OpConversionPattern::OpConversionPattern;
2143 matchAndRewrite(moore::FuncDPICallOp op, OpAdaptor adaptor,
2144 ConversionPatternRewriter &rewriter)
const override {
2145 SmallVector<Type> convResTypes;
2146 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2148 rewriter.replaceOpWithNewOp<sim::DPICallOp>(
2149 op, convResTypes, op.getCalleeAttr(), Value(),
2150 Value(), adaptor.getInputs());
2156 using OpConversionPattern::OpConversionPattern;
2159 matchAndRewrite(moore::DPIFuncOp op, OpAdaptor adaptor,
2160 ConversionPatternRewriter &rewriter)
const override {
2162 auto toDPIDir = [](moore::DPIArgDirection dir) -> sim::DPIDirection {
2164 case moore::DPIArgDirection::In:
2165 return sim::DPIDirection::Input;
2166 case moore::DPIArgDirection::Out:
2167 return sim::DPIDirection::Output;
2168 case moore::DPIArgDirection::InOut:
2169 return sim::DPIDirection::InOut;
2170 case moore::DPIArgDirection::Return:
2171 return sim::DPIDirection::Return;
2173 llvm_unreachable(
"unknown DPIArgDirection");
2177 auto dirs = op.getDpiArgDirs();
2178 auto names = op.getDpiArgNames();
2179 SmallVector<Type> argTypes;
2180 op.getDPIArgTypes(argTypes);
2182 SmallVector<sim::DPIArgument> dpiArguments;
2183 for (
auto [dirAttr, nameAttr, mooreType] :
2184 llvm::zip(dirs, names, argTypes)) {
2185 auto dir = toDPIDir(cast<moore::DPIArgDirectionAttr>(dirAttr).getValue());
2186 auto name = cast<StringAttr>(nameAttr);
2187 Type coreType = typeConverter->convertType(mooreType);
2189 return op.emitOpError(
"argument '")
2190 << name <<
"' has unsupported type " << mooreType;
2191 dpiArguments.push_back({name, coreType, dir});
2194 auto coreDPIFuncType =
2195 sim::DPIFunctionType::get(rewriter.getContext(), dpiArguments);
2196 auto simFunc = sim::DPIFuncOp::create(
2197 rewriter, op.getLoc(), op.getSymNameAttr(), coreDPIFuncType,
2198 op.getArgumentLocsAttr(), op.getVerilogNameAttr());
2199 SymbolTable::setSymbolVisibility(simFunc,
2200 SymbolTable::getSymbolVisibility(op));
2201 rewriter.eraseOp(op);
2206struct UnrealizedConversionCastConversion
2208 using OpConversionPattern::OpConversionPattern;
2211 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
2212 ConversionPatternRewriter &rewriter)
const override {
2213 SmallVector<Type> convResTypes;
2214 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2219 if (convResTypes == adaptor.getOperands().getTypes()) {
2220 rewriter.replaceOp(op, adaptor.getOperands());
2224 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2225 op, convResTypes, adaptor.getOperands());
2231 using OpConversionPattern::OpConversionPattern;
2234 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
2235 ConversionPatternRewriter &rewriter)
const override {
2236 Type resultType = typeConverter->convertType(op.getResult().getType());
2240 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2241 resultType.getIntOrFloatBitWidth(), op->getLoc());
2242 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
2249 using OpConversionPattern::OpConversionPattern;
2252 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
2253 ConversionPatternRewriter &rewriter)
const override {
2254 Type resultType = typeConverter->convertType(op.getResult().getType());
2258 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2259 resultType.getIntOrFloatBitWidth(), op->getLoc());
2261 op, resultType, adaptor.getValue(), amount,
false);
2267 using OpConversionPattern::OpConversionPattern;
2270 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
2271 ConversionPatternRewriter &rewriter)
const override {
2272 Type resultType = typeConverter->convertType(op.getResult().getType());
2274 Location loc = op->getLoc();
2279 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
2280 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
2283 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
2291 using OpConversionPattern::OpConversionPattern;
2294 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
2295 ConversionPatternRewriter &rewriter)
const override {
2296 Type resultType = typeConverter->convertType(op.getResult().getType());
2300 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
2301 op, resultType, adaptor.getLhs(), adaptor.getRhs());
2307 using OpConversionPattern::OpConversionPattern;
2310 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
2311 ConversionPatternRewriter &rewriter)
const override {
2312 Type resultType = typeConverter->convertType(op.getResult().getType());
2316 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2317 resultType.getIntOrFloatBitWidth(), op->getLoc());
2319 op, resultType, adaptor.getValue(), amount,
false);
2325 using OpConversionPattern::OpConversionPattern;
2328 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
2329 ConversionPatternRewriter &rewriter)
const override {
2330 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
2335struct AssignedVariableOpConversion
2337 using OpConversionPattern::OpConversionPattern;
2340 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
2341 ConversionPatternRewriter &rewriter)
const override {
2342 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
2343 adaptor.getNameAttr());
2349static llhd::TimeAttr
2350getBlockingOrContinuousAssignDelay(mlir::MLIRContext *
context) {
2351 return llhd::TimeAttr::get(
context, 0U,
"ns", 0, 1);
2354template <
typename OpTy>
2357 using OpAdaptor =
typename OpTy::Adaptor;
2360 matchAndRewrite(OpTy op, OpAdaptor adaptor,
2361 ConversionPatternRewriter &rewriter)
const override {
2364 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
2365 std::is_same_v<OpTy, BlockingAssignOp>) {
2366 delay = llhd::ConstantTimeOp::create(
2367 rewriter, op->getLoc(),
2368 getBlockingOrContinuousAssignDelay(op->getContext()));
2369 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
2371 delay = llhd::ConstantTimeOp::create(
2372 rewriter, op->getLoc(),
2373 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
2376 delay = adaptor.getDelay();
2379 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
2380 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
2386 using OpConversionPattern::OpConversionPattern;
2389 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
2390 ConversionPatternRewriter &rewriter)
const override {
2395 auto type = typeConverter->convertType(op.getType());
2397 auto hasNoWriteEffect = [](Region ®ion) {
2398 auto result = region.walk([](Operation *operation) {
2399 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
2400 if (!memOp.hasEffect<MemoryEffects::Write>() &&
2401 !memOp.hasEffect<MemoryEffects::Free>())
2402 return WalkResult::advance();
2404 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
2405 return WalkResult::advance();
2407 return WalkResult::interrupt();
2409 return !result.wasInterrupted();
2412 if (hasNoWriteEffect(op.getTrueRegion()) &&
2413 hasNoWriteEffect(op.getFalseRegion())) {
2414 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
2415 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
2417 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
2418 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
2420 Value convTrueVal = typeConverter->materializeTargetConversion(
2421 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
2422 Value convFalseVal = typeConverter->materializeTargetConversion(
2423 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
2425 rewriter.eraseOp(trueTerm);
2426 rewriter.eraseOp(falseTerm);
2428 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
2429 convTrueVal, convFalseVal);
2434 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
2435 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
2436 ifOp.getThenRegion().end());
2437 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
2438 ifOp.getElseRegion().end());
2439 rewriter.replaceOp(op, ifOp);
2445 using OpConversionPattern::OpConversionPattern;
2448 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
2449 ConversionPatternRewriter &rewriter)
const override {
2450 if (isa<llhd::GlobalSignalOp>(op->getParentOp()))
2451 rewriter.replaceOpWithNewOp<llhd::YieldOp>(op, adaptor.getResult());
2453 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
2458template <
typename SourceOp>
2461 using OpAdaptor =
typename SourceOp::Adaptor;
2464 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2465 ConversionPatternRewriter &rewriter)
const override {
2466 rewriter.modifyOpInPlace(op,
2467 [&]() { op->setOperands(adaptor.getOperands()); });
2472template <
typename MooreOpTy,
typename VerifOpTy>
2475 using OpAdaptor =
typename MooreOpTy::Adaptor;
2478 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
2479 ConversionPatternRewriter &rewriter)
const override {
2481 op.getLabel().has_value()
2482 ? StringAttr::get(op->getContext(), op.getLabel().value())
2483 : StringAttr::
get(op->getContext());
2484 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
2495 using OpConversionPattern::OpConversionPattern;
2498 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2499 ConversionPatternRewriter &rewriter)
const override {
2500 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2506 using OpConversionPattern::OpConversionPattern;
2509 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2510 ConversionPatternRewriter &rewriter)
const override {
2511 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2512 adaptor.getInputs());
2517struct FormatHierPathOpConversion
2519 using OpConversionPattern::OpConversionPattern;
2522 matchAndRewrite(FormatHierPathOp op, OpAdaptor adaptor,
2523 ConversionPatternRewriter &rewriter)
const override {
2524 rewriter.replaceOpWithNewOp<sim::FormatHierPathOp>(op,
2525 adaptor.getUseEscapes());
2531 using OpConversionPattern::OpConversionPattern;
2534 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2535 ConversionPatternRewriter &rewriter)
const override {
2537 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2538 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2539 auto widthAttr = adaptor.getSpecifierWidthAttr();
2541 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2542 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2544 switch (op.getFormat()) {
2545 case IntFormat::Decimal:
2546 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2547 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2548 adaptor.getIsSignedAttr());
2550 case IntFormat::Binary:
2551 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2552 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2554 case IntFormat::Octal:
2555 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2556 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2558 case IntFormat::HexLower:
2559 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2560 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2561 isLeftAlignedAttr, padCharAttr, widthAttr);
2563 case IntFormat::HexUpper:
2564 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2565 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2566 padCharAttr, widthAttr);
2569 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2574 using OpConversionPattern::OpConversionPattern;
2577 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2578 ConversionPatternRewriter &rewriter)
const override {
2579 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2581 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2582 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2583 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2585 switch (op.getFormat()) {
2586 case RealFormat::General:
2587 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2588 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2591 case RealFormat::Float:
2592 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2593 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2596 case RealFormat::Exponential:
2597 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2598 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2606 using OpConversionPattern::OpConversionPattern;
2609 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2610 ConversionPatternRewriter &rewriter)
const override {
2611 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2617 using OpConversionPattern::OpConversionPattern;
2620 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2621 ConversionPatternRewriter &rewriter)
const override {
2622 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2628 using OpConversionPattern::OpConversionPattern;
2631 matchAndRewrite(StringGetOp op, OpAdaptor adaptor,
2632 ConversionPatternRewriter &rewriter)
const override {
2633 rewriter.replaceOpWithNewOp<sim::StringGetOp>(op, adaptor.getStr(),
2634 adaptor.getIndex());
2640 using OpConversionPattern::OpConversionPattern;
2643 matchAndRewrite(QueueSizeBIOp op, OpAdaptor adaptor,
2644 ConversionPatternRewriter &rewriter)
const override {
2645 rewriter.replaceOpWithNewOp<sim::QueueSizeOp>(op, adaptor.getQueue());
2650struct DynQueueExtractOpConversion
2652 using OpConversionPattern::OpConversionPattern;
2655 matchAndRewrite(DynQueueExtractOp op, OpAdaptor adaptor,
2656 ConversionPatternRewriter &rewriter)
const override {
2657 bool isSingleElementExtract =
2658 op.getInput().getType().getElementType() == op.getResult().getType();
2660 if (isSingleElementExtract) {
2661 rewriter.replaceOpWithNewOp<sim::QueueGetOp>(op, adaptor.getInput(),
2662 adaptor.getLowerIdx());
2664 rewriter.replaceOpWithNewOp<sim::QueueSliceOp>(
2665 op, adaptor.getInput(), adaptor.getLowerIdx(), adaptor.getUpperIdx());
2681probeRefAndDriveWithResult(OpBuilder &builder, Location loc, Value ref,
2682 const std::function<Value(Value)> &func) {
2684 Value v = llhd::ProbeOp::create(builder, loc, ref);
2687 Value delay = llhd::ConstantTimeOp::create(
2688 builder, loc, getBlockingOrContinuousAssignDelay(builder.getContext()));
2690 llhd::DriveOp::create(builder, loc, ref, func(v), delay, Value{});
2694 using OpConversionPattern::OpConversionPattern;
2697 matchAndRewrite(QueuePushBackOp op, OpAdaptor adaptor,
2698 ConversionPatternRewriter &rewriter)
const override {
2699 probeRefAndDriveWithResult(
2700 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2701 return sim::QueuePushBackOp::create(rewriter, op->getLoc(), queue,
2702 adaptor.getElement());
2705 rewriter.eraseOp(op);
2710struct QueuePushFrontOpConversion
2712 using OpConversionPattern::OpConversionPattern;
2715 matchAndRewrite(QueuePushFrontOp op, OpAdaptor adaptor,
2716 ConversionPatternRewriter &rewriter)
const override {
2718 probeRefAndDriveWithResult(
2719 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2720 return sim::QueuePushFrontOp::create(rewriter, op->getLoc(), queue,
2721 adaptor.getElement());
2724 rewriter.eraseOp(op);
2730 using OpConversionPattern::OpConversionPattern;
2733 matchAndRewrite(QueuePopBackOp op, OpAdaptor adaptor,
2734 ConversionPatternRewriter &rewriter)
const override {
2736 probeRefAndDriveWithResult(
2737 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2739 sim::QueuePopBackOp::create(rewriter, op->getLoc(), queue);
2740 popped = popBack.getPopped();
2741 return popBack.getOutQueue();
2743 rewriter.replaceOp(op, popped);
2750 using OpConversionPattern::OpConversionPattern;
2753 matchAndRewrite(QueuePopFrontOp op, OpAdaptor adaptor,
2754 ConversionPatternRewriter &rewriter)
const override {
2756 probeRefAndDriveWithResult(
2757 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2759 sim::QueuePopFrontOp::create(rewriter, op->getLoc(), queue);
2760 popped = popFront.getPopped();
2761 return popFront.getOutQueue();
2763 rewriter.replaceOp(op, popped);
2770 using OpConversionPattern::OpConversionPattern;
2773 matchAndRewrite(QueueClearOp op, OpAdaptor adaptor,
2774 ConversionPatternRewriter &rewriter)
const override {
2775 auto refType = cast<llhd::RefType>(adaptor.getQueue().getType());
2776 auto queueType = refType.getNestedType();
2778 sim::QueueEmptyOp::create(rewriter, op->getLoc(), queueType);
2781 Value delay = llhd::ConstantTimeOp::create(
2782 rewriter, op.getLoc(),
2783 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
2785 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getQueue(), emptyQueue,
2788 rewriter.eraseOp(op);
2794 using OpConversionPattern::OpConversionPattern;
2797 matchAndRewrite(QueueInsertOp op, OpAdaptor adaptor,
2798 ConversionPatternRewriter &rewriter)
const override {
2799 probeRefAndDriveWithResult(
2800 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2802 sim::QueueInsertOp::create(rewriter, op->getLoc(), queue,
2803 adaptor.getIndex(), adaptor.getItem());
2805 return insert.getOutQueue();
2807 rewriter.eraseOp(op);
2814 using OpConversionPattern::OpConversionPattern;
2817 matchAndRewrite(QueueDeleteOp op, OpAdaptor adaptor,
2818 ConversionPatternRewriter &rewriter)
const override {
2819 probeRefAndDriveWithResult(
2820 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2821 auto delOp = sim::QueueDeleteOp::create(rewriter, op->getLoc(), queue,
2822 adaptor.getIndex());
2824 return delOp.getOutQueue();
2826 rewriter.eraseOp(op);
2833 using OpConversionPattern::OpConversionPattern;
2836 matchAndRewrite(QueueResizeOp op, OpAdaptor adaptor,
2837 ConversionPatternRewriter &rewriter)
const override {
2839 rewriter.replaceOpWithNewOp<sim::QueueResizeOp>(
2840 op, getTypeConverter()->convertType(op.getResult().getType()),
2841 adaptor.getInput());
2847 using OpConversionPattern::OpConversionPattern;
2849 matchAndRewrite(QueueSetOp op, OpAdaptor adaptor,
2850 ConversionPatternRewriter &rewriter)
const override {
2851 probeRefAndDriveWithResult(
2852 rewriter, op->getLoc(), adaptor.getQueue(), [&](Value queue) {
2854 sim::QueueSetOp::create(rewriter, op.getLoc(), queue,
2855 adaptor.getIndex(), adaptor.getItem());
2856 return setOp.getOutQueue();
2858 rewriter.eraseOp(op);
2864 using OpConversionPattern::OpConversionPattern;
2867 matchAndRewrite(QueueCmpOp op, OpAdaptor adaptor,
2868 ConversionPatternRewriter &rewriter)
const override {
2876 auto unpackedPred = adaptor.getPredicateAttr().getValue();
2877 sim::QueueCmpPredicate queuePred;
2878 switch (unpackedPred) {
2879 case circt::moore::UArrayCmpPredicate::eq:
2880 queuePred = sim::QueueCmpPredicate::eq;
2882 case circt::moore::UArrayCmpPredicate::ne:
2883 queuePred = sim::QueueCmpPredicate::ne;
2887 auto cmpPred = sim::QueueCmpPredicateAttr::get(getContext(), queuePred);
2889 rewriter.replaceOpWithNewOp<sim::QueueCmpOp>(op, cmpPred, adaptor.getLhs(),
2895struct QueueFromUnpackedArrayOpConversion
2897 using OpConversionPattern::OpConversionPattern;
2900 matchAndRewrite(QueueFromUnpackedArrayOp op, OpAdaptor adaptor,
2901 ConversionPatternRewriter &rewriter)
const override {
2902 rewriter.replaceOpWithNewOp<sim::QueueFromArrayOp>(
2903 op, getTypeConverter()->convertType(op.getResult().getType()),
2904 adaptor.getInput());
2910 using OpConversionPattern::OpConversionPattern;
2913 matchAndRewrite(QueueConcatOp op, OpAdaptor adaptor,
2914 ConversionPatternRewriter &rewriter)
const override {
2915 rewriter.replaceOpWithNewOp<sim::QueueConcatOp>(
2916 op, getTypeConverter()->convertType(op.getResult().getType()),
2917 adaptor.getInputs());
2923 using OpConversionPattern::OpConversionPattern;
2926 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
2927 ConversionPatternRewriter &rewriter)
const override {
2928 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
2929 op, adaptor.getMessage());
2941static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
2942 ConversionPatternRewriter &rewriter) {
2943 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
2948static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
2949 ConversionPatternRewriter &rewriter) {
2950 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
2956static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
2957 ConversionPatternRewriter &rewriter) {
2959 std::string severityString;
2961 switch (op.getSeverity()) {
2962 case (Severity::Fatal):
2963 severityString =
"Fatal: ";
2965 case (Severity::Error):
2966 severityString =
"Error: ";
2968 case (Severity::Warning):
2969 severityString =
"Warning: ";
2971 case (Severity::Info):
2972 severityString =
"Info: ";
2977 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
2978 auto message = sim::FormatStringConcatOp::create(
2979 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
2980 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
2994 UrandomRangeBIOp::Adaptor adaptor,
2995 ConversionPatternRewriter &rewriter,
2996 FunctionCache &funcCache) {
2997 auto loc = op.getLoc();
2998 auto i32Ty = rewriter.getI32Type();
2999 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
3000 auto fn = funcCache.getOrCreate(rewriter,
"__circt_urandom_range",
3001 {i32Ty, i32Ty, ptrTy}, {i32Ty});
3004 if (
auto seedRef = adaptor.getSeed()) {
3007 seedPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, i32Ty, one);
3008 auto seedVal = llhd::ProbeOp::create(rewriter, loc, seedRef);
3009 LLVM::StoreOp::create(rewriter, loc, seedVal, seedPtr);
3011 seedPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
3014 auto call = func::CallOp::create(
3016 ValueRange{adaptor.getMinval(), adaptor.getMaxval(), seedPtr});
3019 if (adaptor.getSeed()) {
3020 auto newSeed = LLVM::LoadOp::create(rewriter, loc, i32Ty, seedPtr);
3021 auto epsilon = llhd::ConstantTimeOp::create(
3023 llhd::TimeAttr::get(rewriter.getContext(), 0,
"ns", 0, 1));
3024 llhd::DriveOp::create(rewriter, loc, adaptor.getSeed(), newSeed, epsilon,
3028 rewriter.replaceOp(op, call.getResult(0));
3034 FinishMessageBIOp::Adaptor adaptor,
3035 ConversionPatternRewriter &rewriter) {
3037 rewriter.eraseOp(op);
3046static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
3047 ConversionPatternRewriter &rewriter) {
3048 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
3053static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
3054 ConversionPatternRewriter &rewriter) {
3055 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
3060static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
3061 ConversionPatternRewriter &rewriter) {
3062 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
3071 const TypeConverter &converter) {
3072 target.addIllegalDialect<MooreDialect>();
3073 target.addLegalDialect<comb::CombDialect>();
3074 target.addLegalDialect<hw::HWDialect>();
3075 target.addLegalDialect<seq::SeqDialect>();
3076 target.addLegalDialect<llhd::LLHDDialect>();
3077 target.addLegalDialect<ltl::LTLDialect>();
3078 target.addLegalDialect<mlir::BuiltinDialect>();
3079 target.addLegalDialect<mlir::math::MathDialect>();
3080 target.addLegalDialect<sim::SimDialect>();
3081 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3082 target.addLegalDialect<verif::VerifDialect>();
3083 target.addLegalDialect<arith::ArithDialect>();
3085 target.addLegalOp<debug::ScopeOp>();
3087 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
3088 UnrealizedConversionCastOp, hw::OutputOp,
3089 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
3091 [&](Operation *op) {
return converter.isLegal(op); });
3093 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
3094 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
3095 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
3098 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
3099 return converter.isSignatureLegal(op.getFunctionType());
3103 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
3104 converter.isLegal(&op.getBody());
3109 typeConverter.addConversion([&](IntType type) {
3110 return IntegerType::get(type.getContext(), type.getWidth());
3113 typeConverter.addConversion([&](RealType type) -> mlir::Type {
3114 MLIRContext *ctx = type.getContext();
3115 switch (type.getWidth()) {
3116 case moore::RealWidth::f32:
3117 return mlir::Float32Type::get(ctx);
3118 case moore::RealWidth::f64:
3119 return mlir::Float64Type::get(ctx);
3123 typeConverter.addConversion(
3124 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
3126 typeConverter.addConversion([&](FormatStringType type) {
3127 return sim::FormatStringType::get(type.getContext());
3130 typeConverter.addConversion([&](StringType type) {
3131 return sim::DynamicStringType::get(type.getContext());
3134 typeConverter.addConversion([&](QueueType type) {
3135 return sim::QueueType::get(type.getContext(),
3136 typeConverter.convertType(type.getElementType()),
3140 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
3141 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3142 return hw::ArrayType::get(
elementType, type.getSize());
3149 typeConverter.addConversion(
3150 [&](UnpackedArrayType type) -> std::optional<Type> {
3151 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3152 return hw::ArrayType::get(
elementType, type.getSize());
3156 typeConverter.addConversion([&](OpenArrayType type) -> std::optional<Type> {
3157 return LLVM::LLVMPointerType::get(type.getContext());
3160 typeConverter.addConversion(
3161 [&](OpenUnpackedArrayType type) -> std::optional<Type> {
3162 return LLVM::LLVMPointerType::get(type.getContext());
3165 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
3166 SmallVector<hw::StructType::FieldInfo> fields;
3167 for (
auto field : type.getMembers()) {
3168 hw::StructType::FieldInfo info;
3169 info.type = typeConverter.convertType(field.type);
3172 info.name = field.name;
3173 fields.push_back(info);
3175 return hw::StructType::get(type.getContext(), fields);
3183 typeConverter.addConversion(
3184 [&](UnpackedStructType type) -> std::optional<Type> {
3185 SmallVector<hw::StructType::FieldInfo> fields;
3186 for (
auto field : type.getMembers()) {
3187 hw::StructType::FieldInfo info;
3188 info.type = typeConverter.convertType(field.type);
3191 info.name = field.name;
3192 fields.push_back(info);
3194 return hw::StructType::get(type.getContext(), fields);
3198 typeConverter.addConversion([&](UnionType type) -> std::optional<Type> {
3199 SmallVector<hw::UnionType::FieldInfo> fields;
3200 for (
auto field : type.getMembers()) {
3201 hw::UnionType::FieldInfo info;
3202 info.type = typeConverter.convertType(field.type);
3205 info.name = field.name;
3207 fields.push_back(info);
3209 auto result = hw::UnionType::get(type.getContext(), fields);
3214 typeConverter.addConversion(
3215 [&](UnpackedUnionType type) -> std::optional<Type> {
3216 SmallVector<hw::UnionType::FieldInfo> fields;
3217 for (
auto field : type.getMembers()) {
3218 hw::UnionType::FieldInfo info;
3219 info.type = typeConverter.convertType(field.type);
3222 info.name = field.name;
3224 fields.push_back(info);
3226 return hw::UnionType::get(type.getContext(), fields);
3230 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
3231 return LLVM::LLVMPointerType::get(type.getContext());
3235 typeConverter.addConversion(
3236 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
3239 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
3240 return LLVM::LLVMPointerType::get(type.getContext());
3243 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
3244 if (isa<OpenArrayType, OpenUnpackedArrayType>(type.getNestedType()))
3245 return LLVM::LLVMPointerType::get(type.getContext());
3246 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3247 return llhd::RefType::get(innerType);
3252 typeConverter.addConversion([](IntegerType type) {
return type; });
3253 typeConverter.addConversion([](FloatType type) {
return type; });
3254 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
3255 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
3256 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
3257 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
3258 typeConverter.addConversion([](debug::StructType type) {
return type; });
3260 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
3261 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3262 return llhd::RefType::get(innerType);
3266 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
3267 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3268 return hw::ArrayType::get(
elementType, type.getNumElements());
3272 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
3273 SmallVector<hw::StructType::FieldInfo> fields;
3274 for (
auto field : type.getElements()) {
3275 hw::StructType::FieldInfo info;
3276 info.type = typeConverter.convertType(field.type);
3279 info.name = field.name;
3280 fields.push_back(info);
3282 return hw::StructType::get(type.getContext(), fields);
3285 typeConverter.addConversion([&](hw::UnionType type) -> std::optional<Type> {
3286 SmallVector<hw::UnionType::FieldInfo> fields;
3287 for (
auto field : type.getElements()) {
3288 hw::UnionType::FieldInfo info;
3289 info.type = typeConverter.convertType(field.type);
3292 info.name = field.name;
3293 info.offset = field.offset;
3294 fields.push_back(info);
3296 return hw::UnionType::get(type.getContext(), fields);
3299 typeConverter.addTargetMaterialization(
3300 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3301 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3302 if (inputs.size() != 1 || !inputs[0])
3304 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3309 typeConverter.addSourceMaterialization(
3310 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3311 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3312 if (inputs.size() != 1)
3314 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3321 TypeConverter &typeConverter,
3322 ClassTypeCache &classCache,
3323 FunctionCache &funcCache) {
3328 classCache, funcCache);
3329 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
3330 patterns.getContext(), classCache);
3334 ClassUpcastOpConversion,
3336 VariableOpConversion,
3340 ConversionOpConversion,
3341 BitcastConversion<PackedToSBVOp>,
3342 BitcastConversion<SBVToPackedOp>,
3343 NoOpConversion<LogicToIntOp>,
3344 NoOpConversion<IntToLogicOp>,
3345 NoOpConversion<ToBuiltinIntOp>,
3346 NoOpConversion<FromBuiltinIntOp>,
3350 SIntToRealOpConversion,
3351 UIntToRealOpConversion,
3352 IntToStringOpConversion,
3353 RealToIntOpConversion,
3354 ConvertRealOpConversion,
3360 ReplicateOpConversion,
3362 ExtractOpConversion,
3363 DynExtractOpConversion,
3364 DynExtractRefOpConversion,
3366 StructExtractOpConversion,
3367 StructExtractRefOpConversion,
3368 ExtractRefOpConversion,
3369 StructCreateOpConversion,
3370 UnionCreateOpConversion,
3371 UnionExtractOpConversion,
3372 UnionExtractRefOpConversion,
3373 ConditionalOpConversion,
3374 ArrayCreateOpConversion,
3377 ConstantStringOpConv,
3380 ReduceAndOpConversion,
3381 ReduceOrOpConversion,
3382 ReduceXorOpConversion,
3383 BoolCastOpConversion,
3388 BinaryOpConversion<AddOp, comb::AddOp>,
3389 BinaryOpConversion<SubOp, comb::SubOp>,
3390 BinaryOpConversion<MulOp, comb::MulOp>,
3391 BinaryOpConversion<DivUOp, comb::DivUOp>,
3392 BinaryOpConversion<DivSOp, comb::DivSOp>,
3393 BinaryOpConversion<ModUOp, comb::ModUOp>,
3394 BinaryOpConversion<ModSOp, comb::ModSOp>,
3395 BinaryOpConversion<AndOp, comb::AndOp>,
3396 BinaryOpConversion<OrOp, comb::OrOp>,
3397 BinaryOpConversion<XorOp, comb::XorOp>,
3400 NegRealOpConversion,
3403 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
3404 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
3405 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
3406 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
3407 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
3410 PowUOpConversion, PowSOpConversion,
3413 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
3414 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
3415 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
3416 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
3417 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
3418 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
3419 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
3420 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
3421 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
3422 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
3423 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
3424 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
3425 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
3426 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
3427 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::ONE>,
3428 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
3429 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
3430 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
3431 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
3432 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
3433 CaseXZEqOpConversion<CaseZEqOp, true>,
3434 CaseXZEqOpConversion<CaseXZEqOp, false>,
3437 SVModuleOpConversion,
3438 InstanceOpConversion,
3439 ProcedureOpConversion,
3440 CoroutineOpConversion,
3441 CallCoroutineOpConversion,
3442 WaitEventOpConversion,
3450 AssignOpConversion<ContinuousAssignOp>,
3451 AssignOpConversion<DelayedContinuousAssignOp>,
3452 AssignOpConversion<BlockingAssignOp>,
3453 AssignOpConversion<NonBlockingAssignOp>,
3454 AssignOpConversion<DelayedNonBlockingAssignOp>,
3455 AssignedVariableOpConversion,
3458 HWInstanceOpConversion,
3461 DPIFuncOpConversion,
3462 FuncDPICallOpConversion,
3463 UnrealizedConversionCastConversion,
3464 InPlaceOpConversion<debug::ArrayOp>,
3465 InPlaceOpConversion<debug::StructOp>,
3466 InPlaceOpConversion<debug::VariableOp>,
3469 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
3470 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
3471 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
3474 FormatLiteralOpConversion,
3475 FormatConcatOpConversion,
3476 FormatHierPathOpConversion,
3477 FormatIntOpConversion,
3478 FormatRealOpConversion,
3479 DisplayBIOpConversion,
3482 StringLenOpConversion,
3483 StringConcatOpConversion,
3484 StringGetOpConversion,
3487 QueueSizeBIOpConversion,
3488 QueuePushBackOpConversion,
3489 QueuePushFrontOpConversion,
3490 QueuePopBackOpConversion,
3491 QueuePopFrontOpConversion,
3492 QueueDeleteOpConversion,
3493 QueueInsertOpConversion,
3494 QueueClearOpConversion,
3495 DynQueueExtractOpConversion,
3496 QueueResizeOpConversion,
3497 QueueSetOpConversion,
3498 QueueCmpOpConversion,
3499 QueueFromUnpackedArrayOpConversion,
3500 QueueConcatOpConversion
3501 >(typeConverter,
patterns.getContext());
3524 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
3526 hw::populateHWModuleLikeTypeConversionPattern(
3527 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
3528 populateSCFToControlFlowConversionPatterns(
patterns);
3537struct MooreToCorePass
3538 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
3539 void runOnOperation()
override;
3545 return std::make_unique<MooreToCorePass>();
3549void MooreToCorePass::runOnOperation() {
3550 MLIRContext &
context = getContext();
3551 ModuleOp
module = getOperation();
3552 ClassTypeCache classCache;
3553 auto &symbolTable = getAnalysis<SymbolTable>();
3554 FunctionCache funcCache(symbolTable);
3556 IRRewriter rewriter(module);
3557 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
3559 TypeConverter typeConverter;
3562 ConversionTarget target(
context);
3567 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
3570 if (failed(applyFullConversion(module, target, std::move(
patterns))))
3571 signalPassFailure();
assert(baseType &&"element must be base type")
static std::unique_ptr< Context > context
static FIRRTLBaseType convertType(FIRRTLBaseType type)
Returns null type if no conversion is needed.
static Value createZeroValue(ImplicitLocOpBuilder &builder, FIRRTLBaseType type, SmallDenseMap< FIRRTLBaseType, Value > &cache)
Construct a zero value of the given type using the given builder.
static LogicalResult convert(StopBIOp op, StopBIOp::Adaptor adaptor, ConversionPatternRewriter &rewriter)
static void populateOpConversion(ConversionPatternSet &patterns, TypeConverter &typeConverter, ClassTypeCache &classCache, FunctionCache &funcCache)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
Extension of RewritePatternSet that allows adding matchAndRewrite functions with op adaptors and Conv...
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateArithToCombPatterns(mlir::RewritePatternSet &patterns, TypeConverter &typeConverter)
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.
This holds a decoded list of input/inout and output ports for a module or instance.
This holds the name, type, direction of a module's ports.