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(StructCreateOp op, OpAdaptor adaptor,
906 ConversionPatternRewriter &rewriter)
const override {
907 Type resultType = typeConverter->convertType(op.getResult().getType());
909 adaptor.getFields());
915 using OpConversionPattern::OpConversionPattern;
918 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
919 ConversionPatternRewriter &rewriter)
const override {
921 op, adaptor.getInput(), adaptor.getFieldNameAttr());
926struct StructExtractRefOpConversion
928 using OpConversionPattern::OpConversionPattern;
931 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
932 ConversionPatternRewriter &rewriter)
const override {
933 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
934 op, adaptor.getInput(), adaptor.getFieldNameAttr());
940 using OpConversionPattern::OpConversionPattern;
942 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
943 ConversionPatternRewriter &rewriter)
const override {
944 Type resultType = typeConverter->convertType(op.getInput().getType());
945 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
947 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
948 adaptor.getInput(), max);
954 using OpConversionPattern::OpConversionPattern;
956 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
957 ConversionPatternRewriter &rewriter)
const override {
958 Type resultType = typeConverter->convertType(op.getInput().getType());
959 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
961 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
962 adaptor.getInput(), zero);
968 using OpConversionPattern::OpConversionPattern;
970 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
971 ConversionPatternRewriter &rewriter)
const override {
973 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
979 using OpConversionPattern::OpConversionPattern;
981 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
982 ConversionPatternRewriter &rewriter)
const override {
983 Type resultType = typeConverter->convertType(op.getInput().getType());
984 if (isa_and_nonnull<IntegerType>(resultType)) {
985 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
986 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
987 adaptor.getInput(), zero);
995 using OpConversionPattern::OpConversionPattern;
997 matchAndRewrite(NotOp op, OpAdaptor adaptor,
998 ConversionPatternRewriter &rewriter)
const override {
1000 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1001 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
1003 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1009 using OpConversionPattern::OpConversionPattern;
1011 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1012 ConversionPatternRewriter &rewriter)
const override {
1014 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1015 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
1017 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1022template <
typename SourceOp,
typename TargetOp>
1025 using OpAdaptor =
typename SourceOp::Adaptor;
1028 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1029 ConversionPatternRewriter &rewriter)
const override {
1030 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1031 adaptor.getRhs(),
false);
1036template <
typename SourceOp, ICmpPredicate pred>
1039 using OpAdaptor =
typename SourceOp::Adaptor;
1042 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1043 ConversionPatternRewriter &rewriter)
const override {
1045 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1047 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1048 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1053template <
typename SourceOp,
bool withoutX>
1056 using OpAdaptor =
typename SourceOp::Adaptor;
1059 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1060 ConversionPatternRewriter &rewriter)
const override {
1066 unsigned bitWidth = op.getLhs().getType().getWidth();
1067 auto ignoredBits = APInt::getZero(bitWidth);
1068 auto detectIgnoredBits = [&](Value value) {
1069 auto constOp = value.getDefiningOp<ConstantOp>();
1072 auto constValue = constOp.getValue();
1074 ignoredBits |= constValue.getZBits();
1076 ignoredBits |= constValue.getUnknownBits();
1078 detectIgnoredBits(op.getLhs());
1079 detectIgnoredBits(op.getRhs());
1083 Value lhs = adaptor.getLhs();
1084 Value rhs = adaptor.getRhs();
1085 if (!ignoredBits.isZero()) {
1086 ignoredBits.flipAllBits();
1087 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
1088 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1089 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1092 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1102 using OpConversionPattern::OpConversionPattern;
1105 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1106 ConversionPatternRewriter &rewriter)
const override {
1107 Location loc = op.getLoc();
1108 Type resultType = typeConverter->convertType(op.getResult().getType());
1109 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1110 int64_t resultBw = hw::getBitWidth(resultType);
1111 if (inputBw == -1 || resultBw == -1)
1115 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1116 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1119 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1120 rewriter.replaceOp(op, result);
1126 using OpConversionPattern::OpConversionPattern;
1129 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1130 ConversionPatternRewriter &rewriter)
const override {
1131 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1132 op.getType().getWidth());
1138 using OpConversionPattern::OpConversionPattern;
1141 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1142 ConversionPatternRewriter &rewriter)
const override {
1143 auto targetWidth = op.getType().getWidth();
1144 auto inputWidth = op.getInput().getType().getWidth();
1147 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1150 op, ValueRange{zeroExt, adaptor.getInput()});
1156 using OpConversionPattern::OpConversionPattern;
1159 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1160 ConversionPatternRewriter &rewriter)
const override {
1161 auto type = typeConverter->convertType(op.getType());
1163 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1164 rewriter.replaceOp(op, value);
1174 using OpConversionPattern::OpConversionPattern;
1177 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1178 ConversionPatternRewriter &rewriter)
const override {
1179 SmallVector<Type> convResTypes;
1180 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1183 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1184 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1185 adaptor.getOperands(), op.getArgNames(),
1186 op.getResultNames(),
1187 rewriter.getArrayAttr({}),
nullptr);
1194 using OpConversionPattern::OpConversionPattern;
1197 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1198 ConversionPatternRewriter &rewriter)
const override {
1199 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1205 using OpConversionPattern::OpConversionPattern;
1208 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1209 ConversionPatternRewriter &rewriter)
const override {
1210 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1211 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1212 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
1218 using OpConversionPattern::OpConversionPattern;
1221 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1222 ConversionPatternRewriter &rewriter)
const override {
1223 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1224 adaptor.getDestOperands());
1230 using OpConversionPattern::OpConversionPattern;
1233 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1234 ConversionPatternRewriter &rewriter)
const override {
1235 SmallVector<Type> convResTypes;
1236 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1238 rewriter.replaceOpWithNewOp<func::CallOp>(
1239 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1244struct UnrealizedConversionCastConversion
1246 using OpConversionPattern::OpConversionPattern;
1249 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1250 ConversionPatternRewriter &rewriter)
const override {
1251 SmallVector<Type> convResTypes;
1252 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1257 if (convResTypes == adaptor.getOperands().getTypes()) {
1258 rewriter.replaceOp(op, adaptor.getOperands());
1262 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1263 op, convResTypes, adaptor.getOperands());
1269 using OpConversionPattern::OpConversionPattern;
1272 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1273 ConversionPatternRewriter &rewriter)
const override {
1274 Type resultType = typeConverter->convertType(op.getResult().getType());
1278 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1279 resultType.getIntOrFloatBitWidth(), op->getLoc());
1280 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1287 using OpConversionPattern::OpConversionPattern;
1290 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1291 ConversionPatternRewriter &rewriter)
const override {
1292 Type resultType = typeConverter->convertType(op.getResult().getType());
1296 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1297 resultType.getIntOrFloatBitWidth(), op->getLoc());
1299 op, resultType, adaptor.getValue(), amount,
false);
1305 using OpConversionPattern::OpConversionPattern;
1308 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1309 ConversionPatternRewriter &rewriter)
const override {
1310 Type resultType = typeConverter->convertType(op.getResult().getType());
1312 Location loc = op.getLoc();
1313 auto intType = cast<IntType>(op.getRhs().getType());
1316 Type integerType = rewriter.getIntegerType(intType.getWidth());
1317 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1319 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1320 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1323 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1325 auto forOp = rewriter.create<scf::ForOp>(
1326 loc, lowerBound, upperBound, step, ValueRange(initVal),
1327 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1328 Value loopVar = iterArgs.front();
1330 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1333 rewriter.replaceOp(op, forOp.getResult(0));
1340 using OpConversionPattern::OpConversionPattern;
1343 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1344 ConversionPatternRewriter &rewriter)
const override {
1345 Type resultType = typeConverter->convertType(op.getResult().getType());
1347 Location loc = op.getLoc();
1348 auto intType = cast<IntType>(op.getRhs().getType());
1350 Type integerType = rewriter.getIntegerType(intType.getWidth());
1351 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1352 Value rhsVal = rewriter.create<ConversionOp>(loc, integerType, op.getRhs());
1353 Value constZero = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1355 Value isNegative = rewriter.
create<comb::ICmpOp>(loc, ICmpPredicate::slt,
1360 rewriter.create<
comb::MuxOp>(loc, isNegative, constZeroResult, lhsVal);
1362 rewriter.create<
comb::MuxOp>(loc, isNegative, constZero, rhsVal);
1364 Value lowerBound = constZero;
1365 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1368 auto forOp = rewriter.
create<scf::ForOp>(
1369 loc, lowerBound, upperBound, step, ValueRange(initVal),
1370 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1371 auto loopVar = iterArgs.front();
1373 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1376 rewriter.replaceOp(op, forOp.getResult(0));
1383 using OpConversionPattern::OpConversionPattern;
1386 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1387 ConversionPatternRewriter &rewriter)
const override {
1388 Type resultType = typeConverter->convertType(op.getResult().getType());
1392 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1393 resultType.getIntOrFloatBitWidth(), op->getLoc());
1395 op, resultType, adaptor.getValue(), amount,
false);
1401 using OpConversionPattern::OpConversionPattern;
1404 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1405 ConversionPatternRewriter &rewriter)
const override {
1406 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1411struct AssignedVariableOpConversion
1413 using OpConversionPattern::OpConversionPattern;
1416 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1417 ConversionPatternRewriter &rewriter)
const override {
1418 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1419 adaptor.getNameAttr());
1424template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1427 using OpAdaptor =
typename OpTy::Adaptor;
1430 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1431 ConversionPatternRewriter &rewriter)
const override {
1434 auto timeAttr = llhd::TimeAttr::get(
1435 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1436 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1437 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1438 adaptor.getSrc(), time, Value{});
1444 using OpConversionPattern::OpConversionPattern;
1447 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1448 ConversionPatternRewriter &rewriter)
const override {
1453 auto type = typeConverter->convertType(op.getType());
1455 auto hasNoWriteEffect = [](Region ®ion) {
1456 auto result = region.walk([](Operation *operation) {
1457 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1458 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1459 !memOp.hasEffect<MemoryEffects::Free>())
1460 return WalkResult::advance();
1462 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1463 return WalkResult::advance();
1465 return WalkResult::interrupt();
1467 return !result.wasInterrupted();
1470 if (hasNoWriteEffect(op.getTrueRegion()) &&
1471 hasNoWriteEffect(op.getFalseRegion())) {
1472 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1473 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1475 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1476 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1478 Value convTrueVal = typeConverter->materializeTargetConversion(
1479 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1480 Value convFalseVal = typeConverter->materializeTargetConversion(
1481 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1483 rewriter.eraseOp(trueTerm);
1484 rewriter.eraseOp(falseTerm);
1486 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1487 convTrueVal, convFalseVal);
1492 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1493 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1494 ifOp.getThenRegion().end());
1495 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1496 ifOp.getElseRegion().end());
1497 rewriter.replaceOp(op, ifOp);
1503 using OpConversionPattern::OpConversionPattern;
1506 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1507 ConversionPatternRewriter &rewriter)
const override {
1508 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1513template <
typename SourceOp>
1516 using OpAdaptor =
typename SourceOp::Adaptor;
1519 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1520 ConversionPatternRewriter &rewriter)
const override {
1521 rewriter.modifyOpInPlace(op,
1522 [&]() { op->setOperands(adaptor.getOperands()); });
1527template <
typename MooreOpTy,
typename VerifOpTy>
1530 using OpAdaptor =
typename MooreOpTy::Adaptor;
1533 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1534 ConversionPatternRewriter &rewriter)
const override {
1536 op.getLabel().has_value()
1537 ? StringAttr::get(op->getContext(), op.getLabel().value())
1538 : StringAttr::
get(op->getContext());
1539 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1550 using OpConversionPattern::OpConversionPattern;
1553 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1554 ConversionPatternRewriter &rewriter)
const override {
1555 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1561 using OpConversionPattern::OpConversionPattern;
1564 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1565 ConversionPatternRewriter &rewriter)
const override {
1566 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1567 adaptor.getInputs());
1573 using OpConversionPattern::OpConversionPattern;
1576 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1577 ConversionPatternRewriter &rewriter)
const override {
1579 switch (op.getFormat()) {
1580 case IntFormat::Decimal:
1581 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1583 case IntFormat::Binary:
1584 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1586 case IntFormat::HexLower:
1587 case IntFormat::HexUpper:
1588 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1591 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1597 using OpConversionPattern::OpConversionPattern;
1600 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1601 ConversionPatternRewriter &rewriter)
const override {
1602 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1603 op, adaptor.getMessage());
1615 const TypeConverter &converter) {
1616 target.addIllegalDialect<MooreDialect>();
1617 target.addLegalDialect<comb::CombDialect>();
1618 target.addLegalDialect<hw::HWDialect>();
1619 target.addLegalDialect<llhd::LLHDDialect>();
1620 target.addLegalDialect<mlir::BuiltinDialect>();
1621 target.addLegalDialect<sim::SimDialect>();
1622 target.addLegalDialect<verif::VerifDialect>();
1624 target.addLegalOp<debug::ScopeOp>();
1626 target.addDynamicallyLegalOp<
1627 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1628 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1629 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1630 [&](Operation *op) {
return converter.isLegal(op); });
1632 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1633 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1634 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1637 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1638 return converter.isSignatureLegal(op.getFunctionType()) &&
1639 converter.isLegal(&op.getFunctionBody());
1643 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1644 converter.isLegal(&op.getBody());
1649 typeConverter.addConversion([&](IntType type) {
1650 return IntegerType::get(type.getContext(), type.getWidth());
1653 typeConverter.addConversion([&](FormatStringType type) {
1654 return sim::FormatStringType::get(type.getContext());
1657 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1658 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1659 return hw::ArrayType::get(
elementType, type.getSize());
1666 typeConverter.addConversion(
1667 [&](UnpackedArrayType type) -> std::optional<Type> {
1668 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1669 return hw::ArrayType::get(
elementType, type.getSize());
1673 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1674 SmallVector<hw::StructType::FieldInfo> fields;
1675 for (
auto field : type.getMembers()) {
1676 hw::StructType::FieldInfo info;
1677 info.type = typeConverter.convertType(field.type);
1680 info.name = field.name;
1681 fields.push_back(info);
1683 return hw::StructType::get(type.getContext(), fields);
1691 typeConverter.addConversion(
1692 [&](UnpackedStructType type) -> std::optional<Type> {
1693 SmallVector<hw::StructType::FieldInfo> fields;
1694 for (
auto field : type.getMembers()) {
1695 hw::StructType::FieldInfo info;
1696 info.type = typeConverter.convertType(field.type);
1699 info.name = field.name;
1700 fields.push_back(info);
1702 return hw::StructType::get(type.getContext(), fields);
1705 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1706 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1707 return hw::InOutType::get(innerType);
1712 typeConverter.addConversion([](IntegerType type) {
return type; });
1713 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1714 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1715 typeConverter.addConversion([](debug::StructType type) {
return type; });
1717 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1718 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1719 return hw::InOutType::get(innerType);
1723 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1724 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1725 return hw::ArrayType::get(
elementType, type.getNumElements());
1729 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1730 SmallVector<hw::StructType::FieldInfo> fields;
1731 for (
auto field : type.getElements()) {
1732 hw::StructType::FieldInfo info;
1733 info.type = typeConverter.convertType(field.type);
1736 info.name = field.name;
1737 fields.push_back(info);
1739 return hw::StructType::get(type.getContext(), fields);
1742 typeConverter.addTargetMaterialization(
1743 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1744 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1745 if (inputs.size() != 1 || !inputs[0])
1748 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1752 typeConverter.addSourceMaterialization(
1753 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1754 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1755 if (inputs.size() != 1)
1758 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1764 TypeConverter &typeConverter) {
1765 auto *context =
patterns.getContext();
1769 VariableOpConversion,
1773 ConversionOpConversion,
1779 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1780 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1782 StructExtractOpConversion, StructExtractRefOpConversion,
1783 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion,
1784 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1787 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1788 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1791 BinaryOpConversion<AddOp, comb::AddOp>,
1792 BinaryOpConversion<SubOp, comb::SubOp>,
1793 BinaryOpConversion<MulOp, comb::MulOp>,
1794 BinaryOpConversion<DivUOp, comb::DivUOp>,
1795 BinaryOpConversion<DivSOp, comb::DivSOp>,
1796 BinaryOpConversion<ModUOp, comb::ModUOp>,
1797 BinaryOpConversion<ModSOp, comb::ModSOp>,
1798 BinaryOpConversion<AndOp, comb::AndOp>,
1799 BinaryOpConversion<OrOp, comb::OrOp>,
1800 BinaryOpConversion<XorOp, comb::XorOp>,
1803 PowUOpConversion, PowSOpConversion,
1806 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1807 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1808 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1809 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1810 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1811 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1812 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1813 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1814 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1815 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1816 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1817 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1818 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1819 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1820 CaseXZEqOpConversion<CaseZEqOp, true>,
1821 CaseXZEqOpConversion<CaseXZEqOp, false>,
1824 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1827 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1830 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1831 AssignOpConversion<BlockingAssignOp, 0, 1>,
1832 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1833 AssignedVariableOpConversion,
1836 CondBranchOpConversion, BranchOpConversion,
1839 HWInstanceOpConversion, ReturnOpConversion,
1840 CallOpConversion, UnrealizedConversionCastConversion,
1841 InPlaceOpConversion<debug::ArrayOp>,
1842 InPlaceOpConversion<debug::StructOp>,
1843 InPlaceOpConversion<debug::VariableOp>,
1846 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1847 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1848 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1851 FormatLiteralOpConversion,
1852 FormatConcatOpConversion,
1853 FormatIntOpConversion,
1854 DisplayBIOpConversion
1855 >(typeConverter, context);
1858 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1860 hw::populateHWModuleLikeTypeConversionPattern(
1861 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1862 populateSCFToControlFlowConversionPatterns(
patterns);
1871struct MooreToCorePass
1872 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1873 void runOnOperation()
override;
1879 return std::make_unique<MooreToCorePass>();
1883void MooreToCorePass::runOnOperation() {
1884 MLIRContext &context = getContext();
1885 ModuleOp
module = getOperation();
1887 IRRewriter rewriter(module);
1888 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1890 ConversionTarget target(context);
1891 TypeConverter typeConverter;
1892 RewritePatternSet
patterns(&context);
1897 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1898 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.