summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/alu.ml117
-rw-r--r--cpu/cpu.ml84
-rw-r--r--cpu/prog_rom0.rom7
3 files changed, 175 insertions, 33 deletions
diff --git a/cpu/alu.ml b/cpu/alu.ml
index 7356fbb..e0c1ef9 100644
--- a/cpu/alu.ml
+++ b/cpu/alu.ml
@@ -1,5 +1,13 @@
open Netlist_gen
+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 rec rep n k =
if n = 1 then k
else
@@ -27,25 +35,55 @@ let rec nonnull n a =
let rec sign_extend n_a n_dest a =
a ++ rep (n_dest - n_a) (a ** (n_a - 1))
+(* Arithmetic operations *)
+
let fulladder a b c =
let s = a ^^ b ^^ c in
let r = (a ^& b) ^| ((a ^^ b) ^& c) in
s, r
-let rec nadder n a b c_in =
+let rec nadder_with_carry n a b c_in =
if n = 1 then fulladder a b c_in
else
let s_n, c_n1 = fulladder (a ** 0) (b ** 0) c_in in
- let s_n1, c_out = nadder (n-1) (a % (1, n-1)) (b % (1, n-1)) c_n1 in
+ let s_n1, c_out = nadder_with_carry (n-1) (a % (1, n-1)) (b % (1, n-1)) c_n1 in
s_n ++ s_n1, c_out
-let rec npshift_signed n p a b =
- a (* TODO *)
-
-let nadder_nocarry n a b =
- let a, b = nadder n a b (const "0") in
+let nadder n a b =
+ let a, b = nadder_with_carry n a b (const "0") in
ignore b a
+let rec nsubber n a b =
+ zeroes n (* TODO *)
+
+let rec nmul n a b =
+ zeroes n, zeroes n (* TODO : retuns lo and hi part of 32-bit answer *)
+
+let rec ndiv n a b =
+ zeroes n, zeroes n (* TODO : returns quotient and remainder *)
+
+let rec nmulu n a b =
+ zeroes n, zeroes n (* TODO : same as nmul but unsigned *)
+
+let rec ndivu n a b =
+ zeroes n, zeroes n (* TODO : save as ndiv but unsigned *)
+
+(* Shifts *)
+
+let npshift_signed n p a b =
+ a (* TODO (here b is a signed integer on p bits) *)
+
+let op_lsl n a b =
+ a (* TODO (b is unsigned, same size n) *)
+
+let op_lsr n a b =
+ a (* TODO (b is unsigned, same size n) *)
+
+let op_asr n a b =
+ a (* TODO (b unsigned size n) *)
+
+(* Comparisons *)
+
let rec eq_n n a b =
all1 n (not (a ^^ b))
@@ -64,6 +102,8 @@ let rec le_n n a b =
let rec ule_n n a b =
const "0" (* TODO : less than or equal, unsigned *)
+(* Big pieces *)
+
let alu_comparer n f0 f a b =
(*
f0 f action
@@ -82,3 +122,66 @@ let alu_comparer n f0 f a b =
let lte_unsigned = mux (f ** 0) (ult_n n a b) (ule_n n a b) in
let lte = mux (f ** 1) lte_signed lte_unsigned in
mux f0 eq_ne lte
+
+let alu_arith f1 f a b =
+ (* See table for ALU below *)
+ let add = nadder 16 a b in
+ let sub = nsubber 16 a b in
+ let mul, mul2 = nmul 16 a b in
+ let div, div2 = ndiv 16 a b in
+ let mulu, mulu2 = nmulu 16 a b in
+ let divu, divu2 = ndivu 16 a b in
+ let q00 = mux (f ** 0) add sub in
+ let q01 = mux (f ** 0) mul div in
+ let q03 = mux (f ** 0) mulu divu in
+ let q10 = mux (f ** 1) q00 q01 in
+ let q11 = mux (f ** 1) q00 q03 in
+ let q = mux f1 q10 q11 in
+ let r01 = mux (f ** 0) mul2 div2 in
+ let r03 = mux (f ** 0) mulu2 divu2 in
+ let r10 = mux (f ** 1) (zeroes 16) r01 in
+ let r11 = mux (f ** 1) (zeroes 16) r03 in
+ let r = mux f1 r10 r11 in
+ q, r
+
+let alu_logic f a b =
+ (* See table for ALU below *)
+ let q0 = mux (f ** 0) (a ^| b) (a ^& b) in
+ let q1 = mux (f ** 0) (a ^^ b) (not (a ^| b)) in
+ mux (f ** 1) q0 q1
+
+let alu_shifts f a b =
+ (* See table for ALU below *)
+ let q1 = mux (f ** 0) (op_lsr 16 a b) (op_asr 16 a b) in
+ mux (f ** 1) (op_lsl 16 a b) q1
+
+let alu f1 f0 f a b =
+ (*
+ f0 f1 f action
+ -- -- - ------
+ 0 0 0 add
+ 0 0 1 sub
+ 0 0 2 mul
+ 0 0 3 div
+ 0 1 0 addu
+ 0 1 1 subu
+ 0 1 2 mulu
+ 0 1 3 divu
+ 1 0 0 or
+ 1 0 1 and
+ 1 0 2 xor
+ 1 0 3 nor
+ 1 1 0 lsl
+ 1 1 1 lsl
+ 1 1 2 lsr
+ 1 1 3 asr
+ *)
+ let arith, arith_r = alu_arith f1 f a b in
+ let logic = alu_logic f a b in
+ let shifts = alu_shifts f a b in
+
+ let q0 = mux f1 logic shifts in
+ let s = mux f0 arith q0 in
+ let r = mux f0 arith_r (zeroes 16) in
+ s, r
+
diff --git a/cpu/cpu.ml b/cpu/cpu.ml
index 6a71efd..e47c0c8 100644
--- a/cpu/cpu.ml
+++ b/cpu/cpu.ml
@@ -1,17 +1,12 @@
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 ser_out, set_ser_out = loop 8
let ser_in_busy, set_ser_in_busy = loop 1
+let dbg_ra, set_dbg_ra = loop 16
+let dbg_read_data, set_dbg_read_data = loop 8
+
let cpu_ram ra we wa d =
(* Ram chip has word size = 8 bits and address size = 16 bits
0x0000 to 0x3FFF is ROM0
@@ -40,10 +35,9 @@ let cpu_ram ra we wa d =
let read_tick = eq_c 16 ra 0x4000 in
let next_tick, set_next_tick = loop 8 in
- let tick = reg 8 next_tick in
- let tick_d = sign_extend 1 8 (get "tick") in
+ let tick = nadder 8 (reg 8 next_tick) (get "tick" ++ zeroes 7) in
let read_data =
- set_next_tick (mux read_tick (nadder_nocarry 8 tick tick_d) tick_d) ^.
+ set_next_tick (mux read_tick tick (zeroes 8)) ^.
mux read_tick read_data tick in
let write_ser = we ^& (eq_c 16 wa 0x4102) in
@@ -51,7 +45,7 @@ let cpu_ram ra we wa d =
set_ser_out (mux write_ser (zeroes 8) d) ^.
read_data in
- let read_ser = eq_c 16 ra 0x4000 in
+ let read_ser = eq_c 16 ra 0x4100 in
let next_ser, set_next_ser = loop 8 in
let ser = reg 8 next_ser in
let ser_in = get "ser_in" in
@@ -63,6 +57,8 @@ let cpu_ram ra we wa d =
set_next_ser ser ^.
mux read_ser read_data ser in
+ set_dbg_ra ra ^.
+ set_dbg_read_data read_data ^.
read_data
@@ -118,7 +114,7 @@ let rl, rh, i, ex, exf, pc =
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 ra = mux read_ihi ra (nadder 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
@@ -130,7 +126,7 @@ let rl, rh, i, ex, exf, pc =
let i = save_i i in
(* Execute instruction if exec is set *)
- let next_pc = nadder_nocarry 16 pc (two 16) in
+ let next_pc = nadder 16 pc (two 16) in
let exec_finished = exec in
let i_i = i % (11, 15) in
@@ -149,6 +145,22 @@ let rl, rh, i, ex, exf, pc =
let wr = zeroes 3 in
let rwd = zeroes 16 in
+ (* instruction : add/sub/mul/div/unsigned/or/and/xor/nor/lsl/lsr/asr *)
+ let instr_alu = eq_c 3 (i_i % (2, 4)) 0b000 in
+ let f0 = i_i ** 0 in
+ let f1 = i_i ** 1 in
+ let double_instr_alu = instr_alu ^& (not f1) ^& (i_f ** 1) ^& (ne_n 3 i_r (const "101")) in
+ let instr_alu = exec ^& instr_alu in
+ let instr_alu_2 = reg 1 (exec ^& double_instr_alu) in
+
+ let alu_d1, alu_d2 = alu f1 f0 i_f v_ra v_rb in
+ let wr = mux instr_alu wr i_r in
+ let rwd = mux instr_alu rwd alu_d1 in
+ let wr = mux instr_alu_2 wr (const "101") in
+ let rwd = mux instr_alu_2 rwd alu_d2 in
+ let exec_finished = mux double_instr_alu exec_finished instr_alu_2 in
+
+
(* instruction : se/sne/slt/slte/sleu/sleu *)
let instr_sxxx = exec ^& (eq_c 4 (i_i % (1, 4)) 0b0010) in
let f0 = i_i ** 0 in
@@ -159,7 +171,7 @@ let rl, rh, i, ex, exf, pc =
(* 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
+ let rwd = mux instr_incri rwd (nadder 16 v_r (sign_extend 8 16 i_id)) in
(* instruction : shi *)
let instr_shi = exec ^& eq_c 5 i_i 0b00111 in
let wr = mux instr_shi wr i_r in
@@ -167,10 +179,10 @@ let rl, rh, i, ex, exf, pc =
(* 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
+ let next_pc = mux instr_j next_pc (nadder 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 next_pc = mux instr_jal next_pc (nadder 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
@@ -187,7 +199,7 @@ let rl, rh, i, ex, exf, pc =
(* instruction : lra *)
let instr_lra = exec ^& eq_c 5 i_i 0b01100 in
let wr = mux instr_lra wr (const "101") in
- let rwd = mux instr_lra rwd (nadder_nocarry 16 pc (sign_extend 11 16 i_jd)) in
+ let rwd = mux instr_lra rwd (nadder 16 pc (sign_extend 11 16 i_jd)) in
(* instruction : lw/lwr/sw/swr *)
let instr_lsw = eq_c 4 (i_i % (1, 4)) 0b1000 in
@@ -197,8 +209,8 @@ let rl, rh, i, ex, exf, pc =
let instr_lwx = instr_lswx ^& (not (i_i ** 0)) in
let lswx_d = mux instr_lswr (sign_extend 5 16 i_kd) v_rb in
- let lswx_addr_lo = reg 16 (nadder_nocarry 16 v_ra lswx_d) in
- let lswx_addr_hi = let a, b = nadder 16 v_ra lswx_d (const "1") in b ^. reg 16 a in
+ let lswx_addr_lo = reg 16 (nadder 16 v_ra lswx_d) in
+ let lswx_addr_hi = let a, b = nadder_with_carry 16 v_ra lswx_d (const "1") in b ^. reg 16 a in
let lwx_load_lo = reg 1 (exec ^& instr_lwx) in
let lwx_load_hi = reg 1 lwx_load_lo in
@@ -218,16 +230,38 @@ let rl, rh, i, ex, exf, pc =
let we = we ^| swx_save_hi in
let wa = mux swx_save_hi wa lswx_addr_hi in
let d = mux swx_save_hi d (v_r % (8, 15)) in
- let exec_finished = mux instr_lwx exec_finished swx_save_hi in
+ let exec_finished = mux instr_swx exec_finished swx_save_hi in
+
+ (* instruction : lb/lbr/sb/sbr *)
+ let instr_lsb = eq_c 4 (i_i % (1, 4)) 0b1001 in
+ let instr_lsbr = eq_c 4 (i_i % (1, 4)) 0b1011 in
+ let instr_lsbx = instr_lsb ^| instr_lsbr in
+ let instr_sbx = instr_lsbx ^& (i_i ** 0) in
+ let instr_lbx = instr_lsbx ^& (not (i_i ** 0)) in
+
+ let lsbx_d = mux instr_lsbr (sign_extend 5 16 i_kd) v_rb in
+ let lsbx_addr = reg 16 (nadder 16 v_ra lsbx_d) in
+
+ let lbx_load = reg 1 (exec ^& instr_lbx) in
+ let ra = mux lbx_load ra lsbx_addr in
+ let wr = mux lbx_load wr i_r in
+ let rwd = mux lbx_load rwd (ram_read ++ (zeroes 8)) in
+ let exec_finished = mux instr_lbx exec_finished lbx_load in
+
+ let sbx_save = reg 1 (exec ^& instr_sbx) in
+ let we = we ^| sbx_save in
+ let wa = mux sbx_save wa lsbx_addr in
+ let d = mux sbx_save d (v_r % (0, 7)) in
+ let exec_finished = mux instr_sbx exec_finished sbx_save in
(* instruction : lil/lilz/liu/liuz *)
let instr_lixx = eq_c 3 (i_i % (2, 4))0b110 in
- let instr_lixz = i ** 0 in
- let instr_liux = i ** 1 in
+ let instr_lixz = i_i ** 0 in
+ let instr_liux = i_i ** 1 in
let wr = mux instr_lixx wr i_r in
let rwd = mux instr_lixx rwd
(mux instr_liux
- ( (* lil *) i_id ++ (mux instr_lixz (v_r % (8, 15)) (zeroes 8)) )
+ ( (* lil *) i_id ++ (mux instr_lixz (v_r % (8, 15)) (zeroes 8)))
( (* liu *) (mux instr_lixz (v_r % (0, 7)) (zeroes 8)) ++ i_id)) in
save_cpu_regs wr rwd ^.
@@ -248,6 +282,8 @@ let p =
"exec_instr", 1, ex;
"exec_finished", 1, exf;
"instruction", 16, i;
+ "ra", 16, dbg_ra;
+ "read_data", 8, dbg_read_data;
"pc", 16, pc;
"r0_Z", 16, r0;
"r1_A", 16, r1;
diff --git a/cpu/prog_rom0.rom b/cpu/prog_rom0.rom
index 1321436..1cd848b 100644
--- a/cpu/prog_rom0.rom
+++ b/cpu/prog_rom0.rom
@@ -1,3 +1,6 @@
-4 8
+10 8
+x40 01011011 # liuz B 0x40 -> B = 0x4000 (address of ticker)
+00000010 11000001 # lw C 0(B)
+00110001 00100000 # add D D C
/1 10001100 # incri A 1
-01111111 11100010 # j -2 (ie jump to address 0)
+/-6 11100010 # j -6 (ie to lw instruction)