21#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
22#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
23#include "mlir/Dialect/Func/IR/FuncOps.h"
24#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
25#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
26#include "mlir/Dialect/Math/IR/Math.h"
27#include "mlir/Dialect/SCF/IR/SCF.h"
28#include "mlir/IR/BuiltinDialect.h"
29#include "mlir/IR/Iterators.h"
30#include "mlir/Interfaces/SideEffectInterfaces.h"
31#include "mlir/Pass/Pass.h"
32#include "mlir/Transforms/DialectConversion.h"
33#include "mlir/Transforms/RegionUtils.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/IR/DerivedTypes.h"
38#define GEN_PASS_DEF_CONVERTMOORETOCORE
39#include "circt/Conversion/Passes.h.inc"
46using comb::ICmpPredicate;
47using llvm::SmallDenseSet;
55static Value adjustIntegerWidth(OpBuilder &builder, Value value,
56 uint32_t targetWidth, Location loc) {
57 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
58 if (intWidth == targetWidth)
61 if (intWidth < targetWidth) {
63 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
64 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
68 intWidth - targetWidth);
70 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
71 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
75 builder.getIntegerType(targetWidth), -1);
76 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
84 auto moduleTy = op.getModuleType();
85 SmallVector<hw::PortInfo> ports;
86 ports.reserve(moduleTy.getNumPorts());
88 for (
auto port : moduleTy.getPorts()) {
89 Type portTy = typeConverter.convertType(port.type);
90 if (port.dir == hw::ModulePort::Direction::Output) {
92 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
100 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
112 using OpConversionPattern::OpConversionPattern;
115 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
116 ConversionPatternRewriter &rewriter)
const override {
117 rewriter.setInsertionPoint(op);
121 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getSymNameAttr(),
122 getModulePortInfo(*typeConverter, op));
125 SymbolTable::setSymbolVisibility(hwModuleOp,
126 SymbolTable::getSymbolVisibility(op));
127 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
129 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
131 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
132 hwModuleOp.getBodyRegion().end());
135 rewriter.eraseOp(op);
141 using OpConversionPattern::OpConversionPattern;
144 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
145 ConversionPatternRewriter &rewriter)
const override {
146 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
152 using OpConversionPattern::OpConversionPattern;
155 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
156 ConversionPatternRewriter &rewriter)
const override {
157 auto instName = op.getInstanceNameAttr();
158 auto moduleName = op.getModuleNameAttr();
161 rewriter.setInsertionPoint(op);
162 auto instOp = hw::InstanceOp::create(
163 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
164 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
165 rewriter.getArrayAttr({}),
nullptr,
169 op.replaceAllUsesWith(instOp.getResults());
170 rewriter.eraseOp(op);
175static void getValuesToObserve(Region *region,
176 function_ref<
void(Value)> setInsertionPoint,
177 const TypeConverter *typeConverter,
178 ConversionPatternRewriter &rewriter,
179 SmallVector<Value> &observeValues) {
180 SmallDenseSet<Value> alreadyObserved;
181 Location loc = region->getLoc();
183 auto probeIfSignal = [&](Value value) -> Value {
184 if (!isa<llhd::RefType>(value.getType()))
186 return llhd::ProbeOp::create(rewriter, loc, value);
189 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
190 [&](Operation *operation) {
191 for (
auto value : operation->getOperands()) {
192 if (isa<BlockArgument>(value))
193 value = rewriter.getRemappedValue(value);
195 if (region->isAncestor(value.getParentRegion()))
197 if (
auto *defOp = value.getDefiningOp();
198 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
200 if (!alreadyObserved.insert(value).second)
203 OpBuilder::InsertionGuard g(rewriter);
204 if (
auto remapped = rewriter.getRemappedValue(value)) {
205 setInsertionPoint(remapped);
206 observeValues.push_back(probeIfSignal(remapped));
208 setInsertionPoint(value);
209 auto type = typeConverter->convertType(value.getType());
210 auto converted = typeConverter->materializeTargetConversion(
211 rewriter, loc, type, value);
212 observeValues.push_back(probeIfSignal(converted));
219 using OpConversionPattern::OpConversionPattern;
222 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
223 ConversionPatternRewriter &rewriter)
const override {
225 SmallVector<Value> observedValues;
226 if (op.getKind() == ProcedureKind::AlwaysComb ||
227 op.getKind() == ProcedureKind::AlwaysLatch) {
228 auto setInsertionPoint = [&](Value value) {
229 rewriter.setInsertionPoint(op);
231 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
232 rewriter, observedValues);
235 auto loc = op.getLoc();
236 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
241 if (op.getKind() == ProcedureKind::Initial ||
242 op.getKind() == ProcedureKind::Final) {
244 if (op.getKind() == ProcedureKind::Initial)
245 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
247 newOp = llhd::FinalOp::create(rewriter, loc);
248 auto &body = newOp->getRegion(0);
249 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
251 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
252 rewriter.setInsertionPoint(returnOp);
253 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
255 rewriter.eraseOp(op);
260 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
265 rewriter.createBlock(&newOp.getBody());
266 auto *block = &op.getBody().front();
267 cf::BranchOp::create(rewriter, loc, block);
268 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
269 newOp.getBody().end());
277 if (op.getKind() == ProcedureKind::AlwaysComb ||
278 op.getKind() == ProcedureKind::AlwaysLatch) {
279 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
280 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
281 ValueRange{}, block);
288 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
289 rewriter.setInsertionPoint(returnOp);
290 cf::BranchOp::create(rewriter, loc, block);
291 rewriter.eraseOp(returnOp);
294 rewriter.eraseOp(op);
300 using OpConversionPattern::OpConversionPattern;
303 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
304 ConversionPatternRewriter &rewriter)
const override {
338 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
344 if (op.getBody().front().empty()) {
347 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
351 auto *waitBlock = rewriter.createBlock(resumeBlock);
352 auto *checkBlock = rewriter.createBlock(resumeBlock);
354 auto loc = op.getLoc();
355 rewriter.setInsertionPoint(op);
356 cf::BranchOp::create(rewriter, loc, waitBlock);
366 SmallVector<Value> valuesBefore;
367 rewriter.setInsertionPointToEnd(waitBlock);
368 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
369 bool allDetectsAreAnyChange =
true;
371 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
372 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
373 allDetectsAreAnyChange =
false;
374 valuesBefore.push_back(detectOp.getInput());
375 rewriter.eraseOp(detectOp);
381 SmallVector<Value> observeValues;
382 auto setInsertionPointAfterDef = [&](Value value) {
383 if (
auto *op = value.getDefiningOp())
384 rewriter.setInsertionPointAfter(op);
385 if (
auto arg = dyn_cast<BlockArgument>(value))
386 rewriter.setInsertionPointToStart(value.getParentBlock());
389 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
390 typeConverter, rewriter, observeValues);
395 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
396 observeValues, ValueRange{}, checkBlock);
397 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
398 rewriter.eraseOp(clonedOp);
402 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
403 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
405 rewriter.eraseOp(op);
409 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
410 assert(before.getType() == after.getType() &&
411 "mismatched types after clone op");
412 auto beforeType = cast<IntType>(before.getType());
416 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
417 constexpr int LSB = 0;
419 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
421 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
422 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
425 auto intType = rewriter.getIntegerType(beforeType.getWidth());
426 before = typeConverter->materializeTargetConversion(rewriter, loc,
428 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
431 if (edge == Edge::AnyChange)
432 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
435 SmallVector<Value> disjuncts;
438 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
440 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
442 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
443 disjuncts.push_back(posedge);
446 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
448 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
450 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
451 disjuncts.push_back(posedge);
454 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
461 SmallVector<Value> triggers;
462 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
463 if (!allDetectsAreAnyChange) {
464 if (!isa<IntType>(before.getType()))
465 return detectOp->emitError() <<
"requires int operand";
467 rewriter.setInsertionPoint(detectOp);
469 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
470 if (detectOp.getCondition()) {
471 auto condition = typeConverter->materializeTargetConversion(
472 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
474 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
476 triggers.push_back(trigger);
479 rewriter.eraseOp(detectOp);
482 rewriter.setInsertionPointToEnd(checkBlock);
483 if (triggers.empty()) {
488 cf::BranchOp::create(rewriter, loc, resumeBlock);
494 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
495 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
504static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
505 ConversionPatternRewriter &rewriter) {
507 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
508 rewriter.setInsertionPoint(op);
509 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
510 adaptor.getDelay(), ValueRange{},
511 ValueRange{}, resumeBlock);
512 rewriter.setInsertionPointToStart(resumeBlock);
517static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
518 ConversionPatternRewriter &rewriter) {
519 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
528 ConversionPatternRewriter &rewriter) {
530 if (isa<mlir::LLVM::LLVMPointerType>(type))
531 return mlir::LLVM::ZeroOp::create(rewriter, loc, type);
534 if (isa<llhd::TimeType>(type)) {
536 llhd::TimeAttr::get(type.getContext(), 0U, llvm::StringRef(
"ns"), 0, 0);
537 return llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
541 if (
auto floatType = dyn_cast<FloatType>(type)) {
542 auto floatAttr = rewriter.getFloatAttr(floatType, 0.0);
543 return mlir::arith::ConstantOp::create(rewriter, loc, floatAttr);
547 int64_t width = hw::getBitWidth(type);
555 return rewriter.createOrFold<
hw::BitcastOp>(loc, type, constZero);
559 using OpConversionPattern::OpConversionPattern;
562 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
563 ConversionPatternRewriter &rewriter)
const override {
564 auto loc = op.getLoc();
565 auto resultType = typeConverter->convertType(op.getResult().getType());
567 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
570 Value init = adaptor.getInitial();
572 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
578 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
579 op.getNameAttr(), init);
585 using OpConversionPattern::OpConversionPattern;
588 matchAndRewrite(NetOp op, OpAdaptor adaptor,
589 ConversionPatternRewriter &rewriter)
const override {
590 auto loc = op.getLoc();
591 if (op.getKind() != NetKind::Wire)
592 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
594 auto resultType = typeConverter->convertType(op.getResult().getType());
596 return rewriter.notifyMatchFailure(loc,
"invalid net type");
600 auto elementType = cast<llhd::RefType>(resultType).getNestedType();
608 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
609 op, resultType, op.getNameAttr(), init);
611 if (
auto assignedValue = adaptor.getAssignment()) {
612 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
613 llvm::StringRef(
"ns"), 0, 1);
614 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
615 llhd::DriveOp::create(rewriter, loc, signal, assignedValue, time,
628 using OpConversionPattern::OpConversionPattern;
631 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
632 ConversionPatternRewriter &rewriter)
const override {
634 auto value = op.getValue().toAPInt(
false);
635 auto type = rewriter.getIntegerType(value.getBitWidth());
637 op, type, rewriter.getIntegerAttr(type, value));
643 using OpConversionPattern::OpConversionPattern;
646 matchAndRewrite(ConstantRealOp op, OpAdaptor adaptor,
647 ConversionPatternRewriter &rewriter)
const override {
648 rewriter.replaceOpWithNewOp<arith::ConstantOp>(op, op.getValueAttr());
654 using OpConversionPattern::OpConversionPattern;
657 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
658 ConversionPatternRewriter &rewriter)
const override {
659 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
660 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
661 StringRef(
"fs"), 0, 0));
667 using OpConversionPattern::OpConversionPattern;
669 matchAndRewrite(moore::ConstantStringOp op, OpAdaptor adaptor,
670 ConversionPatternRewriter &rewriter)
const override {
671 const auto resultType =
672 typeConverter->convertType(op.getResult().getType());
673 const auto intType = mlir::cast<IntegerType>(resultType);
675 const auto str = op.getValue();
676 const unsigned byteWidth = intType.getWidth();
677 APInt value(byteWidth, 0);
680 const size_t maxChars =
681 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
682 for (
size_t i = 0; i < maxChars; i++) {
683 const size_t pos = str.size() - 1 - i;
684 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
685 value |= APInt(byteWidth, asciiChar) << (8 * i);
689 op, resultType, rewriter.getIntegerAttr(resultType, value));
695 using OpConversionPattern::OpConversionPattern;
697 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
698 ConversionPatternRewriter &rewriter)
const override {
699 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
705 using OpConversionPattern::OpConversionPattern;
707 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
708 ConversionPatternRewriter &rewriter)
const override {
709 Type resultType = typeConverter->convertType(op.getResult().getType());
711 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
718 using OpConversionPattern::OpConversionPattern;
721 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
722 ConversionPatternRewriter &rewriter)
const override {
725 Type resultType = typeConverter->convertType(op.getResult().getType());
726 Type inputType = adaptor.getInput().getType();
727 int32_t low = adaptor.getLowBit();
729 if (isa<IntegerType>(inputType)) {
730 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
731 int32_t resultWidth = hw::getBitWidth(resultType);
732 int32_t high = low + resultWidth;
734 SmallVector<Value> toConcat;
737 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
739 if (low < inputWidth && high > 0) {
740 int32_t lowIdx = std::max(low, 0);
743 rewriter.getIntegerType(
744 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
745 adaptor.getInput(), lowIdx);
746 toConcat.push_back(middle);
749 int32_t diff = high - inputWidth;
753 toConcat.push_back(val);
758 rewriter.replaceOp(op,
concat);
762 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
763 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
764 int32_t inputWidth = arrTy.getNumElements();
766 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType);
767 resArrTy && resArrTy != arrTy.getElementType()) {
768 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
769 if (elementWidth < 0)
772 int32_t high = low + resArrTy.getNumElements();
773 int32_t resWidth = resArrTy.getNumElements();
775 SmallVector<Value> toConcat;
778 rewriter, op.getLoc(),
779 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
782 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
784 toConcat.push_back(res);
787 if (low < inputWidth && high > 0) {
788 int32_t lowIdx = std::max(0, low);
790 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
794 arrTy.getElementType(),
795 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
796 adaptor.getInput(), lowIdxVal);
797 toConcat.push_back(middle);
800 int32_t diff = high - inputWidth;
803 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
805 rewriter, op.getLoc(),
806 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
807 toConcat.push_back(val);
812 rewriter.replaceOp(op,
concat);
817 if (low < 0 || low >= inputWidth) {
818 int32_t bw = hw::getBitWidth(resultType);
824 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
825 rewriter.replaceOp(op, bitcast);
830 rewriter.getIntegerType(width),
831 adaptor.getLowBit());
832 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
841 using OpConversionPattern::OpConversionPattern;
844 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
845 ConversionPatternRewriter &rewriter)
const override {
847 Type resultType = typeConverter->convertType(op.getResult().getType());
849 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
851 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
852 int64_t width = hw::getBitWidth(inputType);
857 rewriter, op.getLoc(),
858 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
859 adaptor.getLowBit());
860 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
861 op, resultType, adaptor.getInput(), lowBit);
865 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
867 rewriter, op.getLoc(),
868 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
869 adaptor.getLowBit());
873 if (arrType.getElementType() !=
874 cast<llhd::RefType>(resultType).getNestedType()) {
875 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
876 op, resultType, adaptor.getInput(), lowBit);
880 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
890 using OpConversionPattern::OpConversionPattern;
893 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
894 ConversionPatternRewriter &rewriter)
const override {
895 Type resultType = typeConverter->convertType(op.getResult().getType());
896 Type inputType = adaptor.getInput().getType();
898 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
899 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
900 intType.getWidth(), op->getLoc());
901 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
902 adaptor.getInput(), amount);
904 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
908 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
909 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
910 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
913 if (isa<hw::ArrayType>(resultType)) {
915 adaptor.getInput(), idx);
919 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
928 using OpConversionPattern::OpConversionPattern;
931 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
932 ConversionPatternRewriter &rewriter)
const override {
934 Type resultType = typeConverter->convertType(op.getResult().getType());
936 cast<llhd::RefType>(adaptor.getInput().getType()).getNestedType();
938 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
939 int64_t width = hw::getBitWidth(inputType);
944 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
945 llvm::Log2_64_Ceil(width), op->getLoc());
946 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
947 op, resultType, adaptor.getInput(), amount);
951 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
952 Value idx = adjustIntegerWidth(
953 rewriter, adaptor.getLowBit(),
954 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
956 if (isa<hw::ArrayType>(cast<llhd::RefType>(resultType).getNestedType())) {
957 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
958 op, resultType, adaptor.getInput(), idx);
962 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
972 using OpConversionPattern::OpConversionPattern;
975 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
976 ConversionPatternRewriter &rewriter)
const override {
977 Type resultType = typeConverter->convertType(op.getResult().getType());
979 adaptor.getElements());
985 using OpConversionPattern::OpConversionPattern;
988 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
989 ConversionPatternRewriter &rewriter)
const override {
990 Type resultType = typeConverter->convertType(op.getResult().getType());
992 adaptor.getFields());
998 using OpConversionPattern::OpConversionPattern;
1001 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
1002 ConversionPatternRewriter &rewriter)
const override {
1004 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1009struct StructExtractRefOpConversion
1011 using OpConversionPattern::OpConversionPattern;
1014 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
1015 ConversionPatternRewriter &rewriter)
const override {
1016 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
1017 op, adaptor.getInput(), adaptor.getFieldNameAttr());
1023 using OpConversionPattern::OpConversionPattern;
1025 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
1026 ConversionPatternRewriter &rewriter)
const override {
1027 Type resultType = typeConverter->convertType(op.getInput().getType());
1030 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
1031 adaptor.getInput(), max);
1037 using OpConversionPattern::OpConversionPattern;
1039 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1040 ConversionPatternRewriter &rewriter)
const override {
1041 Type resultType = typeConverter->convertType(op.getInput().getType());
1044 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1045 adaptor.getInput(), zero);
1051 using OpConversionPattern::OpConversionPattern;
1053 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1054 ConversionPatternRewriter &rewriter)
const override {
1056 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1062 using OpConversionPattern::OpConversionPattern;
1064 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1065 ConversionPatternRewriter &rewriter)
const override {
1066 Type resultType = typeConverter->convertType(op.getInput().getType());
1067 if (isa_and_nonnull<IntegerType>(resultType)) {
1070 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1071 adaptor.getInput(), zero);
1079 using OpConversionPattern::OpConversionPattern;
1081 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1082 ConversionPatternRewriter &rewriter)
const override {
1084 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1087 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1093 using OpConversionPattern::OpConversionPattern;
1095 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1096 ConversionPatternRewriter &rewriter)
const override {
1098 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1101 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1106template <
typename SourceOp,
typename TargetOp>
1109 using OpAdaptor =
typename SourceOp::Adaptor;
1112 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1113 ConversionPatternRewriter &rewriter)
const override {
1114 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1115 adaptor.getRhs(),
false);
1120template <
typename SourceOp, ICmpPredicate pred>
1123 using OpAdaptor =
typename SourceOp::Adaptor;
1126 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1127 ConversionPatternRewriter &rewriter)
const override {
1129 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1131 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1132 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1137template <
typename SourceOp,
bool withoutX>
1140 using OpAdaptor =
typename SourceOp::Adaptor;
1143 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1144 ConversionPatternRewriter &rewriter)
const override {
1150 unsigned bitWidth = op.getLhs().getType().getWidth();
1151 auto ignoredBits = APInt::getZero(bitWidth);
1152 auto detectIgnoredBits = [&](Value value) {
1153 auto constOp = value.getDefiningOp<ConstantOp>();
1156 auto constValue = constOp.getValue();
1158 ignoredBits |= constValue.getZBits();
1160 ignoredBits |= constValue.getUnknownBits();
1162 detectIgnoredBits(op.getLhs());
1163 detectIgnoredBits(op.getRhs());
1167 Value lhs = adaptor.getLhs();
1168 Value rhs = adaptor.getRhs();
1169 if (!ignoredBits.isZero()) {
1170 ignoredBits.flipAllBits();
1172 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1173 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1176 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1186 using OpConversionPattern::OpConversionPattern;
1189 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1190 ConversionPatternRewriter &rewriter)
const override {
1191 Location loc = op.getLoc();
1192 Type resultType = typeConverter->convertType(op.getResult().getType());
1193 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1194 int64_t resultBw = hw::getBitWidth(resultType);
1195 if (inputBw == -1 || resultBw == -1)
1199 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1200 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1203 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1204 rewriter.replaceOp(op, result);
1209template <
typename SourceOp>
1212 using OpAdaptor =
typename SourceOp::Adaptor;
1213 using ConversionPattern::typeConverter;
1216 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1217 ConversionPatternRewriter &rewriter)
const override {
1218 auto type = typeConverter->convertType(op.getResult().getType());
1219 if (type == adaptor.getInput().getType())
1220 rewriter.replaceOp(op, adaptor.getInput());
1222 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1228 using OpConversionPattern::OpConversionPattern;
1231 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1232 ConversionPatternRewriter &rewriter)
const override {
1233 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1234 op.getType().getWidth());
1240 using OpConversionPattern::OpConversionPattern;
1243 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1244 ConversionPatternRewriter &rewriter)
const override {
1245 auto targetWidth = op.getType().getWidth();
1246 auto inputWidth = op.getInput().getType().getWidth();
1249 rewriter, op.getLoc(),
1250 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1253 op, ValueRange{zeroExt, adaptor.getInput()});
1259 using OpConversionPattern::OpConversionPattern;
1262 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1263 ConversionPatternRewriter &rewriter)
const override {
1264 auto type = typeConverter->convertType(op.getType());
1266 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1267 rewriter.replaceOp(op, value);
1277 using OpConversionPattern::OpConversionPattern;
1280 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1281 ConversionPatternRewriter &rewriter)
const override {
1282 SmallVector<Type> convResTypes;
1283 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1286 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1287 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1288 adaptor.getOperands(), op.getArgNames(),
1289 op.getResultNames(),
1290 rewriter.getArrayAttr({}),
nullptr);
1297 using OpConversionPattern::OpConversionPattern;
1300 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1301 ConversionPatternRewriter &rewriter)
const override {
1302 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1308 using OpConversionPattern::OpConversionPattern;
1311 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1312 ConversionPatternRewriter &rewriter)
const override {
1313 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1314 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1315 adaptor.getFalseDestOperands(),
nullptr,
1316 op.getTrueDest(), op.getFalseDest());
1322 using OpConversionPattern::OpConversionPattern;
1325 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1326 ConversionPatternRewriter &rewriter)
const override {
1327 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1328 adaptor.getDestOperands());
1334 using OpConversionPattern::OpConversionPattern;
1337 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1338 ConversionPatternRewriter &rewriter)
const override {
1339 SmallVector<Type> convResTypes;
1340 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1342 rewriter.replaceOpWithNewOp<func::CallOp>(
1343 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1348struct UnrealizedConversionCastConversion
1350 using OpConversionPattern::OpConversionPattern;
1353 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1354 ConversionPatternRewriter &rewriter)
const override {
1355 SmallVector<Type> convResTypes;
1356 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1361 if (convResTypes == adaptor.getOperands().getTypes()) {
1362 rewriter.replaceOp(op, adaptor.getOperands());
1366 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1367 op, convResTypes, adaptor.getOperands());
1373 using OpConversionPattern::OpConversionPattern;
1376 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1377 ConversionPatternRewriter &rewriter)
const override {
1378 Type resultType = typeConverter->convertType(op.getResult().getType());
1382 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1383 resultType.getIntOrFloatBitWidth(), op->getLoc());
1384 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1391 using OpConversionPattern::OpConversionPattern;
1394 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1395 ConversionPatternRewriter &rewriter)
const override {
1396 Type resultType = typeConverter->convertType(op.getResult().getType());
1400 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1401 resultType.getIntOrFloatBitWidth(), op->getLoc());
1403 op, resultType, adaptor.getValue(), amount,
false);
1409 using OpConversionPattern::OpConversionPattern;
1412 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1413 ConversionPatternRewriter &rewriter)
const override {
1414 Type resultType = typeConverter->convertType(op.getResult().getType());
1416 Location loc = op->getLoc();
1421 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1422 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1425 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1433 using OpConversionPattern::OpConversionPattern;
1436 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1437 ConversionPatternRewriter &rewriter)
const override {
1438 Type resultType = typeConverter->convertType(op.getResult().getType());
1442 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1443 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1449 using OpConversionPattern::OpConversionPattern;
1452 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1453 ConversionPatternRewriter &rewriter)
const override {
1454 Type resultType = typeConverter->convertType(op.getResult().getType());
1458 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1459 resultType.getIntOrFloatBitWidth(), op->getLoc());
1461 op, resultType, adaptor.getValue(), amount,
false);
1467 using OpConversionPattern::OpConversionPattern;
1470 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1471 ConversionPatternRewriter &rewriter)
const override {
1472 rewriter.replaceOpWithNewOp<llhd::ProbeOp>(op, adaptor.getInput());
1477struct AssignedVariableOpConversion
1479 using OpConversionPattern::OpConversionPattern;
1482 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1483 ConversionPatternRewriter &rewriter)
const override {
1484 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1485 adaptor.getNameAttr());
1490template <
typename OpTy>
1493 using OpAdaptor =
typename OpTy::Adaptor;
1496 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1497 ConversionPatternRewriter &rewriter)
const override {
1500 if constexpr (std::is_same_v<OpTy, ContinuousAssignOp> ||
1501 std::is_same_v<OpTy, BlockingAssignOp>) {
1503 delay = llhd::ConstantTimeOp::create(
1504 rewriter, op->getLoc(),
1505 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 0, 1));
1506 }
else if constexpr (std::is_same_v<OpTy, NonBlockingAssignOp>) {
1508 delay = llhd::ConstantTimeOp::create(
1509 rewriter, op->getLoc(),
1510 llhd::TimeAttr::get(op->getContext(), 0U,
"ns", 1, 0));
1513 delay = adaptor.getDelay();
1516 rewriter.replaceOpWithNewOp<llhd::DriveOp>(
1517 op, adaptor.getDst(), adaptor.getSrc(), delay, Value{});
1523 using OpConversionPattern::OpConversionPattern;
1526 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1527 ConversionPatternRewriter &rewriter)
const override {
1532 auto type = typeConverter->convertType(op.getType());
1534 auto hasNoWriteEffect = [](Region ®ion) {
1535 auto result = region.walk([](Operation *operation) {
1536 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1537 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1538 !memOp.hasEffect<MemoryEffects::Free>())
1539 return WalkResult::advance();
1541 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1542 return WalkResult::advance();
1544 return WalkResult::interrupt();
1546 return !result.wasInterrupted();
1549 if (hasNoWriteEffect(op.getTrueRegion()) &&
1550 hasNoWriteEffect(op.getFalseRegion())) {
1551 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1552 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1554 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1555 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1557 Value convTrueVal = typeConverter->materializeTargetConversion(
1558 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1559 Value convFalseVal = typeConverter->materializeTargetConversion(
1560 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1562 rewriter.eraseOp(trueTerm);
1563 rewriter.eraseOp(falseTerm);
1565 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1566 convTrueVal, convFalseVal);
1571 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1572 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1573 ifOp.getThenRegion().end());
1574 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1575 ifOp.getElseRegion().end());
1576 rewriter.replaceOp(op, ifOp);
1582 using OpConversionPattern::OpConversionPattern;
1585 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1586 ConversionPatternRewriter &rewriter)
const override {
1587 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1592template <
typename SourceOp>
1595 using OpAdaptor =
typename SourceOp::Adaptor;
1598 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1599 ConversionPatternRewriter &rewriter)
const override {
1600 rewriter.modifyOpInPlace(op,
1601 [&]() { op->setOperands(adaptor.getOperands()); });
1606template <
typename MooreOpTy,
typename VerifOpTy>
1609 using OpAdaptor =
typename MooreOpTy::Adaptor;
1612 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1613 ConversionPatternRewriter &rewriter)
const override {
1615 op.getLabel().has_value()
1616 ? StringAttr::get(op->getContext(), op.getLabel().value())
1617 : StringAttr::
get(op->getContext());
1618 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1629 using OpConversionPattern::OpConversionPattern;
1632 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1633 ConversionPatternRewriter &rewriter)
const override {
1634 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
1640 using OpConversionPattern::OpConversionPattern;
1643 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1644 ConversionPatternRewriter &rewriter)
const override {
1645 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1646 adaptor.getInputs());
1652 using OpConversionPattern::OpConversionPattern;
1655 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1656 ConversionPatternRewriter &rewriter)
const override {
1658 switch (op.getFormat()) {
1659 case IntFormat::Decimal:
1660 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1662 case IntFormat::Binary:
1663 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1665 case IntFormat::HexLower:
1666 case IntFormat::HexUpper:
1667 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1670 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1676 using OpConversionPattern::OpConversionPattern;
1679 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1680 ConversionPatternRewriter &rewriter)
const override {
1681 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1682 op, adaptor.getMessage());
1694static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
1695 ConversionPatternRewriter &rewriter) {
1696 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
1701static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
1702 ConversionPatternRewriter &rewriter) {
1703 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
1709static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
1710 ConversionPatternRewriter &rewriter) {
1712 std::string severityString;
1714 switch (op.getSeverity()) {
1715 case (Severity::Fatal):
1716 severityString =
"Fatal: ";
1718 case (Severity::Error):
1719 severityString =
"Error: ";
1721 case (Severity::Warning):
1722 severityString =
"Warning: ";
1729 sim::FormatLiteralOp::create(rewriter, op.getLoc(), severityString);
1730 auto message = sim::FormatStringConcatOp::create(
1731 rewriter, op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
1732 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
1738 FinishMessageBIOp::Adaptor adaptor,
1739 ConversionPatternRewriter &rewriter) {
1741 rewriter.eraseOp(op);
1750 const TypeConverter &converter) {
1751 target.addIllegalDialect<MooreDialect>();
1752 target.addLegalDialect<comb::CombDialect>();
1753 target.addLegalDialect<hw::HWDialect>();
1754 target.addLegalDialect<seq::SeqDialect>();
1755 target.addLegalDialect<llhd::LLHDDialect>();
1756 target.addLegalDialect<ltl::LTLDialect>();
1757 target.addLegalDialect<mlir::BuiltinDialect>();
1758 target.addLegalDialect<mlir::math::MathDialect>();
1759 target.addLegalDialect<sim::SimDialect>();
1760 target.addLegalDialect<mlir::LLVM::LLVMDialect>();
1761 target.addLegalDialect<verif::VerifDialect>();
1762 target.addLegalDialect<arith::ArithDialect>();
1764 target.addLegalOp<debug::ScopeOp>();
1766 target.addDynamicallyLegalOp<
1767 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1768 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1769 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1770 [&](Operation *op) {
return converter.isLegal(op); });
1772 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1773 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1774 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1777 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1778 return converter.isSignatureLegal(op.getFunctionType()) &&
1779 converter.isLegal(&op.getFunctionBody());
1783 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1784 converter.isLegal(&op.getBody());
1789 typeConverter.addConversion([&](IntType type) {
1790 return IntegerType::get(type.getContext(), type.getWidth());
1793 typeConverter.addConversion([&](RealType type) -> mlir::Type {
1794 MLIRContext *ctx = type.getContext();
1795 switch (type.getWidth()) {
1796 case moore::RealWidth::f32:
1797 return mlir::Float32Type::get(ctx);
1798 case moore::RealWidth::f64:
1799 return mlir::Float64Type::get(ctx);
1803 typeConverter.addConversion(
1804 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
1806 typeConverter.addConversion([&](FormatStringType type) {
1807 return sim::FormatStringType::get(type.getContext());
1810 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1811 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1812 return hw::ArrayType::get(
elementType, type.getSize());
1819 typeConverter.addConversion(
1820 [&](UnpackedArrayType type) -> std::optional<Type> {
1821 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1822 return hw::ArrayType::get(
elementType, type.getSize());
1826 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1827 SmallVector<hw::StructType::FieldInfo> fields;
1828 for (
auto field : type.getMembers()) {
1829 hw::StructType::FieldInfo info;
1830 info.type = typeConverter.convertType(field.type);
1833 info.name = field.name;
1834 fields.push_back(info);
1836 return hw::StructType::get(type.getContext(), fields);
1844 typeConverter.addConversion(
1845 [&](UnpackedStructType type) -> std::optional<Type> {
1846 SmallVector<hw::StructType::FieldInfo> fields;
1847 for (
auto field : type.getMembers()) {
1848 hw::StructType::FieldInfo info;
1849 info.type = typeConverter.convertType(field.type);
1852 info.name = field.name;
1853 fields.push_back(info);
1855 return hw::StructType::get(type.getContext(), fields);
1859 typeConverter.addConversion([&](ChandleType type) -> std::optional<Type> {
1860 return LLVM::LLVMPointerType::get(type.getContext());
1864 typeConverter.addConversion(
1865 [](LLVM::LLVMPointerType t) -> std::optional<Type> {
return t; });
1867 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1868 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1869 return llhd::RefType::get(innerType);
1874 typeConverter.addConversion([](IntegerType type) {
return type; });
1875 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
1876 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1877 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1878 typeConverter.addConversion([](debug::StructType type) {
return type; });
1880 typeConverter.addConversion([&](llhd::RefType type) -> std::optional<Type> {
1881 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1882 return llhd::RefType::get(innerType);
1886 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1887 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1888 return hw::ArrayType::get(
elementType, type.getNumElements());
1892 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1893 SmallVector<hw::StructType::FieldInfo> fields;
1894 for (
auto field : type.getElements()) {
1895 hw::StructType::FieldInfo info;
1896 info.type = typeConverter.convertType(field.type);
1899 info.name = field.name;
1900 fields.push_back(info);
1902 return hw::StructType::get(type.getContext(), fields);
1905 typeConverter.addTargetMaterialization(
1906 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1907 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1908 if (inputs.size() != 1 || !inputs[0])
1910 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1915 typeConverter.addSourceMaterialization(
1916 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1917 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1918 if (inputs.size() != 1)
1920 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1927 TypeConverter &typeConverter) {
1931 VariableOpConversion,
1935 ConversionOpConversion,
1936 BitcastConversion<PackedToSBVOp>,
1937 BitcastConversion<SBVToPackedOp>,
1938 BitcastConversion<LogicToIntOp>,
1939 BitcastConversion<IntToLogicOp>,
1940 BitcastConversion<ToBuiltinBoolOp>,
1949 ReplicateOpConversion,
1951 ExtractOpConversion,
1952 DynExtractOpConversion,
1953 DynExtractRefOpConversion,
1955 StructExtractOpConversion,
1956 StructExtractRefOpConversion,
1957 ExtractRefOpConversion,
1958 StructCreateOpConversion,
1959 ConditionalOpConversion,
1960 ArrayCreateOpConversion,
1963 ConstantStringOpConv,
1966 ReduceAndOpConversion,
1967 ReduceOrOpConversion,
1968 ReduceXorOpConversion,
1969 BoolCastOpConversion,
1974 BinaryOpConversion<AddOp, comb::AddOp>,
1975 BinaryOpConversion<SubOp, comb::SubOp>,
1976 BinaryOpConversion<MulOp, comb::MulOp>,
1977 BinaryOpConversion<DivUOp, comb::DivUOp>,
1978 BinaryOpConversion<DivSOp, comb::DivSOp>,
1979 BinaryOpConversion<ModUOp, comb::ModUOp>,
1980 BinaryOpConversion<ModSOp, comb::ModSOp>,
1981 BinaryOpConversion<AndOp, comb::AndOp>,
1982 BinaryOpConversion<OrOp, comb::OrOp>,
1983 BinaryOpConversion<XorOp, comb::XorOp>,
1986 PowUOpConversion, PowSOpConversion,
1989 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1990 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1991 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1992 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1993 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1994 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1995 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1996 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1997 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1998 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1999 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
2000 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
2001 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
2002 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
2003 CaseXZEqOpConversion<CaseZEqOp, true>,
2004 CaseXZEqOpConversion<CaseXZEqOp, false>,
2007 SVModuleOpConversion,
2008 InstanceOpConversion,
2009 ProcedureOpConversion,
2010 WaitEventOpConversion,
2018 AssignOpConversion<ContinuousAssignOp>,
2019 AssignOpConversion<DelayedContinuousAssignOp>,
2020 AssignOpConversion<BlockingAssignOp>,
2021 AssignOpConversion<NonBlockingAssignOp>,
2022 AssignOpConversion<DelayedNonBlockingAssignOp>,
2023 AssignedVariableOpConversion,
2026 CondBranchOpConversion,
2030 HWInstanceOpConversion,
2033 UnrealizedConversionCastConversion,
2034 InPlaceOpConversion<debug::ArrayOp>,
2035 InPlaceOpConversion<debug::StructOp>,
2036 InPlaceOpConversion<debug::VariableOp>,
2039 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
2040 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
2041 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
2044 FormatLiteralOpConversion,
2045 FormatConcatOpConversion,
2046 FormatIntOpConversion,
2047 DisplayBIOpConversion
2048 >(typeConverter,
patterns.getContext());
2061 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
2063 hw::populateHWModuleLikeTypeConversionPattern(
2064 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
2065 populateSCFToControlFlowConversionPatterns(
patterns);
2074struct MooreToCorePass
2075 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
2076 void runOnOperation()
override;
2082 return std::make_unique<MooreToCorePass>();
2086void MooreToCorePass::runOnOperation() {
2087 MLIRContext &context = getContext();
2088 ModuleOp
module = getOperation();
2090 IRRewriter rewriter(module);
2091 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
2093 TypeConverter typeConverter;
2096 ConversionTarget target(context);
2102 if (failed(applyFullConversion(module, target, std::move(
patterns))))
2103 signalPassFailure();
assert(baseType &&"element must be base type")
static SmallVector< T > concat(const SmallVectorImpl< T > &a, const SmallVectorImpl< T > &b)
Returns a new vector containing the concatenation of vectors a and b.
static Value createZeroValue(ImplicitLocOpBuilder &builder, FIRRTLBaseType type, SmallDenseMap< FIRRTLBaseType, Value > &cache)
Construct a zero value of the given type using the given builder.
static void populateOpConversion(ConversionPatternSet &patterns, TypeConverter &typeConverter)
static LogicalResult convert(StopBIOp op, StopBIOp::Adaptor adaptor, ConversionPatternRewriter &rewriter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
Extension of RewritePatternSet that allows adding matchAndRewrite functions with op adaptors and Conv...
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateArithToCombPatterns(mlir::RewritePatternSet &patterns, TypeConverter &typeConverter)
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.
This holds a decoded list of input/inout and output ports for a module or instance.
This holds the name, type, direction of a module's ports.