Pure compute: builds both LUTs, runs all five timed paths, returns numbers. No printing — the caller (RPC handler or boot-time bridge) decides.
| 42 | /// Pure compute: builds both LUTs, runs all five timed paths, returns numbers. |
| 43 | /// No printing — the caller (RPC handler or boot-time bridge) decides. |
| 44 | inline Wave8ExpandResult measureWave8Expand(int iters_in = 30000) { |
| 45 | Wave8ExpandResult result{}; |
| 46 | if (iters_in < 1) { |
| 47 | iters_in = 1; |
| 48 | } |
| 49 | if (iters_in > 200000) { |
| 50 | iters_in = 200000; |
| 51 | } |
| 52 | result.iters = static_cast<fl::u32>(iters_in); |
| 53 | |
| 54 | // Representative WS2812B-ish timing; absolutes don't matter for the bench. |
| 55 | fl::ChipsetTiming timing; |
| 56 | timing.T1 = 400; |
| 57 | timing.T2 = 450; |
| 58 | timing.T3 = 400; |
| 59 | |
| 60 | fl::Wave8BitExpansionLut nibLut = fl::buildWave8ExpansionLUT(timing); |
| 61 | fl::Wave8ByteExpansionLut byteLut = fl::buildWave8ByteExpansionLUT(nibLut); |
| 62 | |
| 63 | fl::u8 lanes[16]; |
| 64 | for (int i = 0; i < 16; ++i) { |
| 65 | lanes[i] = static_cast<fl::u8>(i * 17 + 3); |
| 66 | } |
| 67 | fl::Wave8Byte out[16]; |
| 68 | volatile fl::u32 sink = 0; |
| 69 | |
| 70 | // Warm caches / icache. |
| 71 | for (int i = 0; i < 16; ++i) { |
| 72 | fl::detail::wave8_convert_byte_to_wave8byte(lanes[i], nibLut, &out[i]); |
| 73 | fl::detail::wave8_expand_byte(lanes[i], byteLut, &out[i]); |
| 74 | } |
| 75 | fl::u8 transposed[16 * sizeof(fl::Wave8Byte)]; |
| 76 | fl::wave8Transpose_16(reinterpret_cast<const fl::u8(&)[16]>(lanes), nibLut, |
| 77 | reinterpret_cast<fl::u8(&)[16 * sizeof(fl::Wave8Byte)]>(transposed)); |
| 78 | fl::wave8Transpose_16(reinterpret_cast<const fl::u8(&)[16]>(lanes), byteLut, |
| 79 | reinterpret_cast<fl::u8(&)[16 * sizeof(fl::Wave8Byte)]>(transposed)); |
| 80 | |
| 81 | const int iters = iters_in; |
| 82 | |
| 83 | // --- Expansion only: nibble (current production path) --- |
| 84 | { |
| 85 | fl::u32 t0 = micros(); |
| 86 | for (int it = 0; it < iters; ++it) { |
| 87 | lanes[0] = static_cast<fl::u8>(it); |
| 88 | lanes[8] = static_cast<fl::u8>(~it); |
| 89 | for (int i = 0; i < 16; ++i) { |
| 90 | fl::detail::wave8_convert_byte_to_wave8byte(lanes[i], nibLut, &out[i]); |
| 91 | } |
| 92 | sink ^= out[0].symbols[0].data ^ out[15].symbols[7].data; |
| 93 | } |
| 94 | result.expand_nibble_us = micros() - t0; |
| 95 | } |
| 96 | |
| 97 | // --- Expansion only: byte-LUT (S1) --- |
| 98 | { |
| 99 | fl::u32 t0 = micros(); |
| 100 | for (int it = 0; it < iters; ++it) { |
| 101 | lanes[0] = static_cast<fl::u8>(it); |
no test coverage detected