24#ifndef AIE_DIALECT_AIEX_UTILS_BDLOWERING_H
25#define AIE_DIALECT_AIEX_UTILS_BDLOWERING_H
27#include "mlir/Dialect/Utils/StaticValueUtils.h"
28#include "mlir/IR/Builders.h"
29#include "mlir/IR/BuiltinTypes.h"
30#include "mlir/IR/Operation.h"
31#include "mlir/IR/Value.h"
32#include "mlir/Support/LLVM.h"
33#include "llvm/ADT/ArrayRef.h"
34#include "llvm/ADT/Twine.h"
59 uint32_t addressGranularity) {
60 return addressGranularity / std::gcd(elemWidth, (uint64_t)addressGranularity);
66 uint32_t addressGranularity) {
67 return value * (int64_t)elemWidth % (int64_t)addressGranularity == 0;
76inline mlir::LogicalResult
78 llvm::ArrayRef<mlir::OpFoldResult> sizes,
79 llvm::ArrayRef<mlir::OpFoldResult> strides,
80 uint64_t elemWidth, uint32_t gran) {
81 std::optional<int64_t> d0Size =
82 sizes.empty() ? std::nullopt : mlir::getConstantIntValue(sizes[0]);
84 return op->emitOpError(
"d0 size ")
85 << *d0Size <<
" elements at " << (elemWidth / 8)
86 <<
" bytes each is not a multiple of the " << (gran / 8)
87 <<
"-byte address-gen granule.";
88 for (
int i = 0; i < (int)strides.size(); i++) {
89 auto s = mlir::getConstantIntValue(strides[i]);
97 if (i == 0 && *s == 1)
100 return op->emitOpError(
"stride ")
101 << i <<
" is " << *s <<
" elements at " << (elemWidth / 8)
102 <<
" bytes each, not a multiple of the " << (gran / 8)
103 <<
"-byte address-gen granule.";
104 if (i == 0 && elemWidth != gran && !(d0Size && *d0Size <= 1))
105 return op->emitOpError(
"stride 0 is ")
106 << *s <<
" elements, but must be 1 for " << (elemWidth / 8)
107 <<
"-byte elements: the DMA moves whole " << (gran / 8)
108 <<
"-byte granules.";
121 constexpr int kIterDim = 3;
122 for (
int i = 0; i < (int)sizes.size() && i < (
int)strides.size(); i++) {
123 auto sz = mlir::getConstantIntValue(sizes[i]);
124 auto st = mlir::getConstantIntValue(strides[i]);
125 if (!st || (sz && *sz <= 1))
127 if (i == kIterDim ? *st < 0 : *st < 1)
128 return op->emitOpError(
"stride ")
131 ?
" must be non-negative unless its size is statically 1."
132 :
" must be positive unless its size is statically 1.");
134 return mlir::success();
144template <
typename Policy>
146 uint32_t addressGranularity,
147 typename Policy::V inputSizes[4],
148 typename Policy::V inputStrides[4],
149 typename Policy::V sizes[4],
150 typename Policy::V strides[4]) {
151 using V =
typename Policy::V;
154 auto biasedStride = [&](V inStride) -> V {
155 return p.sub(p.div(p.mul(inStride, elemWidth), addressGranularity), 1);
159 sizes[0] = p.div(p.mul(inputSizes[0], elemWidth), addressGranularity);
166 if (elemWidth > addressGranularity) {
167 strides[0] = p.cst(0);
169 strides[0] = p.selectLt(p.mul(inputStrides[0], elemWidth),
170 p.cst((int64_t)addressGranularity), p.cst(0),
171 biasedStride(inputStrides[0]));
175 sizes[1] = inputSizes[1];
177 p.selectGT1(inputSizes[1], biasedStride(inputStrides[1]), p.cst(0));
178 sizes[2] = inputSizes[2];
180 p.selectGT1(inputSizes[2], biasedStride(inputStrides[2]), p.cst(0));
187 sizes[3] = p.selectGT1(inputSizes[3], p.sub(inputSizes[3], 1), p.cst(0));
188 strides[3] = p.selectGT1(
190 p.selectGT0(inputStrides[3], biasedStride(inputStrides[3]), p.cst(0)),
197 static V cst(int64_t c) {
return c; }
198 static V mul(
V v, int64_t c) {
return v * c; }
199 static V div(
V v, int64_t c) {
return v / c; }
200 static V sub(
V v, int64_t c) {
return v - c; }
210 using V = mlir::Value;
216 V cst(int64_t c)
const;
217 V mul(
V v, int64_t c)
const;
218 V div(
V v, int64_t c)
const;
219 V sub(
V v, int64_t c)
const;
230 mlir::Location loc, mlir::Value cond,
231 const llvm::Twine &message);
240mlir::Value
getAsValue(mlir::OpBuilder &builder, mlir::Location loc,
241 mlir::OpFoldResult ofr, mlir::Type intType);
246mlir::Value
getAsI64(mlir::OpBuilder &builder, mlir::Location loc,
247 mlir::OpFoldResult ofr);
256 llvm::ArrayRef<mlir::OpFoldResult> elementOffsets,
257 llvm::ArrayRef<mlir::OpFoldResult> strides,
258 int64_t elemWidthBytes, int64_t baseByteOffset,
259 uint32_t granuleBytes);
268 mlir::BaseMemRefType hostBufferType,
269 int64_t baseByteOffset, int64_t elemWidthBytes,
270 llvm::ArrayRef<mlir::OpFoldResult> offsets,
271 llvm::ArrayRef<mlir::OpFoldResult> offsetStrides,
272 llvm::ArrayRef<mlir::OpFoldResult> sizes,
273 llvm::ArrayRef<mlir::OpFoldResult> strides);
279 llvm::ArrayRef<std::tuple<mlir::Value, uint32_t, uint32_t>> fields);
289 int tileCol,
int tileRow,
290 mlir::OpFoldResult bdId);
335 llvm::ArrayRef<mlir::OpFoldResult> mixedSizes,
336 llvm::ArrayRef<mlir::OpFoldResult> mixedStrides,
337 uint64_t elemWidth, uint32_t burstLength, uint32_t axcache,
338 mlir::OpFoldResult lenElems, mlir::Value &repeatCountOut,
339 llvm::SmallVectorImpl<mlir::Value> &wordsOut);
int64_t bdGranuleDivisor(uint64_t elemWidth, uint32_t addressGranularity)
mlir::Value buildBdWord(mlir::OpBuilder &builder, mlir::Location loc, llvm::ArrayRef< std::tuple< mlir::Value, uint32_t, uint32_t > > fields)
void encodeHardwareStridesWraps(Policy &p, uint64_t elemWidth, uint32_t addressGranularity, typename Policy::V inputSizes[4], typename Policy::V inputStrides[4], typename Policy::V sizes[4], typename Policy::V strides[4])
mlir::Value buildArgPlusValue(mlir::OpBuilder &builder, mlir::Location loc, llvm::ArrayRef< mlir::OpFoldResult > elementOffsets, llvm::ArrayRef< mlir::OpFoldResult > strides, int64_t elemWidthBytes, int64_t baseByteOffset, uint32_t granuleBytes)
mlir::Value getAsValue(mlir::OpBuilder &builder, mlir::Location loc, mlir::OpFoldResult ofr, mlir::Type intType)
mlir::LogicalResult guardWithinHostBuffer(mlir::OpBuilder &builder, mlir::Location loc, mlir::BaseMemRefType hostBufferType, int64_t baseByteOffset, int64_t elemWidthBytes, llvm::ArrayRef< mlir::OpFoldResult > offsets, llvm::ArrayRef< mlir::OpFoldResult > offsetStrides, llvm::ArrayRef< mlir::OpFoldResult > sizes, llvm::ArrayRef< mlir::OpFoldResult > strides)
mlir::LogicalResult buildBdWords(mlir::OpBuilder &builder, mlir::Location loc, const xilinx::AIE::AIETargetModel &targetModel, int tileCol, int tileRow, const BdTemplateFields &fields, llvm::ArrayRef< mlir::OpFoldResult > mixedSizes, llvm::ArrayRef< mlir::OpFoldResult > mixedStrides, uint64_t elemWidth, uint32_t burstLength, uint32_t axcache, mlir::OpFoldResult lenElems, mlir::Value &repeatCountOut, llvm::SmallVectorImpl< mlir::Value > &wordsOut)
mlir::Value getAsI64(mlir::OpBuilder &builder, mlir::Location loc, mlir::OpFoldResult ofr)
void eraseDeadArith(mlir::Operation *root)
bool isConstMultipleOfGranule(int64_t value, uint64_t elemWidth, uint32_t addressGranularity)
mlir::Value getBdRegisterBase(mlir::OpBuilder &builder, mlir::Location loc, const xilinx::AIE::AIETargetModel &targetModel, int tileCol, int tileRow, mlir::OpFoldResult bdId)
mlir::LogicalResult emitRuntimeCheck(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value cond, const llvm::Twine &message)
mlir::LogicalResult verifyConstBdRealizability(mlir::Operation *op, llvm::ArrayRef< mlir::OpFoldResult > sizes, llvm::ArrayRef< mlir::OpFoldResult > strides, uint64_t elemWidth, uint32_t gran)
mlir::Value next_bd_id_val
int32_t iteration_current
mlir::Value lock_rel_val_val
mlir::Value lock_acq_val_val
static V div(V v, int64_t c)
static V selectLt(V a, V b, V t, V e)
static V sub(V v, int64_t c)
static V selectGT0(V cond, V t, V e)
static V mul(V v, int64_t c)
static V selectGT1(V cond, V t, V e)
V selectGT1(V cond, V t, V e) const
V div(V v, int64_t c) const
V sub(V v, int64_t c) const
SsaStridePolicy(mlir::OpBuilder &b, mlir::Location l)
mlir::OpBuilder & builder
V selectGT0(V cond, V t, V e) const
V mul(V v, int64_t c) const
V selectLt(V a, V b, V t, V e) const