summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/alu.ml68
-rw-r--r--cpu/cpu.ml24
2 files changed, 76 insertions, 16 deletions
diff --git a/cpu/alu.ml b/cpu/alu.ml
index cf33cd2..a0115a4 100644
--- a/cpu/alu.ml
+++ b/cpu/alu.ml
@@ -1,5 +1,20 @@
open Netlist_gen
+let rec rep n k =
+ if n = 1 then k
+ else
+ let s = rep (n/2) k in
+ if n mod 2 = 0 then s ++ s else s ++ s ++ k
+
+let rec eq_c n v c = (* v is a value, c is a constant *)
+ if n = 1 then
+ if c = 1 then v else not v
+ else
+ (eq_c 1 (v ** 0) (c mod 2)) ^& (eq_c (n-1) (v % (1, n-1)) (c/2))
+
+let rec sign_extend n_a n_dest a =
+ a ++ rep (n_dest - n_a) (a ** (n_a - 1))
+
let fulladder a b c =
let s = a ^^ b ^^ c in
let r = (a ^& b) ^| ((a ^^ b) ^& c) in
@@ -16,18 +31,47 @@ let nadder_nocarry n a b =
let a, b = nadder n a b (const "0") in
ignore b a
-let rec rep n k =
- if n = 1 then k
- else
- let s = rep (n/2) k in
- if n mod 2 = 0 then s ++ s else s ++ s ++ k
-
-let rec sign_extend n_a n_dest a =
- a ++ rep (n_dest - n_a) (a ** (n_a - 1))
+let rec eq_n n a b =
+ if n = 1 then
+ not (a ^^ b)
+ else
+ (not ((a ** 0) ^^ (b ** 0)))
+ ^& (eq_n (n-1) (a % (1, n-1)) (b % (1, n-1)))
-let rec eq_c n v c = (* v is a value, c is a constant *)
+let rec ne_n n a b =
if n = 1 then
- if c = 1 then v else not v
- else
- (eq_c 1 (v ** 0) (c mod 2)) ^& (eq_c (n-1) (v % (1, n-1)) (c/2))
+ a ^^ b
+ else
+ ((a ** 0) ^^ (b ** 0))
+ ^| (ne_n (n-1) (a % (1, n-1)) (b % (1, n-1)))
+
+let rec lt_n n a b =
+ const "0" (* TODO : less than *)
+
+let rec ult_n n a b =
+ const "0" (* TODO : less than, unsigned *)
+
+let rec le_n n a b =
+ const "0" (* TODO : less than or equal *)
+
+let rec ule_n n a b =
+ const "0" (* TODO : less than or equal, unsigned *)
+let alu_comparer n f0 f a b =
+ (*
+ f0 f action
+ -- - ------
+ 0 0 equal
+ 0 1 not equal
+ 0 2 equal
+ 0 3 not equal
+ 1 0 lt
+ 1 1 le
+ 1 2 lt unsigned
+ 1 3 le unsigned
+ *)
+ let eq_ne = mux (f ** 0) (eq_n n a b) (ne_n n a b) in
+ let lte_signed = mux (f ** 0) (lt_n n a b) (le_n n a b) in
+ 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
diff --git a/cpu/cpu.ml b/cpu/cpu.ml
index 8a31c9e..c70d6e2 100644
--- a/cpu/cpu.ml
+++ b/cpu/cpu.ml
@@ -95,8 +95,13 @@ let rl, rh, i, ex, exf, pc =
let ra = mux read_ihi ra (nadder_nocarry 16 pc (one 16)) in
let ihi = mux read_ihi (zeroes 8) ram_read in
- let exec = ignore (save_next_read_ihi read_ilow) read_ihi in
- let i = ilow ++ ihi 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
@@ -127,9 +132,20 @@ let rl, rh, i, ex, exf, pc =
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 wr = mux instr_jal wr (const "011") in
- let rwd = mux instr_jal rwd next_pc 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) ^.