14 #include "../PassDetail.h"
19 #include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
20 #include "mlir/Dialect/Func/IR/FuncOps.h"
21 #include "mlir/IR/BuiltinDialect.h"
22 #include "mlir/Transforms/DialectConversion.h"
23 #include "llvm/ADT/TypeSwitch.h"
26 using namespace circt;
27 using namespace moore;
35 static Value adjustIntegerWidth(OpBuilder &
builder, Value value,
36 uint32_t targetWidth, Location loc) {
37 uint32_t intWidth = value.getType().getIntOrFloatBitWidth();
38 if (intWidth == targetWidth)
41 if (intWidth < targetWidth) {
43 loc,
builder.getIntegerType(targetWidth - intWidth), 0);
48 intWidth - targetWidth);
50 loc,
builder.getIntegerType(intWidth - targetWidth), 0);
51 Value isZero =
builder.create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
55 loc,
builder.getIntegerType(targetWidth), -1);
61 static bool isSignedType(Operation *op) {
62 return TypeSwitch<Operation *, bool>(op)
63 .template Case<LtOp, LeOp, GtOp, GeOp>([&](
auto op) ->
bool {
64 return cast<UnpackedType>(op->getOperand(0).getType())
65 .castToSimpleBitVector()
67 cast<UnpackedType>(op->getOperand(1).getType())
68 .castToSimpleBitVector()
71 .Default([&](
auto op) ->
bool {
72 return cast<UnpackedType>(op->getResult(0).getType())
73 .castToSimpleBitVector()
81 static comb::ICmpPredicate getCombPredicate(Operation *op) {
82 using comb::ICmpPredicate;
83 return TypeSwitch<Operation *, ICmpPredicate>(op)
84 .Case<LtOp>([&](
auto op) {
85 return isSignedType(op) ? ICmpPredicate::slt : ICmpPredicate::ult;
87 .Case<LeOp>([&](
auto op) {
88 return isSignedType(op) ? ICmpPredicate::sle : ICmpPredicate::ule;
90 .Case<GtOp>([&](
auto op) {
91 return isSignedType(op) ? ICmpPredicate::sgt : ICmpPredicate::ugt;
93 .Case<GeOp>([&](
auto op) {
94 return isSignedType(op) ? ICmpPredicate::sge : ICmpPredicate::uge;
96 .Case<EqOp>([&](
auto op) {
return ICmpPredicate::eq; })
97 .Case<NeOp>([&](
auto op) {
return ICmpPredicate::ne; })
98 .Case<CaseEqOp>([&](
auto op) {
return ICmpPredicate::ceq; })
99 .Case<CaseNeOp>([&](
auto op) {
return ICmpPredicate::cne; })
100 .Case<WildcardEqOp>([&](
auto op) {
return ICmpPredicate::weq; })
101 .Case<WildcardNeOp>([&](
auto op) {
return ICmpPredicate::wne; });
109 using OpConversionPattern::OpConversionPattern;
112 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
113 ConversionPatternRewriter &rewriter)
const override {
115 rewriter.replaceOpWithNewOp<
hw::ConstantOp>(op, op.getValueAttr());
121 using OpConversionPattern::OpConversionPattern;
123 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
124 ConversionPatternRewriter &rewriter)
const override {
125 rewriter.replaceOpWithNewOp<
comb::ConcatOp>(op, adaptor.getValues());
131 using OpConversionPattern::OpConversionPattern;
133 matchAndRewrite(ReplicateOp op, OpAdaptor adaptor,
134 ConversionPatternRewriter &rewriter)
const override {
135 Type resultType = typeConverter->convertType(op.getResult().getType());
137 rewriter.replaceOpWithNewOp<comb::ReplicateOp>(op, resultType,
144 using OpConversionPattern::OpConversionPattern;
147 matchAndRewrite(ExtractOp op, OpAdaptor adaptor,
148 ConversionPatternRewriter &rewriter)
const override {
149 Type resultType = typeConverter->convertType(op.getResult().getType());
150 auto width = typeConverter->convertType(op.getInput().getType())
151 .getIntOrFloatBitWidth();
153 adjustIntegerWidth(rewriter, adaptor.getLowBit(),
width, op->getLoc());
157 rewriter.replaceOpWithNewOp<
comb::ExtractOp>(op, resultType, value, 0);
163 using OpConversionPattern::OpConversionPattern;
165 matchAndRewrite(ReduceAndOp op, OpAdaptor adaptor,
166 ConversionPatternRewriter &rewriter)
const override {
167 Type resultType = typeConverter->convertType(op.getInput().getType());
168 Value max = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, -1);
170 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::eq,
171 adaptor.getInput(), max);
177 using OpConversionPattern::OpConversionPattern;
179 matchAndRewrite(ReduceOrOp op, OpAdaptor adaptor,
180 ConversionPatternRewriter &rewriter)
const override {
181 Type resultType = typeConverter->convertType(op.getInput().getType());
182 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
184 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
185 adaptor.getInput(), zero);
191 using OpConversionPattern::OpConversionPattern;
193 matchAndRewrite(ReduceXorOp op, OpAdaptor adaptor,
194 ConversionPatternRewriter &rewriter)
const override {
196 rewriter.replaceOpWithNewOp<
comb::ParityOp>(op, adaptor.getInput());
202 using OpConversionPattern::OpConversionPattern;
204 matchAndRewrite(BoolCastOp op, OpAdaptor adaptor,
205 ConversionPatternRewriter &rewriter)
const override {
206 if (cast<UnpackedType>(op.getInput().getType())
207 .castToSimpleBitVectorOrNull()) {
208 Type resultType = typeConverter->convertType(op.getInput().getType());
209 Value zero = rewriter.create<
hw::ConstantOp>(op->getLoc(), resultType, 0);
211 rewriter.replaceOpWithNewOp<comb::ICmpOp>(op, comb::ICmpPredicate::ne,
212 adaptor.getInput(), zero);
221 using OpConversionPattern::OpConversionPattern;
223 matchAndRewrite(NotOp op, OpAdaptor adaptor,
224 ConversionPatternRewriter &rewriter)
const override {
226 ConversionPattern::typeConverter->convertType(op.getResult().getType());
227 Value max = rewriter.create<
hw::ConstantOp>(op.getLoc(), resultType, -1);
229 rewriter.replaceOpWithNewOp<
comb::XorOp>(op, adaptor.getInput(), max);
234 template <
typename SourceOp,
typename UnsignedOp,
235 typename SignedOp = UnsignedOp>
238 using OpAdaptor =
typename SourceOp::Adaptor;
241 matchAndRewrite(SourceOp op, OpAdaptor adaptor,
242 ConversionPatternRewriter &rewriter)
const override {
245 ? rewriter.replaceOpWithNewOp<SignedOp>(op, adaptor.getLhs(),
246 adaptor.getRhs(),
false)
247 : rewriter.replaceOpWithNewOp<UnsignedOp>(op, adaptor.getLhs(),
248 adaptor.getRhs(),
false);
253 template <
typename SourceOp>
256 using OpAdaptor =
typename SourceOp::Adaptor;
259 matchAndRewrite(SourceOp op, OpAdaptor adapter,
260 ConversionPatternRewriter &rewriter)
const override {
262 ConversionPattern::typeConverter->convertType(op.getResult().getType());
263 comb::ICmpPredicate pred = getCombPredicate(op);
265 rewriter.replaceOpWithNewOp<comb::ICmpOp>(
266 op, resultType, pred, adapter.getLhs(), adapter.getRhs());
272 using OpConversionPattern::OpConversionPattern;
275 matchAndRewrite(ConversionOp op, OpAdaptor adaptor,
276 ConversionPatternRewriter &rewriter)
const override {
277 Type resultType = typeConverter->convertType(op.getResult().getType());
279 adjustIntegerWidth(rewriter, adaptor.getInput(),
280 resultType.getIntOrFloatBitWidth(), op->getLoc());
282 rewriter.replaceOpWithNewOp<
hw::BitcastOp>(op, resultType, amount);
292 using OpConversionPattern::OpConversionPattern;
295 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
296 ConversionPatternRewriter &rewriter)
const override {
297 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
303 using OpConversionPattern::OpConversionPattern;
306 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
307 ConversionPatternRewriter &rewriter)
const override {
308 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
309 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
310 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
316 using OpConversionPattern::OpConversionPattern;
319 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
320 ConversionPatternRewriter &rewriter)
const override {
321 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
322 adaptor.getDestOperands());
328 using OpConversionPattern::OpConversionPattern;
331 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
332 ConversionPatternRewriter &rewriter)
const override {
333 SmallVector<Type> convResTypes;
334 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
336 rewriter.replaceOpWithNewOp<func::CallOp>(
337 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
342 struct UnrealizedConversionCastConversion
344 using OpConversionPattern::OpConversionPattern;
347 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
348 ConversionPatternRewriter &rewriter)
const override {
349 SmallVector<Type> convResTypes;
350 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
355 if (convResTypes == adaptor.getOperands().getTypes()) {
356 rewriter.replaceOp(op, adaptor.getOperands());
360 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
361 op, convResTypes, adaptor.getOperands());
367 using OpConversionPattern::OpConversionPattern;
370 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
371 ConversionPatternRewriter &rewriter)
const override {
372 Type resultType = typeConverter->convertType(op.getResult().getType());
376 adjustIntegerWidth(rewriter, adaptor.getAmount(),
377 resultType.getIntOrFloatBitWidth(), op->getLoc());
378 rewriter.replaceOpWithNewOp<
comb::ShlOp>(op, resultType, adaptor.getValue(),
385 using OpConversionPattern::OpConversionPattern;
388 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
389 ConversionPatternRewriter &rewriter)
const override {
390 Type resultType = typeConverter->convertType(op.getResult().getType());
394 adjustIntegerWidth(rewriter, adaptor.getAmount(),
395 resultType.getIntOrFloatBitWidth(), op->getLoc());
397 op, resultType, adaptor.getValue(), amount,
false);
403 using OpConversionPattern::OpConversionPattern;
406 matchAndRewrite(AShrOp op, OpAdaptor adaptor,
407 ConversionPatternRewriter &rewriter)
const override {
408 Type resultType = typeConverter->convertType(op.getResult().getType());
412 adjustIntegerWidth(rewriter, adaptor.getAmount(),
413 resultType.getIntOrFloatBitWidth(), op->getLoc());
415 op, resultType, adaptor.getValue(), amount,
false);
436 template <
typename Op>
438 target.addDynamicallyLegalOp<Op>([](Op op) {
444 target.addIllegalDialect<MooreDialect>();
445 target.addLegalDialect<mlir::BuiltinDialect>();
446 target.addLegalDialect<hw::HWDialect>();
447 target.addLegalDialect<llhd::LLHDDialect>();
448 target.addLegalDialect<comb::CombDialect>();
450 addGenericLegality<cf::CondBranchOp>(target);
451 addGenericLegality<cf::BranchOp>(target);
452 addGenericLegality<func::CallOp>(target);
453 addGenericLegality<func::ReturnOp>(target);
454 addGenericLegality<UnrealizedConversionCastOp>(target);
456 target.addDynamicallyLegalOp<func::FuncOp>([](func::FuncOp op) {
457 auto argsConverted = llvm::none_of(op.getBlocks(), [](
auto &block) {
458 return hasMooreType(block.getArguments());
460 auto resultsConverted = !
hasMooreType(op.getResultTypes());
461 return argsConverted && resultsConverted;
466 typeConverter.addConversion([&](
IntType type) {
473 typeConverter.addConversion([&](
UnpackedType type) -> std::optional<Type> {
474 if (
auto sbv = type.getSimpleBitVectorOrNull())
476 if (isa<UnpackedRangeDim, PackedRangeDim>(type))
483 typeConverter.addConversion([](mlir::IntegerType type) {
return type; });
487 TypeConverter &typeConverter) {
488 auto *context =
patterns.getContext();
492 ConstantOpConv, ConcatOpConversion, ReplicateOpConversion,
493 ExtractOpConversion, ConversionOpConversion,
496 ReduceAndOpConversion, ReduceOrOpConversion, ReduceXorOpConversion,
497 BoolCastOpConversion, NotOpConversion,
500 BinaryOpConversion<AddOp, comb::AddOp>,
501 BinaryOpConversion<SubOp, comb::SubOp>,
502 BinaryOpConversion<MulOp, comb::MulOp>,
503 BinaryOpConversion<DivOp, comb::DivUOp, comb::DivSOp>,
504 BinaryOpConversion<ModOp, comb::ModUOp, comb::ModSOp>,
505 BinaryOpConversion<AndOp, comb::AndOp>,
506 BinaryOpConversion<OrOp, comb::OrOp>,
507 BinaryOpConversion<XorOp, comb::XorOp>,
510 ICmpOpConversion<LtOp>, ICmpOpConversion<LeOp>, ICmpOpConversion<GtOp>,
511 ICmpOpConversion<GeOp>, ICmpOpConversion<EqOp>, ICmpOpConversion<NeOp>,
512 ICmpOpConversion<CaseEqOp>, ICmpOpConversion<CaseNeOp>,
513 ICmpOpConversion<WildcardEqOp>, ICmpOpConversion<WildcardNeOp>,
516 ShrOpConversion, ShlOpConversion, AShrOpConversion,
519 CondBranchOpConversion, BranchOpConversion,
522 ReturnOpConversion, CallOpConversion, UnrealizedConversionCastConversion
523 >(typeConverter, context);
525 mlir::populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(
534 struct MooreToCorePass :
public ConvertMooreToCoreBase<MooreToCorePass> {
535 void runOnOperation()
override;
541 return std::make_unique<MooreToCorePass>();
545 void MooreToCorePass::runOnOperation() {
546 MLIRContext &context = getContext();
547 ModuleOp module = getOperation();
549 ConversionTarget target(context);
550 TypeConverter typeConverter;
551 RewritePatternSet
patterns(&context);
556 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)
An integer vector or atom type.
static unsigned getBitSize(Kind kind)
Get the size of one of the integer types.
An unpacked SystemVerilog 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.
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.