18 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
19 #include "mlir/Dialect/Func/IR/FuncOps.h"
20 #include "mlir/IR/BuiltinDialect.h"
21 #include "mlir/Pass/Pass.h"
22 #include "mlir/Transforms/DialectConversion.h"
23 #include "llvm/ADT/TypeSwitch.h"
26 #define GEN_PASS_DEF_CONVERTMOORETOCORE
27 #include "circt/Conversion/Passes.h.inc"
31 using namespace circt;
32 using namespace moore;
34 using comb::ICmpPredicate;
42 static Value adjustIntegerWidth(OpBuilder &builder, Value value,
43 uint32_t targetWidth, Location loc) {
44 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
45 if (intWidth == targetWidth)
48 if (intWidth < targetWidth) {
50 loc, builder.getIntegerType(targetWidth - intWidth), 0);
55 intWidth - targetWidth);
57 loc, builder.getIntegerType(intWidth - targetWidth), 0);
58 Value isZero = builder.
create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
62 loc, builder.getIntegerType(targetWidth), -1);
67 static hw::ModulePortInfo getModulePortInfo(
const TypeConverter &typeConverter,
71 auto moduleTy = op.getModuleType();
72 SmallVector<hw::PortInfo> inputs, outputs;
73 inputs.reserve(moduleTy.getNumInputs());
74 outputs.reserve(moduleTy.getNumOutputs());
76 for (
auto port : moduleTy.getPorts())
79 hw::PortInfo({{port.name, port.type, port.dir}, resultNum++, {}}));
87 hw::PortInfo({{port.name, port.type, port.dir}, inputNum++, {}}));
90 return hw::ModulePortInfo(inputs, outputs);
98 using OpConversionPattern::OpConversionPattern;
101 matchAndRewrite(SVModuleOp op, OpAdaptor adaptor,
102 ConversionPatternRewriter &rewriter)
const override {
103 auto outputOp = op.getOutputOp();
104 rewriter.setInsertionPoint(op);
109 getModulePortInfo(*typeConverter, op));
110 rewriter.eraseBlock(hwModuleOp.getBodyBlock());
111 rewriter.inlineRegionBefore(op.getBodyRegion(), hwModuleOp.getBodyRegion(),
112 hwModuleOp.getBodyRegion().end());
115 rewriter.setInsertionPointToEnd(hwModuleOp.getBodyBlock());
116 rewriter.replaceOpWithNewOp<hw::OutputOp>(outputOp, outputOp.getOperands());
119 rewriter.eraseOp(op);
125 using OpConversionPattern::OpConversionPattern;
128 matchAndRewrite(InstanceOp op, OpAdaptor adaptor,
129 ConversionPatternRewriter &rewriter)
const override {
130 auto instName = op.getInstanceNameAttr();
131 auto moduleName = op.getModuleNameAttr();
134 rewriter.setInsertionPoint(op);
135 auto instOp = rewriter.create<hw::InstanceOp>(
136 op.getLoc(), op.getResultTypes(), instName, moduleName, op.getInputs(),
137 op.getInputNamesAttr(), op.getOutputNamesAttr(),
138 rewriter.getArrayAttr({}),
nullptr);
141 op.replaceAllUsesWith(instOp.getResults());
142 rewriter.eraseOp(op);
152 using OpConversionPattern::OpConversionPattern;
155 matchAndRewrite(VariableOp op, OpAdaptor adaptor,
156 ConversionPatternRewriter &rewriter)
const override {
157 Type resultType = typeConverter->convertType(op.getResult().getType());
158 Value init = adaptor.getInitial();
160 if (!init && cast<RefType>(op.getResult().getType()).getDomain() ==
165 init = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
167 op.getNameAttr(), init);
177 using OpConversionPattern::OpConversionPattern;
180 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
181 ConversionPatternRewriter &rewriter)
const override {
183 rewriter.replaceOpWithNewOp<
hw::ConstantOp>(op, op.getValueAttr());
189 using OpConversionPattern::OpConversionPattern;
192 matchAndRewrite(NamedConstantOp op, OpAdaptor adaptor,
193 ConversionPatternRewriter &rewriter)
const override {
195 Type resultType = typeConverter->convertType(op.getResult().getType());
196 SmallString<32> symStr;
197 switch (op.getKind()) {
198 case NamedConst::Parameter:
199 symStr =
"parameter";
201 case NamedConst::LocalParameter:
202 symStr =
"localparameter";
204 case NamedConst::SpecParameter:
205 symStr =
"specparameter";
209 rewriter.getStringAttr(symStr + Twine(
"_") + adaptor.getName());
210 rewriter.replaceOpWithNewOp<hw::WireOp>(op, resultType, adaptor.getValue(),
218 using OpConversionPattern::OpConversionPattern;
220 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
221 ConversionPatternRewriter &rewriter)
const override {
222 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
228 using OpConversionPattern::OpConversionPattern;
230 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
231 ConversionPatternRewriter &rewriter)
const override {
232 Type resultType = typeConverter->convertType(op.getResult().getType());
234 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
241 using OpConversionPattern::OpConversionPattern;
244 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
245 ConversionPatternRewriter &rewriter)
const override {
246 Type resultType = typeConverter->convertType(op.getResult().getType());
248 op, resultType, adaptor.getInput(), adaptor.getLowBit());
254 using OpConversionPattern::OpConversionPattern;
257 matchAndRewrite(DynExtractOp op, OpAdaptor adaptor,
258 ConversionPatternRewriter &rewriter)
const override {
259 Type resultType = typeConverter->convertType(op.getResult().getType());
260 auto width = typeConverter->convertType(op.getInput().getType())
261 .getIntOrFloatBitWidth();
263 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
width, op->getLoc());
265 rewriter.create<
comb::ShrUOp>(op->getLoc(), adaptor.getInput(), amount);
267 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
273 using OpConversionPattern::OpConversionPattern;
275 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
276 ConversionPatternRewriter &rewriter)
const override {
277 Type resultType = typeConverter->convertType(op.getInput().getType());
278 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
280 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
281 adaptor.getInput(), max);
287 using OpConversionPattern::OpConversionPattern;
289 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
290 ConversionPatternRewriter &rewriter)
const override {
291 Type resultType = typeConverter->convertType(op.getInput().getType());
292 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
294 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
295 adaptor.getInput(), zero);
301 using OpConversionPattern::OpConversionPattern;
303 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
304 ConversionPatternRewriter &rewriter)
const override {
306 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
312 using OpConversionPattern::OpConversionPattern;
314 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
315 ConversionPatternRewriter &rewriter)
const override {
316 Type resultType = typeConverter->convertType(op.getInput().getType());
317 if (isa_and_nonnull<IntegerType>(resultType)) {
318 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
319 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
320 adaptor.getInput(), zero);
328 using OpConversionPattern::OpConversionPattern;
330 matchAndRewrite(NotOp op, OpAdaptor adaptor,
331 ConversionPatternRewriter &rewriter)
const override {
333 ConversionPattern::typeConverter->convertType(op.getResult().getType());
334 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
336 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
342 using OpConversionPattern::OpConversionPattern;
344 matchAndRewrite(NegOp op, OpAdaptor adaptor,
345 ConversionPatternRewriter &rewriter)
const override {
347 ConversionPattern::typeConverter->convertType(op.getResult().getType());
348 Value zero = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, 0);
350 rewriter.replaceOpWithNewOp<
comb::SubOp>(op, zero, adaptor.getInput());
355 template <
typename SourceOp,
typename TargetOp>
358 using OpAdaptor =
typename SourceOp::Adaptor;
361 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
362 ConversionPatternRewriter &rewriter)
const override {
363 rewriter.replaceOpWithNewOp<TargetOp>(op, adaptor.getLhs(),
364 adaptor.getRhs(),
false);
369 template <
typename SourceOp, ICmpPredicate pred>
372 using OpAdaptor =
typename SourceOp::Adaptor;
375 matchAndRewrite(SourceOp op, OpAdaptor adapter,
376 ConversionPatternRewriter &rewriter)
const override {
378 ConversionPattern::typeConverter->convertType(op.getResult().getType());
380 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
381 op, resultType, pred, adapter.getLhs(), adapter.getRhs());
387 using OpConversionPattern::OpConversionPattern;
390 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
391 ConversionPatternRewriter &rewriter)
const override {
392 Type resultType = typeConverter->convertType(op.getResult().getType());
394 adjustIntegerWidth(rewriter, adaptor.getInput(),
395 resultType.getIntOrFloatBitWidth(), op->getLoc());
397 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, resultType, amount);
407 using OpConversionPattern::OpConversionPattern;
410 matchAndRewrite(hw::OutputOp op, OpAdaptor adaptor,
411 ConversionPatternRewriter &rewriter)
const override {
412 rewriter.replaceOpWithNewOp<hw::OutputOp>(op, adaptor.getOperands());
418 using OpConversionPattern::OpConversionPattern;
421 matchAndRewrite(hw::InstanceOp op, OpAdaptor adaptor,
422 ConversionPatternRewriter &rewriter)
const override {
423 SmallVector<Type> convResTypes;
424 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
427 rewriter.replaceOpWithNewOp<hw::InstanceOp>(
428 op, convResTypes, op.getInstanceName(), op.getModuleName(),
429 adaptor.getOperands(), op.getArgNames(),
431 rewriter.getArrayAttr({}),
nullptr);
438 using OpConversionPattern::OpConversionPattern;
441 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
442 ConversionPatternRewriter &rewriter)
const override {
443 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
449 using OpConversionPattern::OpConversionPattern;
452 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
453 ConversionPatternRewriter &rewriter)
const override {
454 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
455 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
456 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
462 using OpConversionPattern::OpConversionPattern;
465 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
466 ConversionPatternRewriter &rewriter)
const override {
467 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
468 adaptor.getDestOperands());
474 using OpConversionPattern::OpConversionPattern;
477 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
478 ConversionPatternRewriter &rewriter)
const override {
479 SmallVector<Type> convResTypes;
480 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
482 rewriter.replaceOpWithNewOp<func::CallOp>(
483 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
488 struct UnrealizedConversionCastConversion
490 using OpConversionPattern::OpConversionPattern;
493 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
494 ConversionPatternRewriter &rewriter)
const override {
495 SmallVector<Type> convResTypes;
496 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
501 if (convResTypes == adaptor.getOperands().getTypes()) {
502 rewriter.replaceOp(op, adaptor.getOperands());
506 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
507 op, convResTypes, adaptor.getOperands());
513 using OpConversionPattern::OpConversionPattern;
516 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
517 ConversionPatternRewriter &rewriter)
const override {
518 Type resultType = typeConverter->convertType(op.getResult().getType());
522 adjustIntegerWidth(rewriter, adaptor.getAmount(),
523 resultType.getIntOrFloatBitWidth(), op->getLoc());
524 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
531 using OpConversionPattern::OpConversionPattern;
534 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
535 ConversionPatternRewriter &rewriter)
const override {
536 Type resultType = typeConverter->convertType(op.getResult().getType());
540 adjustIntegerWidth(rewriter, adaptor.getAmount(),
541 resultType.getIntOrFloatBitWidth(), op->getLoc());
543 op, resultType, adaptor.getValue(), amount,
false);
549 using OpConversionPattern::OpConversionPattern;
552 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
553 ConversionPatternRewriter &rewriter)
const override {
554 Type resultType = typeConverter->convertType(op.getResult().getType());
558 adjustIntegerWidth(rewriter, adaptor.getAmount(),
559 resultType.getIntOrFloatBitWidth(), op->getLoc());
561 op, resultType, adaptor.getValue(), amount,
false);
567 using OpConversionPattern::OpConversionPattern;
570 matchAndRewrite(ReadOp op, OpAdaptor adaptor,
571 ConversionPatternRewriter &rewriter)
const override {
572 Type resultType = typeConverter->convertType(op.getResult().getType());
573 rewriter.replaceOpWithNewOp<llhd::PrbOp>(op, resultType,
579 template <
typename OpTy>
582 using OpAdaptor =
typename OpTy::Adaptor;
585 matchAndRewrite(OpTy op, OpAdaptor adaptor,
586 ConversionPatternRewriter &rewriter)
const override {
591 llvm::StringRef(
"ns"),
unsigned(0),
unsigned(0));
592 auto time = rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), timeAttr);
593 rewriter.replaceOpWithNewOp<llhd::DrvOp>(op, adaptor.getDst(),
594 adaptor.getSrc(), time, Value{});
605 static bool isMooreType(Type type) {
return isa<UnpackedType>(type); }
615 template <
typename Op>
617 target.addDynamicallyLegalOp<Op>([](Op op) {
623 target.addIllegalDialect<MooreDialect>();
624 target.addLegalDialect<mlir::BuiltinDialect>();
625 target.addLegalDialect<hw::HWDialect>();
626 target.addLegalDialect<llhd::LLHDDialect>();
627 target.addLegalDialect<comb::CombDialect>();
629 addGenericLegality<cf::CondBranchOp>(target);
630 addGenericLegality<cf::BranchOp>(target);
631 addGenericLegality<func::CallOp>(target);
632 addGenericLegality<func::ReturnOp>(target);
633 addGenericLegality<UnrealizedConversionCastOp>(target);
635 target.addDynamicallyLegalOp<func::FuncOp>([](func::FuncOp op) {
636 auto argsConverted = llvm::none_of(op.getBlocks(), [](
auto &block) {
637 return hasMooreType(block.getArguments());
639 auto resultsConverted = !
hasMooreType(op.getResultTypes());
640 return argsConverted && resultsConverted;
649 target.addDynamicallyLegalOp<hw::InstanceOp>([](hw::InstanceOp op) {
653 target.addDynamicallyLegalOp<hw::OutputOp>(
654 [](hw::OutputOp op) {
return !
hasMooreType(op.getOutputs()); });
658 typeConverter.addConversion([&](IntType type) {
662 typeConverter.addConversion([&](RefType type) -> std::optional<Type> {
663 if (isa<IntType, ArrayType, UnpackedArrayType>(type.getNestedType()))
665 type.getBitSize().value());
670 typeConverter.addConversion([](mlir::IntegerType type) {
return type; });
671 typeConverter.addTargetMaterialization(
672 [&](mlir::OpBuilder &builder, mlir::Type resultType,
673 mlir::ValueRange inputs,
674 mlir::Location loc) -> std::optional<mlir::Value> {
675 if (inputs.size() != 1)
680 typeConverter.addSourceMaterialization(
681 [&](mlir::OpBuilder &builder, mlir::Type resultType,
682 mlir::ValueRange inputs,
683 mlir::Location loc) -> std::optional<mlir::Value> {
684 if (inputs.size() != 1)
691 TypeConverter &typeConverter) {
692 auto *context =
patterns.getContext();
696 VariableOpConversion,
699 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
700 ExtractOpConversion, DynExtractOpConversion, ConversionOpConversion,
701 ReadOpConversion, NamedConstantOpConv,
704 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
705 BoolCastOpConversion, NotOpConversion, NegOpConversion,
708 BinaryOpConversion<AddOp, comb::AddOp>,
709 BinaryOpConversion<SubOp, comb::SubOp>,
710 BinaryOpConversion<MulOp, comb::MulOp>,
711 BinaryOpConversion<DivUOp, comb::DivUOp>,
712 BinaryOpConversion<DivSOp, comb::DivSOp>,
713 BinaryOpConversion<ModUOp, comb::ModUOp>,
714 BinaryOpConversion<ModSOp, comb::ModSOp>,
715 BinaryOpConversion<AndOp, comb::AndOp>,
716 BinaryOpConversion<OrOp, comb::OrOp>,
717 BinaryOpConversion<XorOp, comb::XorOp>,
720 ICmpOpConversion<UltOp, ICmpPredicate::ult>,
721 ICmpOpConversion<SltOp, ICmpPredicate::slt>,
722 ICmpOpConversion<UleOp, ICmpPredicate::ule>,
723 ICmpOpConversion<SleOp, ICmpPredicate::sle>,
724 ICmpOpConversion<UgtOp, ICmpPredicate::ugt>,
725 ICmpOpConversion<SgtOp, ICmpPredicate::sgt>,
726 ICmpOpConversion<UgeOp, ICmpPredicate::uge>,
727 ICmpOpConversion<SgeOp, ICmpPredicate::sge>,
728 ICmpOpConversion<EqOp, ICmpPredicate::eq>,
729 ICmpOpConversion<NeOp, ICmpPredicate::ne>,
730 ICmpOpConversion<CaseEqOp, ICmpPredicate::ceq>,
731 ICmpOpConversion<CaseNeOp, ICmpPredicate::cne>,
732 ICmpOpConversion<WildcardEqOp, ICmpPredicate::weq>,
733 ICmpOpConversion<WildcardNeOp, ICmpPredicate::wne>,
736 SVModuleOpConversion, InstanceOpConversion,
739 ShrOpConversion, ShlOpConversion, AShrOpConversion,
742 AssignOpConversion<ContinuousAssignOp>,
745 CondBranchOpConversion, BranchOpConversion,
748 HWOutputOpConversion, HWInstanceOpConversion, ReturnOpConversion,
749 CallOpConversion, UnrealizedConversionCastConversion
750 >(typeConverter, context);
752 mlir::populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(
756 hw::HWModuleOp::getOperationName(),
patterns, typeConverter);
764 struct MooreToCorePass
765 :
public circt::impl::ConvertMooreToCoreBase<MooreToCorePass> {
766 void runOnOperation()
override;
772 return std::make_unique<MooreToCorePass>();
776 void MooreToCorePass::runOnOperation() {
777 MLIRContext &context = getContext();
778 ModuleOp module = getOperation();
780 ConversionTarget target(context);
781 TypeConverter typeConverter;
782 RewritePatternSet
patterns(&context);
787 if (failed(applyFullConversion(module, target, std::move(
patterns))))
static void populateLegality(ConversionTarget &target)
static bool hasMooreType(TypeRange types)
static void populateOpConversion(RewritePatternSet &patterns, TypeConverter &typeConverter)
static bool isMooreType(Type type)
static void addGenericLegality(ConversionTarget &target)
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.
void populateHWModuleLikeTypeConversionPattern(StringRef moduleLikeOpName, RewritePatternSet &patterns, TypeConverter &converter)
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.