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) {
42 Value zeroExt =
builder.create<hw::ConstantOp>(
43 loc,
builder.getIntegerType(targetWidth - intWidth), 0);
44 return builder.create<comb::ConcatOp>(loc, ValueRange{zeroExt, value});
47 Value hi =
builder.create<comb::ExtractOp>(loc, value, targetWidth,
48 intWidth - targetWidth);
49 Value zero =
builder.create<hw::ConstantOp>(
50 loc,
builder.getIntegerType(intWidth - targetWidth), 0);
51 Value isZero =
builder.create<comb::ICmpOp>(loc, comb::ICmpPredicate::eq, hi,
53 Value lo =
builder.create<comb::ExtractOp>(loc, value, 0, targetWidth);
54 Value max =
builder.create<hw::ConstantOp>(
55 loc,
builder.getIntegerType(targetWidth), -1);
56 return builder.create<comb::MuxOp>(loc, isZero, lo, max,
false);
64 using OpConversionPattern::OpConversionPattern;
67 matchAndRewrite(ConstantOp op, OpAdaptor adaptor,
68 ConversionPatternRewriter &rewriter)
const override {
70 rewriter.replaceOpWithNewOp<hw::ConstantOp>(op, op.getValueAttr());
76 using OpConversionPattern::OpConversionPattern;
78 matchAndRewrite(ConcatOp op, OpAdaptor adaptor,
79 ConversionPatternRewriter &rewriter)
const override {
80 rewriter.replaceOpWithNewOp<comb::ConcatOp>(op, adaptor.getValues());
90 using OpConversionPattern::OpConversionPattern;
93 matchAndRewrite(VariableDeclOp op, OpAdaptor adaptor,
94 ConversionPatternRewriter &rewriter)
const override {
95 Type resultType = typeConverter->convertType(op.getResult().getType());
97 rewriter.create<hw::ConstantOp>(op->getLoc(), op.getInitAttr());
98 rewriter.replaceOpWithNewOp<llhd::SigOp>(op, resultType, op.getName(),
105 using OpConversionPattern::OpConversionPattern;
108 matchAndRewrite(AssignOp op, OpAdaptor adaptor,
109 ConversionPatternRewriter &rewriter)
const override {
111 rewriter.create<llhd::ConstantTimeOp>(op->getLoc(), 0,
"s", 0, 1);
112 rewriter.replaceOpWithNewOp<llhd::DrvOp>(
113 op, adaptor.getDest(), adaptor.getSrc(), timeVal, Value());
119 using OpConversionPattern::OpConversionPattern;
122 matchAndRewrite(func::ReturnOp op, OpAdaptor adaptor,
123 ConversionPatternRewriter &rewriter)
const override {
124 rewriter.replaceOpWithNewOp<func::ReturnOp>(op, adaptor.getOperands());
130 using OpConversionPattern::OpConversionPattern;
133 matchAndRewrite(cf::CondBranchOp op, OpAdaptor adaptor,
134 ConversionPatternRewriter &rewriter)
const override {
135 rewriter.replaceOpWithNewOp<cf::CondBranchOp>(
136 op, adaptor.getCondition(), adaptor.getTrueDestOperands(),
137 adaptor.getFalseDestOperands(), op.getTrueDest(), op.getFalseDest());
143 using OpConversionPattern::OpConversionPattern;
146 matchAndRewrite(cf::BranchOp op, OpAdaptor adaptor,
147 ConversionPatternRewriter &rewriter)
const override {
148 rewriter.replaceOpWithNewOp<cf::BranchOp>(op, op.getDest(),
149 adaptor.getDestOperands());
155 using OpConversionPattern::OpConversionPattern;
158 matchAndRewrite(func::CallOp op, OpAdaptor adaptor,
159 ConversionPatternRewriter &rewriter)
const override {
160 SmallVector<Type> convResTypes;
161 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
163 rewriter.replaceOpWithNewOp<func::CallOp>(
164 op, adaptor.getCallee(), convResTypes, adaptor.getOperands());
169 struct UnrealizedConversionCastConversion
171 using OpConversionPattern::OpConversionPattern;
174 matchAndRewrite(UnrealizedConversionCastOp op, OpAdaptor adaptor,
175 ConversionPatternRewriter &rewriter)
const override {
176 SmallVector<Type> convResTypes;
177 if (typeConverter->convertTypes(op.getResultTypes(), convResTypes).failed())
182 if (convResTypes == adaptor.getOperands().getTypes()) {
183 rewriter.replaceOp(op, adaptor.getOperands());
187 rewriter.replaceOpWithNewOp<UnrealizedConversionCastOp>(
188 op, convResTypes, adaptor.getOperands());
194 using OpConversionPattern::OpConversionPattern;
197 matchAndRewrite(ShlOp op, OpAdaptor adaptor,
198 ConversionPatternRewriter &rewriter)
const override {
199 Type resultType = typeConverter->convertType(op.getResult().getType());
203 adjustIntegerWidth(rewriter, adaptor.getAmount(),
204 resultType.getIntOrFloatBitWidth(), op->getLoc());
205 rewriter.replaceOpWithNewOp<comb::ShlOp>(op, resultType, adaptor.getValue(),
212 using OpConversionPattern::OpConversionPattern;
215 matchAndRewrite(ShrOp op, OpAdaptor adaptor,
216 ConversionPatternRewriter &rewriter)
const override {
217 Type resultType = typeConverter->convertType(op.getResult().getType());
218 bool hasSignedResultType = op.getResult()
221 .castToSimpleBitVector()
226 adjustIntegerWidth(rewriter, adaptor.getAmount(),
227 resultType.getIntOrFloatBitWidth(), op->getLoc());
229 if (adaptor.getArithmetic() && hasSignedResultType) {
230 rewriter.replaceOpWithNewOp<comb::ShrSOp>(
231 op, resultType, adaptor.getValue(), amount,
false);
235 rewriter.replaceOpWithNewOp<comb::ShrUOp>(
236 op, resultType, adaptor.getValue(), amount,
false);
249 type.isa<LValueType>();
260 template <
typename Op>
262 target.addDynamicallyLegalOp<Op>([](Op op) {
268 target.addIllegalDialect<MooreDialect>();
269 target.addLegalDialect<mlir::BuiltinDialect>();
270 target.addLegalDialect<hw::HWDialect>();
271 target.addLegalDialect<llhd::LLHDDialect>();
272 target.addLegalDialect<comb::CombDialect>();
274 addGenericLegality<cf::CondBranchOp>(target);
275 addGenericLegality<cf::BranchOp>(target);
276 addGenericLegality<func::CallOp>(target);
277 addGenericLegality<func::ReturnOp>(target);
278 addGenericLegality<UnrealizedConversionCastOp>(target);
280 target.addDynamicallyLegalOp<func::FuncOp>([](func::FuncOp op) {
281 auto argsConverted = llvm::none_of(op.getBlocks(), [](
auto &block) {
282 return hasMooreType(block.getArguments());
284 auto resultsConverted = !
hasMooreType(op.getResultTypes());
285 return argsConverted && resultsConverted;
290 typeConverter.addConversion([&](
IntType type) {
293 typeConverter.addConversion([&](LValueType type) {
294 auto inner = typeConverter.convertType(type.getNestedType());
301 typeConverter.addConversion([&](
UnpackedType type) -> std::optional<Type> {
302 if (
auto sbv = type.getSimpleBitVectorOrNull())
308 typeConverter.addConversion([](mlir::IntegerType type) {
return type; });
312 TypeConverter &typeConverter) {
313 auto *context =
patterns.getContext();
321 CondBranchOpConversion,
326 UnrealizedConversionCastConversion
327 >(typeConverter, context);
329 mlir::populateFunctionOpInterfaceTypeConversionPattern<func::FuncOp>(
338 struct MooreToCorePass :
public ConvertMooreToCoreBase<MooreToCorePass> {
339 void runOnOperation()
override;
345 return std::make_unique<MooreToCorePass>();
349 void MooreToCorePass::runOnOperation() {
350 MLIRContext &context = getContext();
351 ModuleOp module = getOperation();
353 ConversionTarget target(context);
354 TypeConverter typeConverter;
355 RewritePatternSet
patterns(&context);
360 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.
This file defines an intermediate representation for circuits acting as an abstraction for constraint...
std::unique_ptr< OperationPass< ModuleOp > > createConvertMooreToCorePass()
Create an Moore to Comb/HW/LLHD conversion pass.