code wiki / _hdl_build / rv64im_min_alu_proof.nx
rv64im_min_alu_proof.nx source
↩ module page · 115 lines · 3577 B
1// nx_rv64im_alu_proof.nx -- vector dumper to PROVE the RV64IM ALU.
2//
3// Runs nx_rv64im_alu_compute over every ALU op (1..28) across a
4// deterministic mix of edge values + LCG-generated 64-bit operands,
5// and writes "<op_dec>\t<a_hex16>\t<b_hex16>\t<r_hex16>\n" lines to
6// the proof folder. An independent Python implementation of the
7// RV64IM spec then recomputes each result and diffs -- 1:1 proof,
8// not "assertions PASS".
9//
10// expect_exit: 0
11// license_tier: ORIGINAL
12
13import "nx_syscalls.nx"
14import "rv64im_min_alu.nx"
15
16func _hex16(v: i64, out: *u8, pos: i64) -> i64 {
17 var k: i64 = 15
18 var p: i64 = pos
19 while k >= 0 {
20 let nib: i64 = (v >> (k * 4)) & 15
21 if nib < 10 { out[p] = (0x30 + nib) as u8 }
22 if nib >= 10 { out[p] = (0x61 + nib - 10) as u8 }
23 p = p + 1
24 k = k - 1
25 }
26 return p
27}
28
29func _dec2(v: i64, out: *u8, pos: i64) -> i64 {
30 var p: i64 = pos
31 if v >= 10 { out[p] = (0x30 + (v / 10)) as u8; p = p + 1 }
32 out[p] = (0x30 + (v % 10)) as u8
33 p = p + 1
34 return p
35}
36
37func _emit_vec(op: i64, a: i64, b: i64, out: *u8, pos: i64) -> i64 {
38 let r: i64 = nx_rv64im_alu_compute(op, a, b)
39 var p: i64 = pos
40 p = _dec2(op, out, p)
41 out[p] = 0x09 as u8; p = p + 1
42 p = _hex16(a, out, p)
43 out[p] = 0x09 as u8; p = p + 1
44 p = _hex16(b, out, p)
45 out[p] = 0x09 as u8; p = p + 1
46 p = _hex16(r, out, p)
47 out[p] = 0x0A as u8; p = p + 1
48 return p
49}
50
51func main() -> i64 {
52 // Edge-value table (built arithmetically; NishiLang large hex
53 // literals are avoided per the substrate idiom).
54 let E: *i64 = sys_mmap(8 * 16) as *i64
55 E[0]=0; E[1]=1; E[2]=2; E[3]=3; E[4]=7
56 E[5]=0 - 1 // 0xFFFFFFFFFFFFFFFF
57 E[6]=0 - 9223372036854775808 // INT_MIN
58 E[7]=9223372036854775807 // INT_MAX
59 E[8]=4294967296 // 1<<32
60 E[9]=4294967295 // 0xFFFFFFFF
61 E[10]=2147483648 // 1<<31
62 E[11]=2147483647 // 0x7FFFFFFF
63 E[12]=0 - 2147483648 // -(1<<31)
64 E[13]=255
65 E[14]=256
66 E[15]=0 - 256
67 let ne: i64 = 16
68
69 let out: *u8 = sys_mmap(8388608) as *u8 // 8 MiB
70 var pos: i64 = 0
71
72 // LCG state (MMIX constants); deterministic.
73 var lcg: i64 = 88172645463325252
74
75 var op: i64 = 1
76 while op < NX_RV64IM_ALU_N {
77 // trace current op to stderr so a native-divide trap is locatable
78 let tb: *u8 = sys_mmap(8)
79 var tp: i64 = _dec2(op, tb, 0)
80 tb[tp] = 0x0A as u8
81 sys_write(2, tb, tp + 1)
82 // All edge x edge crosses.
83 var i: i64 = 0
84 while i < ne {
85 var j: i64 = 0
86 while j < ne {
87 pos = _emit_vec(op, E[i], E[j], out, pos)
88 j = j + 1
89 }
90 i = i + 1
91 }
92 // LCG random pairs.
93 var k: i64 = 0
94 while k < 256 {
95 lcg = lcg * 6364136223846793005 + 1442695040888963407
96 let a: i64 = lcg
97 lcg = lcg * 6364136223846793005 + 1442695040888963407
98 let b: i64 = lcg
99 pos = _emit_vec(op, a, b, out, pos)
100 k = k + 1
101 }
102 op = op + 1
103 }
104
105 let path: *u8 = "/mnt/c/Users/elder/nishi-browser-proofs/alu_vectors.tsv\x00"
106 let ofd: i64 = sys_openat_wr(path, 0x1A4)
107 if ofd <= 0 { return 70 }
108 sys_write(ofd, out, pos)
109 sys_close(ofd)
110
111 let pass: *u8 = sys_mmap(16)
112 pass[0]=0x4F; pass[1]=0x4B; pass[2]=0x0A // "OK\n"
113 sys_write(1, pass, 3)
114 return 0
115}