1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
open Netlist_gen
open Alu
let zeroes n =
const (String.make n '0')
let one n =
const "1" ++ zeroes (n-1)
let two n =
const "01" ++ zeroes (n-2)
let cpu_ram ra we wa d =
(* Ram chip has word size = 8 bits and address size = 16 bits
0x0000 to 0x3FFF is ROM0
0x4000 to 0x7FFF is unused, reserved for MMIO
0x8000 to 0xFFFF is RAM *)
let ra_hi1 = ra ** 15 in
let ra_lo1 = ra % (0, 14) in
let ra_hi2 = ra ** 14 in
let ra_lo2 = ra % (0, 13) in
let read_rom = (not ra_hi1) ^& (not ra_hi2) in
let read_ram = ra_hi1 in
let wa_hi1 = wa ** 15 in
let wa_lo1 = wa % (0, 14) in
let we_ram = we ^& wa_hi1 in
let rd_rom = rom "ROM0" 14 8 ra_lo2 in
let rd_ram = ram 15 8 ra_lo1 we_ram wa_lo1 d in
mux read_ram (mux read_rom (zeroes 8) rd_rom) rd_ram
let r0 = zeroes 16
let r1, save_r1 = loop 16
let r2, save_r2 = loop 16
let r3, save_r3 = loop 16
let r4, save_r4 = loop 16
let r5, save_r5 = loop 16
let r6, save_r6 = loop 16
let r7, save_r7 = loop 16
let cpu_get_reg i =
let a00 = mux (i ** 0) r0 r1 in
let a01 = mux (i ** 0) r2 r3 in
let a02 = mux (i ** 0) r4 r5 in
let a03 = mux (i ** 0) r6 r7 in
let a10 = mux (i ** 1) a00 a01 in
let a11 = mux (i ** 1) a02 a03 in
mux (i ** 2) a10 a00
let save_cpu_regs wr wd =
let next_r1 = mux (eq_c 3 wr 1) r1 wd in
let next_r2 = mux (eq_c 3 wr 2) r2 wd in
let next_r3 = mux (eq_c 3 wr 3) r3 wd in
let next_r4 = mux (eq_c 3 wr 4) r4 wd in
let next_r5 = mux (eq_c 3 wr 5) r5 wd in
let next_r6 = mux (eq_c 3 wr 6) r6 wd in
let next_r7 = mux (eq_c 3 wr 7) r7 wd in
save_r1 (reg 16 next_r1) ^.
save_r2 (reg 16 next_r2) ^.
save_r3 (reg 16 next_r3) ^.
save_r4 (reg 16 next_r4) ^.
save_r5 (reg 16 next_r5) ^.
save_r6 (reg 16 next_r6) ^.
save_r7 (reg 16 next_r7) ^.
r0
(*
let ticker n =
let k, save_k = loop n in
let s = reg n k in
let next = nadder_nocarry n s (one n) in
ignore (save_k next) s
let tick1 = ticker 1
let tick2 = ticker 2
*)
let rl, rh, i, ex, exf, pc =
let next_read, save_next_read = loop 1 in
let read = not (reg 1 (not next_read)) in
let next_pc, save_next_pc = loop 16 in
let pc = reg 16 next_pc in
let ra, we, wa, d = zeroes 16, zeroes 1, zeroes 16, zeroes 8 in
let ram_read, save_ram_read = loop 8 in
(* Read instruction low when read is set and instruction high on next tick *)
let next_read_ihi, save_next_read_ihi = loop 1 in
let read_ihi = reg 1 next_read_ihi in
let read_ilow = read in
let ra = mux read_ilow ra pc in
let ilow = reg 8 (mux read_ilow (zeroes 8) ram_read) in
let ra = mux read_ihi ra (nadder_nocarry 16 pc (one 16)) in
let ihi = mux read_ihi (zeroes 8) ram_read in
let read_ilow = save_next_read_ihi read_ilow in
(* When execution has just been read, exec is true, and exec is false the rest of the time *)
let exec = read_ihi in
(* Keep same instruction in register until new instruction is read *)
let si, save_i = loop 16 in
let i = mux exec (reg 16 si) (ilow ++ ihi) in
let i = save_i i in
(* Execute instruction if exec is set *)
let next_pc = nadder_nocarry 16 pc (two 16) in
let exec_finished = exec in
let i_i = i % (11, 15) in
let i_r = i % (8, 10) in
let i_ra = i % (5, 7) in
let i_rb = i % (2, 4) in
let i_f = i % (0, 1) in
let i_id = i % (0, 7) in
let i_jd = i % (0, 10) in
let i_kd = i % (0, 4) in
(* registers *)
let v_r = cpu_get_reg i_r in
let v_ra = cpu_get_reg i_ra in
let v_rb = cpu_get_reg i_rb in
let wr = zeroes 3 in
let rwd = zeroes 16 in
(* instruction : incri *)
let instr_incri = exec ^& eq_c 5 i_i 0b00110 in
let wr = mux instr_incri wr i_r in
let rwd = mux instr_incri rwd (nadder_nocarry 16 v_r (sign_extend 8 16 i_id)) in
(* instruction : j *)
let instr_j = exec ^& eq_c 5 i_i 0b01000 in
let next_pc = mux instr_j next_pc (nadder_nocarry 16 pc (sign_extend 11 16 i_jd)) in
(* instruction : jal *)
let instr_jal = exec ^& eq_c 5 i_i 0b01001 in
let next_pc = mux instr_jal next_pc (nadder_nocarry 16 pc (sign_extend 11 16 i_jd)) in
let instr_jalxx = instr_jal in
(* instruction : jr/jalr/jer/jner/jltr/jler/jltru/ljeru *)
let instr_jxxr = exec ^& eq_c 4 (i_i % (1, 4)) 0b0101 in
let f0 = i_i ** 0 in
let instr_jr = (not f0) ^& (eq_c 2 i_f 0) in
let instr_jalr = (not f0) ^& (eq_c 2 i_f 1) in
let instr_jalxx = instr_jalxx ^| (instr_jxxr ^& instr_jalr) in
let cond_jxxr = instr_jxxr ^& (alu_comparer 16 f0 i_f v_ra v_rb ^| instr_jr ^| instr_jalr) in
let next_pc = mux cond_jxxr next_pc v_r in
(* prologue for jal/jalr *)
let wr = mux instr_jalxx wr (const "011") in
let rwd = mux instr_jalxx rwd next_pc in
save_cpu_regs wr rwd ^.
save_ram_read (cpu_ram ra we wa d) ^.
save_next_read exec_finished ^.
save_next_pc (mux exec_finished pc next_pc) ^.
read_ilow, read_ihi, i, exec, exec_finished, pc
let p =
program
[]
[
"read_ilow", 1, rl;
"read_ihi", 1, rh;
"instruction", 16, i;
"exec_instr", 1, ex;
"exec_finished", 1, exf;
"pc", 16, pc;
"r0", 16, r0;
"r1", 16, r1;
"r2", 16, r2;
"r3", 16, r3;
"r4", 16, r4;
"r5", 16, r5;
"r6", 16, r6;
"r7", 16, r7;
]
let () = Netlist_gen.print stdout p
|