21 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
22 #include "mlir/Dialect/Func/IR/FuncOps.h"
23 #include "mlir/Dialect/SCF/IR/SCF.h"
24 #include "mlir/IR/BuiltinDialect.h"
25 #include "mlir/IR/Iterators.h"
26 #include "mlir/Interfaces/SideEffectInterfaces.h"
27 #include "mlir/Pass/Pass.h"
28 #include "mlir/Transforms/DialectConversion.h"
29 #include "mlir/Transforms/RegionUtils.h"
30 #include "llvm/ADT/TypeSwitch.h"
33 #define GEN_PASS_DEF_CONVERTMOORETOCORE
34 #include "circt/Conversion/Passes.h.inc"
38 using namespace circt;
39 using namespace moore;
41 using comb::ICmpPredicate;
42 using llvm::SmallDenseSet;
50 static Value adjustIntegerWidth(OpBuilder &builder, Value value,
51 uint32_t targetWidth, Location loc) {
52 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
53 if (intWidth == targetWidth)
56 if (intWidth < targetWidth) {
58 loc, builder.getIntegerType(targetWidth - intWidth), 0);
63 intWidth - targetWidth);
65 loc, builder.getIntegerType(intWidth - targetWidth), 0);
66 Value isZero = builder.
create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
70 loc, builder.getIntegerType(targetWidth), -1);
75 static hw::ModulePortInfo getModulePortInfo(
const TypeConverter &typeConverter,
79 auto moduleTy = op.getModuleType();
80 SmallVector<hw::PortInfo> inputs, outputs;
81 inputs.reserve(moduleTy.getNumInputs());
82 outputs.reserve(moduleTy.getNumOutputs());
84 for (
auto port : moduleTy.getPorts()) {
85 Type portTy = typeConverter.convertType(port.type);
86 if (
auto ioTy = dyn_cast_or_null<hw::InOutType>(portTy)) {
87 inputs.push_back(hw::PortInfo(
96 hw::PortInfo({{port.name, portTy, port.dir}, resultNum++, {}}));
104 hw::PortInfo({{port.name, portTy, port.dir}, inputNum++, {}}));
108 return hw::ModulePortInfo(inputs, outputs);
116 using OpConversionPattern::OpConversionPattern;
119 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
120 ConversionPatternRewriter &rewriter)
const override {
121 rewriter.setInsertionPoint(op);
126 getModulePortInfo(*typeConverter, op));
129 SymbolTable::setSymbolVisibility(hwModuleOp,
130 SymbolTable::getSymbolVisibility(op));
131 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
133 rewriter.convertRegionTypes(&op.getBodyRegion(), *typeConverter)))
135 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
136 hwModuleOp.getBodyRegion().end());
139 rewriter.eraseOp(op);
145 using OpConversionPattern::OpConversionPattern;
148 matchAndRewrite(OutputOp op, OpAdaptor adaptor,
149 ConversionPatternRewriter &rewriter)
const override {
150 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
156 using OpConversionPattern::OpConversionPattern;
159 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
160 ConversionPatternRewriter &rewriter)
const override {
161 auto instName = op.getInstanceNameAttr();
162 auto moduleName = op.getModuleNameAttr();
165 rewriter.setInsertionPoint(op);
166 auto instOp = rewriter.create<hw::InstanceOp>(
167 op.getLoc(), op.getResultTypes(), instName, moduleName, op.getInputs(),
168 op.getInputNamesAttr(), op.getOutputNamesAttr(),
169 rewriter.getArrayAttr({}),
nullptr,
173 op.replaceAllUsesWith(instOp.getResults());
174 rewriter.eraseOp(op);
179 static void getValuesToObserve(Region *region,
180 function_ref<
void(Value)> setInsertionPoint,
181 const TypeConverter *typeConverter,
182 ConversionPatternRewriter &rewriter,
183 SmallVector<Value> &observeValues) {
184 SmallDenseSet<Value> alreadyObserved;
185 Location loc = region->getLoc();
187 auto probeIfSignal = [&](Value value) -> Value {
188 if (!isa<hw::InOutType>(value.getType()))
190 return rewriter.create<llhd::PrbOp>(loc, value);
193 region->getParentOp()->walk<WalkOrder::PreOrder, ForwardDominanceIterator<>>(
194 [&](Operation *operation) {
195 for (
auto value : operation->getOperands()) {
196 if (region->isAncestor(value.getParentRegion()))
198 if (
auto *defOp = value.getDefiningOp();
199 defOp && defOp->hasTrait<OpTrait::ConstantLike>())
201 if (!alreadyObserved.insert(value).second)
204 OpBuilder::InsertionGuard g(rewriter);
205 if (
auto remapped = rewriter.getRemappedValue(value)) {
206 setInsertionPoint(remapped);
207 observeValues.push_back(probeIfSignal(remapped));
209 setInsertionPoint(value);
210 auto type = typeConverter->convertType(value.getType());
211 auto converted = typeConverter->materializeTargetConversion(
212 rewriter, loc, type, value);
213 observeValues.push_back(probeIfSignal(converted));
220 using OpConversionPattern::OpConversionPattern;
223 matchAndRewrite(ProcedureOp op, OpAdaptor adaptor,
224 ConversionPatternRewriter &rewriter)
const override {
226 SmallVector<Value> observedValues;
227 if (op.getKind() == ProcedureKind::AlwaysComb ||
228 op.getKind() == ProcedureKind::AlwaysLatch) {
229 auto setInsertionPoint = [&](Value value) {
230 rewriter.setInsertionPoint(op);
232 getValuesToObserve(&op.getBody(), setInsertionPoint, typeConverter,
233 rewriter, observedValues);
236 auto loc = op.getLoc();
237 if (failed(rewriter.convertRegionTypes(&op.getBody(), *typeConverter)))
242 if (op.getKind() == ProcedureKind::Initial ||
243 op.getKind() == ProcedureKind::Final) {
245 if (op.getKind() == ProcedureKind::Initial)
246 newOp = rewriter.create<llhd::ProcessOp>(loc);
248 newOp = rewriter.create<llhd::FinalOp>(loc);
249 auto &body = newOp->getRegion(0);
250 rewriter.inlineRegionBefore(op.getBody(), body, body.end());
252 llvm::make_early_inc_range(body.getOps<ReturnOp>())) {
253 rewriter.setInsertionPoint(returnOp);
254 rewriter.replaceOpWithNewOp<llhd::HaltOp>(returnOp);
256 rewriter.eraseOp(op);
261 auto newOp = rewriter.create<llhd::ProcessOp>(loc);
266 rewriter.createBlock(&newOp.getBody());
267 auto *block = &op.getBody().front();
268 rewriter.create<cf::BranchOp>(loc, block);
269 rewriter.inlineRegionBefore(op.getBody(), newOp.getBody(),
270 newOp.getBody().end());
278 if (op.getKind() == ProcedureKind::AlwaysComb ||
279 op.getKind() == ProcedureKind::AlwaysLatch) {
280 Block *waitBlock = rewriter.createBlock(&newOp.getBody());
281 rewriter.create<llhd::WaitOp>(loc, observedValues, Value(), ValueRange{},
289 for (
auto returnOp : llvm::make_early_inc_range(newOp.getOps<ReturnOp>())) {
290 rewriter.setInsertionPoint(returnOp);
291 rewriter.create<cf::BranchOp>(loc, block);
292 rewriter.eraseOp(returnOp);
295 rewriter.eraseOp(op);
301 using OpConversionPattern::OpConversionPattern;
304 matchAndRewrite(WaitEventOp op, OpAdaptor adaptor,
305 ConversionPatternRewriter &rewriter)
const override {
339 rewriter.splitBlock(op->getBlock(), ++Block::iterator(op));
340 auto *waitBlock = rewriter.createBlock(resumeBlock);
341 auto *checkBlock = rewriter.createBlock(resumeBlock);
343 auto loc = op.getLoc();
344 rewriter.setInsertionPoint(op);
345 rewriter.create<cf::BranchOp>(loc, waitBlock);
355 SmallVector<Value> valuesBefore;
356 rewriter.setInsertionPointToEnd(waitBlock);
357 auto clonedOp = cast<WaitEventOp>(rewriter.clone(*op));
359 llvm::make_early_inc_range(clonedOp.getOps<DetectEventOp>())) {
360 valuesBefore.push_back(detectOp.getInput());
361 rewriter.eraseOp(detectOp);
367 SmallVector<Value> observeValues;
368 auto setInsertionPointAfterDef = [&](Value value) {
369 if (
auto *op = value.getDefiningOp())
370 rewriter.setInsertionPointAfter(op);
371 if (
auto arg = dyn_cast<BlockArgument>(value))
372 rewriter.setInsertionPointToStart(value.getParentBlock());
375 getValuesToObserve(&clonedOp.getBody(), setInsertionPointAfterDef,
376 typeConverter, rewriter, observeValues);
381 auto waitOp = rewriter.create<llhd::WaitOp>(loc, observeValues, Value(),
382 ValueRange{}, checkBlock);
383 rewriter.inlineBlockBefore(&clonedOp.getBody().front(), waitOp);
384 rewriter.eraseOp(clonedOp);
388 SmallVector<DetectEventOp> detectOps(op.getBody().getOps<DetectEventOp>());
389 rewriter.inlineBlockBefore(&op.getBody().front(), checkBlock,
391 rewriter.eraseOp(op);
395 auto computeTrigger = [&](Value before, Value after, Edge edge) -> Value {
396 assert(before.getType() == after.getType() &&
397 "mismatched types after clone op");
398 auto beforeType = cast<IntType>(before.getType());
402 if (beforeType.getWidth() != 1 && edge != Edge::AnyChange) {
403 constexpr
int LSB = 0;
405 IntType::get(rewriter.getContext(), 1, beforeType.getDomain());
407 rewriter.create<moore::ExtractOp>(loc, beforeType, before, LSB);
408 after = rewriter.create<moore::ExtractOp>(loc, beforeType, after, LSB);
411 auto intType = rewriter.getIntegerType(beforeType.getWidth());
412 before = typeConverter->materializeTargetConversion(rewriter, loc,
414 after = typeConverter->materializeTargetConversion(rewriter, loc, intType,
417 if (edge == Edge::AnyChange)
418 return rewriter.create<comb::ICmpOp>(loc, ICmpPredicate::ne, before,
421 SmallVector<Value> disjuncts;
422 Value trueVal = rewriter.create<
hw::ConstantOp>(loc, APInt(1, 1));
424 if (edge == Edge::PosEdge || edge == Edge::BothEdges) {
428 rewriter.create<
comb::AndOp>(loc, notOldVal, after,
true);
429 disjuncts.push_back(posedge);
432 if (edge == Edge::NegEdge || edge == Edge::BothEdges) {
434 rewriter.create<
comb::XorOp>(loc, after, trueVal,
true);
436 rewriter.create<
comb::AndOp>(loc, before, notCurrVal,
true);
437 disjuncts.push_back(posedge);
440 return rewriter.createOrFold<
comb::OrOp>(loc, disjuncts,
true);
447 SmallVector<Value> triggers;
448 for (
auto [detectOp, before] : llvm::zip(detectOps, valuesBefore)) {
449 if (!isa<IntType>(before.getType()))
450 return detectOp->emitError() <<
"requires int operand";
452 rewriter.setInsertionPoint(detectOp);
454 computeTrigger(before, detectOp.getInput(), detectOp.getEdge());
455 if (detectOp.getCondition()) {
456 auto condition = typeConverter->materializeTargetConversion(
457 rewriter, loc, rewriter.getI1Type(), detectOp.getCondition());
458 trigger = rewriter.create<
comb::AndOp>(loc, trigger, condition,
true);
460 triggers.push_back(trigger);
461 rewriter.eraseOp(detectOp);
468 rewriter.setInsertionPointToEnd(checkBlock);
469 if (!triggers.empty()) {
470 auto triggered = rewriter.createOrFold<
comb::OrOp>(loc, triggers,
true);
471 rewriter.create<cf::CondBranchOp>(loc, triggered, resumeBlock, waitBlock);
473 rewriter.create<cf::BranchOp>(loc, waitBlock);
485 using OpConversionPattern::OpConversionPattern;
488 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
489 ConversionPatternRewriter &rewriter)
const override {
490 Location loc = op.getLoc();
491 Type resultType = typeConverter->convertType(op.getResult().getType());
493 return rewriter.notifyMatchFailure(op.getLoc(),
"invalid variable type");
496 Value init = adaptor.getInitial();
498 Type
elementType = cast<hw::InOutType>(resultType).getElementType();
506 Value constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
510 rewriter.replaceOpWithNewOp<llhd::SignalOp>(op, resultType,
511 op.getNameAttr(), init);
517 using OpConversionPattern::OpConversionPattern;
520 matchAndRewrite(NetOp op, OpAdaptor adaptor,
521 ConversionPatternRewriter &rewriter)
const override {
522 auto loc = op.getLoc();
523 if (op.getKind() != NetKind::Wire)
524 return rewriter.notifyMatchFailure(loc,
"only wire nets supported");
526 auto resultType = typeConverter->convertType(op.getResult().getType());
528 return rewriter.notifyMatchFailure(loc,
"invalid net type");
532 auto elementType = cast<hw::InOutType>(resultType).getElementType();
536 auto constZero = rewriter.create<
hw::ConstantOp>(loc, APInt(width, 0));
540 auto signal = rewriter.replaceOpWithNewOp<llhd::SignalOp>(
541 op, resultType, op.getNameAttr(), init);
543 if (
auto assignedValue = adaptor.getAssignment()) {
545 llvm::StringRef(
"ns"), 0, 1);
546 auto time = rewriter.create<llhd::ConstantTimeOp>(loc, timeAttr);
547 rewriter.create<llhd::DrvOp>(loc, signal, assignedValue, time, Value{});
559 using OpConversionPattern::OpConversionPattern;
562 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
563 ConversionPatternRewriter &rewriter)
const override {
565 auto value = op.getValue().toAPInt(
false);
566 auto type = rewriter.getIntegerType(value.getBitWidth());
568 op, type, rewriter.getIntegerAttr(type, value));
574 using OpConversionPattern::OpConversionPattern;
576 matchAndRewrite(moore::StringConstantOp op, OpAdaptor adaptor,
577 ConversionPatternRewriter &rewriter)
const override {
578 const auto str = op.getValue();
579 const unsigned byteWidth = str.size() * 8;
580 const auto resultType =
581 typeConverter->convertType(op.getResult().getType());
582 if (
const auto intType = mlir::dyn_cast<IntegerType>(resultType)) {
583 if (intType.getWidth() < byteWidth) {
584 return rewriter.notifyMatchFailure(op,
585 "invalid string constant type size");
588 return rewriter.notifyMatchFailure(op,
"invalid string constant type");
590 APInt value(byteWidth, 0);
591 for (
size_t i = 0; i < str.size(); ++i) {
592 const auto asciiChar =
static_cast<uint8_t
>(str[i]);
593 value |= APInt(byteWidth, asciiChar) << (8 * (str.size() - 1 - i));
596 op, resultType, rewriter.getIntegerAttr(resultType, value));
602 using OpConversionPattern::OpConversionPattern;
604 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
605 ConversionPatternRewriter &rewriter)
const override {
606 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
612 using OpConversionPattern::OpConversionPattern;
614 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
615 ConversionPatternRewriter &rewriter)
const override {
616 Type resultType = typeConverter->convertType(op.getResult().getType());
618 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
625 using OpConversionPattern::OpConversionPattern;
628 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
629 ConversionPatternRewriter &rewriter)
const override {
631 Type resultType = typeConverter->convertType(op.getResult().getType());
632 Type inputType = adaptor.getInput().getType();
634 if (isa<IntegerType>(inputType)) {
636 op, resultType, adaptor.getInput(), adaptor.getLowBit());
640 if (
auto arrTy = dyn_cast<hw::ArrayType>(inputType)) {
641 int64_t width = llvm::Log2_64_Ceil(arrTy.getNumElements());
643 op.getLoc(), rewriter.getIntegerType(width), adaptor.getLowBit());
644 if (isa<hw::ArrayType>(resultType)) {
646 adaptor.getInput(), idx);
651 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
660 using OpConversionPattern::OpConversionPattern;
663 matchAndRewrite(ExtractRefOp op, OpAdaptor adaptor,
664 ConversionPatternRewriter &rewriter)
const override {
666 Type resultType = typeConverter->convertType(op.getResult().getType());
668 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
670 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
676 op.getLoc(), rewriter.getIntegerType(llvm::Log2_64_Ceil(width)),
677 adaptor.getLowBit());
678 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
679 op, resultType, adaptor.getInput(), lowBit);
683 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
686 rewriter.getIntegerType(llvm::Log2_64_Ceil(arrType.getNumElements())),
687 adaptor.getLowBit());
689 if (isa<hw::ArrayType>(
690 cast<hw::InOutType>(resultType).getElementType())) {
691 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
692 op, resultType, adaptor.getInput(), lowBit);
696 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
706 using OpConversionPattern::OpConversionPattern;
709 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
710 ConversionPatternRewriter &rewriter)
const override {
711 Type resultType = typeConverter->convertType(op.getResult().getType());
712 Type inputType = adaptor.getInput().getType();
714 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
715 Value amount = adjustIntegerWidth(rewriter, adaptor.getLowBit(),
716 intType.getWidth(), op->getLoc());
717 Value value = rewriter.create<
comb::ShrUOp>(op->getLoc(),
718 adaptor.getInput(), amount);
720 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
724 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
725 unsigned idxWidth = llvm::Log2_64_Ceil(arrType.getNumElements());
726 Value idx = adjustIntegerWidth(rewriter, adaptor.getLowBit(), idxWidth,
729 if (isa<hw::ArrayType>(resultType)) {
731 adaptor.getInput(), idx);
735 rewriter.replaceOpWithNewOp<
hw::ArrayGetOp>(op, adaptor.getInput(), idx);
744 using OpConversionPattern::OpConversionPattern;
747 matchAndRewrite(DynExtractRefOp op, OpAdaptor adaptor,
748 ConversionPatternRewriter &rewriter)
const override {
750 Type resultType = typeConverter->convertType(op.getResult().getType());
752 cast<hw::InOutType>(adaptor.getInput().getType()).getElementType();
754 if (
auto intType = dyn_cast<IntegerType>(inputType)) {
760 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
761 llvm::Log2_64_Ceil(width), op->getLoc());
762 rewriter.replaceOpWithNewOp<llhd::SigExtractOp>(
763 op, resultType, adaptor.getInput(), amount);
767 if (
auto arrType = dyn_cast<hw::ArrayType>(inputType)) {
768 Value idx = adjustIntegerWidth(
769 rewriter, adaptor.getLowBit(),
770 llvm::Log2_64_Ceil(arrType.getNumElements()), op->getLoc());
772 if (isa<hw::ArrayType>(
773 cast<hw::InOutType>(resultType).getElementType())) {
774 rewriter.replaceOpWithNewOp<llhd::SigArraySliceOp>(
775 op, resultType, adaptor.getInput(), idx);
779 rewriter.replaceOpWithNewOp<llhd::SigArrayGetOp>(op, adaptor.getInput(),
789 using OpConversionPattern::OpConversionPattern;
792 matchAndRewrite(StructCreateOp op, OpAdaptor adaptor,
793 ConversionPatternRewriter &rewriter)
const override {
794 Type resultType = typeConverter->convertType(op.getResult().getType());
796 adaptor.getFields());
802 using OpConversionPattern::OpConversionPattern;
805 matchAndRewrite(StructExtractOp op, OpAdaptor adaptor,
806 ConversionPatternRewriter &rewriter)
const override {
808 op, adaptor.getInput(), adaptor.getFieldNameAttr());
813 struct StructExtractRefOpConversion
815 using OpConversionPattern::OpConversionPattern;
818 matchAndRewrite(StructExtractRefOp op, OpAdaptor adaptor,
819 ConversionPatternRewriter &rewriter)
const override {
820 rewriter.replaceOpWithNewOp<llhd::SigStructExtractOp>(
821 op, adaptor.getInput(), adaptor.getFieldNameAttr());
827 using OpConversionPattern::OpConversionPattern;
829 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
830 ConversionPatternRewriter &rewriter)
const override {
831 Type resultType = typeConverter->convertType(op.getInput().getType());
832 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
834 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
835 adaptor.getInput(), max);
841 using OpConversionPattern::OpConversionPattern;
843 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
844 ConversionPatternRewriter &rewriter)
const override {
845 Type resultType = typeConverter->convertType(op.getInput().getType());
846 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
848 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
849 adaptor.getInput(), zero);
855 using OpConversionPattern::OpConversionPattern;
857 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
858 ConversionPatternRewriter &rewriter)
const override {
860 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
866 using OpConversionPattern::OpConversionPattern;
868 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
869 ConversionPatternRewriter &rewriter)
const override {
870 Type resultType = typeConverter->convertType(op.getInput().getType());
871 if (isa_and_nonnull<IntegerType>(resultType)) {
872 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
873 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
874 adaptor.getInput(), zero);
882 using OpConversionPattern::OpConversionPattern;
884 matchAndRewrite(NotOp op, OpAdaptor adaptor,
885 ConversionPatternRewriter &rewriter)
const override {
887 ConversionPattern::typeConverter->convertType(op.getResult().getType());
888 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
890 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
896 using OpConversionPattern::OpConversionPattern;
898 matchAndRewrite(NegOp op, OpAdaptor adaptor,
899 ConversionPatternRewriter &rewriter)
const override {
901 ConversionPattern::typeConverter->convertType(op.getResult().getType());
902 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
904 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
909 template <
typename SourceOp,
typename TargetOp>
912 using OpAdaptor =
typename SourceOp::Adaptor;
915 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
916 ConversionPatternRewriter &rewriter)
const override {
917 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
918 adaptor.getRhs(),
false);
923 template <
typename SourceOp, ICmpPredicate pred>
926 using OpAdaptor =
typename SourceOp::Adaptor;
929 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
930 ConversionPatternRewriter &rewriter)
const override {
932 ConversionPattern::typeConverter->convertType(op.getResult().getType());
934 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
935 op, resultType, pred, adaptor.getLhs(), adaptor.getRhs());
940 template <
typename SourceOp,
bool withoutX>
943 using OpAdaptor =
typename SourceOp::Adaptor;
946 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
947 ConversionPatternRewriter &rewriter)
const override {
953 unsigned bitWidth = op.getLhs().getType().getWidth();
954 auto ignoredBits = APInt::getZero(bitWidth);
955 auto detectIgnoredBits = [&](Value value) {
956 auto constOp = value.getDefiningOp<ConstantOp>();
959 auto constValue = constOp.getValue();
961 ignoredBits |= constValue.getZBits();
963 ignoredBits |= constValue.getUnknownBits();
965 detectIgnoredBits(op.getLhs());
966 detectIgnoredBits(op.getRhs());
970 Value lhs = adaptor.getLhs();
971 Value rhs = adaptor.getRhs();
972 if (!ignoredBits.isZero()) {
973 ignoredBits.flipAllBits();
974 auto maskOp = rewriter.create<
hw::ConstantOp>(op.getLoc(), ignoredBits);
975 lhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), lhs, maskOp);
976 rhs = rewriter.createOrFold<
comb::AndOp>(op.getLoc(), rhs, maskOp);
979 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, ICmpPredicate::ceq, lhs, rhs);
989 using OpConversionPattern::OpConversionPattern;
992 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
993 ConversionPatternRewriter &rewriter)
const override {
994 Location loc = op.getLoc();
995 Type resultType = typeConverter->convertType(op.getResult().getType());
998 if (inputBw == -1 || resultBw == -1)
1002 loc, rewriter.getIntegerType(inputBw), adaptor.getInput());
1003 Value amount = adjustIntegerWidth(rewriter, input, resultBw, loc);
1006 rewriter.createOrFold<
hw::BitcastOp>(loc, resultType, amount);
1007 rewriter.replaceOp(op, result);
1013 using OpConversionPattern::OpConversionPattern;
1016 matchAndRewrite(TruncOp op, OpAdaptor adaptor,
1017 ConversionPatternRewriter &rewriter)
const override {
1018 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, adaptor.getInput(), 0,
1019 op.getType().getWidth());
1025 using OpConversionPattern::OpConversionPattern;
1028 matchAndRewrite(ZExtOp op, OpAdaptor adaptor,
1029 ConversionPatternRewriter &rewriter)
const override {
1030 auto targetWidth = op.getType().getWidth();
1031 auto inputWidth = op.getInput().getType().getWidth();
1034 op.getLoc(), rewriter.getIntegerType(targetWidth - inputWidth), 0);
1037 op, ValueRange{zeroExt, adaptor.getInput()});
1043 using OpConversionPattern::OpConversionPattern;
1046 matchAndRewrite(SExtOp op, OpAdaptor adaptor,
1047 ConversionPatternRewriter &rewriter)
const override {
1048 auto type = typeConverter->convertType(op.getType());
1051 rewriter.replaceOp(op, value);
1061 using OpConversionPattern::OpConversionPattern;
1064 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
1065 ConversionPatternRewriter &rewriter)
const override {
1066 SmallVector<Type> convResTypes;
1067 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1070 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
1071 op, convResTypes, op.getInstanceName(), op.getModuleName(),
1072 adaptor.getOperands(), op.getArgNames(),
1073 op.getResultNames(),
1074 rewriter.getArrayAttr({}),
nullptr);
1081 using OpConversionPattern::OpConversionPattern;
1084 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
1085 ConversionPatternRewriter &rewriter)
const override {
1086 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
1092 using OpConversionPattern::OpConversionPattern;
1095 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
1096 ConversionPatternRewriter &rewriter)
const override {
1097 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
1098 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
1099 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
1105 using OpConversionPattern::OpConversionPattern;
1108 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
1109 ConversionPatternRewriter &rewriter)
const override {
1110 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
1111 adaptor.getDestOperands());
1117 using OpConversionPattern::OpConversionPattern;
1120 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
1121 ConversionPatternRewriter &rewriter)
const override {
1122 SmallVector<Type> convResTypes;
1123 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1125 rewriter.replaceOpWithNewOp<func::CallOp>(
1126 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
1131 struct UnrealizedConversionCastConversion
1133 using OpConversionPattern::OpConversionPattern;
1136 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
1137 ConversionPatternRewriter &rewriter)
const override {
1138 SmallVector<Type> convResTypes;
1139 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
1144 if (convResTypes == adaptor.getOperands().getTypes()) {
1145 rewriter.replaceOp(op, adaptor.getOperands());
1149 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
1150 op, convResTypes, adaptor.getOperands());
1156 using OpConversionPattern::OpConversionPattern;
1159 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
1160 ConversionPatternRewriter &rewriter)
const override {
1161 Type resultType = typeConverter->convertType(op.getResult().getType());
1165 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1166 resultType.getIntOrFloatBitWidth(), op->getLoc());
1167 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
1174 using OpConversionPattern::OpConversionPattern;
1177 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
1178 ConversionPatternRewriter &rewriter)
const override {
1179 Type resultType = typeConverter->convertType(op.getResult().getType());
1183 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1184 resultType.getIntOrFloatBitWidth(), op->getLoc());
1186 op, resultType, adaptor.getValue(), amount,
false);
1192 using OpConversionPattern::OpConversionPattern;
1195 matchAndRewrite(PowUOp op, OpAdaptor adaptor,
1196 ConversionPatternRewriter &rewriter)
const override {
1197 Type resultType = typeConverter->convertType(op.getResult().getType());
1199 Location loc = op.getLoc();
1200 auto intType = cast<IntType>(op.getRhs().getType());
1203 Type integerType = rewriter.getIntegerType(intType.getWidth());
1204 Value lowerBound = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1206 rewriter.
create<ConversionOp>(loc, integerType, op.getRhs());
1207 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1210 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1212 auto forOp = rewriter.create<scf::ForOp>(
1213 loc, lowerBound, upperBound, step, ValueRange(initVal),
1214 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1215 Value loopVar = iterArgs.front();
1217 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1220 rewriter.replaceOp(op, forOp.getResult(0));
1227 using OpConversionPattern::OpConversionPattern;
1230 matchAndRewrite(PowSOp op, OpAdaptor adaptor,
1231 ConversionPatternRewriter &rewriter)
const override {
1232 Type resultType = typeConverter->convertType(op.getResult().getType());
1234 Location loc = op.getLoc();
1235 auto intType = cast<IntType>(op.getRhs().getType());
1237 Type integerType = rewriter.getIntegerType(intType.getWidth());
1238 Value lhsVal = rewriter.
create<ConversionOp>(loc, resultType, op.getLhs());
1239 Value rhsVal = rewriter.create<ConversionOp>(loc, integerType, op.getRhs());
1240 Value constZero = rewriter.create<
hw::ConstantOp>(loc, integerType, 0);
1242 Value isNegative = rewriter.
create<comb::ICmpOp>(loc, ICmpPredicate::slt,
1247 rewriter.create<
comb::MuxOp>(loc, isNegative, constZeroResult, lhsVal);
1249 rewriter.create<
comb::MuxOp>(loc, isNegative, constZero, rhsVal);
1251 Value lowerBound = constZero;
1252 Value step = rewriter.create<
hw::ConstantOp>(loc, integerType, 1);
1255 auto forOp = rewriter.
create<scf::ForOp>(
1256 loc, lowerBound, upperBound, step, ValueRange(initVal),
1257 [&](OpBuilder &builder, Location loc, Value i, ValueRange iterArgs) {
1258 auto loopVar = iterArgs.front();
1260 rewriter.create<scf::YieldOp>(loc, ValueRange(mul));
1263 rewriter.replaceOp(op, forOp.getResult(0));
1270 using OpConversionPattern::OpConversionPattern;
1273 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
1274 ConversionPatternRewriter &rewriter)
const override {
1275 Type resultType = typeConverter->convertType(op.getResult().getType());
1279 adjustIntegerWidth(rewriter, adaptor.getAmount(),
1280 resultType.getIntOrFloatBitWidth(), op->getLoc());
1282 op, resultType, adaptor.getValue(), amount,
false);
1288 using OpConversionPattern::OpConversionPattern;
1291 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
1292 ConversionPatternRewriter &rewriter)
const override {
1293 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, adaptor.getInput());
1298 struct AssignedVariableOpConversion
1300 using OpConversionPattern::OpConversionPattern;
1303 matchAndRewrite(AssignedVariableOp op, OpAdaptor adaptor,
1304 ConversionPatternRewriter &rewriter)
const override {
1305 rewriter.replaceOpWithNewOp<hw::WireOp>(op, adaptor.getInput(),
1306 adaptor.getNameAttr());
1311 template <
typename OpTy,
unsigned DeltaTime,
unsigned EpsilonTime>
1314 using OpAdaptor =
typename OpTy::Adaptor;
1317 matchAndRewrite(OpTy op, OpAdaptor adaptor,
1318 ConversionPatternRewriter &rewriter)
const override {
1322 op->getContext(), 0U, llvm::StringRef(
"ns"), DeltaTime, EpsilonTime);
1323 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
1324 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
1325 adaptor.getSrc(), time, Value{});
1331 using OpConversionPattern::OpConversionPattern;
1334 matchAndRewrite(ConditionalOp op, OpAdaptor adaptor,
1335 ConversionPatternRewriter &rewriter)
const override {
1340 auto type = typeConverter->convertType(op.getType());
1342 auto hasNoWriteEffect = [](Region ®ion) {
1343 auto result = region.walk([](Operation *operation) {
1344 if (
auto memOp = dyn_cast<MemoryEffectOpInterface>(operation))
1345 if (!memOp.hasEffect<MemoryEffects::Write>() &&
1346 !memOp.hasEffect<MemoryEffects::Free>())
1347 return WalkResult::advance();
1349 return WalkResult::interrupt();
1351 return !result.wasInterrupted();
1354 if (hasNoWriteEffect(op.getTrueRegion()) &&
1355 hasNoWriteEffect(op.getFalseRegion())) {
1356 Operation *trueTerm = op.getTrueRegion().front().getTerminator();
1357 Operation *falseTerm = op.getFalseRegion().front().getTerminator();
1359 rewriter.inlineBlockBefore(&op.getTrueRegion().front(), op);
1360 rewriter.inlineBlockBefore(&op.getFalseRegion().front(), op);
1362 Value convTrueVal = typeConverter->materializeTargetConversion(
1363 rewriter, op.getLoc(), type, trueTerm->getOperand(0));
1364 Value convFalseVal = typeConverter->materializeTargetConversion(
1365 rewriter, op.getLoc(), type, falseTerm->getOperand(0));
1367 rewriter.eraseOp(trueTerm);
1368 rewriter.eraseOp(falseTerm);
1370 rewriter.replaceOpWithNewOp<
comb::MuxOp>(op, adaptor.getCondition(),
1371 convTrueVal, convFalseVal);
1376 rewriter.create<scf::IfOp>(op.getLoc(), type, adaptor.getCondition());
1377 rewriter.inlineRegionBefore(op.getTrueRegion(), ifOp.getThenRegion(),
1378 ifOp.getThenRegion().end());
1379 rewriter.inlineRegionBefore(op.getFalseRegion(), ifOp.getElseRegion(),
1380 ifOp.getElseRegion().end());
1381 rewriter.replaceOp(op, ifOp);
1387 using OpConversionPattern::OpConversionPattern;
1390 matchAndRewrite(YieldOp op, OpAdaptor adaptor,
1391 ConversionPatternRewriter &rewriter)
const override {
1392 rewriter.replaceOpWithNewOp<scf::YieldOp>(op, adaptor.getResult());
1397 template <
typename SourceOp>
1400 using OpAdaptor =
typename SourceOp::Adaptor;
1403 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
1404 ConversionPatternRewriter &rewriter)
const override {
1405 rewriter.modifyOpInPlace(op,
1406 [&]() { op->setOperands(adaptor.getOperands()); });
1411 template <
typename MooreOpTy,
typename VerifOpTy>
1414 using OpAdaptor =
typename MooreOpTy::Adaptor;
1417 matchAndRewrite(MooreOpTy op, OpAdaptor adaptor,
1418 ConversionPatternRewriter &rewriter)
const override {
1420 op.getLabel().has_value()
1422 : StringAttr::
get(op->getContext());
1423 rewriter.replaceOpWithNewOp<VerifOpTy>(op, adaptor.getCond(), mlir::Value(),
1434 using OpConversionPattern::OpConversionPattern;
1437 matchAndRewrite(FormatLiteralOp op, OpAdaptor adaptor,
1438 ConversionPatternRewriter &rewriter)
const override {
1439 rewriter.replaceOpWithNewOp<sim::FormatLitOp>(op, adaptor.getLiteral());
1445 using OpConversionPattern::OpConversionPattern;
1448 matchAndRewrite(FormatConcatOp op, OpAdaptor adaptor,
1449 ConversionPatternRewriter &rewriter)
const override {
1450 rewriter.replaceOpWithNewOp<sim::FormatStringConcatOp>(op,
1451 adaptor.getInputs());
1457 using OpConversionPattern::OpConversionPattern;
1460 matchAndRewrite(FormatIntOp op, OpAdaptor adaptor,
1461 ConversionPatternRewriter &rewriter)
const override {
1463 switch (op.getFormat()) {
1464 case IntFormat::Decimal:
1465 rewriter.replaceOpWithNewOp<sim::FormatDecOp>(op, adaptor.getValue());
1467 case IntFormat::Binary:
1468 rewriter.replaceOpWithNewOp<sim::FormatBinOp>(op, adaptor.getValue());
1470 case IntFormat::HexLower:
1471 case IntFormat::HexUpper:
1472 rewriter.replaceOpWithNewOp<sim::FormatHexOp>(op, adaptor.getValue());
1475 return rewriter.notifyMatchFailure(op,
"unsupported int format");
1481 using OpConversionPattern::OpConversionPattern;
1484 matchAndRewrite(DisplayBIOp op, OpAdaptor adaptor,
1485 ConversionPatternRewriter &rewriter)
const override {
1486 rewriter.replaceOpWithNewOp<sim::PrintFormattedProcOp>(
1487 op, adaptor.getMessage());
1499 const TypeConverter &converter) {
1500 target.addIllegalDialect<MooreDialect>();
1501 target.addLegalDialect<comb::CombDialect>();
1502 target.addLegalDialect<hw::HWDialect>();
1503 target.addLegalDialect<llhd::LLHDDialect>();
1504 target.addLegalDialect<mlir::BuiltinDialect>();
1505 target.addLegalDialect<sim::SimDialect>();
1506 target.addLegalDialect<verif::VerifDialect>();
1508 target.addLegalOp<debug::ScopeOp>();
1510 target.addDynamicallyLegalOp<
1511 cf::CondBranchOp, cf::BranchOp, scf::IfOp, scf::ForOp, scf::YieldOp,
1512 func::CallOp, func::ReturnOp, UnrealizedConversionCastOp, hw::OutputOp,
1513 hw::InstanceOp, debug::ArrayOp, debug::StructOp, debug::VariableOp>(
1514 [&](Operation *op) {
return converter.isLegal(op); });
1516 target.addDynamicallyLegalOp<func::FuncOp>([&](func::FuncOp op) {
1517 return converter.isSignatureLegal(op.getFunctionType()) &&
1518 converter.isLegal(&op.getFunctionBody());
1522 return converter.isSignatureLegal(op.getModuleType().getFuncType()) &&
1523 converter.isLegal(&op.getBody());
1528 typeConverter.addConversion([&](IntType type) {
1532 typeConverter.addConversion([&](FormatStringType type) {
1536 typeConverter.addConversion([&](ArrayType type) -> std::optional<Type> {
1537 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1545 typeConverter.addConversion(
1546 [&](UnpackedArrayType type) -> std::optional<Type> {
1547 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1552 typeConverter.addConversion([&](StructType type) -> std::optional<Type> {
1553 SmallVector<hw::StructType::FieldInfo> fields;
1554 for (
auto field : type.getMembers()) {
1555 hw::StructType::FieldInfo info;
1556 info.type = typeConverter.convertType(field.type);
1559 info.name = field.name;
1560 fields.push_back(info);
1570 typeConverter.addConversion(
1571 [&](UnpackedStructType type) -> std::optional<Type> {
1572 SmallVector<hw::StructType::FieldInfo> fields;
1573 for (
auto field : type.getMembers()) {
1574 hw::StructType::FieldInfo info;
1575 info.type = typeConverter.convertType(field.type);
1578 info.name = field.name;
1579 fields.push_back(info);
1584 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
1585 if (
auto innerType = typeConverter.convertType(type.getNestedType()))
1591 typeConverter.addConversion([](IntegerType type) {
return type; });
1592 typeConverter.addConversion([](debug::ArrayType type) {
return type; });
1593 typeConverter.addConversion([](debug::ScopeType type) {
return type; });
1594 typeConverter.addConversion([](debug::StructType type) {
return type; });
1596 typeConverter.addConversion([&](
hw::InOutType type) -> std::optional<Type> {
1597 if (
auto innerType = typeConverter.convertType(type.getElementType()))
1602 typeConverter.addConversion([&](hw::ArrayType type) -> std::optional<Type> {
1603 if (
auto elementType = typeConverter.convertType(type.getElementType()))
1608 typeConverter.addConversion([&](hw::StructType type) -> std::optional<Type> {
1609 SmallVector<hw::StructType::FieldInfo> fields;
1610 for (
auto field : type.getElements()) {
1611 hw::StructType::FieldInfo info;
1612 info.type = typeConverter.convertType(field.type);
1615 info.name = field.name;
1616 fields.push_back(info);
1621 typeConverter.addTargetMaterialization(
1622 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1623 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1624 if (inputs.size() != 1 || !inputs[0])
1627 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1631 typeConverter.addSourceMaterialization(
1632 [&](mlir::OpBuilder &builder, mlir::Type resultType,
1633 mlir::ValueRange inputs, mlir::Location loc) -> mlir::Value {
1634 if (inputs.size() != 1)
1637 .create<UnrealizedConversionCastOp>(loc, resultType, inputs[0])
1643 TypeConverter &typeConverter) {
1644 auto *context =
patterns.getContext();
1648 VariableOpConversion,
1652 ConversionOpConversion,
1658 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
1659 ExtractOpConversion, DynExtractOpConversion, DynExtractRefOpConversion,
1661 StructExtractOpConversion, StructExtractRefOpConversion,
1662 ExtractRefOpConversion, StructCreateOpConversion, ConditionalOpConversion,
1663 YieldOpConversion, OutputOpConversion, StringConstantOpConv,
1666 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
1667 BoolCastOpConversion, NotOpConversion, NegOpConversion,
1670 BinaryOpConversion<AddOp, comb::AddOp>,
1671 BinaryOpConversion<SubOp, comb::SubOp>,
1672 BinaryOpConversion<MulOp, comb::MulOp>,
1673 BinaryOpConversion<DivUOp, comb::DivUOp>,
1674 BinaryOpConversion<DivSOp, comb::DivSOp>,
1675 BinaryOpConversion<ModUOp, comb::ModUOp>,
1676 BinaryOpConversion<ModSOp, comb::ModSOp>,
1677 BinaryOpConversion<AndOp, comb::AndOp>,
1678 BinaryOpConversion<OrOp, comb::OrOp>,
1679 BinaryOpConversion<XorOp, comb::XorOp>,
1682 PowUOpConversion, PowSOpConversion,
1685 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
1686 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
1687 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
1688 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
1689 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
1690 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
1691 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
1692 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
1693 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
1694 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
1695 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
1696 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
1697 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
1698 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
1699 CaseXZEqOpConversion<CaseZEqOp, true>,
1700 CaseXZEqOpConversion<CaseXZEqOp, false>,
1703 SVModuleOpConversion, InstanceOpConversion, ProcedureOpConversion, WaitEventOpConversion,
1706 ShrOpConversion, ShlOpConversion, AShrOpConversion,
1709 AssignOpConversion<ContinuousAssignOp, 0, 1>,
1710 AssignOpConversion<BlockingAssignOp, 0, 1>,
1711 AssignOpConversion<NonBlockingAssignOp, 1, 0>,
1712 AssignedVariableOpConversion,
1715 CondBranchOpConversion, BranchOpConversion,
1718 HWInstanceOpConversion, ReturnOpConversion,
1719 CallOpConversion, UnrealizedConversionCastConversion,
1720 InPlaceOpConversion<debug::ArrayOp>,
1721 InPlaceOpConversion<debug::StructOp>,
1722 InPlaceOpConversion<debug::VariableOp>,
1725 AssertLikeOpConversion<AssertOp, verif::AssertOp>,
1726 AssertLikeOpConversion<AssumeOp, verif::AssumeOp>,
1727 AssertLikeOpConversion<CoverOp, verif::CoverOp>,
1730 FormatLiteralOpConversion,
1731 FormatConcatOpConversion,
1732 FormatIntOpConversion,
1733 DisplayBIOpConversion
1734 >(typeConverter, context);
1737 mlir::populateAnyFunctionOpInterfaceTypeConversionPattern(
patterns,
1740 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
1748 struct MooreToCorePass
1749 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
1750 void runOnOperation()
override;
1756 return std::make_unique<MooreToCorePass>();
1760 void MooreToCorePass::runOnOperation() {
1761 MLIRContext &context = getContext();
1762 ModuleOp module = getOperation();
1764 IRRewriter rewriter(module);
1765 (void)mlir::eraseUnreachableBlocks(rewriter, module->getRegions());
1767 ConversionTarget target(context);
1768 TypeConverter typeConverter;
1769 RewritePatternSet
patterns(&context);
1774 if (failed(applyFullConversion(module, target, std::move(
patterns))))
1775 signalPassFailure();
assert(baseType &&"element must be base type")
static void populateOpConversion(RewritePatternSet &patterns, TypeConverter &typeConverter)
static void populateLegality(ConversionTarget &target, const TypeConverter &converter)
static void populateTypeConversion(TypeConverter &typeConverter)
def create(data_type, value)
Direction get(bool isOutput)
Returns an output direction if isOutput is true, otherwise returns an input direction.
Value createOrFoldSExt(Location loc, Value value, Type destTy, OpBuilder &builder)
Create a sign extension operation from a value of integer type to an equal or larger integer type.
mlir::Type innerType(mlir::Type type)
std::optional< int64_t > getBitWidth(FIRRTLBaseType type, bool ignoreFlip=false)
void populateHWModuleLikeTypeConversionPattern(StringRef moduleLikeOpName, RewritePatternSet &patterns, TypeConverter &converter)
circt::hw::InOutType InOutType
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.