MLIR-AIE
AIETargetLdScript.cpp
Go to the documentation of this file.
1//===- AIETargetLdScript.cpp -----------------------------------*- C++ -*-===//
2//
3// This file is licensed under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// (c) Copyright 2023 Advanced Micro Devices, Inc.
8//
9//===----------------------------------------------------------------------===//
10
13
14using namespace mlir;
15using namespace xilinx;
16using namespace xilinx::AIE;
17
18// Output the memorymap in gnu linker format for the given buffer operations,
19// with the given offset. The offset is different depending on where the buffers
20// are accessed from.
21static void writeLDScriptMap(raw_ostream &output, BufferOp buf, int offset) {
22 std::string bufName(buf.name().getValue());
23 int bufferBaseAddr = getBufferBaseAddress(buf);
24 int numBytes = buf.getAllocationSize();
25 output << ". = 0x" << llvm::utohexstr(offset + bufferBaseAddr) << ";\n";
26 output << bufName << " = .;\n";
27 output << ". += 0x" << llvm::utohexstr(numBytes) << ";\n";
28}
29
30///// ld.script format:
31//
32// MEMORY
33// {
34// program (RX) : ORIGIN = 0, LENGTH = 0x0020000
35// data (!RX) : ORIGIN = 0x20000, LENGTH = 0x0020000
36// }
37// ENTRY(__start)
38// INPUT(something.o)
39// SECTIONS
40// {
41// . = 0x0;
42// .text : {
43// // the __start symbol has to come at address zero.
44// *crt0.o(.text*)
45// __ctors_start__ = .;
46// __init_array_start = .;
47// KEEP(SORT(*)(.init_array))
48// __ctors_end__ = .;
49// __init_array_end = .;
50// __dtors_start__ = .;
51// __dtors_end__ = .;
52// *(.text*)
53// } > program
54// .data : { *(.data*) } > data
55// . = 0x20000;
56// _sp_start_value_DM_stack = .;
57// . = 0x24000;
58// a = .;
59// . += 1024;
60// .bss : { *(.bss*) } > data
61// }
62// PROVIDE(main = core_3_3);
63
64LogicalResult xilinx::AIE::AIETranslateToLdScript(ModuleOp module,
65 raw_ostream &output,
66 int tileCol, int tileRow,
67 llvm::StringRef deviceName) {
68 DenseMap<TileID, Operation *> tiles;
69 DenseMap<Operation *, SmallVector<BufferOp, 4>> buffers;
70
71 DeviceOp targetOp =
72 AIE::DeviceOp::getForSymbolInModuleOrError(module, deviceName);
73
74 if (!targetOp) {
75 return failure();
76 }
77
78 collectTiles(targetOp, tiles);
79 collectBuffers(targetOp, buffers);
80
81 for (auto tile : targetOp.getOps<TileOp>())
82 if (tile.colIndex() == tileCol && tile.rowIndex() == tileRow) {
83 TileID srcCoord = {tile.colIndex(), tile.rowIndex()};
84 const auto &targetModel = getTargetModel(tile);
85
86 // Figure out how much memory we have left for random allocations
87 auto core = tile.getCoreOp();
88 int max = core.getStackSize();
89 for (auto buf : buffers[tiles[srcCoord]]) {
90 int bufferBaseAddr = getBufferBaseAddress(buf);
91 int numBytes = buf.getAllocationSize();
92 max = std::max(max, bufferBaseAddr + numBytes);
93 }
94 int origin = targetModel.getMemInternalBaseAddress(srcCoord) + max;
95 int length = targetModel.getLocalMemorySize() - max;
96 output << R"THESCRIPT(
97MEMORY
98{
99 program (RX) : ORIGIN = 0, LENGTH = 0x0020000
100)THESCRIPT";
101 output << " data (!RX) : ORIGIN = 0x" << llvm::utohexstr(origin)
102 << ", LENGTH = 0x" << llvm::utohexstr(length);
103 output << R"THESCRIPT(
104}
105ENTRY(__start)
106SECTIONS
107{
108 . = 0x0;
109 .text : {
110 /* the __start symbol has to come at address zero. */
111 *crt0.o(.text*)
112 _ctors_start = .;
113 _init_array_start = .;
114 KEEP(SORT(*.init_array))
115 _ctors_end = .;
116 _init_array_end = .;
117 _dtors_start = .;
118 _dtors_end = .;
119 *(.text*)
120 } > program
121 .data : {
122 *(.data*)
123 *(.rodata*)
124 } > data
125 .comment : {
126 *(.comment*)
127 }
128 .symtab : {
129 *(.symtab)
130 }
131 .shstrtab : {
132 *(.shstrtab)
133 }
134 .strtab : {
135 *(.strtab)
136 }
137 .stack_sizes : {
138 *(.stack_sizes)
139 }
140
141)THESCRIPT";
142 auto doBuffer = [&](std::optional<TileID> tile, int offset,
143 std::string dir) {
144 if (tile) {
145 if (tiles.count(*tile))
146 for (auto buf : buffers[tiles[*tile]])
147 writeLDScriptMap(output, buf, offset);
148 } else {
149 output << "/* No tile with memory exists to the " << dir << ". */\n";
150 output << ". = 0x" << llvm::utohexstr(offset) << ";\n";
151 uint32_t localMemSize = targetModel.getLocalMemorySize();
152 output << ". += 0x" << llvm::utohexstr(localMemSize) << ";\n";
153 }
154 };
155
156 // Stack
157 output << ". = 0x"
158 << llvm::utohexstr(targetModel.getMemInternalBaseAddress(srcCoord))
159 << ";\n";
160 output << "_sp_start_value_DM_stack = .;\n";
161
162 if (auto core = tile.getCoreOp())
163 output << ". += 0x" << llvm::utohexstr(core.getStackSize())
164 << "; /* stack */\n";
165 else
166 output << "/* no stack allocated */\n";
167
168 doBuffer(targetModel.getMemSouth(srcCoord),
169 targetModel.getMemSouthBaseAddress(), std::string("south"));
170 doBuffer(targetModel.getMemWest(srcCoord),
171 targetModel.getMemWestBaseAddress(), std::string("west"));
172 doBuffer(targetModel.getMemNorth(srcCoord),
173 targetModel.getMemNorthBaseAddress(), std::string("north"));
174 doBuffer(targetModel.getMemEast(srcCoord),
175 targetModel.getMemEastBaseAddress(), std::string("east"));
176
177 output << " .bss : { *(.bss*) } > data\n";
178 // INPUT() directives must follow the closing brace of SECTIONS; placing
179 // them inside SECTIONS is invalid linker script syntax.
180 output << "}\n";
181 if (auto coreOp = tile.getCoreOp()) {
182 if (auto filesAttr = coreOp.getLinkFiles()) {
183 // Canonical path: link_files populated by aie-assign-core-link-files.
184 for (auto f : filesAttr->getAsRange<mlir::StringAttr>())
185 output << "INPUT(" << f.getValue() << ")\n";
186 } else if (auto fileAttr = coreOp.getLinkWith()) {
187 // Deprecated fallback: core-level link_with was not migrated by
188 // aie-assign-core-link-files (e.g., the pass was not run).
189 output << "INPUT(" << fileAttr.value().str() << ")\n";
190 }
191
192 output << "PROVIDE(main = core_" << tile.getCol() << "_"
193 << tile.getRow() << ");\n";
194 }
195 }
196 return success();
197}
Include the generated interface declarations.
void collectTiles(DeviceOp &device, llvm::DenseMap< TileID, mlir::Operation * > &tiles)
void collectBuffers(DeviceOp &device, llvm::DenseMap< mlir::Operation *, llvm::SmallVector< BufferOp, 4 > > &buffers)
mlir::LogicalResult AIETranslateToLdScript(mlir::ModuleOp module, llvm::raw_ostream &output, int tileCol, int tileRow, llvm::StringRef deviceName="")
TileID { friend std::ostream &operator<<(std::ostream &os, const TileID &s) { os<< "TileID("<< s.col<< ", "<< s.row<< ")" TileID
int32_t getBufferBaseAddress(mlir::Operation *bufOp)
const AIETargetModel & getTargetModel(mlir::Operation *op)