22#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
23#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
24#include "mlir/Dialect/Func/IR/FuncOps.h"
25#include "mlir/Dialect/SCF/IR/SCF.h"
26#include "mlir/IR/BuiltinDialect.h"
27#include "mlir/IR/Iterators.h"
28#include "mlir/Interfaces/SideEffectInterfaces.h"
29#include "mlir/Pass/Pass.h"
30#include "mlir/Transforms/DialectConversion.h"
31#include "mlir/Transforms/RegionUtils.h"
32#include "llvm/ADT/TypeSwitch.h"
35#define GEN_PASS_DEF_CONVERTMOORETOCORE
36#include "circt/Conversion/Passes.h.inc"
43using comb::ICmpPredicate;
44using llvm::SmallDenseSet;
52static Value adjustIntegerWidth(OpBuilder &builder, Value value,
53 uint32_t targetWidth, Location loc) {
54 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
55 if (intWidth == targetWidth)
58 if (intWidth < targetWidth) {
60 loc, builder.getIntegerType(targetWidth - intWidth), 0);
65 intWidth - targetWidth);
67 loc, builder.getIntegerType(intWidth - targetWidth), 0);
68 Value isZero = builder.
create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
72 loc, builder.getIntegerType(targetWidth), -1);
81 auto moduleTy = op.getModuleType();
82 SmallVector<hw::PortInfo> inputs, outputs;
83 inputs.reserve(moduleTy.getNumInputs());
84 outputs.reserve(moduleTy.getNumOutputs());
86 for (
auto port : moduleTy.getPorts()) {
87 Type portTy = typeConverter.convertType(port.type);
88 if (
auto ioTy = dyn_cast_or_null<hw::InOutType>(portTy)) {
96 if (port.dir == hw::ModulePort::Direction::Output) {
98 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
106 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
118 using OpConversionPattern::OpConversionPattern;
121 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
122 ConversionPatternRewriter &rewriter)
const override {
123 rewriter.setInsertionPoint(op);
128 getModulePortInfo(*typeConverter, op));
131 SymbolTable::setSymbolVisibility(hwModuleOp,
132 SymbolTable::getSymbolVisibility(op));
133 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
135 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
137 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
138 hwModuleOp.getBodyRegion().end());
141 rewriter.eraseOp(op);
147 using OpConversionPattern::OpConversionPattern;
150 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
151 ConversionPatternRewriter &rewriter)
const override {
152 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
158 using OpConversionPattern::OpConversionPattern;
161 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
162 ConversionPatternRewriter &rewriter)
const override {
163 auto instName = op.getInstanceNameAttr();
164 auto moduleName = op.getModuleNameAttr();
167 rewriter.setInsertionPoint(op);
168 auto instOp = rewriter.create<hw::InstanceOp>(
169 op.getLoc(), op.getResultTypes(), instName, moduleName, op.getInputs(),
170 op.getInputNamesAttr(), op.getOutputNamesAttr(),
171 rewriter.getArrayAttr({}),
nullptr,
175 op.replaceAllUsesWith(instOp.getResults());
176 rewriter.eraseOp(op);
181static void getValuesToObserve(Region *region,
182 function_ref<
void(Value)> setInsertionPoint,
183 const TypeConverter *typeConverter,
184 ConversionPatternRewriter &rewriter,
185 SmallVector<Value> &observeValues) {
186 SmallDenseSet<Value> alreadyObserved;
187 Location loc = region->getLoc();
189 auto probeIfSignal = [&](Value value) -> Value {
190 if (!isa<hw::InOutType>(value.getType()))
192 return rewriter.create<llhd::PrbOp>(loc, value);
195 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
196 [&](Operation *operation) {
197 for (
auto value : operation->getOperands()) {
198 if (isa<BlockArgument>(value))
199 value = rewriter.getRemappedValue(value);
201 if (region->isAncestor(value.getParentRegion()))
203 if (
auto *defOp = value.getDefiningOp();
204 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
206 if (!alreadyObserved.insert(value).second)
209 OpBuilder::InsertionGuard g(rewriter);
210 if (
auto remapped = rewriter.getRemappedValue(value)) {
211 setInsertionPoint(remapped);
212 observeValues.push_back(probeIfSignal(remapped));
214 setInsertionPoint(value);
215 auto type = typeConverter->convertType(value.getType());
216 auto converted = typeConverter->materializeTargetConversion(
217 rewriter, loc, type, value);
218 observeValues.push_back(probeIfSignal(converted));
225 using OpConversionPattern::OpConversionPattern;
228 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
229 ConversionPatternRewriter &rewriter)
const override {
231 SmallVector<Value> observedValues;
232 if (op.getKind() == ProcedureKind::AlwaysComb ||
233 op.getKind() == ProcedureKind::AlwaysLatch) {
234 auto setInsertionPoint = [&](Value value) {
235 rewriter.setInsertionPoint(op);
237 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
238 rewriter, observedValues);
241 auto loc = op.getLoc();
242 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
247 if (op.getKind() == ProcedureKind::Initial ||
248 op.getKind() == ProcedureKind::Final) {
250 if (op.getKind() == ProcedureKind::Initial)
251 newOp = rewriter.create<llhd::ProcessOp>(loc, TypeRange{});
253 newOp = rewriter.create<llhd::FinalOp>(loc);
254 auto &body = newOp->getRegion(0);
255 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
257 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
258 rewriter.setInsertionPoint(returnOp);
259 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
261 rewriter.eraseOp(op);
266 auto newOp = rewriter.create<llhd::ProcessOp>(loc, TypeRange{});
271 rewriter.createBlock(&newOp.getBody());
272 auto *block = &op.getBody().front();
273 rewriter.create<cf::BranchOp>(loc, block);
274 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
275 newOp.getBody().end());
283 if (op.getKind() == ProcedureKind::AlwaysComb ||
284 op.getKind() == ProcedureKind::AlwaysLatch) {
285 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
286 rewriter.create<llhd::WaitOp>(loc, ValueRange{}, Value(), observedValues,
287 ValueRange{}, block);
294 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
295 rewriter.setInsertionPoint(returnOp);
296 rewriter.create<cf::BranchOp>(loc, block);
297 rewriter.eraseOp(returnOp);
300 rewriter.eraseOp(op);
306 using OpConversionPattern::OpConversionPattern;
309 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
310 ConversionPatternRewriter &rewriter)
const override {
344 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
350 if (op.getBody().front().empty()) {
353 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
357 auto *waitBlock = rewriter.createBlock(resumeBlock);
358 auto *checkBlock = rewriter.createBlock(resumeBlock);
360 auto loc = op.getLoc();
361 rewriter.setInsertionPoint(op);
362 rewriter.create<cf::BranchOp>(loc, waitBlock);
372 SmallVector<Value> valuesBefore;
373 rewriter.setInsertionPointToEnd(waitBlock);
374 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
375 bool allDetectsAreAnyChange =
true;
377 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
378 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
379 allDetectsAreAnyChange =
false;
380 valuesBefore.push_back(detectOp.getInput());
381 rewriter.eraseOp(detectOp);
387 SmallVector<Value> observeValues;
388 auto setInsertionPointAfterDef = [&](Value value) {
389 if (
auto *op = value.getDefiningOp())
390 rewriter.setInsertionPointAfter(op);
391 if (
auto arg = dyn_cast<BlockArgument>(value))
392 rewriter.setInsertionPointToStart(value.getParentBlock());
395 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
396 typeConverter, rewriter, observeValues);
401 auto waitOp = rewriter.create<llhd::WaitOp>(
402 loc, ValueRange{}, Value(), observeValues, ValueRange{}, checkBlock);
403 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
404 rewriter.eraseOp(clonedOp);
408 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
409 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
411 rewriter.eraseOp(op);
415 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
416 assert(before.getType() == after.getType() &&
417 "mismatched types after clone op");
418 auto beforeType = cast<IntType>(before.getType());
422 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
423 constexpr int LSB = 0;
425 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
427 rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
428 after = rewriter.create<moore::ExtractOp>(loc, beforeType, after, LSB);
431 auto intType = rewriter.getIntegerType(beforeType.getWidth());
432 before = typeConverter->materializeTargetConversion(rewriter, loc,
434 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
437 if (edge == Edge::AnyChange)
438 return rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
441 SmallVector<Value> disjuncts;
442 Value trueVal = rewriter.create<
hw::ConstantOp>(loc, APInt(1, 1));
444 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
448 rewriter.create<
comb::AndOp>(loc, notOldVal, after,
true);
449 disjuncts.push_back(posedge);
452 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
454 rewriter.create<
comb::XorOp>(loc, after, trueVal,
true);
456 rewriter.create<
comb::AndOp>(loc, before, notCurrVal,
true);
457 disjuncts.push_back(posedge);
460 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
467 SmallVector<Value> triggers;
468 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
469 if (!allDetectsAreAnyChange) {
470 if (!isa<IntType>(before.getType()))
471 return detectOp->emitError() <<
"requires int operand";
473 rewriter.setInsertionPoint(detectOp);
475 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
476 if (detectOp.getCondition()) {
477 auto condition = typeConverter->materializeTargetConversion(
478 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
479 trigger = rewriter.create<
comb::AndOp>(loc, trigger, condition,
true);
481 triggers.push_back(trigger);
484 rewriter.eraseOp(detectOp);
487 rewriter.setInsertionPointToEnd(checkBlock);
488 if (triggers.empty()) {
493 rewriter.create<cf::BranchOp>(loc, resumeBlock);
499 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
500 rewriter.create<cf::CondBranchOp>(loc, triggered, resumeBlock, waitBlock);
512 using OpConversionPattern::OpConversionPattern;
515 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
516 ConversionPatternRewriter &rewriter)
const override {
517 Location loc = op.getLoc();
518 Type resultType = typeConverter->convertType(op.getResult().getType());
520 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
523 Value init = adaptor.getInitial();
525 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
533 Value constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
537 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
538 op.getNameAttr(), init);
544 using OpConversionPattern::OpConversionPattern;
547 matchAndRewrite(NetOp op, OpAdaptor adaptor,
548 ConversionPatternRewriter &rewriter)
const override {
549 auto loc = op.getLoc();
550 if (op.getKind() != NetKind::Wire)
551 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
553 auto resultType = typeConverter->convertType(op.getResult().getType());
555 return rewriter.notifyMatchFailure(loc,
"invalid net type");
559 auto elementType = cast<hw::InOutType>(resultType).getElementType();
563 auto constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
567 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
568 op, resultType, op.getNameAttr(), init);
570 if (
auto assignedValue = adaptor.getAssignment()) {
571 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
572 llvm::StringRef(
"ns"), 0, 1);
573 auto time = rewriter.create<llhd::ConstantTimeOp>(loc, timeAttr);
574 rewriter.create<llhd::DrvOp>(loc, signal, assignedValue, time, Value{});
586 using OpConversionPattern::OpConversionPattern;
589 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
590 ConversionPatternRewriter &rewriter)
const override {
592 auto value = op.getValue().toAPInt(
false);
593 auto type = rewriter.getIntegerType(value.getBitWidth());
595 op, type, rewriter.getIntegerAttr(type, value));
601 using OpConversionPattern::OpConversionPattern;
603 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
604 ConversionPatternRewriter &rewriter)
const override {
605 const auto str = op.getValue();
606 const unsigned byteWidth = str.size() * 8;
607 const auto resultType =
608 typeConverter->convertType(op.getResult().getType());
609 if (
const auto intType = mlir::dyn_cast<IntegerType>(resultType)) {
610 if (intType.getWidth() < byteWidth) {
611 return rewriter.notifyMatchFailure(op,
612 "invalid string constant type size");
615 return rewriter.notifyMatchFailure(op,
"invalid string constant type");
617 APInt value(byteWidth, 0);
618 for (
size_t i = 0; i < str.size(); ++i) {
619 const auto asciiChar =
static_cast<uint8_t
>(str[i]);
620 value |= APInt(byteWidth, asciiChar) << (8 * (str.size() - 1 - i));
623 op, resultType, rewriter.getIntegerAttr(resultType, value));
629 using OpConversionPattern::OpConversionPattern;
631 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
632 ConversionPatternRewriter &rewriter)
const override {
633 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
639 using OpConversionPattern::OpConversionPattern;
641 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
642 ConversionPatternRewriter &rewriter)
const override {
643 Type resultType = typeConverter->convertType(op.getResult().getType());
645 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
652 using OpConversionPattern::OpConversionPattern;
655 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
656 ConversionPatternRewriter &rewriter)
const override {
659 Type resultType = typeConverter->convertType(op.getResult().getType());
660 Type inputType = adaptor.getInput().getType();
661 int32_t low = adaptor.getLowBit();
663 if (isa<IntegerType>(inputType)) {
664 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
665 int32_t resultWidth = resultType.getIntOrFloatBitWidth();
666 int32_t high = low + resultWidth;
668 SmallVector<Value> toConcat;
671 op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
673 if (low < inputWidth && high > 0) {
674 int32_t lowIdx = std::max(low, 0);
677 rewriter.getIntegerType(
678 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
679 adaptor.getInput(), lowIdx);
680 toConcat.push_back(middle);
683 int32_t diff = high - inputWidth;
687 toConcat.push_back(val);
692 rewriter.replaceOp(op,
concat);
696 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
697 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
698 int32_t inputWidth = arrTy.getNumElements();
700 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
701 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
702 if (elementWidth < 0)
705 int32_t high = low + resArrTy.getNumElements();
706 int32_t resWidth = resArrTy.getNumElements();
708 SmallVector<Value> toConcat;
712 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
715 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
717 toConcat.push_back(res);
720 if (low < inputWidth && high > 0) {
721 int32_t lowIdx = std::max(0, low);
723 op.getLoc(), rewriter.getIntegerType(width), lowIdx);
727 arrTy.getElementType(),
728 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
729 adaptor.getInput(), lowIdxVal);
730 toConcat.push_back(middle);
733 int32_t diff = high - inputWidth;
736 op.getLoc(), APInt(diff * elementWidth, 0));
738 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), diff),
740 toConcat.push_back(val);
745 rewriter.replaceOp(op,
concat);
750 if (low < 0 || low >= inputWidth) {
751 int32_t bw = hw::getBitWidth(resultType);
755 Value val = rewriter.create<
hw::ConstantOp>(op.getLoc(), APInt(bw, 0));
757 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
758 rewriter.replaceOp(op, bitcast);
763 op.getLoc(), rewriter.getIntegerType(width), adaptor.getLowBit());
764 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
773 using OpConversionPattern::OpConversionPattern;
776 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
777 ConversionPatternRewriter &rewriter)
const override {
779 Type resultType = typeConverter->convertType(op.getResult().getType());
781 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
783 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
784 int64_t width = hw::getBitWidth(inputType);
789 op.getLoc(), rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
790 adaptor.getLowBit());
791 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
792 op, resultType, adaptor.getInput(), lowBit);
796 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
799 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
800 adaptor.getLowBit());
802 if (isa<hw::ArrayType>(
803 cast<hw::InOutType>(resultType).getElementType())) {
804 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
805 op, resultType, adaptor.getInput(), lowBit);
809 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
819 using OpConversionPattern::OpConversionPattern;
822 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
823 ConversionPatternRewriter &rewriter)
const override {
824 Type resultType = typeConverter->convertType(op.getResult().getType());
825 Type inputType = adaptor.getInput().getType();
827 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
828 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
829 intType.getWidth(), op->getLoc());
830 Value value = rewriter.create<
comb::ShrUOp>(op->getLoc(),
831 adaptor.getInput(), amount);
833 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
837 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
838 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
839 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
842 if (isa<hw::ArrayType>(resultType)) {
844 adaptor.getInput(), idx);
848 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
857 using OpConversionPattern::OpConversionPattern;
860 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
861 ConversionPatternRewriter &rewriter)
const override {
863 Type resultType = typeConverter->convertType(op.getResult().getType());
865 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
867 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
868 int64_t width = hw::getBitWidth(inputType);
873 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
874 llvm::Log2_64_Ceil(width), op->getLoc());
875 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
876 op, resultType, adaptor.getInput(), amount);
880 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
881 Value idx = adjustIntegerWidth(
882 rewriter, adaptor.getLowBit(),
883 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
885 if (isa<hw::ArrayType>(
886 cast<hw::InOutType>(resultType).getElementType())) {
887 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
888 op, resultType, adaptor.getInput(), idx);
892 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
902 using OpConversionPattern::OpConversionPattern;
905 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
906 ConversionPatternRewriter &rewriter)
const override {
907 Type resultType = typeConverter->convertType(op.getResult().getType());
909 adaptor.getElements());
915 using OpConversionPattern::OpConversionPattern;
918 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
919 ConversionPatternRewriter &rewriter)
const override {
920 Type resultType = typeConverter->convertType(op.getResult().getType());
922 adaptor.getFields());
928 using OpConversionPattern::OpConversionPattern;
931 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
932 ConversionPatternRewriter &rewriter)
const override {
934 op, adaptor.getInput(), adaptor.getFieldNameAttr());
939struct StructExtractRefOpConversion
941 using OpConversionPattern::OpConversionPattern;
944 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
945 ConversionPatternRewriter &rewriter)
const override {
946 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
947 op, adaptor.getInput(), adaptor.getFieldNameAttr());
953 using OpConversionPattern::OpConversionPattern;
955 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
956 ConversionPatternRewriter &rewriter)
const override {
957 Type resultType = typeConverter->convertType(op.getInput().getType());
958 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
960 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
961 adaptor.getInput(), max);
967 using OpConversionPattern::OpConversionPattern;
969 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
970 ConversionPatternRewriter &rewriter)
const override {
971 Type resultType = typeConverter->convertType(op.getInput().getType());
972 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
974 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
975 adaptor.getInput(), zero);
981 using OpConversionPattern::OpConversionPattern;
983 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
984 ConversionPatternRewriter &rewriter)
const override {
986 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
992 using OpConversionPattern::OpConversionPattern;
994 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
995 ConversionPatternRewriter &rewriter)
const override {
996 Type resultType = typeConverter->convertType(op.getInput().getType());
997 if (isa_and_nonnull<IntegerType>(resultType)) {
998 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
999 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1000 adaptor.getInput(), zero);
1008 using OpConversionPattern::OpConversionPattern;
1010 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1011 ConversionPatternRewriter &rewriter)
const override {
1013 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1014 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
1016 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1022 using OpConversionPattern::OpConversionPattern;
1024 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1025 ConversionPatternRewriter &rewriter)
const override {
1027 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1028 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
1030 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1035template <
typename SourceOp,
typename TargetOp>
1038 using OpAdaptor =
typename SourceOp::Adaptor;
1041 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1042 ConversionPatternRewriter &rewriter)
const override {
1043 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1044 adaptor.getRhs(),
false);
1049template <
typename SourceOp, ICmpPredicate pred>
1052 using OpAdaptor =
typename SourceOp::Adaptor;
1055 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1056 ConversionPatternRewriter &rewriter)
const override {
1058 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1060 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1061 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1066template <
typename SourceOp,
bool withoutX>
1069 using OpAdaptor =
typename SourceOp::Adaptor;
1072 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1073 ConversionPatternRewriter &rewriter)
const override {
1079 unsigned bitWidth = op.getLhs().getType().getWidth();
1080 auto ignoredBits = APInt::getZero(bitWidth);
1081 auto detectIgnoredBits = [&](Value value) {
1082 auto constOp = value.getDefiningOp<ConstantOp>();
1085 auto constValue = constOp.getValue();
1087 ignoredBits |= constValue.getZBits();
1089 ignoredBits |= constValue.getUnknownBits();
1091 detectIgnoredBits(op.getLhs());
1092 detectIgnoredBits(op.getRhs());
1096 Value lhs = adaptor.getLhs();
1097 Value rhs = adaptor.getRhs();
1098 if (!ignoredBits.isZero()) {
1099 ignoredBits.flipAllBits();
1100 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
1101 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1102 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1105 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1115 using OpConversionPattern::OpConversionPattern;
1118 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1119 ConversionPatternRewriter &rewriter)
const override {
1120 Location loc = op.getLoc();
1121 Type resultType = typeConverter->convertType(op.getResult().getType());
1122 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1123 int64_t resultBw = hw::getBitWidth(resultType);
1124 if (inputBw == -1 || resultBw == -1)
1128 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1129 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1132 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1133 rewriter.replaceOp(op, result);
1139 using OpConversionPattern::OpConversionPattern;
1142 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1143 ConversionPatternRewriter &rewriter)
const override {
1144 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1145 op.getType().getWidth());
1151 using OpConversionPattern::OpConversionPattern;
1154 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1155 ConversionPatternRewriter &rewriter)
const override {
1156 auto targetWidth = op.getType().getWidth();
1157 auto inputWidth = op.getInput().getType().getWidth();
1160 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1163 op, ValueRange{zeroExt, adaptor.getInput()});
1169 using OpConversionPattern::OpConversionPattern;
1172 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1173 ConversionPatternRewriter &rewriter)
const override {
1174 auto type = typeConverter->convertType(op.getType());
1176 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1177 rewriter.replaceOp(op, value);
1187 using OpConversionPattern::OpConversionPattern;
1190 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1191 ConversionPatternRewriter &rewriter)
const override {
1192 SmallVector<Type> convResTypes;
1193 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1196 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1197 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1198 adaptor.getOperands(), op.getArgNames(),
1199 op.getResultNames(),
1200 rewriter.getArrayAttr({}),
nullptr);
1207 using OpConversionPattern::OpConversionPattern;
1210 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1211 ConversionPatternRewriter &rewriter)
const override {
1212 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1218 using OpConversionPattern::OpConversionPattern;
1221 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1222 ConversionPatternRewriter &rewriter)
const override {
1223 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1224 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1225 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
1231 using OpConversionPattern::OpConversionPattern;
1234 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1235 ConversionPatternRewriter &rewriter)
const override {
1236 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1237 adaptor.getDestOperands());
1243 using OpConversionPattern::OpConversionPattern;
1246 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1247 ConversionPatternRewriter &rewriter)
const override {
1248 SmallVector<Type> convResTypes;
1249 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1251 rewriter.replaceOpWithNewOp<func::CallOp>(
1252 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1257struct UnrealizedConversionCastConversion
1259 using OpConversionPattern::OpConversionPattern;
1262 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1263 ConversionPatternRewriter &rewriter)
const override {
1264 SmallVector<Type> convResTypes;
1265 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1270 if (convResTypes == adaptor.getOperands().getTypes()) {
1271 rewriter.replaceOp(op, adaptor.getOperands());
1275 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1276 op, convResTypes, adaptor.getOperands());
1282 using OpConversionPattern::OpConversionPattern;
1285 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1286 ConversionPatternRewriter &rewriter)
const override {
1287 Type resultType = typeConverter->convertType(op.getResult().getType());
1291 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1292 resultType.getIntOrFloatBitWidth(), op->getLoc());
1293 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1300 using OpConversionPattern::OpConversionPattern;
1303 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1304 ConversionPatternRewriter &rewriter)
const override {
1305 Type resultType = typeConverter->convertType(op.getResult().getType());
1309 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1310 resultType.getIntOrFloatBitWidth(), op->getLoc());
1312 op, resultType, adaptor.getValue(), amount,
false);
1318 using OpConversionPattern::OpConversionPattern;
1321 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1322 ConversionPatternRewriter &rewriter)
const override {
1323 Type resultType = typeConverter->convertType(op.getResult().getType());
1325 Location loc = op.getLoc();
1326 auto intType = cast<IntType>(op.getRhs().getType());
1329 Type integerType = rewriter.getIntegerType(intType.getWidth());
1330 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1332 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1333 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1336 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1338 auto forOp = rewriter.create<scf::ForOp>(
1339 loc, lowerBound, upperBound, step, ValueRange(initVal),
1340 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1341 Value loopVar = iterArgs.front();
1343 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1346 rewriter.replaceOp(op, forOp.getResult(0));
1353 using OpConversionPattern::OpConversionPattern;
1356 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1357 ConversionPatternRewriter &rewriter)
const override {
1358 Type resultType = typeConverter->convertType(op.getResult().getType());
1360 Location loc = op.getLoc();
1361 auto intType = cast<IntType>(op.getRhs().getType());
1363 Type integerType = rewriter.getIntegerType(intType.getWidth());
1364 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1365 Value rhsVal = rewriter.create<ConversionOp>(loc, integerType, op.getRhs());
1366 Value constZero = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1368 Value isNegative = rewriter.
create<comb::ICmpOp>(loc, ICmpPredicate::slt,
1373 rewriter.create<
comb::MuxOp>(loc, isNegative, constZeroResult, lhsVal);
1375 rewriter.create<
comb::MuxOp>(loc, isNegative, constZero, rhsVal);
1377 Value lowerBound = constZero;
1378 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1381 auto forOp = rewriter.
create<scf::ForOp>(
1382 loc, lowerBound, upperBound, step, ValueRange(initVal),
1383 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1384 auto loopVar = iterArgs.front();
1386 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1389 rewriter.replaceOp(op, forOp.getResult(0));
1396 using OpConversionPattern::OpConversionPattern;
1399 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1400 ConversionPatternRewriter &rewriter)
const override {
1401 Type resultType = typeConverter->convertType(op.getResult().getType());
1405 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1406 resultType.getIntOrFloatBitWidth(), op->getLoc());
1408 op, resultType, adaptor.getValue(), amount,
false);
1414 using OpConversionPattern::OpConversionPattern;
1417 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1418 ConversionPatternRewriter &rewriter)
const override {
1419 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1424struct AssignedVariableOpConversion
1426 using OpConversionPattern::OpConversionPattern;
1429 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1430 ConversionPatternRewriter &rewriter)
const override {
1431 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1432 adaptor.getNameAttr());
1437template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1440 using OpAdaptor =
typename OpTy::Adaptor;
1443 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1444 ConversionPatternRewriter &rewriter)
const override {
1447 auto timeAttr = llhd::TimeAttr::get(
1448 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1449 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1450 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1451 adaptor.getSrc(), time, Value{});
1457 using OpConversionPattern::OpConversionPattern;
1460 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1461 ConversionPatternRewriter &rewriter)
const override {
1466 auto type = typeConverter->convertType(op.getType());
1468 auto hasNoWriteEffect = [](Region ®ion) {
1469 auto result = region.walk([](Operation *operation) {
1470 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1471 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1472 !memOp.hasEffect<MemoryEffects::Free>())
1473 return WalkResult::advance();
1475 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1476 return WalkResult::advance();
1478 return WalkResult::interrupt();
1480 return !result.wasInterrupted();
1483 if (hasNoWriteEffect(op.getTrueRegion()) &&
1484 hasNoWriteEffect(op.getFalseRegion())) {
1485 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1486 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1488 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1489 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1491 Value convTrueVal = typeConverter->materializeTargetConversion(
1492 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1493 Value convFalseVal = typeConverter->materializeTargetConversion(
1494 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1496 rewriter.eraseOp(trueTerm);
1497 rewriter.eraseOp(falseTerm);
1499 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1500 convTrueVal, convFalseVal);
1505 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1506 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1507 ifOp.getThenRegion().end());
1508 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1509 ifOp.getElseRegion().end());
1510 rewriter.replaceOp(op, ifOp);
1516 using OpConversionPattern::OpConversionPattern;
1519 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1520 ConversionPatternRewriter &rewriter)
const override {
1521 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1526template <
typename SourceOp>
1529 using OpAdaptor =
typename SourceOp::Adaptor;
1532 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1533 ConversionPatternRewriter &rewriter)
const override {
1534 rewriter.modifyOpInPlace(op,
1535 [&]() { op->setOperands(adaptor.getOperands()); });
1540template <
typename MooreOpTy,
typename VerifOpTy>
1543 using OpAdaptor =
typename MooreOpTy::Adaptor;
1546 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1547 ConversionPatternRewriter &rewriter)
const override {
1549 op.getLabel().has_value()
1550 ? StringAttr::get(op->getContext(), op.getLabel().value())
1551 : StringAttr::
get(op->getContext());
1552 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1563 using OpConversionPattern::OpConversionPattern;
1566 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1567 ConversionPatternRewriter &rewriter)
const override {
1568 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1574 using OpConversionPattern::OpConversionPattern;
1577 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1578 ConversionPatternRewriter &rewriter)
const override {
1579 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1580 adaptor.getInputs());
1586 using OpConversionPattern::OpConversionPattern;
1589 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1590 ConversionPatternRewriter &rewriter)
const override {
1592 switch (op.getFormat()) {
1593 case IntFormat::Decimal:
1594 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1596 case IntFormat::Binary:
1597 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1599 case IntFormat::HexLower:
1600 case IntFormat::HexUpper:
1601 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1604 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1610 using OpConversionPattern::OpConversionPattern;
1613 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1614 ConversionPatternRewriter &rewriter)
const override {
1615 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1616 op, adaptor.getMessage());
1628 const TypeConverter &converter) {
1629 target.addIllegalDialect<MooreDialect>();
1630 target.addLegalDialect<comb::CombDialect>();
1631 target.addLegalDialect<hw::HWDialect>();
1632 target.addLegalDialect<llhd::LLHDDialect>();
1633 target.addLegalDialect<mlir::BuiltinDialect>();
1634 target.addLegalDialect<sim::SimDialect>();
1635 target.addLegalDialect<verif::VerifDialect>();
1637 target.addLegalOp<debug::ScopeOp>();
1639 target.addDynamicallyLegalOp<
1640 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1641 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1642 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1643 [&](Operation *op) {
return converter.isLegal(op); });
1645 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1646 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1647 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1650 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1651 return converter.isSignatureLegal(op.getFunctionType()) &&
1652 converter.isLegal(&op.getFunctionBody());
1656 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1657 converter.isLegal(&op.getBody());
1662 typeConverter.addConversion([&](IntType type) {
1663 return IntegerType::get(type.getContext(), type.getWidth());
1666 typeConverter.addConversion([&](FormatStringType type) {
1667 return sim::FormatStringType::get(type.getContext());
1670 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1671 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1672 return hw::ArrayType::get(
elementType, type.getSize());
1679 typeConverter.addConversion(
1680 [&](UnpackedArrayType type) -> std::optional<Type> {
1681 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1682 return hw::ArrayType::get(
elementType, type.getSize());
1686 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1687 SmallVector<hw::StructType::FieldInfo> fields;
1688 for (
auto field : type.getMembers()) {
1689 hw::StructType::FieldInfo info;
1690 info.type = typeConverter.convertType(field.type);
1693 info.name = field.name;
1694 fields.push_back(info);
1696 return hw::StructType::get(type.getContext(), fields);
1704 typeConverter.addConversion(
1705 [&](UnpackedStructType type) -> std::optional<Type> {
1706 SmallVector<hw::StructType::FieldInfo> fields;
1707 for (
auto field : type.getMembers()) {
1708 hw::StructType::FieldInfo info;
1709 info.type = typeConverter.convertType(field.type);
1712 info.name = field.name;
1713 fields.push_back(info);
1715 return hw::StructType::get(type.getContext(), fields);
1718 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1719 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1720 return hw::InOutType::get(innerType);
1725 typeConverter.addConversion([](IntegerType type) {
return type; });
1726 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1727 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1728 typeConverter.addConversion([](debug::StructType type) {
return type; });
1730 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1731 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1732 return hw::InOutType::get(innerType);
1736 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1737 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1738 return hw::ArrayType::get(
elementType, type.getNumElements());
1742 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1743 SmallVector<hw::StructType::FieldInfo> fields;
1744 for (
auto field : type.getElements()) {
1745 hw::StructType::FieldInfo info;
1746 info.type = typeConverter.convertType(field.type);
1749 info.name = field.name;
1750 fields.push_back(info);
1752 return hw::StructType::get(type.getContext(), fields);
1755 typeConverter.addTargetMaterialization(
1756 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1757 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1758 if (inputs.size() != 1 || !inputs[0])
1761 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1765 typeConverter.addSourceMaterialization(
1766 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1767 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1768 if (inputs.size() != 1)
1771 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1777 TypeConverter &typeConverter) {
1778 auto *context =
patterns.getContext();
1782 VariableOpConversion,
1786 ConversionOpConversion,
1792 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1793 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1795 StructExtractOpConversion, StructExtractRefOpConversion,
1796 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion, ArrayCreateOpConversion,
1797 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1800 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1801 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1804 BinaryOpConversion<AddOp, comb::AddOp>,
1805 BinaryOpConversion<SubOp, comb::SubOp>,
1806 BinaryOpConversion<MulOp, comb::MulOp>,
1807 BinaryOpConversion<DivUOp, comb::DivUOp>,
1808 BinaryOpConversion<DivSOp, comb::DivSOp>,
1809 BinaryOpConversion<ModUOp, comb::ModUOp>,
1810 BinaryOpConversion<ModSOp, comb::ModSOp>,
1811 BinaryOpConversion<AndOp, comb::AndOp>,
1812 BinaryOpConversion<OrOp, comb::OrOp>,
1813 BinaryOpConversion<XorOp, comb::XorOp>,
1816 PowUOpConversion, PowSOpConversion,
1819 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1820 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1821 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1822 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1823 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1824 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1825 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1826 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1827 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1828 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1829 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1830 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1831 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1832 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1833 CaseXZEqOpConversion<CaseZEqOp, true>,
1834 CaseXZEqOpConversion<CaseXZEqOp, false>,
1837 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1840 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1843 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1844 AssignOpConversion<BlockingAssignOp, 0, 1>,
1845 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1846 AssignedVariableOpConversion,
1849 CondBranchOpConversion, BranchOpConversion,
1852 HWInstanceOpConversion, ReturnOpConversion,
1853 CallOpConversion, UnrealizedConversionCastConversion,
1854 InPlaceOpConversion<debug::ArrayOp>,
1855 InPlaceOpConversion<debug::StructOp>,
1856 InPlaceOpConversion<debug::VariableOp>,
1859 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1860 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1861 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1864 FormatLiteralOpConversion,
1865 FormatConcatOpConversion,
1866 FormatIntOpConversion,
1867 DisplayBIOpConversion
1868 >(typeConverter, context);
1871 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1873 hw::populateHWModuleLikeTypeConversionPattern(
1874 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1875 populateSCFToControlFlowConversionPatterns(
patterns);
1884struct MooreToCorePass
1885 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1886 void runOnOperation()
override;
1892 return std::make_unique<MooreToCorePass>();
1896void MooreToCorePass::runOnOperation() {
1897 MLIRContext &context = getContext();
1898 ModuleOp
module = getOperation();
1900 IRRewriter rewriter(module);
1901 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1903 ConversionTarget target(context);
1904 TypeConverter typeConverter;
1905 RewritePatternSet
patterns(&context);
1910 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1911 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.