code wiki / _hdl_build / nx_gsim_seq_test.nx
nx_gsim_seq_test.nx source
↩ module page · 57 lines · 2500 B
1// nx_gsim_seq_test.nx -- proves the SEQUENTIAL gate simulator (nx_gsim_tick): a
2// netlist with DFFs that holds + updates STATE across clocked ticks. This is the
3// keystone that makes a gate-level CPU RUNNABLE (registers, PC, accumulators).
4//
5// Two stateful elements share the clock:
6// Q1 (counter): D1 = Q1 + 1 -> Q1 counts ticks
7// Q2 (accumulator): D2 = Q2 + in -> Q2 sums the per-tick inputs
8// Drive in=[10,20,30] then 97 idle ticks (in=0). After 100 ticks: Q1=100, Q2=60.
9// Known answer: "100 60", exit 0.
10
11import "nx_nxgate_sim.nx"
12
13func _set(c: *NxGsimCell, id: i64, kind: i64, fo: i64, f0: i64, f1: i64, val: i64) -> i64 {
14 c[id].kind = kind; c[id].fanout = fo; c[id].f0 = f0; c[id].f1 = f1; c[id].f2 = 0 - 1; c[id].val = val
15 return 0
16}
17func _emit_dec(v: i64) -> i64 {
18 let b: *u8 = sys_mmap(28); var n: i64 = v; if n < 0 { n = 0 - n }
19 let t: *u8 = sys_mmap(28); var k: i64 = 0
20 if n == 0 { t[0] = 48; k = 1 }
21 while n > 0 { t[k] = 48 + (n % 10); n = n / 10; k = k + 1 }
22 var i: i64 = 0; while i < k { b[i] = t[k - 1 - i]; i = i + 1 }
23 b[k] = 32; sys_write(1, b, k + 1); return 0
24}
25func _nl() -> i64 { let z: *u8 = sys_mmap(2); z[0] = 10; sys_write(1, z, 1); return 0 }
26
27func main() -> i64 {
28 let vals: *i64 = sys_mmap(8 * 16) as *i64
29 let cells: *NxGsimCell = sys_mmap(48 * 16) as *NxGsimCell
30 let g: *NxGsim = sys_mmap(64) as *NxGsim
31 let dtmp: *i64 = sys_mmap(8 * 4) as *i64
32
33 // nets: 0=in 1=c1 2=Q1 3=D1 4=Q2 5=D2
34 _set(cells, 0, NX_GATE_KIND_CONST, 1, 0 - 1, 0 - 1, 1) // c1 = 1
35 _set(cells, 1, NX_GATE_KIND_ADD, 3, 2, 1, 0) // D1 = Q1 + 1
36 _set(cells, 2, NX_GATE_KIND_ADD, 5, 4, 0, 0) // D2 = Q2 + in
37 _set(cells, 3, NX_GATE_KIND_DFF, 2, 3, 0 - 1, 0) // Q1 <- D1
38 _set(cells, 4, NX_GATE_KIND_DFF, 4, 5, 0 - 1, 0) // Q2 <- D2
39 g.vals = vals; g.n_nets = 6; g.cells = cells; g.n_cells = 5
40
41 vals[2] = 0 // Q1 init
42 vals[4] = 0 // Q2 init
43
44 let inv: *i64 = sys_mmap(8 * 3) as *i64
45 inv[0] = 10; inv[1] = 20; inv[2] = 30
46 var t: i64 = 0
47 while t < 100 {
48 if t < 3 { vals[0] = inv[t] } else { vals[0] = 0 }
49 if nx_gsim_tick(g, dtmp) != NX_GSIM_OK { sys_exit(40); return 40 }
50 t = t + 1
51 }
52
53 _emit_dec(vals[2]); _emit_dec(vals[4]); _nl()
54 if vals[2] != 100 { sys_exit(1); return 1 } // Q1 counted 100 ticks
55 if vals[4] != 60 { sys_exit(2); return 2 } // Q2 summed 10+20+30
56 sys_exit(0); return 0
57}