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}