From 81c8bf189720fc2def842257f0579fecc5206338 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Mon, 16 Mar 2009 11:31:51 +0000 Subject: [PATCH] - simplified instruction decoder and removed genrom functions Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@394 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/src/core/mips_instr.vhd | 680 ++++++++++++++------------ 1 file changed, 356 insertions(+), 324 deletions(-) diff --git a/lib/CPUs/MIPS/src/core/mips_instr.vhd b/lib/CPUs/MIPS/src/core/mips_instr.vhd index 97a0c0b..dbaf405 100644 --- a/lib/CPUs/MIPS/src/core/mips_instr.vhd +++ b/lib/CPUs/MIPS/src/core/mips_instr.vhd @@ -43,12 +43,7 @@ package mips_instr is function extract_bimm18(instr, pc : word_t) return word_t; function decode_op(instr : word_t) return op_t; function ctrl_lines_default return ctrl_lines_t; - function special_ctrl_lines(func : func_t) return ctrl_lines_t; - function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t; - function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t; - function gen_rom_opcode return rom_opcode_t; - function gen_rom_regimm return rom_regimm_t; - function gen_rom_special return rom_special_t; + function opcode_ctrl_lines(instr : word_t) return ctrl_lines_t; end mips_instr; @@ -153,12 +148,14 @@ package body mips_instr is variable opc : natural range 0 to 63; variable func : natural range 0 to 63; variable rt : natural range 0 to 31; + variable rs : natural range 0 to 31; begin opc := to_integer(extract_opc(instr)); func := to_integer(extract_func(instr)); rt := to_integer(extract_rt(instr)); + rs := to_integer(extract_rs(instr)); result := op_sll; @@ -317,16 +314,100 @@ package body mips_instr is result := op_lui; when 16 => - result := op_cop0; + case rs is + when 0 => + result := op_mfc0; + when 2 => + result := op_cfc0; -- illegal + when 4 => + result := op_mtc0; + when 6 => + result := op_ctc0; -- illegal + when 8 => + case rt is + when 0 => + result := op_bcf0; -- illegal + when 1 => + result := op_bct0; -- illegal + + when others => null; -- undef + end case; + + when others => null; -- undef + + end case; when 17 => - result := op_cop1; + case rs is + when 0 => + result := op_mfc1; + when 2 => + result := op_cfc1; + when 4 => + result := op_mtc1; + when 6 => + result := op_ctc1; + when 8 => + case rt is + when 0 => + result := op_bcf1; + when 1 => + result := op_bct1; + + when others => null; -- undef + end case; + + when others => null; -- undef + + end case; when 18 => - result := op_cop2; + case rs is + when 0 => + result := op_mfc2; + when 2 => + result := op_cfc2; + when 4 => + result := op_mtc2; + when 6 => + result := op_ctc2; + when 8 => + case rt is + when 0 => + result := op_bcf2; + when 1 => + result := op_bct2; + + when others => null; -- undef + end case; + + when others => null; -- undef + + end case; when 19 => - result := op_cop3; + case rs is + when 0 => + result := op_mfc3; + when 2 => + result := op_cfc3; + when 4 => + result := op_mtc3; + when 6 => + result := op_ctc3; + when 8 => + case rt is + when 0 => + result := op_bcf3; + when 1 => + result := op_bct3; + + when others => null; -- undef + end case; + + when others => null; -- undef + + end case; when 32 => result := op_lb; @@ -364,6 +445,9 @@ package body mips_instr is when 46 => result := op_swr; + when 48 => + result := op_lwc0; -- illegal + when 49 => result := op_lwc1; @@ -373,6 +457,9 @@ package body mips_instr is when 51 => result := op_lwc3; + when 56 => + result := op_swc0; -- illegal + when 57 => result := op_swc1; @@ -436,312 +523,274 @@ package body mips_instr is end ctrl_lines_default; - - function special_ctrl_lines(func : func_t) return ctrl_lines_t is + function opcode_ctrl_lines(instr : word_t) return ctrl_lines_t is variable result : ctrl_lines_t; - variable op : integer range 0 to 2**func_t'length-1; + variable opc : integer range 0 to 2**opcode_t'length-1; + variable func : integer range 0 to 2**func_t'length-1; + variable rt : integer range 0 to 2**reg_ptr_t'length-1; + variable rs : integer range 0 to 2**reg_ptr_t'length-1; begin - result := ctrl_lines_default; - - op := to_integer(func); - case op is + result := ctrl_lines_default; + opc := to_integer(extract_opc(instr)); + func := to_integer(extract_func(instr)); + rt := to_integer(extract_rt(instr)); + rs := to_integer(extract_rs(instr)); --- when op_add => - when 32 => - result.alu.outsel := alu_adder; - result.alu.add := '1'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - result.alu_exc_en := '1'; + case opc is +-- SPECIAL + when 0 => + case func is --- when op_addu => - when 33 => - result.alu.outsel := alu_adder; - result.alu.add := '1'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; + -- when op_add => + when 32 => + result.alu.outsel := alu_adder; + result.alu.add := '1'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + result.alu_exc_en := '1'; --- when op_and => - when 36 => - result.alu.outsel := alu_and; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; + -- when op_addu => + when 33 => + result.alu.outsel := alu_adder; + result.alu.add := '1'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; --- when op_break => - when 13 => - result.exc_break := '1'; - result.except_en := '1'; + -- when op_and => + when 36 => + result.alu.outsel := alu_and; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; --- when op_div => - when 26 => - result.mul_access := '1'; - result.mul_start := '1'; - result.mul_s_un := '1'; - result.mul_mul_divn := '0'; + -- when op_break => + when 13 => + result.exc_break := '1'; + result.except_en := '1'; + + -- when op_div => + when 26 => + result.mul_access := '1'; + result.mul_start := '1'; + result.mul_s_un := '1'; + result.mul_mul_divn := '0'; + + -- when op_divu => + when 27 => + result.mul_access := '1'; + result.mul_start := '1'; + result.mul_s_un := '0'; + result.mul_mul_divn := '0'; + + -- when op_jalr => + when 9 => + result.jump_long := '1'; + result.wptr_srcsel := wptr_src_imm; + result.reg_write := '1'; + result.reg_link := '1'; + + -- when op_jr => + when 8 => + result.jump_long := '1'; + + -- when op_mfhi => + when 16 => + result.reg_write := '1'; + result.mul_access := '1'; + result.mul_hilo_sel := '1'; + + -- when op_mflo => + when 18 => + result.reg_write := '1'; + result.mul_access := '1'; + result.mul_hilo_sel := '0'; + + -- when op_mthi => + when 17 => + result.mul_hilo_we := '1'; + result.mul_hilo_sel := '1'; + + -- when op_mtlo => + when 19 => + result.mul_hilo_we := '1'; + result.mul_hilo_sel := '0'; + + -- when op_mult => + when 24 => + result.mul_access := '1'; + result.mul_start := '1'; + result.mul_s_un := '1'; + result.mul_mul_divn := '1'; + + -- when op_multu => + when 25 => + result.mul_access := '1'; + result.mul_start := '1'; + result.mul_s_un := '0'; + result.mul_mul_divn := '1'; + + -- when op_or => + when 37 => + result.alu.outsel := alu_or; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + -- when op_nor => + when 39 => + result.alu.outsel := alu_nor; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + -- when op_sll => + when 0 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '0'; + result.shamt2_srcsel := sa_src_imm; + result.reg_write := '1'; + + -- when op_sllv => + when 4 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '0'; + result.shamt2_srcsel := sa_src_reg; + result.reg_write := '1'; + + -- when op_slt => + when 42 => + result.alu.outsel := alu_lts; + result.alu.add := '0'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + -- when op_sltu => + when 43 => + result.alu.outsel := alu_ltu; + result.alu.add := '0'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + -- when op_sra => + when 3 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '1'; + result.alu.shift_arith := '1'; + result.shamt2_srcsel := sa_src_imm; + result.reg_write := '1'; + + -- when op_srav => + when 7 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '1'; + result.alu.shift_arith := '1'; + result.shamt2_srcsel := sa_src_reg; + result.reg_write := '1'; + + -- when op_srl => + when 2 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '1'; + result.alu.shift_arith := '0'; + result.shamt2_srcsel := sa_src_imm; + result.reg_write := '1'; + + -- when op_srlv => + when 6 => + result.alu.op2_src := alu_src_reg; + result.alu.outsel := alu_shift2; + result.alu.shift_right := '1'; + result.alu.shift_arith := '0'; + result.shamt2_srcsel := sa_src_reg; + result.reg_write := '1'; + + -- when op_sub => + when 34 => + result.alu.outsel := alu_adder; + result.alu.add := '0'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + result.alu_exc_en := '1'; + + -- when op_subu => + when 35 => + result.alu.outsel := alu_adder; + result.alu.add := '0'; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + -- when op_syscall => + when 12 => + result.exc_syscall := '1'; + result.except_en := '1'; + + -- when op_xor => + when 38 => + result.alu.outsel := alu_xor; + result.alu.op1_src := alu_src_reg; + result.alu.op2_src := alu_src_reg; + result.reg_write := '1'; + + when others => + result.exc_illegal := '1'; + + end case; + +-- REGIMM + when 1 => + case rt is + + -- when op_bgez => + when 1 => + result.branch := '1'; + result.bc_src := bc_ltz_gez; + result.bc_not := '1'; + + -- when op_bgezal => + when 17 => + result.branch := '1'; + result.bc_src := bc_ltz_gez; + result.bc_not := '1'; + result.wptr_srcsel := wptr_src_const; + result.reg_write := '1'; + result.reg_link := '1'; + + -- when op_bltz => + when 0 => + result.branch := '1'; + result.bc_src := bc_ltz_gez; + result.bc_not := '0'; + + -- when op_bltzal => + when 16 => + result.branch := '1'; + result.bc_src := bc_ltz_gez; + result.bc_not := '0'; + result.wptr_srcsel := wptr_src_const; + result.reg_write := '1'; + result.reg_link := '1'; + + when others => + result.exc_illegal := '1'; + + end case; + +-- when COPz => + when 16 | 17 | 18 | 19 => + result.cop_instr_en := '1'; --- when op_divu => - when 27 => - result.mul_access := '1'; - result.mul_start := '1'; - result.mul_s_un := '0'; - result.mul_mul_divn := '0'; - --- when op_jalr => - when 9 => - result.jump_long := '1'; - result.wptr_srcsel := wptr_src_imm; - result.reg_write := '1'; - result.reg_link := '1'; - --- when op_jr => - when 8 => - result.jump_long := '1'; - --- when op_mfhi => - when 16 => - result.reg_write := '1'; - result.mul_access := '1'; - result.mul_hilo_sel := '1'; - --- when op_mflo => - when 18 => - result.reg_write := '1'; - result.mul_access := '1'; - result.mul_hilo_sel := '0'; - --- when op_mthi => - when 17 => - result.mul_hilo_we := '1'; - result.mul_hilo_sel := '1'; - --- when op_mtlo => - when 19 => - result.mul_hilo_we := '1'; - result.mul_hilo_sel := '0'; - --- when op_mult => - when 24 => - result.mul_access := '1'; - result.mul_start := '1'; - result.mul_s_un := '1'; - result.mul_mul_divn := '1'; - --- when op_multu => - when 25 => - result.mul_access := '1'; - result.mul_start := '1'; - result.mul_s_un := '0'; - result.mul_mul_divn := '1'; - --- when op_or => - when 37 => - result.alu.outsel := alu_or; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - --- when op_nor => - when 39 => - result.alu.outsel := alu_nor; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - --- when op_sll => - when 0 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '0'; - result.shamt2_srcsel := sa_src_imm; - result.reg_write := '1'; - --- when op_sllv => - when 4 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '0'; - result.shamt2_srcsel := sa_src_reg; - result.reg_write := '1'; - --- when op_slt => - when 42 => - result.alu.outsel := alu_lts; - result.alu.add := '0'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - --- when op_sltu => - when 43 => - result.alu.outsel := alu_ltu; - result.alu.add := '0'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - --- when op_sra => - when 3 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '1'; - result.alu.shift_arith := '1'; - result.shamt2_srcsel := sa_src_imm; - result.reg_write := '1'; - --- when op_srav => - when 7 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '1'; - result.alu.shift_arith := '1'; - result.shamt2_srcsel := sa_src_reg; - result.reg_write := '1'; - --- when op_srl => - when 2 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '1'; - result.alu.shift_arith := '0'; - result.shamt2_srcsel := sa_src_imm; - result.reg_write := '1'; - --- when op_srlv => - when 6 => - result.alu.op2_src := alu_src_reg; - result.alu.outsel := alu_shift2; - result.alu.shift_right := '1'; - result.alu.shift_arith := '0'; - result.shamt2_srcsel := sa_src_reg; - result.reg_write := '1'; - --- when op_sub => - when 34 => - result.alu.outsel := alu_adder; - result.alu.add := '0'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - result.alu_exc_en := '1'; - --- when op_subu => - when 35 => - result.alu.outsel := alu_adder; - result.alu.add := '0'; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - --- when op_syscall => - when 12 => - result.exc_syscall := '1'; - result.except_en := '1'; - --- when op_xor => - when 38 => - result.alu.outsel := alu_xor; - result.alu.op1_src := alu_src_reg; - result.alu.op2_src := alu_src_reg; - result.reg_write := '1'; - - when others => - result.exc_illegal := '1'; - - end case; - - return result; - - end special_ctrl_lines; - - function gen_rom_special return rom_special_t is - variable result : rom_special_t; - variable func : func_t; - begin - - for i in 0 to 2**func_t'length-1 loop - func := to_unsigned(i, func_t'length); - result(i) := special_ctrl_lines(func); - end loop; - - return result; - end gen_rom_special; - - function regimm_ctrl_lines(rt : reg_ptr_t) return ctrl_lines_t is - variable result : ctrl_lines_t; - variable op : integer range 0 to 2**reg_ptr_t'length-1; - begin - - result := ctrl_lines_default; - - op := to_integer(rt); - case op is - --- when op_bgez => - when 1 => - result.branch := '1'; - result.bc_src := bc_ltz_gez; - result.bc_not := '1'; - --- when op_bgezal => - when 17 => - result.branch := '1'; - result.bc_src := bc_ltz_gez; - result.bc_not := '1'; - result.wptr_srcsel := wptr_src_const; - result.reg_write := '1'; - result.reg_link := '1'; - --- when op_bltz => - when 0 => - result.branch := '1'; - result.bc_src := bc_ltz_gez; - result.bc_not := '0'; - --- when op_bltzal => - when 16 => - result.branch := '1'; - result.bc_src := bc_ltz_gez; - result.bc_not := '0'; - result.wptr_srcsel := wptr_src_const; - result.reg_write := '1'; - result.reg_link := '1'; - - when others => - result.exc_illegal := '1'; - - end case; - - return result; - - end regimm_ctrl_lines; - - function gen_rom_regimm return rom_regimm_t is - variable result : rom_regimm_t; - variable rt : reg_ptr_t; - begin - - for i in 0 to 2**reg_ptr_t'length-1 loop - rt := to_unsigned(i, reg_ptr_t'length); - result(i) := regimm_ctrl_lines(rt); - end loop; - - return result; - end gen_rom_regimm; - - function opcode_ctrl_lines(opc : opcode_t) return ctrl_lines_t is - variable result : ctrl_lines_t; - variable op : integer range 0 to 2**opcode_t'length-1; - begin - - result := ctrl_lines_default; - - op := to_integer(opc); - case op is - -- when op_addi => when 8 => result.imm_src := src_imm32; @@ -793,10 +842,6 @@ package body mips_instr is result.bc_src := bc_eq_ne; result.bc_not := '1'; --- when op_cop => - when 16 | 17 | 18 | 19 => - result.cop_instr_en := '1'; - -- when op_j => when 2 => result.jump := '1'; @@ -977,19 +1022,6 @@ package body mips_instr is end opcode_ctrl_lines; - function gen_rom_opcode return rom_opcode_t is - variable result : rom_opcode_t; - variable opc : opcode_t; - begin - - for i in 0 to 2**opcode_t'length-1 loop - opc := to_unsigned(i, opcode_t'length); - result(i) := opcode_ctrl_lines(opc); - end loop; - - return result; - end gen_rom_opcode; - end mips_instr; --------------------------------------------------------------------------