mirror of https://github.com/llvm/circt.git
[HWToSMT] Add ArrayInject lowering to HWToSMT (#8765)
This commit implements the lowering of hw.array_inject operations to SMT expressions using smt.array.store operations. The lowering creates a new array with the specified element injected at the given index, with proper bounds checking to handle out-of-bounds accesses gracefully. The implementation includes bounds checking that compares the index against the maximum valid index (numElements - 1) and uses smt.ite to return either the updated array (if in bounds) or the original array (if out of bounds).
This commit is contained in:
parent
959e0f18e2
commit
186dcc8b0e
|
@ -154,6 +154,40 @@ struct ArrayGetOpConversion : OpConversionPattern<ArrayGetOp> {
|
|||
}
|
||||
};
|
||||
|
||||
/// Lower a hw::ArrayInjectOp operation to smt::ArrayStoreOp.
|
||||
struct ArrayInjectOpConversion : OpConversionPattern<ArrayInjectOp> {
|
||||
using OpConversionPattern<ArrayInjectOp>::OpConversionPattern;
|
||||
|
||||
LogicalResult
|
||||
matchAndRewrite(ArrayInjectOp op, OpAdaptor adaptor,
|
||||
ConversionPatternRewriter &rewriter) const override {
|
||||
Location loc = op.getLoc();
|
||||
unsigned numElements =
|
||||
cast<hw::ArrayType>(op.getInput().getType()).getNumElements();
|
||||
|
||||
Type arrType = typeConverter->convertType(op.getType());
|
||||
if (!arrType)
|
||||
return rewriter.notifyMatchFailure(op.getLoc(), "unsupported array type");
|
||||
|
||||
// Check if the index is within bounds
|
||||
Value numElementsVal = rewriter.create<mlir::smt::BVConstantOp>(
|
||||
loc, numElements - 1, llvm::Log2_64_Ceil(numElements));
|
||||
Value inBounds =
|
||||
rewriter.create<mlir::smt::BVCmpOp>(loc, mlir::smt::BVCmpPredicate::ule,
|
||||
adaptor.getIndex(), numElementsVal);
|
||||
|
||||
// Store the element at the given index
|
||||
Value stored = rewriter.create<mlir::smt::ArrayStoreOp>(
|
||||
loc, adaptor.getInput(), adaptor.getIndex(), adaptor.getElement());
|
||||
|
||||
// Return the original array if out of bounds, otherwise return the new
|
||||
// array
|
||||
rewriter.replaceOpWithNewOp<mlir::smt::IteOp>(op, inBounds, stored,
|
||||
adaptor.getInput());
|
||||
return success();
|
||||
}
|
||||
};
|
||||
|
||||
/// Remove redundant (seq::FromClock and seq::ToClock) ops.
|
||||
template <typename OpTy>
|
||||
struct ReplaceWithInput : OpConversionPattern<OpTy> {
|
||||
|
@ -291,7 +325,8 @@ void circt::populateHWToSMTConversionPatterns(TypeConverter &converter,
|
|||
patterns.add<HWConstantOpConversion, HWModuleOpConversion, OutputOpConversion,
|
||||
InstanceOpConversion, ReplaceWithInput<seq::ToClockOp>,
|
||||
ReplaceWithInput<seq::FromClockOp>, ArrayCreateOpConversion,
|
||||
ArrayGetOpConversion>(converter, patterns.getContext());
|
||||
ArrayGetOpConversion, ArrayInjectOpConversion>(
|
||||
converter, patterns.getContext());
|
||||
}
|
||||
|
||||
void ConvertHWToSMTPass::runOnOperation() {
|
||||
|
|
|
@ -25,3 +25,15 @@ hw.module @modB(in %in: i32, out out: i32) {
|
|||
// CHECK-NEXT: return [[V]] : !smt.bv<32>
|
||||
hw.output %0 : i32
|
||||
}
|
||||
|
||||
// CHECK-LABEL: func.func @inject
|
||||
// CHECK-SAME: (%[[ARR:.+]]: !smt.array<[!smt.bv<2> -> !smt.bv<8>]>, %[[IDX:.+]]: !smt.bv<2>, %[[VAL:.+]]: !smt.bv<8>)
|
||||
hw.module @inject(in %arr: !hw.array<3xi8>, in %index: i2, in %v: i8, out out: !hw.array<3xi8>) {
|
||||
// CHECK-NEXT: %[[C2:.+]] = smt.bv.constant #smt.bv<-2> : !smt.bv<2>
|
||||
// CHECK-NEXT: %[[CMP:.+]] = smt.bv.cmp ule %[[IDX]], %[[C2]] : !smt.bv<2>
|
||||
// CHECK-NEXT: %[[STORED:.+]] = smt.array.store %[[ARR]][%[[IDX]]], %[[VAL]] : !smt.array<[!smt.bv<2> -> !smt.bv<8>]>
|
||||
// CHECK-NEXT: %[[RESULT:.+]] = smt.ite %[[CMP]], %[[STORED]], %[[ARR]] : !smt.array<[!smt.bv<2> -> !smt.bv<8>]>
|
||||
// CHECK-NEXT: return %[[RESULT]] : !smt.array<[!smt.bv<2> -> !smt.bv<8>]>
|
||||
%arr_injected = hw.array_inject %arr[%index], %v : !hw.array<3xi8>, i2
|
||||
hw.output %arr_injected : !hw.array<3xi8>
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue