code wiki / _hdl_build / nx_amo_payload.nx
nx_amo_payload.nx source
↩ module page · 62 lines · 3946 B
1// nx_amo_payload.nx -- emit a bare-metal RV64IA test payload (.bin) that exercises the A-extension
2// (amoadd/amoswap/amoxor/amoand .d, with signed operands) by threading a byte through a scratch
3// word and writing each amo's OLD value to the 16550 UART -- the emitted stream spells "ATOMIC".
4// Run the SAME .bin on the sovereign emulator AND real qemu-system-riscv64 -M virt: identical
5// output = EXTERNAL-ORACLE proof of the atomics (mirrors the 72-byte boot-payload evidence).
6import "nx_syscalls.nx"
7import "nishi_hdl_primitives.nx"
8import "nx_rv64_asm.nx"
9const K_MAGIC_4096: i64 = 4096
10
11// AMO instruction word: funct5[31:27] rs2[24:20] rs1[19:15] funct3[14:12] rd[11:7] opcode=0x2f (aq=rl=0).
12func amo_enc(funct5: i64, rs2: i64, rs1: i64, funct3: i64, rd: i64) -> i64 {
13 return (funct5<<27) | (rs2<<20) | (rs1<<15) | (funct3<<12) | (rd<<7) | 0x2f
14}
15
16func build(out: *u8) -> i64 {
17 let po: *i64 = sys_mmap(8) as *i64; po[0]=0
18 po[0]=ra_put(out, po[0], ra_u(0x37, 1, 0x10000)) // lui x1, UART base 0x10000000
19 po[0]=ra_put(out, po[0], ra_u(0x37, 2, 0x100)) // lui x2, finisher base 0x100000
20 po[0]=ra_put(out, po[0], ra_u(0x37, 3, 0x5)) // lui x3, 5
21 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 3, 3, 0x555)) // addi x3,x3,0x555 -> 0x5555
22 po[0]=ra_put(out, po[0], ra_u(0x37, 15, 0x80002)) // lui x15, 0x80002 (sign-extended)
23 po[0]=ra_put(out, po[0], ra_i(0x13, 1, 15, 15, 32)) // slli x15,x15,32
24 po[0]=ra_put(out, po[0], ra_i(0x13, 5, 15, 15, 32)) // srli x15,x15,32 -> 0x80002000
25 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 5, 0, 0x41)) // addi x5,x0,0x41 ('A')
26 po[0]=ra_put(out, po[0], ra_s(0x23, 3, 15, 5, 0)) // sd x5,0(x15)
27 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 6, 0, 0x13)) // addi x6,x0,0x13
28 po[0]=ra_put(out, po[0], amo_enc(0x00, 6, 15, 3, 7)) // amoadd.d x7,x6,(x15) old 'A', mem 'T'
29 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 7, 0)) // sb x7,0(x1) -> 'A'
30 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 6, 0, 0x4F)) // addi x6,x0,0x4F ('O')
31 po[0]=ra_put(out, po[0], amo_enc(0x01, 6, 15, 3, 8)) // amoswap.d x8 old 'T', mem 'O'
32 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 8, 0)) // sb x8 -> 'T'
33 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 6, 0, 0x02)) // addi x6,x0,0x02
34 po[0]=ra_put(out, po[0], amo_enc(0x04, 6, 15, 3, 9)) // amoxor.d x9 old 'O', mem 'M'
35 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 9, 0)) // sb x9 -> 'O'
36 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 6, 0, 0-5)) // addi x6,x0,-5
37 po[0]=ra_put(out, po[0], amo_enc(0x0c, 6, 15, 3, 10)) // amoand.d x10 (neg operand) old 'M', mem 'I'
38 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 10, 0)) // sb x10 -> 'M'
39 po[0]=ra_put(out, po[0], ra_i(0x13, 0, 6, 0, 0-6)) // addi x6,x0,-6
40 po[0]=ra_put(out, po[0], amo_enc(0x00, 6, 15, 3, 11)) // amoadd.d x11 old 'I', mem 'C'
41 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 11, 0)) // sb x11 -> 'I'
42 po[0]=ra_put(out, po[0], ra_i(0x03, 3, 12, 15, 0)) // ld x12,0(x15) -> 'C'
43 po[0]=ra_put(out, po[0], ra_s(0x23, 0, 1, 12, 0)) // sb x12 -> 'C'
44 po[0]=ra_put(out, po[0], ra_s(0x23, 2, 2, 3, 0)) // sw x3,0(x2) -> finisher halt
45 return po[0]
46}
47
48func main() -> i64 {
49 let out: *u8 = sys_mmap(K_MAGIC_4096)
50 let nb: i64 = build(out)
51 let fd: i64 = sys_openat_wr("knowledge/hw/amo_test.bin" as *u8, 420)
52 if fd >= 0 { sys_write(fd, out, nb); sys_close(fd) }
53 sys_write(1, "wrote knowledge/hw/amo_test.bin (expect UART = 'ATOMIC') nbytes=" as *u8, 63)
54 let b: *u8=sys_mmap(8); var d: i64=0; var y: i64=nb
55 if nb==0 { b[0]=48; sys_write(1,b,1) }
56 while y>0 { d=d+1; y=y/10 }
57 var i: i64=d-1; y=nb
58 while i>=0 { b[i]=(48+(y%10)) as u8; y=y/10; i=i-1 }
59 if d>0 { sys_write(1,b,d) }
60 sys_write(1, "\n" as *u8, 1)
61 sys_exit(0); return 0
62}