Last active
September 2, 2026 20:06
-
-
Save xypron/83f68494e144069674e337fbd243a2ee to your computer and use it in GitHub Desktop.
vloxei64.v.test.c
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
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #define PAGE_SIZE 4096 | |
| // Robust 16-bit bit reversal using mask-and-swap layers (bytes -> nibbles -> pairs -> bits) | |
| uint16_t reverse_16_bits(uint16_t x, uint32_t bit_width) { | |
| // 1. Swap bytes: 0xAABB -> 0xBBAA | |
| x = ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8); | |
| // 2. Swap nibbles: 0x1234 -> 0x2143 | |
| x = ((x & 0x0F0F) << 4) | ((x & 0xF0F0) >> 4); | |
| // 3. Swap 2-bit pairs | |
| x = ((x & 0x3333) << 2) | ((x & 0xCCCC) >> 2); | |
| // 4. Swap individual bits | |
| x = ((x & 0x5555) << 1) | ((x & 0xAAAA) >> 1); | |
| // Shift down to the actual active bit width of our system | |
| // Example: If bit_width is 4 (16 elements), we shift down by (16 - 4) = 12 | |
| return x >> (16 - bit_width); | |
| } | |
| int main() { | |
| uint32_t num_elements = 0; | |
| // 1. Query the hardware to check how many elements fit in LMUL=1 | |
| asm volatile ( | |
| "vsetvli %0, zero, e8, m1, ta \n\t" | |
| : "=r" (num_elements) | |
| ); | |
| printf("Detected Hardware Profiling:\n"); | |
| printf(" Elements handled per register (VLEN/8): %u\n", num_elements); | |
| printf(" Implied VLEN size: %u bits\n\n", num_elements * 8); | |
| // Calculate the binary bit-width needed for this element count | |
| uint32_t bit_width = 0; | |
| while ((1 << bit_width) < num_elements) { | |
| bit_width++; | |
| } | |
| // 2. Allocate page-aligned memory chunks dynamically | |
| uint8_t **pages = malloc(num_elements * sizeof(uint8_t*)); | |
| for (uint32_t i = 0; i < num_elements; i++) { | |
| if (posix_memalign((void**)&pages[i], PAGE_SIZE, PAGE_SIZE) != 0) { | |
| perror("Allocation failed"); | |
| return 1; | |
| } | |
| *pages[i] = (uint8_t)(0x55 ^ i); | |
| } | |
| // 3. Setup base address and compute true bit-reversed offsets | |
| uintptr_t base_addr = (uintptr_t)pages; | |
| uint64_t *offsets = malloc(num_elements * sizeof(uint64_t)); | |
| for (uint32_t i = 0; i < num_elements; i++) { | |
| uint32_t rev_i = reverse_16_bits((uint16_t)i, bit_width); | |
| offsets[i] = (uint64_t)((uintptr_t)pages[rev_i] - base_addr); | |
| } | |
| // Allocate output buffer | |
| uint8_t *destination_output = calloc(num_elements, sizeof(uint8_t)); | |
| // 4. Inline Dynamic RISC-V Assembly Block | |
| asm volatile ( | |
| "vsetvli zero, %3, e8, m1, ta \n\t" | |
| // Step A: Switch configuration to load the 64-bit indices. | |
| // Index EMUL = (64 / 8) * m1 = m8. | |
| "vsetvli zero, %3, e64, m8, ta \n\t" | |
| "vle64.v v8, (%1) \n\t" // Fills v8-v15 completely | |
| // Step B: Revert back to the destination data layout configuration | |
| "vsetvli zero, %3, e8, m1, ta \n\t" | |
| // Step C: Execute Gather Load | |
| "vloxei64.v v0, (%0), v8 \n\t" | |
| // Step D: Store out the dynamically filled vector register | |
| "vse8.v v0, (%2) \n\t" | |
| : | |
| : "r" (base_addr), "r" (offsets), "r" (destination_output), "r" (num_elements) | |
| : "t0", "memory", "v4", "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15" | |
| ); | |
| // 5. Dynamic Verification Check | |
| int success = 1; | |
| for (uint32_t i = 0; i < num_elements; i++) { | |
| uint32_t rev_i = reverse_16_bits((uint16_t)i, bit_width); | |
| uint8_t expected = (uint8_t)(0x55 ^ rev_i); | |
| uint8_t actual = destination_output[i]; | |
| printf("Slot %5d: Expected Page %5d (Value 0x%02x), Loaded 0x%02x -> %s\n", | |
| i, rev_i, expected, actual, (expected == actual) ? "PASS" : "FAIL"); | |
| if (expected != actual) { | |
| success = 0; | |
| } | |
| } | |
| // Cleanup | |
| for (uint32_t i = 0; i < num_elements; i++) free(pages[i]); | |
| free(pages); | |
| free(offsets); | |
| free(destination_output); | |
| if (success) { | |
| printf("\nResult: SUCCESS! 16-bit bit-reversed data verified successfully across all lanes.\n"); | |
| return 0; | |
| } else { | |
| printf("\nResult: FAILURE! Data verification failed.\n"); | |
| return 1; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment