Merge main (user mods) into no-fft

This commit is contained in:
2026-06-25 00:43:53 +08:00
11 changed files with 2521 additions and 448 deletions

View File

@@ -1,166 +1,226 @@
/**
* user-sample — CIC-IEC 2026 Stage 3 (DMA-driven)
* user-sample - CIC-IEC 2026 Stage 3 Evaluation Program
*
* (UPDATED FOR PING-PONG BUFFER ARCHITECTURE)
*
* Reads N groups of 4x4 unsigned matrix multiplications from ExtRAM,
* computes C = A x B via the hardware matmul IP using Ping-Pong buffering,
* writes results back, computes CRC32 over the result region, and outputs
* the required identifiers.
*/
#include <stdio.h>
#include <stdint.h>
#include "dma.h"
/* ─── Configurable group count (default 10 for fast local testing) ─── */
#ifndef MATMUL_GROUP_NUM
#define MATMUL_GROUP_NUM 5000
#endif
/* ─── BSP globals ──────────────────────────────────────────────────── */
/* ─── BSP globals ─────────────────────────────────────────────────── */
unsigned long UART_BASE = 0xbf000000;
unsigned long CONFREG_TIMER_BASE = 0xbf20f100;
unsigned long CONFREG_CLOCKS_PER_SEC = 50000000L;
unsigned long CORE_CLOCKS_PER_SEC = 33000000L;
/* ─── Memory layout ─────────────────────────────────────────────────── */
/* ─── Memory layout ────────────────────────────────────────────────── */
#define EXTRAM_BASE_PHYS 0x1c400000
#define EXTRAM_BASE (0xA0000000 | (EXTRAM_BASE_PHYS & 0x1FFFFFFF))
#define SRC_BASE 0
#define DST_BASE (SRC_BASE + MATMUL_GROUP_NUM * 32)
#define RESULT_WORDS (MATMUL_GROUP_NUM * 48)
#define RESULT_BYTES (RESULT_WORDS * 4)
/* ─── MATMUL IP registers ──────────────────────────────────────────── */
/* ─── MATMUL IP registers (Ping-Pong Memory Map) ──────────────────── */
#define MATMUL_BASE 0xbf500000
#define MATMUL_CTRL (MATMUL_BASE + 0x000)
#define MATMUL_STATUS (MATMUL_BASE + 0x004)
#define MATMUL_A_BASE (MATMUL_BASE + 0x020)
#define MATMUL_B_BASE (MATMUL_BASE + 0x060)
#define MATMUL_C_BASE (MATMUL_BASE + 0x0a0)
/* DMA needs physical addresses (mask high bits) */
#define MATMUL_A_BASE_PHYS ((MATMUL_A_BASE) & 0x1FFFFFFF)
#define MATMUL_C_BASE_PHYS ((MATMUL_C_BASE) & 0x1FFFFFFF)
// Bank 0 Memory Space
#define MATMUL_B0_A (MATMUL_BASE + 0x100)
#define MATMUL_B0_B (MATMUL_BASE + 0x140)
#define MATMUL_B0_C (MATMUL_BASE + 0x180)
#define INPUT_BYTES_PER_GROUP 128 /* 32 words of A+B */
#define OUTPUT_BYTES_PER_GROUP 192 /* 48 words of C */
// Bank 1 Memory Space
#define MATMUL_B1_A (MATMUL_BASE + 0x300)
#define MATMUL_B1_B (MATMUL_BASE + 0x340)
#define MATMUL_B1_C (MATMUL_BASE + 0x380)
#define CTRL_START 0x1
// Control & Status Bit Masks
#define CTRL_START_B0 0x1
#define CTRL_START_B1 0x2
#define STATUS_BUSY 0x1
#define STATUS_DONE 0x2
#define STATUS_ERROR 0x4
/* ─── Convenience ──────────────────────────────────────────────────── */
/* ─── Convenience macros ──────────────────────────────────────────── */
#define REG_WR(addr, val) (*(volatile uint32_t *)(addr) = (uint32_t)(val))
#define REG_RD(addr) (*(volatile uint32_t *)(addr))
/* ─── CRC32 table ──────────────────────────────────────────────────── */
/* ─── CRC32 table (IEEE 802.3, polynomial 0xEDB88320) ─────────────── */
static const uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB30A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
static void wait_done(void)
/* ─── Read N words from IP register space ─────────────────────────── */
static void read_ip(uint32_t base, volatile uint32_t *dst, int n)
{
uint32_t status;
do { status = REG_RD(MATMUL_STATUS); }
while (!(status & (STATUS_DONE | STATUS_ERROR)));
for (int i = 0; i < n; i++)
dst[i] = REG_RD(base + i * 4);
}
int main(void)
/* ─── Write N words to IP register space ──────────────────────────── */
static void write_ip(uint32_t base, const volatile uint32_t *src, int n)
{
volatile uint32_t *extram = (volatile uint32_t *)EXTRAM_BASE;
uint32_t crc;
int g, i;
for (int i = 0; i < n; i++)
REG_WR(base + i * 4, src[i]);
}
printf("MATMUL_START\n");
/* ─── Poll IP STATUS until done and clear it (W1C) ────────────────── */
static void wait_and_clear_done(void)
{
uint32_t status;
do {
status = REG_RD(MATMUL_STATUS);
} while (!(status & (STATUS_DONE | STATUS_ERROR)));
// Write 1 to Clear the DONE bit so it's ready for the next interrupt/poll
REG_WR(MATMUL_STATUS, STATUS_DONE);
}
for (g = 0; g < MATMUL_GROUP_NUM; g++) {
uint32_t src_phys = EXTRAM_BASE_PHYS + g * INPUT_BYTES_PER_GROUP;
uint32_t dst_phys = EXTRAM_BASE_PHYS + DST_BASE * 4 + g * OUTPUT_BYTES_PER_GROUP;
/* ─── CRC32 over ExtRAM result region (little-endian byte stream) ─── */
static uint32_t compute_crc32(volatile uint32_t *extram)
{
uint32_t crc = 0xFFFFFFFF;
uint32_t i, w;
/* DMA ch0: ExtRAM → IP (A[16]+B[16] in one burst) */
dma_start_transfer(0, src_phys, MATMUL_A_BASE_PHYS, INPUT_BYTES_PER_GROUP, 0);
dma_wait_polling(0);
/* Start IP */
REG_WR(MATMUL_STATUS, STATUS_DONE | STATUS_ERROR);
REG_WR(MATMUL_CTRL, CTRL_START);
wait_done();
/* DMA ch1: IP → ExtRAM (C[48]) */
dma_start_transfer(1, MATMUL_C_BASE_PHYS, dst_phys, OUTPUT_BYTES_PER_GROUP, 0);
dma_wait_polling(1);
}
/* ── CRC32 from ExtRAM result region ────────────────────────── */
crc = 0xFFFFFFFF;
for (i = 0; i < RESULT_WORDS; i++) {
uint32_t w = extram[DST_BASE + i];
w = extram[DST_BASE + i];
crc = crc32_table[(crc ^ (w & 0xFF)) & 0xFF] ^ (crc >> 8);
crc = crc32_table[(crc ^ ((w >> 8) & 0xFF)) & 0xFF] ^ (crc >> 8);
crc = crc32_table[(crc ^ ((w >> 16) & 0xFF)) & 0xFF] ^ (crc >> 8);
crc = crc32_table[(crc ^ (w >> 24) ) & 0xFF] ^ (crc >> 8);
}
crc ^= 0xFFFFFFFF;
return crc ^ 0xFFFFFFFF;
}
/* ═══════════════════════════════════════════════════════════════════ */
int main(void)
{
if (MATMUL_GROUP_NUM <= 0) return 0;
volatile uint32_t *extram = (volatile uint32_t *)EXTRAM_BASE;
uint32_t a_buf[16], b_buf[16], c_buf[48];
uint32_t crc;
int g, i;
// Ping-Pong Buffer Register Addresses
uint32_t bank_A[2] = {MATMUL_B0_A, MATMUL_B1_A};
uint32_t bank_B[2] = {MATMUL_B0_B, MATMUL_B1_B};
uint32_t bank_C[2] = {MATMUL_B0_C, MATMUL_B1_C};
uint32_t ctrl_start[2] = {CTRL_START_B0, CTRL_START_B1};
int cur_bank = 0;
/* ── Start marker (must be first output) ──────────────────── */
printf("MATMUL_START\n");
/* ── Prologue: Load and Start the very first group ────────── */
for (i = 0; i < 16; i++) {
a_buf[i] = extram[SRC_BASE + 0 * 32 + i];
b_buf[i] = extram[SRC_BASE + 0 * 32 + 16 + i];
}
write_ip(bank_A[0], a_buf, 16);
write_ip(bank_B[0], b_buf, 16);
// Clear any pending statuses before starting
REG_WR(MATMUL_STATUS, STATUS_DONE | STATUS_ERROR);
REG_WR(MATMUL_CTRL, ctrl_start[0]);
/* ── Main Loop: Pipelined Execution ───────────────────────── */
for (g = 1; g < MATMUL_GROUP_NUM; g++) {
cur_bank = g % 2;
int prev_bank = (g - 1) % 2;
int finished_g = g - 1;
// 1. Prepare/Load data for the NEXT group into the idle bank
// (This happens concurrently while hardware calculates the previous group)
for (i = 0; i < 16; i++) {
a_buf[i] = extram[SRC_BASE + g * 32 + i];
b_buf[i] = extram[SRC_BASE + g * 32 + 16 + i];
}
write_ip(bank_A[cur_bank], a_buf, 16);
write_ip(bank_B[cur_bank], b_buf, 16);
// 2. Wait for the PREVIOUS group hardware calculation to finish
wait_and_clear_done();
// 3. Immediately start the current bank to keep hardware busy
REG_WR(MATMUL_CTRL, ctrl_start[cur_bank]);
// 4. Read the PREVIOUS group's result and write to memory
read_ip(bank_C[prev_bank], c_buf, 48);
// Required DBG prints logic modified to match the pipelined flow
if (finished_g == 1) {
printf("DBG C[0..2]=%08lx %08lx %08lx\n",
(unsigned long)c_buf[0], (unsigned long)c_buf[1], (unsigned long)c_buf[2]);
}
for (i = 0; i < 48; i++) {
extram[DST_BASE + finished_g * 48 + i] = c_buf[i];
}
if (finished_g == 0) {
printf("DBG wrote C[0]=%08lx @ ExtRAM[%d]\n",
(unsigned long)extram[DST_BASE], DST_BASE);
}
}
/* ── Epilogue: Wait for and read the very last group ──────── */
wait_and_clear_done();
read_ip(bank_C[cur_bank], c_buf, 48);
for (i = 0; i < 48; i++) {
extram[DST_BASE + (MATMUL_GROUP_NUM - 1) * 48 + i] = c_buf[i];
}
/* ── CRC32 over result region ─────────────────────────────── */
crc = compute_crc32(extram);
/* ── Final markers ────────────────────────────────────────── */
printf("MATMUL_CRC32=%08lx\n", (unsigned long)crc);
printf("MATMUL_DONE\n");
return 0;
}
}