126 static llvm::cl::opt<int> tileCol(
127 "tilecol", llvm::cl::desc(
"column coordinate of core to translate"),
129 static llvm::cl::opt<int> tileRow(
130 "tilerow", llvm::cl::desc(
"row coordinate of core to translate"),
133 static llvm::cl::opt<std::string> workDirPath(
134 "work-dir-path", llvm::cl::Optional,
135 llvm::cl::desc(
"Absolute path to working directory"));
137 static llvm::cl::opt<bool> bigEndian(
"big-endian", llvm::cl::init(
false),
138 llvm::cl::desc(
"Endianness"));
140 static llvm::cl::opt<bool> cdoUnified(
141 "cdo-unified", llvm::cl::init(
false),
142 llvm::cl::desc(
"Emit unified CDO bin (or separate bins)"));
143 static llvm::cl::opt<bool> cdoDebug(
"cdo-debug", llvm::cl::init(
false),
144 llvm::cl::desc(
"Emit cdo debug info"));
145 static llvm::cl::opt<bool> cdoAieSim(
146 "cdo-aiesim", llvm::cl::init(
false),
147 llvm::cl::desc(
"AIESIM target cdo generation"));
148 static llvm::cl::opt<bool> cdoXaieDebug(
149 "cdo-xaie-debug", llvm::cl::init(
false),
150 llvm::cl::desc(
"Emit libxaie debug info"));
151 static llvm::cl::opt<size_t> cdoEnableCores(
152 "cdo-enable-cores", llvm::cl::init(
true),
153 llvm::cl::desc(
"Enable cores in CDO"));
155 static llvm::cl::opt<bool> outputBinary(
156 "aie-output-binary", llvm::cl::init(
true),
158 "Select binary (true) or text (false) output for supported "
159 "translations. e.g. aie-npu-to-binary, aie-ctrlpkt-to-bin"));
160 static llvm::cl::opt<bool> npuFoldDDRAddrOffset(
161 "aie-npu-fold-ddr-addr-offset", llvm::cl::init(
true),
163 "For aie-npu-to-binary and aie-npu-to-cpp: fold the AIE "
164 "DDR-aperture offset into the arg_plus of DDR address patches for "
165 "host arguments beyond the firmware-translated set. Required for "
166 "the xclbin + instruction-buffer runtime; must be false for the "
167 "full-ELF (xrt.ext.kernel) runtime and for HRX, which translate "
168 "every host buffer address themselves."));
169 static llvm::cl::opt<bool> npuEmitDispatchShim(
170 "aie-npu-emit-dispatch-shim", llvm::cl::init(
false),
172 "For aie-npu-to-cpp: also emit the extern \"C\" dispatch_abi() and "
173 "dispatch_generate() entry points the JIT dispatch bridge loads via "
174 "ctypes. Requires exactly one aie.runtime_sequence."));
175 static llvm::cl::opt<std::string> deviceName(
176 "aie-device-name", llvm::cl::init(
""),
177 llvm::cl::desc(
"Specify which device to translate"));
178 static llvm::cl::opt<std::string> sequenceName(
179 "aie-sequence-name", llvm::cl::init(
""),
181 "Specify the name of the aiex.runtime_sequence to translate"));
182 static llvm::cl::opt<std::string> npuEmitLocmap(
183 "aie-npu-emit-locmap", llvm::cl::init(
""),
184 llvm::cl::value_desc(
"filename"),
186 "For aie-npu-to-binary, also write a JSON sidecar mapping each "
187 "transaction word's byte offset to its source MLIR Location (and "
188 "regdb register name where applicable) to the given file. The binary "
189 "is still emitted to the main output."));
191 TranslateFromMLIRRegistration registrationMMap(
192 "aie-generate-mmap",
"Generate AIE memory map",
193 [](ModuleOp module, raw_ostream &output) {
194 DenseMap<TileID, Operation *> tiles;
195 DenseMap<Operation *, SmallVector<BufferOp, 4>> buffers;
198 AIE::DeviceOp::getForSymbolInModule(module, deviceName);
200 module.emitOpError("expected AIE.device operation at toplevel");
205 using tileType = std::pair<TileID, Operation *>;
207 bool operator()(
const tileType &lhs,
const tileType &rhs)
const {
208 return lhs.first < rhs.first;
211 std::set<tileType, tileCmp> sortedTiles;
212 for (
auto tile : tiles)
213 sortedTiles.insert(tileType{tile.first, tile.second});
217 for (
auto tile : sortedTiles) {
218 Operation *srcTileOp = tile.second;
219 TileID srcCoord = cast<TileOp>(srcTileOp).getTileID();
220 int srcCol = srcCoord.col;
221 int srcRow = srcCoord.row;
223 output <<
"// Tile(" << srcCol <<
", " << srcRow <<
")\n";
224 output <<
"// Memory map: name base_address num_bytes\n";
226 auto doBuffer = [&](std::optional<TileID> tile,
int offset) {
227 if (tiles.count(*tile))
228 for (
auto buf : buffers[tiles[*tile]])
229 writeBufferMap(output, buf, offset);
234 if (
auto tile = targetModel.getMemSouth(srcCoord))
235 doBuffer(tile, targetModel.getMemSouthBaseAddress());
236 if (
auto tile = targetModel.getMemWest(srcCoord))
237 doBuffer(tile, targetModel.getMemWestBaseAddress());
238 if (
auto tile = targetModel.getMemNorth(srcCoord))
239 doBuffer(tile, targetModel.getMemNorthBaseAddress());
240 if (
auto tile = targetModel.getMemEast(srcCoord))
241 doBuffer(tile, targetModel.getMemEastBaseAddress());
247 TranslateFromMLIRRegistration registrationShimDMAToJSON(
248 "aie-generate-json",
"Transform AIE shim DMA allocation info into JSON",
249 [](ModuleOp module, raw_ostream &output) {
251 AIE::DeviceOp::getForSymbolInModuleOrError(module, deviceName);
255 llvm::json::Object moduleJSON;
256 for (
auto shimDMAMeta : d.getOps<ShimDMAAllocationOp>()) {
257 llvm::json::Object shimJSON;
258 auto channelDir = shimDMAMeta.getChannelDirAttr();
259 shimJSON[
"channelDir"] = attrToJSON(channelDir);
260 auto channelIndex = shimDMAMeta.getChannelIndexAttr();
261 shimJSON[
"channelIndex"] = attrToJSON(channelIndex);
262 AIE::TileOp tile = shimDMAMeta.getTileOp();
264 shimDMAMeta.emitError(
265 "shim DMA allocation must reference a valid TileOp");
268 auto col = tile.getColAttr();
269 shimJSON[
"col"] = attrToJSON(col);
270 moduleJSON[shimDMAMeta.getSymName()] =
271 llvm::json::Value(std::move(shimJSON));
273 llvm::json::Value topv(std::move(moduleJSON));
275 llvm::raw_string_ostream ss(ret);
276 ss << llvm::formatv(
"{0:2}", topv) <<
"\n";
282 TranslateFromMLIRRegistration registrationLDScript(
283 "aie-generate-ldscript",
"Generate AIE loader script",
284 [](ModuleOp module, raw_ostream &output) {
290 TranslateFromMLIRRegistration registrationBCF(
291 "aie-generate-bcf",
"Generate AIE bcf",
292 [](ModuleOp module, raw_ostream &output) {
297 TranslateFromMLIRRegistration registrationTargetArch(
298 "aie-generate-target-arch",
"Get the target architecture",
299 [](ModuleOp module, raw_ostream &output) {
304 TranslateFromMLIRRegistration registrationCoreList(
305 "aie-generate-corelist",
"Generate python list of cores",
306 [](ModuleOp module, raw_ostream &output) {
308 AIE::DeviceOp::getForSymbolInModule(module, deviceName);
310 module.emitOpError("expected AIE.device operation at toplevel");
315 for (
auto tileOp : targetOp.getOps<TileOp>()) {
316 int col = tileOp.colIndex();
317 int row = tileOp.rowIndex();
318 if (
auto coreOp = tileOp.getCoreOp()) {
319 std::string elfFile =
"None";
320 if (
auto fileAttr = coreOp.getElfFile())
321 elfFile =
"\"" + fileAttr.value().str() +
"\"";
322 output <<
'(' << col <<
',' << row <<
',' << elfFile <<
"),";
330 TranslateFromMLIRRegistration registrationXAIE(
331 "aie-generate-xaie",
"Generate libxaie configuration",
332 [](ModuleOp module, raw_ostream &output) {
336 TranslateFromMLIRRegistration registrationXJSON(
337 "aie-flows-to-json",
"Translate AIE flows to JSON",
338 [](ModuleOp module, raw_ostream &output) {
342 TranslateFromMLIRRegistration registrationXPE(
343 "aie-mlir-to-xpe",
"Translate AIE design to XPE file for simulation",
344 [](ModuleOp module, raw_ostream &output) {
348 TranslateFromMLIRRegistration registrationSCSimConfig(
349 "aie-mlir-to-scsim-config",
350 "Translate AIE design to SCSimConfig file for simulation",
351 [](ModuleOp module, raw_ostream &output) {
355 TranslateFromMLIRRegistration registrationShimSolution(
356 "aie-mlir-to-shim-solution",
357 "Translate AIE design to ShimSolution file for simulation",
358 [](ModuleOp module, raw_ostream &output) {
362 TranslateFromMLIRRegistration registrationCDODirect(
363 "aie-generate-cdo",
"Generate libxaie for CDO directly",
364 [](ModuleOp module, raw_ostream &) {
365 SmallString<128> workDirPath_;
366 if (workDirPath.getNumOccurrences() == 0) {
367 if (llvm::sys::fs::current_path(workDirPath_))
368 llvm::report_fatal_error(
369 "couldn't get cwd to use as work-dir-path");
371 workDirPath_ = workDirPath.getValue();
372 LLVM_DEBUG(llvm::dbgs() <<
"work-dir-path: " << workDirPath_ <<
"\n");
374 bigEndian, cdoUnified, cdoDebug,
375 cdoAieSim, cdoXaieDebug, cdoEnableCores);
378 TranslateFromMLIRRegistration registrationNPU(
379 "aie-npu-to-binary",
"Translate npu instructions to binary",
380 [](ModuleOp module, raw_ostream &output) {
381 std::vector<uint32_t> instructions;
382 std::vector<TxnLocEntry> locmap;
383 bool emitLocmap = !npuEmitLocmap.empty();
385 module, instructions, deviceName, sequenceName,
386 emitLocmap ? &locmap :
nullptr, npuFoldDDRAddrOffset);
391 output.write(
reinterpret_cast<const char *
>(instructions.data()),
392 instructions.size() *
sizeof(uint32_t));
394 for (
auto w : instructions)
395 output << llvm::format(
"%08X\n", w);
402 llvm::raw_fd_ostream locFile(npuEmitLocmap, ec,
403 llvm::sys::fs::OF_Text);
405 llvm::errs() <<
"Error opening locmap file '" << npuEmitLocmap
406 <<
"': " << ec.message() <<
"\n";
414 TranslateFromMLIRRegistration registrationNpuToCpp(
416 "Translate npu instructions to a C++ TXN-builder function",
417 [](ModuleOp module, raw_ostream &output) {
419 npuEmitDispatchShim);
422 TranslateFromMLIRRegistration registrationCtrlPkt(
423 "aie-ctrlpkt-to-bin",
"Translate aiex.control_packet ops to binary",
424 [](ModuleOp module, raw_ostream &output) {
425 std::vector<uint32_t> instructions;
427 deviceName, sequenceName);
431 output.write(
reinterpret_cast<const char *
>(instructions.data()),
432 instructions.size() *
sizeof(uint32_t));
434 for (
auto w : instructions)
435 output << llvm::format(
"%08X\n", w);
442 TranslateFromMLIRRegistration registrationCertToAsm(
443 "aie-cert-to-asm",
"Translate cert operations to assembly",
444 [](ModuleOp module, raw_ostream &output) {