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}