code wiki / _hdl_build / nx_fpga_verilog.nx
nx_fpga_verilog.nx source
↩ module page · 115 lines · 6618 B
1// nx_fpga_verilog.nx -- LIB: RUNG 28 -- the SYNTH BRIDGE emitter, SEQUENTIAL-capable. Serializes any fabric
2// (combinational LUT4 cells AND clocked DFF cells, the `kind` bitstream from nx_fpga_seq) to a Yosys-synthesizable
3// Verilog gate-netlist: LUT cells -> combinational `assign comb[k] = (INIT >> inputs) & 1`; DFF cells -> a `reg ff[k]`
4// latched in `always @(posedge clk)`. Each cell carries a machine-readable `//@C k kind init s0 s1 s2 s3` tag so the
5// netlist round-trips (fab_parse_seq reconstructs kind/init/src/po byte-identically). This is the layer
6// nishi_hdl_primitives calls "future" and rv64im_min leaves undone -- the path from the sim fabric toward an ECP5
7// bitstream. NEVER-BRICK (#26): pure text emit/parse, bounded, deterministic, zero hardware-state writes.
8// license_tier: ORIGINAL
9import "nx_syscalls.nx"
10
11func vlg_isdig(c: i64) -> i64 { if c < 48 { return 0 } if c > 57 { return 0 } return 1 }
12func vlg_wr_str(buf: *u8, off: i64, s: *u8) -> i64 { var o: i64=off; var i: i64=0; while s[i]!=(0 as u8){ buf[o]=s[i]; o=o+1; i=i+1 } return o }
13func vlg_wr_int(buf: *u8, off: i64, v: i64) -> i64 {
14 var o: i64=off; var m: i64=v
15 if m < 0 { buf[o]=45 as u8; o=o+1; m=0-m }
16 if m == 0 { buf[o]=48 as u8; return o+1 }
17 let t: *u8=sys_mmap(28); var k: i64=0
18 while m > 0 { t[k]=(48+(m%10)) as u8; m=m/10; k=k+1 }
19 var j: i64=0; while j < k { buf[o]=t[k-1-j]; o=o+1; j=j+1 }
20 return o
21}
22// emit a cell/PI reference: pi[x] (PI) | ff[x] (DFF cell) | comb[x] (LUT cell)
23func vlg_wr_op(buf: *u8, off: i64, s: i64, npi: i64, kind: *i64) -> i64 {
24 var o: i64=off
25 if s < npi { o=vlg_wr_str(buf,o,"pi[\x00" as *u8); o=vlg_wr_int(buf,o,s); o=vlg_wr_str(buf,o,"]\x00" as *u8); return o }
26 let c: i64 = s - npi
27 if kind[c]==1 { o=vlg_wr_str(buf,o,"ff[\x00" as *u8) } else { o=vlg_wr_str(buf,o,"comb[\x00" as *u8) }
28 o=vlg_wr_int(buf,o,c); o=vlg_wr_str(buf,o,"]\x00" as *u8); return o
29}
30
31// EMIT the (possibly sequential) fabric as Verilog (+ //@ netlist tags). Returns length.
32func fab_emit_verilog_seq(buf: *u8, ncells: i64, npi: i64, npo: i64, kind: *i64, init: *i64, src: *i64, po: *i64) -> i64 {
33 var o: i64=0
34 o=vlg_wr_str(buf,o,"// LUT4+DFF gate-netlist emitted from the sovereign FPGA fabric (Yosys-synthesizable)\n\x00" as *u8)
35 o=vlg_wr_str(buf,o,"//@H \x00" as *u8); o=vlg_wr_int(buf,o,ncells); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,npi); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,npo); o=vlg_wr_str(buf,o,"\n\x00" as *u8)
36 o=vlg_wr_str(buf,o,"module fab(input clk, input [\x00" as *u8); o=vlg_wr_int(buf,o,npi-1); o=vlg_wr_str(buf,o,":0] pi, output [\x00" as *u8); o=vlg_wr_int(buf,o,npo-1); o=vlg_wr_str(buf,o,":0] po);\n\x00" as *u8)
37 o=vlg_wr_str(buf,o," wire [\x00" as *u8); o=vlg_wr_int(buf,o,ncells-1); o=vlg_wr_str(buf,o,":0] comb;\n reg [\x00" as *u8); o=vlg_wr_int(buf,o,ncells-1); o=vlg_wr_str(buf,o,":0] ff;\n\x00" as *u8)
38 // combinational LUT cells
39 var k: i64=0
40 while k < ncells {
41 if kind[k]==0 {
42 o=vlg_wr_str(buf,o," assign comb[\x00" as *u8); o=vlg_wr_int(buf,o,k); o=vlg_wr_str(buf,o,"] = (\x00" as *u8); o=vlg_wr_int(buf,o,init[k]); o=vlg_wr_str(buf,o," >> (\x00" as *u8)
43 var j: i64=0
44 while j < 4 {
45 if j > 0 { o=vlg_wr_str(buf,o,"|\x00" as *u8) }
46 o=vlg_wr_str(buf,o,"(\x00" as *u8); o=vlg_wr_op(buf,o,src[k*4+j],npi,kind); o=vlg_wr_str(buf,o,"<<\x00" as *u8); o=vlg_wr_int(buf,o,j); o=vlg_wr_str(buf,o,")\x00" as *u8)
47 j=j+1
48 }
49 o=vlg_wr_str(buf,o,")) & 1'b1; //@C \x00" as *u8); o=vlg_wr_int(buf,o,k); o=vlg_wr_str(buf,o," 0 \x00" as *u8); o=vlg_wr_int(buf,o,init[k])
50 j=0; while j < 4 { o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,src[k*4+j]); j=j+1 }
51 o=vlg_wr_str(buf,o,"\n\x00" as *u8)
52 }
53 k=k+1
54 }
55 // sequential DFF cells
56 o=vlg_wr_str(buf,o," always @(posedge clk) begin\n\x00" as *u8)
57 k=0
58 while k < ncells {
59 if kind[k]==1 {
60 o=vlg_wr_str(buf,o," ff[\x00" as *u8); o=vlg_wr_int(buf,o,k); o=vlg_wr_str(buf,o,"] <= \x00" as *u8); o=vlg_wr_op(buf,o,src[k*4+0],npi,kind)
61 o=vlg_wr_str(buf,o,"; //@C \x00" as *u8); o=vlg_wr_int(buf,o,k); o=vlg_wr_str(buf,o," 1 0 \x00" as *u8); o=vlg_wr_int(buf,o,src[k*4+0]); o=vlg_wr_str(buf,o," 0 0 0\n\x00" as *u8)
62 }
63 k=k+1
64 }
65 o=vlg_wr_str(buf,o," end\n\x00" as *u8)
66 // outputs
67 var p: i64=0
68 while p < npo {
69 o=vlg_wr_str(buf,o," assign po[\x00" as *u8); o=vlg_wr_int(buf,o,p); o=vlg_wr_str(buf,o,"] = \x00" as *u8); o=vlg_wr_op(buf,o,po[p],npi,kind); o=vlg_wr_str(buf,o,"; //@P \x00" as *u8); o=vlg_wr_int(buf,o,p); o=vlg_wr_str(buf,o," \x00" as *u8); o=vlg_wr_int(buf,o,po[p]); o=vlg_wr_str(buf,o,"\n\x00" as *u8)
70 p=p+1
71 }
72 o=vlg_wr_str(buf,o,"endmodule\n\x00" as *u8)
73 return o
74}
75
76func vlg_rd_int(buf: *u8, pp: *i64) -> i64 {
77 var p: i64=pp[0]
78 while buf[p]==(32 as u8) { p=p+1 }
79 var v: i64=0; var neg: i64=0
80 if buf[p]==(45 as u8) { neg=1; p=p+1 }
81 while vlg_isdig(buf[p] as i64)==1 { v=v*10 + ((buf[p] as i64)-48); p=p+1 }
82 if neg==1 { v=0-v }
83 pp[0]=p; return v
84}
85func vlg_find(buf: *u8, len: i64, from: i64, marker: *u8, mlen: i64) -> i64 {
86 var p: i64=from
87 while p + mlen <= len {
88 var m: i64=1; var j: i64=0
89 while j < mlen { if buf[p+j]!=marker[j] { m=0 } j=j+1 }
90 if m==1 { return p+mlen }
91 p=p+1
92 }
93 return 0-1
94}
95// parse the //@ tags -> reconstruct kind/init/src/po; returns ncells (npi via pnpi, npo via pnpo)
96func fab_parse_seq(buf: *u8, len: i64, rkind: *i64, rinit: *i64, rsrc: *i64, rpo: *i64, pnpi: *i64, pnpo: *i64) -> i64 {
97 let pp: *i64=sys_mmap(16) as *i64
98 let h: i64=vlg_find(buf,len,0,"//@H \x00" as *u8,5)
99 pp[0]=h; let ncells: i64=vlg_rd_int(buf,pp); pnpi[0]=vlg_rd_int(buf,pp); pnpo[0]=vlg_rd_int(buf,pp)
100 var pos: i64=0
101 while pos >= 0 {
102 let c: i64=vlg_find(buf,len,pos,"//@C \x00" as *u8,5)
103 if c < 0 { pos = 0-1 } else {
104 pp[0]=c; let k: i64=vlg_rd_int(buf,pp); rkind[k]=vlg_rd_int(buf,pp); rinit[k]=vlg_rd_int(buf,pp)
105 rsrc[k*4+0]=vlg_rd_int(buf,pp); rsrc[k*4+1]=vlg_rd_int(buf,pp); rsrc[k*4+2]=vlg_rd_int(buf,pp); rsrc[k*4+3]=vlg_rd_int(buf,pp)
106 pos = pp[0]
107 }
108 }
109 pos=0
110 while pos >= 0 {
111 let c: i64=vlg_find(buf,len,pos,"//@P \x00" as *u8,5)
112 if c < 0 { pos = 0-1 } else { pp[0]=c; let j: i64=vlg_rd_int(buf,pp); rpo[j]=vlg_rd_int(buf,pp); pos=pp[0] }
113 }
114 return ncells
115}