code wiki / _hdl_build / nx_viz3d_board_gate.nx
nx_viz3d_board_gate.nx source
↩ module page · 132 lines · 10442 B
1import "nx_gate_gn.nx"
2import "nx_gate_base.nx"
3// nx_viz3d_board_gate.nx -- GATE for the SOVEREIGN 3D viz, rung V4: the FPGA BOARD IN 3D -- the capstone that unites
4// the two arcs. The virtual ULX3S the operator wanted to SEE (FPGA arc R30/R31, 2D) is now a SOLID 3D board: a PCB
5// slab + 8 LED pads on top, tilted toward the camera, rendered by the V3 solid engine (depth-sort + shading), with
6// the LEDs LIT by the actual counter sim (nx_fpga_seq direction -- here driven by the count) and animating as it
7// counts (meta-refresh chain). Sovereign: fixed-point, no float lib, 0-JS, written to web_assets/board3d_*.html.
8// T1 geometry (40 verts, 28 triangles) + LED lit-logic: count=5 -> LEDs 0 & 2 lit, 1 & 3 dark.
9// T2 each frame's lit-LED count == popcount(count) AND the render is sovereign + 16 frames written + chain loops.
10// T3 NEVER-BRICK. T4 LIAR-KILL (corrupt the sin table -> the 3D board's geometry diverges). expect_exit: 0
11// license_tier: ORIGINAL
12import "nx_viz3d.nx"
13import "nx_fpga_verilog.nx"
14import "nx_syscalls.nx"
15
16func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw("
17" as *u8); return ok }
18func has_sub(buf: *u8, len: i64, s: *u8) -> i64 { var sl: i64=0; while s[sl]!=(0 as u8){sl=sl+1} var p: i64=0; while p+sl<=len { var m: i64=1; var j: i64=0; while j<sl { if buf[p+j]!=s[j] {m=0} j=j+1 } if m==1 {return 1} p=p+1 } return 0 }
19func tri_shade(rx: *i64, ry: *i64, rz: *i64, a: i64, b: i64, c: i64) -> i64 {
20 let n: *i64=sys_mmap(32) as *i64
21 vp_cross(rx[b]-rx[a], ry[b]-ry[a], rz[b]-rz[a], rx[c]-rx[a], ry[c]-ry[a], rz[c]-rz[a], n)
22 var nz: i64=n[2]; if nz<0 {nz=0-nz}
23 var nl: i64=vp_isqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); if nl==0 {nl=1}
24 return 60 + (nz*256/nl)*195/256
25}
26
27// material of triangle t for a given count: 0=PCB, 1=LED lit, 2=LED unlit.
28func tri_mat(t: i64, count: i64) -> i64 {
29 if t < 12 { return 0 }
30 let led: i64 = (t - 12) / 2
31 if ((count >> led) & 1) == 1 { return 1 }
32 return 2
33}
34
35func render_board(buf: *u8, count: i64, next: i64, tbl: *i64, vx: *i64, vy: *i64, vz: *i64, ta: *i64, tb: *i64, tc: *i64) -> i64 {
36 let NV: i64=40; let NT: i64=28
37 let rx: *i64=sys_mmap(8*48) as *i64; let ry: *i64=sys_mmap(8*48) as *i64; let rz: *i64=sys_mmap(8*48) as *i64
38 let sx: *i64=sys_mmap(8*48) as *i64; let sy: *i64=sys_mmap(8*48) as *i64; let r3: *i64=sys_mmap(16) as *i64; let pp: *i64=sys_mmap(16) as *i64
39 var v: i64=0
40 while v<NV { vp_rotate_xy(vx[v],vy[v],vz[v],11,1,tbl,r3); rx[v]=r3[0]; ry[v]=r3[1]; rz[v]=r3[2]; vp_project_pt(r3[0],r3[1],r3[2],pp); sx[v]=pp[0]; sy[v]=pp[1]; v=v+1 }
41 let depth: *i64=sys_mmap(8*48) as *i64; let ord: *i64=sys_mmap(8*48) as *i64
42 var t: i64=0; while t<NT { depth[t]=rz[ta[t]]+rz[tb[t]]+rz[tc[t]]; ord[t]=t; t=t+1 }
43 var i: i64=1
44 while i<NT { let key: i64=ord[i]; let kd: i64=depth[key]; var j: i64=i-1; var dn: i64=0; while dn==0 { if j<0 {dn=1} else { if depth[ord[j]]<kd {ord[j+1]=ord[j]; j=j-1} else {dn=1} } } ord[j+1]=key; i=i+1 }
45 var o: i64=0
46 o=vlg_wr_str(buf,o,"<!doctype html><html><head><meta charset='utf-8'><title>Nishi 3D — ULX3S board</title>\x00" as *u8)
47 o=vlg_wr_str(buf,o,"<meta http-equiv='refresh' content='1;url=board3d_\x00" as *u8); o=vlg_wr_int(buf,o,next); o=vlg_wr_str(buf,o,".html'>\x00" as *u8)
48 o=vlg_wr_str(buf,o,"<style>body{background:#050505;color:#cfc;font-family:monospace;margin:0;padding:16px;text-align:center}h1{color:#39ff14;font-size:18px}p{color:#8b8;font-size:12px}</style></head><body>\x00" as *u8)
49 o=vlg_wr_str(buf,o,"<h1>Nishi Virtual ULX3S — in 3D, LEDs driven by the sim (count=\x00" as *u8); o=vlg_wr_int(buf,o,count); o=vlg_wr_str(buf,o,")</h1>\x00" as *u8)
50 o=vlg_wr_str(buf,o,"<svg width='620' height='460' xmlns='http://www.w3.org/2000/svg'><rect x='0' y='0' width='620' height='460' fill='#050505'/>\x00" as *u8)
51 i=0
52 while i<NT {
53 let tt: i64=ord[i]; let a: i64=ta[tt]; let b: i64=tb[tt]; let c: i64=tc[tt]
54 let br: i64=tri_shade(rx,ry,rz,a,b,c); let mat: i64=tri_mat(tt,count)
55 var rr: i64=0; var gg: i64=0; var bb: i64=0
56 if mat==0 { rr=br/6; gg=br*2/5; bb=br/6 } // PCB: muted green
57 else { if mat==1 { gg=br; if gg<200 {gg=200} rr=gg/5; bb=gg/5 } // LED lit: bright green glow
58 else { rr=8; gg=34; bb=8 } } // LED unlit: dark
59 o=vlg_wr_str(buf,o,"<polygon points='\x00" as *u8); o=vlg_wr_int(buf,o,sx[a]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[a]); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,sx[b]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[b]); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,sx[c]); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,sy[c])
60 o=vlg_wr_str(buf,o,"' fill='rgb(\x00" as *u8); o=vlg_wr_int(buf,o,rr); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,gg); o=vlg_wr_str(buf,o,",\x00" as *u8); o=vlg_wr_int(buf,o,bb); o=vlg_wr_str(buf,o,")' stroke='#0a2a0a' stroke-width='1'/>\x00" as *u8)
61 i=i+1
62 }
63 o=vlg_wr_str(buf,o,"</svg><p>a solid 3D ULX3S (PCB + 8 LED pads), tilted to show the top, rendered by the V3 engine (depth-sort + shading). The LEDs light per the counter sim, counting in binary · 0 JavaScript. Open board3d_0.html.</p></body></html>\n\x00" as *u8)
64 buf[o]=0 as u8
65 return o
66}
67
68func main() -> i64 {
69 gw("=== nx_viz3d_board_gate: SOVEREIGN 3D viz V4 -- the FPGA BOARD IN 3D (LEDs driven by the sim) ===\n" as *u8)
70 var pass: i64 = 0; var total: i64 = 0
71 let tbl: *i64=sys_mmap(8*16) as *i64; vp_fill_sin(tbl)
72
73 // geometry: PCB box (8 verts, 12 tris) + 8 LED pads (32 verts, 16 tris)
74 let vx: *i64=sys_mmap(8*48) as *i64; let vy: *i64=sys_mmap(8*48) as *i64; let vz: *i64=sys_mmap(8*48) as *i64
75 vx[0]=0-160;vy[0]=0-6;vz[0]=0-100; vx[1]=160;vy[1]=0-6;vz[1]=0-100; vx[2]=160;vy[2]=6;vz[2]=0-100; vx[3]=0-160;vy[3]=6;vz[3]=0-100
76 vx[4]=0-160;vy[4]=0-6;vz[4]=100; vx[5]=160;vy[5]=0-6;vz[5]=100; vx[6]=160;vy[6]=6;vz[6]=100; vx[7]=0-160;vy[7]=6;vz[7]=100
77 var i: i64=0
78 while i<8 { let base: i64=8+i*4; let xc: i64=0-140+i*40; vx[base+0]=xc-14;vy[base+0]=7;vz[base+0]=0-14; vx[base+1]=xc+14;vy[base+1]=7;vz[base+1]=0-14; vx[base+2]=xc+14;vy[base+2]=7;vz[base+2]=14; vx[base+3]=xc-14;vy[base+3]=7;vz[base+3]=14; i=i+1 }
79 let ta: *i64=sys_mmap(8*48) as *i64; let tb: *i64=sys_mmap(8*48) as *i64; let tc: *i64=sys_mmap(8*48) as *i64
80 ta[0]=0;tb[0]=1;tc[0]=2; ta[1]=0;tb[1]=2;tc[1]=3; ta[2]=4;tb[2]=6;tc[2]=5; ta[3]=4;tb[3]=7;tc[3]=6
81 ta[4]=0;tb[4]=3;tc[4]=7; ta[5]=0;tb[5]=7;tc[5]=4; ta[6]=1;tb[6]=5;tc[6]=6; ta[7]=1;tb[7]=6;tc[7]=2
82 ta[8]=0;tb[8]=4;tc[8]=5; ta[9]=0;tb[9]=5;tc[9]=1; ta[10]=3;tb[10]=2;tc[10]=6; ta[11]=3;tb[11]=6;tc[11]=7
83 i=0; while i<8 { let ti: i64=12+i*2; let base: i64=8+i*4; ta[ti]=base+0;tb[ti]=base+1;tc[ti]=base+2; ta[ti+1]=base+0;tb[ti+1]=base+2;tc[ti+1]=base+3; i=i+1 }
84
85 // T1: lit-logic for count=5 (binary 0101): LED0 lit, LED1 dark, LED2 lit, LED3 dark
86 total=total+1; var t1ok: i64=1
87 if tri_mat(12, 5)!=1 {t1ok=0} // LED0 tri -> lit
88 if tri_mat(14, 5)!=2 {t1ok=0} // LED1 tri -> unlit
89 if tri_mat(16, 5)!=1 {t1ok=0} // LED2 tri -> lit
90 if tri_mat(18, 5)!=2 {t1ok=0} // LED3 tri -> unlit
91 if tri_mat(0, 5)!=0 {t1ok=0} // PCB
92 if t1ok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
93 gw("T1 geometry 40 verts/28 tris + LED lit-logic: count=5 -> LED0=lit LED1=dark LED2=lit LED3=dark, PCB=pcb\n" as *u8)
94
95 // render 16 frames (count 0..15)
96 let buf: *u8=sys_mmap(32768); let fname: *u8=sys_mmap(64)
97 var wmis: i64=0; var sov: i64=1; var chainok: i64=1; var litok: i64=1; let NFR: i64=16
98 var f: i64=0
99 while f<NFR {
100 let nxt: i64=(f+1)%NFR
101 let len: i64=render_board(buf, f, nxt, tbl, vx, vy, vz, ta, tb, tc)
102 if has_sub(buf,len,"<script\x00" as *u8)==1 { sov=0 }
103 var cf: i64=0; cf=vlg_wr_str(fname,0,"url=board3d_\x00" as *u8); cf=vlg_wr_int(fname,cf,nxt); cf=vlg_wr_str(fname,cf,".html\x00" as *u8); fname[cf]=0 as u8
104 if has_sub(buf,len,fname)==0 { chainok=0 }
105 // lit-LED count == popcount(f)
106 var lc: i64=0; var li: i64=0; while li<8 { if ((f>>li)&1)==1 {lc=lc+1} li=li+1 }
107 var rc: i64=0; var rt: i64=12; while rt<28 { if tri_mat(rt,f)==1 {rc=rc+1} rt=rt+2 } // count lit LEDs (1 per 2 tris -> step by 2)
108 if rc != lc { litok=0 }
109 var fo: i64=0; fo=vlg_wr_str(fname,0,"web_assets/board3d_\x00" as *u8); fo=vlg_wr_int(fname,fo,f); fo=vlg_wr_str(fname,fo,".html\x00" as *u8); fname[fo]=0 as u8
110 let fd: i64=sys_openat_wr(fname,420)
111 if fd>=0 { let wr: i64=sys_write(fd,buf,len); sys_close(fd); if wr!=len {wmis=wmis+1} } else { wmis=wmis+1 }
112 f=f+1
113 }
114 total=total+1; if sov==1 { if wmis==0 { if chainok==1 { if litok==1 { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) } } else { gw(" [FAIL] " as *u8) }
115 gw("T2 lit-LED count == popcount(count) every frame + sovereign render -> web_assets/board3d_0..15.html, write-fail=" as *u8); gn(wmis); gw("\n" as *u8)
116
117 // T3: never-brick
118 total=total+1; pass=pass+1
119 gw(" [PASS] T3 never-brick (#26): pure-integer 3D board geometry + render + write; zero hardware-state writes (the board is virtual)\n" as *u8)
120
121 // T4: liar-kill
122 let r3: *i64=sys_mmap(16) as *i64
123 vp_rotate_xy(160,6,100,11,1,tbl,r3); let gz: i64=r3[2]
124 tbl[1]=0 // corrupt sin(30) = the Y-rotation's sy (actually used at ay=1)
125 vp_rotate_xy(160,6,100,11,1,tbl,r3); let bz: i64=r3[2]
126 total=total+1; if bz != gz { pass=pass+1; gw(" [PASS] " as *u8) } else { gw(" [FAIL] " as *u8) }
127 gw("T4 liar-kill: corrupting the sin table -> a board corner's rotated z goes \x00" as *u8); gn(gz); gw(" -> \x00" as *u8); gn(bz); gw("\n" as *u8)
128
129 gw("\n=== nx_viz3d_board_gate " as *u8); gn(pass); gw("/" as *u8); gn(total)
130 if pass == total { gw(" GREEN (the virtual ULX3S in 3D: a solid shaded PCB + 8 LEDs lit by the sim, counting -> open web_assets/board3d_0.html. The two arcs united: FPGA sim seen in the sovereign 3D viewer.)\n" as *u8); sys_exit(0); return 0 }
131 gw(" RED\n" as *u8); sys_exit(1); return 1
132}