diff options
Diffstat (limited to 'cpu')
-rw-r--r-- | cpu/alu.ml | 117 | ||||
-rw-r--r-- | cpu/cpu.ml | 84 | ||||
-rw-r--r-- | cpu/prog_rom0.rom | 7 |
3 files changed, 175 insertions, 33 deletions
@@ -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 + @@ -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) |