21#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
22#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
23#include "mlir/Dialect/Func/IR/FuncOps.h"
24#include "mlir/Dialect/Math/IR/Math.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 builder, loc, builder.getIntegerType(targetWidth - intWidth), 0);
61 return comb::ConcatOp::create(builder, loc, ValueRange{zeroExt, value});
65 intWidth - targetWidth);
67 builder, loc, builder.getIntegerType(intWidth - targetWidth), 0);
68 Value isZero = comb::ICmpOp::create(builder, loc, comb::ICmpPredicate::eq, hi,
72 builder.getIntegerType(targetWidth), -1);
73 return comb::MuxOp::create(builder, loc, isZero, lo, max,
false);
81 auto moduleTy = op.getModuleType();
82 SmallVector<hw::PortInfo> ports;
83 ports.reserve(moduleTy.getNumPorts());
85 for (
auto port : moduleTy.getPorts()) {
86 Type portTy = typeConverter.convertType(port.type);
87 if (
auto ioTy = dyn_cast_or_null<hw::InOutType>(portTy)) {
95 if (port.dir == hw::ModulePort::Direction::Output) {
97 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
105 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
117 using OpConversionPattern::OpConversionPattern;
120 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
121 ConversionPatternRewriter &rewriter)
const override {
122 rewriter.setInsertionPoint(op);
126 hw::HWModuleOp::create(rewriter, op.getLoc(), op.getSymNameAttr(),
127 getModulePortInfo(*typeConverter, op));
130 SymbolTable::setSymbolVisibility(hwModuleOp,
131 SymbolTable::getSymbolVisibility(op));
132 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
134 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
136 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
137 hwModuleOp.getBodyRegion().end());
140 rewriter.eraseOp(op);
146 using OpConversionPattern::OpConversionPattern;
149 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
150 ConversionPatternRewriter &rewriter)
const override {
151 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
157 using OpConversionPattern::OpConversionPattern;
160 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
161 ConversionPatternRewriter &rewriter)
const override {
162 auto instName = op.getInstanceNameAttr();
163 auto moduleName = op.getModuleNameAttr();
166 rewriter.setInsertionPoint(op);
167 auto instOp = hw::InstanceOp::create(
168 rewriter, op.getLoc(), op.getResultTypes(), instName, moduleName,
169 op.getInputs(), op.getInputNamesAttr(), op.getOutputNamesAttr(),
170 rewriter.getArrayAttr({}),
nullptr,
174 op.replaceAllUsesWith(instOp.getResults());
175 rewriter.eraseOp(op);
180static void getValuesToObserve(Region *region,
181 function_ref<
void(Value)> setInsertionPoint,
182 const TypeConverter *typeConverter,
183 ConversionPatternRewriter &rewriter,
184 SmallVector<Value> &observeValues) {
185 SmallDenseSet<Value> alreadyObserved;
186 Location loc = region->getLoc();
188 auto probeIfSignal = [&](Value value) -> Value {
189 if (!isa<hw::InOutType>(value.getType()))
191 return llhd::PrbOp::create(rewriter, loc, value);
194 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
195 [&](Operation *operation) {
196 for (
auto value : operation->getOperands()) {
197 if (isa<BlockArgument>(value))
198 value = rewriter.getRemappedValue(value);
200 if (region->isAncestor(value.getParentRegion()))
202 if (
auto *defOp = value.getDefiningOp();
203 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
205 if (!alreadyObserved.insert(value).second)
208 OpBuilder::InsertionGuard g(rewriter);
209 if (
auto remapped = rewriter.getRemappedValue(value)) {
210 setInsertionPoint(remapped);
211 observeValues.push_back(probeIfSignal(remapped));
213 setInsertionPoint(value);
214 auto type = typeConverter->convertType(value.getType());
215 auto converted = typeConverter->materializeTargetConversion(
216 rewriter, loc, type, value);
217 observeValues.push_back(probeIfSignal(converted));
224 using OpConversionPattern::OpConversionPattern;
227 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
228 ConversionPatternRewriter &rewriter)
const override {
230 SmallVector<Value> observedValues;
231 if (op.getKind() == ProcedureKind::AlwaysComb ||
232 op.getKind() == ProcedureKind::AlwaysLatch) {
233 auto setInsertionPoint = [&](Value value) {
234 rewriter.setInsertionPoint(op);
236 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
237 rewriter, observedValues);
240 auto loc = op.getLoc();
241 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
246 if (op.getKind() == ProcedureKind::Initial ||
247 op.getKind() == ProcedureKind::Final) {
249 if (op.getKind() == ProcedureKind::Initial)
250 newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
252 newOp = llhd::FinalOp::create(rewriter, loc);
253 auto &body = newOp->getRegion(0);
254 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
256 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
257 rewriter.setInsertionPoint(returnOp);
258 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp, ValueRange{});
260 rewriter.eraseOp(op);
265 auto newOp = llhd::ProcessOp::create(rewriter, loc, TypeRange{});
270 rewriter.createBlock(&newOp.getBody());
271 auto *block = &op.getBody().front();
272 cf::BranchOp::create(rewriter, loc, block);
273 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
274 newOp.getBody().end());
282 if (op.getKind() == ProcedureKind::AlwaysComb ||
283 op.getKind() == ProcedureKind::AlwaysLatch) {
284 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
285 llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(), observedValues,
286 ValueRange{}, block);
293 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
294 rewriter.setInsertionPoint(returnOp);
295 cf::BranchOp::create(rewriter, loc, block);
296 rewriter.eraseOp(returnOp);
299 rewriter.eraseOp(op);
305 using OpConversionPattern::OpConversionPattern;
308 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
309 ConversionPatternRewriter &rewriter)
const override {
343 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
349 if (op.getBody().front().empty()) {
352 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
356 auto *waitBlock = rewriter.createBlock(resumeBlock);
357 auto *checkBlock = rewriter.createBlock(resumeBlock);
359 auto loc = op.getLoc();
360 rewriter.setInsertionPoint(op);
361 cf::BranchOp::create(rewriter, loc, waitBlock);
371 SmallVector<Value> valuesBefore;
372 rewriter.setInsertionPointToEnd(waitBlock);
373 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
374 bool allDetectsAreAnyChange =
true;
376 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
377 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
378 allDetectsAreAnyChange =
false;
379 valuesBefore.push_back(detectOp.getInput());
380 rewriter.eraseOp(detectOp);
386 SmallVector<Value> observeValues;
387 auto setInsertionPointAfterDef = [&](Value value) {
388 if (
auto *op = value.getDefiningOp())
389 rewriter.setInsertionPointAfter(op);
390 if (
auto arg = dyn_cast<BlockArgument>(value))
391 rewriter.setInsertionPointToStart(value.getParentBlock());
394 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
395 typeConverter, rewriter, observeValues);
400 auto waitOp = llhd::WaitOp::create(rewriter, loc, ValueRange{}, Value(),
401 observeValues, ValueRange{}, checkBlock);
402 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
403 rewriter.eraseOp(clonedOp);
407 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
408 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
410 rewriter.eraseOp(op);
414 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
415 assert(before.getType() == after.getType() &&
416 "mismatched types after clone op");
417 auto beforeType = cast<IntType>(before.getType());
421 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
422 constexpr int LSB = 0;
424 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
426 moore::ExtractOp::create(rewriter, loc, beforeType, before, LSB);
427 after = moore::ExtractOp::create(rewriter, loc, beforeType, after, LSB);
430 auto intType = rewriter.getIntegerType(beforeType.getWidth());
431 before = typeConverter->materializeTargetConversion(rewriter, loc,
433 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
436 if (edge == Edge::AnyChange)
437 return comb::ICmpOp::create(rewriter, loc, ICmpPredicate::ne, before,
440 SmallVector<Value> disjuncts;
443 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
445 comb::XorOp::create(rewriter, loc, before, trueVal,
true);
447 comb::AndOp::create(rewriter, loc, notOldVal, after,
true);
448 disjuncts.push_back(posedge);
451 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
453 comb::XorOp::create(rewriter, loc, after, trueVal,
true);
455 comb::AndOp::create(rewriter, loc, before, notCurrVal,
true);
456 disjuncts.push_back(posedge);
459 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
466 SmallVector<Value> triggers;
467 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
468 if (!allDetectsAreAnyChange) {
469 if (!isa<IntType>(before.getType()))
470 return detectOp->emitError() <<
"requires int operand";
472 rewriter.setInsertionPoint(detectOp);
474 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
475 if (detectOp.getCondition()) {
476 auto condition = typeConverter->materializeTargetConversion(
477 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
479 comb::AndOp::create(rewriter, loc, trigger, condition,
true);
481 triggers.push_back(trigger);
484 rewriter.eraseOp(detectOp);
487 rewriter.setInsertionPointToEnd(checkBlock);
488 if (triggers.empty()) {
493 cf::BranchOp::create(rewriter, loc, resumeBlock);
499 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
500 cf::CondBranchOp::create(rewriter, loc, triggered, resumeBlock,
509static LogicalResult
convert(WaitDelayOp op, WaitDelayOp::Adaptor adaptor,
510 ConversionPatternRewriter &rewriter) {
512 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
513 rewriter.setInsertionPoint(op);
514 rewriter.replaceOpWithNewOp<llhd::WaitOp>(op, ValueRange{},
515 adaptor.getDelay(), ValueRange{},
516 ValueRange{}, resumeBlock);
517 rewriter.setInsertionPointToStart(resumeBlock);
522static LogicalResult
convert(UnreachableOp op, UnreachableOp::Adaptor adaptor,
523 ConversionPatternRewriter &rewriter) {
524 rewriter.replaceOpWithNewOp<llhd::HaltOp>(op, ValueRange{});
533 using OpConversionPattern::OpConversionPattern;
536 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
537 ConversionPatternRewriter &rewriter)
const override {
538 Location loc = op.getLoc();
539 Type resultType = typeConverter->convertType(op.getResult().getType());
541 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
544 Value init = adaptor.getInitial();
546 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
558 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
559 op.getNameAttr(), init);
565 using OpConversionPattern::OpConversionPattern;
568 matchAndRewrite(NetOp op, OpAdaptor adaptor,
569 ConversionPatternRewriter &rewriter)
const override {
570 auto loc = op.getLoc();
571 if (op.getKind() != NetKind::Wire)
572 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
574 auto resultType = typeConverter->convertType(op.getResult().getType());
576 return rewriter.notifyMatchFailure(loc,
"invalid net type");
580 auto elementType = cast<hw::InOutType>(resultType).getElementType();
588 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
589 op, resultType, op.getNameAttr(), init);
591 if (
auto assignedValue = adaptor.getAssignment()) {
592 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
593 llvm::StringRef(
"ns"), 0, 1);
594 auto time = llhd::ConstantTimeOp::create(rewriter, loc, timeAttr);
595 llhd::DrvOp::create(rewriter, loc, signal, assignedValue, time, Value{});
607 using OpConversionPattern::OpConversionPattern;
610 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
611 ConversionPatternRewriter &rewriter)
const override {
613 auto value = op.getValue().toAPInt(
false);
614 auto type = rewriter.getIntegerType(value.getBitWidth());
616 op, type, rewriter.getIntegerAttr(type, value));
622 using OpConversionPattern::OpConversionPattern;
625 matchAndRewrite(ConstantTimeOp op, OpAdaptor adaptor,
626 ConversionPatternRewriter &rewriter)
const override {
627 rewriter.replaceOpWithNewOp<llhd::ConstantTimeOp>(
628 op, llhd::TimeAttr::get(op->getContext(), op.getValue(),
629 StringRef(
"fs"), 0, 0));
635 using OpConversionPattern::OpConversionPattern;
637 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
638 ConversionPatternRewriter &rewriter)
const override {
639 const auto resultType =
640 typeConverter->convertType(op.getResult().getType());
641 const auto intType = mlir::cast<IntegerType>(resultType);
643 const auto str = op.getValue();
644 const unsigned byteWidth = intType.getWidth();
645 APInt value(byteWidth, 0);
648 const size_t maxChars =
649 std::min(str.size(),
static_cast<size_t>(byteWidth / 8));
650 for (
size_t i = 0; i < maxChars; i++) {
651 const size_t pos = str.size() - 1 - i;
652 const auto asciiChar =
static_cast<uint8_t
>(str[pos]);
653 value |= APInt(byteWidth, asciiChar) << (8 * i);
657 op, resultType, rewriter.getIntegerAttr(resultType, value));
663 using OpConversionPattern::OpConversionPattern;
665 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
666 ConversionPatternRewriter &rewriter)
const override {
667 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
673 using OpConversionPattern::OpConversionPattern;
675 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
676 ConversionPatternRewriter &rewriter)
const override {
677 Type resultType = typeConverter->convertType(op.getResult().getType());
679 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
686 using OpConversionPattern::OpConversionPattern;
689 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
690 ConversionPatternRewriter &rewriter)
const override {
693 Type resultType = typeConverter->convertType(op.getResult().getType());
694 Type inputType = adaptor.getInput().getType();
695 int32_t low = adaptor.getLowBit();
697 if (isa<IntegerType>(inputType)) {
698 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
699 int32_t resultWidth = hw::getBitWidth(resultType);
700 int32_t high = low + resultWidth;
702 SmallVector<Value> toConcat;
705 rewriter, op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
707 if (low < inputWidth && high > 0) {
708 int32_t lowIdx = std::max(low, 0);
711 rewriter.getIntegerType(
712 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
713 adaptor.getInput(), lowIdx);
714 toConcat.push_back(middle);
717 int32_t diff = high - inputWidth;
721 toConcat.push_back(val);
726 rewriter.replaceOp(op,
concat);
730 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
731 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
732 int32_t inputWidth = arrTy.getNumElements();
734 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
735 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
736 if (elementWidth < 0)
739 int32_t high = low + resArrTy.getNumElements();
740 int32_t resWidth = resArrTy.getNumElements();
742 SmallVector<Value> toConcat;
745 rewriter, op.getLoc(),
746 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
749 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
751 toConcat.push_back(res);
754 if (low < inputWidth && high > 0) {
755 int32_t lowIdx = std::max(0, low);
757 rewriter, op.getLoc(), rewriter.getIntegerType(width), lowIdx);
761 arrTy.getElementType(),
762 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
763 adaptor.getInput(), lowIdxVal);
764 toConcat.push_back(middle);
767 int32_t diff = high - inputWidth;
770 rewriter, op.getLoc(), APInt(diff * elementWidth, 0));
772 rewriter, op.getLoc(),
773 hw::ArrayType::get(arrTy.getElementType(), diff), constZero);
774 toConcat.push_back(val);
779 rewriter.replaceOp(op,
concat);
784 if (low < 0 || low >= inputWidth) {
785 int32_t bw = hw::getBitWidth(resultType);
791 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
792 rewriter.replaceOp(op, bitcast);
797 rewriter.getIntegerType(width),
798 adaptor.getLowBit());
799 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
808 using OpConversionPattern::OpConversionPattern;
811 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
812 ConversionPatternRewriter &rewriter)
const override {
814 Type resultType = typeConverter->convertType(op.getResult().getType());
816 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
818 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
819 int64_t width = hw::getBitWidth(inputType);
824 rewriter, op.getLoc(),
825 rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
826 adaptor.getLowBit());
827 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
828 op, resultType, adaptor.getInput(), lowBit);
832 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
834 rewriter, op.getLoc(),
835 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
836 adaptor.getLowBit());
840 if (arrType.getElementType() !=
841 cast<hw::InOutType>(resultType).getElementType()) {
842 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
843 op, resultType, adaptor.getInput(), lowBit);
847 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
857 using OpConversionPattern::OpConversionPattern;
860 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
861 ConversionPatternRewriter &rewriter)
const override {
862 Type resultType = typeConverter->convertType(op.getResult().getType());
863 Type inputType = adaptor.getInput().getType();
865 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
866 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
867 intType.getWidth(), op->getLoc());
868 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
869 adaptor.getInput(), amount);
871 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
875 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
876 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
877 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
880 if (isa<hw::ArrayType>(resultType)) {
882 adaptor.getInput(), idx);
886 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
895 using OpConversionPattern::OpConversionPattern;
898 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
899 ConversionPatternRewriter &rewriter)
const override {
901 Type resultType = typeConverter->convertType(op.getResult().getType());
903 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
905 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
906 int64_t width = hw::getBitWidth(inputType);
911 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
912 llvm::Log2_64_Ceil(width), op->getLoc());
913 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
914 op, resultType, adaptor.getInput(), amount);
918 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
919 Value idx = adjustIntegerWidth(
920 rewriter, adaptor.getLowBit(),
921 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
923 if (isa<hw::ArrayType>(
924 cast<hw::InOutType>(resultType).getElementType())) {
925 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
926 op, resultType, adaptor.getInput(), idx);
930 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
940 using OpConversionPattern::OpConversionPattern;
943 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
944 ConversionPatternRewriter &rewriter)
const override {
945 Type resultType = typeConverter->convertType(op.getResult().getType());
947 adaptor.getElements());
953 using OpConversionPattern::OpConversionPattern;
956 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
957 ConversionPatternRewriter &rewriter)
const override {
958 Type resultType = typeConverter->convertType(op.getResult().getType());
960 adaptor.getFields());
966 using OpConversionPattern::OpConversionPattern;
969 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
970 ConversionPatternRewriter &rewriter)
const override {
972 op, adaptor.getInput(), adaptor.getFieldNameAttr());
977struct StructExtractRefOpConversion
979 using OpConversionPattern::OpConversionPattern;
982 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
983 ConversionPatternRewriter &rewriter)
const override {
984 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
985 op, adaptor.getInput(), adaptor.getFieldNameAttr());
991 using OpConversionPattern::OpConversionPattern;
993 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
994 ConversionPatternRewriter &rewriter)
const override {
995 Type resultType = typeConverter->convertType(op.getInput().getType());
998 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
999 adaptor.getInput(), max);
1005 using OpConversionPattern::OpConversionPattern;
1007 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1008 ConversionPatternRewriter &rewriter)
const override {
1009 Type resultType = typeConverter->convertType(op.getInput().getType());
1012 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1013 adaptor.getInput(), zero);
1019 using OpConversionPattern::OpConversionPattern;
1021 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1022 ConversionPatternRewriter &rewriter)
const override {
1024 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1030 using OpConversionPattern::OpConversionPattern;
1032 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1033 ConversionPatternRewriter &rewriter)
const override {
1034 Type resultType = typeConverter->convertType(op.getInput().getType());
1035 if (isa_and_nonnull<IntegerType>(resultType)) {
1038 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1039 adaptor.getInput(), zero);
1047 using OpConversionPattern::OpConversionPattern;
1049 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1050 ConversionPatternRewriter &rewriter)
const override {
1052 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1055 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1061 using OpConversionPattern::OpConversionPattern;
1063 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1064 ConversionPatternRewriter &rewriter)
const override {
1066 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1069 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1074template <
typename SourceOp,
typename TargetOp>
1077 using OpAdaptor =
typename SourceOp::Adaptor;
1080 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1081 ConversionPatternRewriter &rewriter)
const override {
1082 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1083 adaptor.getRhs(),
false);
1088template <
typename SourceOp, ICmpPredicate pred>
1091 using OpAdaptor =
typename SourceOp::Adaptor;
1094 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1095 ConversionPatternRewriter &rewriter)
const override {
1097 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1099 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1100 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1105template <
typename SourceOp,
bool withoutX>
1108 using OpAdaptor =
typename SourceOp::Adaptor;
1111 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1112 ConversionPatternRewriter &rewriter)
const override {
1118 unsigned bitWidth = op.getLhs().getType().getWidth();
1119 auto ignoredBits = APInt::getZero(bitWidth);
1120 auto detectIgnoredBits = [&](Value value) {
1121 auto constOp = value.getDefiningOp<ConstantOp>();
1124 auto constValue = constOp.getValue();
1126 ignoredBits |= constValue.getZBits();
1128 ignoredBits |= constValue.getUnknownBits();
1130 detectIgnoredBits(op.getLhs());
1131 detectIgnoredBits(op.getRhs());
1135 Value lhs = adaptor.getLhs();
1136 Value rhs = adaptor.getRhs();
1137 if (!ignoredBits.isZero()) {
1138 ignoredBits.flipAllBits();
1140 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1141 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1144 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1154 using OpConversionPattern::OpConversionPattern;
1157 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1158 ConversionPatternRewriter &rewriter)
const override {
1159 Location loc = op.getLoc();
1160 Type resultType = typeConverter->convertType(op.getResult().getType());
1161 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1162 int64_t resultBw = hw::getBitWidth(resultType);
1163 if (inputBw == -1 || resultBw == -1)
1167 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1168 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1171 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1172 rewriter.replaceOp(op, result);
1177template <
typename SourceOp>
1180 using OpAdaptor =
typename SourceOp::Adaptor;
1181 using ConversionPattern::typeConverter;
1184 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1185 ConversionPatternRewriter &rewriter)
const override {
1186 auto type = typeConverter->convertType(op.getResult().getType());
1187 if (type == adaptor.getInput().getType())
1188 rewriter.replaceOp(op, adaptor.getInput());
1190 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1196 using OpConversionPattern::OpConversionPattern;
1199 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1200 ConversionPatternRewriter &rewriter)
const override {
1201 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1202 op.getType().getWidth());
1208 using OpConversionPattern::OpConversionPattern;
1211 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1212 ConversionPatternRewriter &rewriter)
const override {
1213 auto targetWidth = op.getType().getWidth();
1214 auto inputWidth = op.getInput().getType().getWidth();
1217 rewriter, op.getLoc(),
1218 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1221 op, ValueRange{zeroExt, adaptor.getInput()});
1227 using OpConversionPattern::OpConversionPattern;
1230 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1231 ConversionPatternRewriter &rewriter)
const override {
1232 auto type = typeConverter->convertType(op.getType());
1234 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1235 rewriter.replaceOp(op, value);
1245 using OpConversionPattern::OpConversionPattern;
1248 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1249 ConversionPatternRewriter &rewriter)
const override {
1250 SmallVector<Type> convResTypes;
1251 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1254 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1255 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1256 adaptor.getOperands(), op.getArgNames(),
1257 op.getResultNames(),
1258 rewriter.getArrayAttr({}),
nullptr);
1265 using OpConversionPattern::OpConversionPattern;
1268 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1269 ConversionPatternRewriter &rewriter)
const override {
1270 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1276 using OpConversionPattern::OpConversionPattern;
1279 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1280 ConversionPatternRewriter &rewriter)
const override {
1281 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1282 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1283 adaptor.getFalseDestOperands(),
nullptr,
1284 op.getTrueDest(), op.getFalseDest());
1290 using OpConversionPattern::OpConversionPattern;
1293 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1294 ConversionPatternRewriter &rewriter)
const override {
1295 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1296 adaptor.getDestOperands());
1302 using OpConversionPattern::OpConversionPattern;
1305 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1306 ConversionPatternRewriter &rewriter)
const override {
1307 SmallVector<Type> convResTypes;
1308 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1310 rewriter.replaceOpWithNewOp<func::CallOp>(
1311 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1316struct UnrealizedConversionCastConversion
1318 using OpConversionPattern::OpConversionPattern;
1321 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1322 ConversionPatternRewriter &rewriter)
const override {
1323 SmallVector<Type> convResTypes;
1324 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1329 if (convResTypes == adaptor.getOperands().getTypes()) {
1330 rewriter.replaceOp(op, adaptor.getOperands());
1334 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1335 op, convResTypes, adaptor.getOperands());
1341 using OpConversionPattern::OpConversionPattern;
1344 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1345 ConversionPatternRewriter &rewriter)
const override {
1346 Type resultType = typeConverter->convertType(op.getResult().getType());
1350 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1351 resultType.getIntOrFloatBitWidth(), op->getLoc());
1352 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1359 using OpConversionPattern::OpConversionPattern;
1362 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1363 ConversionPatternRewriter &rewriter)
const override {
1364 Type resultType = typeConverter->convertType(op.getResult().getType());
1368 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1369 resultType.getIntOrFloatBitWidth(), op->getLoc());
1371 op, resultType, adaptor.getValue(), amount,
false);
1377 using OpConversionPattern::OpConversionPattern;
1380 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1381 ConversionPatternRewriter &rewriter)
const override {
1382 Type resultType = typeConverter->convertType(op.getResult().getType());
1384 Location loc = op->getLoc();
1389 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1390 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1393 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1401 using OpConversionPattern::OpConversionPattern;
1404 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1405 ConversionPatternRewriter &rewriter)
const override {
1406 Type resultType = typeConverter->convertType(op.getResult().getType());
1410 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1411 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1417 using OpConversionPattern::OpConversionPattern;
1420 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1421 ConversionPatternRewriter &rewriter)
const override {
1422 Type resultType = typeConverter->convertType(op.getResult().getType());
1426 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1427 resultType.getIntOrFloatBitWidth(), op->getLoc());
1429 op, resultType, adaptor.getValue(), amount,
false);
1435 using OpConversionPattern::OpConversionPattern;
1438 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1439 ConversionPatternRewriter &rewriter)
const override {
1440 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1445struct AssignedVariableOpConversion
1447 using OpConversionPattern::OpConversionPattern;
1450 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1451 ConversionPatternRewriter &rewriter)
const override {
1452 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1453 adaptor.getNameAttr());
1458template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1461 using OpAdaptor =
typename OpTy::Adaptor;
1464 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1465 ConversionPatternRewriter &rewriter)
const override {
1468 auto timeAttr = llhd::TimeAttr::get(
1469 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1470 auto time = llhd::ConstantTimeOp::create(rewriter, op->getLoc(), timeAttr);
1471 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1472 adaptor.getSrc(), time, Value{});
1478 using OpConversionPattern::OpConversionPattern;
1481 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1482 ConversionPatternRewriter &rewriter)
const override {
1487 auto type = typeConverter->convertType(op.getType());
1489 auto hasNoWriteEffect = [](Region ®ion) {
1490 auto result = region.walk([](Operation *operation) {
1491 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1492 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1493 !memOp.hasEffect<MemoryEffects::Free>())
1494 return WalkResult::advance();
1496 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1497 return WalkResult::advance();
1499 return WalkResult::interrupt();
1501 return !result.wasInterrupted();
1504 if (hasNoWriteEffect(op.getTrueRegion()) &&
1505 hasNoWriteEffect(op.getFalseRegion())) {
1506 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1507 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1509 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1510 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1512 Value convTrueVal = typeConverter->materializeTargetConversion(
1513 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1514 Value convFalseVal = typeConverter->materializeTargetConversion(
1515 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1517 rewriter.eraseOp(trueTerm);
1518 rewriter.eraseOp(falseTerm);
1520 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1521 convTrueVal, convFalseVal);
1526 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1527 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1528 ifOp.getThenRegion().end());
1529 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1530 ifOp.getElseRegion().end());
1531 rewriter.replaceOp(op, ifOp);
1537 using OpConversionPattern::OpConversionPattern;
1540 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1541 ConversionPatternRewriter &rewriter)
const override {
1542 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1547template <
typename SourceOp>
1550 using OpAdaptor =
typename SourceOp::Adaptor;
1553 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1554 ConversionPatternRewriter &rewriter)
const override {
1555 rewriter.modifyOpInPlace(op,
1556 [&]() { op->setOperands(adaptor.getOperands()); });
1561template <
typename MooreOpTy,
typename VerifOpTy>
1564 using OpAdaptor =
typename MooreOpTy::Adaptor;
1567 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1568 ConversionPatternRewriter &rewriter)
const override {
1570 op.getLabel().has_value()
1571 ? StringAttr::get(op->getContext(), op.getLabel().value())
1572 : StringAttr::
get(op->getContext());
1573 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1584 using OpConversionPattern::OpConversionPattern;
1587 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1588 ConversionPatternRewriter &rewriter)
const override {
1589 rewriter.replaceOpWithNewOp<sim::FormatLiteralOp>(op, adaptor.getLiteral());
1595 using OpConversionPattern::OpConversionPattern;
1598 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1599 ConversionPatternRewriter &rewriter)
const override {
1600 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1601 adaptor.getInputs());
1607 using OpConversionPattern::OpConversionPattern;
1610 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1611 ConversionPatternRewriter &rewriter)
const override {
1613 switch (op.getFormat()) {
1614 case IntFormat::Decimal:
1615 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1617 case IntFormat::Binary:
1618 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1620 case IntFormat::HexLower:
1621 case IntFormat::HexUpper:
1622 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1625 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1631 using OpConversionPattern::OpConversionPattern;
1634 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1635 ConversionPatternRewriter &rewriter)
const override {
1636 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1637 op, adaptor.getMessage());
1649static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
1650 ConversionPatternRewriter &rewriter) {
1651 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
1656static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
1657 ConversionPatternRewriter &rewriter) {
1658 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
1664static LogicalResult
convert(SeverityBIOp op, SeverityBIOp::Adaptor adaptor,
1665 ConversionPatternRewriter &rewriter) {
1667 std::string severityString;
1669 switch (op.getSeverity()) {
1670 case (Severity::Fatal):
1671 severityString =
"Fatal: ";
1673 case (Severity::Error):
1674 severityString =
"Error: ";
1676 case (Severity::Warning):
1677 severityString =
"Warning: ";
1684 rewriter.create<sim::FormatLiteralOp>(op.getLoc(), severityString);
1685 auto message = rewriter.create<sim::FormatStringConcatOp>(
1686 op.getLoc(), ValueRange{prefix, adaptor.getMessage()});
1687 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(op, message);
1693 FinishMessageBIOp::Adaptor adaptor,
1694 ConversionPatternRewriter &rewriter) {
1696 rewriter.eraseOp(op);
1705 const TypeConverter &converter) {
1706 target.addIllegalDialect<MooreDialect>();
1707 target.addLegalDialect<comb::CombDialect>();
1708 target.addLegalDialect<hw::HWDialect>();
1709 target.addLegalDialect<seq::SeqDialect>();
1710 target.addLegalDialect<llhd::LLHDDialect>();
1711 target.addLegalDialect<ltl::LTLDialect>();
1712 target.addLegalDialect<mlir::BuiltinDialect>();
1713 target.addLegalDialect<mlir::math::MathDialect>();
1714 target.addLegalDialect<sim::SimDialect>();
1715 target.addLegalDialect<verif::VerifDialect>();
1717 target.addLegalOp<debug::ScopeOp>();
1719 target.addDynamicallyLegalOp<
1720 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1721 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1722 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1723 [&](Operation *op) {
return converter.isLegal(op); });
1725 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1726 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1727 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1730 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1731 return converter.isSignatureLegal(op.getFunctionType()) &&
1732 converter.isLegal(&op.getFunctionBody());
1736 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1737 converter.isLegal(&op.getBody());
1742 typeConverter.addConversion([&](IntType type) {
1743 return IntegerType::get(type.getContext(), type.getWidth());
1746 typeConverter.addConversion(
1747 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
1749 typeConverter.addConversion([&](FormatStringType type) {
1750 return sim::FormatStringType::get(type.getContext());
1753 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1754 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1755 return hw::ArrayType::get(
elementType, type.getSize());
1762 typeConverter.addConversion(
1763 [&](UnpackedArrayType type) -> std::optional<Type> {
1764 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1765 return hw::ArrayType::get(
elementType, type.getSize());
1769 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1770 SmallVector<hw::StructType::FieldInfo> fields;
1771 for (
auto field : type.getMembers()) {
1772 hw::StructType::FieldInfo info;
1773 info.type = typeConverter.convertType(field.type);
1776 info.name = field.name;
1777 fields.push_back(info);
1779 return hw::StructType::get(type.getContext(), fields);
1787 typeConverter.addConversion(
1788 [&](UnpackedStructType type) -> std::optional<Type> {
1789 SmallVector<hw::StructType::FieldInfo> fields;
1790 for (
auto field : type.getMembers()) {
1791 hw::StructType::FieldInfo info;
1792 info.type = typeConverter.convertType(field.type);
1795 info.name = field.name;
1796 fields.push_back(info);
1798 return hw::StructType::get(type.getContext(), fields);
1801 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1802 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1803 if (hw::isHWValueType(innerType))
1804 return hw::InOutType::get(innerType);
1809 typeConverter.addConversion([](IntegerType type) {
return type; });
1810 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
1811 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1812 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1813 typeConverter.addConversion([](debug::StructType type) {
return type; });
1815 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1816 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1817 return hw::InOutType::get(innerType);
1821 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1822 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1823 return hw::ArrayType::get(
elementType, type.getNumElements());
1827 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1828 SmallVector<hw::StructType::FieldInfo> fields;
1829 for (
auto field : type.getElements()) {
1830 hw::StructType::FieldInfo info;
1831 info.type = typeConverter.convertType(field.type);
1834 info.name = field.name;
1835 fields.push_back(info);
1837 return hw::StructType::get(type.getContext(), fields);
1840 typeConverter.addTargetMaterialization(
1841 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1842 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1843 if (inputs.size() != 1 || !inputs[0])
1845 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1850 typeConverter.addSourceMaterialization(
1851 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1852 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1853 if (inputs.size() != 1)
1855 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1862 TypeConverter &typeConverter) {
1866 VariableOpConversion,
1870 ConversionOpConversion,
1871 BitcastConversion<PackedToSBVOp>,
1872 BitcastConversion<SBVToPackedOp>,
1873 BitcastConversion<LogicToIntOp>,
1874 BitcastConversion<IntToLogicOp>,
1875 BitcastConversion<ToBuiltinBoolOp>,
1883 ReplicateOpConversion,
1885 ExtractOpConversion,
1886 DynExtractOpConversion,
1887 DynExtractRefOpConversion,
1889 StructExtractOpConversion,
1890 StructExtractRefOpConversion,
1891 ExtractRefOpConversion,
1892 StructCreateOpConversion,
1893 ConditionalOpConversion,
1894 ArrayCreateOpConversion,
1897 StringConstantOpConv,
1900 ReduceAndOpConversion,
1901 ReduceOrOpConversion,
1902 ReduceXorOpConversion,
1903 BoolCastOpConversion,
1908 BinaryOpConversion<AddOp, comb::AddOp>,
1909 BinaryOpConversion<SubOp, comb::SubOp>,
1910 BinaryOpConversion<MulOp, comb::MulOp>,
1911 BinaryOpConversion<DivUOp, comb::DivUOp>,
1912 BinaryOpConversion<DivSOp, comb::DivSOp>,
1913 BinaryOpConversion<ModUOp, comb::ModUOp>,
1914 BinaryOpConversion<ModSOp, comb::ModSOp>,
1915 BinaryOpConversion<AndOp, comb::AndOp>,
1916 BinaryOpConversion<OrOp, comb::OrOp>,
1917 BinaryOpConversion<XorOp, comb::XorOp>,
1920 PowUOpConversion, PowSOpConversion,
1923 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1924 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1925 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1926 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1927 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1928 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1929 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1930 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1931 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1932 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1933 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1934 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1935 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1936 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1937 CaseXZEqOpConversion<CaseZEqOp, true>,
1938 CaseXZEqOpConversion<CaseXZEqOp, false>,
1941 SVModuleOpConversion,
1942 InstanceOpConversion,
1943 ProcedureOpConversion,
1944 WaitEventOpConversion,
1952 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1953 AssignOpConversion<BlockingAssignOp, 0, 1>,
1954 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1955 AssignedVariableOpConversion,
1958 CondBranchOpConversion,
1962 HWInstanceOpConversion,
1965 UnrealizedConversionCastConversion,
1966 InPlaceOpConversion<debug::ArrayOp>,
1967 InPlaceOpConversion<debug::StructOp>,
1968 InPlaceOpConversion<debug::VariableOp>,
1971 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1972 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1973 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1976 FormatLiteralOpConversion,
1977 FormatConcatOpConversion,
1978 FormatIntOpConversion,
1979 DisplayBIOpConversion
1980 >(typeConverter,
patterns.getContext());
1993 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1995 hw::populateHWModuleLikeTypeConversionPattern(
1996 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1997 populateSCFToControlFlowConversionPatterns(
patterns);
2006struct MooreToCorePass
2007 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
2008 void runOnOperation()
override;
2014 return std::make_unique<MooreToCorePass>();
2018void MooreToCorePass::runOnOperation() {
2019 MLIRContext &context = getContext();
2020 ModuleOp
module = getOperation();
2022 IRRewriter rewriter(module);
2023 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
2025 TypeConverter typeConverter;
2028 ConversionTarget target(context);
2034 if (failed(applyFullConversion(module, target, std::move(
patterns))))
2035 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(ConversionPatternSet &patterns, TypeConverter &typeConverter)
static LogicalResult convert(StopBIOp op, StopBIOp::Adaptor adaptor, ConversionPatternRewriter &rewriter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
Extension of RewritePatternSet that allows adding matchAndRewrite functions with op adaptors and Conv...
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.