Skip to content

Commit 80dde41

Browse files
committed
Declarative aiecc rewrite
1 parent 373ec1e commit 80dde41

95 files changed

Lines changed: 7104 additions & 6960 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

include/aie/Dialect/AIEX/AIEUtils.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77

88
#include "aie/Dialect/AIE/IR/AIEDialect.h"
99
#include "mlir/Dialect/MemRef/IR/MemRef.h"
10+
#include "mlir/IR/BuiltinOps.h"
1011
#include "mlir/IR/Value.h"
1112
#include "llvm/ADT/DenseMap.h"
1213

14+
#include "llvm/Support/raw_ostream.h"
15+
1316
using namespace mlir;
1417

1518
namespace xilinx {
@@ -57,5 +60,16 @@ LogicalResult emitUpdateBdAddressFromOffsetParameter(OpBuilder &builder,
5760
Operation *bdOp,
5861
BaseMemRefType bufType,
5962
uint64_t registerAddr);
63+
64+
// Emit the params.txt description of every `aiex.scratchpad_parameter` in
65+
// `moduleOp` (with their assigned `state_table_idx`/`kind`) to `os`.
66+
//
67+
// Format (one entry per line, easily parsed with std::ifstream >>):
68+
// <num_parameters>
69+
// <name> <state_table_idx> <type> <kind>
70+
// ...
71+
// where kind is "core" (shift-2 encoded, for read_scratchpad_parameter) or
72+
// "addr" (raw, for offset_parameter on DMA ops).
73+
void emitScratchpadParamsFile(mlir::ModuleOp moduleOp, llvm::raw_ostream &os);
6074
}
6175
} // namespace xilinx

lib/Dialect/AIE/IR/AIEDialect.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3092,7 +3092,13 @@ RuntimeSequenceOp::getForSymbolInDevice(DeviceOp deviceOp,
30923092
llvm::StringRef symbol) {
30933093
RuntimeSequenceOp runtimeSequenceOp;
30943094
if (!symbol.size()) {
3095-
runtimeSequenceOp = *deviceOp.getOps<RuntimeSequenceOp>().begin();
3095+
auto range = deviceOp.getOps<RuntimeSequenceOp>();
3096+
if (range.begin() == range.end()) {
3097+
// No runtime sequence in the device; let the caller emit a diagnostic
3098+
// rather than dereferencing an end iterator (which crashes).
3099+
return nullptr;
3100+
}
3101+
runtimeSequenceOp = *range.begin();
30963102
} else {
30973103
Operation *maybeRuntimeSequenceOp =
30983104
mlir::SymbolTable::lookupSymbolIn(deviceOp, symbol);

lib/Dialect/AIEX/Transforms/AIELowerScratchpadParameters.cpp

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//===----------------------------------------------------------------------===//
77

88
#include "aie/Dialect/AIE/IR/AIEDialect.h"
9+
#include "aie/Dialect/AIEX/AIEUtils.h"
910
#include "aie/Dialect/AIEX/IR/AIEXDialect.h"
1011
#include "aie/Dialect/AIEX/Transforms/AIEXPasses.h"
1112

@@ -264,15 +265,10 @@ struct AIELowerScratchpadParametersPass
264265
}
265266
}
266267

267-
// Emit a single params.txt for the whole module.
268-
//
269-
// Format (one entry per line, easily parsed with std::ifstream >>):
270-
// <num_parameters>
271-
// <name> <state_table_idx> <type> <kind>
272-
// ...
273-
// where kind is "core" (shift-2 encoded, for read_scratchpad_parameter) or
274-
// "addr" (raw, for offset_parameter on DMA ops).
275-
LogicalResult emitParamsFile(ArrayRef<ScratchpadParameterOp> allParams) {
268+
// Emit a single params.txt for the whole module to `outputParamsFile`.
269+
// The actual serialization lives in the shared `emitScratchpadParamsFile`
270+
// helper so the aiecc graph and this pass stay in sync.
271+
LogicalResult emitParamsFile() {
276272
if (outputParamsFile.empty())
277273
return success();
278274

@@ -284,18 +280,7 @@ struct AIELowerScratchpadParametersPass
284280
<< outputParamsFile << "': " << ec.message();
285281
}
286282

287-
out << allParams.size() << "\n";
288-
for (auto p : allParams) {
289-
std::string typeStr;
290-
llvm::raw_string_ostream os(typeStr);
291-
p.getType().print(os);
292-
StringRef kindStr = p.getKind().value() == ScratchpadParameterKind::Addr
293-
? "addr"
294-
: "core";
295-
out << p.getSymName() << " "
296-
<< static_cast<unsigned>(p.getStateTableIdx().value()) << " "
297-
<< typeStr << " " << kindStr << "\n";
298-
}
283+
emitScratchpadParamsFile(getOperation(), out);
299284
return success();
300285
}
301286

@@ -445,7 +430,7 @@ struct AIELowerScratchpadParametersPass
445430
}
446431

447432
// Step 5: emit the single params.txt for the module.
448-
if (failed(emitParamsFile(allParams))) {
433+
if (failed(emitParamsFile())) {
449434
return signalPassFailure();
450435
}
451436
}

lib/Dialect/AIEX/Utils/AIEUtils.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,3 +201,21 @@ LogicalResult AIEX::emitUpdateBdAddressFromOffsetParameter(
201201
/*buffer=*/nullptr, /*column=*/nullptr, /*row=*/nullptr);
202202
return success();
203203
}
204+
205+
void AIEX::emitScratchpadParamsFile(ModuleOp moduleOp, llvm::raw_ostream &os) {
206+
SmallVector<AIEX::ScratchpadParameterOp> allParams;
207+
moduleOp.walk([&](AIEX::ScratchpadParameterOp p) { allParams.push_back(p); });
208+
209+
os << allParams.size() << "\n";
210+
for (auto p : allParams) {
211+
std::string typeStr;
212+
llvm::raw_string_ostream ts(typeStr);
213+
p.getType().print(ts);
214+
StringRef kindStr =
215+
p.getKind().value() == AIEX::ScratchpadParameterKind::Addr ? "addr"
216+
: "core";
217+
os << p.getSymName() << " "
218+
<< static_cast<unsigned>(p.getStateTableIdx().value()) << " " << typeStr
219+
<< " " << kindStr << "\n";
220+
}
221+
}

programming_guide/compilation_stages.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ linked into the final xclbin.
166166
| `main_core_<col>_<row>.ld.script` | linker script Peano used to lay out that ELF |
167167
| `main_core_<col>_<row>.ll` | per-core LLVM IR before `opt` |
168168
| `main_core_<col>_<row>.opt.ll` | per-core LLVM IR after `opt` |
169-
| `main_core_<col>_<row>.peanohack.ll` | Peano workaround IR (vector-intrinsic fixups) |
169+
| `main_core_<col>_<row>.peano-compat.ll` | Peano-compatible IR (LLVM-23 features downgraded for Peano's opt/llc) |
170170
| `main_core_<col>_<row>.o` | per-core compiled object that links into the `.elf` |
171171
| `<kernel>.cc` | `ExternalFunction` kernel source, copied in for `clang` |
172172
| `<kernel>_<hash>.o` | `clang`'s compiled `.o` for that `ExternalFunction` |

python/utils/callabledesign.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,14 +344,19 @@ def __call__(self, *runtime_args, **runtime_kwargs):
344344
extra_key=compilable._generation_cache_key(),
345345
)
346346

347-
kernel = self._kernel_cache.get(cache_key) if compilable.use_cache else None
348-
if kernel is not None and (
349-
not Path(kernel.xclbin_path).is_file()
350-
or not Path(kernel.insts_path).is_file()
351-
):
352-
self._kernel_cache.pop(cache_key, None)
353-
kernel = None
354-
if kernel is None:
347+
if compilable.use_cache and cache_key in self._kernel_cache:
348+
kernel = self._kernel_cache[cache_key]
349+
# Defend against an on-disk artifact being removed out from under a
350+
# live in-memory cache entry (e.g. a caller clearing ~/.npu/cache
351+
# between dispatches): recompile if either the cached xclbin or the
352+
# instructions file is gone.
353+
if not (
354+
Path(kernel.xclbin_path).is_file() and Path(kernel.insts_path).is_file()
355+
):
356+
kernel = self._compile_and_build_kernel(
357+
compilable, cache_key, trace_config
358+
)
359+
else:
355360
kernel = self._compile_and_build_kernel(compilable, cache_key, trace_config)
356361

357362
tensor_args, remaining_scalars = compilable.split_runtime_args(

python/utils/compile/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ def compile_mlir_module(
213213
args.extend(["--aie-generate-elf", f"--elf-name={elf_path}"])
214214
if work_dir:
215215
args.append(f"--tmpdir={work_dir}")
216+
# Emit input_with_addresses.mlir into work_dir; the JIT DMA-size
217+
# validator (parse_dma_sizes) and the trace parser read it from there.
218+
args.append("--aie-generate-input-with-addresses")
216219
if verbose:
217220
args.append("--verbose")
218221
if options:

test/aiecc/buffers_xclbin.mlir

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
//===----------------------------------------------------------------------===//
66

77
// The host BO count is derived from the runtime_sequence argument count, so a
8-
// 6-argument sequence emits exactly bo0..bo5.
8+
// 6-argument sequence emits exactly bo0..bo5. Only the generated kernels JSON
9+
// metadata is inspected, so this runs the front-end without compiling cores.
910

1011
// RUN: %python aiecc.py -n --no-compile --no-link --aie-generate-xclbin %s
11-
// RUN: FileCheck %s --input-file=buffers_xclbin.mlir.prj/main_kernels.json
12+
// RUN: FileCheck %s --input-file=buffers_xclbin.mlir.prj/kernels_main.json
1213

1314
// CHECK: "name": "bo0"
1415
// CHECK: "offset": "0x14"

test/aiecc/buffers_xclbin_few.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//===----------------------------------------------------------------------===//
66

77
// RUN: %python aiecc.py -n --no-compile --no-link --aie-generate-xclbin %s
8-
// RUN: FileCheck %s --input-file=buffers_xclbin_few.mlir.prj/main_kernels.json
8+
// RUN: FileCheck %s --input-file=buffers_xclbin_few.mlir.prj/kernels_main.json
99

1010
// The host BO count is the runtime_sequence argument count, floored at 5 to
1111
// satisfy the NPU firmware command-chain (xrt::runlist) ABI. A 2-argument

test/aiecc/cpp_aie2p_target.mlir

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,15 @@
99

1010
// Test AIE2P (Strix) target compilation
1111

12-
// RUN: aiecc --no-xchesscc --no-xbridge --verbose %s | FileCheck %s
13-
14-
// CHECK: Successfully parsed input file
15-
// CHECK: Found 1 AIE device
16-
// CHECK: Detected AIE target: AIE2p
17-
// CHECK: Running resource allocation pipeline in-memory
18-
// CHECK: Resource allocation pipeline completed successfully
19-
// CHECK: Running routing pipeline in-memory
20-
// CHECK: Compiling core (0, 2)
21-
// CHECK: Compilation completed successfully
12+
// RUN: aiecc --no-xchesscc --no-xbridge --aie-generate-npu-insts --aie-generate-xclbin --verbose %s 2>&1 | FileCheck %s
13+
14+
// Pipeline coverage plus AIE2p target detection, verified via the aie2p
15+
// code-generation triple.
16+
// CHECK: ({{[0-9]+}}/{{[0-9]+}}) input.mlir
17+
// CHECK: ({{[0-9]+}}/{{[0-9]+}}) placed.mlir
18+
// CHECK: ({{[0-9]+}}/{{[0-9]+}}) input_physical.mlir
19+
// CHECK: exec:{{.*}}--march=aie2p
20+
// CHECK: wrote edge 'insts_
2221

2322
module {
2423
aie.device(npu2) {

0 commit comments

Comments
 (0)