### Symmetric FIR Filter Example using AIE API Source: https://context7.com/xilinx/aie_api/llms.txt Illustrates a symmetric FIR filter implementation leveraging coefficient symmetry with `aie::sliding_mul_sym_ops`. This optimized version requires only half the coefficients and automatically applies symmetry during the multiply-accumulate operation. It requires the same AIE API headers as the standard FIR filter. ```cpp // Symmetric FIR filter (exploits coefficient symmetry) void symmetric_fir_example() { constexpr unsigned Lanes = 8; constexpr unsigned Points = 16; // Total filter length using SymMul = aie::sliding_mul_sym_ops; aie::vector coeffs; // Only half coefficients needed aie::vector data; // Symmetric multiply automatically uses coefficient symmetry aie::accum acc = SymMul::mul_sym(coeffs, 0, data, 0); } ``` -------------------------------- ### Sliding Multiply FIR Filter Example using AIE API Source: https://context7.com/xilinx/aie_api/llms.txt Demonstrates a standard FIR filter implementation using `aie::sliding_mul_ops`. It configures the operation with specified lanes, filter points, and data types, then performs a multiply-accumulate operation and converts the result to an output vector. Dependencies include the `` and `` headers. ```cpp #include #include void sliding_mul_fir_example() { // FIR filter configuration constexpr unsigned Lanes = 8; // Output samples per operation constexpr unsigned Points = 8; // Filter taps constexpr unsigned CoeffStep = 1; constexpr unsigned DataStepX = 1; constexpr unsigned DataStepY = 1; using SlidingMul = aie::sliding_mul_ops; // Coefficients (filter taps) aie::vector coeffs; // Input data (must be larger than output + filter length - 1) aie::vector data; // Perform sliding multiply aie::accum acc = SlidingMul::mul(coeffs, /*coeff_start=*/0, data, /*data_start=*/0); // Convert to output aie::vector output = acc.to_vector(15); // Multiply-accumulate variant aie::accum acc2 = SlidingMul::mac(acc, coeffs, 0, data, 0); } ``` -------------------------------- ### Basic Matrix Multiplication with aie::mmul in C++ Source: https://context7.com/xilinx/aie_api/llms.txt Demonstrates basic matrix multiplication (C = A * B) and multiply-accumulate (C += A * B) using the aie::mmul class template. It shows how to define matrix dimensions, initialize matrices as vectors, perform the operations, and retrieve results. Requires the `` header. ```cpp #include void matrix_multiplication_basic() { // Define matrix multiplication: 4x4 x 4x4 = 4x4 with int16 elements using MMUL = aie::mmul<4, 4, 4, int16, int16>; // Matrices stored as vectors (row-major) aie::vector A; // 4x4 = 16 elements aie::vector B; // 4x4 = 16 elements // Create mmul object and perform multiplication MMUL mmul; mmul.mul(A, B); // C = A * B // Get result as vector aie::vector C = mmul.to_vector(0); // Multiply-accumulate: C += A * B mmul.mac(A, B); // Get result as accumulator auto acc = mmul.to_accum(); } ``` -------------------------------- ### Tensor Buffer Stream for Multi-dimensional Memory Access (C++) Source: https://context7.com/xilinx/aie_api/llms.txt Demonstrates creating and using tensor buffer streams for multi-dimensional addressing in AIE-ML/XDNA. It covers creating tensor descriptors and reading data in patterns suitable for operations like GEMM. ```cpp #include void tensor_buffer_stream_example() { alignas(aie::vector_decl_align) int16 buffer[256]; // Create tensor descriptor for 3D access // Parameters: tensor_dim(size, step) auto desc = aie::make_tensor_descriptor( aie::tensor_dim(2u, 4), // Dim 0: 2 iterations, step 4 aie::tensor_dim(2u, 2), // Dim 1: 2 iterations, step 2 aie::tensor_dim(2u, 1) // Dim 2: 2 iterations, step 1 ); // Create tensor buffer stream auto tbs = aie::make_tensor_buffer_stream(buffer, desc); // Read vectors following tensor pattern for (unsigned i = 0; i < 8; ++i) { aie::vector v; tbs >> v; // Or: auto v = tbs.pop(); } // GEMM-style tensor access for matrix multiplication // A: M x K matrix, B: K x N matrix constexpr unsigned M = 32, K = 64, N = 32; alignas(aie::vector_decl_align) int16 A[M * K]; alignas(aie::vector_decl_align) int16 B[K * N]; auto desc_A = aie::make_tensor_descriptor( aie::tensor_dim(K / 4, 4), // K dimension aie::tensor_dim(M / 4, K) // M dimension ); auto desc_B = aie::make_tensor_descriptor( aie::tensor_dim(N / 4, 4), // N dimension aie::tensor_dim(K / 4, N) // K dimension ); auto stream_A = aie::make_tensor_buffer_stream(A, desc_A); auto stream_B = aie::make_tensor_buffer_stream(B, desc_B); } ``` -------------------------------- ### bfloat16 Matrix Multiplication with aie::mmul in C++ Source: https://context7.com/xilinx/aie_api/llms.txt Shows how to perform matrix multiplication using the bfloat16 data type with the aie::mmul class template. This is relevant for AI/ML workloads on AIE-ML/XDNA architectures. Requires the `` header. ```cpp #include void matrix_multiplication_bfloat16() { // bfloat16 matrix multiplication (AIE-ML/XDNA) using MMUL_BF16 = aie::mmul<4, 8, 4, bfloat16, bfloat16>; aie::vector A; aie::vector B; MMUL_BF16 mmul; mmul.mul(A, B); aie::vector C = mmul.to_vector(); } ``` -------------------------------- ### Parallel and Linear Approximation Lookup Tables (C++) Source: https://context7.com/xilinx/aie_api/llms.txt Illustrates hardware-accelerated lookup table operations using the AIE API, including parallel lookups with interleaved data and linear approximation for non-linear functions. Requires specific data layout for parallel access. ```cpp #include void lookup_table_example() { // Parallel lookup requires specially laid out data // For 4 parallel accesses: data must be duplicated and interleaved constexpr unsigned LUT_SIZE = 256; alignas(aie::vector_decl_align) int32 lut_ab[LUT_SIZE * 2]; // Bank A+B interleaved alignas(aie::vector_decl_align) int32 lut_cd[LUT_SIZE * 2]; // Bank C+D interleaved // Create LUT object aie::lut<4, int32> my_lut(LUT_SIZE, lut_ab, lut_cd); // Parallel lookup aie::parallel_lookup> lookup(my_lut, /*step_bits=*/0, /*bias=*/128); // Perform lookup alignas(aie::vector_decl_align) int8 indices[32]; alignas(aie::vector_decl_align) int32 results[32]; auto it_in = aie::begin_vector<32>(indices); auto it_out = aie::begin_vector<32>(results); *it_out = lookup.fetch(*it_in); // Linear approximation for non-linear functions // Requires offset and slope tables alignas(aie::vector_decl_align) int16 offset_ab[LUT_SIZE * 2]; alignas(aie::vector_decl_align) int16 offset_cd[LUT_SIZE * 2]; alignas(aie::vector_decl_align) int16 slope_ab[LUT_SIZE * 2]; alignas(aie::vector_decl_align) int16 slope_cd[LUT_SIZE * 2]; aie::lut<4, int16, int16> approx_lut(LUT_SIZE, offset_ab, offset_cd, slope_ab, slope_cd); aie::linear_approx> lin_approx( approx_lut, /*step_bits=*/4, /*bias=*/128, /*shift_offset=*/8 ); auto acc_result = lin_approx.compute(*it_in); aie::vector approx_result = acc_result.to_vector(/*shift=*/8); } ``` -------------------------------- ### Blocked Matrix Multiplication with aie::mmul in C++ Source: https://context7.com/xilinx/aie_api/llms.txt Implements blocked (tiled) General Matrix Multiplication (GEMM) using the aie::mmul class. This approach is suitable for larger matrices by processing them in smaller tiles. It utilizes `aie::load_v` and `aie::store_v` for data loading and storing, assuming pre-tiled data. Requires the `` header. ```cpp #include void matrix_multiplication_blocked() { // Blocked GEMM example: C[M,N] = A[M,K] * B[K,N] constexpr unsigned M = 4, K = 4, N = 4; using MMUL = aie::mmul; // Tiled matrix pointers (pre-tiled data expected) const int16 *pA; // Size: rowA * colA * MMUL::size_A const int16 *pB; // Size: colA * colB * MMUL::size_B int16 *pC; // Size: rowA * colB * MMUL::size_C unsigned rowA = 2, colA = 3, colB = 2; // Number of tiles for (unsigned i = 0; i < rowA; ++i) { for (unsigned j = 0; j < colB; ++j) { MMUL C_tile; for (unsigned k = 0; k < colA; ++k) { auto A_tile = aie::load_v(pA + (i * colA + k) * MMUL::size_A); auto B_tile = aie::load_v(pB + (k * colB + j) * MMUL::size_B); if (k == 0) C_tile.mul(A_tile, B_tile); else C_tile.mac(A_tile, B_tile); } aie::store_v(pC + (i * colB + j) * MMUL::size_C, C_tile.to_vector(0)); } } } ``` -------------------------------- ### Multiplication and Multiply-Accumulate Operations with mul / mac Source: https://context7.com/xilinx/aie_api/llms.txt Provides functions for vector multiplication, returning accumulators with extended precision. Supports specifying accumulation precision (e.g., `acc64`) and scalar multiplication. Includes multiply-accumulate (`mac`), multiply-subtract (`msc`), and negative multiply operations. Results can be converted back to vectors with optional right-shifting. ```cpp #include void arithmetic_mul() { aie::vector a, b; // Multiply: returns accumulator (uses default accumulation precision) auto acc = aie::mul(a, b); // Returns aie::accum for int16 x int16 // Specify accumulation precision auto acc64 = aie::mul(a, b); // Force 64-bit accumulation // Vector x Scalar multiplication auto acc_scalar = aie::mul(a, int16(10)); // Multiply-accumulate: acc = acc + (a * b) aie::accum acc_init; auto acc_mac = aie::mac(acc_init, a, b); // Multiply-subtract: acc = acc - (a * b) auto acc_msc = aie::msc(acc_init, a, b); // Negative multiply-accumulate: acc = -acc + (a * b) auto acc_negmac = aie::negmul(a, b); // Equivalent to -mul(a, b) // Convert result to vector aie::vector result = acc.to_vector(15); // Shift right by 15 // Element-wise multiplication (returns vector, not accumulator) aie::vector f1, f2; aie::accum fp_acc = aie::mul(f1, f2); aie::vector fp_result = fp_acc.to_vector(); } ``` -------------------------------- ### Aligned Memory Access with load_v / store_v Source: https://context7.com/xilinx/aie_api/llms.txt Functions for loading and storing vectors from/to memory with strict alignment requirements. The buffer must be declared with `alignas(aie::vector_decl_align)` and pointers used with `load_v` and `store_v` must be aligned to the vector size. Supports explicit sizing and auto-sizing based on architecture. ```cpp #include void memory_aligned_access() { // Aligned buffer declaration (required for vector load/store) alignas(aie::vector_decl_align) int16 buffer[64]; // Aligned load - pointer must be aligned to vector size aie::vector v1 = aie::load_v<16>(buffer); // Load 16 elements aie::vector v2 = aie::load_v<32>(buffer); // Load 32 elements // Auto-sized load (uses optimal size for architecture) auto v_auto = aie::load_v(buffer); // Aligned store aie::store_v(buffer, v1); aie::store_v(buffer + 16, v2); // Example: copy aligned data alignas(aie::vector_decl_align) int32 src[128]; alignas(aie::vector_decl_align) int32 dst[128]; for (unsigned i = 0; i < 128; i += 8) { aie::vector v = aie::load_v<8>(src + i); aie::store_v(dst + i, v); } } ``` -------------------------------- ### Vector Operations with aie::vector Source: https://context7.com/xilinx/aie_api/llms.txt Demonstrates the usage of the `aie::vector` class for SIMD operations. This class represents a collection of elements mapped to vector registers and supports various operations like initialization, element access, subvector extraction/insertion, concatenation, broadcasting, zero initialization, casting, packing, and unpacking. It is fundamental for performing parallel computations on AI Engine architectures. ```cpp #include void vector_operations() { // Declare a 32-element int16 vector (512 bits) aie::vector v1; // Initialize from values aie::vector v2(1, 2, 3, 4, 5, 6, 7, 8); // Element access v1.set(42, 0); // Set element at index 0 int16 val = v1.get(0); // Get element at index 0 v1[1] = 100; // Operator[] access // Extract subvector (elements 0-7) aie::vector sub = v1.extract<8>(0); // Insert subvector at position 1 (elements 8-15) v1.insert(1, v2); // Concatenate two vectors aie::vector concat_v = aie::concat(v2, v2); // Broadcast scalar to all elements aie::vector broadcast_v = aie::broadcast(42); // Zero-initialized vector aie::vector zeros_v = aie::zeros(); // Cast vector to different element type (same total bits) aie::vector v_int32 = v1.cast_to(); // Pack to smaller type / unpack to larger type aie::vector packed = v1.pack(); aie::vector unpacked = v1.unpack(); } ``` -------------------------------- ### Absolute Value and Negation with abs / neg Source: https://context7.com/xilinx/aie_api/llms.txt Provides functions to compute the absolute value and negation of vector elements. `aie::abs` computes the absolute value, while `aie::neg` computes the negation. Also includes `aie::abs_square` for calculating the square of the absolute value of complex numbers. ```cpp #include void arithmetic_abs_neg() { aie::vector v; // Absolute value aie::vector v_abs = aie::abs(v); // Negation aie::vector v_neg = aie::neg(v); // Square of absolute value (for complex) aie::vector cv; aie::accum cv_abs_sq = aie::abs_square(cv); } ``` -------------------------------- ### Mask Operations with aie::mask Source: https://context7.com/xilinx/aie_api/llms.txt Details the functionality of the `aie::mask` class, which stores the results of comparison operations. It supports standard comparison operators (`lt`, `gt`, `eq`, `neq`, `le`, `ge`), initialization from integer types, bitwise operations (`&`, `|`, `^`, `~`), checking if all or any elements meet a condition, and usage with the `select` operation for conditional element selection. ```cpp #include void mask_operations() { aie::vector a, b; // Comparison operations return masks aie::mask<16> m_lt = aie::lt(a, b); // a[i] < b[i] aie::mask<16> m_gt = aie::gt(a, b); // a[i] > b[i] aie::mask<16> m_eq = aie::eq(a, b); // a[i] == b[i] aie::mask<16> m_ne = aie::neq(a, b); // a[i] != b[i] aie::mask<16> m_le = aie::le(a, b); // a[i] <= b[i] aie::mask<16> m_ge = aie::ge(a, b); // a[i] >= b[i] // Initialize mask from constant auto m1 = aie::mask<64>::from_uint64(0xAAAABBBBCCCCDDDDULL); auto m2 = aie::mask<16>::from_uint32(0b1010101010101010); // Bitwise operations on masks aie::mask<16> m_and = m_lt & m_gt; aie::mask<16> m_or = m_lt | m_gt; aie::mask<16> m_xor = m_lt ^ m_gt; aie::mask<16> m_not = ~m_lt; // Check all/any elements bool all_true = aie::equal(a, a); // Returns true if all elements equal bool any_diff = aie::not_equal(a, b); // Returns true if any element differs // Use mask with select operation aie::vector selected = aie::select(a, b, m_lt); // m[i]==0 ? a[i] : b[i] } ``` -------------------------------- ### Accumulator Operations with aie::accum Source: https://context7.com/xilinx/aie_api/llms.txt Illustrates the use of the `aie::accum` class for accumulator operations. This class provides extended precision (32-80 bits) for storing multiplication results and performing reduction operations. It supports initialization from vectors, conversion to vectors with downshifting, sub-accumulator extraction, growing to larger accumulators, and can be used with free functions for conversion. ```cpp #include void accumulator_operations() { // Declare 16-element 48-bit accumulator aie::accum acc1; // Initialize from vector with optional upshift aie::vector v; aie::accum acc2(v, 0); // shift = 0 // Alternative initialization acc1.from_vector(v, 4); // upshift by 4 bits // Convert accumulator to vector with downshift aie::vector result = acc1.to_vector(8); // downshift by 8 bits // For floating-point accumulators aie::accum fp_acc; aie::vector fp_result = fp_acc.to_vector(); // Extract sub-accumulator aie::accum sub_acc = acc1.extract<8>(0); // Grow to larger accumulator aie::accum large_acc = acc1.grow<32>(); // Using from_vector free function aie::accum acc3 = aie::from_vector(v, 0); // Using to_vector free function aie::vector vec_out = aie::to_vector(acc3, 15); } ``` -------------------------------- ### Unaligned Memory Access with load_unaligned_v / store_unaligned_v Source: https://context7.com/xilinx/aie_api/llms.txt Functions designed for memory access when pointer alignment is not guaranteed. These functions allow specifying alignment and offset, providing flexibility for unaligned data. `load_floor_v` is also available to align pointers down to the nearest boundary before loading. ```cpp #include void memory_unaligned_access() { int16 buffer[100]; // May not be aligned // Unaligned load - specify alignment in elements aie::vector v1 = aie::load_unaligned_v<16>(buffer, 1); // 1-element aligned aie::vector v2 = aie::load_unaligned_v<16>(buffer + 3, 1); // Offset by 3 // Unaligned store aie::store_unaligned_v<16>(buffer + 5, v1, 1); // Floor-aligned load (aligns pointer down to boundary before loading) alignas(aie::vector_decl_align) int16 data[32] = {0, 1, 2, 3, /*...*/}; int16 *ptr = &data[3]; // Not aligned to 16 elements // Load from floor-aligned address aie::vector v_floor = aie::load_floor_v<16>(ptr, 16); // v_floor contains data[0..15] (floored to 16-element boundary) } ``` -------------------------------- ### Element-wise Addition and Subtraction with add / sub Source: https://context7.com/xilinx/aie_api/llms.txt Performs element-wise addition and subtraction operations on vectors. Supports operations between two vectors, a vector and a scalar, or a scalar and a vector. Includes saturating arithmetic options that clamp results to the type's range and accumulator addition. ```cpp #include void arithmetic_add_sub() { aie::vector a, b; // Vector + Vector aie::vector sum = aie::add(a, b); aie::vector diff = aie::sub(a, b); // Vector + Scalar aie::vector sum_scalar = aie::add(a, int16(10)); aie::vector diff_scalar = aie::sub(a, int16(5)); // Scalar + Vector aie::vector sum2 = aie::add(int16(10), b); // Saturating arithmetic (clamps to type range) aie::vector sat_sum = aie::saturating_add(a, b); aie::vector sat_diff = aie::saturating_sub(a, b); // Accumulator addition aie::accum acc_a, acc_b; aie::accum acc_sum = aie::add(acc_a, acc_b); } ``` -------------------------------- ### Vector Shuffling: shuffle_up, shuffle_down, reverse, filter Source: https://context7.com/xilinx/aie_api/llms.txt Reorders elements within a vector using various shuffle modes including shifts, rotations, fills, replication, and reversal. Also includes filtering of even/odd elements. Requires the `` header. ```cpp #include void reshaping_shuffle() { aie::vector v; // Shift elements up (new elements undefined) aie::vector v_up = aie::shuffle_up(v, 4); // Shift elements down aie::vector v_down = aie::shuffle_down(v, 4); // Rotate elements (wrap around) aie::vector v_rot_up = aie::shuffle_up_rotate(v, 4); aie::vector v_rot_down = aie::shuffle_down_rotate(v, 4); // Fill with elements from another vector aie::vector fill_v; aie::vector v_fill = aie::shuffle_up_fill(v, fill_v, 4); // Replicate first element while shifting aie::vector v_repl = aie::shuffle_up_replicate(v, 4); // Reverse vector order aie::vector v_rev = aie::reverse(v); // Filter even/odd elements aie::vector v_even = aie::filter_even(v, 1); aie::vector v_odd = aie::filter_odd(v, 1); } ``` -------------------------------- ### Vector Reductions: reduce_add, reduce_max, reduce_min Source: https://context7.com/xilinx/aie_api/llms.txt Performs reduction operations on vectors to compute a single scalar value. Supports integer and floating-point vectors, as well as accumulators. Requires the `` header. ```cpp #include void reduction_operations() { aie::vector v; // Sum all elements int16 sum = aie::reduce_add(v); // Find maximum element int16 max_val = aie::reduce_max(v); // Find minimum element int16 min_val = aie::reduce_min(v); // For floating point aie::vector fv; float f_sum = aie::reduce_add(fv); float f_max = aie::reduce_max(fv); float f_min = aie::reduce_min(fv); // Accumulator reduction aie::accum acc; auto reduced_acc = aie::reduce_add(acc); } ``` -------------------------------- ### Interleaving Operations: interleave_zip, interleave_unzip Source: https://context7.com/xilinx/aie_api/llms.txt Interleaves or deinterleaves elements between two vectors. The 'step' parameter controls the granularity of the interleaving. Requires the `` header. ```cpp #include void reshaping_interleave() { aie::vector even = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30}; aie::vector odd = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}; // Interleave (zip) - combine alternating elements auto [lo, hi] = aie::interleave_zip(even, odd, 1); // lo = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15} // hi = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31} // Deinterleave (unzip) - separate alternating elements aie::vector mixed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; auto [evens, odds] = aie::interleave_unzip(mixed, mixed, 1); // Step parameter controls granularity auto [zip_lo2, zip_hi2] = aie::interleave_zip(even, odd, 2); // Zip pairs auto [zip_lo4, zip_hi4] = aie::interleave_zip(even, odd, 4); // Zip quads } ``` -------------------------------- ### Vector Iterators for Memory Access - C++ Source: https://context7.com/xilinx/aie_api/llms.txt Provides iterators for sequential and circular access to memory buffers as vectors. Supports various access modes including restricted and unaligned access, enabling efficient data processing with Xilinx AIE vector types. ```cpp #include void iterator_operations() { alignas(aie::vector_decl_align) int16 buffer[128]; // Basic vector iterator auto it = aie::begin_vector<16>(buffer); auto it_end = aie::end_vector<16>(buffer); // Read vectors sequentially while (it != it_end) { aie::vector v = *it++; // Process v... } // Random access auto it_rand = aie::begin_vector<16>(buffer); aie::vector v0 = it_rand[0]; // First vector aie::vector v2 = it_rand[2]; // Third vector it_rand += 3; // Advance by 3 vectors // Circular iterator (wraps around) auto it_circ = aie::begin_vector_circular<16, 64>(buffer); // 64-element circular buffer for (int i = 0; i < 10; ++i) { aie::vector v = *it_circ++; // Wraps after 4 vectors (64/16) } // Restrict iterator (allows compiler optimization) auto it_restrict = aie::begin_restrict_vector<16>(buffer); // Unaligned iterator auto it_unaligned = aie::begin_unaligned_vector<16>(buffer + 3); // Writing with iterators auto out_it = aie::begin_vector<16>(buffer); aie::vector data = aie::broadcast(42); *out_it++ = data; } ``` -------------------------------- ### Matrix Transpose: transpose Source: https://context7.com/xilinx/aie_api/llms.txt Transposes elements of a vector, treating it as a matrix. The function takes the vector and its dimensions (rows, columns) as arguments. Requires the `` header. ```cpp #include void reshaping_transpose() { // Transpose a 4x4 matrix stored as vector aie::vector matrix; // 4x4 matrix in row-major order // Transpose: Row/Col = 4 aie::vector transposed = aie::transpose(matrix, 4, 4); // Transpose 2x8 -> 8x2 aie::vector m2x8; aie::vector m8x2 = aie::transpose(m2x8, 2, 8); } ``` -------------------------------- ### FFT Stage Functions (Radix-2 and Mixed Radix) - C++ Source: https://context7.com/xilinx/aie_api/llms.txt Implements decimation-in-time FFTs using radix-2 and mixed radix-4 stages. These functions require specific twiddle factor arrays and shift parameters for computation. They are designed for use within the Xilinx AIE environment. ```cpp #include #include // 1024-point FFT using radix-2 stages void fft_1024pt(const cint16 *x, cint16 *y, cint16 *tmp, const cint16 *tw1, const cint16 *tw2, const cint16 *tw4, const cint16 *tw8, const cint16 *tw16, const cint16 *tw32, const cint16 *tw64, const cint16 *tw128, const cint16 *tw256, const cint16 *tw512, unsigned shift_tw, unsigned shift, bool inv) { constexpr unsigned N = 1024; // Each stage: fft_dit_r2_stage(in, twiddles, N, shift_tw, shift, inv, out) aie::fft_dit_r2_stage<512>(x, tw1, N, shift_tw, shift, inv, tmp); aie::fft_dit_r2_stage<256>(tmp, tw2, N, shift_tw, shift, inv, y); aie::fft_dit_r2_stage<128>(y, tw4, N, shift_tw, shift, inv, tmp); aie::fft_dit_r2_stage<64> (tmp, tw8, N, shift_tw, shift, inv, y); aie::fft_dit_r2_stage<32> (y, tw16, N, shift_tw, shift, inv, tmp); aie::fft_dit_r2_stage<16> (tmp, tw32, N, shift_tw, shift, inv, y); aie::fft_dit_r2_stage<8> (y, tw64, N, shift_tw, shift, inv, tmp); aie::fft_dit_r2_stage<4> (tmp, tw128, N, shift_tw, shift, inv, y); aie::fft_dit_r2_stage<2> (y, tw256, N, shift_tw, shift, inv, tmp); aie::fft_dit_r2_stage<1> (tmp, tw512, N, shift_tw, shift, inv, y); } // 512-point FFT using mixed radix-2 and radix-4 stages void fft_512pt(const cint16 *x, cint16 *y, cint16 *tmp, const cint16 *tw1, const cint16 *tw2, const cint16 *tw4, const cint16 *tw2_4, const cint16 *tw8, const cint16 *tw16, const cint16 *tw8_16, const cint16 *tw32, const cint16 *tw64, const cint16 *tw32_64, const cint16 *tw128, const cint16 *tw256, const cint16 *tw128_256, unsigned shift_tw, unsigned shift, bool inv) { constexpr unsigned N = 512; // Radix-2 first stage aie::fft_dit_r2_stage<256>(x, tw1, N, shift_tw, shift, inv, y); // Radix-4 stages (three twiddle pointers per stage) aie::fft_dit_r4_stage<64>(y, tw2, tw4, tw2_4, N, shift_tw, shift, inv, tmp); aie::fft_dit_r4_stage<16>(tmp, tw8, tw16, tw8_16, N, shift_tw, shift, inv, y); aie::fft_dit_r4_stage<4> (y, tw32, tw64, tw32_64, N, shift_tw, shift, inv, tmp); aie::fft_dit_r4_stage<1> (tmp, tw128, tw256, tw128_256, N, shift_tw, shift, inv, y); } // Twiddle factor generation (conceptual - run on host) void generate_twiddles_r2(cint16 *tw, unsigned n_stage, unsigned shift_tw) { // tw[i] = exp(-2j * pi * i / n_stage) * (1 << shift_tw) for (unsigned i = 0; i < n_stage / 2; ++i) { float angle = -2.0f * M_PI * i / n_stage; tw[i].real = (int16)(cos(angle) * (1 << shift_tw)); tw[i].imag = (int16)(sin(angle) * (1 << shift_tw)); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.