diff --git a/examples/Makefile.peano b/examples/Makefile.peano index 010365f..ccf97e4 100644 --- a/examples/Makefile.peano +++ b/examples/Makefile.peano @@ -6,7 +6,7 @@ CXX = clang++ --target=aie2-none-unknown-elf CXXFLAGS = -std=c++2b -Wno-unknown-attributes CPPFLAGS = -I../include -I$(XILINX_VITIS_AIETOOLS)/include -SOURCES := add.cpp aligned_memcpy.cpp gemm_bf16xbf16.cpp gemm_int8xint8_sparse.cpp \ +SOURCES := add.cpp aligned_memcpy.cpp cascade.cpp gemm_bf16xbf16.cpp gemm_int8xint8_sparse.cpp \ lazy.cpp lookup_table.cpp mmul.cpp operators.cpp TARGETS := $(SOURCES:.cpp=.o) diff --git a/examples/cascade.cpp b/examples/cascade.cpp new file mode 100644 index 0000000..6fc24da --- /dev/null +++ b/examples/cascade.cpp @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MIT +// Copyright (C) 2022 Xilinx, Inc. +// Copyright (C) 2022-2026 Advanced Micro Devices, Inc. + +#include + +// The adf-free cascade accessors are available where __AIE_API_HAS_CASCADE__ is +// set (today: aie2p under Peano; see aie_api/cascade.hpp). Guarding the example +// on the capability macro keeps a default build green on architectures and +// compilers that do not implement it yet, and exercises the accessors where it +// is available, e.g. clang++ --target=aie2p-none-unknown-elf -I../include -c cascade.cpp. +#if __AIE_API_HAS_CASCADE__ + +//![Adf-free cascade round-trip] +// Put a 16-lane int32 vector to the master cascade, then read one back from the +// slave cascade. On real hardware the two ends are on adjacent cores; a fused +// cross-core reduction issues the put on one core and the get on the next. +extern "C" aie::vector cascade_passthrough_i32(aie::vector x) +{ + aie::cascade_out(x); + return aie::cascade_in_i32(); +} + +// The accumulator path, which a fused cross-core K-reduction uses (partial sums +// travel as accumulators). +extern "C" aie::accum cascade_passthrough_acc32(aie::accum a) +{ + aie::cascade_out(a); + return aie::cascade_in_acc32(); +} +//![Adf-free cascade round-trip] + +#endif // __AIE_API_HAS_CASCADE__ diff --git a/include/aie_api/aie.hpp b/include/aie_api/aie.hpp index 9b631d9..2064cc9 100644 --- a/include/aie_api/aie.hpp +++ b/include/aie_api/aie.hpp @@ -72,6 +72,7 @@ #if AIE_API_ML_VERSION >= 210 #include "block_vector.hpp" #endif +#include "cascade.hpp" #include "concepts.hpp" #include "expr.hpp" #include "fft.hpp" @@ -8247,7 +8248,12 @@ BINARY_OP_IMPL(Neg) } -#ifdef __AIENGINE__ +// aie_adf.hpp brings in the ADF stream API, which includes . That header +// is part of the Vitis ADF framework and is not present in bare-metal, IRON, or +// mlir-aie builds. Only pull it in when it is actually available, so aie_api can +// be used outside the ADF flow; when __has_include is unavailable, fall back to +// the previous behavior of including it under __AIENGINE__. +#if defined(__AIENGINE__) && (!defined(__has_include) || __has_include()) #include "aie_adf.hpp" #endif #include "operators.hpp" diff --git a/include/aie_api/cascade.hpp b/include/aie_api/cascade.hpp new file mode 100644 index 0000000..434aaf6 --- /dev/null +++ b/include/aie_api/cascade.hpp @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MIT +// Copyright (C) 2022 Xilinx, Inc. +// Copyright (C) 2022-2026 Advanced Micro Devices, Inc. + +#pragma once + +#ifndef __AIE_API_CASCADE__HPP__ +#define __AIE_API_CASCADE__HPP__ + +#include "accum.hpp" +#include "vector.hpp" + +// Adf-free accessor for the AIE core-to-core cascade. +// +// aie_api otherwise exposes the cascade only through the ADF stream API in +// aie_api/adf/, which includes . 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 compiler +// intrinsics directly. +// +// The accessors bridge aie_api's vector and accum types onto the compiler's +// cascade stream intrinsics put_mcd/get_scd (aie2p intrinsic layer), which +// enable the cascade with en = 1 by default. aie_api otherwise reaches those +// intrinsics only through the ADF stream types. +// +// Availability follows aie_api's usual capability model. The cascade datapath +// exists across the AIE generations, but the intrinsics are compiler and +// architecture specific (chess vs Peano; aie2/aie2p/aie2ps). __AIE_API_HAS_CASCADE__ +// (detail//config.hpp) is 1 exactly where an implementation is present: +// today aie2p under Peano. put_mcd/get_scd are the standard stream intrinsic +// names, so extending to another compiler or architecture is expected to be a +// matter of confirming the intrinsics there and setting __AIE_API_HAS_CASCADE__; +// callers that guard on the macro then pick it up with no source change. + +namespace aie { + +#if __AIE_API_HAS_CASCADE__ + +/** + * \brief Write a 16-lane int32 vector to the master cascade datapath. + * + * Adf-free: reaches the cascade without the ADF stream API. + */ +inline void cascade_out(const vector &v) +{ + put_mcd(v.to_native()); +} + +/** + * \brief Read a 16-lane int32 vector from the slave cascade datapath. + */ +inline vector cascade_in_i32() +{ + return get_scd_v16int32(); +} + +/** + * \brief Write a 16-lane acc32 accumulator to the master cascade datapath. + * + * 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 through accum::to_native(), so no reinterpret_cast + * is needed and the storage representation is not assumed. + */ +inline void cascade_out(const accum &a) +{ + put_mcd(a.to_native()); +} + +/** + * \brief Read a 16-lane acc32 accumulator from the slave cascade datapath. + * + * The native accumulator the intrinsic returns is rebuilt into an accum through + * the implicit accum(storage_t) constructor. + */ +inline accum cascade_in_acc32() +{ + return accum(get_scd_v16acc32()); +} + +#endif // __AIE_API_HAS_CASCADE__ + +} // namespace aie + +#endif // __AIE_API_CASCADE__HPP__ diff --git a/include/aie_api/detail/aie1/config.hpp b/include/aie_api/detail/aie1/config.hpp index 513d532..17d18c9 100644 --- a/include/aie_api/detail/aie1/config.hpp +++ b/include/aie_api/detail/aie1/config.hpp @@ -11,6 +11,10 @@ #define AIE_API_ML_VERSION 100 #define AIE_API_MATH_VERSION 100 +// The adf-free cascade accessor (aie_api/cascade.hpp) is currently implemented +// only for aie2p under Peano; it is not available on this architecture. +#define __AIE_API_HAS_CASCADE__ 0 + // >= 900000 is used to detect the master development branch #define __AIE_API_REGISTER_ATTR_DEFINED__ ((__AIE_MODEL_VERSION__ >= 900000) || \ diff --git a/include/aie_api/detail/aie2/config.hpp b/include/aie_api/detail/aie2/config.hpp index 4ad6399..922640c 100644 --- a/include/aie_api/detail/aie2/config.hpp +++ b/include/aie_api/detail/aie2/config.hpp @@ -19,6 +19,10 @@ #define __AIE_API_FP32_EMULATION__ (__AIE_MODEL_VERSION__ >= 3000) +// The adf-free cascade accessor (aie_api/cascade.hpp) is currently implemented +// only for aie2p under Peano; it is not available on this architecture. +#define __AIE_API_HAS_CASCADE__ 0 + #define __AIE_API_FP32_SUPPORT__ 0 #define __AIE_API_32ELEM_FLOAT_SRS_UPS__ (__AIE_MODEL_VERSION__ >= 10300) diff --git a/include/aie_api/detail/aie2p/config.hpp b/include/aie_api/detail/aie2p/config.hpp index 11e1ba0..501e5a7 100644 --- a/include/aie_api/detail/aie2p/config.hpp +++ b/include/aie_api/detail/aie2p/config.hpp @@ -33,6 +33,17 @@ #define __AIE_API_HAS_COMPLEX_BFLOAT16_FIFO__ (__AIE_MODEL_VERSION__ >= 10500) +// Adf-free core-to-core cascade accessor (aie_api/cascade.hpp). The cascade +// datapath exists on the silicon, but the accessor is currently implemented +// only through the Peano __builtin_aie2p_* intrinsics, so it is available on +// aie2p under Peano. On other compilers (chess) the capability is 0 until the +// corresponding intrinsic path is added, so the accessor is simply not defined. +#ifdef __PEANO__ +#define __AIE_API_HAS_CASCADE__ 1 +#else +#define __AIE_API_HAS_CASCADE__ 0 +#endif + #define __AIE_API_CONSTEXPR_BFLOAT16__ (__AIE_MODEL_VERSION__ >= 10900) #define __AIE_API_COMPLEX_FP32_EMULATION__ 0 diff --git a/include/aie_api/detail/aie2ps/config.hpp b/include/aie_api/detail/aie2ps/config.hpp index fee9156..0ed2278 100644 --- a/include/aie_api/detail/aie2ps/config.hpp +++ b/include/aie_api/detail/aie2ps/config.hpp @@ -21,6 +21,10 @@ #define __AIE_API_FP32_EMULATION__ (__AIE_MODEL_VERSION__ >= 3000) +// The adf-free cascade accessor (aie_api/cascade.hpp) is currently implemented +// only for aie2p under Peano; it is not available on this architecture. +#define __AIE_API_HAS_CASCADE__ 0 + #define __AIE_API_FP32_SUPPORT__ 0 #define __AIE_API_HAS_EXTRACT_V64BFP16__ 0