22#include "mlir/Conversion/SCFToControlFlow/SCFToControlFlow.h"
23#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
24#include "mlir/Dialect/Func/IR/FuncOps.h"
25#include "mlir/Dialect/SCF/IR/SCF.h"
26#include "mlir/IR/BuiltinDialect.h"
27#include "mlir/IR/Iterators.h"
28#include "mlir/Interfaces/SideEffectInterfaces.h"
29#include "mlir/Pass/Pass.h"
30#include "mlir/Transforms/DialectConversion.h"
31#include "mlir/Transforms/RegionUtils.h"
32#include "llvm/ADT/TypeSwitch.h"
35#define GEN_PASS_DEF_CONVERTMOORETOCORE
36#include "circt/Conversion/Passes.h.inc"
43using comb::ICmpPredicate;
44using llvm::SmallDenseSet;
52static Value adjustIntegerWidth(OpBuilder &builder, Value value,
53 uint32_t targetWidth, Location loc) {
54 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
55 if (intWidth == targetWidth)
58 if (intWidth < targetWidth) {
60 loc, builder.getIntegerType(targetWidth - intWidth), 0);
65 intWidth - targetWidth);
67 loc, builder.getIntegerType(intWidth - targetWidth), 0);
68 Value isZero = builder.
create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
72 loc, builder.getIntegerType(targetWidth), -1);
81 auto moduleTy = op.getModuleType();
82 SmallVector<hw::PortInfo> inputs, outputs;
83 inputs.reserve(moduleTy.getNumInputs());
84 outputs.reserve(moduleTy.getNumOutputs());
86 for (
auto port : moduleTy.getPorts()) {
87 Type portTy = typeConverter.convertType(port.type);
88 if (
auto ioTy = dyn_cast_or_null<hw::InOutType>(portTy)) {
96 if (port.dir == hw::ModulePort::Direction::Output) {
98 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
106 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
118 using OpConversionPattern::OpConversionPattern;
121 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
122 ConversionPatternRewriter &rewriter)
const override {
123 rewriter.setInsertionPoint(op);
128 getModulePortInfo(*typeConverter, op));
131 SymbolTable::setSymbolVisibility(hwModuleOp,
132 SymbolTable::getSymbolVisibility(op));
133 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
135 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
137 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
138 hwModuleOp.getBodyRegion().end());
141 rewriter.eraseOp(op);
147 using OpConversionPattern::OpConversionPattern;
150 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
151 ConversionPatternRewriter &rewriter)
const override {
152 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
158 using OpConversionPattern::OpConversionPattern;
161 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
162 ConversionPatternRewriter &rewriter)
const override {
163 auto instName = op.getInstanceNameAttr();
164 auto moduleName = op.getModuleNameAttr();
167 rewriter.setInsertionPoint(op);
168 auto instOp = rewriter.create<hw::InstanceOp>(
169 op.getLoc(), op.getResultTypes(), instName, moduleName, op.getInputs(),
170 op.getInputNamesAttr(), op.getOutputNamesAttr(),
171 rewriter.getArrayAttr({}),
nullptr,
175 op.replaceAllUsesWith(instOp.getResults());
176 rewriter.eraseOp(op);
181static void getValuesToObserve(Region *region,
182 function_ref<
void(Value)> setInsertionPoint,
183 const TypeConverter *typeConverter,
184 ConversionPatternRewriter &rewriter,
185 SmallVector<Value> &observeValues) {
186 SmallDenseSet<Value> alreadyObserved;
187 Location loc = region->getLoc();
189 auto probeIfSignal = [&](Value value) -> Value {
190 if (!isa<hw::InOutType>(value.getType()))
192 return rewriter.create<llhd::PrbOp>(loc, value);
195 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
196 [&](Operation *operation) {
197 for (
auto value : operation->getOperands()) {
198 if (region->isAncestor(value.getParentRegion()))
200 if (
auto *defOp = value.getDefiningOp();
201 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
203 if (!alreadyObserved.insert(value).second)
206 OpBuilder::InsertionGuard g(rewriter);
207 if (
auto remapped = rewriter.getRemappedValue(value)) {
208 setInsertionPoint(remapped);
209 observeValues.push_back(probeIfSignal(remapped));
211 setInsertionPoint(value);
212 auto type = typeConverter->convertType(value.getType());
213 auto converted = typeConverter->materializeTargetConversion(
214 rewriter, loc, type, value);
215 observeValues.push_back(probeIfSignal(converted));
222 using OpConversionPattern::OpConversionPattern;
225 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
226 ConversionPatternRewriter &rewriter)
const override {
228 SmallVector<Value> observedValues;
229 if (op.getKind() == ProcedureKind::AlwaysComb ||
230 op.getKind() == ProcedureKind::AlwaysLatch) {
231 auto setInsertionPoint = [&](Value value) {
232 rewriter.setInsertionPoint(op);
234 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
235 rewriter, observedValues);
238 auto loc = op.getLoc();
239 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
244 if (op.getKind() == ProcedureKind::Initial ||
245 op.getKind() == ProcedureKind::Final) {
247 if (op.getKind() == ProcedureKind::Initial)
248 newOp = rewriter.create<llhd::ProcessOp>(loc);
250 newOp = rewriter.create<llhd::FinalOp>(loc);
251 auto &body = newOp->getRegion(0);
252 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
254 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
255 rewriter.setInsertionPoint(returnOp);
256 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp);
258 rewriter.eraseOp(op);
263 auto newOp = rewriter.create<llhd::ProcessOp>(loc);
268 rewriter.createBlock(&newOp.getBody());
269 auto *block = &op.getBody().front();
270 rewriter.create<cf::BranchOp>(loc, block);
271 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
272 newOp.getBody().end());
280 if (op.getKind() == ProcedureKind::AlwaysComb ||
281 op.getKind() == ProcedureKind::AlwaysLatch) {
282 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
283 rewriter.create<llhd::WaitOp>(loc, observedValues, Value(), ValueRange{},
291 for (
auto returnOp :
llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
292 rewriter.setInsertionPoint(returnOp);
293 rewriter.create<cf::BranchOp>(loc, block);
294 rewriter.eraseOp(returnOp);
297 rewriter.eraseOp(op);
303 using OpConversionPattern::OpConversionPattern;
306 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
307 ConversionPatternRewriter &rewriter)
const override {
341 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
342 auto *waitBlock = rewriter.createBlock(resumeBlock);
343 auto *checkBlock = rewriter.createBlock(resumeBlock);
345 auto loc = op.getLoc();
346 rewriter.setInsertionPoint(op);
347 rewriter.create<cf::BranchOp>(loc, waitBlock);
357 SmallVector<Value> valuesBefore;
358 rewriter.setInsertionPointToEnd(waitBlock);
359 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
360 bool allDetectsAreAnyChange =
true;
362 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
363 if (detectOp.getEdge() != Edge::AnyChange || detectOp.getCondition())
364 allDetectsAreAnyChange =
false;
365 valuesBefore.push_back(detectOp.getInput());
366 rewriter.eraseOp(detectOp);
372 SmallVector<Value> observeValues;
373 auto setInsertionPointAfterDef = [&](Value value) {
374 if (
auto *op = value.getDefiningOp())
375 rewriter.setInsertionPointAfter(op);
376 if (
auto arg = dyn_cast<BlockArgument>(value))
377 rewriter.setInsertionPointToStart(value.getParentBlock());
380 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
381 typeConverter, rewriter, observeValues);
386 auto waitOp = rewriter.create<llhd::WaitOp>(loc, observeValues, Value(),
387 ValueRange{}, checkBlock);
388 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
389 rewriter.eraseOp(clonedOp);
393 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
394 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
396 rewriter.eraseOp(op);
400 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
401 assert(before.getType() == after.getType() &&
402 "mismatched types after clone op");
403 auto beforeType = cast<IntType>(before.getType());
407 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
408 constexpr int LSB = 0;
410 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
412 rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
413 after = rewriter.create<moore::ExtractOp>(loc, beforeType, after, LSB);
416 auto intType = rewriter.getIntegerType(beforeType.getWidth());
417 before = typeConverter->materializeTargetConversion(rewriter, loc,
419 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
422 if (edge == Edge::AnyChange)
423 return rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
426 SmallVector<Value> disjuncts;
427 Value trueVal = rewriter.create<
hw::ConstantOp>(loc, APInt(1, 1));
429 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
433 rewriter.create<
comb::AndOp>(loc, notOldVal, after,
true);
434 disjuncts.push_back(posedge);
437 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
439 rewriter.create<
comb::XorOp>(loc, after, trueVal,
true);
441 rewriter.create<
comb::AndOp>(loc, before, notCurrVal,
true);
442 disjuncts.push_back(posedge);
445 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
452 SmallVector<Value> triggers;
453 for (
auto [detectOp, before] :
llvm::zip(detectOps, valuesBefore)) {
454 if (!allDetectsAreAnyChange) {
455 if (!isa<IntType>(before.getType()))
456 return detectOp->emitError() <<
"requires int operand";
458 rewriter.setInsertionPoint(detectOp);
460 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
461 if (detectOp.getCondition()) {
462 auto condition = typeConverter->materializeTargetConversion(
463 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
464 trigger = rewriter.create<
comb::AndOp>(loc, trigger, condition,
true);
466 triggers.push_back(trigger);
469 rewriter.eraseOp(detectOp);
472 rewriter.setInsertionPointToEnd(checkBlock);
473 if (triggers.empty()) {
478 rewriter.create<cf::BranchOp>(loc, resumeBlock);
484 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
485 rewriter.create<cf::CondBranchOp>(loc, triggered, resumeBlock, waitBlock);
497 using OpConversionPattern::OpConversionPattern;
500 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
501 ConversionPatternRewriter &rewriter)
const override {
502 Location loc = op.getLoc();
503 Type resultType = typeConverter->convertType(op.getResult().getType());
505 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
508 Value init = adaptor.getInitial();
510 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
518 Value constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
522 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
523 op.getNameAttr(), init);
529 using OpConversionPattern::OpConversionPattern;
532 matchAndRewrite(NetOp op, OpAdaptor adaptor,
533 ConversionPatternRewriter &rewriter)
const override {
534 auto loc = op.getLoc();
535 if (op.getKind() != NetKind::Wire)
536 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
538 auto resultType = typeConverter->convertType(op.getResult().getType());
540 return rewriter.notifyMatchFailure(loc,
"invalid net type");
544 auto elementType = cast<hw::InOutType>(resultType).getElementType();
548 auto constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
552 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
553 op, resultType, op.getNameAttr(), init);
555 if (
auto assignedValue = adaptor.getAssignment()) {
556 auto timeAttr = llhd::TimeAttr::get(resultType.getContext(), 0U,
557 llvm::StringRef(
"ns"), 0, 1);
558 auto time = rewriter.create<llhd::ConstantTimeOp>(loc, timeAttr);
559 rewriter.create<llhd::DrvOp>(loc, signal, assignedValue, time, Value{});
571 using OpConversionPattern::OpConversionPattern;
574 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
575 ConversionPatternRewriter &rewriter)
const override {
577 auto value = op.getValue().toAPInt(
false);
578 auto type = rewriter.getIntegerType(value.getBitWidth());
580 op, type, rewriter.getIntegerAttr(type, value));
586 using OpConversionPattern::OpConversionPattern;
588 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
589 ConversionPatternRewriter &rewriter)
const override {
590 const auto str = op.getValue();
591 const unsigned byteWidth = str.size() * 8;
592 const auto resultType =
593 typeConverter->convertType(op.getResult().getType());
594 if (
const auto intType = mlir::dyn_cast<IntegerType>(resultType)) {
595 if (intType.getWidth() < byteWidth) {
596 return rewriter.notifyMatchFailure(op,
597 "invalid string constant type size");
600 return rewriter.notifyMatchFailure(op,
"invalid string constant type");
602 APInt value(byteWidth, 0);
603 for (
size_t i = 0; i < str.size(); ++i) {
604 const auto asciiChar =
static_cast<uint8_t
>(str[i]);
605 value |= APInt(byteWidth, asciiChar) << (8 * (str.size() - 1 - i));
608 op, resultType, rewriter.getIntegerAttr(resultType, value));
614 using OpConversionPattern::OpConversionPattern;
616 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
617 ConversionPatternRewriter &rewriter)
const override {
618 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
624 using OpConversionPattern::OpConversionPattern;
626 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
627 ConversionPatternRewriter &rewriter)
const override {
628 Type resultType = typeConverter->convertType(op.getResult().getType());
630 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
637 using OpConversionPattern::OpConversionPattern;
640 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
641 ConversionPatternRewriter &rewriter)
const override {
644 Type resultType = typeConverter->convertType(op.getResult().getType());
645 Type inputType = adaptor.getInput().getType();
646 int32_t low = adaptor.getLowBit();
648 if (isa<IntegerType>(inputType)) {
649 int32_t inputWidth = inputType.getIntOrFloatBitWidth();
650 int32_t resultWidth = resultType.getIntOrFloatBitWidth();
651 int32_t high = low + resultWidth;
653 SmallVector<Value> toConcat;
656 op.getLoc(), APInt(std::min(-low, resultWidth), 0)));
658 if (low < inputWidth && high > 0) {
659 int32_t lowIdx = std::max(low, 0);
662 rewriter.getIntegerType(
663 std::min(resultWidth, std::min(high, inputWidth) - lowIdx)),
664 adaptor.getInput(), lowIdx);
665 toConcat.push_back(middle);
668 int32_t diff = high - inputWidth;
672 toConcat.push_back(val);
677 rewriter.replaceOp(op,
concat);
681 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
682 int32_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
683 int32_t inputWidth = arrTy.getNumElements();
685 if (
auto resArrTy = dyn_cast<hw::ArrayType>(resultType)) {
686 int32_t elementWidth = hw::getBitWidth(arrTy.getElementType());
687 if (elementWidth < 0)
690 int32_t high = low + resArrTy.getNumElements();
691 int32_t resWidth = resArrTy.getNumElements();
693 SmallVector<Value> toConcat;
697 APInt(std::min((-low) * elementWidth, resWidth * elementWidth),
700 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), -low),
702 toConcat.push_back(res);
705 if (low < inputWidth && high > 0) {
706 int32_t lowIdx = std::max(0, low);
708 op.getLoc(), rewriter.getIntegerType(width), lowIdx);
712 arrTy.getElementType(),
713 std::min(resWidth, std::min(inputWidth, high) - lowIdx)),
714 adaptor.getInput(), lowIdxVal);
715 toConcat.push_back(middle);
718 int32_t diff = high - inputWidth;
721 op.getLoc(), APInt(diff * elementWidth, 0));
723 op.getLoc(), hw::ArrayType::get(arrTy.getElementType(), diff),
725 toConcat.push_back(val);
730 rewriter.replaceOp(op,
concat);
735 if (low < 0 || low >= inputWidth) {
736 int32_t bw = hw::getBitWidth(resultType);
740 Value val = rewriter.create<
hw::ConstantOp>(op.getLoc(), APInt(bw, 0));
742 rewriter.createOrFold<
hw::BitcastOp>(op.getLoc(), resultType, val);
743 rewriter.replaceOp(op, bitcast);
748 op.getLoc(), rewriter.getIntegerType(width), adaptor.getLowBit());
749 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
758 using OpConversionPattern::OpConversionPattern;
761 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
762 ConversionPatternRewriter &rewriter)
const override {
764 Type resultType = typeConverter->convertType(op.getResult().getType());
766 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
768 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
769 int64_t width = hw::getBitWidth(inputType);
774 op.getLoc(), rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
775 adaptor.getLowBit());
776 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
777 op, resultType, adaptor.getInput(), lowBit);
781 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
784 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
785 adaptor.getLowBit());
787 if (isa<hw::ArrayType>(
788 cast<hw::InOutType>(resultType).getElementType())) {
789 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
790 op, resultType, adaptor.getInput(), lowBit);
794 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
804 using OpConversionPattern::OpConversionPattern;
807 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
808 ConversionPatternRewriter &rewriter)
const override {
809 Type resultType = typeConverter->convertType(op.getResult().getType());
810 Type inputType = adaptor.getInput().getType();
812 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
813 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
814 intType.getWidth(), op->getLoc());
815 Value value = rewriter.create<
comb::ShrUOp>(op->getLoc(),
816 adaptor.getInput(), amount);
818 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
822 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
823 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
824 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
827 if (isa<hw::ArrayType>(resultType)) {
829 adaptor.getInput(), idx);
833 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
842 using OpConversionPattern::OpConversionPattern;
845 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
846 ConversionPatternRewriter &rewriter)
const override {
848 Type resultType = typeConverter->convertType(op.getResult().getType());
850 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
852 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
853 int64_t width = hw::getBitWidth(inputType);
858 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
859 llvm::Log2_64_Ceil(width), op->getLoc());
860 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
861 op, resultType, adaptor.getInput(), amount);
865 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
866 Value idx = adjustIntegerWidth(
867 rewriter, adaptor.getLowBit(),
868 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
870 if (isa<hw::ArrayType>(
871 cast<hw::InOutType>(resultType).getElementType())) {
872 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
873 op, resultType, adaptor.getInput(), idx);
877 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
887 using OpConversionPattern::OpConversionPattern;
890 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
891 ConversionPatternRewriter &rewriter)
const override {
892 Type resultType = typeConverter->convertType(op.getResult().getType());
894 adaptor.getFields());
900 using OpConversionPattern::OpConversionPattern;
903 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
904 ConversionPatternRewriter &rewriter)
const override {
906 op, adaptor.getInput(), adaptor.getFieldNameAttr());
911struct StructExtractRefOpConversion
913 using OpConversionPattern::OpConversionPattern;
916 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
917 ConversionPatternRewriter &rewriter)
const override {
918 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
919 op, adaptor.getInput(), adaptor.getFieldNameAttr());
925 using OpConversionPattern::OpConversionPattern;
927 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
928 ConversionPatternRewriter &rewriter)
const override {
929 Type resultType = typeConverter->convertType(op.getInput().getType());
930 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
932 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
933 adaptor.getInput(), max);
939 using OpConversionPattern::OpConversionPattern;
941 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
942 ConversionPatternRewriter &rewriter)
const override {
943 Type resultType = typeConverter->convertType(op.getInput().getType());
944 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
946 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
947 adaptor.getInput(), zero);
953 using OpConversionPattern::OpConversionPattern;
955 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
956 ConversionPatternRewriter &rewriter)
const override {
958 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
964 using OpConversionPattern::OpConversionPattern;
966 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
967 ConversionPatternRewriter &rewriter)
const override {
968 Type resultType = typeConverter->convertType(op.getInput().getType());
969 if (isa_and_nonnull<IntegerType>(resultType)) {
970 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
971 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
972 adaptor.getInput(), zero);
980 using OpConversionPattern::OpConversionPattern;
982 matchAndRewrite(NotOp op, OpAdaptor adaptor,
983 ConversionPatternRewriter &rewriter)
const override {
985 ConversionPattern::typeConverter->convertType(op.getResult().getType());
986 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
988 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
994 using OpConversionPattern::OpConversionPattern;
996 matchAndRewrite(NegOp op, OpAdaptor adaptor,
997 ConversionPatternRewriter &rewriter)
const override {
999 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1000 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
1002 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
1007template <
typename SourceOp,
typename TargetOp>
1010 using OpAdaptor =
typename SourceOp::Adaptor;
1013 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1014 ConversionPatternRewriter &rewriter)
const override {
1015 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
1016 adaptor.getRhs(),
false);
1021template <
typename SourceOp, ICmpPredicate pred>
1024 using OpAdaptor =
typename SourceOp::Adaptor;
1027 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1028 ConversionPatternRewriter &rewriter)
const override {
1030 ConversionPattern::typeConverter->convertType(op.getResult().getType());
1032 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
1033 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
1038template <
typename SourceOp,
bool withoutX>
1041 using OpAdaptor =
typename SourceOp::Adaptor;
1044 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1045 ConversionPatternRewriter &rewriter)
const override {
1051 unsigned bitWidth = op.getLhs().getType().getWidth();
1052 auto ignoredBits = APInt::getZero(bitWidth);
1053 auto detectIgnoredBits = [&](Value value) {
1054 auto constOp = value.getDefiningOp<ConstantOp>();
1057 auto constValue = constOp.getValue();
1059 ignoredBits |= constValue.getZBits();
1061 ignoredBits |= constValue.getUnknownBits();
1063 detectIgnoredBits(op.getLhs());
1064 detectIgnoredBits(op.getRhs());
1068 Value lhs = adaptor.getLhs();
1069 Value rhs = adaptor.getRhs();
1070 if (!ignoredBits.isZero()) {
1071 ignoredBits.flipAllBits();
1072 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
1073 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
1074 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
1077 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
1087 using OpConversionPattern::OpConversionPattern;
1090 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
1091 ConversionPatternRewriter &rewriter)
const override {
1092 Location loc = op.getLoc();
1093 Type resultType = typeConverter->convertType(op.getResult().getType());
1094 int64_t inputBw = hw::getBitWidth(adaptor.getInput().getType());
1095 int64_t resultBw = hw::getBitWidth(resultType);
1096 if (inputBw == -1 || resultBw == -1)
1100 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1101 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1104 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1105 rewriter.replaceOp(op, result);
1111 using OpConversionPattern::OpConversionPattern;
1114 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1115 ConversionPatternRewriter &rewriter)
const override {
1116 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1117 op.getType().getWidth());
1123 using OpConversionPattern::OpConversionPattern;
1126 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1127 ConversionPatternRewriter &rewriter)
const override {
1128 auto targetWidth = op.getType().getWidth();
1129 auto inputWidth = op.getInput().getType().getWidth();
1132 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1135 op, ValueRange{zeroExt, adaptor.getInput()});
1141 using OpConversionPattern::OpConversionPattern;
1144 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1145 ConversionPatternRewriter &rewriter)
const override {
1146 auto type = typeConverter->convertType(op.getType());
1148 comb::createOrFoldSExt(op.getLoc(), adaptor.getInput(), type, rewriter);
1149 rewriter.replaceOp(op, value);
1159 using OpConversionPattern::OpConversionPattern;
1162 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1163 ConversionPatternRewriter &rewriter)
const override {
1164 SmallVector<Type> convResTypes;
1165 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1168 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1169 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1170 adaptor.getOperands(), op.getArgNames(),
1171 op.getResultNames(),
1172 rewriter.getArrayAttr({}),
nullptr);
1179 using OpConversionPattern::OpConversionPattern;
1182 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1183 ConversionPatternRewriter &rewriter)
const override {
1184 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1190 using OpConversionPattern::OpConversionPattern;
1193 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1194 ConversionPatternRewriter &rewriter)
const override {
1195 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1196 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1197 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
1203 using OpConversionPattern::OpConversionPattern;
1206 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1207 ConversionPatternRewriter &rewriter)
const override {
1208 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1209 adaptor.getDestOperands());
1215 using OpConversionPattern::OpConversionPattern;
1218 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1219 ConversionPatternRewriter &rewriter)
const override {
1220 SmallVector<Type> convResTypes;
1221 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1223 rewriter.replaceOpWithNewOp<func::CallOp>(
1224 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1229struct UnrealizedConversionCastConversion
1231 using OpConversionPattern::OpConversionPattern;
1234 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1235 ConversionPatternRewriter &rewriter)
const override {
1236 SmallVector<Type> convResTypes;
1237 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1242 if (convResTypes == adaptor.getOperands().getTypes()) {
1243 rewriter.replaceOp(op, adaptor.getOperands());
1247 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1248 op, convResTypes, adaptor.getOperands());
1254 using OpConversionPattern::OpConversionPattern;
1257 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1258 ConversionPatternRewriter &rewriter)
const override {
1259 Type resultType = typeConverter->convertType(op.getResult().getType());
1263 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1264 resultType.getIntOrFloatBitWidth(), op->getLoc());
1265 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1272 using OpConversionPattern::OpConversionPattern;
1275 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1276 ConversionPatternRewriter &rewriter)
const override {
1277 Type resultType = typeConverter->convertType(op.getResult().getType());
1281 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1282 resultType.getIntOrFloatBitWidth(), op->getLoc());
1284 op, resultType, adaptor.getValue(), amount,
false);
1290 using OpConversionPattern::OpConversionPattern;
1293 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1294 ConversionPatternRewriter &rewriter)
const override {
1295 Type resultType = typeConverter->convertType(op.getResult().getType());
1297 Location loc = op.getLoc();
1298 auto intType = cast<IntType>(op.getRhs().getType());
1301 Type integerType = rewriter.getIntegerType(intType.getWidth());
1302 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1304 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1305 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1308 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1310 auto forOp = rewriter.create<scf::ForOp>(
1311 loc, lowerBound, upperBound, step, ValueRange(initVal),
1312 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1313 Value loopVar = iterArgs.front();
1315 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1318 rewriter.replaceOp(op, forOp.getResult(0));
1325 using OpConversionPattern::OpConversionPattern;
1328 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1329 ConversionPatternRewriter &rewriter)
const override {
1330 Type resultType = typeConverter->convertType(op.getResult().getType());
1332 Location loc = op.getLoc();
1333 auto intType = cast<IntType>(op.getRhs().getType());
1335 Type integerType = rewriter.getIntegerType(intType.getWidth());
1336 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1337 Value rhsVal = rewriter.create<ConversionOp>(loc, integerType, op.getRhs());
1338 Value constZero = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1340 Value isNegative = rewriter.
create<comb::ICmpOp>(loc, ICmpPredicate::slt,
1345 rewriter.create<
comb::MuxOp>(loc, isNegative, constZeroResult, lhsVal);
1347 rewriter.create<
comb::MuxOp>(loc, isNegative, constZero, rhsVal);
1349 Value lowerBound = constZero;
1350 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1353 auto forOp = rewriter.
create<scf::ForOp>(
1354 loc, lowerBound, upperBound, step, ValueRange(initVal),
1355 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1356 auto loopVar = iterArgs.front();
1358 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1361 rewriter.replaceOp(op, forOp.getResult(0));
1368 using OpConversionPattern::OpConversionPattern;
1371 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1372 ConversionPatternRewriter &rewriter)
const override {
1373 Type resultType = typeConverter->convertType(op.getResult().getType());
1377 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1378 resultType.getIntOrFloatBitWidth(), op->getLoc());
1380 op, resultType, adaptor.getValue(), amount,
false);
1386 using OpConversionPattern::OpConversionPattern;
1389 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1390 ConversionPatternRewriter &rewriter)
const override {
1391 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1396struct AssignedVariableOpConversion
1398 using OpConversionPattern::OpConversionPattern;
1401 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1402 ConversionPatternRewriter &rewriter)
const override {
1403 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1404 adaptor.getNameAttr());
1409template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1412 using OpAdaptor =
typename OpTy::Adaptor;
1415 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1416 ConversionPatternRewriter &rewriter)
const override {
1419 auto timeAttr = llhd::TimeAttr::get(
1420 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1421 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1422 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1423 adaptor.getSrc(), time, Value{});
1429 using OpConversionPattern::OpConversionPattern;
1432 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1433 ConversionPatternRewriter &rewriter)
const override {
1438 auto type = typeConverter->convertType(op.getType());
1440 auto hasNoWriteEffect = [](Region ®ion) {
1441 auto result = region.walk([](Operation *operation) {
1442 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1443 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1444 !memOp.hasEffect<MemoryEffects::Free>())
1445 return WalkResult::advance();
1447 if (operation->hasTrait<OpTrait::HasRecursiveMemoryEffects>())
1448 return WalkResult::advance();
1450 return WalkResult::interrupt();
1452 return !result.wasInterrupted();
1455 if (hasNoWriteEffect(op.getTrueRegion()) &&
1456 hasNoWriteEffect(op.getFalseRegion())) {
1457 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1458 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1460 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1461 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1463 Value convTrueVal = typeConverter->materializeTargetConversion(
1464 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1465 Value convFalseVal = typeConverter->materializeTargetConversion(
1466 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1468 rewriter.eraseOp(trueTerm);
1469 rewriter.eraseOp(falseTerm);
1471 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1472 convTrueVal, convFalseVal);
1477 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1478 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1479 ifOp.getThenRegion().end());
1480 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1481 ifOp.getElseRegion().end());
1482 rewriter.replaceOp(op, ifOp);
1488 using OpConversionPattern::OpConversionPattern;
1491 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1492 ConversionPatternRewriter &rewriter)
const override {
1493 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1498template <
typename SourceOp>
1501 using OpAdaptor =
typename SourceOp::Adaptor;
1504 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1505 ConversionPatternRewriter &rewriter)
const override {
1506 rewriter.modifyOpInPlace(op,
1507 [&]() { op->setOperands(adaptor.getOperands()); });
1512template <
typename MooreOpTy,
typename VerifOpTy>
1515 using OpAdaptor =
typename MooreOpTy::Adaptor;
1518 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1519 ConversionPatternRewriter &rewriter)
const override {
1521 op.getLabel().has_value()
1522 ? StringAttr::get(op->getContext(), op.getLabel().value())
1523 : StringAttr::
get(op->getContext());
1524 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1535 using OpConversionPattern::OpConversionPattern;
1538 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1539 ConversionPatternRewriter &rewriter)
const override {
1540 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1546 using OpConversionPattern::OpConversionPattern;
1549 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1550 ConversionPatternRewriter &rewriter)
const override {
1551 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1552 adaptor.getInputs());
1558 using OpConversionPattern::OpConversionPattern;
1561 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1562 ConversionPatternRewriter &rewriter)
const override {
1564 switch (op.getFormat()) {
1565 case IntFormat::Decimal:
1566 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1568 case IntFormat::Binary:
1569 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1571 case IntFormat::HexLower:
1572 case IntFormat::HexUpper:
1573 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1576 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1582 using OpConversionPattern::OpConversionPattern;
1585 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1586 ConversionPatternRewriter &rewriter)
const override {
1587 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1588 op, adaptor.getMessage());
1600 const TypeConverter &converter) {
1601 target.addIllegalDialect<MooreDialect>();
1602 target.addLegalDialect<comb::CombDialect>();
1603 target.addLegalDialect<hw::HWDialect>();
1604 target.addLegalDialect<llhd::LLHDDialect>();
1605 target.addLegalDialect<mlir::BuiltinDialect>();
1606 target.addLegalDialect<sim::SimDialect>();
1607 target.addLegalDialect<verif::VerifDialect>();
1609 target.addLegalOp<debug::ScopeOp>();
1611 target.addDynamicallyLegalOp<
1612 cf::CondBranchOp, cf::BranchOp, scf::YieldOp, func::CallOp,
1613 func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp, hw::InstanceOp,
1614 debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1615 [&](Operation *op) {
return converter.isLegal(op); });
1617 target.addDynamicallyLegalOp<scf::IfOp, scf::ForOp, scf::ExecuteRegionOp,
1618 scf::WhileOp, scf::ForallOp>([&](Operation *op) {
1619 return converter.isLegal(op) && !op->getParentOfType<llhd::ProcessOp>();
1622 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1623 return converter.isSignatureLegal(op.getFunctionType()) &&
1624 converter.isLegal(&op.getFunctionBody());
1628 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1629 converter.isLegal(&op.getBody());
1634 typeConverter.addConversion([&](IntType type) {
1635 return IntegerType::get(type.getContext(), type.getWidth());
1638 typeConverter.addConversion([&](FormatStringType type) {
1639 return sim::FormatStringType::get(type.getContext());
1642 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1643 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1644 return hw::ArrayType::get(
elementType, type.getSize());
1651 typeConverter.addConversion(
1652 [&](UnpackedArrayType type) -> std::optional<Type> {
1653 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1654 return hw::ArrayType::get(
elementType, type.getSize());
1658 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1659 SmallVector<hw::StructType::FieldInfo> fields;
1660 for (
auto field : type.getMembers()) {
1661 hw::StructType::FieldInfo info;
1662 info.type = typeConverter.convertType(field.type);
1665 info.name = field.name;
1666 fields.push_back(info);
1668 return hw::StructType::get(type.getContext(), fields);
1676 typeConverter.addConversion(
1677 [&](UnpackedStructType type) -> std::optional<Type> {
1678 SmallVector<hw::StructType::FieldInfo> fields;
1679 for (
auto field : type.getMembers()) {
1680 hw::StructType::FieldInfo info;
1681 info.type = typeConverter.convertType(field.type);
1684 info.name = field.name;
1685 fields.push_back(info);
1687 return hw::StructType::get(type.getContext(), fields);
1690 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1691 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1692 return hw::InOutType::get(innerType);
1697 typeConverter.addConversion([](IntegerType type) {
return type; });
1698 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1699 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1700 typeConverter.addConversion([](debug::StructType type) {
return type; });
1702 typeConverter.addConversion([&](hw::InOutType type) -> std::optional<Type> {
1703 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1704 return hw::InOutType::get(innerType);
1708 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1709 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1710 return hw::ArrayType::get(
elementType, type.getNumElements());
1714 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1715 SmallVector<hw::StructType::FieldInfo> fields;
1716 for (
auto field : type.getElements()) {
1717 hw::StructType::FieldInfo info;
1718 info.type = typeConverter.convertType(field.type);
1721 info.name = field.name;
1722 fields.push_back(info);
1724 return hw::StructType::get(type.getContext(), fields);
1727 typeConverter.addTargetMaterialization(
1728 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1729 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1730 if (inputs.size() != 1 || !inputs[0])
1733 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1737 typeConverter.addSourceMaterialization(
1738 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1739 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1740 if (inputs.size() != 1)
1743 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1749 TypeConverter &typeConverter) {
1750 auto *context =
patterns.getContext();
1754 VariableOpConversion,
1758 ConversionOpConversion,
1764 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1765 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1767 StructExtractOpConversion, StructExtractRefOpConversion,
1768 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion,
1769 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1772 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1773 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1776 BinaryOpConversion<AddOp, comb::AddOp>,
1777 BinaryOpConversion<SubOp, comb::SubOp>,
1778 BinaryOpConversion<MulOp, comb::MulOp>,
1779 BinaryOpConversion<DivUOp, comb::DivUOp>,
1780 BinaryOpConversion<DivSOp, comb::DivSOp>,
1781 BinaryOpConversion<ModUOp, comb::ModUOp>,
1782 BinaryOpConversion<ModSOp, comb::ModSOp>,
1783 BinaryOpConversion<AndOp, comb::AndOp>,
1784 BinaryOpConversion<OrOp, comb::OrOp>,
1785 BinaryOpConversion<XorOp, comb::XorOp>,
1788 PowUOpConversion, PowSOpConversion,
1791 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1792 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1793 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1794 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1795 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1796 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1797 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1798 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1799 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1800 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1801 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1802 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1803 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1804 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1805 CaseXZEqOpConversion<CaseZEqOp, true>,
1806 CaseXZEqOpConversion<CaseXZEqOp, false>,
1809 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1812 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1815 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1816 AssignOpConversion<BlockingAssignOp, 0, 1>,
1817 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1818 AssignedVariableOpConversion,
1821 CondBranchOpConversion, BranchOpConversion,
1824 HWInstanceOpConversion, ReturnOpConversion,
1825 CallOpConversion, UnrealizedConversionCastConversion,
1826 InPlaceOpConversion<debug::ArrayOp>,
1827 InPlaceOpConversion<debug::StructOp>,
1828 InPlaceOpConversion<debug::VariableOp>,
1831 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1832 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1833 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1836 FormatLiteralOpConversion,
1837 FormatConcatOpConversion,
1838 FormatIntOpConversion,
1839 DisplayBIOpConversion
1840 >(typeConverter, context);
1843 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1845 hw::populateHWModuleLikeTypeConversionPattern(
1846 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1847 populateSCFToControlFlowConversionPatterns(
patterns);
1856struct MooreToCorePass
1857 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1858 void runOnOperation()
override;
1864 return std::make_unique<MooreToCorePass>();
1868void MooreToCorePass::runOnOperation() {
1869 MLIRContext &context = getContext();
1870 ModuleOp
module = getOperation();
1872 IRRewriter rewriter(module);
1873 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1875 ConversionTarget target(context);
1876 TypeConverter typeConverter;
1877 RewritePatternSet
patterns(&context);
1882 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1883 signalPassFailure();
assert(baseType &&"element must be base type")
static SmallVector< T > concat(const SmallVectorImpl< T > &a, const SmallVectorImpl< T > &b)
Returns a new vector containing the concatenation of vectors a and b.
static void populateOpConversion(RewritePatternSet &patterns, TypeConverter &typeConverter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
create(array_value, low_index, ret_type)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
void populateArithToCombPatterns(mlir::RewritePatternSet &patterns, TypeConverter &typeConverter)
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.
This holds a decoded list of input/inout and output ports for a module or instance.
This holds the name, type, direction of a module's ports.