code wiki / _hdl_build / nx_simd_isa.nx
nx_simd_isa.nx source
↩ module page · 50 lines · 2360 B
1// nx_simd_isa.nx -- a sovereign VECTOR ISA + SIMD emulator, so vectorized kernels
2// run as real vector MACHINE CODE and are proven by EXECUTION (the way we proved the
3// scalar RV64/ARM/x86 emit). Bits-up: Nishi has its own vector extension; the AVX2 /
4// NEON / RVV emit is then a DEPLOY-TIME lowering of this ISA to whatever vector unit
5// the spore/seed lands on (vertical co-design at the deploy boundary). 8 vector
6// registers x SV_W lanes (i64). Instruction = 2 words: [op|vd|va|vb, imm].
7//
8// Ops: VLOAD vd,[imm] VSTORE [imm],va VADD/VMUL/VSUB vd,va,vb. One vector op does
9// SV_W lanes -- the throughput the uops.info/nanoBench cost model prices.
10
11import "nx_syscalls.nx"
12
13const SV_W: i64 = 8
14
15const SVOP_HALT: i64 = 0
16const SVOP_VLOAD: i64 = 1
17const SVOP_VSTORE: i64 = 2
18const SVOP_VADD: i64 = 3
19const SVOP_VMUL: i64 = 4
20const SVOP_VSUB: i64 = 5
21
22// encode one instruction at slot idx; returns idx+1.
23func sv_emit(prog: *i64, idx: i64, op: i64, vd: i64, va: i64, vb: i64, imm: i64) -> i64 {
24 prog[idx * 2] = op | (vd << 8) | (va << 16) | (vb << 24)
25 prog[idx * 2 + 1] = imm
26 return idx + 1
27}
28
29// execute a straight-line vector program on the vector register file + memory image.
30// VLOAD vd <- mem[imm..]; VSTORE mem[imm..] <- va; VADD/VMUL/VSUB vd = va (op) vb,
31// lane-wise. Returns the number of vector instructions executed.
32func sv_run(prog: *i64, ninstr: i64, vregs: *i64, mem: *i64) -> i64 {
33 var pc: i64 = 0
34 while pc < ninstr {
35 let w: i64 = prog[pc * 2]
36 let imm: i64 = prog[pc * 2 + 1]
37 let op: i64 = w & 0xFF
38 let vd: i64 = (w >> 8) & 0xFF
39 let va: i64 = (w >> 16) & 0xFF
40 let vb: i64 = (w >> 24) & 0xFF
41 var j: i64 = 0
42 if op == SVOP_VLOAD { while j < SV_W { vregs[vd * SV_W + j] = mem[imm + j]; j = j + 1 } }
43 if op == SVOP_VSTORE { while j < SV_W { mem[imm + j] = vregs[va * SV_W + j]; j = j + 1 } }
44 if op == SVOP_VADD { while j < SV_W { vregs[vd * SV_W + j] = vregs[va * SV_W + j] + vregs[vb * SV_W + j]; j = j + 1 } }
45 if op == SVOP_VMUL { while j < SV_W { vregs[vd * SV_W + j] = vregs[va * SV_W + j] * vregs[vb * SV_W + j]; j = j + 1 } }
46 if op == SVOP_VSUB { while j < SV_W { vregs[vd * SV_W + j] = vregs[va * SV_W + j] - vregs[vb * SV_W + j]; j = j + 1 } }
47 pc = pc + 1
48 }
49 return ninstr
50}