rebase: pythoc onto upstream/main (5b9b3a3) - #25
Draft
fifield wants to merge 49 commits into
Draft
Conversation
Implement external PythoC kernel compilation for IRON framework. PythoC kernels can now be compiled to LLVM IR and integrated into IRON programs as Kernel objects. New files: - python/iron/pythoc/__init__.py - Package exports - python/iron/pythoc/compiler.py - PythoC→LLVM IR compilation - python/iron/pythoc/types.py - Type mapping (PythoC↔NumPy) - python/iron/pythoc/kernel.py - PythocKernel class - python/iron/pythoc/test_standalone.py - Compilation test Modified: - python/iron/__init__.py - Export PythocKernel, compile_pythoc_kernel Key features: - Compiles PythoC kernels to AIE2-compatible LLVM IR - Returns .ll files (Peano toolchain handles .ll→.o) - Type system mapping for IRON integration - Tested with mul.py kernel (1557 bytes LLVM IR) Phase 2 (single-source inline kernels) ready for implementation. See: PythoC/PYTHOC_IRON_INTEGRATION_PLAN.md for details
…el decorator - Add @aie_kernel decorator for inline kernel definitions - Extend PythocKernel to detect and compile decorated functions - Add vector_add_inline.py example demonstrating single-source workflow - Add comprehensive test suite (all 3/3 tests pass) - Update compiler.py to support inline kernel compilation Phase 2 enables single-source development where PythoC kernels are defined inline using the @aie_kernel decorator and compiled automatically during PythocKernel initialization. This eliminates the need for separate kernel files and manual compilation steps. Test results: - Decorator metadata capture: PASS - Inline kernel compilation: PASS (1546 bytes LLVM IR) - Error handling: PASS
…mple - Follow pattern from programming_guide/mini_tutorial/single_file_end_to_end.py - Add command-line argument parsing (device, work-dir, tensor-size, etc.) - Include full compilation pipeline: MLIR generation, aiecc, and XRT execution - Add proper error handling and validation - Make executable with proper shebang The example now demonstrates the complete workflow: 1. Define PythoC kernel inline with @aie_kernel 2. Build IRON program (kernel compiles automatically) 3. Generate MLIR and compile to xclbin 4. Run on NPU and verify results Usage: python3 vector_add_inline.py [--device npu2] [--tensor-size 4096] [--skip-run]
out of date
- Use ml_dtypes.bfloat16 for proper float32→bf16→uint16 conversion (old float32.view(uint16)[::2] produced zero/half-size buffers) - Validate results with np.allclose on float32 instead of exact uint16 match - NPU end-to-end test now passes correctly
- my_kernels.py: reusable kernel library with add, sub, add_bf16, mul_bf16 - vector_add_library.py: imports add_kernel from my_kernels module instead of defining inline; NPU test passes
End-to-end example reading hardware registers (lock values) from the processor bus using PythoC's read_tm() intrinsic. Demonstrates the Peano equivalent of the Chess-based tile_mapped_read test. Targets AIE2P (npu2) by default. Verified passing on hardware.
Demonstrates runtime DMA programming from the AIE core using write_tm (processor bus writes). The kernel programs BD registers, starts DMA channels, and uses lock-based signaling for completion — no static tile DMA configuration from MLIR. Flow: host sends data via shim DMA -> core programs S2MM BD0 to receive -> core does add-one -> core programs MM2S BD1 to send -> host verifies output.
…-coding - Add get_register_offset() method to AIEAddressDecoder in regdb.py - Add extra_globals parameter to compile_pythoc_source() so callers can inject constants (e.g. register addresses) into PythoC kernels - Replace all hard-coded hex addresses in dynamic_dma_add_one.py with named constants looked up from the register database at import time
- Add extra_globals parameter to PythocKernel, forwarded to compile_pythoc_source for injecting constants (e.g. regdb addresses) - Update dynamic_dma_add_one.py and tile_mapped_read_inline.py to use PythocKernel for inline kernel compilation instead of calling compile_pythoc_source directly
PythocKernel inherits Kernel.resolve() which calls external_func internally. Use kernel.resolve() + kernel(...) directly instead of manually declaring external_func and a separate call variable.
Compiler changes: - Support helpers parameter in compile_pythoc_source() to compile helper functions alongside the main kernel in a single .o - Register helpers in PythoC's unified registry so call resolution works - Add struct type to compilation globals PythocKernel changes: - Accept helpers parameter (list of Python functions) - Prepend helper source to main kernel source before compilation New example: - dynamic_dma_struct.py: struct-based DMA BD/lock programming with helper functions compiled alongside the main kernel Minor: - Add clarifying comments to kernel.resolve() calls in low-level examples
Kernel.__init__ renamed bin_name -> object_file_name. Core() no longer accepts link_with; it must be set on external_func() instead (handled automatically by Kernel.resolve()). Update PythocKernel super().__init__() calls and programming examples accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
BFP16 matrix multiplication kernel for AIE2P using PythoC + IRON. Implements the same algorithm as mlir-air's bf16 matmul example: bf16 → accfloat → bfp16ebs8 → BFP576.MAC hardware path. 32×32 single-core with 2×2 output blocking (8×8 tiles). Passes random-data validation with <1.5% relative error vs f32 reference. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replicates mlir-air/test.cpp methodology: 10 warmup + 20 measurement iterations, wall-clock timing, reports avg/min/max latency and GFLOPS. 32×32×32 single core: ~80 us / 0.82 GFLOPS peak. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The AIE2p llc backend selects vlda/vldb only when the vector load/store carries no explicit alignment annotation (or one >= the vector width). PythoC emits element-size alignment (e.g. align 2 for bfloat) on all vector loads, which tells llc the pointer is only 2-byte aligned and forces a scalar fallback: 128x lda.s16 + 448x vpush.hi.32 per 64-element bfloat vector instead of a single vlda. Add _strip_vector_alignment() which removes 'align N' from load/store <N x T> instructions before writing the .ll file passed to llc. Scalar loads/stores are left unchanged. This matches the 'peanohack' pre-processing step already performed by aiecc on mlir-air kernels. Measured on bf16_gemm_tile_kernel: Before: vlda/vldb=4, vpush.hi.32=448, lda=456 After: vlda/vldb=49, vpush.hi.32=0, lda=63 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds hardware event tracing via IRON rt.enable_trace() to bf16_gemm_single_core.py: - Worker(trace=1) marks the compute tile for tracing - rt.enable_trace(trace_size, workers=[worker]) inside the sequence context inserts the trace packet_flow and DDR capture BD - TraceConfig / DefaultNPURuntime handles the 4th XRT buffer, hex dump, and post-processing - --trace-size BYTES CLI flag (e.g. 0x20000); 0 = disabled - After PASS, prints event0→event1 cycle summary per tile Single-core topology (one tile, one shim column) avoids the stream switch congestion that prevents tracing the multi-core design. Note: single-core correctness regression is pre-existing and unrelated to trace (fails identically without --trace-size). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Re-apply the _strip_vector_alignment performance fix, narrowed to only strip alignment annotations from <N x bfloat> and <N x half> vector load/store operations. The previous version stripped all vector types including float/i32, which caused data corruption in accumulators. The AIE2p llc backend selects vlda/vldb (vector load/store) only when alignment is absent or >= vector width. PythoC emits element-size alignment (align 2 for bfloat) which forces scalar fallback. Stripping alignment for bfloat/half enables the efficient vector instructions without affecting float/i32 types that require correct alignment. Verified on hardware: - bf16 passthrough: 0 mismatches - f32 passthrough: 0 mismatches - bf16 GEMM single-core: 1.4% relative error (PASS) - bf16 GEMM multi-core 4x4: 0.95% relative error (PASS) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Compiler pipeline (python/iron/pythoc/compiler.py): - Replace llvmlite in-process optimize+emit with Peano opt+llc subprocesses - Strip ALL vector alignment pre-opt (peanohack) and post-opt - Add _strip_unsupported_flags() for samesign and initializes(...) attributes - Pipeline: raw IR → strip align+flags → Peano opt -O2 → strip align+flags → llc Kernel changes (bf16_gemm_single_core.py, bf16_gemm_multi_core.py): - Interleave loads between MACs to reduce peak BFP register pressure (load B1 after MAC(A0,B0), load A1 after MAC(A0,B1)) - Use incrementing phi-carried pointer offsets instead of recomputing k*STRIDE - Add separate C buffer zero loop + accumulator preload from zeroed C buffer Results: single-core PASS (1.4% relative error), multi-core 1.87 TFLOPS peak at 2048x2048x2048 with 16-instruction VLIW inner loop. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The bf16_zero_kernel loop was being folded by Peano opt -O2 into llvm.memset, which lowered to a scalar byte-at-a-time st.s8 loop (16384 iterations for a 32KB buffer). Fix by using i32 vectors with vshuffle as an optimization barrier — vshuffle is an opaque AIE intrinsic that prevents the memset pattern match while still producing a zero vector. The result is a proper 512-bit vst loop (512 iterations). Also adds trace infrastructure (enable_trace, TraceConfig) for profiling support. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- program.py: create shim/mem/compute tile stubs for trace shim_col override so pathfinder has valid routing paths - runtime.py: trace configuration and shim tile handling improvements - bf16_gemm_single_core.py: move event0() after zero-fill loop Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebased
pythoconto Xilinx/mlir-aiemainat 5b9b3a3.The weekly npu-dev bead recorded upstream head 91692b3, but upstream/main had advanced when fetched for this rebase. This topic uses the current upstream/main head.
Reviewer: rebase and merge or squash and merge to advance
pythoc. The npu-dev gitlink bump lands as a separate draft PR gated on this one.