summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/alu.ml67
-rw-r--r--cpu/cpu.ml18
-rw-r--r--cpu/os.asm94
3 files changed, 137 insertions, 42 deletions
diff --git a/cpu/alu.ml b/cpu/alu.ml
index aa82a6d..96e2ae4 100644
--- a/cpu/alu.ml
+++ b/cpu/alu.ml
@@ -120,41 +120,36 @@ let rec split_list = function
| x::y::tl -> let a, b = split_list tl in x::a, y::b
(* n must be a power of two *)
-let nmul n a b =
+let nmulu n a b start_signal =
+ let next_busy, set_next_busy = loop 1 in
+ let busy = start_signal ^| (reg 1 next_busy) in
- let summands = List.map (fun i ->
- mux (b ** i)
- (zeroes (2*n))
- ((zeroes i) ++ a ++ (zeroes (n - i)))
-
- ) (range 0 (n-1)) in
+ let res, set_res = loop (2*n) in
+ let t_res = mux start_signal (const "0" ++ ((reg (2*n) res) % (0, 2*n-2))) (zeroes (2*n)) in
+ let mul, set_mul = loop n in
+ let mul = set_mul (mux start_signal (((reg n mul) % (1, n-1)) ++ const "0") b) in
+ let add = nonnull n mul in
+ let res = set_res (mux add t_res (nadder (2*n) (a ++ zeroes n) t_res)) in
-
- let rec sum_list = function
- | [x] -> x
- | l ->
- let s1, s2 = split_list l in
- nadder (2*n) (sum_list s1) (sum_list s2)
+ let finished =
+ set_next_busy (busy ^& add) ^.
+ (not add) ^& busy in
- in
- let r = sum_list summands in
- (r % (0, n-1)), (r % (n, 2*n - 1))
+ res % (0, n-1), res % (n, 2*n-1), finished
+let rec ndivu n a b start_signal =
+ zeroes n, zeroes n, start_signal (* TODO : unsigned division, returns quotient and remainder *)
-let rec ndiv n a b =
- zeroes n, zeroes n (* TODO : returns quotient and remainder *)
+let rec nmul n a b start_signal =
+ zeroes n, zeroes n, start_signal (* TODO : signed multiplication ; returns low part and high part *)
+let rec ndiv n a b start_signal =
+ zeroes n, zeroes n, start_signal (* TODO : signed division *)
-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 =
@@ -210,14 +205,14 @@ let alu_comparer n f0 f a b =
let lte = mux (f ** 1) lte_signed lte_unsigned in
mux f0 eq_ne lte
-let alu_arith f1 f a b =
+let alu_arith f1 f a b start_signal =
(* 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 mul, mul2, mul_end_signal = nmul 16 a b start_signal in
+ let div, div2, div_end_signal = ndiv 16 a b start_signal in
+ let mulu, mulu2, mulu_end_signal = nmulu 16 a b start_signal in
+ let divu, divu2, divu_end_signal = ndivu 16 a b start_signal 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
@@ -229,7 +224,12 @@ let alu_arith f1 f a b =
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 s01 = mux (f ** 0) mul_end_signal div_end_signal in
+ let s03 = mux (f ** 0) mulu_end_signal divu_end_signal in
+ let s10 = mux (f ** 1) start_signal s01 in
+ let s11 = mux (f ** 1) start_signal s03 in
+ let end_signal = mux f1 s10 s11 in
+ q, r, end_signal
let alu_logic f a b =
(* See table for ALU below *)
@@ -242,7 +242,7 @@ let alu_shifts f a b =
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 =
+let alu f1 f0 f a b start_signal =
(*
f0 f1 f action
-- -- - ------
@@ -263,12 +263,13 @@ let alu f1 f0 f a b =
1 1 2 lsr
1 1 3 asr
*)
- let arith, arith_r = alu_arith f1 f a b in
+ let arith, arith_r, arith_end_signal = alu_arith f1 f a b start_signal 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
+ let end_signal = mux f0 arith_end_signal start_signal in
+ s, r, end_signal
diff --git a/cpu/cpu.ml b/cpu/cpu.ml
index c5643ec..14b1f2a 100644
--- a/cpu/cpu.ml
+++ b/cpu/cpu.ml
@@ -157,15 +157,15 @@ let rl, rh, i, ex, exf, pc =
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
+
+ let alu_d1, alu_d2, instr_alu_finished = alu f1 f0 i_f v_ra v_rb (exec ^& instr_alu) in
+ let instr_alu_store_2 = reg 1 (instr_alu_finished ^& double_instr_alu) in
+ let wr = mux instr_alu_finished wr i_r in
+ let rwd = mux instr_alu_finished rwd alu_d1 in
+ let wr = mux instr_alu_store_2 wr (const "101") in
+ let rwd = mux instr_alu_store_2 rwd alu_d2 in
+ let exec_finished = mux instr_alu exec_finished
+ (mux double_instr_alu instr_alu_finished instr_alu_store_2) in
(* instruction : se/sne/slt/slte/sleu/sleu *)
diff --git a/cpu/os.asm b/cpu/os.asm
index 4a7449a..c7abde3 100644
--- a/cpu/os.asm
+++ b/cpu/os.asm
@@ -4,6 +4,8 @@
# all registers are caller-saved, except SP which is preserved by function calls
.text
+ jal run_unit_tests
+
li A msghello
jal ser_out_msg
@@ -87,8 +89,84 @@ add_b_to_string:
incri C 1
sw C 0(D)
pop A
+ jz A check_input
check_input_ret:
jr RA
+
+# PROCEDURE: run_unit_tests
+# ROLE: check that CPU features work correctly ; displays message to serial output
+# ARGUMENTS: none
+run_unit_tests:
+ push RA
+
+ li A testbegin
+ jal ser_out_msg
+
+ li A test0
+ jal ser_out_msg
+ jal unit_test_0
+ li A testfail
+ jz B t0fail
+ li A testok
+t0fail:
+ jal ser_out_msg
+
+ li A test1
+ jal ser_out_msg
+ jal unit_test_1
+ li A testfail
+ jz B t1fail
+ li A testok
+t1fail:
+ jal ser_out_msg
+
+ li A test2
+ jal ser_out_msg
+ jal unit_test_2
+ li A testfail
+ jz B t2fail
+ li A testok
+t2fail:
+ jal ser_out_msg
+
+ li A test3
+ jal ser_out_msg
+ jal unit_test_3
+ li A testfail
+ jz B t2fail
+ li A testok
+t3fail:
+ jal ser_out_msg
+
+ pop RA
+ jr RA
+
+unit_test_0:
+ li B 1
+
+ li C 12
+ li D 44
+ add C C D
+ sei A C 56
+ and B B A
+
+ li C -7
+ li D 7
+ add C C D
+ se A C Z
+ and B B A
+
+ jr RA
+unit_test_1:
+ li B 1
+ jr RA
+unit_test_2:
+ li B 1
+ jr RA
+unit_test_3:
+ li B 1
+ jr RA
+
# READ-ONLY PROGRAM DATA
@@ -103,6 +181,22 @@ endl:
error:
ascii "Sorry but I'm to stupid to understand that.\n"
+testbegin:
+ ascii "Runing CPU unit tests...\n"
+testok:
+ ascii "OK\n"
+testfail:
+ ascii "FAIL\n"
+test0:
+ ascii "Addition/substraction: "
+test1:
+ ascii "Unsigned multiplication: "
+test2:
+ ascii "Unsigned division: "
+test3:
+ ascii "Signed division/multiplication: "
+
+
.data
# Space where command-line is buffered from serial input