code wiki / _hdl_build / nx_fpga_decode.nx
nx_fpga_decode.nx source
↩ module page · 65 lines · 3553 B
1// nx_fpga_decode.nx -- LIB: RUNG 9 -- the RV64I R-type DECODER on the LUT4 fabric: maps (funct3, funct7 bit 5)
2// to the datapath CONTROL signals + a result-class selector, each as a LUT4 (a 4-input function of f3_0/f3_1/
3// f3_2/f7b5). This is the CONTROL UNIT the prior rungs left to the gate; composing it (decode on fabric) with
4// the ALU/shift/compare datapaths (execute on fabric) is a full R-type instruction running on the simulated FPGA.
5//
6// Decode table (RV64I R-type, opcode 0x33):
7// f3=0: ADD (f7b5=0) / SUB (f7b5=1) f3=1: SLL f3=2: SLT f3=3: SLTU
8// f3=4: XOR f3=5: SRL (f7b5=0) / SRA (f7b5=1) f3=6: OR f3=7: AND
9// Control outputs (each a LUT4 cell over PIs f3_0,f3_1,f3_2,f7b5):
10// [0]sub [1]msel0 [2]msel1 (ALU datapath) [3]right [4]arith (shift) [5]unsigned (cmp)
11// [6]class0 [7]class1 (result class: 0=ALU, 1=shift, 2=compare)
12// NEVER-BRICK (#26): pure integer, 8 bounded LUT evals, total, deterministic, zero hardware writes.
13// license_tier: ORIGINAL
14import "nx_fpga_lut.nx"
15import "nx_fpga_fabric.nx"
16import "nx_syscalls.nx"
17
18// --- reference decode (the golden control table; also used to BUILD the LUT inits) ---
19func r9_sub(f3: i64, f7b5: i64) -> i64 { if f3==0 { if f7b5==1 { return 1 } } return 0 }
20func r9_msel0(f3: i64) -> i64 { if f3==0 { return 1 } if f3==6 { return 1 } return 0 }
21func r9_msel1(f3: i64) -> i64 { if f3==0 { return 1 } if f3==4 { return 1 } return 0 }
22func r9_right(f3: i64) -> i64 { if f3==5 { return 1 } return 0 }
23func r9_arith(f3: i64, f7b5: i64) -> i64 { if f3==5 { if f7b5==1 { return 1 } } return 0 }
24func r9_uns(f3: i64) -> i64 { if f3==3 { return 1 } return 0 }
25func r9_class(f3: i64) -> i64 { if f3==1 { return 1 } if f3==5 { return 1 } if f3==2 { return 2 } if f3==3 { return 2 } return 0 }
26
27// EMIT the decoder fabric. npi=4 (PI 0,1,2=funct3 bits, 3=funct7 bit5). ncells=8. po_src[0..7]=control bits above.
28func fab_build_decode(inits: *i64, src: *i64, po_src: *i64) -> i64 {
29 let npi: i64 = 4
30 var i_sub: i64=0; var i_m0: i64=0; var i_m1: i64=0; var i_r: i64=0; var i_a: i64=0; var i_u: i64=0; var i_c0: i64=0; var i_c1: i64=0
31 var idx: i64 = 0
32 while idx < 16 {
33 let f3: i64 = idx & 7
34 let f7: i64 = (idx >> 3) & 1
35 if r9_sub(f3,f7)==1 { i_sub = i_sub | (1<<idx) }
36 if r9_msel0(f3)==1 { i_m0 = i_m0 | (1<<idx) }
37 if r9_msel1(f3)==1 { i_m1 = i_m1 | (1<<idx) }
38 if r9_right(f3)==1 { i_r = i_r | (1<<idx) }
39 if r9_arith(f3,f7)==1 { i_a = i_a | (1<<idx) }
40 if r9_uns(f3)==1 { i_u = i_u | (1<<idx) }
41 let cls: i64 = r9_class(f3)
42 if (cls & 1)==1 { i_c0 = i_c0 | (1<<idx) }
43 if ((cls>>1)&1)==1 { i_c1 = i_c1 | (1<<idx) }
44 idx = idx + 1
45 }
46 let v: *i64 = sys_mmap(8 * 8) as *i64
47 v[0]=i_sub; v[1]=i_m0; v[2]=i_m1; v[3]=i_r; v[4]=i_a; v[5]=i_u; v[6]=i_c0; v[7]=i_c1
48 var c: i64 = 0
49 while c < 8 {
50 inits[c] = v[c]
51 src[c*4+0]=0; src[c*4+1]=1; src[c*4+2]=2; src[c*4+3]=3 // inputs = the 4 PIs
52 po_src[c] = npi + c
53 c = c + 1
54 }
55 return npi
56}
57
58// run the decoder; fill ctrl[0..7] = [sub,msel0,msel1,right,arith,unsigned,class0,class1].
59func fab_decode_run(inits: *i64, src: *i64, po_src: *i64, pi: *i64, co: *i64, f3: i64, f7b5: i64, ctrl: *i64) -> i64 {
60 pi[0] = f3 & 1; pi[1] = (f3>>1) & 1; pi[2] = (f3>>2) & 1; pi[3] = f7b5 & 1
61 fab_eval(8, 4, inits, src, pi, co)
62 var i: i64 = 0
63 while i < 8 { ctrl[i] = fab_po(po_src[i], 4, pi, co); i = i + 1 }
64 return 0
65}