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++, {}}));
392 using OpConversionPattern::OpConversionPattern;
395 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
396 ConversionPatternRewriter &rewriter)
const override {
397 rewriter.setInsertionPoint(op);
400 auto portInfo = getModulePortInfo(*typeConverter, op);
401 if (failed(portInfo))
404 auto hwModuleOp = hw::HWModuleOp::create(rewriter, op.getLoc(),
405 op.getSymNameAttr(), *portInfo);
408 SymbolTable::setSymbolVisibility(hwModuleOp,
409 SymbolTable::getSymbolVisibility(op));
410 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
412 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
414 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
415 hwModuleOp.getBodyRegion().end());
418 rewriter.eraseOp(op);
424 using OpConversionPattern::OpConversionPattern;
427 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
428 ConversionPatternRewriter &rewriter)
const override {
429 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
435 using OpConversionPattern::OpConversionPattern;
438 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
439 ConversionPatternRewriter &rewriter)
const override {
440 auto instName = op.getInstanceNameAttr();
441 auto moduleName = op.getModuleNameAttr();
444 rewriter.setInsertionPoint(op);
445 auto instOp = hw::InstanceOp::create(
446 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
447 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
448 rewriter.getArrayAttr({}),
nullptr,
452 op.replaceAllUsesWith(instOp.getResults());
453 rewriter.eraseOp(op);
458static void getValuesToObserve(Region *region,
459 function_ref<
void(Value)> setInsertionPoint,
460 const TypeConverter *typeConverter,
461 ConversionPatternRewriter &rewriter,
462 SmallVector<Value> &observeValues) {
463 SmallDenseSet<Value> alreadyObserved;
464 Location loc = region->getLoc();
466 auto probeIfSignal = [&](Value value) -> Value {
467 Type type = value.getType();
468 if (
auto refType = dyn_cast<llhd::RefType>(type)) {
469 if (!hw::isHWValueType(refType.getNestedType()))
471 return llhd::ProbeOp::create(rewriter, loc, value);
473 if (!hw::isHWValueType(type))
478 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
479 [&](Operation *operation) {
480 for (
auto value : operation->getOperands()) {
481 if (isa<BlockArgument>(value))
482 value = rewriter.getRemappedValue(value);
484 if (region->isAncestor(value.getParentRegion()))
486 if (
auto *defOp = value.getDefiningOp();
487 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
489 if (!alreadyObserved.insert(value).second)
492 OpBuilder::InsertionGuard g(rewriter);
493 if (
auto remapped = rewriter.getRemappedValue(value)) {
494 setInsertionPoint(remapped);
495 if (
auto observed = probeIfSignal(remapped))
496 observeValues.push_back(observed);
498 setInsertionPoint(value);
499 auto type = typeConverter->convertType(value.getType());
500 auto converted = typeConverter->materializeTargetConversion(
501 rewriter, loc, type, value);
502 if (
auto observed = probeIfSignal(converted))
503 observeValues.push_back(observed);
510 using OpConversionPattern::OpConversionPattern;
513 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
514 ConversionPatternRewriter &rewriter)
const override {
516 SmallVector<Value> observedValues;
517 if (op.getKind() == ProcedureKind::AlwaysComb ||
518 op.getKind() == ProcedureKind::AlwaysLatch) {
519 auto setInsertionPoint = [&](Value value) {
520 rewriter.setInsertionPoint(op);
522 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
523 rewriter, observedValues);
526 auto loc = op.getLoc();
527 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
532 if (op.getKind() == ProcedureKind::Initial ||
533 op.getKind() == ProcedureKind::Final) {
535 if (op.getKind() == ProcedureKind::Initial)
536 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
538 newOp = llhd::FinalOp::create(rewriter, loc);
539 auto &body = newOp->getRegion(0);
540 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
542 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
543 rewriter.setInsertionPoint(returnOp);
544 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
546 rewriter.eraseOp(op);
551 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
556 rewriter.createBlock(&newOp.getBody());
557 auto *block = &op.getBody().front();
558 cf::BranchOp::create(rewriter, loc, block);
559 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
560 newOp.getBody().end());
568 if (op.getKind() == ProcedureKind::AlwaysComb ||
569 op.getKind() == ProcedureKind::AlwaysLatch) {
570 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
571 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
572 ValueRange{}, block);
579 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
580 rewriter.setInsertionPoint(returnOp);
581 cf::BranchOp::create(rewriter, loc, block);
582 rewriter.eraseOp(returnOp);
585 rewriter.eraseOp(op);
595 using OpConversionPattern::OpConversionPattern;
598 matchAndRewrite(CoroutineOp op, OpAdaptor adaptor,
599 ConversionPatternRewriter &rewriter)
const override {
600 auto funcType = op.getFunctionType();
601 TypeConverter::SignatureConversion sigConversion(funcType.getNumInputs());
602 for (
auto [i, type] :
llvm::enumerate(funcType.getInputs())) {
603 auto converted = typeConverter->convertType(type);
606 sigConversion.addInputs(i, converted);
608 SmallVector<Type> resultTypes;
609 if (failed(typeConverter->convertTypes(funcType.getResults(), resultTypes)))
612 auto newFuncType = FunctionType::get(
613 rewriter.getContext(), sigConversion.getConvertedTypes(), resultTypes);
614 auto newOp = llhd::CoroutineOp::create(rewriter, op.getLoc(),
615 op.getSymName(), newFuncType);
616 newOp.setSymVisibilityAttr(op.getSymVisibilityAttr());
617 if (
auto dpiExport = op->getAttr(
"circt.dpi.export"))
618 newOp->setAttr(
"circt.dpi.export", dpiExport);
619 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
620 newOp.getBody().end());
621 if (failed(rewriter.convertRegionTypes(&newOp.getBody(), *typeConverter,
627 llvm::make_early_inc_range(newOp.getBody().getOps<ReturnOp>())) {
628 rewriter.setInsertionPoint(returnOp);
629 rewriter.replaceOpWithNewOp<llhd::ReturnOp>(returnOp, ValueRange{});
632 rewriter.eraseOp(op);
638 using OpConversionPattern::OpConversionPattern;
641 matchAndRewrite(CallCoroutineOp op, OpAdaptor adaptor,
642 ConversionPatternRewriter &rewriter)
const override {
643 SmallVector<Type> convResTypes;
644 if (failed(typeConverter->convertTypes(op.getResultTypes(), convResTypes)))
646 rewriter.replaceOpWithNewOp<llhd::CallCoroutineOp>(
647 op, convResTypes, adaptor.getCallee(), adaptor.getOperands());
653 using OpConversionPattern::OpConversionPattern;
656 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
657 ConversionPatternRewriter &rewriter)
const override {
691 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
697 if (op.getBody().front().empty()) {
700 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
704 auto *waitBlock = rewriter.createBlock(resumeBlock);
705 auto *checkBlock = rewriter.createBlock(resumeBlock);
707 auto loc = op.getLoc();
708 rewriter.setInsertionPoint(op);
709 cf::BranchOp::create(rewriter, loc, waitBlock);
719 SmallVector<Value> valuesBefore;
720 rewriter.setInsertionPointToEnd(waitBlock);
721 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
722 bool allDetectsAreAnyChange =
true;
724 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
725 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
726 allDetectsAreAnyChange =
false;
727 valuesBefore.push_back(detectOp.getInput());
728 rewriter.eraseOp(detectOp);
734 SmallVector<Value> observeValues;
735 auto setInsertionPointAfterDef = [&](Value value) {
736 if (
auto *op = value.getDefiningOp())
737 rewriter.setInsertionPointAfter(op);
738 if (
auto arg = dyn_cast<BlockArgument>(value))
739 rewriter.setInsertionPointToStart(value.getParentBlock());
742 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
743 typeConverter, rewriter, observeValues);
748 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
749 observeValues, ValueRange{}, checkBlock);
750 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
751 rewriter.eraseOp(clonedOp);
755 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
756 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
758 rewriter.eraseOp(op);
762 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
763 assert(before.getType() == after.getType() &&
764 "mismatched types after clone op");
765 auto beforeType = cast<IntType>(before.getType());
769 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
770 constexpr int LSB = 0;
772 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
774 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
775 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
778 auto intType = rewriter.getIntegerType(beforeType.getWidth());
779 before = typeConverter->materializeTargetConversion(rewriter, loc,
781 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
784 if (edge == Edge::AnyChange)
785 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
788 SmallVector<Value> disjuncts;
791 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
793 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
795 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
796 disjuncts.push_back(posedge);
799 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
801 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
803 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
804 disjuncts.push_back(posedge);
807 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
814 SmallVector<Value> triggers;
815 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
816 if (!allDetectsAreAnyChange) {
817 if (!isa<IntType>(before.getType()))
818 return detectOp->emitError() <<
"requires int operand";
820 rewriter.setInsertionPoint(detectOp);
822 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
823 if (detectOp.getCondition()) {
824 auto condition = typeConverter->materializeTargetConversion(
825 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
827 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
829 triggers.push_back(trigger);
832 rewriter.eraseOp(detectOp);
835 rewriter.setInsertionPointToEnd(checkBlock);
836 if (triggers.empty()) {
841 cf::BranchOp::create(rewriter, loc, resumeBlock);
847 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
848 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
857static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
858 ConversionPatternRewriter &rewriter) {
860 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
861 rewriter.setInsertionPoint(op);
862 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
863 adaptor.getDelay(), ValueRange{},
864 ValueRange{}, resumeBlock);
865 rewriter.setInsertionPointToStart(resumeBlock);
870static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
871 ConversionPatternRewriter &rewriter) {
872 rewriter.replaceOpWithNewOp<ub::UnreachableOp>(op);
881 ConversionPatternRewriter &rewriter) {
883 if (isa<mlir::LLVM::LLVMPointerType>(type))
884 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
887 if (isa<llhd::TimeType>(type)) {
889 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
890 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
894 if (
auto floatType = dyn_cast<FloatType>(type)) {
895 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
896 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
900 if (
auto strType = dyn_cast<sim::DynamicStringType>(type))
901 return sim::StringConstantOp::create(rewriter, loc, strType,
"");
904 if (
auto assocArrayType = dyn_cast<sim::AssocArrayType>(type))
905 return sim::AssocArrayEmptyOp::create(rewriter, loc, assocArrayType);
908 if (
auto queueType = dyn_cast<sim::QueueType>(type))
909 return sim::QueueEmptyOp::create(rewriter, loc, queueType);
912 if (
auto arrayType = dyn_cast<hw::ArrayType>(type)) {
913 if (hw::getBitWidth(type) == -1) {
918 SmallVector<Value> elements(arrayType.getNumElements(), zeroElement);
923 if (
auto structType = dyn_cast<hw::StructType>(type)) {
924 if (hw::getBitWidth(type) == -1) {
925 SmallVector<Value> fields;
926 for (
auto field : structType.getElements()) {
930 fields.push_back(zeroField);
937 int64_t width = hw::getBitWidth(type);
945 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
948struct ClassPropertyRefOpConversion
950 ClassPropertyRefOpConversion(TypeConverter &tc, MLIRContext *ctx,
951 ClassTypeCache &cache)
955 matchAndRewrite(circt::moore::ClassPropertyRefOp op, OpAdaptor adaptor,
956 ConversionPatternRewriter &rewriter)
const override {
957 Location loc = op.getLoc();
958 MLIRContext *ctx = rewriter.getContext();
961 Type dstTy = getTypeConverter()->convertType(op.getPropertyRef().getType());
963 Value instRef = adaptor.getInstance();
967 cast<circt::moore::ClassHandleType>(op.getInstance().getType());
968 SymbolRefAttr classSym = classRefTy.getClassSym();
969 ModuleOp mod = op->getParentOfType<ModuleOp>();
970 if (failed(resolveClassStructBody(mod, classSym, *typeConverter, cache)))
971 return rewriter.notifyMatchFailure(op,
972 "Could not resolve class struct for " +
973 classSym.getRootReference().str());
975 auto structInfo = cache.getStructInfo(classSym);
976 assert(structInfo &&
"class struct info must exist");
977 auto structTy = structInfo->classBody;
980 auto propSym = op.getProperty();
981 auto pathOpt = structInfo->getFieldPath(propSym);
983 return rewriter.notifyMatchFailure(op,
984 "no GEP path for property " + propSym);
986 auto i32Ty = IntegerType::get(ctx, 32);
987 SmallVector<Value> idxVals;
988 for (
unsigned idx : *pathOpt)
989 idxVals.push_back(LLVM::ConstantOp::create(
990 rewriter, loc, i32Ty, rewriter.getI32IntegerAttr(idx)));
993 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
995 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, instRef, idxVals);
998 Value fieldRef = UnrealizedConversionCastOp::create(rewriter, loc, dstTy,
1002 rewriter.replaceOp(op, fieldRef);
1007 ClassTypeCache &cache;
1011 using OpConversionPattern::OpConversionPattern;
1014 matchAndRewrite(ClassUpcastOp op, OpAdaptor adaptor,
1015 ConversionPatternRewriter &rewriter)
const override {
1017 Type dstTy = getTypeConverter()->convertType(op.getResult().getType());
1018 Type srcTy = adaptor.getInstance().getType();
1021 return rewriter.notifyMatchFailure(op,
"failed to convert result type");
1024 if (dstTy == srcTy && isa<LLVM::LLVMPointerType>(srcTy)) {
1025 rewriter.replaceOp(op, adaptor.getInstance());
1028 return rewriter.notifyMatchFailure(
1029 op,
"Upcast applied to non-opaque pointers!");
1035 ClassNewOpConversion(TypeConverter &tc, MLIRContext *ctx,
1036 ClassTypeCache &cache, FunctionCache &funcCache)
1038 funcCache(funcCache) {}
1041 matchAndRewrite(ClassNewOp op, OpAdaptor adaptor,
1042 ConversionPatternRewriter &rewriter)
const override {
1043 Location loc = op.getLoc();
1044 MLIRContext *ctx = rewriter.getContext();
1046 auto handleTy = cast<ClassHandleType>(op.getResult().getType());
1047 auto sym = handleTy.getClassSym();
1049 ModuleOp mod = op->getParentOfType<ModuleOp>();
1051 if (failed(resolveClassStructBody(mod, sym, *typeConverter, cache)))
1052 return op.emitError() <<
"Could not resolve class struct for " << sym;
1054 auto structTy = cache.getStructInfo(sym)->classBody;
1055 auto typeInfo = cache.getStructInfo(sym)->typeInfo;
1060 for (
auto memberTy : structTy.getBody()) {
1061 if (!LLVM::isCompatibleType(memberTy) &&
1062 !memberTy.hasTrait<DataLayoutTypeInterface::Trait>()) {
1063 return op.emitError()
1064 <<
"class struct has member types with no data layout";
1070 uint64_t byteSize = dl.getTypeSize(structTy);
1071 auto i64Ty = IntegerType::get(ctx, 64);
1072 auto cSize = LLVM::ConstantOp::create(rewriter, loc, i64Ty,
1073 rewriter.getI64IntegerAttr(byteSize));
1076 auto ptrTy = LLVM::LLVMPointerType::get(ctx);
1077 auto mallocFn = funcCache.getOrCreate(rewriter,
"malloc", {i64Ty}, {ptrTy});
1079 func::CallOp::create(rewriter, loc, mallocFn, ValueRange{cSize});
1082 LLVM::AddressOfOp::create(rewriter, loc, typeInfo.global);
1083 auto i32Ty = IntegerType::get(ctx, 32);
1084 auto headerIdx = LLVM::ConstantOp::create(
1085 rewriter, loc, i32Ty,
1086 rewriter.getI32IntegerAttr(cache.getStructInfo(sym)->headerFieldIndex));
1087 auto typeInfoIdx = LLVM::ConstantOp::create(
1088 rewriter, loc, i32Ty,
1089 rewriter.getI32IntegerAttr(
1090 cache.getStructInfo(sym)->typeInfoFieldIndex));
1092 LLVM::GEPOp::create(rewriter, loc, ptrTy, structTy, call.getResult(0),
1093 ValueRange{headerIdx, typeInfoIdx});
1094 LLVM::StoreOp::create(rewriter, loc, typeInfoAddr, headerPtr);
1098 rewriter.replaceOp(op, call.getResult(0));
1103 ClassTypeCache &cache;
1104 FunctionCache &funcCache;
1108 ClassDeclOpConversion(TypeConverter &tc, MLIRContext *ctx,
1109 ClassTypeCache &cache)
1113 matchAndRewrite(ClassDeclOp op, OpAdaptor,
1114 ConversionPatternRewriter &rewriter)
const override {
1116 if (failed(resolveClassStructBody(op, *typeConverter, cache)))
1119 rewriter.eraseOp(op);
1124 ClassTypeCache &cache;
1128 using OpConversionPattern::OpConversionPattern;
1131 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
1132 ConversionPatternRewriter &rewriter)
const override {
1133 auto loc = op.getLoc();
1134 auto resultType = typeConverter->convertType(op.getResult().getType());
1136 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
1138 auto refType = dyn_cast<llhd::RefType>(resultType);
1140 return rewriter.notifyMatchFailure(
1141 op.getLoc(),
"variable type did not convert to llhd::RefType");
1144 Value init = adaptor.getInitial();
1151 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
1152 op.getNameAttr(), init);
1158 using OpConversionPattern::OpConversionPattern;
1161 matchAndRewrite(NetOp op, OpAdaptor adaptor,
1162 ConversionPatternRewriter &rewriter)
const override {
1163 auto loc = op.getLoc();
1165 auto resultType = typeConverter->convertType(op.getResult().getType());
1167 return rewriter.notifyMatchFailure(loc,
"invalid net type");
1169 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
1175 createInitialValue(op.getKind(), rewriter, loc, width,
elementType);
1176 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
1177 op, resultType, op.getNameAttr(), init);
1179 if (
auto assignedValue = adaptor.getAssignment()) {
1180 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
1181 llvm::StringRef(
"ns"), 0, 1);
1182 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
1183 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
1190 static mlir::Value createInitialValue(NetKind kind,
1191 ConversionPatternRewriter &rewriter,
1192 Location loc, int64_t width,
1203 if (kind == NetKind::Supply1 || kind == NetKind::Tri1)
1204 return APInt::getAllOnes(width);
1205 return APInt::getZero(width);
1213static LogicalResult
convert(GlobalVariableOp op,
1214 GlobalVariableOp::Adaptor adaptor,
1215 ConversionPatternRewriter &rewriter,
1216 const TypeConverter &typeConverter) {
1217 auto type = typeConverter.convertType(op.getType());
1219 llhd::GlobalSignalOp::create(rewriter, op.getLoc(), op.getSymNameAttr(),
1221 sig.getInitRegion().takeBody(op.getInitRegion());
1222 rewriter.eraseOp(op);
1227static LogicalResult
convert(GetGlobalVariableOp op,
1228 GetGlobalVariableOp::Adaptor adaptor,
1229 ConversionPatternRewriter &rewriter,
1230 const TypeConverter &typeConverter) {
1231 auto type = typeConverter.convertType(op.getType());
1232 rewriter.replaceOpWithNewOp<llhd::GetGlobalSignalOp>(op, type,
1233 op.getGlobalNameAttr());
1242 using OpConversionPattern::OpConversionPattern;
1245 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
1246 ConversionPatternRewriter &rewriter)
const override {
1248 auto value = op.getValue().toAPInt(
false);
1249 auto type = rewriter.getIntegerType(value.getBitWidth());
1251 op, type, rewriter.getIntegerAttr(type, value));
1257 using OpConversionPattern::OpConversionPattern;
1260 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
1261 ConversionPatternRewriter &rewriter)
const override {
1262 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
1268 using OpConversionPattern::OpConversionPattern;
1271 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
1272 ConversionPatternRewriter &rewriter)
const override {
1273 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
1274 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
1275 StringRef(
"fs"), 0, 0));
1281 using OpConversionPattern::OpConversionPattern;
1283 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
1284 ConversionPatternRewriter &rewriter)
const override {
1285 const auto resultType =
1286 typeConverter->convertType(op.getResult().getType());
1287 const auto intType = mlir::cast<IntegerType>(resultType);
1289 const auto str = op.getValue();
1290 const unsigned byteWidth = intType.getWidth();
1291 APInt value(byteWidth, 0);
1294 const size_t maxChars =
1295 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
1296 for (
size_t i = 0; i < maxChars; i++) {
1297 const size_t pos = str.size() - 1 - i;
1298 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
1299 value |= APInt(byteWidth, asciiChar) << (8 * i);
1303 op, resultType, rewriter.getIntegerAttr(resultType, value));
1309 using OpConversionPattern::OpConversionPattern;
1311 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
1312 ConversionPatternRewriter &rewriter)
const override {
1313 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
1319 using OpConversionPattern::OpConversionPattern;
1321 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
1322 ConversionPatternRewriter &rewriter)
const override {
1323 Type resultType = typeConverter->convertType(op.getResult().getType());
1325 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
1326 adaptor.getValue());
1332 using OpConversionPattern::OpConversionPattern;
1335 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
1336 ConversionPatternRewriter &rewriter)
const override {
1339 Type resultType = typeConverter->convertType(op.getResult().getType());
1340 Value input = adaptor.getInput();
1341 Type inputType = input.getType();
1342 int32_t low = adaptor.getLowBit();
1343 auto loc = op.getLoc();
1346 if (isa<IntegerType>(inputType)) {
1347 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
1348 int32_t resultWidth = hw::getBitWidth(resultType);
1349 if (resultWidth < 0)
1352 int32_t high = low + resultWidth;
1353 int32_t lsbPad = std::clamp(-low, 0, resultWidth);
1354 int32_t msbPad = std::clamp(high - inputWidth, 0, resultWidth - lsbPad);
1355 int32_t extractWidth = resultWidth - lsbPad - msbPad;
1357 SmallVector<Value> sbv;
1361 if (extractWidth > 0)
1363 loc, rewriter.getIntegerType(extractWidth), input,
1370 if (res.getType() != resultType)
1371 res = rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, res);
1373 rewriter.replaceOp(op, res);
1378 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
1380 int32_t idxWidth = llvm::Log2_64_Ceil(arrTy.getNumElements());
1381 int32_t inputWidth = arrTy.getNumElements();
1385 if (low < 0 || low >= inputWidth) {
1389 rewriter.replaceOp(op, zeros);
1394 rewriter.getIntegerType(idxWidth), low));
1400 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
1401 resArrTy && resArrTy.getElementType() ==
elementType) {
1402 int32_t resultWidth = resArrTy.getNumElements();
1403 int32_t high = low + resultWidth;
1405 int32_t lsbPad = std::clamp(-low, 0, resultWidth);
1406 int32_t msbPad = std::clamp(high - inputWidth, 0, resultWidth - lsbPad);
1407 int32_t extractWidth = resultWidth - lsbPad - msbPad;
1409 SmallVector<Value> toConcat;
1415 toConcat.push_back(zeros);
1418 if (extractWidth > 0)
1420 loc, hw::ArrayType::get(
elementType, extractWidth), input,
1422 rewriter.getIntegerType(idxWidth),
1423 std::max(low, 0))));
1430 toConcat.push_back(zeros);
1444 using OpConversionPattern::OpConversionPattern;
1447 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
1448 ConversionPatternRewriter &rewriter)
const override {
1450 Type resultType = typeConverter->convertType(op.getResult().getType());
1452 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1454 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1455 int64_t width = hw::getBitWidth(inputType);
1460 rewriter, op.getLoc(),
1461 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
1462 adaptor.getLowBit());
1463 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1464 op, resultType, adaptor.getInput(), lowBit);
1468 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1470 rewriter, op.getLoc(),
1471 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
1472 adaptor.getLowBit());
1476 if (arrType.getElementType() !=
1477 cast<llhd::RefType>(resultType).getNestedType()) {
1478 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1479 op, resultType, adaptor.getInput(), lowBit);
1483 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1493 using OpConversionPattern::OpConversionPattern;
1496 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
1497 ConversionPatternRewriter &rewriter)
const override {
1498 Type resultType = typeConverter->convertType(op.getResult().getType());
1499 Type inputType = adaptor.getInput().getType();
1501 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1502 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1503 intType.getWidth(), op->getLoc());
1504 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
1505 adaptor.getInput(), amount);
1507 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
1511 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1512 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
1513 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
1516 bool isSingleElementExtract = arrType.getElementType() == resultType;
1518 if (isSingleElementExtract)
1519 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(),
1523 adaptor.getInput(), idx);
1533 using OpConversionPattern::OpConversionPattern;
1536 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
1537 ConversionPatternRewriter &rewriter)
const override {
1539 Type resultType = typeConverter->convertType(op.getResult().getType());
1541 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
1543 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
1544 int64_t width = hw::getBitWidth(inputType);
1549 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
1550 llvm::Log2_64_Ceil(width), op->getLoc());
1551 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
1552 op, resultType, adaptor.getInput(), amount);
1556 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
1557 Value idx = adjustIntegerWidth(
1558 rewriter, adaptor.getLowBit(),
1559 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
1561 auto resultNestedType = cast<llhd::RefType>(resultType).getNestedType();
1562 bool isSingleElementExtract =
1563 arrType.getElementType() == resultNestedType;
1565 if (isSingleElementExtract)
1566 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
1569 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
1570 op, resultType, adaptor.getInput(), idx);
1580 using OpConversionPattern::OpConversionPattern;
1583 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
1584 ConversionPatternRewriter &rewriter)
const override {
1585 Type resultType = typeConverter->convertType(op.getResult().getType());
1587 adaptor.getElements());
1593 using OpConversionPattern::OpConversionPattern;
1596 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
1597 ConversionPatternRewriter &rewriter)
const override {
1598 Type resultType = typeConverter->convertType(op.getResult().getType());
1600 adaptor.getFields());
1606 using OpConversionPattern::OpConversionPattern;
1609 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1610 ConversionPatternRewriter &rewriter)
const override {
1612 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1617struct StructExtractRefOpConversion
1619 using OpConversionPattern::OpConversionPattern;
1622 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1623 ConversionPatternRewriter &rewriter)
const override {
1624 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1625 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1631 using OpConversionPattern::OpConversionPattern;
1634 matchAndRewrite(UnionCreateOp op, OpAdaptor adaptor,
1635 ConversionPatternRewriter &rewriter)
const override {
1636 Type resultType = typeConverter->convertType(op.getResult().getType());
1637 rewriter.replaceOpWithNewOp<hw::UnionCreateOp>(
1638 op, resultType, adaptor.getFieldNameAttr(), adaptor.getInput());
1644 using OpConversionPattern::OpConversionPattern;
1647 matchAndRewrite(UnionExtractOp op, OpAdaptor adaptor,
1648 ConversionPatternRewriter &rewriter)
const override {
1649 rewriter.replaceOpWithNewOp<hw::UnionExtractOp>(op, adaptor.getInput(),
1650 adaptor.getFieldNameAttr());
1655struct UnionExtractRefOpConversion
1657 using OpConversionPattern::OpConversionPattern;
1660 matchAndRewrite(UnionExtractRefOp op, OpAdaptor adaptor,
1661 ConversionPatternRewriter &rewriter)
const override {
1662 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1663 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1669 using OpConversionPattern::OpConversionPattern;
1671 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1672 ConversionPatternRewriter &rewriter)
const override {
1673 Type resultType = typeConverter->convertType(op.getInput().getType());
1676 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1677 adaptor.getInput(), max);
1683 using OpConversionPattern::OpConversionPattern;
1685 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1686 ConversionPatternRewriter &rewriter)
const override {
1687 Type resultType = typeConverter->convertType(op.getInput().getType());
1690 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1691 adaptor.getInput(), zero);
1697 using OpConversionPattern::OpConversionPattern;
1699 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1700 ConversionPatternRewriter &rewriter)
const override {
1702 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1708 using OpConversionPattern::OpConversionPattern;
1710 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1711 ConversionPatternRewriter &rewriter)
const override {
1712 Type resultType = typeConverter->convertType(op.getInput().getType());
1713 if (isa_and_nonnull<IntegerType>(resultType)) {
1716 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1717 adaptor.getInput(), zero);
1720 if (isa_and_nonnull<FloatType>(resultType)) {
1721 Value zero = arith::ConstantOp::create(
1722 rewriter, op->getLoc(), rewriter.getFloatAttr(resultType, 0.0));
1723 rewriter.replaceOpWithNewOp<arith::CmpFOp>(op, arith::CmpFPredicate::ONE,
1724 adaptor.getInput(), zero);
1727 if (isa_and_nonnull<llhd::TimeType>(resultType)) {
1729 llhd::TimeToIntOp::create(rewriter, op->getLoc(), adaptor.getInput());
1731 rewriter.getI64Type(), 0);
1732 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1736 if (isa_and_nonnull<hw::StructType, hw::ArrayType, hw::UnionType>(
1738 int64_t width = hw::getBitWidth(resultType);
1741 auto intTy = rewriter.getIntegerType(width);
1742 Value input = rewriter.createOrFold<
hw::BitcastOp>(op->getLoc(), intTy,
1743 adaptor.getInput());
1745 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1754 using OpConversionPattern::OpConversionPattern;
1756 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1757 ConversionPatternRewriter &rewriter)
const override {
1759 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1762 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1768 using OpConversionPattern::OpConversionPattern;
1770 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1771 ConversionPatternRewriter &rewriter)
const override {
1773 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1776 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1782 using OpConversionPattern::OpConversionPattern;
1784 matchAndRewrite(NegRealOp op, OpAdaptor adaptor,
1785 ConversionPatternRewriter &rewriter)
const override {
1786 rewriter.replaceOpWithNewOp<arith::NegFOp>(op, adaptor.getInput());
1791template <
typename SourceOp,
typename TargetOp>
1794 using OpAdaptor =
typename SourceOp::Adaptor;
1797 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1798 ConversionPatternRewriter &rewriter)
const override {
1799 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1800 adaptor.getRhs(),
false);
1805template <
typename SourceOp,
typename TargetOp>
1808 using OpAdaptor =
typename SourceOp::Adaptor;
1811 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1812 ConversionPatternRewriter &rewriter)
const override {
1813 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1820 using OpConversionPattern::OpConversionPattern;
1822 matchAndRewrite(HypotBIOp op, OpAdaptor adaptor,
1823 ConversionPatternRewriter &rewriter)
const override {
1824 Value lhs = adaptor.getLhs();
1825 Value rhs = adaptor.getRhs();
1826 ImplicitLocOpBuilder b(op->getLoc(), rewriter);
1827 auto left = arith::MulFOp::create(b, lhs, lhs);
1828 auto right = arith::MulFOp::create(b, rhs, rhs);
1829 auto sum = arith::AddFOp::create(b, left, right);
1830 auto out = math::SqrtOp::create(b, sum);
1831 rewriter.replaceOp(op, out);
1836template <
typename SourceOp,
typename TargetOp>
1839 using OpAdaptor =
typename SourceOp::Adaptor;
1842 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1843 ConversionPatternRewriter &rewriter)
const override {
1844 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getValue());
1849template <
typename SourceOp, ICmpPredicate pred>
1852 using OpAdaptor =
typename SourceOp::Adaptor;
1855 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1856 ConversionPatternRewriter &rewriter)
const override {
1858 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1860 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1861 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1866template <
typename SourceOp>
1870 using OpAdaptor =
typename SourceOp::Adaptor;
1873 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1874 ConversionPatternRewriter &rewriter)
const override {
1875 Type ptrTy = getTypeConverter()->convertType(op.getResult().getType());
1877 return rewriter.notifyMatchFailure(op,
"failed to convert null type");
1878 rewriter.replaceOpWithNewOp<LLVM::ZeroOp>(op, ptrTy);
1883template <
typename SourceOp, LLVM::ICmpPredicate pred>
1886 using OpAdaptor =
typename SourceOp::Adaptor;
1889 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1890 ConversionPatternRewriter &rewriter)
const override {
1891 rewriter.replaceOpWithNewOp<LLVM::ICmpOp>(op, pred, adaptor.getLhs(),
1897template <
typename SourceOp, arith::CmpFPredicate pred>
1900 using OpAdaptor =
typename SourceOp::Adaptor;
1903 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1904 ConversionPatternRewriter &rewriter)
const override {
1906 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1908 rewriter.replaceOpWithNewOp<arith::CmpFOp>(
1909 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1914template <
typename SourceOp,
bool withoutX>
1917 using OpAdaptor =
typename SourceOp::Adaptor;
1920 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1921 ConversionPatternRewriter &rewriter)
const override {
1927 unsigned bitWidth = op.getLhs().getType().getWidth();
1928 auto ignoredBits = APInt::getZero(bitWidth);
1929 auto detectIgnoredBits = [&](Value value) {
1930 auto constOp = value.getDefiningOp<ConstantOp>();
1933 auto constValue = constOp.getValue();
1935 ignoredBits |= constValue.getZBits();
1937 ignoredBits |= constValue.getUnknownBits();
1939 detectIgnoredBits(op.getLhs());
1940 detectIgnoredBits(op.getRhs());
1944 Value lhs = adaptor.getLhs();
1945 Value rhs = adaptor.getRhs();
1946 if (!ignoredBits.isZero()) {
1947 ignoredBits.flipAllBits();
1949 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1950 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1953 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1962template <
typename SourceOp>
1965 using OpAdaptor =
typename SourceOp::Adaptor;
1966 using ConversionPattern::typeConverter;
1969 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1970 ConversionPatternRewriter &rewriter)
const override {
1971 auto type = typeConverter->convertType(op.getResult().getType());
1972 if (type == adaptor.getInput().getType())
1973 rewriter.replaceOp(op, adaptor.getInput());
1975 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1981template <
typename SourceOp>
1984 using OpAdaptor =
typename SourceOp::Adaptor;
1985 using ConversionPattern::typeConverter;
1988 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1989 ConversionPatternRewriter &rewriter)
const override {
1990 rewriter.replaceOp(op, adaptor.getInput());
1996 using OpConversionPattern::OpConversionPattern;
1999 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
2000 ConversionPatternRewriter &rewriter)
const override {
2001 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
2002 op.getType().getWidth());
2008 using OpConversionPattern::OpConversionPattern;
2011 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
2012 ConversionPatternRewriter &rewriter)
const override {
2013 auto targetWidth = op.getType().getWidth();
2014 auto inputWidth = op.getInput().getType().getWidth();
2017 rewriter, op.getLoc(),
2018 rewriter.getIntegerType(targetWidth - inputWidth), 0);
2021 op, ValueRange{zeroExt, adaptor.getInput()});
2027 using OpConversionPattern::OpConversionPattern;
2030 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
2031 ConversionPatternRewriter &rewriter)
const override {
2032 auto type = typeConverter->convertType(op.getType());
2034 comb::createOrFoldSExt(rewriter, op.getLoc(), adaptor.getInput(), type);
2035 rewriter.replaceOp(op, value);
2041 using OpConversionPattern::OpConversionPattern;
2044 matchAndRewrite(SIntToRealOp op, OpAdaptor adaptor,
2045 ConversionPatternRewriter &rewriter)
const override {
2046 rewriter.replaceOpWithNewOp<arith::SIToFPOp>(
2047 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2053 using OpConversionPattern::OpConversionPattern;
2056 matchAndRewrite(UIntToRealOp op, OpAdaptor adaptor,
2057 ConversionPatternRewriter &rewriter)
const override {
2058 rewriter.replaceOpWithNewOp<arith::UIToFPOp>(
2059 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2065 using OpConversionPattern::OpConversionPattern;
2068 matchAndRewrite(IntToStringOp op, OpAdaptor adaptor,
2069 ConversionPatternRewriter &rewriter)
const override {
2070 rewriter.replaceOpWithNewOp<sim::IntToStringOp>(op, adaptor.getInput());
2076 using OpConversionPattern::OpConversionPattern;
2079 matchAndRewrite(StringToIntOp op, OpAdaptor adaptor,
2080 ConversionPatternRewriter &rewriter)
const override {
2081 Type resultTy = typeConverter->convertType(op.getType());
2084 rewriter.replaceOpWithNewOp<sim::StringToIntOp>(op, resultTy,
2085 adaptor.getInput());
2090struct FormatStringToStringOpConversion
2092 using OpConversionPattern::OpConversionPattern;
2095 matchAndRewrite(FormatStringToStringOp op, OpAdaptor adaptor,
2096 ConversionPatternRewriter &rewriter)
const override {
2097 rewriter.replaceOpWithNewOp<sim::FormatToStringOp>(op,
2098 adaptor.getFmtstring());
2104 using OpConversionPattern::OpConversionPattern;
2107 matchAndRewrite(RealToIntOp op, OpAdaptor adaptor,
2108 ConversionPatternRewriter &rewriter)
const override {
2109 rewriter.replaceOpWithNewOp<arith::FPToSIOp>(
2110 op, typeConverter->convertType(op.getType()), adaptor.getInput());
2116 using OpConversionPattern::OpConversionPattern;
2119 matchAndRewrite(ConvertRealOp op, OpAdaptor adaptor,
2120 ConversionPatternRewriter &rewriter)
const override {
2121 op.getInput().getType().getWidth() < op.getResult().getType().getWidth()
2122 ? rewriter.replaceOpWithNewOp<arith::ExtFOp>(
2123 op, typeConverter->convertType(op.getType()), adaptor.getInput())
2124 : rewriter.replaceOpWithNewOp<arith::TruncFOp>(
2125 op, typeConverter->
convertType(op.getType()), adaptor.getInput());
2130template <
typename SourceOp>
2133 using OpAdaptor =
typename SourceOp::Adaptor;
2136 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2137 ConversionPatternRewriter &rewriter)
const override {
2139 ConversionPattern::typeConverter->convertType(op.getResult().getType());
2140 rewriter.replaceOpWithNewOp<arith::BitcastOp>(op, resultTy,
2141 adaptor.getValue());
2151 using OpConversionPattern::OpConversionPattern;
2154 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
2155 ConversionPatternRewriter &rewriter)
const override {
2156 SmallVector<Type> convResTypes;
2157 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2160 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
2161 op, convResTypes, op.getInstanceName(), op.getModuleName(),
2162 adaptor.getOperands(), op.getArgNames(),
2163 op.getResultNames(),
2164 rewriter.getArrayAttr({}),
nullptr);
2171 using OpConversionPattern::OpConversionPattern;
2174 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
2175 ConversionPatternRewriter &rewriter)
const override {
2176 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
2182 using OpConversionPattern::OpConversionPattern;
2185 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
2186 ConversionPatternRewriter &rewriter)
const override {
2187 SmallVector<Type> convResTypes;
2188 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2190 rewriter.replaceOpWithNewOp<func::CallOp>(
2191 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
2196struct FuncDPICallOpConversion
2198 using OpConversionPattern::OpConversionPattern;
2201 matchAndRewrite(moore::FuncDPICallOp op, OpAdaptor adaptor,
2202 ConversionPatternRewriter &rewriter)
const override {
2203 SmallVector<Type> convResTypes;
2204 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2206 rewriter.replaceOpWithNewOp<sim::DPICallOp>(
2207 op, convResTypes, op.getCalleeAttr(), Value(),
2208 Value(), adaptor.getInputs());
2214 using OpConversionPattern::OpConversionPattern;
2217 matchAndRewrite(moore::DPIFuncOp op, OpAdaptor adaptor,
2218 ConversionPatternRewriter &rewriter)
const override {
2220 auto toDPIDir = [](moore::DPIArgDirection dir) -> sim::DPIDirection {
2222 case moore::DPIArgDirection::In:
2223 return sim::DPIDirection::Input;
2224 case moore::DPIArgDirection::Out:
2225 return sim::DPIDirection::Output;
2226 case moore::DPIArgDirection::InOut:
2227 return sim::DPIDirection::InOut;
2228 case moore::DPIArgDirection::Return:
2229 return sim::DPIDirection::Return;
2231 llvm_unreachable(
"unknown DPIArgDirection");
2235 auto dirs = op.getDpiArgDirs();
2236 auto names = op.getDpiArgNames();
2237 SmallVector<Type> argTypes;
2238 op.getDPIArgTypes(argTypes);
2240 SmallVector<sim::DPIArgument> dpiArguments;
2241 for (
auto [dirAttr, nameAttr, mooreType] :
2242 llvm::zip(dirs, names, argTypes)) {
2243 auto dir = toDPIDir(cast<moore::DPIArgDirectionAttr>(dirAttr).getValue());
2244 auto name = cast<StringAttr>(nameAttr);
2245 Type coreType = typeConverter->convertType(mooreType);
2247 return op.emitOpError(
"argument '")
2248 << name <<
"' has unsupported type " << mooreType;
2249 dpiArguments.push_back({name, coreType, dir});
2252 auto coreDPIFuncType =
2253 sim::DPIFunctionType::get(rewriter.getContext(), dpiArguments);
2254 auto simFunc = sim::DPIFuncOp::create(
2255 rewriter, op.getLoc(), op.getSymNameAttr(), coreDPIFuncType,
2256 op.getArgumentLocsAttr(), op.getVerilogNameAttr());
2257 SymbolTable::setSymbolVisibility(simFunc,
2258 SymbolTable::getSymbolVisibility(op));
2259 rewriter.eraseOp(op);
2264struct UnrealizedConversionCastConversion
2266 using OpConversionPattern::OpConversionPattern;
2269 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
2270 ConversionPatternRewriter &rewriter)
const override {
2271 SmallVector<Type> convResTypes;
2272 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
2277 if (convResTypes == adaptor.getOperands().getTypes()) {
2278 rewriter.replaceOp(op, adaptor.getOperands());
2282 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
2283 op, convResTypes, adaptor.getOperands());
2289 using OpConversionPattern::OpConversionPattern;
2292 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
2293 ConversionPatternRewriter &rewriter)
const override {
2294 Type resultType = typeConverter->convertType(op.getResult().getType());
2298 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2299 resultType.getIntOrFloatBitWidth(), op->getLoc());
2300 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
2307 using OpConversionPattern::OpConversionPattern;
2310 matchAndRewrite(ShrOp 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(PowUOp op, OpAdaptor adaptor,
2329 ConversionPatternRewriter &rewriter)
const override {
2330 Type resultType = typeConverter->convertType(op.getResult().getType());
2332 Location loc = op->getLoc();
2337 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
2338 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
2341 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
2349 using OpConversionPattern::OpConversionPattern;
2352 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
2353 ConversionPatternRewriter &rewriter)
const override {
2354 Type resultType = typeConverter->convertType(op.getResult().getType());
2358 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
2359 op, resultType, adaptor.getLhs(), adaptor.getRhs());
2365 using OpConversionPattern::OpConversionPattern;
2368 matchAndRewrite(Clog2BIOp op, OpAdaptor adaptor,
2369 ConversionPatternRewriter &rewriter)
const override {
2370 Type resultType = typeConverter->convertType(op.getResult().getType());
2371 Location loc = op.getLoc();
2372 unsigned width = resultType.getIntOrFloatBitWidth();
2373 Value value = adaptor.getValue();
2382 Value valueMinusOne = comb::SubOp::create(rewriter, loc, value, one,
false);
2384 mlir::math::CountLeadingZerosOp::create(rewriter, loc, valueMinusOne);
2385 Value bitLength = comb::SubOp::create(rewriter, loc, bitWidth, clz,
false);
2387 Value isZero = comb::ICmpOp::create(rewriter, loc, comb::ICmpPredicate::eq,
2388 value, zero,
false);
2389 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, isZero, zero, bitLength,
2396 using OpConversionPattern::OpConversionPattern;
2399 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
2400 ConversionPatternRewriter &rewriter)
const override {
2401 Type resultType = typeConverter->convertType(op.getResult().getType());
2405 adjustIntegerWidth(rewriter, adaptor.getAmount(),
2406 resultType.getIntOrFloatBitWidth(), op->getLoc());
2408 op, resultType, adaptor.getValue(), amount,
false);
2414 using OpConversionPattern::OpConversionPattern;
2417 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
2418 ConversionPatternRewriter &rewriter)
const override {
2419 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
2424struct AssignedVariableOpConversion
2426 using OpConversionPattern::OpConversionPattern;
2429 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
2430 ConversionPatternRewriter &rewriter)
const override {
2431 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
2432 adaptor.getNameAttr());
2438static llhd::TimeAttr
2439getBlockingOrContinuousAssignDelay(mlir::MLIRContext *
context) {
2440 return llhd::TimeAttr::get(
context, 0U,
"ns", 0, 1);
2443template <
typename OpTy>
2446 using OpAdaptor =
typename OpTy::Adaptor;
2449 matchAndRewrite(OpTy op, OpAdaptor adaptor,
2450 ConversionPatternRewriter &rewriter)
const override {
2453 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
2454 std::is_same_v<OpTy, BlockingAssignOp>) {
2455 delay = llhd::ConstantTimeOp::create(
2456 rewriter, op->getLoc(),
2457 getBlockingOrContinuousAssignDelay(op->getContext()));
2458 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
2460 delay = llhd::ConstantTimeOp::create(
2461 rewriter, op->getLoc(),
2462 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
2465 delay = adaptor.getDelay();
2468 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
2469 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
2475 using OpConversionPattern::OpConversionPattern;
2478 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
2479 ConversionPatternRewriter &rewriter)
const override {
2484 auto type = typeConverter->convertType(op.getType());
2486 auto hasNoWriteEffect = [](Region ®ion) {
2487 auto result = region.walk([](Operation *operation) {
2488 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
2489 if (!memOp.hasEffect<MemoryEffects::Write>() &&
2490 !memOp.hasEffect<MemoryEffects::Free>())
2491 return WalkResult::advance();
2493 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
2494 return WalkResult::advance();
2496 return WalkResult::interrupt();
2498 return !result.wasInterrupted();
2501 if (hasNoWriteEffect(op.getTrueRegion()) &&
2502 hasNoWriteEffect(op.getFalseRegion())) {
2503 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
2504 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
2506 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
2507 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
2509 Value convTrueVal = typeConverter->materializeTargetConversion(
2510 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
2511 Value convFalseVal = typeConverter->materializeTargetConversion(
2512 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
2514 rewriter.eraseOp(trueTerm);
2515 rewriter.eraseOp(falseTerm);
2517 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
2518 convTrueVal, convFalseVal);
2523 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
2524 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
2525 ifOp.getThenRegion().end());
2526 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
2527 ifOp.getElseRegion().end());
2528 rewriter.replaceOp(op, ifOp);
2534 using OpConversionPattern::OpConversionPattern;
2537 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
2538 ConversionPatternRewriter &rewriter)
const override {
2539 Operation *parent = op->getParentOp();
2540 if (isa<llhd::GlobalSignalOp>(parent))
2541 rewriter.replaceOpWithNewOp<llhd::YieldOp>(op, adaptor.getResult());
2542 else if (isa<scf::ExecuteRegionOp, scf::ForOp, scf::IfOp,
2543 scf::IndexSwitchOp, scf::WhileOp>(parent))
2544 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
2546 return rewriter.notifyMatchFailure(
2547 op,
"yield parent has not been converted to a legal region op yet");
2552template <
typename SourceOp>
2555 using OpAdaptor =
typename SourceOp::Adaptor;
2558 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
2559 ConversionPatternRewriter &rewriter)
const override {
2560 rewriter.modifyOpInPlace(op,
2561 [&]() { op->setOperands(adaptor.getOperands()); });
2566template <
typename MooreOpTy,
typename VerifOpTy>
2569 using OpAdaptor =
typename MooreOpTy::Adaptor;
2572 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
2573 ConversionPatternRewriter &rewriter)
const override {
2575 op.getLabel().has_value()
2576 ? StringAttr::get(op->getContext(), op.getLabel().value())
2577 : StringAttr::
get(op->getContext());
2578 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
2589 using OpConversionPattern::OpConversionPattern;
2592 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
2593 ConversionPatternRewriter &rewriter)
const override {
2594 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
2600 using OpConversionPattern::OpConversionPattern;
2603 matchAndRewrite(FormatStringOp op, OpAdaptor adaptor,
2604 ConversionPatternRewriter &rewriter)
const override {
2606 op.getPadding().value_or(IntPadding::Space) == IntPadding::Space ? 32
2608 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2609 auto widthAttr = adaptor.getWidthAttr();
2611 bool isLeftAligned =
2612 op.getAlignment().value_or(IntAlign::Right) == IntAlign::Left;
2613 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2615 rewriter.replaceOpWithNewOp<sim::FormatStringOp>(
2616 op, adaptor.getString(), isLeftAlignedAttr, padCharAttr, widthAttr);
2622 using OpConversionPattern::OpConversionPattern;
2625 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
2626 ConversionPatternRewriter &rewriter)
const override {
2627 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
2628 adaptor.getInputs());
2633struct FormatHierPathOpConversion
2635 using OpConversionPattern::OpConversionPattern;
2638 matchAndRewrite(FormatHierPathOp op, OpAdaptor adaptor,
2639 ConversionPatternRewriter &rewriter)
const override {
2640 rewriter.replaceOpWithNewOp<sim::FormatHierPathOp>(op,
2641 adaptor.getUseEscapes());
2647 using OpConversionPattern::OpConversionPattern;
2650 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
2651 ConversionPatternRewriter &rewriter)
const override {
2653 char padChar = adaptor.getPadding() == IntPadding::Space ? 32 : 48;
2654 IntegerAttr padCharAttr = rewriter.getI8IntegerAttr(padChar);
2655 auto widthAttr = adaptor.getSpecifierWidthAttr();
2657 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2658 BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2660 switch (op.getFormat()) {
2661 case IntFormat::Decimal:
2662 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(
2663 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr,
2664 adaptor.getIsSignedAttr());
2666 case IntFormat::Binary:
2667 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(
2668 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2670 case IntFormat::Octal:
2671 rewriter.replaceOpWithNewOp<sim::FormatOctOp>(
2672 op, adaptor.getValue(), isLeftAlignedAttr, padCharAttr, widthAttr);
2674 case IntFormat::HexLower:
2675 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2676 op, adaptor.getValue(), rewriter.getBoolAttr(
false),
2677 isLeftAlignedAttr, padCharAttr, widthAttr);
2679 case IntFormat::HexUpper:
2680 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(
2681 op, adaptor.getValue(), rewriter.getBoolAttr(
true), isLeftAlignedAttr,
2682 padCharAttr, widthAttr);
2685 return rewriter.notifyMatchFailure(op,
"unsupported int format");
2690 using OpConversionPattern::OpConversionPattern;
2693 matchAndRewrite(FormatRealOp op, OpAdaptor adaptor,
2694 ConversionPatternRewriter &rewriter)
const override {
2695 auto fracDigitsAttr = adaptor.getFracDigitsAttr();
2697 auto fieldWidthAttr = adaptor.getFieldWidthAttr();
2698 bool isLeftAligned = adaptor.getAlignment() == IntAlign::Left;
2699 mlir::BoolAttr isLeftAlignedAttr = rewriter.getBoolAttr(isLeftAligned);
2701 switch (op.getFormat()) {
2702 case RealFormat::General:
2703 rewriter.replaceOpWithNewOp<sim::FormatGeneralOp>(
2704 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2707 case RealFormat::Float:
2708 rewriter.replaceOpWithNewOp<sim::FormatFloatOp>(
2709 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2712 case RealFormat::Exponential:
2713 rewriter.replaceOpWithNewOp<sim::FormatScientificOp>(
2714 op, adaptor.getValue(), isLeftAlignedAttr, fieldWidthAttr,
2721struct FormatCharOpConversion
2723 using OpConversionPattern::OpConversionPattern;
2725 matchAndRewrite(moore::FormatCharOp op, OpAdaptor adaptor,
2726 ConversionPatternRewriter &rewriter)
const override {
2727 rewriter.replaceOpWithNewOp<sim::FormatCharOp>(op, adaptor.getValue());
2733 using OpConversionPattern::OpConversionPattern;
2736 matchAndRewrite(StringLenOp op, OpAdaptor adaptor,
2737 ConversionPatternRewriter &rewriter)
const override {
2738 rewriter.replaceOpWithNewOp<sim::StringLengthOp>(op, adaptor.getStr());
2744 using OpConversionPattern::OpConversionPattern;
2747 matchAndRewrite(StringConcatOp op, OpAdaptor adaptor,
2748 ConversionPatternRewriter &rewriter)
const override {
2749 rewriter.replaceOpWithNewOp<sim::StringConcatOp>(op, adaptor.getInputs());
2755 using OpConversionPattern::OpConversionPattern;
2758 matchAndRewrite(StringGetOp op, OpAdaptor adaptor,
2759 ConversionPatternRewriter &rewriter)
const override {
2760 rewriter.replaceOpWithNewOp<sim::StringGetOp>(op, adaptor.getStr(),
2761 adaptor.getIndex());
2767 using OpConversionPattern::OpConversionPattern;
2770 matchAndRewrite(QueueSizeBIOp op, OpAdaptor adaptor,
2771 ConversionPatternRewriter &rewriter)
const override {
2772 rewriter.replaceOpWithNewOp<sim::QueueSizeOp>(op, adaptor.getQueue());
2777struct DynQueueExtractOpConversion
2779 using OpConversionPattern::OpConversionPattern;
2782 matchAndRewrite(DynQueueExtractOp op, OpAdaptor adaptor,
2783 ConversionPatternRewriter &rewriter)
const override {
2784 bool isSingleElementExtract =
2785 op.getInput().getType().getElementType() == op.getResult().getType();
2787 if (isSingleElementExtract) {
2788 rewriter.replaceOpWithNewOp<sim::QueueGetOp>(op, adaptor.getInput(),
2789 adaptor.getLowerIdx());
2791 rewriter.replaceOpWithNewOp<sim::QueueSliceOp>(
2792 op, adaptor.getInput(), adaptor.getLowerIdx(), adaptor.getUpperIdx());
2808probeRefAndDriveWithResult(OpBuilder &builder, Location loc, Value ref,
2809 const std::function<Value(Value)> &func) {
2811 Value v = llhd::ProbeOp::create(builder, loc, ref);
2814 Value delay = llhd::ConstantTimeOp::create(
2815 builder, loc, getBlockingOrContinuousAssignDelay(builder.getContext()));
2817 llhd::DriveOp::create(builder, loc, ref, func(v), delay, Value{});
2821 using OpConversionPattern::OpConversionPattern;
2824 matchAndRewrite(QueuePushBackOp op, OpAdaptor adaptor,
2825 ConversionPatternRewriter &rewriter)
const override {
2826 probeRefAndDriveWithResult(
2827 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2828 return sim::QueuePushBackOp::create(rewriter, op->getLoc(), queue,
2829 adaptor.getElement());
2832 rewriter.eraseOp(op);
2837struct QueuePushFrontOpConversion
2839 using OpConversionPattern::OpConversionPattern;
2842 matchAndRewrite(QueuePushFrontOp op, OpAdaptor adaptor,
2843 ConversionPatternRewriter &rewriter)
const override {
2845 probeRefAndDriveWithResult(
2846 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2847 return sim::QueuePushFrontOp::create(rewriter, op->getLoc(), queue,
2848 adaptor.getElement());
2851 rewriter.eraseOp(op);
2857 using OpConversionPattern::OpConversionPattern;
2860 matchAndRewrite(QueuePopBackOp op, OpAdaptor adaptor,
2861 ConversionPatternRewriter &rewriter)
const override {
2863 probeRefAndDriveWithResult(
2864 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2866 sim::QueuePopBackOp::create(rewriter, op->getLoc(), queue);
2867 popped = popBack.getPopped();
2868 return popBack.getOutQueue();
2870 rewriter.replaceOp(op, popped);
2877 using OpConversionPattern::OpConversionPattern;
2880 matchAndRewrite(QueuePopFrontOp op, OpAdaptor adaptor,
2881 ConversionPatternRewriter &rewriter)
const override {
2883 probeRefAndDriveWithResult(
2884 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2886 sim::QueuePopFrontOp::create(rewriter, op->getLoc(), queue);
2887 popped = popFront.getPopped();
2888 return popFront.getOutQueue();
2890 rewriter.replaceOp(op, popped);
2897 using OpConversionPattern::OpConversionPattern;
2900 matchAndRewrite(QueueClearOp op, OpAdaptor adaptor,
2901 ConversionPatternRewriter &rewriter)
const override {
2902 auto refType = cast<llhd::RefType>(adaptor.getQueue().getType());
2903 auto queueType = refType.getNestedType();
2905 sim::QueueEmptyOp::create(rewriter, op->getLoc(), queueType);
2908 Value delay = llhd::ConstantTimeOp::create(
2909 rewriter, op.getLoc(),
2910 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
2912 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getQueue(), emptyQueue,
2915 rewriter.eraseOp(op);
2921 using OpConversionPattern::OpConversionPattern;
2924 matchAndRewrite(QueueInsertOp op, OpAdaptor adaptor,
2925 ConversionPatternRewriter &rewriter)
const override {
2926 probeRefAndDriveWithResult(
2927 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2929 sim::QueueInsertOp::create(rewriter, op->getLoc(), queue,
2930 adaptor.getIndex(), adaptor.getItem());
2932 return insert.getOutQueue();
2934 rewriter.eraseOp(op);
2941 using OpConversionPattern::OpConversionPattern;
2944 matchAndRewrite(QueueDeleteOp op, OpAdaptor adaptor,
2945 ConversionPatternRewriter &rewriter)
const override {
2946 probeRefAndDriveWithResult(
2947 rewriter, op.getLoc(), adaptor.getQueue(), [&](Value queue) {
2948 auto delOp = sim::QueueDeleteOp::create(rewriter, op->getLoc(), queue,
2949 adaptor.getIndex());
2951 return delOp.getOutQueue();
2953 rewriter.eraseOp(op);
2960 using OpConversionPattern::OpConversionPattern;
2963 matchAndRewrite(QueueResizeOp op, OpAdaptor adaptor,
2964 ConversionPatternRewriter &rewriter)
const override {
2966 rewriter.replaceOpWithNewOp<sim::QueueResizeOp>(
2967 op, getTypeConverter()->convertType(op.getResult().getType()),
2968 adaptor.getInput());
2974 using OpConversionPattern::OpConversionPattern;
2976 matchAndRewrite(QueueSetOp op, OpAdaptor adaptor,
2977 ConversionPatternRewriter &rewriter)
const override {
2978 probeRefAndDriveWithResult(
2979 rewriter, op->getLoc(), adaptor.getQueue(), [&](Value queue) {
2981 sim::QueueSetOp::create(rewriter, op.getLoc(), queue,
2982 adaptor.getIndex(), adaptor.getItem());
2983 return setOp.getOutQueue();
2985 rewriter.eraseOp(op);
2994static Value buildUArrayElementEq(ConversionPatternRewriter &rewriter,
2995 Location loc, Value lhs, Value rhs, Type type,
2996 UArrayCmpPredicate pred) {
2997 bool isEq = pred == UArrayCmpPredicate::eq;
2999 if (isa<mlir::FloatType>(type))
3000 return arith::CmpFOp::create(
3002 isEq ? arith::CmpFPredicate::OEQ : arith::CmpFPredicate::UNE, lhs, rhs);
3004 if (int64_t width = hw::getBitWidth(type); width != -1) {
3005 auto intTy = rewriter.getIntegerType(width);
3008 return comb::ICmpOp::create(rewriter, loc,
3009 isEq ? ICmpPredicate::eq : ICmpPredicate::ne,
3013 if (isa<sim::DynamicStringType>(type))
3014 return sim::StringCmpOp::create(rewriter, loc,
3015 isEq ? sim::StringCmpPredicate::eq
3016 :
sim::StringCmpPredicate::ne,
3019 if (isa<sim::QueueType>(type)) {
3020 auto pred = sim::UArrayCmpPredicateAttr::get(
3021 rewriter.getContext(),
3022 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3023 return sim::QueueCmpOp::create(rewriter, loc, pred, lhs, rhs);
3026 if (isa<sim::AssocArrayType>(type)) {
3027 auto pred = sim::UArrayCmpPredicateAttr::get(
3028 rewriter.getContext(),
3029 isEq ? sim::UArrayCmpPredicate::eq :
sim::UArrayCmpPredicate::ne);
3030 return sim::AssocArrayCmpOp::create(rewriter, loc, pred, lhs, rhs);
3033 auto arrayTy = dyn_cast<hw::ArrayType>(type);
3037 unsigned size = arrayTy.getNumElements();
3041 unsigned idxWidth = size == 1 ? 1 : llvm::Log2_64_Ceil(size);
3042 auto idxTy = rewriter.getIntegerType(idxWidth);
3044 SmallVector<Value> elemEqs;
3045 elemEqs.reserve(size);
3046 for (
unsigned i = 0; i < size; ++i) {
3050 Value elemEq = buildUArrayElementEq(rewriter, loc, lhsElem, rhsElem,
3051 arrayTy.getElementType(), pred);
3054 elemEqs.push_back(elemEq);
3057 return (isEq ? comb::AndOp::create(rewriter, loc, elemEqs,
true)
3059 :
comb::OrOp::create(rewriter, loc, elemEqs, true)
3064 using OpConversionPattern::OpConversionPattern;
3067 matchAndRewrite(QueueCmpOp op, OpAdaptor adaptor,
3068 ConversionPatternRewriter &rewriter)
const override {
3073 Value lhs = adaptor.getLhs();
3075 buildUArrayElementEq(rewriter, op.getLoc(), lhs, adaptor.getRhs(),
3076 lhs.getType(), op.getPredicate());
3077 rewriter.replaceOp(op, result);
3082struct QueueFromUnpackedArrayOpConversion
3084 using OpConversionPattern::OpConversionPattern;
3087 matchAndRewrite(QueueFromUnpackedArrayOp op, OpAdaptor adaptor,
3088 ConversionPatternRewriter &rewriter)
const override {
3089 rewriter.replaceOpWithNewOp<sim::QueueFromArrayOp>(
3090 op, getTypeConverter()->convertType(op.getResult().getType()),
3091 adaptor.getInput());
3097 using OpConversionPattern::OpConversionPattern;
3100 matchAndRewrite(QueueConcatOp op, OpAdaptor adaptor,
3101 ConversionPatternRewriter &rewriter)
const override {
3102 rewriter.replaceOpWithNewOp<sim::QueueConcatOp>(
3103 op, getTypeConverter()->convertType(op.getResult().getType()),
3104 adaptor.getInputs());
3109struct AssocArrayExtractOpConversion
3111 using OpConversionPattern::OpConversionPattern;
3113 matchAndRewrite(AssocArrayExtractOp op, OpAdaptor adaptor,
3114 ConversionPatternRewriter &rewriter)
const override {
3115 Type resultType = getTypeConverter()->convertType(op.getResult().getType());
3123 sim::AssocArrayGetOp::create(rewriter, op.getLoc(), resultType,
3124 adaptor.getInput(), adaptor.getIndex());
3125 Value exists = sim::AssocArrayExistsOp::create(
3126 rewriter, op.getLoc(), adaptor.getInput(), adaptor.getIndex());
3128 Value existsBit = comb::ICmpOp::create(
3129 rewriter, op.getLoc(), comb::ICmpPredicate::ne, exists, zeroI32,
false);
3130 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, existsBit, raw, zero,
false);
3136 using OpConversionPattern::OpConversionPattern;
3138 matchAndRewrite(UArrayCmpOp op, OpAdaptor adaptor,
3139 ConversionPatternRewriter &rewriter)
const override {
3140 Value lhs = adaptor.getLhs();
3141 Value rhs = adaptor.getRhs();
3142 auto pred = op.getPredicate();
3143 Value eq = buildUArrayElementEq(rewriter, op.getLoc(), lhs, rhs,
3144 lhs.getType(), pred);
3147 return rewriter.notifyMatchFailure(
3148 op,
"unpacked array element type does not support comparison");
3150 rewriter.replaceOp(op, eq);
3156 using OpConversionPattern::OpConversionPattern;
3158 matchAndRewrite(AssocArraySetOp op, OpAdaptor adaptor,
3159 ConversionPatternRewriter &rewriter)
const override {
3160 probeRefAndDriveWithResult(
3161 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3162 return sim::AssocArraySetOp::create(rewriter, op.getLoc(), array,
3167 rewriter.eraseOp(op);
3172struct AssocArrayDeleteOpConversion
3174 using OpConversionPattern::OpConversionPattern;
3176 matchAndRewrite(AssocArrayDeleteOp op, OpAdaptor adaptor,
3177 ConversionPatternRewriter &rewriter)
const override {
3178 probeRefAndDriveWithResult(
3179 rewriter, op.getLoc(), adaptor.getAssocArray(), [&](Value array) {
3180 return sim::AssocArrayDeleteOp::create(rewriter, op.getLoc(), array,
3184 rewriter.eraseOp(op);
3189struct AssocArrayClearOpConversion
3191 using OpConversionPattern::OpConversionPattern;
3193 matchAndRewrite(AssocArrayClearOp op, OpAdaptor adaptor,
3194 ConversionPatternRewriter &rewriter)
const override {
3195 auto refType = cast<llhd::RefType>(adaptor.getAssocArray().getType());
3196 Value emptyArray = sim::AssocArrayEmptyOp::create(rewriter, op->getLoc(),
3197 refType.getNestedType());
3198 Value delay = llhd::ConstantTimeOp::create(
3199 rewriter, op.getLoc(),
3200 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3201 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getAssocArray(),
3202 emptyArray, delay, Value{});
3203 rewriter.eraseOp(op);
3208struct AssocArraySizeOpConversion
3210 using OpConversionPattern::OpConversionPattern;
3212 matchAndRewrite(AssocArraySizeOp op, OpAdaptor adaptor,
3213 ConversionPatternRewriter &rewriter)
const override {
3215 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3216 rewriter.replaceOpWithNewOp<sim::AssocArraySizeOp>(op, array);
3221struct AssocArrayExistsOpConversion
3223 using OpConversionPattern::OpConversionPattern;
3225 matchAndRewrite(AssocArrayExistsOp op, OpAdaptor adaptor,
3226 ConversionPatternRewriter &rewriter)
const override {
3228 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3229 rewriter.replaceOpWithNewOp<sim::AssocArrayExistsOp>(op, array,
3230 adaptor.getIndex());
3235template <
typename MooreOpTy,
typename SimOpTy>
3238 using OpAdaptor =
typename MooreOpTy::Adaptor;
3240 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3241 ConversionPatternRewriter &rewriter)
const override {
3243 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3244 auto endpointOp = SimOpTy::create(rewriter, op.getLoc(), array);
3246 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3249 comb::ICmpOp::create(rewriter, op.getLoc(), comb::ICmpPredicate::ne,
3250 endpointOp->getResult(0), zero,
false);
3252 comb::MuxOp::create(rewriter, op.getLoc(), foundBit,
3253 endpointOp->getResult(1), curIndex,
false);
3254 Value delay = llhd::ConstantTimeOp::create(
3255 rewriter, op.getLoc(),
3256 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3257 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(), newIndex,
3259 rewriter.replaceOp(op, endpointOp->getResult(0));
3264template <
typename MooreOpTy,
typename SimOpTy>
3267 using OpAdaptor =
typename MooreOpTy::Adaptor;
3269 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
3270 ConversionPatternRewriter &rewriter)
const override {
3272 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getAssocArray());
3274 llhd::ProbeOp::create(rewriter, op.getLoc(), adaptor.getIndex());
3275 auto stepOp = SimOpTy::create(rewriter, op.getLoc(), array, curIndex);
3276 Value delay = llhd::ConstantTimeOp::create(
3277 rewriter, op.getLoc(),
3278 getBlockingOrContinuousAssignDelay(rewriter.getContext()));
3279 llhd::DriveOp::create(rewriter, op.getLoc(), adaptor.getIndex(),
3280 stepOp->getResult(1), delay, Value{});
3281 rewriter.replaceOp(op, stepOp->getResult(0));
3286using AssocArrayFirstOpConversion =
3287 AssocArrayEndpointOpConversion<AssocArrayFirstOp, sim::AssocArrayFirstOp>;
3288using AssocArrayLastOpConversion =
3289 AssocArrayEndpointOpConversion<AssocArrayLastOp, sim::AssocArrayLastOp>;
3290using AssocArrayNextOpConversion =
3291 AssocArrayStepOpConversion<AssocArrayNextOp, sim::AssocArrayNextOp>;
3292using AssocArrayPrevOpConversion =
3293 AssocArrayStepOpConversion<AssocArrayPrevOp, sim::AssocArrayPrevOp>;
3296 using OpConversionPattern::OpConversionPattern;
3299 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
3300 ConversionPatternRewriter &rewriter)
const override {
3301 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3302 op, adaptor.getMessage());
3308 using OpConversionPattern::OpConversionPattern;
3310 matchAndRewrite(FDisplayBIOp op, OpAdaptor adaptor,
3311 ConversionPatternRewriter &rewriter)
const override {
3312 auto stream = sim::SVChannelToOutputStreamOp::create(rewriter, op.getLoc(),
3314 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
3315 op, adaptor.getMessage(), stream.getStream());
3321 using OpConversionPattern::OpConversionPattern;
3323 matchAndRewrite(FOpenBIOp op, OpAdaptor adaptor,
3324 ConversionPatternRewriter &rewriter)
const override {
3325 sim::SVFOpenModeAttr simMode;
3326 if (
auto modeAttr = op.getModeAttr()) {
3327 auto mapMode = [](moore::FOpenMode m) -> sim::SVFOpenMode {
3329 case moore::FOpenMode::Read:
3330 return sim::SVFOpenMode::Read;
3331 case moore::FOpenMode::Write:
3332 return sim::SVFOpenMode::Write;
3333 case moore::FOpenMode::Append:
3334 return sim::SVFOpenMode::Append;
3335 case moore::FOpenMode::ReadUpdate:
3336 return sim::SVFOpenMode::ReadUpdate;
3337 case moore::FOpenMode::WriteUpdate:
3338 return sim::SVFOpenMode::WriteUpdate;
3339 case moore::FOpenMode::AppendUpdate:
3340 return sim::SVFOpenMode::AppendUpdate;
3342 llvm_unreachable(
"unknown FOpenMode");
3344 simMode = sim::SVFOpenModeAttr::get(op.getContext(),
3345 mapMode(modeAttr.getValue()));
3347 rewriter.replaceOpWithNewOp<sim::SVFOpenOp>(op, adaptor.getFilename(),
3353struct PlusArgsTestBIOpConversion
3355 using OpConversionPattern::OpConversionPattern;
3357 matchAndRewrite(PlusArgsTestBIOp op, OpAdaptor adaptor,
3358 ConversionPatternRewriter &rewriter)
const override {
3359 rewriter.replaceOpWithNewOp<sim::PlusArgsTestOp>(op, rewriter.getI1Type(),
3360 op.getFormatStringAttr());
3365struct PlusArgsValueBIOpConversion
3367 using OpConversionPattern::OpConversionPattern;
3369 matchAndRewrite(PlusArgsValueBIOp op, OpAdaptor adaptor,
3370 ConversionPatternRewriter &rewriter)
const override {
3371 auto resultType = typeConverter->convertType(op.getResult().getType());
3373 return rewriter.notifyMatchFailure(op,
"unsupported result type");
3374 rewriter.replaceOpWithNewOp<sim::PlusArgsValueOp>(
3375 op, rewriter.getI1Type(), resultType, op.getFormatStringAttr());
3381 using OpConversionPattern::OpConversionPattern;
3384 matchAndRewrite(FCloseBIOp op, OpAdaptor adaptor,
3385 ConversionPatternRewriter &rewriter)
const override {
3386 rewriter.replaceOpWithNewOp<sim::SVFCloseOp>(op, adaptor.getFd());
3392 using OpConversionPattern::OpConversionPattern;
3395 matchAndRewrite(FFlushBIOp op, OpAdaptor adaptor,
3396 ConversionPatternRewriter &rewriter)
const override {
3397 if (!adaptor.getFd()) {
3398 rewriter.replaceOpWithNewOp<sim::SVFFlushAllOp>(op);
3400 auto stream = sim::SVChannelToOutputStreamOp::create(
3401 rewriter, op.getLoc(), adaptor.getFd());
3402 rewriter.replaceOpWithNewOp<sim::FlushOp>(op, stream);
3409 using OpConversionPattern::OpConversionPattern;
3412 matchAndRewrite(StringCmpOp op, OpAdaptor adaptor,
3413 ConversionPatternRewriter &rewriter)
const override {
3414 sim::StringCmpPredicate pred;
3415 switch (op.getPredicate()) {
3416 case moore::StringCmpPredicate::eq:
3417 pred = sim::StringCmpPredicate::eq;
3419 case moore::StringCmpPredicate::ne:
3420 pred = sim::StringCmpPredicate::ne;
3422 case moore::StringCmpPredicate::lt:
3423 pred = sim::StringCmpPredicate::lt;
3425 case moore::StringCmpPredicate::le:
3426 pred = sim::StringCmpPredicate::le;
3428 case moore::StringCmpPredicate::gt:
3429 pred = sim::StringCmpPredicate::gt;
3431 case moore::StringCmpPredicate::ge:
3432 pred = sim::StringCmpPredicate::ge;
3435 rewriter.replaceOpWithNewOp<sim::StringCmpOp>(op, pred, adaptor.getLhs(),
3442 using OpConversionPattern::OpConversionPattern;
3445 matchAndRewrite(ReadMemBIOp op, OpAdaptor adaptor,
3446 ConversionPatternRewriter &rewriter)
const override {
3447 auto loc = op.getLoc();
3448 Value memory = llhd::ProbeOp::create(rewriter, loc, adaptor.getDest());
3449 Value loaded = sim::SVReadMemOp::create(
3450 rewriter, loc, memory.getType(), adaptor.getFilename(), memory,
3451 rewriter.getBoolAttr(op.getBase() == MemBase::Binary),
3452 adaptor.getStartAddr(), adaptor.getFinishAddr(), adaptor.getSliceLeft(),
3453 adaptor.getSliceRight(), op.getDimLowsAttr(), op.getDimDescendingAttr(),
3454 op.getEnumValuesAttr());
3455 Value delay = llhd::ConstantTimeOp::create(
3457 llhd::TimeAttr::get(rewriter.getContext(), 0U,
"ns", 0, 1));
3458 rewriter.replaceOpWithNewOp<llhd::DriveOp>(op, adaptor.getDest(), loaded,
3471static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
3472 ConversionPatternRewriter &rewriter) {
3473 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
3478static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
3479 ConversionPatternRewriter &rewriter) {
3480 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
3486static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
3487 ConversionPatternRewriter &rewriter) {
3489 std::string severityString;
3491 switch (op.getSeverity()) {
3492 case (Severity::Fatal):
3493 severityString =
"Fatal: ";
3495 case (Severity::Error):
3496 severityString =
"Error: ";
3498 case (Severity::Warning):
3499 severityString =
"Warning: ";
3501 case (Severity::Info):
3502 severityString =
"Info: ";
3507 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
3508 auto message = sim::FormatStringConcatOp::create(
3509 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
3510 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
3524 UrandomRangeBIOp::Adaptor adaptor,
3525 ConversionPatternRewriter &rewriter,
3526 FunctionCache &funcCache) {
3527 auto loc = op.getLoc();
3528 auto i32Ty = rewriter.getI32Type();
3529 auto ptrTy = LLVM::LLVMPointerType::get(rewriter.getContext());
3530 auto fn = funcCache.getOrCreate(rewriter,
"__circt_urandom_range",
3531 {i32Ty, i32Ty, ptrTy}, {i32Ty});
3534 if (
auto seedRef = adaptor.getSeed()) {
3537 seedPtr = LLVM::AllocaOp::create(rewriter, loc, ptrTy, i32Ty, one);
3538 auto seedVal = llhd::ProbeOp::create(rewriter, loc, seedRef);
3539 LLVM::StoreOp::create(rewriter, loc, seedVal, seedPtr);
3541 seedPtr = LLVM::ZeroOp::create(rewriter, loc, ptrTy);
3544 auto call = func::CallOp::create(
3546 ValueRange{adaptor.getMinval(), adaptor.getMaxval(), seedPtr});
3549 if (adaptor.getSeed()) {
3550 auto newSeed = LLVM::LoadOp::create(rewriter, loc, i32Ty, seedPtr);
3551 auto epsilon = llhd::ConstantTimeOp::create(
3553 llhd::TimeAttr::get(rewriter.getContext(), 0,
"ns", 0, 1));
3554 llhd::DriveOp::create(rewriter, loc, adaptor.getSeed(), newSeed, epsilon,
3558 rewriter.replaceOp(op, call.getResult(0));
3564 FinishMessageBIOp::Adaptor adaptor,
3565 ConversionPatternRewriter &rewriter) {
3567 rewriter.eraseOp(op);
3576static LogicalResult
convert(TimeBIOp op, TimeBIOp::Adaptor adaptor,
3577 ConversionPatternRewriter &rewriter) {
3578 rewriter.replaceOpWithNewOp<llhd::CurrentTimeOp>(op);
3583static LogicalResult
convert(LogicToTimeOp op, LogicToTimeOp::Adaptor adaptor,
3584 ConversionPatternRewriter &rewriter) {
3585 rewriter.replaceOpWithNewOp<llhd::IntToTimeOp>(op, adaptor.getInput());
3590static LogicalResult
convert(TimeToLogicOp op, TimeToLogicOp::Adaptor adaptor,
3591 ConversionPatternRewriter &rewriter) {
3592 rewriter.replaceOpWithNewOp<llhd::TimeToIntOp>(op, adaptor.getInput());
3601 const TypeConverter &converter) {
3602 target.addIllegalDialect<MooreDialect>();
3603 target.addLegalDialect<comb::CombDialect>();
3604 target.addLegalDialect<hw::HWDialect>();
3605 target.addLegalDialect<seq::SeqDialect>();
3606 target.addLegalDialect<llhd::LLHDDialect>();
3607 target.addLegalDialect<ltl::LTLDialect>();
3608 target.addLegalDialect<mlir::BuiltinDialect>();
3609 target.addLegalDialect<mlir::math::MathDialect>();
3610 target.addLegalDialect<sim::SimDialect>();
3611 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
3612 target.addLegalDialect<mlir::ub::UBDialect>();
3613 target.addLegalDialect<verif::VerifDialect>();
3614 target.addLegalDialect<arith::ArithDialect>();
3616 target.addLegalOp<debug::ScopeOp>();
3618 target.addDynamicallyLegalOp<scf::YieldOp, func::CallOp, func::ReturnOp,
3619 UnrealizedConversionCastOp, hw::OutputOp,
3620 hw::InstanceOp, debug::ArrayOp, debug::StructOp,
3621 debug::VariableOp, arith::SelectOp>(
3622 [&](Operation *op) {
return converter.isLegal(op); });
3624 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
3625 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
3626 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
3629 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
3630 return converter.isSignatureLegal(op.getFunctionType());
3634 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
3635 converter.isLegal(&op.getBody());
3640 typeConverter.addConversion([&](IntType type) {
3641 return IntegerType::get(type.getContext(), type.getWidth());
3644 typeConverter.addConversion([&](RealType type) -> mlir::Type {
3645 MLIRContext *ctx = type.getContext();
3646 switch (type.getWidth()) {
3647 case moore::RealWidth::f32:
3648 return mlir::Float32Type::get(ctx);
3649 case moore::RealWidth::f64:
3650 return mlir::Float64Type::get(ctx);
3654 typeConverter.addConversion(
3655 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
3657 typeConverter.addConversion([&](FormatStringType type) {
3658 return sim::FormatStringType::get(type.getContext());
3661 typeConverter.addConversion([&](StringType type) {
3662 return sim::DynamicStringType::get(type.getContext());
3665 typeConverter.addConversion([&](QueueType type) {
3666 return sim::QueueType::get(type.getContext(),
3667 typeConverter.convertType(type.getElementType()),
3671 typeConverter.addConversion([&](sim::QueueType type) -> std::optional<Type> {
3672 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3673 return sim::QueueType::get(type.getContext(),
elementType,
3678 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
3679 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3680 return hw::ArrayType::get(
elementType, type.getSize());
3684 typeConverter.addConversion([&](AssocArrayType type) -> std::optional<Type> {
3685 auto elementType = typeConverter.convertType(type.getElementType());
3686 auto indexType = typeConverter.convertType(type.getIndexType());
3689 return sim::AssocArrayType::get(type.getContext(),
elementType, indexType);
3695 typeConverter.addConversion(
3696 [&](UnpackedArrayType type) -> std::optional<Type> {
3697 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3698 return hw::ArrayType::get(
elementType, type.getSize());
3702 typeConverter.addConversion([&](OpenArrayType type) -> std::optional<Type> {
3703 return LLVM::LLVMPointerType::get(type.getContext());
3706 typeConverter.addConversion(
3707 [&](OpenUnpackedArrayType type) -> std::optional<Type> {
3708 return LLVM::LLVMPointerType::get(type.getContext());
3711 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
3712 SmallVector<hw::StructType::FieldInfo> fields;
3713 for (
auto field : type.getMembers()) {
3714 hw::StructType::FieldInfo info;
3715 info.type = typeConverter.convertType(field.type);
3718 info.name = field.name;
3719 fields.push_back(info);
3721 return hw::StructType::get(type.getContext(), fields);
3729 typeConverter.addConversion(
3730 [&](UnpackedStructType type) -> std::optional<Type> {
3731 SmallVector<hw::StructType::FieldInfo> fields;
3732 for (
auto field : type.getMembers()) {
3733 hw::StructType::FieldInfo info;
3734 info.type = typeConverter.convertType(field.type);
3737 info.name = field.name;
3738 fields.push_back(info);
3740 return hw::StructType::get(type.getContext(), fields);
3744 typeConverter.addConversion([&](UnionType type) -> std::optional<Type> {
3745 SmallVector<hw::UnionType::FieldInfo> fields;
3746 for (
auto field : type.getMembers()) {
3747 hw::UnionType::FieldInfo info;
3748 info.type = typeConverter.convertType(field.type);
3751 info.name = field.name;
3753 fields.push_back(info);
3755 auto result = hw::UnionType::get(type.getContext(), fields);
3760 typeConverter.addConversion(
3761 [&](UnpackedUnionType type) -> std::optional<Type> {
3762 SmallVector<hw::UnionType::FieldInfo> fields;
3763 for (
auto field : type.getMembers()) {
3764 hw::UnionType::FieldInfo info;
3765 info.type = typeConverter.convertType(field.type);
3768 info.name = field.name;
3770 fields.push_back(info);
3772 return hw::UnionType::get(type.getContext(), fields);
3776 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
3777 return LLVM::LLVMPointerType::get(type.getContext());
3781 typeConverter.addConversion(
3782 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
3785 typeConverter.addConversion([&](ClassHandleType type) -> std::optional<Type> {
3786 return LLVM::LLVMPointerType::get(type.getContext());
3790 typeConverter.addConversion([&](NullType type) -> std::optional<Type> {
3791 return LLVM::LLVMPointerType::get(type.getContext());
3794 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
3795 if (isa<OpenArrayType, OpenUnpackedArrayType>(type.getNestedType()))
3796 return LLVM::LLVMPointerType::get(type.getContext());
3797 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3798 return llhd::RefType::get(innerType);
3803 typeConverter.addConversion([](IntegerType type) {
return type; });
3804 typeConverter.addConversion([](FloatType type) {
return type; });
3805 typeConverter.addConversion([](sim::DynamicStringType type) {
return type; });
3806 typeConverter.addConversion([](sim::FormatStringType type) {
return type; });
3807 typeConverter.addConversion([](sim::AssocArrayType type) {
return type; });
3808 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
3809 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
3810 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
3811 typeConverter.addConversion([](debug::StructType type) {
return type; });
3813 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
3814 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
3815 return llhd::RefType::get(innerType);
3819 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
3820 if (
auto elementType = typeConverter.convertType(type.getElementType()))
3821 return hw::ArrayType::get(
elementType, type.getNumElements());
3825 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
3826 SmallVector<hw::StructType::FieldInfo> fields;
3827 for (
auto field : type.getElements()) {
3828 hw::StructType::FieldInfo info;
3829 info.type = typeConverter.convertType(field.type);
3832 info.name = field.name;
3833 fields.push_back(info);
3835 return hw::StructType::get(type.getContext(), fields);
3838 typeConverter.addConversion([&](hw::UnionType type) -> std::optional<Type> {
3839 SmallVector<hw::UnionType::FieldInfo> fields;
3840 for (
auto field : type.getElements()) {
3841 hw::UnionType::FieldInfo info;
3842 info.type = typeConverter.convertType(field.type);
3845 info.name = field.name;
3846 info.offset = field.offset;
3847 fields.push_back(info);
3849 return hw::UnionType::get(type.getContext(), fields);
3852 typeConverter.addTargetMaterialization(
3853 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3854 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3855 if (inputs.size() != 1 || !inputs[0])
3857 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3862 typeConverter.addSourceMaterialization(
3863 [&](mlir::OpBuilder &builder, mlir::Type resultType,
3864 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
3865 if (inputs.size() != 1)
3867 return UnrealizedConversionCastOp::create(builder, loc, resultType,
3874 TypeConverter &typeConverter,
3875 ClassTypeCache &classCache,
3876 FunctionCache &funcCache) {
3881 classCache, funcCache);
3882 patterns.add<ClassPropertyRefOpConversion>(typeConverter,
3883 patterns.getContext(), classCache);
3887 ClassUpcastOpConversion,
3888 NullOpConversion<NullOp>,
3889 NullOpConversion<NullChandleOp>,
3890 NullOpConversion<NullClassOp>,
3892 VariableOpConversion,
3896 BitcastConversion<PackedToSBVOp>,
3897 BitcastConversion<SBVToPackedOp>,
3898 NoOpConversion<LogicToIntOp>,
3899 NoOpConversion<IntToLogicOp>,
3900 NoOpConversion<ToBuiltinIntOp>,
3901 NoOpConversion<FromBuiltinIntOp>,
3905 SIntToRealOpConversion,
3906 UIntToRealOpConversion,
3907 IntToStringOpConversion,
3908 StringToIntOpConversion,
3909 FormatStringToStringOpConversion,
3910 RealToIntOpConversion,
3911 ConvertRealOpConversion,
3912 RealBitcastOpConversion<RealtobitsBIOp>,
3913 RealBitcastOpConversion<BitstorealBIOp>,
3914 RealBitcastOpConversion<ShortrealtobitsBIOp>,
3915 RealBitcastOpConversion<BitstoshortrealBIOp>,
3921 ReplicateOpConversion,
3923 ExtractOpConversion,
3924 DynExtractOpConversion,
3925 DynExtractRefOpConversion,
3927 StructExtractOpConversion,
3928 StructExtractRefOpConversion,
3929 ExtractRefOpConversion,
3930 StructCreateOpConversion,
3931 UnionCreateOpConversion,
3932 UnionExtractOpConversion,
3933 UnionExtractRefOpConversion,
3934 ConditionalOpConversion,
3935 ArrayCreateOpConversion,
3936 UArrayCmpOpConversion,
3939 ConstantStringOpConv,
3942 ReduceAndOpConversion,
3943 ReduceOrOpConversion,
3944 ReduceXorOpConversion,
3945 BoolCastOpConversion,
3950 BinaryOpConversion<AddOp, comb::AddOp>,
3951 BinaryOpConversion<SubOp, comb::SubOp>,
3952 BinaryOpConversion<MulOp, comb::MulOp>,
3953 BinaryOpConversion<DivUOp, comb::DivUOp>,
3954 BinaryOpConversion<DivSOp, comb::DivSOp>,
3955 BinaryOpConversion<ModUOp, comb::ModUOp>,
3956 BinaryOpConversion<ModSOp, comb::ModSOp>,
3957 BinaryOpConversion<AndOp, comb::AndOp>,
3958 BinaryOpConversion<OrOp, comb::OrOp>,
3959 BinaryOpConversion<XorOp, comb::XorOp>,
3962 NegRealOpConversion,
3965 BinaryRealOpConversion<AddRealOp, arith::AddFOp>,
3966 BinaryRealOpConversion<SubRealOp, arith::SubFOp>,
3967 BinaryRealOpConversion<DivRealOp, arith::DivFOp>,
3968 BinaryRealOpConversion<MulRealOp, arith::MulFOp>,
3969 BinaryRealOpConversion<PowRealOp, math::PowFOp>,
3972 RealMathFunc<LnBIOp, math::LogOp>,
3973 RealMathFunc<Log10BIOp, math::Log10Op>,
3974 RealMathFunc<ExpBIOp, math::ExpOp>,
3975 RealMathFunc<SqrtBIOp, math::SqrtOp>,
3976 BinaryRealOpConversion<MinBIOp, arith::MinimumFOp>,
3977 BinaryRealOpConversion<MaxBIOp, arith::MaximumFOp>,
3978 RealMathFunc<AbsBIOp, math::AbsFOp>,
3979 RealMathFunc<FloorBIOp, math::FloorOp>,
3980 RealMathFunc<CeilBIOp, math::CeilOp>,
3981 RealMathFunc<SinBIOp, math::SinOp>,
3982 RealMathFunc<CosBIOp, math::CosOp>,
3983 RealMathFunc<TanBIOp, math::TanOp>,
3984 RealMathFunc<AsinBIOp, math::AsinOp>,
3985 RealMathFunc<AcosBIOp, math::AcosOp>,
3986 RealMathFunc<AtanBIOp, math::AtanOp>,
3987 BinaryRealOpConversion<Atan2BIOp, math::Atan2Op>,
3988 HypotBIOpConversion,
3989 RealMathFunc<SinhBIOp, math::SinhOp>,
3990 RealMathFunc<CoshBIOp, math::CoshOp>,
3991 RealMathFunc<TanhBIOp, math::TanhOp>,
3992 RealMathFunc<AsinhBIOp, math::AsinhOp>,
3993 RealMathFunc<AcoshBIOp, math::AcoshOp>,
3994 RealMathFunc<AtanhBIOp, math::AtanhOp>,
3997 PowUOpConversion, PowSOpConversion,
3998 Clog2BIOpConversion,
4001 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
4002 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
4003 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
4004 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
4005 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
4006 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
4007 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
4008 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
4009 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
4010 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
4011 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
4012 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
4013 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
4014 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
4015 FCmpOpConversion<NeRealOp, arith::CmpFPredicate::UNE>,
4016 FCmpOpConversion<FltOp, arith::CmpFPredicate::OLT>,
4017 FCmpOpConversion<FleOp, arith::CmpFPredicate::OLE>,
4018 FCmpOpConversion<FgtOp, arith::CmpFPredicate::OGT>,
4019 FCmpOpConversion<FgeOp, arith::CmpFPredicate::OGE>,
4020 FCmpOpConversion<EqRealOp, arith::CmpFPredicate::OEQ>,
4021 CaseXZEqOpConversion<CaseZEqOp, true>,
4022 CaseXZEqOpConversion<CaseXZEqOp, false>,
4023 HandleCmpOpConversion<HandleEqOp, LLVM::ICmpPredicate::eq>,
4024 HandleCmpOpConversion<HandleNeOp, LLVM::ICmpPredicate::ne>,
4027 SVModuleOpConversion,
4028 InstanceOpConversion,
4029 ProcedureOpConversion,
4030 CoroutineOpConversion,
4031 CallCoroutineOpConversion,
4032 WaitEventOpConversion,
4040 AssignOpConversion<ContinuousAssignOp>,
4041 AssignOpConversion<DelayedContinuousAssignOp>,
4042 AssignOpConversion<BlockingAssignOp>,
4043 AssignOpConversion<NonBlockingAssignOp>,
4044 AssignOpConversion<DelayedNonBlockingAssignOp>,
4045 AssignedVariableOpConversion,
4048 HWInstanceOpConversion,
4051 DPIFuncOpConversion,
4052 FuncDPICallOpConversion,
4053 UnrealizedConversionCastConversion,
4054 InPlaceOpConversion<debug::ArrayOp>,
4055 InPlaceOpConversion<debug::StructOp>,
4056 InPlaceOpConversion<debug::VariableOp>,
4059 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
4060 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
4061 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
4064 FormatLiteralOpConversion,
4065 FormatStringOpConversion,
4066 FormatConcatOpConversion,
4067 FormatHierPathOpConversion,
4068 FormatIntOpConversion,
4069 FormatRealOpConversion,
4070 FormatCharOpConversion,
4071 DisplayBIOpConversion,
4072 FDisplayBIOpConversion,
4075 FOpenBIOpConversion,
4076 FCloseBIOpConversion,
4077 FFlushBIOpConversion,
4078 ReadMemBIOpConversion,
4081 PlusArgsTestBIOpConversion,
4082 PlusArgsValueBIOpConversion,
4085 StringLenOpConversion,
4086 StringConcatOpConversion,
4087 StringGetOpConversion,
4088 StringCmpOpConversion,
4091 QueueSizeBIOpConversion,
4092 QueuePushBackOpConversion,
4093 QueuePushFrontOpConversion,
4094 QueuePopBackOpConversion,
4095 QueuePopFrontOpConversion,
4096 QueueDeleteOpConversion,
4097 QueueInsertOpConversion,
4098 QueueClearOpConversion,
4099 DynQueueExtractOpConversion,
4100 QueueResizeOpConversion,
4101 QueueSetOpConversion,
4102 QueueCmpOpConversion,
4103 QueueFromUnpackedArrayOpConversion,
4104 QueueConcatOpConversion,
4107 AssocArrayExtractOpConversion,
4108 AssocArraySetOpConversion,
4109 AssocArrayDeleteOpConversion,
4110 AssocArrayClearOpConversion,
4111 AssocArraySizeOpConversion,
4112 AssocArrayExistsOpConversion,
4113 AssocArrayFirstOpConversion,
4114 AssocArrayLastOpConversion,
4115 AssocArrayNextOpConversion,
4116 AssocArrayPrevOpConversion
4117 >(typeConverter,
patterns.getContext());
4140 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
4142 hw::populateHWModuleLikeTypeConversionPattern(
4143 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
4144 populateSCFToControlFlowConversionPatterns(
patterns);
4153struct MooreToCorePass
4154 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
4155 void runOnOperation()
override;
4161 return std::make_unique<MooreToCorePass>();
4165void MooreToCorePass::runOnOperation() {
4166 MLIRContext &
context = getContext();
4167 ModuleOp
module = getOperation();
4168 ClassTypeCache classCache;
4169 auto &symbolTable = getAnalysis<SymbolTable>();
4170 FunctionCache funcCache(symbolTable);
4172 IRRewriter rewriter(module);
4173 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
4175 TypeConverter typeConverter;
4178 ConversionTarget target(
context);
4183 mlir::cf::populateCFStructuralTypeConversionsAndLegality(typeConverter,
4186 if (failed(applyFullConversion(module, target, std::move(
patterns))))
4187 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.