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());
838 if (isa<hw::ArrayType>(
839 cast<hw::InOutType>(resultType).getElementType())) {
840 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
841 op, resultType, adaptor.getInput(), lowBit);
845 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
855 using OpConversionPattern::OpConversionPattern;
858 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
859 ConversionPatternRewriter &rewriter)
const override {
860 Type resultType = typeConverter->convertType(op.getResult().getType());
861 Type inputType = adaptor.getInput().getType();
863 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
864 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
865 intType.getWidth(), op->getLoc());
866 Value value = comb::ShrUOp::create(rewriter, op->getLoc(),
867 adaptor.getInput(), amount);
869 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
873 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
874 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
875 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
878 if (isa<hw::ArrayType>(resultType)) {
880 adaptor.getInput(), idx);
884 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
893 using OpConversionPattern::OpConversionPattern;
896 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
897 ConversionPatternRewriter &rewriter)
const override {
899 Type resultType = typeConverter->convertType(op.getResult().getType());
901 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
903 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
904 int64_t width = hw::getBitWidth(inputType);
909 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
910 llvm::Log2_64_Ceil(width), op->getLoc());
911 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
912 op, resultType, adaptor.getInput(), amount);
916 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
917 Value idx = adjustIntegerWidth(
918 rewriter, adaptor.getLowBit(),
919 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
921 if (isa<hw::ArrayType>(
922 cast<hw::InOutType>(resultType).getElementType())) {
923 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
924 op, resultType, adaptor.getInput(), idx);
928 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
938 using OpConversionPattern::OpConversionPattern;
941 matchAndRewrite(ArrayCreateOp op, OpAdaptor adaptor,
942 ConversionPatternRewriter &rewriter)
const override {
943 Type resultType = typeConverter->convertType(op.getResult().getType());
945 adaptor.getElements());
951 using OpConversionPattern::OpConversionPattern;
954 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
955 ConversionPatternRewriter &rewriter)
const override {
956 Type resultType = typeConverter->convertType(op.getResult().getType());
958 adaptor.getFields());
964 using OpConversionPattern::OpConversionPattern;
967 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
968 ConversionPatternRewriter &rewriter)
const override {
970 op, adaptor.getInput(), adaptor.getFieldNameAttr());
975struct StructExtractRefOpConversion
977 using OpConversionPattern::OpConversionPattern;
980 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
981 ConversionPatternRewriter &rewriter)
const override {
982 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
983 op, adaptor.getInput(), adaptor.getFieldNameAttr());
989 using OpConversionPattern::OpConversionPattern;
991 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
992 ConversionPatternRewriter &rewriter)
const override {
993 Type resultType = typeConverter->convertType(op.getInput().getType());
996 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
997 adaptor.getInput(), max);
1003 using OpConversionPattern::OpConversionPattern;
1005 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
1006 ConversionPatternRewriter &rewriter)
const override {
1007 Type resultType = typeConverter->convertType(op.getInput().getType());
1010 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1011 adaptor.getInput(), zero);
1017 using OpConversionPattern::OpConversionPattern;
1019 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
1020 ConversionPatternRewriter &rewriter)
const override {
1022 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
1028 using OpConversionPattern::OpConversionPattern;
1030 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
1031 ConversionPatternRewriter &rewriter)
const override {
1032 Type resultType = typeConverter->convertType(op.getInput().getType());
1033 if (isa_and_nonnull<IntegerType>(resultType)) {
1036 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
1037 adaptor.getInput(), zero);
1045 using OpConversionPattern::OpConversionPattern;
1047 matchAndRewrite(NotOp op, OpAdaptor adaptor,
1048 ConversionPatternRewriter &rewriter)
const override {
1050 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1053 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
1059 using OpConversionPattern::OpConversionPattern;
1061 matchAndRewrite(NegOp op, OpAdaptor adaptor,
1062 ConversionPatternRewriter &rewriter)
const override {
1064 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1067 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1072template <
typename SourceOp,
typename TargetOp>
1075 using OpAdaptor =
typename SourceOp::Adaptor;
1078 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1079 ConversionPatternRewriter &rewriter)
const override {
1080 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1081 adaptor.getRhs(),
false);
1086template <
typename SourceOp, ICmpPredicate pred>
1089 using OpAdaptor =
typename SourceOp::Adaptor;
1092 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1093 ConversionPatternRewriter &rewriter)
const override {
1095 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1097 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1098 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1103template <
typename SourceOp,
bool withoutX>
1106 using OpAdaptor =
typename SourceOp::Adaptor;
1109 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1110 ConversionPatternRewriter &rewriter)
const override {
1116 unsigned bitWidth = op.getLhs().getType().getWidth();
1117 auto ignoredBits = APInt::getZero(bitWidth);
1118 auto detectIgnoredBits = [&](Value value) {
1119 auto constOp = value.getDefiningOp<ConstantOp>();
1122 auto constValue = constOp.getValue();
1124 ignoredBits |= constValue.getZBits();
1126 ignoredBits |= constValue.getUnknownBits();
1128 detectIgnoredBits(op.getLhs());
1129 detectIgnoredBits(op.getRhs());
1133 Value lhs = adaptor.getLhs();
1134 Value rhs = adaptor.getRhs();
1135 if (!ignoredBits.isZero()) {
1136 ignoredBits.flipAllBits();
1138 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1139 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1142 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1152 using OpConversionPattern::OpConversionPattern;
1155 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1156 ConversionPatternRewriter &rewriter)
const override {
1157 Location loc = op.getLoc();
1158 Type resultType = typeConverter->convertType(op.getResult().getType());
1159 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1160 int64_t resultBw = hw::getBitWidth(resultType);
1161 if (inputBw == -1 || resultBw == -1)
1165 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1166 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1169 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1170 rewriter.replaceOp(op, result);
1175template <
typename SourceOp>
1178 using OpAdaptor =
typename SourceOp::Adaptor;
1179 using ConversionPattern::typeConverter;
1182 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1183 ConversionPatternRewriter &rewriter)
const override {
1184 auto type = typeConverter->convertType(op.getResult().getType());
1185 if (type == adaptor.getInput().getType())
1186 rewriter.replaceOp(op, adaptor.getInput());
1188 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, type, adaptor.getInput());
1194 using OpConversionPattern::OpConversionPattern;
1197 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1198 ConversionPatternRewriter &rewriter)
const override {
1199 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1200 op.getType().getWidth());
1206 using OpConversionPattern::OpConversionPattern;
1209 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1210 ConversionPatternRewriter &rewriter)
const override {
1211 auto targetWidth = op.getType().getWidth();
1212 auto inputWidth = op.getInput().getType().getWidth();
1215 rewriter, op.getLoc(),
1216 rewriter.getIntegerType(targetWidth - inputWidth), 0);
1219 op, ValueRange{zeroExt, adaptor.getInput()});
1225 using OpConversionPattern::OpConversionPattern;
1228 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1229 ConversionPatternRewriter &rewriter)
const override {
1230 auto type = typeConverter->convertType(op.getType());
1232 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1233 rewriter.replaceOp(op, value);
1243 using OpConversionPattern::OpConversionPattern;
1246 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1247 ConversionPatternRewriter &rewriter)
const override {
1248 SmallVector<Type> convResTypes;
1249 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1252 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1253 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1254 adaptor.getOperands(), op.getArgNames(),
1255 op.getResultNames(),
1256 rewriter.getArrayAttr({}),
nullptr);
1263 using OpConversionPattern::OpConversionPattern;
1266 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1267 ConversionPatternRewriter &rewriter)
const override {
1268 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1274 using OpConversionPattern::OpConversionPattern;
1277 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1278 ConversionPatternRewriter &rewriter)
const override {
1279 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1280 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1281 adaptor.getFalseDestOperands(),
nullptr,
1282 op.getTrueDest(), op.getFalseDest());
1288 using OpConversionPattern::OpConversionPattern;
1291 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1292 ConversionPatternRewriter &rewriter)
const override {
1293 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1294 adaptor.getDestOperands());
1300 using OpConversionPattern::OpConversionPattern;
1303 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1304 ConversionPatternRewriter &rewriter)
const override {
1305 SmallVector<Type> convResTypes;
1306 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1308 rewriter.replaceOpWithNewOp<func::CallOp>(
1309 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1314struct UnrealizedConversionCastConversion
1316 using OpConversionPattern::OpConversionPattern;
1319 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1320 ConversionPatternRewriter &rewriter)
const override {
1321 SmallVector<Type> convResTypes;
1322 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1327 if (convResTypes == adaptor.getOperands().getTypes()) {
1328 rewriter.replaceOp(op, adaptor.getOperands());
1332 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1333 op, convResTypes, adaptor.getOperands());
1339 using OpConversionPattern::OpConversionPattern;
1342 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1343 ConversionPatternRewriter &rewriter)
const override {
1344 Type resultType = typeConverter->convertType(op.getResult().getType());
1348 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1349 resultType.getIntOrFloatBitWidth(), op->getLoc());
1350 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1357 using OpConversionPattern::OpConversionPattern;
1360 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1361 ConversionPatternRewriter &rewriter)
const override {
1362 Type resultType = typeConverter->convertType(op.getResult().getType());
1366 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1367 resultType.getIntOrFloatBitWidth(), op->getLoc());
1369 op, resultType, adaptor.getValue(), amount,
false);
1375 using OpConversionPattern::OpConversionPattern;
1378 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1379 ConversionPatternRewriter &rewriter)
const override {
1380 Type resultType = typeConverter->convertType(op.getResult().getType());
1382 Location loc = op->getLoc();
1387 auto lhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getLhs());
1388 auto rhs = comb::ConcatOp::create(rewriter, loc, zeroVal, adaptor.getRhs());
1391 auto pow = mlir::math::IPowIOp::create(rewriter, loc, lhs, rhs);
1399 using OpConversionPattern::OpConversionPattern;
1402 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1403 ConversionPatternRewriter &rewriter)
const override {
1404 Type resultType = typeConverter->convertType(op.getResult().getType());
1408 rewriter.replaceOpWithNewOp<mlir::math::IPowIOp>(
1409 op, resultType, adaptor.getLhs(), adaptor.getRhs());
1415 using OpConversionPattern::OpConversionPattern;
1418 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1419 ConversionPatternRewriter &rewriter)
const override {
1420 Type resultType = typeConverter->convertType(op.getResult().getType());
1424 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1425 resultType.getIntOrFloatBitWidth(), op->getLoc());
1427 op, resultType, adaptor.getValue(), amount,
false);
1433 using OpConversionPattern::OpConversionPattern;
1436 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1437 ConversionPatternRewriter &rewriter)
const override {
1438 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1443struct AssignedVariableOpConversion
1445 using OpConversionPattern::OpConversionPattern;
1448 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1449 ConversionPatternRewriter &rewriter)
const override {
1450 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1451 adaptor.getNameAttr());
1456template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1459 using OpAdaptor =
typename OpTy::Adaptor;
1462 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1463 ConversionPatternRewriter &rewriter)
const override {
1466 auto timeAttr = llhd::TimeAttr::get(
1467 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1468 auto time = llhd::ConstantTimeOp::create(rewriter, op->getLoc(), timeAttr);
1469 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1470 adaptor.getSrc(), time, Value{});
1476 using OpConversionPattern::OpConversionPattern;
1479 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1480 ConversionPatternRewriter &rewriter)
const override {
1485 auto type = typeConverter->convertType(op.getType());
1487 auto hasNoWriteEffect = [](Region ®ion) {
1488 auto result = region.walk([](Operation *operation) {
1489 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1490 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1491 !memOp.hasEffect<MemoryEffects::Free>())
1492 return WalkResult::advance();
1494 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1495 return WalkResult::advance();
1497 return WalkResult::interrupt();
1499 return !result.wasInterrupted();
1502 if (hasNoWriteEffect(op.getTrueRegion()) &&
1503 hasNoWriteEffect(op.getFalseRegion())) {
1504 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1505 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1507 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1508 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1510 Value convTrueVal = typeConverter->materializeTargetConversion(
1511 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1512 Value convFalseVal = typeConverter->materializeTargetConversion(
1513 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1515 rewriter.eraseOp(trueTerm);
1516 rewriter.eraseOp(falseTerm);
1518 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1519 convTrueVal, convFalseVal);
1524 scf::IfOp::create(rewriter, op.getLoc(), type, adaptor.getCondition());
1525 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1526 ifOp.getThenRegion().end());
1527 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1528 ifOp.getElseRegion().end());
1529 rewriter.replaceOp(op, ifOp);
1535 using OpConversionPattern::OpConversionPattern;
1538 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1539 ConversionPatternRewriter &rewriter)
const override {
1540 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1545template <
typename SourceOp>
1548 using OpAdaptor =
typename SourceOp::Adaptor;
1551 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1552 ConversionPatternRewriter &rewriter)
const override {
1553 rewriter.modifyOpInPlace(op,
1554 [&]() { op->setOperands(adaptor.getOperands()); });
1559template <
typename MooreOpTy,
typename VerifOpTy>
1562 using OpAdaptor =
typename MooreOpTy::Adaptor;
1565 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1566 ConversionPatternRewriter &rewriter)
const override {
1568 op.getLabel().has_value()
1569 ? StringAttr::get(op->getContext(), op.getLabel().value())
1570 : StringAttr::
get(op->getContext());
1571 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1582 using OpConversionPattern::OpConversionPattern;
1585 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1586 ConversionPatternRewriter &rewriter)
const override {
1587 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1593 using OpConversionPattern::OpConversionPattern;
1596 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1597 ConversionPatternRewriter &rewriter)
const override {
1598 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1599 adaptor.getInputs());
1605 using OpConversionPattern::OpConversionPattern;
1608 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1609 ConversionPatternRewriter &rewriter)
const override {
1611 switch (op.getFormat()) {
1612 case IntFormat::Decimal:
1613 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1615 case IntFormat::Binary:
1616 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1618 case IntFormat::HexLower:
1619 case IntFormat::HexUpper:
1620 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1623 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1629 using OpConversionPattern::OpConversionPattern;
1632 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1633 ConversionPatternRewriter &rewriter)
const override {
1634 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1635 op, adaptor.getMessage());
1647static LogicalResult
convert(StopBIOp op, StopBIOp::Adaptor adaptor,
1648 ConversionPatternRewriter &rewriter) {
1649 rewriter.replaceOpWithNewOp<sim::PauseOp>(op,
false);
1654static LogicalResult
convert(FinishBIOp op, FinishBIOp::Adaptor adaptor,
1655 ConversionPatternRewriter &rewriter) {
1656 rewriter.replaceOpWithNewOp<sim::TerminateOp>(op, op.getExitCode() == 0,
1663 FinishMessageBIOp::Adaptor adaptor,
1664 ConversionPatternRewriter &rewriter) {
1666 rewriter.eraseOp(op);
1675 const TypeConverter &converter) {
1676 target.addIllegalDialect<MooreDialect>();
1677 target.addLegalDialect<comb::CombDialect>();
1678 target.addLegalDialect<hw::HWDialect>();
1679 target.addLegalDialect<seq::SeqDialect>();
1680 target.addLegalDialect<llhd::LLHDDialect>();
1681 target.addLegalDialect<ltl::LTLDialect>();
1682 target.addLegalDialect<mlir::BuiltinDialect>();
1683 target.addLegalDialect<mlir::math::MathDialect>();
1684 target.addLegalDialect<sim::SimDialect>();
1685 target.addLegalDialect<verif::VerifDialect>();
1687 target.addLegalOp<debug::ScopeOp>();
1689 target.addDynamicallyLegalOp<
1690 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1691 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1692 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1693 [&](Operation *op) {
return converter.isLegal(op); });
1695 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1696 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1697 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1700 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1701 return converter.isSignatureLegal(op.getFunctionType()) &&
1702 converter.isLegal(&op.getFunctionBody());
1706 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1707 converter.isLegal(&op.getBody());
1712 typeConverter.addConversion([&](IntType type) {
1713 return IntegerType::get(type.getContext(), type.getWidth());
1716 typeConverter.addConversion(
1717 [&](TimeType type) {
return llhd::TimeType::get(type.getContext()); });
1719 typeConverter.addConversion([&](FormatStringType type) {
1720 return sim::FormatStringType::get(type.getContext());
1723 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1724 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1725 return hw::ArrayType::get(
elementType, type.getSize());
1732 typeConverter.addConversion(
1733 [&](UnpackedArrayType type) -> std::optional<Type> {
1734 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1735 return hw::ArrayType::get(
elementType, type.getSize());
1739 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1740 SmallVector<hw::StructType::FieldInfo> fields;
1741 for (
auto field : type.getMembers()) {
1742 hw::StructType::FieldInfo info;
1743 info.type = typeConverter.convertType(field.type);
1746 info.name = field.name;
1747 fields.push_back(info);
1749 return hw::StructType::get(type.getContext(), fields);
1757 typeConverter.addConversion(
1758 [&](UnpackedStructType type) -> std::optional<Type> {
1759 SmallVector<hw::StructType::FieldInfo> fields;
1760 for (
auto field : type.getMembers()) {
1761 hw::StructType::FieldInfo info;
1762 info.type = typeConverter.convertType(field.type);
1765 info.name = field.name;
1766 fields.push_back(info);
1768 return hw::StructType::get(type.getContext(), fields);
1771 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1772 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1773 if (hw::isHWValueType(innerType))
1774 return hw::InOutType::get(innerType);
1779 typeConverter.addConversion([](IntegerType type) {
return type; });
1780 typeConverter.addConversion([](llhd::TimeType type) {
return type; });
1781 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1782 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1783 typeConverter.addConversion([](debug::StructType type) {
return type; });
1785 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1786 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1787 return hw::InOutType::get(innerType);
1791 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1792 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1793 return hw::ArrayType::get(
elementType, type.getNumElements());
1797 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1798 SmallVector<hw::StructType::FieldInfo> fields;
1799 for (
auto field : type.getElements()) {
1800 hw::StructType::FieldInfo info;
1801 info.type = typeConverter.convertType(field.type);
1804 info.name = field.name;
1805 fields.push_back(info);
1807 return hw::StructType::get(type.getContext(), fields);
1810 typeConverter.addTargetMaterialization(
1811 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1812 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1813 if (inputs.size() != 1 || !inputs[0])
1815 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1820 typeConverter.addSourceMaterialization(
1821 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1822 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1823 if (inputs.size() != 1)
1825 return UnrealizedConversionCastOp::create(builder, loc, resultType,
1832 TypeConverter &typeConverter) {
1836 VariableOpConversion,
1840 ConversionOpConversion,
1841 BitcastConversion<PackedToSBVOp>,
1842 BitcastConversion<SBVToPackedOp>,
1843 BitcastConversion<LogicToIntOp>,
1844 BitcastConversion<IntToLogicOp>,
1845 BitcastConversion<ToBuiltinBoolOp>,
1853 ReplicateOpConversion,
1855 ExtractOpConversion,
1856 DynExtractOpConversion,
1857 DynExtractRefOpConversion,
1859 StructExtractOpConversion,
1860 StructExtractRefOpConversion,
1861 ExtractRefOpConversion,
1862 StructCreateOpConversion,
1863 ConditionalOpConversion,
1864 ArrayCreateOpConversion,
1867 StringConstantOpConv,
1870 ReduceAndOpConversion,
1871 ReduceOrOpConversion,
1872 ReduceXorOpConversion,
1873 BoolCastOpConversion,
1878 BinaryOpConversion<AddOp, comb::AddOp>,
1879 BinaryOpConversion<SubOp, comb::SubOp>,
1880 BinaryOpConversion<MulOp, comb::MulOp>,
1881 BinaryOpConversion<DivUOp, comb::DivUOp>,
1882 BinaryOpConversion<DivSOp, comb::DivSOp>,
1883 BinaryOpConversion<ModUOp, comb::ModUOp>,
1884 BinaryOpConversion<ModSOp, comb::ModSOp>,
1885 BinaryOpConversion<AndOp, comb::AndOp>,
1886 BinaryOpConversion<OrOp, comb::OrOp>,
1887 BinaryOpConversion<XorOp, comb::XorOp>,
1890 PowUOpConversion, PowSOpConversion,
1893 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1894 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1895 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1896 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1897 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1898 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1899 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1900 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1901 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1902 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1903 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1904 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1905 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1906 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1907 CaseXZEqOpConversion<CaseZEqOp, true>,
1908 CaseXZEqOpConversion<CaseXZEqOp, false>,
1911 SVModuleOpConversion,
1912 InstanceOpConversion,
1913 ProcedureOpConversion,
1914 WaitEventOpConversion,
1922 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1923 AssignOpConversion<BlockingAssignOp, 0, 1>,
1924 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1925 AssignedVariableOpConversion,
1928 CondBranchOpConversion,
1932 HWInstanceOpConversion,
1935 UnrealizedConversionCastConversion,
1936 InPlaceOpConversion<debug::ArrayOp>,
1937 InPlaceOpConversion<debug::StructOp>,
1938 InPlaceOpConversion<debug::VariableOp>,
1941 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1942 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1943 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1946 FormatLiteralOpConversion,
1947 FormatConcatOpConversion,
1948 FormatIntOpConversion,
1949 DisplayBIOpConversion
1950 >(typeConverter,
patterns.getContext());
1962 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1964 hw::populateHWModuleLikeTypeConversionPattern(
1965 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1966 populateSCFToControlFlowConversionPatterns(
patterns);
1975struct MooreToCorePass
1976 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1977 void runOnOperation()
override;
1983 return std::make_unique<MooreToCorePass>();
1987void MooreToCorePass::runOnOperation() {
1988 MLIRContext &context = getContext();
1989 ModuleOp
module = getOperation();
1991 IRRewriter rewriter(module);
1992 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1994 TypeConverter typeConverter;
1997 ConversionTarget target(context);
2003 if (failed(applyFullConversion(module, target, std::move(
patterns))))
2004 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.