diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/alu.ml | 68 | ||||
-rw-r--r-- | cpu/cpu.ml | 24 |
2 files changed, 76 insertions, 16 deletions
@@ -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 @@ -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) ^. |