diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/alu.ml | 67 | ||||
-rw-r--r-- | cpu/cpu.ml | 18 | ||||
-rw-r--r-- | cpu/os.asm | 94 |
3 files changed, 137 insertions, 42 deletions
@@ -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 @@ -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 *) @@ -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 |