16#include "mlir/Dialect/Func/IR/FuncOps.h"
17#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
19#include "llvm/ADT/ArrayRef.h"
20#include "llvm/ADT/TypeSwitch.h"
21#include "llvm/Support/Format.h"
30#define TXN_OPC_WRITE 0x0
31#define TXN_OPC_BLOCKWRITE 0x1
32#define TXN_OPC_MASKWRITE 0x3
33#define TXN_OPC_TCT 0x80
34#define TXN_OPC_DDR_PATCH 0x81
43llvm::MutableArrayRef<uint32_t>
44reserveAndGetTail(std::vector<uint32_t> &instructions, uint64_t tailSize) {
45 auto oldSize = instructions.size();
46 auto newSize = oldSize + tailSize;
47 instructions.resize(newSize, 0);
48 return llvm::MutableArrayRef<uint32_t>(instructions.data() + oldSize,
52void appendSync(std::vector<uint32_t> &instructions, NpuSyncOp op) {
54 auto words = reserveAndGetTail(instructions, 4);
59 words[1] = words.size() *
sizeof(uint32_t);
61 words[2] |=
static_cast<uint32_t
>(op.getDirection()) & 0xff;
62 words[2] |= (op.getRow() & 0xff) << 8;
63 words[2] |= (op.getColumn() & 0xff) << 16;
65 words[3] |= (op.getRowNum() & 0xff) << 8;
66 words[3] |= (op.getColumnNum() & 0xff) << 16;
67 words[3] |= (op.getChannel() & 0xff) << 24;
70void appendWrite32(std::vector<uint32_t> &instructions, NpuWrite32Op op) {
72 auto words = reserveAndGetTail(instructions, 6);
75 op.emitOpError(
"Cannot translate symbolic address");
81 words[2] = op.getAddress();
82 auto col = op.getColumn();
83 auto row = op.getRow();
90 words[4] = op.getValue();
91 words[5] = words.size() *
sizeof(uint32_t);
94void appendMaskWrite32(std::vector<uint32_t> &instructions,
95 NpuMaskWrite32Op op) {
97 auto words = reserveAndGetTail(instructions, 7);
100 op.emitOpError(
"Cannot translate symbolic address");
106 words[2] = op.getAddress();
107 auto col = op.getColumn();
108 auto row = op.getRow();
115 words[4] = op.getValue();
116 words[5] = op.getMask();
117 words[6] = words.size() *
sizeof(uint32_t);
120void appendAddressPatch(std::vector<uint32_t> &instructions,
121 NpuAddressPatchOp op) {
123 auto words = reserveAndGetTail(instructions, 12);
127 words[1] = words.size() *
sizeof(uint32_t);
131 words[6] = op.getAddr();
133 words[8] = op.getArgIdx();
135 words[10] = op.getArgPlus();
138void appendBlockWrite(std::vector<uint32_t> &instructions, NpuBlockWriteOp op) {
140 Value memref = op.getData();
141 int64_t width = cast<MemRefType>(memref.getType()).getElementTypeBitWidth();
143 op.emitWarning(
"Only 32-bit data type is supported for now");
147 memref::GetGlobalOp getGlobal = memref.getDefiningOp<memref::GetGlobalOp>();
149 op.emitError(
"Only MemRefs from memref.get_global are supported");
153 auto global = dyn_cast_if_present<memref::GlobalOp>(
154 op->getParentOfType<AIE::DeviceOp>().lookupSymbol(getGlobal.getName()));
156 op.emitError(
"Global symbol not found");
160 auto initVal = global.getInitialValue();
162 op.emitError(
"Global symbol has no initial value");
166 auto data = dyn_cast<DenseIntElementsAttr>(*initVal);
168 op.emitError(
"Global symbol initial value is not a dense int array");
172 unsigned payload_start = 4;
173 auto words = reserveAndGetTail(instructions, data.size() + payload_start);
177 words[2] = op.getAddress();
178 auto col = op.getColumn();
179 auto row = op.getRow();
181 words[1] = (*
col & 0xff) | ((*
row & 0xff) << 8);
186 words[3] = words.size() *
sizeof(uint32_t);
188 unsigned i = payload_start;
190 words[i++] = d.getZExtValue();
197 std::vector<uint32_t> &instructions,
198 StringRef sequenceName) {
200 auto words = reserveAndGetTail(instructions, 4);
202 DeviceOp deviceOp = *
module.getOps<DeviceOp>().begin();
211 uint8_t numRows = tm.
rows();
212 uint8_t numCols = tm.
columns();
215 words[0] = (numRows << 24) | (devGen << 16) | (minor << 8) | major;
216 words[1] = (numMemTileRows << 8) | numCols;
218 auto sequenceOps = deviceOp.getOps<AIEX::RuntimeSequenceOp>();
219 for (
auto seq : sequenceOps) {
220 if (sequenceName.size() && sequenceName != seq.getSymName())
222 Block &entry = seq.getBody().front();
223 for (
auto &o : entry) {
224 llvm::TypeSwitch<Operation *>(&o)
225 .Case<NpuSyncOp>([&](
auto op) {
227 appendSync(instructions, op);
229 .Case<NpuWrite32Op>([&](
auto op) {
231 appendWrite32(instructions, op);
233 .Case<NpuBlockWriteOp>([&](
auto op) {
235 appendBlockWrite(instructions, op);
237 .Case<NpuMaskWrite32Op>([&](
auto op) {
239 appendMaskWrite32(instructions, op);
241 .Case<NpuAddressPatchOp>([&](
auto op) {
243 appendAddressPatch(instructions, op);
249 instructions[2] = count;
250 instructions[3] = instructions.size() *
sizeof(uint32_t);
255 ModuleOp module, std::vector<uint32_t> &instructions,
256 StringRef sequenceName) {
257 DeviceOp deviceOp = *
module.getOps<DeviceOp>().begin();
258 auto sequenceOps = deviceOp.getOps<AIEX::RuntimeSequenceOp>();
259 for (
auto seq : sequenceOps) {
260 if (sequenceName.size() && sequenceName != seq.getSymName())
262 Block &entry = seq.getBody().front();
263 for (
auto &o : entry) {
264 llvm::TypeSwitch<Operation *>(&o).Case<NpuControlPacketOp>([&](
auto op) {
266 auto data = op.getData();
267 auto length = op.getLength();
270 auto words = reserveAndGetTail(instructions, 1 + size);
273 auto parity = [](uint32_t n) {
281 uint32_t addr = op.getAddress() & 0xFFFFF;
282 uint32_t beats = size - 1;
283 uint32_t opc = op.getOpcode();
284 uint32_t
id = op.getStreamId();
285 uint32_t hdr =
id << 24 | opc << 22 | beats << 20 | addr;
286 words[0] = hdr | (0x1 & parity(hdr)) << 31;
287 if (opc == 0x0 || opc == 0x2)
288 for (
unsigned i = 0; i < size; i++)
289 words[i + 1] = data.value()[i];
#define TXN_OPC_MASKWRITE
#define TXN_OPC_BLOCKWRITE
#define TXN_OPC_DDR_PATCH
virtual int rows() const =0
Return the number of rows in the device.
virtual uint32_t getColumnShift() const =0
virtual int columns() const =0
Return the number of columns in the device.
virtual uint32_t getNumMemTileRows() const =0
virtual uint32_t getRowShift() const =0
Include the generated interface declarations.
mlir::LogicalResult AIETranslateNpuToBinary(mlir::ModuleOp, std::vector< uint32_t > &, llvm::StringRef sequenceName="")
const AIETargetModel & getTargetModel(mlir::Operation *op)
mlir::LogicalResult AIETranslateControlPacketsToUI32Vec(mlir::ModuleOp, std::vector< uint32_t > &, llvm::StringRef sequenceName="")