P3.1: extract FFT code from rt snap (extract_fft.py); decode cplx_mul 0x8440 = in-place elementwise double mult, twiddle loader 0x39b00 stride copy, dispatcher 0x535a70->0x140a10/70->jumptable[0x1826159a0]=4; implement cplx_mul_scalar_inplace
This commit is contained in:
@@ -3,6 +3,13 @@
|
|||||||
|
|
||||||
namespace fft_stage {
|
namespace fft_stage {
|
||||||
|
|
||||||
|
// 0x180008440: dst[i] *= src[i] (double, in-place elementwise; kernel 0x18003fa20)
|
||||||
|
void cplx_mul_scalar_inplace(double* dst, const double* src, uint32_t n) {
|
||||||
|
for (uint32_t i = 0; i < n; i++) {
|
||||||
|
dst[i] *= src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// cplx_mul — complex elementwise multiply: out = in1 * in2 (conjugated 2nd)
|
// cplx_mul — complex elementwise multiply: out = in1 * in2 (conjugated 2nd)
|
||||||
void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n) {
|
void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n) {
|
||||||
for (uint32_t i = 0; i < n * 2; i += 2) {
|
for (uint32_t i = 0; i < n * 2; i += 2) {
|
||||||
|
|||||||
@@ -4,6 +4,12 @@
|
|||||||
|
|
||||||
namespace fft_stage {
|
namespace fft_stage {
|
||||||
|
|
||||||
|
// 0x180008440 (kernel 0x18003fa20): IN-PLACE elementwise double multiply
|
||||||
|
// dst[i] *= src[i]. NOT a complex multiply — the complex op is done via separate
|
||||||
|
// re/im passes on the interleaved layout.
|
||||||
|
void cplx_mul_scalar_inplace(double* dst, const double* src, uint32_t n);
|
||||||
|
|
||||||
|
// complex elementwise multiply (interleaved re,im): out = in1 * in2
|
||||||
void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n);
|
void cplx_mul(double* out, const double* in1, const double* in2, uint32_t n);
|
||||||
void stage_complex(double* out, const double* in, const double* tw, uint32_t n);
|
void stage_complex(double* out, const double* in, const double* tw, uint32_t n);
|
||||||
void stage_double(double* out, const double* in, const double* tw, uint32_t n);
|
void stage_double(double* out, const double* in, const double* tw, uint32_t n);
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""extract_fft.py — extract FFT-related code regions from the rt snap into raw bins."""
|
||||||
|
import struct, mmap, os
|
||||||
|
|
||||||
|
SNAP = '/tmp/snap_rt.bin'
|
||||||
|
OUT = '/tmp/fft/'
|
||||||
|
|
||||||
|
# (name, addr, size)
|
||||||
|
TARGETS = [
|
||||||
|
('cplx_mul_8440', 0x180008440, 0x80),
|
||||||
|
('cplx_mul_kernel_c440', 0x18000c440, 0x100),
|
||||||
|
('stage_bfc0', 0x18000bfc0, 0x600),
|
||||||
|
('stage_c5e0', 0x18000c5e0, 0x600),
|
||||||
|
('twiddle_loader_39b00', 0x180039b00, 0x400),
|
||||||
|
('plan_gen_2f980', 0x18002f980, 0x1200),
|
||||||
|
('dispatcher_535a70', 0x180535a70, 0x100),
|
||||||
|
('scalar_140a10', 0x180140a10, 0x200),
|
||||||
|
('vector_140a70', 0x180140a70, 0x200),
|
||||||
|
('fft_kernel_a5a0', 0x18001a5a0, 0x100),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
os.makedirs(OUT, exist_ok=True)
|
||||||
|
fd = os.open(SNAP, os.O_RDONLY)
|
||||||
|
sz = os.fstat(fd).st_size
|
||||||
|
mm = mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
|
||||||
|
# parse region index once
|
||||||
|
regs = []
|
||||||
|
i = 0
|
||||||
|
while i + 16 <= sz:
|
||||||
|
lo, n = struct.unpack_from('<QQ', mm, i)
|
||||||
|
regs.append((lo, i + 16, n)) # (addr, data_off, size)
|
||||||
|
i += 16 + n
|
||||||
|
regs.sort()
|
||||||
|
|
||||||
|
def readabs(addr, n):
|
||||||
|
for lo, off, rn in regs:
|
||||||
|
if lo <= addr < lo + rn and addr - lo + n <= rn:
|
||||||
|
return mm[off + (addr - lo): off + (addr - lo) + n]
|
||||||
|
return None
|
||||||
|
|
||||||
|
for name, addr, n in TARGETS:
|
||||||
|
b = readabs(addr, n)
|
||||||
|
if b:
|
||||||
|
with open(os.path.join(OUT, name + '.bin'), 'wb') as f:
|
||||||
|
f.write(b)
|
||||||
|
print('%-28s 0x%x %d bytes OK' % (name, addr, len(b)))
|
||||||
|
else:
|
||||||
|
print('%-28s 0x%x MISSING' % (name, addr))
|
||||||
|
mm.close()
|
||||||
|
os.close(fd)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
@@ -55,3 +55,35 @@ outer while (uVar24 < (iVar25-1+iVar33)/iVar33)
|
|||||||
- Copied to scratch by FUN_180039b00( log2N, dst ): step lVar18 = 1 << (10 - log2N) for N<=1024.
|
- Copied to scratch by FUN_180039b00( log2N, dst ): step lVar18 = 1 << (10 - log2N) for N<=1024.
|
||||||
- So for N = 2^m: twiddle angles sampled from table with stride 2^(10-m). For N>1024 separate (two-pass) branch (unresolved).
|
- So for N = 2^m: twiddle angles sampled from table with stride 2^(10-m). For N>1024 separate (two-pass) branch (unresolved).
|
||||||
- Stage kernels (FUN_18000bfc0/18000c5e0) consume these with 0x40-complex chunks, cplx-mul=180008440, acc=FUN_1800437c0/180044700.
|
- Stage kernels (FUN_18000bfc0/18000c5e0) consume these with 0x40-complex chunks, cplx-mul=180008440, acc=FUN_1800437c0/180044700.
|
||||||
|
|
||||||
|
## ============ UPDATE 2026-08-20 (P3: code extracted from rt snap, objdump) ============
|
||||||
|
Raw code extracted from /tmp/snap_rt.bin via handoff/extract_fft.py → /tmp/fft/*.bin.
|
||||||
|
|
||||||
|
### cplx_mul 0x180008440 = IN-PLACE ELEMENTWISE DOUBLE MULTIPLY (not complex!):
|
||||||
|
signature (rcx=dst, rdx=src, r8d=count): dst[i] *= src[i] (double).
|
||||||
|
kernel 0x18003fa20: scalar path mulsd, vector path mulpd (4-wide). Corrects the
|
||||||
|
"cplx-mul=180008440" label — the complex multiply is done via SEPARATE re/im passes
|
||||||
|
(interleaved layout), 0x8440 is the scalar elementwise multiply.
|
||||||
|
|
||||||
|
### twiddle loader FUN_180039b00 (log2N=ecx, dst=rdx):
|
||||||
|
N = 1<<log2N; count = N/4 (sar $2 after N/2 sar).
|
||||||
|
if log2N > 10: separate two-pass branch (0x180039dc9).
|
||||||
|
else stride = 1 << (10-log2N); copy sin_table[0x182616800 + k*stride*8] -> dst[k], k=0..N/4-1.
|
||||||
|
sin_table DAT_182616800 = sin(k·2π/1024) for k=0..256 (257 valid doubles, then garbage).
|
||||||
|
=> twiddle[k] = sin(k·stride·2π/1024), the quarter-period sample set.
|
||||||
|
|
||||||
|
### stage kernels FUN_18000bfc0 / 18000c5e0 (butterfly):
|
||||||
|
prologue stack 0x470 (scratch 0x200×2 doubles). Per 0x40-complex chunk:
|
||||||
|
0x180140c40(src, scratch, scratch+0x200, 0x40) — load/format twiddle into scratch
|
||||||
|
0x8440(dst, scratch, 0x40) — dst *= scratch (elementwise)
|
||||||
|
0x8440(dst, scratch+0x200, 0x40) — dst *= scratch+0x200
|
||||||
|
then butterfly arithmetic + acc (FUN_1800437c0/044700). Full loop still to transcribe.
|
||||||
|
|
||||||
|
### dispatcher 0x535a70 → 0x140a10 (scalar) / 0x140a70 (vector) (per NOTES:166).
|
||||||
|
Second-level dispatch: 0x140a10/140a70 read global index [0x1826159a0] (=4 at capture)
|
||||||
|
then jump through tables:
|
||||||
|
scalar 0x182617548 = {0x180141380, 0x1801413a0, ..., 0x1801414a0} (12 entries, [4]=0x180141400)
|
||||||
|
vector 0x182617588 = {0x180141440, ..., 0x180141560} ([4]=0x1801414c0)
|
||||||
|
These are the per-size/per-type stage kernels (0x1801413xx/1415xx family).
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user