24#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
25#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
26#include "mlir/Dialect/Func/IR/FuncOps.h"
27#include "mlir/Dialect/Math/IR/Math.h"
28#include "mlir/Dialect/SCF/IR/SCF.h"
29#include "mlir/IR/BuiltinDialect.h"
30#include "mlir/IR/Iterators.h"
31#include "mlir/Interfaces/SideEffectInterfaces.h"
32#include "mlir/Pass/Pass.h"
33#include "mlir/Transforms/DialectConversion.h"
34#include "mlir/Transforms/RegionUtils.h"
35#include "llvm/ADT/TypeSwitch.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 (
auto ioTy = dyn_cast_or_null<hw::InOutType>(portTy)) {
98 if (port.dir == hw::ModulePort::Direction::Output) {
100 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
108 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
120 using OpConversionPattern::OpConversionPattern;
123 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
124 ConversionPatternRewriter &rewriter)
const override {
125 rewriter.setInsertionPoint(op);
129 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getSymNameAttr(),
130 getModulePortInfo(*typeConverter, op));
133 SymbolTable::setSymbolVisibility(hwModuleOp,
134 SymbolTable::getSymbolVisibility(op));
135 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
137 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
139 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
140 hwModuleOp.getBodyRegion().end());
143 rewriter.eraseOp(op);
149 using OpConversionPattern::OpConversionPattern;
152 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
153 ConversionPatternRewriter &rewriter)
const override {
154 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
160 using OpConversionPattern::OpConversionPattern;
163 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
164 ConversionPatternRewriter &rewriter)
const override {
165 auto instName = op.getInstanceNameAttr();
166 auto moduleName = op.getModuleNameAttr();
169 rewriter.setInsertionPoint(op);
170 auto instOp = hw::InstanceOp::create(
171 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
172 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
173 rewriter.getArrayAttr({}),
nullptr,
177 op.replaceAllUsesWith(instOp.getResults());
178 rewriter.eraseOp(op);
183static void getValuesToObserve(Region *region,
184 function_ref<
void(Value)> setInsertionPoint,
185 const TypeConverter *typeConverter,
186 ConversionPatternRewriter &rewriter,
187 SmallVector<Value> &observeValues) {
188 SmallDenseSet<Value> alreadyObserved;
189 Location loc = region->getLoc();
191 auto probeIfSignal = [&](Value value) -> Value {
192 if (!isa<hw::InOutType>(value.getType()))
194 return llhd::PrbOp::create(rewriter, loc, value);
197 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
198 [&](Operation *operation) {
199 for (
auto value : operation->getOperands()) {
200 if (isa<BlockArgument>(value))
201 value = rewriter.getRemappedValue(value);
203 if (region->isAncestor(value.getParentRegion()))
205 if (
auto *defOp = value.getDefiningOp();
206 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
208 if (!alreadyObserved.insert(value).second)
211 OpBuilder::InsertionGuard g(rewriter);
212 if (
auto remapped = rewriter.getRemappedValue(value)) {
213 setInsertionPoint(remapped);
214 observeValues.push_back(probeIfSignal(remapped));
216 setInsertionPoint(value);
217 auto type = typeConverter->convertType(value.getType());
218 auto converted = typeConverter->materializeTargetConversion(
219 rewriter, loc, type, value);
220 observeValues.push_back(probeIfSignal(converted));
227 using OpConversionPattern::OpConversionPattern;
230 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
231 ConversionPatternRewriter &rewriter)
const override {
233 SmallVector<Value> observedValues;
234 if (op.getKind() == ProcedureKind::AlwaysComb ||
235 op.getKind() == ProcedureKind::AlwaysLatch) {
236 auto setInsertionPoint = [&](Value value) {
237 rewriter.setInsertionPoint(op);
239 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
240 rewriter, observedValues);
243 auto loc = op.getLoc();
244 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
249 if (op.getKind() == ProcedureKind::Initial ||
250 op.getKind() == ProcedureKind::Final) {
252 if (op.getKind() == ProcedureKind::Initial)
253 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
255 newOp = llhd::FinalOp::create(rewriter, loc);
256 auto &body = newOp->getRegion(0);
257 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
259 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
260 rewriter.setInsertionPoint(returnOp);
261 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
263 rewriter.eraseOp(op);
268 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
273 rewriter.createBlock(&newOp.getBody());
274 auto *block = &op.getBody().front();
275 cf::BranchOp::create(rewriter, loc, block);
276 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
277 newOp.getBody().end());
285 if (op.getKind() == ProcedureKind::AlwaysComb ||
286 op.getKind() == ProcedureKind::AlwaysLatch) {
287 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
288 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
289 ValueRange{}, block);
296 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
297 rewriter.setInsertionPoint(returnOp);
298 cf::BranchOp::create(rewriter, loc, block);
299 rewriter.eraseOp(returnOp);
302 rewriter.eraseOp(op);
308 using OpConversionPattern::OpConversionPattern;
311 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
312 ConversionPatternRewriter &rewriter)
const override {
346 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
352 if (op.getBody().front().empty()) {
355 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
359 auto *waitBlock = rewriter.createBlock(resumeBlock);
360 auto *checkBlock = rewriter.createBlock(resumeBlock);
362 auto loc = op.getLoc();
363 rewriter.setInsertionPoint(op);
364 cf::BranchOp::create(rewriter, loc, waitBlock);
374 SmallVector<Value> valuesBefore;
375 rewriter.setInsertionPointToEnd(waitBlock);
376 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
377 bool allDetectsAreAnyChange =
true;
379 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
380 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
381 allDetectsAreAnyChange =
false;
382 valuesBefore.push_back(detectOp.getInput());
383 rewriter.eraseOp(detectOp);
389 SmallVector<Value> observeValues;
390 auto setInsertionPointAfterDef = [&](Value value) {
391 if (
auto *op = value.getDefiningOp())
392 rewriter.setInsertionPointAfter(op);
393 if (
auto arg = dyn_cast<BlockArgument>(value))
394 rewriter.setInsertionPointToStart(value.getParentBlock());
397 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
398 typeConverter, rewriter, observeValues);
403 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
404 observeValues, ValueRange{}, checkBlock);
405 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
406 rewriter.eraseOp(clonedOp);
410 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
411 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
413 rewriter.eraseOp(op);
417 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
418 assert(before.getType() == after.getType() &&
419 "mismatched types after clone op");
420 auto beforeType = cast<IntType>(before.getType());
424 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
425 constexpr int LSB = 0;
427 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
429 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
430 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
433 auto intType = rewriter.getIntegerType(beforeType.getWidth());
434 before = typeConverter->materializeTargetConversion(rewriter, loc,
436 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
439 if (edge == Edge::AnyChange)
440 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
443 SmallVector<Value> disjuncts;
446 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
448 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
450 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
451 disjuncts.push_back(posedge);
454 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
456 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
458 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
459 disjuncts.push_back(posedge);
462 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
469 SmallVector<Value> triggers;
470 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
471 if (!allDetectsAreAnyChange) {
472 if (!isa<IntType>(before.getType()))
473 return detectOp->emitError() <<
"requires int operand";
475 rewriter.setInsertionPoint(detectOp);
477 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
478 if (detectOp.getCondition()) {
479 auto condition = typeConverter->materializeTargetConversion(
480 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
482 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
484 triggers.push_back(trigger);
487 rewriter.eraseOp(detectOp);
490 rewriter.setInsertionPointToEnd(checkBlock);
491 if (triggers.empty()) {
496 cf::BranchOp::create(rewriter, loc, resumeBlock);
502 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
503 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
516 using OpConversionPattern::OpConversionPattern;
519 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
520 ConversionPatternRewriter &rewriter)
const override {
521 Location loc = op.getLoc();
522 Type resultType = typeConverter->convertType(op.getResult().getType());
524 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
527 Value init = adaptor.getInitial();
529 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
541 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
542 op.getNameAttr(), init);
548 using OpConversionPattern::OpConversionPattern;
551 matchAndRewrite(NetOp op, OpAdaptor adaptor,
552 ConversionPatternRewriter &rewriter)
const override {
553 auto loc = op.getLoc();
554 if (op.getKind() != NetKind::Wire)
555 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
557 auto resultType = typeConverter->convertType(op.getResult().getType());
559 return rewriter.notifyMatchFailure(loc,
"invalid net type");
563 auto elementType = cast<hw::InOutType>(resultType).getElementType();
571 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
572 op, resultType, op.getNameAttr(), init);
574 if (
auto assignedValue = adaptor.getAssignment()) {
575 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
576 llvm::StringRef(
"ns"), 0, 1);
577 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
578 llhd::DrvOp::create(rewriter, loc, signal, assignedValue, time, Value{});
590 using OpConversionPattern::OpConversionPattern;
593 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
594 ConversionPatternRewriter &rewriter)
const override {
596 auto value = op.getValue().toAPInt(
false);
597 auto type = rewriter.getIntegerType(value.getBitWidth());
599 op, type, rewriter.getIntegerAttr(type, value));
605 using OpConversionPattern::OpConversionPattern;
608 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
609 ConversionPatternRewriter &rewriter)
const override {
610 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
611 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
612 StringRef(
"fs"), 0, 0));
618 using OpConversionPattern::OpConversionPattern;
620 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
621 ConversionPatternRewriter &rewriter)
const override {
622 const auto resultType =
623 typeConverter->convertType(op.getResult().getType());
624 const auto intType = mlir::cast<IntegerType>(resultType);
626 const auto str = op.getValue();
627 const unsigned byteWidth = intType.getWidth();
628 APInt value(byteWidth, 0);
631 const size_t maxChars =
632 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
633 for (
size_t i = 0; i < maxChars; i++) {
634 const size_t pos = str.size() - 1 - i;
635 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
636 value |= APInt(byteWidth, asciiChar) << (8 * i);
640 op, resultType, rewriter.getIntegerAttr(resultType, value));
646 using OpConversionPattern::OpConversionPattern;
648 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
649 ConversionPatternRewriter &rewriter)
const override {
650 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
656 using OpConversionPattern::OpConversionPattern;
658 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
659 ConversionPatternRewriter &rewriter)
const override {
660 Type resultType = typeConverter->convertType(op.getResult().getType());
662 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
669 using OpConversionPattern::OpConversionPattern;
672 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
673 ConversionPatternRewriter &rewriter)
const override {
676 Type resultType = typeConverter->convertType(op.getResult().getType());
677 Type inputType = adaptor.getInput().getType();
678 int32_t low = adaptor.getLowBit();
680 if (isa<IntegerType>(inputType)) {
681 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
682 int32_t resultWidth = hw::getBitWidth(resultType);
683 int32_t high = low + resultWidth;
685 SmallVector<Value> toConcat;
688 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
690 if (low < inputWidth && high > 0) {
691 int32_t lowIdx = std::max(low, 0);
694 rewriter.getIntegerType(
695 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
696 adaptor.getInput(), lowIdx);
697 toConcat.push_back(middle);
700 int32_t diff = high - inputWidth;
704 toConcat.push_back(val);
709 rewriter.replaceOp(op,
concat);
713 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
714 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
715 int32_t inputWidth = arrTy.getNumElements();
717 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
718 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
719 if (elementWidth < 0)
722 int32_t high = low + resArrTy.getNumElements();
723 int32_t resWidth = resArrTy.getNumElements();
725 SmallVector<Value> toConcat;
728 rewriter, op.getLoc(),
729 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
732 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
734 toConcat.push_back(res);
737 if (low < inputWidth && high > 0) {
738 int32_t lowIdx = std::max(0, low);
740 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
744 arrTy.getElementType(),
745 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
746 adaptor.getInput(), lowIdxVal);
747 toConcat.push_back(middle);
750 int32_t diff = high - inputWidth;
753 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
755 rewriter, op.getLoc(),
756 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
757 toConcat.push_back(val);
762 rewriter.replaceOp(op,
concat);
767 if (low < 0 || low >= inputWidth) {
768 int32_t bw = hw::getBitWidth(resultType);
774 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
775 rewriter.replaceOp(op, bitcast);
780 rewriter.getIntegerType(width),
781 adaptor.getLowBit());
782 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
791 using OpConversionPattern::OpConversionPattern;
794 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
795 ConversionPatternRewriter &rewriter)
const override {
797 Type resultType = typeConverter->convertType(op.getResult().getType());
799 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
801 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
802 int64_t width = hw::getBitWidth(inputType);
807 rewriter, op.getLoc(),
808 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
809 adaptor.getLowBit());
810 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
811 op, resultType, adaptor.getInput(), lowBit);
815 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
817 rewriter, op.getLoc(),
818 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
819 adaptor.getLowBit());
821 if (isa<hw::ArrayType>(
822 cast<hw::InOutType>(resultType).getElementType())) {
823 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
824 op, resultType, adaptor.getInput(), lowBit);
828 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
838 using OpConversionPattern::OpConversionPattern;
841 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
842 ConversionPatternRewriter &rewriter)
const override {
843 Type resultType = typeConverter->convertType(op.getResult().getType());
844 Type inputType = adaptor.getInput().getType();
846 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
847 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
848 intType.getWidth(), op->getLoc());
849 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
850 adaptor.getInput(), amount);
852 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
856 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
857 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
858 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
861 if (isa<hw::ArrayType>(resultType)) {
863 adaptor.getInput(), idx);
867 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
876 using OpConversionPattern::OpConversionPattern;
879 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
880 ConversionPatternRewriter &rewriter)
const override {
882 Type resultType = typeConverter->convertType(op.getResult().getType());
884 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
886 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
887 int64_t width = hw::getBitWidth(inputType);
892 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
893 llvm::Log2_64_Ceil(width), op->getLoc());
894 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
895 op, resultType, adaptor.getInput(), amount);
899 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
900 Value idx = adjustIntegerWidth(
901 rewriter, adaptor.getLowBit(),
902 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
904 if (isa<hw::ArrayType>(
905 cast<hw::InOutType>(resultType).getElementType())) {
906 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
907 op, resultType, adaptor.getInput(), idx);
911 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
921 using OpConversionPattern::OpConversionPattern;
924 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
925 ConversionPatternRewriter &rewriter)
const override {
926 Type resultType = typeConverter->convertType(op.getResult().getType());
928 adaptor.getElements());
934 using OpConversionPattern::OpConversionPattern;
937 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
938 ConversionPatternRewriter &rewriter)
const override {
939 Type resultType = typeConverter->convertType(op.getResult().getType());
941 adaptor.getFields());
947 using OpConversionPattern::OpConversionPattern;
950 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
951 ConversionPatternRewriter &rewriter)
const override {
953 op, adaptor.getInput(), adaptor.getFieldNameAttr());
958struct StructExtractRefOpConversion
960 using OpConversionPattern::OpConversionPattern;
963 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
964 ConversionPatternRewriter &rewriter)
const override {
965 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
966 op, adaptor.getInput(), adaptor.getFieldNameAttr());
972 using OpConversionPattern::OpConversionPattern;
974 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
975 ConversionPatternRewriter &rewriter)
const override {
976 Type resultType = typeConverter->convertType(op.getInput().getType());
979 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
980 adaptor.getInput(), max);
986 using OpConversionPattern::OpConversionPattern;
988 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
989 ConversionPatternRewriter &rewriter)
const override {
990 Type resultType = typeConverter->convertType(op.getInput().getType());
993 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
994 adaptor.getInput(), zero);
1000 using OpConversionPattern::OpConversionPattern;
1002 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1003 ConversionPatternRewriter &rewriter)
const override {
1005 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1011 using OpConversionPattern::OpConversionPattern;
1013 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1014 ConversionPatternRewriter &rewriter)
const override {
1015 Type resultType = typeConverter->convertType(op.getInput().getType());
1016 if (isa_and_nonnull<IntegerType>(resultType)) {
1019 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1020 adaptor.getInput(), zero);
1028 using OpConversionPattern::OpConversionPattern;
1030 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1031 ConversionPatternRewriter &rewriter)
const override {
1033 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1036 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1042 using OpConversionPattern::OpConversionPattern;
1044 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1045 ConversionPatternRewriter &rewriter)
const override {
1047 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1050 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1055template <
typename SourceOp,
typename TargetOp>
1058 using OpAdaptor =
typename SourceOp::Adaptor;
1061 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1062 ConversionPatternRewriter &rewriter)
const override {
1063 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1064 adaptor.getRhs(),
false);
1069template <
typename SourceOp, ICmpPredicate pred>
1072 using OpAdaptor =
typename SourceOp::Adaptor;
1075 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1076 ConversionPatternRewriter &rewriter)
const override {
1078 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1080 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1081 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1086template <
typename SourceOp,
bool withoutX>
1089 using OpAdaptor =
typename SourceOp::Adaptor;
1092 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1093 ConversionPatternRewriter &rewriter)
const override {
1099 unsigned bitWidth = op.getLhs().getType().getWidth();
1100 auto ignoredBits = APInt::getZero(bitWidth);
1101 auto detectIgnoredBits = [&](Value value) {
1102 auto constOp = value.getDefiningOp<ConstantOp>();
1105 auto constValue = constOp.getValue();
1107 ignoredBits |= constValue.getZBits();
1109 ignoredBits |= constValue.getUnknownBits();
1111 detectIgnoredBits(op.getLhs());
1112 detectIgnoredBits(op.getRhs());
1116 Value lhs = adaptor.getLhs();
1117 Value rhs = adaptor.getRhs();
1118 if (!ignoredBits.isZero()) {
1119 ignoredBits.flipAllBits();
1121 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1122 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1125 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1135 using OpConversionPattern::OpConversionPattern;
1138 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1139 ConversionPatternRewriter &rewriter)
const override {
1140 Location loc = op.getLoc();
1141 Type resultType = typeConverter->convertType(op.getResult().getType());
1142 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1143 int64_t resultBw = hw::getBitWidth(resultType);
1144 if (inputBw == -1 || resultBw == -1)
1148 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1149 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1152 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1153 rewriter.replaceOp(op, result);
1159 using OpConversionPattern::OpConversionPattern;
1162 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1163 ConversionPatternRewriter &rewriter)
const override {
1164 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1165 op.getType().getWidth());
1171 using OpConversionPattern::OpConversionPattern;
1174 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1175 ConversionPatternRewriter &rewriter)
const override {
1176 auto targetWidth = op.getType().getWidth();
1177 auto inputWidth = op.getInput().getType().getWidth();
1180 rewriter, op.getLoc(),
1181 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1184 op, ValueRange{zeroExt, adaptor.getInput()});
1190 using OpConversionPattern::OpConversionPattern;
1193 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1194 ConversionPatternRewriter &rewriter)
const override {
1195 auto type = typeConverter->convertType(op.getType());
1197 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1198 rewriter.replaceOp(op, value);
1208 using OpConversionPattern::OpConversionPattern;
1211 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1212 ConversionPatternRewriter &rewriter)
const override {
1213 SmallVector<Type> convResTypes;
1214 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1217 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1218 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1219 adaptor.getOperands(), op.getArgNames(),
1220 op.getResultNames(),
1221 rewriter.getArrayAttr({}),
nullptr);
1228 using OpConversionPattern::OpConversionPattern;
1231 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1232 ConversionPatternRewriter &rewriter)
const override {
1233 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1239 using OpConversionPattern::OpConversionPattern;
1242 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1243 ConversionPatternRewriter &rewriter)
const override {
1244 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1245 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1246 adaptor.getFalseDestOperands(),
nullptr,
1247 op.getTrueDest(), op.getFalseDest());
1253 using OpConversionPattern::OpConversionPattern;
1256 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1257 ConversionPatternRewriter &rewriter)
const override {
1258 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1259 adaptor.getDestOperands());
1265 using OpConversionPattern::OpConversionPattern;
1268 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1269 ConversionPatternRewriter &rewriter)
const override {
1270 SmallVector<Type> convResTypes;
1271 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1273 rewriter.replaceOpWithNewOp<func::CallOp>(
1274 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1279struct UnrealizedConversionCastConversion
1281 using OpConversionPattern::OpConversionPattern;
1284 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1285 ConversionPatternRewriter &rewriter)
const override {
1286 SmallVector<Type> convResTypes;
1287 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1292 if (convResTypes == adaptor.getOperands().getTypes()) {
1293 rewriter.replaceOp(op, adaptor.getOperands());
1297 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1298 op, convResTypes, adaptor.getOperands());
1304 using OpConversionPattern::OpConversionPattern;
1307 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1308 ConversionPatternRewriter &rewriter)
const override {
1309 Type resultType = typeConverter->convertType(op.getResult().getType());
1313 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1314 resultType.getIntOrFloatBitWidth(), op->getLoc());
1315 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1322 using OpConversionPattern::OpConversionPattern;
1325 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1326 ConversionPatternRewriter &rewriter)
const override {
1327 Type resultType = typeConverter->convertType(op.getResult().getType());
1331 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1332 resultType.getIntOrFloatBitWidth(), op->getLoc());
1334 op, resultType, adaptor.getValue(), amount,
false);
1340 using OpConversionPattern::OpConversionPattern;
1343 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1344 ConversionPatternRewriter &rewriter)
const override {
1345 Type resultType = typeConverter->convertType(op.getResult().getType());
1347 Location loc = op->getLoc();
1352 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1353 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1356 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1364 using OpConversionPattern::OpConversionPattern;
1367 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1368 ConversionPatternRewriter &rewriter)
const override {
1369 Type resultType = typeConverter->convertType(op.getResult().getType());
1373 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1374 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1380 using OpConversionPattern::OpConversionPattern;
1383 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1384 ConversionPatternRewriter &rewriter)
const override {
1385 Type resultType = typeConverter->convertType(op.getResult().getType());
1389 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1390 resultType.getIntOrFloatBitWidth(), op->getLoc());
1392 op, resultType, adaptor.getValue(), amount,
false);
1398 using OpConversionPattern::OpConversionPattern;
1401 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1402 ConversionPatternRewriter &rewriter)
const override {
1403 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1408struct AssignedVariableOpConversion
1410 using OpConversionPattern::OpConversionPattern;
1413 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1414 ConversionPatternRewriter &rewriter)
const override {
1415 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1416 adaptor.getNameAttr());
1421template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1424 using OpAdaptor =
typename OpTy::Adaptor;
1427 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1428 ConversionPatternRewriter &rewriter)
const override {
1431 auto timeAttr = llhd::TimeAttr::get(
1432 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1433 auto time = llhd::ConstantTimeOp::create(rewriter, op->getLoc(), timeAttr);
1434 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1435 adaptor.getSrc(), time, Value{});
1441 using OpConversionPattern::OpConversionPattern;
1444 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1445 ConversionPatternRewriter &rewriter)
const override {
1450 auto type = typeConverter->convertType(op.getType());
1452 auto hasNoWriteEffect = [](Region ®ion) {
1453 auto result = region.walk([](Operation *operation) {
1454 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1455 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1456 !memOp.hasEffect<MemoryEffects::Free>())
1457 return WalkResult::advance();
1459 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1460 return WalkResult::advance();
1462 return WalkResult::interrupt();
1464 return !result.wasInterrupted();
1467 if (hasNoWriteEffect(op.getTrueRegion()) &&
1468 hasNoWriteEffect(op.getFalseRegion())) {
1469 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1470 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1472 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1473 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1475 Value convTrueVal = typeConverter->materializeTargetConversion(
1476 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1477 Value convFalseVal = typeConverter->materializeTargetConversion(
1478 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1480 rewriter.eraseOp(trueTerm);
1481 rewriter.eraseOp(falseTerm);
1483 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1484 convTrueVal, convFalseVal);
1489 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1490 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1491 ifOp.getThenRegion().end());
1492 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1493 ifOp.getElseRegion().end());
1494 rewriter.replaceOp(op, ifOp);
1500 using OpConversionPattern::OpConversionPattern;
1503 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1504 ConversionPatternRewriter &rewriter)
const override {
1505 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1510template <
typename SourceOp>
1513 using OpAdaptor =
typename SourceOp::Adaptor;
1516 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1517 ConversionPatternRewriter &rewriter)
const override {
1518 rewriter.modifyOpInPlace(op,
1519 [&]() { op->setOperands(adaptor.getOperands()); });
1524template <
typename MooreOpTy,
typename VerifOpTy>
1527 using OpAdaptor =
typename MooreOpTy::Adaptor;
1530 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1531 ConversionPatternRewriter &rewriter)
const override {
1533 op.getLabel().has_value()
1534 ? StringAttr::get(op->getContext(), op.getLabel().value())
1535 : StringAttr::
get(op->getContext());
1536 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1547 using OpConversionPattern::OpConversionPattern;
1550 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1551 ConversionPatternRewriter &rewriter)
const override {
1552 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1558 using OpConversionPattern::OpConversionPattern;
1561 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1562 ConversionPatternRewriter &rewriter)
const override {
1563 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1564 adaptor.getInputs());
1570 using OpConversionPattern::OpConversionPattern;
1573 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1574 ConversionPatternRewriter &rewriter)
const override {
1576 switch (op.getFormat()) {
1577 case IntFormat::Decimal:
1578 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1580 case IntFormat::Binary:
1581 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1583 case IntFormat::HexLower:
1584 case IntFormat::HexUpper:
1585 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1588 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1594 using OpConversionPattern::OpConversionPattern;
1597 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1598 ConversionPatternRewriter &rewriter)
const override {
1599 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1600 op, adaptor.getMessage());
1612 const TypeConverter &converter) {
1613 target.addIllegalDialect<MooreDialect>();
1614 target.addLegalDialect<comb::CombDialect>();
1615 target.addLegalDialect<hw::HWDialect>();
1616 target.addLegalDialect<seq::SeqDialect>();
1617 target.addLegalDialect<llhd::LLHDDialect>();
1618 target.addLegalDialect<ltl::LTLDialect>();
1619 target.addLegalDialect<mlir::BuiltinDialect>();
1620 target.addLegalDialect<mlir::math::MathDialect>();
1621 target.addLegalDialect<sim::SimDialect>();
1622 target.addLegalDialect<verif::VerifDialect>();
1624 target.addLegalOp<debug::ScopeOp>();
1626 target.addDynamicallyLegalOp<
1627 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1628 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1629 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1630 [&](Operation *op) {
return converter.isLegal(op); });
1632 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1633 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1634 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1637 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1638 return converter.isSignatureLegal(op.getFunctionType()) &&
1639 converter.isLegal(&op.getFunctionBody());
1643 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1644 converter.isLegal(&op.getBody());
1649 typeConverter.addConversion([&](IntType type) {
1650 return IntegerType::get(type.getContext(), type.getWidth());
1653 typeConverter.addConversion(
1654 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
1656 typeConverter.addConversion([&](FormatStringType type) {
1657 return sim::FormatStringType::get(type.getContext());
1660 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1661 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1662 return hw::ArrayType::get(
elementType, type.getSize());
1669 typeConverter.addConversion(
1670 [&](UnpackedArrayType type) -> std::optional<Type> {
1671 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1672 return hw::ArrayType::get(
elementType, type.getSize());
1676 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1677 SmallVector<hw::StructType::FieldInfo> fields;
1678 for (
auto field : type.getMembers()) {
1679 hw::StructType::FieldInfo info;
1680 info.type = typeConverter.convertType(field.type);
1683 info.name = field.name;
1684 fields.push_back(info);
1686 return hw::StructType::get(type.getContext(), fields);
1694 typeConverter.addConversion(
1695 [&](UnpackedStructType type) -> std::optional<Type> {
1696 SmallVector<hw::StructType::FieldInfo> fields;
1697 for (
auto field : type.getMembers()) {
1698 hw::StructType::FieldInfo info;
1699 info.type = typeConverter.convertType(field.type);
1702 info.name = field.name;
1703 fields.push_back(info);
1705 return hw::StructType::get(type.getContext(), fields);
1708 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1709 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1710 if (hw::isHWValueType(innerType))
1711 return hw::InOutType::get(innerType);
1716 typeConverter.addConversion([](IntegerType type) {
return type; });
1717 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
1718 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1719 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1720 typeConverter.addConversion([](debug::StructType type) {
return type; });
1722 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1723 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1724 return hw::InOutType::get(innerType);
1728 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1729 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1730 return hw::ArrayType::get(
elementType, type.getNumElements());
1734 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1735 SmallVector<hw::StructType::FieldInfo> fields;
1736 for (
auto field : type.getElements()) {
1737 hw::StructType::FieldInfo info;
1738 info.type = typeConverter.convertType(field.type);
1741 info.name = field.name;
1742 fields.push_back(info);
1744 return hw::StructType::get(type.getContext(), fields);
1747 typeConverter.addTargetMaterialization(
1748 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1749 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1750 if (inputs.size() != 1 || !inputs[0])
1752 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1757 typeConverter.addSourceMaterialization(
1758 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1759 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1760 if (inputs.size() != 1)
1762 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1769 TypeConverter &typeConverter) {
1770 auto *context =
patterns.getContext();
1774 VariableOpConversion,
1778 ConversionOpConversion,
1784 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1786 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1788 StructExtractOpConversion, StructExtractRefOpConversion,
1789 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion, ArrayCreateOpConversion,
1790 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1793 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1794 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1797 BinaryOpConversion<AddOp, comb::AddOp>,
1798 BinaryOpConversion<SubOp, comb::SubOp>,
1799 BinaryOpConversion<MulOp, comb::MulOp>,
1800 BinaryOpConversion<DivUOp, comb::DivUOp>,
1801 BinaryOpConversion<DivSOp, comb::DivSOp>,
1802 BinaryOpConversion<ModUOp, comb::ModUOp>,
1803 BinaryOpConversion<ModSOp, comb::ModSOp>,
1804 BinaryOpConversion<AndOp, comb::AndOp>,
1805 BinaryOpConversion<OrOp, comb::OrOp>,
1806 BinaryOpConversion<XorOp, comb::XorOp>,
1809 PowUOpConversion, PowSOpConversion,
1812 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1813 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1814 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1815 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1816 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1817 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1818 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1819 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1820 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1821 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1822 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1823 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1824 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1825 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1826 CaseXZEqOpConversion<CaseZEqOp, true>,
1827 CaseXZEqOpConversion<CaseXZEqOp, false>,
1830 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1833 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1836 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1837 AssignOpConversion<BlockingAssignOp, 0, 1>,
1838 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1839 AssignedVariableOpConversion,
1842 CondBranchOpConversion, BranchOpConversion,
1845 HWInstanceOpConversion, ReturnOpConversion,
1846 CallOpConversion, UnrealizedConversionCastConversion,
1847 InPlaceOpConversion<debug::ArrayOp>,
1848 InPlaceOpConversion<debug::StructOp>,
1849 InPlaceOpConversion<debug::VariableOp>,
1852 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1853 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1854 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1857 FormatLiteralOpConversion,
1858 FormatConcatOpConversion,
1859 FormatIntOpConversion,
1860 DisplayBIOpConversion
1861 >(typeConverter, context);
1864 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1866 hw::populateHWModuleLikeTypeConversionPattern(
1867 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1868 populateSCFToControlFlowConversionPatterns(
patterns);
1877struct MooreToCorePass
1878 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1879 void runOnOperation()
override;
1885 return std::make_unique<MooreToCorePass>();
1889void MooreToCorePass::runOnOperation() {
1890 MLIRContext &context = getContext();
1891 ModuleOp
module = getOperation();
1893 IRRewriter rewriter(module);
1894 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1896 ConversionTarget target(context);
1897 TypeConverter typeConverter;
1898 RewritePatternSet
patterns(&context);
1903 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1904 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 void populateOpConversion(RewritePatternSet &patterns, TypeConverter &typeConverter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
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.