code wiki / _hdl_build / nx_rv64im_alu_proof.nx
nx_rv64im_alu_proof.nx source
↩ module page · 124 lines · 4122 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"
15const K_MAGIC_9223372036854775807: i64 = 9223372036854775807
16const K_MAGIC_4294967296: i64 = 4294967296
17const K_MAGIC_4294967295: i64 = 4294967295
18const K_MAGIC_2147483648: i64 = 2147483648
19const K_MAGIC_2147483647: i64 = 2147483647
20const K_MAGIC_8388608: i64 = 8388608
21const K_MAGIC_88172645463325252: i64 = 88172645463325252
22const K_MAGIC_6364136223846793005: i64 = 6364136223846793005
23const K_MAGIC_1442695040888963407: i64 = 1442695040888963407
24
25func _hex16(v: i64, out: *u8, pos: i64) -> i64 {
26 var k: i64 = 15
27 var p: i64 = pos
28 while k >= 0 {
29 let nib: i64 = (v >> (k * 4)) & 15
30 if nib < 10 { out[p] = (0x30 + nib) as u8 }
31 if nib >= 10 { out[p] = (0x61 + nib - 10) as u8 }
32 p = p + 1
33 k = k - 1
34 }
35 return p
36}
37
38func _dec2(v: i64, out: *u8, pos: i64) -> i64 {
39 var p: i64 = pos
40 if v >= 10 { out[p] = (0x30 + (v / 10)) as u8; p = p + 1 }
41 out[p] = (0x30 + (v % 10)) as u8
42 p = p + 1
43 return p
44}
45
46func _emit_vec(op: i64, a: i64, b: i64, out: *u8, pos: i64) -> i64 {
47 let r: i64 = nx_rv64im_alu_compute(op, a, b)
48 var p: i64 = pos
49 p = _dec2(op, out, p)
50 out[p] = 0x09 as u8; p = p + 1
51 p = _hex16(a, out, p)
52 out[p] = 0x09 as u8; p = p + 1
53 p = _hex16(b, out, p)
54 out[p] = 0x09 as u8; p = p + 1
55 p = _hex16(r, out, p)
56 out[p] = 0x0A as u8; p = p + 1
57 return p
58}
59
60func main() -> i64 {
61 // Edge-value table (built arithmetically; NishiLang large hex
62 // literals are avoided per the substrate idiom).
63 let E: *i64 = sys_mmap(8 * 16) as *i64
64 E[0]=0; E[1]=1; E[2]=2; E[3]=3; E[4]=7
65 E[5]=0 - 1 // 0xFFFFFFFFFFFFFFFF
66 E[6]=0 - 9223372036854775808 // INT_MIN
67 E[7]=K_MAGIC_9223372036854775807 // INT_MAX
68 E[8]=K_MAGIC_4294967296 // 1<<32
69 E[9]=K_MAGIC_4294967295 // 0xFFFFFFFF
70 E[10]=K_MAGIC_2147483648 // 1<<31
71 E[11]=K_MAGIC_2147483647 // 0x7FFFFFFF
72 E[12]=0 - K_MAGIC_2147483648 // -(1<<31)
73 E[13]=255
74 E[14]=256
75 E[15]=0 - 256
76 let ne: i64 = 16
77
78 let out: *u8 = sys_mmap(K_MAGIC_8388608) as *u8 // 8 MiB
79 var pos: i64 = 0
80
81 // LCG state (MMIX constants); deterministic.
82 var lcg: i64 = K_MAGIC_88172645463325252
83
84 var op: i64 = 1
85 while op < NX_RV64IM_ALU_N {
86 // trace current op to stderr so a native-divide trap is locatable
87 let tb: *u8 = sys_mmap(8)
88 var tp: i64 = _dec2(op, tb, 0)
89 tb[tp] = 0x0A as u8
90 sys_write(2, tb, tp + 1)
91 // All edge x edge crosses.
92 var i: i64 = 0
93 while i < ne {
94 var j: i64 = 0
95 while j < ne {
96 pos = _emit_vec(op, E[i], E[j], out, pos)
97 j = j + 1
98 }
99 i = i + 1
100 }
101 // LCG random pairs.
102 var k: i64 = 0
103 while k < 256 {
104 lcg = lcg * K_MAGIC_6364136223846793005 + K_MAGIC_1442695040888963407
105 let a: i64 = lcg
106 lcg = lcg * K_MAGIC_6364136223846793005 + K_MAGIC_1442695040888963407
107 let b: i64 = lcg
108 pos = _emit_vec(op, a, b, out, pos)
109 k = k + 1
110 }
111 op = op + 1
112 }
113
114 let path: *u8 = "/mnt/c/Users/elder/nishi-browser-proofs/alu_vectors.tsv\x00"
115 let ofd: i64 = sys_openat_wr(path, 0x1A4)
116 if ofd <= 0 { return 70 }
117 sys_write(ofd, out, pos)
118 sys_close(ofd)
119
120 let pass: *u8 = sys_mmap(16)
121 pass[0]=0x4F; pass[1]=0x4B; pass[2]=0x0A // "OK\n"
122 sys_write(1, pass, 3)
123 return 0
124}