Add an adf-free accessor for the core-to-core cascade - #13
Open
atassis wants to merge 2 commits into
Open
Conversation
aie_adf.hpp brings in the ADF stream API, which includes <adf.h>. That header is part of the Vitis ADF framework and is not present in bare-metal, IRON, or mlir-aie builds, so including it unconditionally under __AIENGINE__ makes the aie.hpp umbrella fail to compile in those flows. Guard the include with __has_include(<adf.h>) so it is pulled in when it is available (the Vitis flow, unchanged) and skipped gracefully otherwise, which lets aie_api be used outside the ADF flow. When __has_include is not available, fall back to the previous behavior.
aie_api exposes the AIE core-to-core cascade only through the ADF stream API in aie_api/adf/, which includes <adf.h>. Outside the ADF flow that header is absent, so a kernel cannot issue a cascade put or get through aie_api, even though the hardware datapath is reachable through the stream intrinsics. Add aie_api/cascade.hpp with typed free-function accessors (cascade_out, cascade_in_i32, cascade_in_acc32) that bridge aie_api's vector and accum types onto the compiler's put_mcd/get_scd stream intrinsics, which enable the cascade with en = 1 by default. The acc32 path is the one a fused cross-core K-reduction uses; the accum to native conversion stays inside the public accum API through accum::to_native() and the implicit accum(storage_t) constructor. Availability follows aie_api's capability model. __AIE_API_HAS_CASCADE__ is defined in each detail/<arch>/config.hpp and is 1 exactly where an implementation is present: today aie2p under Peano. It is 0 on the other architectures and on chess for aie2p, so the header is a no-op wherever the intrinsics are not available and it does not affect other compilers or architectures. examples/cascade.cpp, guarded on __AIE_API_HAS_CASCADE__, shows the int32 and acc32 round-trips.
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.
Summary
aie_api exposes the AIE core-to-core cascade only through the ADF stream API in
aie_api/adf/, which includes<adf.h>. That header is part of the Vitis ADF framework and is absent in bare-metal, IRON, and mlir-aie builds, so a kernel compiled outside the ADF flow cannot issue a cascade put or get through aie_api, even though the hardware datapath is reachable through the stream intrinsics directly. This makes the cascade usable outside the ADF flow.The branch is two self-standing commits; happy to split into two PRs if you prefer.
1. Only include the ADF headers when adf.h is available
aie.hpppullsaie_adf.hppunder#ifdef __AIENGINE__, andaie_adf.hppincludes<adf.h>.<adf.h>ships with Vitis, so under a non-Vitis toolchain (bare-metal, IRON, mlir-aie) the umbrella fails to compile. Guarding the include with__has_include(<adf.h>)keeps the Vitis flow unchanged (the header is present, so it is included exactly as before) and skips it gracefully otherwise, so<aie_api/aie.hpp>can be used outside the ADF flow. When__has_includeis not available the previous behavior is kept.2. A typed adf-free cascade accessor
aie_api/cascade.hppadds typed free-function accessors:cascade_out/cascade_in_i32forvector<int32_t,16>, andcascade_out/cascade_in_acc32foraccum<acc32,16>. They bridge aie_api's vector and accum types onto the compiler'sput_mcd/get_scdstream intrinsics, which enable the cascade withen = 1by default. The accumulator path is the one a fused cross-core K-reduction uses, since partial sums travel as accumulators; the accum to native conversion stays inside the public accum API (accum::to_native()out, the implicitaccum(storage_t)constructor in).Availability follows the capability model
The cascade datapath exists across the AIE generations, but its intrinsics are compiler and architecture specific, so the accessor is gated on a per-architecture capability macro.
__AIE_API_HAS_CASCADE__is defined in eachdetail/<arch>/config.hppand is 1 exactly where an implementation is present: today aie2p under Peano. It is 0 on the other architectures and on chess for aie2p, so the header is a no-op wherever the intrinsics are not available and it does not affect other compilers or architectures.put_mcd/get_scdare the standard stream intrinsic names, so extending to another compiler or architecture is expected to be a matter of confirming them there and setting the macro. I would welcome guidance on the preferred shape.Testing
examples/cascade.cpp, guarded on__AIE_API_HAS_CASCADE__, issues both round-trips (int32 vector and acc32) and is added to the peano examples Makefile. A default-target build stays green, and an aie2p build exercises the accessors.The accessor is validated on aie2p silicon: a three-core cascade chain (built with mlir-aie, connected by
aie.cascade_flow) whose kernels callaie::cascade_outandaie::cascade_in_i32propagates a seeded value across two cascade hops (14 -> 114 -> 214), and the host reads back 214, PASS, stable across repeated runs. The sameput_mcd/get_scdintrinsics the accessor forwards to (withen = 1) are also exercised by mlir-aie's owntest/npu-xrt/cascade_flows. The numerical behavior of the cascade is unchanged.Not in this PR
Folding the cascade into the
mmulandaccumpath so a multi-core K-reduction fuses natively is a larger design that I would be glad to raise separately as an RFC. The hand-written reduction this accessor enables is the use case that would inform that design.