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);
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);
261 rewriter.eraseOp(op);
266 auto newOp = rewriter.create<llhd::ProcessOp>(loc);
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, observedValues, Value(), ValueRange{},
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));
345 auto *waitBlock = rewriter.createBlock(resumeBlock);
346 auto *checkBlock = rewriter.createBlock(resumeBlock);
348 auto loc = op.getLoc();
349 rewriter.setInsertionPoint(op);
350 rewriter.create<cf::BranchOp>(loc, waitBlock);
360 SmallVector<Value> valuesBefore;
361 rewriter.setInsertionPointToEnd(waitBlock);
362 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
363 bool allDetectsAreAnyChange =
true;
365 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
366 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
367 allDetectsAreAnyChange =
false;
368 valuesBefore.push_back(detectOp.getInput());
369 rewriter.eraseOp(detectOp);
375 SmallVector<Value> observeValues;
376 auto setInsertionPointAfterDef = [&](Value value) {
377 if (
auto *op = value.getDefiningOp())
378 rewriter.setInsertionPointAfter(op);
379 if (
auto arg = dyn_cast<BlockArgument>(value))
380 rewriter.setInsertionPointToStart(value.getParentBlock());
383 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
384 typeConverter, rewriter, observeValues);
389 auto waitOp = rewriter.create<llhd::WaitOp>(loc, observeValues, Value(),
390 ValueRange{}, checkBlock);
391 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
392 rewriter.eraseOp(clonedOp);
396 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
397 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
399 rewriter.eraseOp(op);
403 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
404 assert(before.getType() == after.getType() &&
405 "mismatched types after clone op");
406 auto beforeType = cast<IntType>(before.getType());
410 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
411 constexpr int LSB = 0;
413 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
415 rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
416 after = rewriter.create<moore::ExtractOp>(loc, beforeType, after, LSB);
419 auto intType = rewriter.getIntegerType(beforeType.getWidth());
420 before = typeConverter->materializeTargetConversion(rewriter, loc,
422 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
425 if (edge == Edge::AnyChange)
426 return rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
429 SmallVector<Value> disjuncts;
430 Value trueVal = rewriter.create<
hw::ConstantOp>(loc, APInt(1, 1));
432 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
436 rewriter.create<
comb::AndOp>(loc, notOldVal, after,
true);
437 disjuncts.push_back(posedge);
440 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
442 rewriter.create<
comb::XorOp>(loc, after, trueVal,
true);
444 rewriter.create<
comb::AndOp>(loc, before, notCurrVal,
true);
445 disjuncts.push_back(posedge);
448 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
455 SmallVector<Value> triggers;
456 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
457 if (!allDetectsAreAnyChange) {
458 if (!isa<IntType>(before.getType()))
459 return detectOp->emitError() <<
"requires int operand";
461 rewriter.setInsertionPoint(detectOp);
463 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
464 if (detectOp.getCondition()) {
465 auto condition = typeConverter->materializeTargetConversion(
466 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
467 trigger = rewriter.create<
comb::AndOp>(loc, trigger, condition,
true);
469 triggers.push_back(trigger);
472 rewriter.eraseOp(detectOp);
475 rewriter.setInsertionPointToEnd(checkBlock);
476 if (triggers.empty()) {
481 rewriter.create<cf::BranchOp>(loc, resumeBlock);
487 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
488 rewriter.create<cf::CondBranchOp>(loc, triggered, resumeBlock, waitBlock);
500 using OpConversionPattern::OpConversionPattern;
503 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
504 ConversionPatternRewriter &rewriter)
const override {
505 Location loc = op.getLoc();
506 Type resultType = typeConverter->convertType(op.getResult().getType());
508 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
511 Value init = adaptor.getInitial();
513 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
521 Value constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
525 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
526 op.getNameAttr(), init);
532 using OpConversionPattern::OpConversionPattern;
535 matchAndRewrite(NetOp op, OpAdaptor adaptor,
536 ConversionPatternRewriter &rewriter)
const override {
537 auto loc = op.getLoc();
538 if (op.getKind() != NetKind::Wire)
539 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
541 auto resultType = typeConverter->convertType(op.getResult().getType());
543 return rewriter.notifyMatchFailure(loc,
"invalid net type");
547 auto elementType = cast<hw::InOutType>(resultType).getElementType();
551 auto constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
555 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
556 op, resultType, op.getNameAttr(), init);
558 if (
auto assignedValue = adaptor.getAssignment()) {
559 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
560 llvm::StringRef(
"ns"), 0, 1);
561 auto time = rewriter.create<llhd::ConstantTimeOp>(loc, timeAttr);
562 rewriter.create<llhd::DrvOp>(loc, signal, assignedValue, time, Value{});
574 using OpConversionPattern::OpConversionPattern;
577 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
578 ConversionPatternRewriter &rewriter)
const override {
580 auto value = op.getValue().toAPInt(
false);
581 auto type = rewriter.getIntegerType(value.getBitWidth());
583 op, type, rewriter.getIntegerAttr(type, value));
589 using OpConversionPattern::OpConversionPattern;
591 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
592 ConversionPatternRewriter &rewriter)
const override {
593 const auto str = op.getValue();
594 const unsigned byteWidth = str.size() * 8;
595 const auto resultType =
596 typeConverter->convertType(op.getResult().getType());
597 if (
const auto intType = mlir::dyn_cast<IntegerType>(resultType)) {
598 if (intType.getWidth() < byteWidth) {
599 return rewriter.notifyMatchFailure(op,
600 "invalid string constant type size");
603 return rewriter.notifyMatchFailure(op,
"invalid string constant type");
605 APInt value(byteWidth, 0);
606 for (
size_t i = 0; i < str.size(); ++i) {
607 const auto asciiChar =
static_cast<uint8_t
>(str[i]);
608 value |= APInt(byteWidth, asciiChar) << (8 * (str.size() - 1 - i));
611 op, resultType, rewriter.getIntegerAttr(resultType, value));
617 using OpConversionPattern::OpConversionPattern;
619 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
620 ConversionPatternRewriter &rewriter)
const override {
621 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
627 using OpConversionPattern::OpConversionPattern;
629 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
630 ConversionPatternRewriter &rewriter)
const override {
631 Type resultType = typeConverter->convertType(op.getResult().getType());
633 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
640 using OpConversionPattern::OpConversionPattern;
643 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
644 ConversionPatternRewriter &rewriter)
const override {
647 Type resultType = typeConverter->convertType(op.getResult().getType());
648 Type inputType = adaptor.getInput().getType();
649 int32_t low = adaptor.getLowBit();
651 if (isa<IntegerType>(inputType)) {
652 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
653 int32_t resultWidth = resultType.getIntOrFloatBitWidth();
654 int32_t high = low + resultWidth;
656 SmallVector<Value> toConcat;
659 op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
661 if (low < inputWidth && high > 0) {
662 int32_t lowIdx = std::max(low, 0);
665 rewriter.getIntegerType(
666 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
667 adaptor.getInput(), lowIdx);
668 toConcat.push_back(middle);
671 int32_t diff = high - inputWidth;
675 toConcat.push_back(val);
680 rewriter.replaceOp(op,
concat);
684 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
685 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
686 int32_t inputWidth = arrTy.getNumElements();
688 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
689 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
690 if (elementWidth < 0)
693 int32_t high = low + resArrTy.getNumElements();
694 int32_t resWidth = resArrTy.getNumElements();
696 SmallVector<Value> toConcat;
700 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
703 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
705 toConcat.push_back(res);
708 if (low < inputWidth && high > 0) {
709 int32_t lowIdx = std::max(0, low);
711 op.getLoc(), rewriter.getIntegerType(width), lowIdx);
715 arrTy.getElementType(),
716 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
717 adaptor.getInput(), lowIdxVal);
718 toConcat.push_back(middle);
721 int32_t diff = high - inputWidth;
724 op.getLoc(), APInt(diff * elementWidth, 0));
726 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), diff),
728 toConcat.push_back(val);
733 rewriter.replaceOp(op,
concat);
738 if (low < 0 || low >= inputWidth) {
739 int32_t bw = hw::getBitWidth(resultType);
743 Value val = rewriter.create<
hw::ConstantOp>(op.getLoc(), APInt(bw, 0));
745 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
746 rewriter.replaceOp(op, bitcast);
751 op.getLoc(), rewriter.getIntegerType(width), adaptor.getLowBit());
752 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
761 using OpConversionPattern::OpConversionPattern;
764 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
765 ConversionPatternRewriter &rewriter)
const override {
767 Type resultType = typeConverter->convertType(op.getResult().getType());
769 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
771 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
772 int64_t width = hw::getBitWidth(inputType);
777 op.getLoc(), rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
778 adaptor.getLowBit());
779 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
780 op, resultType, adaptor.getInput(), lowBit);
784 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
787 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
788 adaptor.getLowBit());
790 if (isa<hw::ArrayType>(
791 cast<hw::InOutType>(resultType).getElementType())) {
792 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
793 op, resultType, adaptor.getInput(), lowBit);
797 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
807 using OpConversionPattern::OpConversionPattern;
810 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
811 ConversionPatternRewriter &rewriter)
const override {
812 Type resultType = typeConverter->convertType(op.getResult().getType());
813 Type inputType = adaptor.getInput().getType();
815 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
816 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
817 intType.getWidth(), op->getLoc());
818 Value value = rewriter.create<
comb::ShrUOp>(op->getLoc(),
819 adaptor.getInput(), amount);
821 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
825 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
826 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
827 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
830 if (isa<hw::ArrayType>(resultType)) {
832 adaptor.getInput(), idx);
836 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
845 using OpConversionPattern::OpConversionPattern;
848 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
849 ConversionPatternRewriter &rewriter)
const override {
851 Type resultType = typeConverter->convertType(op.getResult().getType());
853 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
855 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
856 int64_t width = hw::getBitWidth(inputType);
861 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
862 llvm::Log2_64_Ceil(width), op->getLoc());
863 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
864 op, resultType, adaptor.getInput(), amount);
868 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
869 Value idx = adjustIntegerWidth(
870 rewriter, adaptor.getLowBit(),
871 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
873 if (isa<hw::ArrayType>(
874 cast<hw::InOutType>(resultType).getElementType())) {
875 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
876 op, resultType, adaptor.getInput(), idx);
880 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
890 using OpConversionPattern::OpConversionPattern;
893 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
894 ConversionPatternRewriter &rewriter)
const override {
895 Type resultType = typeConverter->convertType(op.getResult().getType());
897 adaptor.getFields());
903 using OpConversionPattern::OpConversionPattern;
906 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
907 ConversionPatternRewriter &rewriter)
const override {
909 op, adaptor.getInput(), adaptor.getFieldNameAttr());
914struct StructExtractRefOpConversion
916 using OpConversionPattern::OpConversionPattern;
919 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
920 ConversionPatternRewriter &rewriter)
const override {
921 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
922 op, adaptor.getInput(), adaptor.getFieldNameAttr());
928 using OpConversionPattern::OpConversionPattern;
930 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
931 ConversionPatternRewriter &rewriter)
const override {
932 Type resultType = typeConverter->convertType(op.getInput().getType());
933 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
935 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
936 adaptor.getInput(), max);
942 using OpConversionPattern::OpConversionPattern;
944 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
945 ConversionPatternRewriter &rewriter)
const override {
946 Type resultType = typeConverter->convertType(op.getInput().getType());
947 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
949 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
950 adaptor.getInput(), zero);
956 using OpConversionPattern::OpConversionPattern;
958 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
959 ConversionPatternRewriter &rewriter)
const override {
961 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
967 using OpConversionPattern::OpConversionPattern;
969 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
970 ConversionPatternRewriter &rewriter)
const override {
971 Type resultType = typeConverter->convertType(op.getInput().getType());
972 if (isa_and_nonnull<IntegerType>(resultType)) {
973 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
974 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
975 adaptor.getInput(), zero);
983 using OpConversionPattern::OpConversionPattern;
985 matchAndRewrite(NotOp op, OpAdaptor adaptor,
986 ConversionPatternRewriter &rewriter)
const override {
988 ConversionPattern::typeConverter->convertType(op.getResult().getType());
989 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
991 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
997 using OpConversionPattern::OpConversionPattern;
999 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1000 ConversionPatternRewriter &rewriter)
const override {
1002 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1003 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
1005 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1010template <
typename SourceOp,
typename TargetOp>
1013 using OpAdaptor =
typename SourceOp::Adaptor;
1016 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1017 ConversionPatternRewriter &rewriter)
const override {
1018 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1019 adaptor.getRhs(),
false);
1024template <
typename SourceOp, ICmpPredicate pred>
1027 using OpAdaptor =
typename SourceOp::Adaptor;
1030 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1031 ConversionPatternRewriter &rewriter)
const override {
1033 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1035 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1036 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1041template <
typename SourceOp,
bool withoutX>
1044 using OpAdaptor =
typename SourceOp::Adaptor;
1047 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1048 ConversionPatternRewriter &rewriter)
const override {
1054 unsigned bitWidth = op.getLhs().getType().getWidth();
1055 auto ignoredBits = APInt::getZero(bitWidth);
1056 auto detectIgnoredBits = [&](Value value) {
1057 auto constOp = value.getDefiningOp<ConstantOp>();
1060 auto constValue = constOp.getValue();
1062 ignoredBits |= constValue.getZBits();
1064 ignoredBits |= constValue.getUnknownBits();
1066 detectIgnoredBits(op.getLhs());
1067 detectIgnoredBits(op.getRhs());
1071 Value lhs = adaptor.getLhs();
1072 Value rhs = adaptor.getRhs();
1073 if (!ignoredBits.isZero()) {
1074 ignoredBits.flipAllBits();
1075 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
1076 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1077 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1080 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1090 using OpConversionPattern::OpConversionPattern;
1093 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1094 ConversionPatternRewriter &rewriter)
const override {
1095 Location loc = op.getLoc();
1096 Type resultType = typeConverter->convertType(op.getResult().getType());
1097 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1098 int64_t resultBw = hw::getBitWidth(resultType);
1099 if (inputBw == -1 || resultBw == -1)
1103 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1104 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1107 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1108 rewriter.replaceOp(op, result);
1114 using OpConversionPattern::OpConversionPattern;
1117 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1118 ConversionPatternRewriter &rewriter)
const override {
1119 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1120 op.getType().getWidth());
1126 using OpConversionPattern::OpConversionPattern;
1129 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1130 ConversionPatternRewriter &rewriter)
const override {
1131 auto targetWidth = op.getType().getWidth();
1132 auto inputWidth = op.getInput().getType().getWidth();
1135 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1138 op, ValueRange{zeroExt, adaptor.getInput()});
1144 using OpConversionPattern::OpConversionPattern;
1147 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1148 ConversionPatternRewriter &rewriter)
const override {
1149 auto type = typeConverter->convertType(op.getType());
1151 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1152 rewriter.replaceOp(op, value);
1162 using OpConversionPattern::OpConversionPattern;
1165 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1166 ConversionPatternRewriter &rewriter)
const override {
1167 SmallVector<Type> convResTypes;
1168 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1171 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1172 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1173 adaptor.getOperands(), op.getArgNames(),
1174 op.getResultNames(),
1175 rewriter.getArrayAttr({}),
nullptr);
1182 using OpConversionPattern::OpConversionPattern;
1185 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1186 ConversionPatternRewriter &rewriter)
const override {
1187 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1193 using OpConversionPattern::OpConversionPattern;
1196 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1197 ConversionPatternRewriter &rewriter)
const override {
1198 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1199 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1200 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
1206 using OpConversionPattern::OpConversionPattern;
1209 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1210 ConversionPatternRewriter &rewriter)
const override {
1211 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1212 adaptor.getDestOperands());
1218 using OpConversionPattern::OpConversionPattern;
1221 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1222 ConversionPatternRewriter &rewriter)
const override {
1223 SmallVector<Type> convResTypes;
1224 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1226 rewriter.replaceOpWithNewOp<func::CallOp>(
1227 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1232struct UnrealizedConversionCastConversion
1234 using OpConversionPattern::OpConversionPattern;
1237 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1238 ConversionPatternRewriter &rewriter)
const override {
1239 SmallVector<Type> convResTypes;
1240 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1245 if (convResTypes == adaptor.getOperands().getTypes()) {
1246 rewriter.replaceOp(op, adaptor.getOperands());
1250 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1251 op, convResTypes, adaptor.getOperands());
1257 using OpConversionPattern::OpConversionPattern;
1260 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1261 ConversionPatternRewriter &rewriter)
const override {
1262 Type resultType = typeConverter->convertType(op.getResult().getType());
1266 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1267 resultType.getIntOrFloatBitWidth(), op->getLoc());
1268 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1275 using OpConversionPattern::OpConversionPattern;
1278 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1279 ConversionPatternRewriter &rewriter)
const override {
1280 Type resultType = typeConverter->convertType(op.getResult().getType());
1284 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1285 resultType.getIntOrFloatBitWidth(), op->getLoc());
1287 op, resultType, adaptor.getValue(), amount,
false);
1293 using OpConversionPattern::OpConversionPattern;
1296 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1297 ConversionPatternRewriter &rewriter)
const override {
1298 Type resultType = typeConverter->convertType(op.getResult().getType());
1300 Location loc = op.getLoc();
1301 auto intType = cast<IntType>(op.getRhs().getType());
1304 Type integerType = rewriter.getIntegerType(intType.getWidth());
1305 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1307 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1308 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1311 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1313 auto forOp = rewriter.create<scf::ForOp>(
1314 loc, lowerBound, upperBound, step, ValueRange(initVal),
1315 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1316 Value loopVar = iterArgs.front();
1318 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1321 rewriter.replaceOp(op, forOp.getResult(0));
1328 using OpConversionPattern::OpConversionPattern;
1331 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1332 ConversionPatternRewriter &rewriter)
const override {
1333 Type resultType = typeConverter->convertType(op.getResult().getType());
1335 Location loc = op.getLoc();
1336 auto intType = cast<IntType>(op.getRhs().getType());
1338 Type integerType = rewriter.getIntegerType(intType.getWidth());
1339 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1340 Value rhsVal = rewriter.create<ConversionOp>(loc, integerType, op.getRhs());
1341 Value constZero = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1343 Value isNegative = rewriter.
create<comb::ICmpOp>(loc, ICmpPredicate::slt,
1348 rewriter.create<
comb::MuxOp>(loc, isNegative, constZeroResult, lhsVal);
1350 rewriter.create<
comb::MuxOp>(loc, isNegative, constZero, rhsVal);
1352 Value lowerBound = constZero;
1353 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1356 auto forOp = rewriter.
create<scf::ForOp>(
1357 loc, lowerBound, upperBound, step, ValueRange(initVal),
1358 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1359 auto loopVar = iterArgs.front();
1361 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1364 rewriter.replaceOp(op, forOp.getResult(0));
1371 using OpConversionPattern::OpConversionPattern;
1374 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1375 ConversionPatternRewriter &rewriter)
const override {
1376 Type resultType = typeConverter->convertType(op.getResult().getType());
1380 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1381 resultType.getIntOrFloatBitWidth(), op->getLoc());
1383 op, resultType, adaptor.getValue(), amount,
false);
1389 using OpConversionPattern::OpConversionPattern;
1392 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1393 ConversionPatternRewriter &rewriter)
const override {
1394 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1399struct AssignedVariableOpConversion
1401 using OpConversionPattern::OpConversionPattern;
1404 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1405 ConversionPatternRewriter &rewriter)
const override {
1406 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1407 adaptor.getNameAttr());
1412template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1415 using OpAdaptor =
typename OpTy::Adaptor;
1418 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1419 ConversionPatternRewriter &rewriter)
const override {
1422 auto timeAttr = llhd::TimeAttr::get(
1423 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1424 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1425 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1426 adaptor.getSrc(), time, Value{});
1432 using OpConversionPattern::OpConversionPattern;
1435 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1436 ConversionPatternRewriter &rewriter)
const override {
1441 auto type = typeConverter->convertType(op.getType());
1443 auto hasNoWriteEffect = [](Region ®ion) {
1444 auto result = region.walk([](Operation *operation) {
1445 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1446 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1447 !memOp.hasEffect<MemoryEffects::Free>())
1448 return WalkResult::advance();
1450 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1451 return WalkResult::advance();
1453 return WalkResult::interrupt();
1455 return !result.wasInterrupted();
1458 if (hasNoWriteEffect(op.getTrueRegion()) &&
1459 hasNoWriteEffect(op.getFalseRegion())) {
1460 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1461 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1463 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1464 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1466 Value convTrueVal = typeConverter->materializeTargetConversion(
1467 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1468 Value convFalseVal = typeConverter->materializeTargetConversion(
1469 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1471 rewriter.eraseOp(trueTerm);
1472 rewriter.eraseOp(falseTerm);
1474 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1475 convTrueVal, convFalseVal);
1480 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1481 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1482 ifOp.getThenRegion().end());
1483 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1484 ifOp.getElseRegion().end());
1485 rewriter.replaceOp(op, ifOp);
1491 using OpConversionPattern::OpConversionPattern;
1494 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1495 ConversionPatternRewriter &rewriter)
const override {
1496 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1501template <
typename SourceOp>
1504 using OpAdaptor =
typename SourceOp::Adaptor;
1507 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1508 ConversionPatternRewriter &rewriter)
const override {
1509 rewriter.modifyOpInPlace(op,
1510 [&]() { op->setOperands(adaptor.getOperands()); });
1515template <
typename MooreOpTy,
typename VerifOpTy>
1518 using OpAdaptor =
typename MooreOpTy::Adaptor;
1521 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1522 ConversionPatternRewriter &rewriter)
const override {
1524 op.getLabel().has_value()
1525 ? StringAttr::get(op->getContext(), op.getLabel().value())
1526 : StringAttr::
get(op->getContext());
1527 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1538 using OpConversionPattern::OpConversionPattern;
1541 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1542 ConversionPatternRewriter &rewriter)
const override {
1543 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1549 using OpConversionPattern::OpConversionPattern;
1552 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1553 ConversionPatternRewriter &rewriter)
const override {
1554 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1555 adaptor.getInputs());
1561 using OpConversionPattern::OpConversionPattern;
1564 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1565 ConversionPatternRewriter &rewriter)
const override {
1567 switch (op.getFormat()) {
1568 case IntFormat::Decimal:
1569 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1571 case IntFormat::Binary:
1572 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1574 case IntFormat::HexLower:
1575 case IntFormat::HexUpper:
1576 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1579 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1585 using OpConversionPattern::OpConversionPattern;
1588 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1589 ConversionPatternRewriter &rewriter)
const override {
1590 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1591 op, adaptor.getMessage());
1603 const TypeConverter &converter) {
1604 target.addIllegalDialect<MooreDialect>();
1605 target.addLegalDialect<comb::CombDialect>();
1606 target.addLegalDialect<hw::HWDialect>();
1607 target.addLegalDialect<llhd::LLHDDialect>();
1608 target.addLegalDialect<mlir::BuiltinDialect>();
1609 target.addLegalDialect<sim::SimDialect>();
1610 target.addLegalDialect<verif::VerifDialect>();
1612 target.addLegalOp<debug::ScopeOp>();
1614 target.addDynamicallyLegalOp<
1615 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1616 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1617 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1618 [&](Operation *op) {
return converter.isLegal(op); });
1620 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1621 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1622 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1625 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1626 return converter.isSignatureLegal(op.getFunctionType()) &&
1627 converter.isLegal(&op.getFunctionBody());
1631 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1632 converter.isLegal(&op.getBody());
1637 typeConverter.addConversion([&](IntType type) {
1638 return IntegerType::get(type.getContext(), type.getWidth());
1641 typeConverter.addConversion([&](FormatStringType type) {
1642 return sim::FormatStringType::get(type.getContext());
1645 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1646 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1647 return hw::ArrayType::get(
elementType, type.getSize());
1654 typeConverter.addConversion(
1655 [&](UnpackedArrayType type) -> std::optional<Type> {
1656 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1657 return hw::ArrayType::get(
elementType, type.getSize());
1661 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1662 SmallVector<hw::StructType::FieldInfo> fields;
1663 for (
auto field : type.getMembers()) {
1664 hw::StructType::FieldInfo info;
1665 info.type = typeConverter.convertType(field.type);
1668 info.name = field.name;
1669 fields.push_back(info);
1671 return hw::StructType::get(type.getContext(), fields);
1679 typeConverter.addConversion(
1680 [&](UnpackedStructType type) -> std::optional<Type> {
1681 SmallVector<hw::StructType::FieldInfo> fields;
1682 for (
auto field : type.getMembers()) {
1683 hw::StructType::FieldInfo info;
1684 info.type = typeConverter.convertType(field.type);
1687 info.name = field.name;
1688 fields.push_back(info);
1690 return hw::StructType::get(type.getContext(), fields);
1693 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1694 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1695 return hw::InOutType::get(innerType);
1700 typeConverter.addConversion([](IntegerType type) {
return type; });
1701 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1702 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1703 typeConverter.addConversion([](debug::StructType type) {
return type; });
1705 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1706 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1707 return hw::InOutType::get(innerType);
1711 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1712 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1713 return hw::ArrayType::get(
elementType, type.getNumElements());
1717 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1718 SmallVector<hw::StructType::FieldInfo> fields;
1719 for (
auto field : type.getElements()) {
1720 hw::StructType::FieldInfo info;
1721 info.type = typeConverter.convertType(field.type);
1724 info.name = field.name;
1725 fields.push_back(info);
1727 return hw::StructType::get(type.getContext(), fields);
1730 typeConverter.addTargetMaterialization(
1731 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1732 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1733 if (inputs.size() != 1 || !inputs[0])
1736 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1740 typeConverter.addSourceMaterialization(
1741 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1742 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1743 if (inputs.size() != 1)
1746 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1752 TypeConverter &typeConverter) {
1753 auto *context =
patterns.getContext();
1757 VariableOpConversion,
1761 ConversionOpConversion,
1767 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1768 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1770 StructExtractOpConversion, StructExtractRefOpConversion,
1771 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion,
1772 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1775 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1776 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1779 BinaryOpConversion<AddOp, comb::AddOp>,
1780 BinaryOpConversion<SubOp, comb::SubOp>,
1781 BinaryOpConversion<MulOp, comb::MulOp>,
1782 BinaryOpConversion<DivUOp, comb::DivUOp>,
1783 BinaryOpConversion<DivSOp, comb::DivSOp>,
1784 BinaryOpConversion<ModUOp, comb::ModUOp>,
1785 BinaryOpConversion<ModSOp, comb::ModSOp>,
1786 BinaryOpConversion<AndOp, comb::AndOp>,
1787 BinaryOpConversion<OrOp, comb::OrOp>,
1788 BinaryOpConversion<XorOp, comb::XorOp>,
1791 PowUOpConversion, PowSOpConversion,
1794 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1795 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1796 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1797 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1798 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1799 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1800 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1801 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1802 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1803 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1804 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1805 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1806 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1807 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1808 CaseXZEqOpConversion<CaseZEqOp, true>,
1809 CaseXZEqOpConversion<CaseXZEqOp, false>,
1812 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1815 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1818 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1819 AssignOpConversion<BlockingAssignOp, 0, 1>,
1820 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1821 AssignedVariableOpConversion,
1824 CondBranchOpConversion, BranchOpConversion,
1827 HWInstanceOpConversion, ReturnOpConversion,
1828 CallOpConversion, UnrealizedConversionCastConversion,
1829 InPlaceOpConversion<debug::ArrayOp>,
1830 InPlaceOpConversion<debug::StructOp>,
1831 InPlaceOpConversion<debug::VariableOp>,
1834 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1835 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1836 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1839 FormatLiteralOpConversion,
1840 FormatConcatOpConversion,
1841 FormatIntOpConversion,
1842 DisplayBIOpConversion
1843 >(typeConverter, context);
1846 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1848 hw::populateHWModuleLikeTypeConversionPattern(
1849 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1850 populateSCFToControlFlowConversionPatterns(
patterns);
1859struct MooreToCorePass
1860 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1861 void runOnOperation()
override;
1867 return std::make_unique<MooreToCorePass>();
1871void MooreToCorePass::runOnOperation() {
1872 MLIRContext &context = getContext();
1873 ModuleOp
module = getOperation();
1875 IRRewriter rewriter(module);
1876 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1878 ConversionTarget target(context);
1879 TypeConverter typeConverter;
1880 RewritePatternSet
patterns(&context);
1885 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1886 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.