23#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
24#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
25#include "mlir/Dialect/Func/IR/FuncOps.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"
37#define GEN_PASS_DEF_CONVERTMOORETOCORE
38#include "circt/Conversion/Passes.h.inc"
45using comb::ICmpPredicate;
46using llvm::SmallDenseSet;
54static Value adjustIntegerWidth(OpBuilder &builder, Value value,
55 uint32_t targetWidth, Location loc) {
56 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
57 if (intWidth == targetWidth)
60 if (intWidth < targetWidth) {
62 loc, builder.getIntegerType(targetWidth - intWidth), 0);
67 intWidth - targetWidth);
69 loc, builder.getIntegerType(intWidth - targetWidth), 0);
70 Value isZero = builder.
create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
74 loc, builder.getIntegerType(targetWidth), -1);
83 auto moduleTy = op.getModuleType();
84 SmallVector<hw::PortInfo> inputs, outputs;
85 inputs.reserve(moduleTy.getNumInputs());
86 outputs.reserve(moduleTy.getNumOutputs());
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);
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 = rewriter.create<hw::InstanceOp>(
171 op.getLoc(), op.getResultTypes(), instName, moduleName, op.getInputs(),
172 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 rewriter.create<llhd::PrbOp>(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 = rewriter.create<llhd::ProcessOp>(loc, TypeRange{});
255 newOp = rewriter.create<llhd::FinalOp>(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 = rewriter.create<llhd::ProcessOp>(loc, TypeRange{});
273 rewriter.createBlock(&newOp.getBody());
274 auto *block = &op.getBody().front();
275 rewriter.create<cf::BranchOp>(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 rewriter.create<llhd::WaitOp>(loc, ValueRange{}, Value(), observedValues,
289 ValueRange{}, block);
296 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
297 rewriter.setInsertionPoint(returnOp);
298 rewriter.create<cf::BranchOp>(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 rewriter.create<cf::BranchOp>(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 = rewriter.create<llhd::WaitOp>(
404 loc, ValueRange{}, Value(), 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 rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
430 after = rewriter.create<moore::ExtractOp>(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 rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
443 SmallVector<Value> disjuncts;
444 Value trueVal = rewriter.create<
hw::ConstantOp>(loc, APInt(1, 1));
446 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
450 rewriter.create<
comb::AndOp>(loc, notOldVal, after,
true);
451 disjuncts.push_back(posedge);
454 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
456 rewriter.create<
comb::XorOp>(loc, after, trueVal,
true);
458 rewriter.create<
comb::AndOp>(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());
481 trigger = rewriter.create<
comb::AndOp>(loc, trigger, condition,
true);
483 triggers.push_back(trigger);
486 rewriter.eraseOp(detectOp);
489 rewriter.setInsertionPointToEnd(checkBlock);
490 if (triggers.empty()) {
495 rewriter.create<cf::BranchOp>(loc, resumeBlock);
501 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
502 rewriter.create<cf::CondBranchOp>(loc, triggered, resumeBlock, waitBlock);
514 using OpConversionPattern::OpConversionPattern;
517 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
518 ConversionPatternRewriter &rewriter)
const override {
519 Location loc = op.getLoc();
520 Type resultType = typeConverter->convertType(op.getResult().getType());
522 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
525 Value init = adaptor.getInitial();
527 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
535 Value constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
539 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
540 op.getNameAttr(), init);
546 using OpConversionPattern::OpConversionPattern;
549 matchAndRewrite(NetOp op, OpAdaptor adaptor,
550 ConversionPatternRewriter &rewriter)
const override {
551 auto loc = op.getLoc();
552 if (op.getKind() != NetKind::Wire)
553 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
555 auto resultType = typeConverter->convertType(op.getResult().getType());
557 return rewriter.notifyMatchFailure(loc,
"invalid net type");
561 auto elementType = cast<hw::InOutType>(resultType).getElementType();
565 auto constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
569 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
570 op, resultType, op.getNameAttr(), init);
572 if (
auto assignedValue = adaptor.getAssignment()) {
573 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
574 llvm::StringRef(
"ns"), 0, 1);
575 auto time = rewriter.create<llhd::ConstantTimeOp>(loc, timeAttr);
576 rewriter.create<llhd::DrvOp>(loc, signal, assignedValue, time, Value{});
588 using OpConversionPattern::OpConversionPattern;
591 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
592 ConversionPatternRewriter &rewriter)
const override {
594 auto value = op.getValue().toAPInt(
false);
595 auto type = rewriter.getIntegerType(value.getBitWidth());
597 op, type, rewriter.getIntegerAttr(type, value));
603 using OpConversionPattern::OpConversionPattern;
605 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
606 ConversionPatternRewriter &rewriter)
const override {
607 const auto str = op.getValue();
608 const unsigned byteWidth = str.size() * 8;
609 const auto resultType =
610 typeConverter->convertType(op.getResult().getType());
611 if (
const auto intType = mlir::dyn_cast<IntegerType>(resultType)) {
612 if (intType.getWidth() < byteWidth) {
613 return rewriter.notifyMatchFailure(op,
614 "invalid string constant type size");
617 return rewriter.notifyMatchFailure(op,
"invalid string constant type");
619 APInt value(byteWidth, 0);
620 for (
size_t i = 0; i < str.size(); ++i) {
621 const auto asciiChar =
static_cast<uint8_t
>(str[i]);
622 value |= APInt(byteWidth, asciiChar) << (8 * (str.size() - 1 - i));
625 op, resultType, rewriter.getIntegerAttr(resultType, value));
631 using OpConversionPattern::OpConversionPattern;
633 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
634 ConversionPatternRewriter &rewriter)
const override {
635 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
641 using OpConversionPattern::OpConversionPattern;
643 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
644 ConversionPatternRewriter &rewriter)
const override {
645 Type resultType = typeConverter->convertType(op.getResult().getType());
647 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
654 using OpConversionPattern::OpConversionPattern;
657 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
658 ConversionPatternRewriter &rewriter)
const override {
661 Type resultType = typeConverter->convertType(op.getResult().getType());
662 Type inputType = adaptor.getInput().getType();
663 int32_t low = adaptor.getLowBit();
665 if (isa<IntegerType>(inputType)) {
666 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
667 int32_t resultWidth = resultType.getIntOrFloatBitWidth();
668 int32_t high = low + resultWidth;
670 SmallVector<Value> toConcat;
673 op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
675 if (low < inputWidth && high > 0) {
676 int32_t lowIdx = std::max(low, 0);
679 rewriter.getIntegerType(
680 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
681 adaptor.getInput(), lowIdx);
682 toConcat.push_back(middle);
685 int32_t diff = high - inputWidth;
689 toConcat.push_back(val);
694 rewriter.replaceOp(op,
concat);
698 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
699 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
700 int32_t inputWidth = arrTy.getNumElements();
702 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
703 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
704 if (elementWidth < 0)
707 int32_t high = low + resArrTy.getNumElements();
708 int32_t resWidth = resArrTy.getNumElements();
710 SmallVector<Value> toConcat;
714 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
717 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
719 toConcat.push_back(res);
722 if (low < inputWidth && high > 0) {
723 int32_t lowIdx = std::max(0, low);
725 op.getLoc(), rewriter.getIntegerType(width), lowIdx);
729 arrTy.getElementType(),
730 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
731 adaptor.getInput(), lowIdxVal);
732 toConcat.push_back(middle);
735 int32_t diff = high - inputWidth;
738 op.getLoc(), APInt(diff * elementWidth, 0));
740 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), diff),
742 toConcat.push_back(val);
747 rewriter.replaceOp(op,
concat);
752 if (low < 0 || low >= inputWidth) {
753 int32_t bw = hw::getBitWidth(resultType);
757 Value val = rewriter.create<
hw::ConstantOp>(op.getLoc(), APInt(bw, 0));
759 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
760 rewriter.replaceOp(op, bitcast);
765 op.getLoc(), rewriter.getIntegerType(width), adaptor.getLowBit());
766 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
775 using OpConversionPattern::OpConversionPattern;
778 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
779 ConversionPatternRewriter &rewriter)
const override {
781 Type resultType = typeConverter->convertType(op.getResult().getType());
783 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
785 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
786 int64_t width = hw::getBitWidth(inputType);
791 op.getLoc(), rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
792 adaptor.getLowBit());
793 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
794 op, resultType, adaptor.getInput(), lowBit);
798 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
801 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
802 adaptor.getLowBit());
804 if (isa<hw::ArrayType>(
805 cast<hw::InOutType>(resultType).getElementType())) {
806 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
807 op, resultType, adaptor.getInput(), lowBit);
811 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
821 using OpConversionPattern::OpConversionPattern;
824 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
825 ConversionPatternRewriter &rewriter)
const override {
826 Type resultType = typeConverter->convertType(op.getResult().getType());
827 Type inputType = adaptor.getInput().getType();
829 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
830 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
831 intType.getWidth(), op->getLoc());
832 Value value = rewriter.create<
comb::ShrUOp>(op->getLoc(),
833 adaptor.getInput(), amount);
835 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
839 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
840 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
841 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
844 if (isa<hw::ArrayType>(resultType)) {
846 adaptor.getInput(), idx);
850 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
859 using OpConversionPattern::OpConversionPattern;
862 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
863 ConversionPatternRewriter &rewriter)
const override {
865 Type resultType = typeConverter->convertType(op.getResult().getType());
867 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
869 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
870 int64_t width = hw::getBitWidth(inputType);
875 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
876 llvm::Log2_64_Ceil(width), op->getLoc());
877 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
878 op, resultType, adaptor.getInput(), amount);
882 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
883 Value idx = adjustIntegerWidth(
884 rewriter, adaptor.getLowBit(),
885 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
887 if (isa<hw::ArrayType>(
888 cast<hw::InOutType>(resultType).getElementType())) {
889 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
890 op, resultType, adaptor.getInput(), idx);
894 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
904 using OpConversionPattern::OpConversionPattern;
907 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
908 ConversionPatternRewriter &rewriter)
const override {
909 Type resultType = typeConverter->convertType(op.getResult().getType());
911 adaptor.getElements());
917 using OpConversionPattern::OpConversionPattern;
920 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
921 ConversionPatternRewriter &rewriter)
const override {
922 Type resultType = typeConverter->convertType(op.getResult().getType());
924 adaptor.getFields());
930 using OpConversionPattern::OpConversionPattern;
933 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
934 ConversionPatternRewriter &rewriter)
const override {
936 op, adaptor.getInput(), adaptor.getFieldNameAttr());
941struct StructExtractRefOpConversion
943 using OpConversionPattern::OpConversionPattern;
946 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
947 ConversionPatternRewriter &rewriter)
const override {
948 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
949 op, adaptor.getInput(), adaptor.getFieldNameAttr());
955 using OpConversionPattern::OpConversionPattern;
957 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
958 ConversionPatternRewriter &rewriter)
const override {
959 Type resultType = typeConverter->convertType(op.getInput().getType());
960 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
962 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
963 adaptor.getInput(), max);
969 using OpConversionPattern::OpConversionPattern;
971 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
972 ConversionPatternRewriter &rewriter)
const override {
973 Type resultType = typeConverter->convertType(op.getInput().getType());
974 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
976 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
977 adaptor.getInput(), zero);
983 using OpConversionPattern::OpConversionPattern;
985 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
986 ConversionPatternRewriter &rewriter)
const override {
988 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
994 using OpConversionPattern::OpConversionPattern;
996 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
997 ConversionPatternRewriter &rewriter)
const override {
998 Type resultType = typeConverter->convertType(op.getInput().getType());
999 if (isa_and_nonnull<IntegerType>(resultType)) {
1000 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
1001 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1002 adaptor.getInput(), zero);
1010 using OpConversionPattern::OpConversionPattern;
1012 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1013 ConversionPatternRewriter &rewriter)
const override {
1015 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1016 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
1018 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1024 using OpConversionPattern::OpConversionPattern;
1026 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1027 ConversionPatternRewriter &rewriter)
const override {
1029 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1030 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
1032 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1037template <
typename SourceOp,
typename TargetOp>
1040 using OpAdaptor =
typename SourceOp::Adaptor;
1043 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1044 ConversionPatternRewriter &rewriter)
const override {
1045 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1046 adaptor.getRhs(),
false);
1051template <
typename SourceOp, ICmpPredicate pred>
1054 using OpAdaptor =
typename SourceOp::Adaptor;
1057 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1058 ConversionPatternRewriter &rewriter)
const override {
1060 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1062 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1063 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1068template <
typename SourceOp,
bool withoutX>
1071 using OpAdaptor =
typename SourceOp::Adaptor;
1074 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1075 ConversionPatternRewriter &rewriter)
const override {
1081 unsigned bitWidth = op.getLhs().getType().getWidth();
1082 auto ignoredBits = APInt::getZero(bitWidth);
1083 auto detectIgnoredBits = [&](Value value) {
1084 auto constOp = value.getDefiningOp<ConstantOp>();
1087 auto constValue = constOp.getValue();
1089 ignoredBits |= constValue.getZBits();
1091 ignoredBits |= constValue.getUnknownBits();
1093 detectIgnoredBits(op.getLhs());
1094 detectIgnoredBits(op.getRhs());
1098 Value lhs = adaptor.getLhs();
1099 Value rhs = adaptor.getRhs();
1100 if (!ignoredBits.isZero()) {
1101 ignoredBits.flipAllBits();
1102 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
1103 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1104 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1107 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1117 using OpConversionPattern::OpConversionPattern;
1120 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1121 ConversionPatternRewriter &rewriter)
const override {
1122 Location loc = op.getLoc();
1123 Type resultType = typeConverter->convertType(op.getResult().getType());
1124 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1125 int64_t resultBw = hw::getBitWidth(resultType);
1126 if (inputBw == -1 || resultBw == -1)
1130 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1131 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1134 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1135 rewriter.replaceOp(op, result);
1141 using OpConversionPattern::OpConversionPattern;
1144 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1145 ConversionPatternRewriter &rewriter)
const override {
1146 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1147 op.getType().getWidth());
1153 using OpConversionPattern::OpConversionPattern;
1156 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1157 ConversionPatternRewriter &rewriter)
const override {
1158 auto targetWidth = op.getType().getWidth();
1159 auto inputWidth = op.getInput().getType().getWidth();
1162 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1165 op, ValueRange{zeroExt, adaptor.getInput()});
1171 using OpConversionPattern::OpConversionPattern;
1174 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1175 ConversionPatternRewriter &rewriter)
const override {
1176 auto type = typeConverter->convertType(op.getType());
1178 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1179 rewriter.replaceOp(op, value);
1189 using OpConversionPattern::OpConversionPattern;
1192 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1193 ConversionPatternRewriter &rewriter)
const override {
1194 SmallVector<Type> convResTypes;
1195 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1198 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1199 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1200 adaptor.getOperands(), op.getArgNames(),
1201 op.getResultNames(),
1202 rewriter.getArrayAttr({}),
nullptr);
1209 using OpConversionPattern::OpConversionPattern;
1212 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1213 ConversionPatternRewriter &rewriter)
const override {
1214 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1220 using OpConversionPattern::OpConversionPattern;
1223 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1224 ConversionPatternRewriter &rewriter)
const override {
1225 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1226 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1227 adaptor.getFalseDestOperands(),
nullptr,
1228 op.getTrueDest(), op.getFalseDest());
1234 using OpConversionPattern::OpConversionPattern;
1237 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1238 ConversionPatternRewriter &rewriter)
const override {
1239 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1240 adaptor.getDestOperands());
1246 using OpConversionPattern::OpConversionPattern;
1249 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1250 ConversionPatternRewriter &rewriter)
const override {
1251 SmallVector<Type> convResTypes;
1252 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1254 rewriter.replaceOpWithNewOp<func::CallOp>(
1255 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1260struct UnrealizedConversionCastConversion
1262 using OpConversionPattern::OpConversionPattern;
1265 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1266 ConversionPatternRewriter &rewriter)
const override {
1267 SmallVector<Type> convResTypes;
1268 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1273 if (convResTypes == adaptor.getOperands().getTypes()) {
1274 rewriter.replaceOp(op, adaptor.getOperands());
1278 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1279 op, convResTypes, adaptor.getOperands());
1285 using OpConversionPattern::OpConversionPattern;
1288 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1289 ConversionPatternRewriter &rewriter)
const override {
1290 Type resultType = typeConverter->convertType(op.getResult().getType());
1294 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1295 resultType.getIntOrFloatBitWidth(), op->getLoc());
1296 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1303 using OpConversionPattern::OpConversionPattern;
1306 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1307 ConversionPatternRewriter &rewriter)
const override {
1308 Type resultType = typeConverter->convertType(op.getResult().getType());
1312 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1313 resultType.getIntOrFloatBitWidth(), op->getLoc());
1315 op, resultType, adaptor.getValue(), amount,
false);
1321 using OpConversionPattern::OpConversionPattern;
1324 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1325 ConversionPatternRewriter &rewriter)
const override {
1326 Type resultType = typeConverter->convertType(op.getResult().getType());
1328 Location loc = op.getLoc();
1329 auto intType = cast<IntType>(op.getRhs().getType());
1332 Type integerType = rewriter.getIntegerType(intType.getWidth());
1333 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1335 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1336 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1339 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1341 auto forOp = rewriter.create<scf::ForOp>(
1342 loc, lowerBound, upperBound, step, ValueRange(initVal),
1343 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1344 Value loopVar = iterArgs.front();
1346 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1349 rewriter.replaceOp(op, forOp.getResult(0));
1356 using OpConversionPattern::OpConversionPattern;
1359 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1360 ConversionPatternRewriter &rewriter)
const override {
1361 Type resultType = typeConverter->convertType(op.getResult().getType());
1365 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1366 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1372 using OpConversionPattern::OpConversionPattern;
1375 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1376 ConversionPatternRewriter &rewriter)
const override {
1377 Type resultType = typeConverter->convertType(op.getResult().getType());
1381 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1382 resultType.getIntOrFloatBitWidth(), op->getLoc());
1384 op, resultType, adaptor.getValue(), amount,
false);
1390 using OpConversionPattern::OpConversionPattern;
1393 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1394 ConversionPatternRewriter &rewriter)
const override {
1395 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1400struct AssignedVariableOpConversion
1402 using OpConversionPattern::OpConversionPattern;
1405 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1406 ConversionPatternRewriter &rewriter)
const override {
1407 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1408 adaptor.getNameAttr());
1413template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1416 using OpAdaptor =
typename OpTy::Adaptor;
1419 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1420 ConversionPatternRewriter &rewriter)
const override {
1423 auto timeAttr = llhd::TimeAttr::get(
1424 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1425 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1426 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1427 adaptor.getSrc(), time, Value{});
1433 using OpConversionPattern::OpConversionPattern;
1436 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1437 ConversionPatternRewriter &rewriter)
const override {
1442 auto type = typeConverter->convertType(op.getType());
1444 auto hasNoWriteEffect = [](Region ®ion) {
1445 auto result = region.walk([](Operation *operation) {
1446 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1447 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1448 !memOp.hasEffect<MemoryEffects::Free>())
1449 return WalkResult::advance();
1451 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1452 return WalkResult::advance();
1454 return WalkResult::interrupt();
1456 return !result.wasInterrupted();
1459 if (hasNoWriteEffect(op.getTrueRegion()) &&
1460 hasNoWriteEffect(op.getFalseRegion())) {
1461 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1462 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1464 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1465 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1467 Value convTrueVal = typeConverter->materializeTargetConversion(
1468 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1469 Value convFalseVal = typeConverter->materializeTargetConversion(
1470 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1472 rewriter.eraseOp(trueTerm);
1473 rewriter.eraseOp(falseTerm);
1475 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1476 convTrueVal, convFalseVal);
1481 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1482 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1483 ifOp.getThenRegion().end());
1484 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1485 ifOp.getElseRegion().end());
1486 rewriter.replaceOp(op, ifOp);
1492 using OpConversionPattern::OpConversionPattern;
1495 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1496 ConversionPatternRewriter &rewriter)
const override {
1497 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1502template <
typename SourceOp>
1505 using OpAdaptor =
typename SourceOp::Adaptor;
1508 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1509 ConversionPatternRewriter &rewriter)
const override {
1510 rewriter.modifyOpInPlace(op,
1511 [&]() { op->setOperands(adaptor.getOperands()); });
1516template <
typename MooreOpTy,
typename VerifOpTy>
1519 using OpAdaptor =
typename MooreOpTy::Adaptor;
1522 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1523 ConversionPatternRewriter &rewriter)
const override {
1525 op.getLabel().has_value()
1526 ? StringAttr::get(op->getContext(), op.getLabel().value())
1527 : StringAttr::
get(op->getContext());
1528 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1539 using OpConversionPattern::OpConversionPattern;
1542 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1543 ConversionPatternRewriter &rewriter)
const override {
1544 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1550 using OpConversionPattern::OpConversionPattern;
1553 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1554 ConversionPatternRewriter &rewriter)
const override {
1555 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1556 adaptor.getInputs());
1562 using OpConversionPattern::OpConversionPattern;
1565 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1566 ConversionPatternRewriter &rewriter)
const override {
1568 switch (op.getFormat()) {
1569 case IntFormat::Decimal:
1570 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1572 case IntFormat::Binary:
1573 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1575 case IntFormat::HexLower:
1576 case IntFormat::HexUpper:
1577 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1580 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1586 using OpConversionPattern::OpConversionPattern;
1589 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1590 ConversionPatternRewriter &rewriter)
const override {
1591 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1592 op, adaptor.getMessage());
1604 const TypeConverter &converter) {
1605 target.addIllegalDialect<MooreDialect>();
1606 target.addLegalDialect<comb::CombDialect>();
1607 target.addLegalDialect<hw::HWDialect>();
1608 target.addLegalDialect<llhd::LLHDDialect>();
1609 target.addLegalDialect<ltl::LTLDialect>();
1610 target.addLegalDialect<mlir::BuiltinDialect>();
1611 target.addLegalDialect<mlir::math::MathDialect>();
1612 target.addLegalDialect<sim::SimDialect>();
1613 target.addLegalDialect<verif::VerifDialect>();
1615 target.addLegalOp<debug::ScopeOp>();
1617 target.addDynamicallyLegalOp<
1618 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1619 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1620 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1621 [&](Operation *op) {
return converter.isLegal(op); });
1623 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1624 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1625 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1628 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1629 return converter.isSignatureLegal(op.getFunctionType()) &&
1630 converter.isLegal(&op.getFunctionBody());
1634 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1635 converter.isLegal(&op.getBody());
1640 typeConverter.addConversion([&](IntType type) {
1641 return IntegerType::get(type.getContext(), type.getWidth());
1644 typeConverter.addConversion([&](FormatStringType type) {
1645 return sim::FormatStringType::get(type.getContext());
1648 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1649 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1650 return hw::ArrayType::get(
elementType, type.getSize());
1657 typeConverter.addConversion(
1658 [&](UnpackedArrayType type) -> std::optional<Type> {
1659 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1660 return hw::ArrayType::get(
elementType, type.getSize());
1664 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1665 SmallVector<hw::StructType::FieldInfo> fields;
1666 for (
auto field : type.getMembers()) {
1667 hw::StructType::FieldInfo info;
1668 info.type = typeConverter.convertType(field.type);
1671 info.name = field.name;
1672 fields.push_back(info);
1674 return hw::StructType::get(type.getContext(), fields);
1682 typeConverter.addConversion(
1683 [&](UnpackedStructType type) -> std::optional<Type> {
1684 SmallVector<hw::StructType::FieldInfo> fields;
1685 for (
auto field : type.getMembers()) {
1686 hw::StructType::FieldInfo info;
1687 info.type = typeConverter.convertType(field.type);
1690 info.name = field.name;
1691 fields.push_back(info);
1693 return hw::StructType::get(type.getContext(), fields);
1696 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1697 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1698 return hw::InOutType::get(innerType);
1703 typeConverter.addConversion([](IntegerType type) {
return type; });
1704 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1705 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1706 typeConverter.addConversion([](debug::StructType type) {
return type; });
1708 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1709 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1710 return hw::InOutType::get(innerType);
1714 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1715 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1716 return hw::ArrayType::get(
elementType, type.getNumElements());
1720 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1721 SmallVector<hw::StructType::FieldInfo> fields;
1722 for (
auto field : type.getElements()) {
1723 hw::StructType::FieldInfo info;
1724 info.type = typeConverter.convertType(field.type);
1727 info.name = field.name;
1728 fields.push_back(info);
1730 return hw::StructType::get(type.getContext(), fields);
1733 typeConverter.addTargetMaterialization(
1734 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1735 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1736 if (inputs.size() != 1 || !inputs[0])
1739 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1743 typeConverter.addSourceMaterialization(
1744 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1745 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1746 if (inputs.size() != 1)
1749 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1755 TypeConverter &typeConverter) {
1756 auto *context =
patterns.getContext();
1760 VariableOpConversion,
1764 ConversionOpConversion,
1770 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1771 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1773 StructExtractOpConversion, StructExtractRefOpConversion,
1774 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion, ArrayCreateOpConversion,
1775 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1778 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1779 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1782 BinaryOpConversion<AddOp, comb::AddOp>,
1783 BinaryOpConversion<SubOp, comb::SubOp>,
1784 BinaryOpConversion<MulOp, comb::MulOp>,
1785 BinaryOpConversion<DivUOp, comb::DivUOp>,
1786 BinaryOpConversion<DivSOp, comb::DivSOp>,
1787 BinaryOpConversion<ModUOp, comb::ModUOp>,
1788 BinaryOpConversion<ModSOp, comb::ModSOp>,
1789 BinaryOpConversion<AndOp, comb::AndOp>,
1790 BinaryOpConversion<OrOp, comb::OrOp>,
1791 BinaryOpConversion<XorOp, comb::XorOp>,
1794 PowUOpConversion, PowSOpConversion,
1797 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1798 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1799 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1800 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1801 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1802 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1803 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1804 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1805 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1806 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1807 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1808 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1809 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1810 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1811 CaseXZEqOpConversion<CaseZEqOp, true>,
1812 CaseXZEqOpConversion<CaseXZEqOp, false>,
1815 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1818 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1821 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1822 AssignOpConversion<BlockingAssignOp, 0, 1>,
1823 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1824 AssignedVariableOpConversion,
1827 CondBranchOpConversion, BranchOpConversion,
1830 HWInstanceOpConversion, ReturnOpConversion,
1831 CallOpConversion, UnrealizedConversionCastConversion,
1832 InPlaceOpConversion<debug::ArrayOp>,
1833 InPlaceOpConversion<debug::StructOp>,
1834 InPlaceOpConversion<debug::VariableOp>,
1837 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1838 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1839 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1842 FormatLiteralOpConversion,
1843 FormatConcatOpConversion,
1844 FormatIntOpConversion,
1845 DisplayBIOpConversion
1846 >(typeConverter, context);
1849 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1851 hw::populateHWModuleLikeTypeConversionPattern(
1852 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1853 populateSCFToControlFlowConversionPatterns(
patterns);
1862struct MooreToCorePass
1863 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1864 void runOnOperation()
override;
1870 return std::make_unique<MooreToCorePass>();
1874void MooreToCorePass::runOnOperation() {
1875 MLIRContext &context = getContext();
1876 ModuleOp
module = getOperation();
1878 IRRewriter rewriter(module);
1879 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1881 ConversionTarget target(context);
1882 TypeConverter typeConverter;
1883 RewritePatternSet
patterns(&context);
1888 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1889 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)
create(array_value, low_index, ret_type)
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.