diff --git a/lib/CPUs/MIPS/src/core/mips_cop.vhd b/lib/CPUs/MIPS/src/core/mips_cop.vhd index ea917c6..512a52f 100644 --- a/lib/CPUs/MIPS/src/core/mips_cop.vhd +++ b/lib/CPUs/MIPS/src/core/mips_cop.vhd @@ -40,6 +40,7 @@ entity cop is ( rst : in STD_LOGIC; clk : in STD_LOGIC; + int : in unsigned(5 downto 0); ir_en : in STD_LOGIC; ir : in word_t; ctrl_in : in cop0_ctrl_in_t; @@ -54,6 +55,8 @@ architecture Behavioral of cop is signal epc : word_t; signal cause : word_t; signal status : word_t; + signal imem_addr : word_t; + signal imem_addr_we : STD_LOGIC; signal BadVAddr : word_t; signal exc_code : unsigned(4 downto 0); signal test_reg : word_t; @@ -68,8 +71,6 @@ architecture Behavioral of cop is signal im : unsigned(7 downto 0); signal status_save : STD_LOGIC; signal status_rest : STD_LOGIC; - signal exception : STD_LOGIC; - signal exception_end : STD_LOGIC; signal eflags : exc_flags_t; signal exc_enable : STD_LOGIC; signal icache_info : unsigned(7 downto 0); @@ -77,6 +78,7 @@ architecture Behavioral of cop is type cop_pipe_t is record opc : opcode_t; + RFE : std_logic; CO : std_logic; reg_ptr : reg_ptr_t; rs : reg_ptr_t; @@ -102,7 +104,7 @@ architecture Behavioral of cop is return result; end eval_int; - type exc_state_t is (exc_init, exc_idle, exc_commit_ID, exc_commit_EX, exc_commit_MEM); + type exc_state_t is (exc_idle, exc_pipe_flush, exc_commit, exc_inject, exc_enter, exc_leave, exc_left); signal exc_state, exc_staten : exc_state_t; -------------------------------------------------------------------------- @@ -119,10 +121,10 @@ begin cop_pipe_ID.CO <= ir(25); cop_pipe_ID.re <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "111000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00000")) else '0'; cop_pipe_ID.we <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "110000" or (cop_pipe_ID.opc = "010000" and cop_pipe_ID.rs = "00100")) else '0'; - + cop_pipe_ID.RFE <= cop_pipe_ID.cs when (cop_pipe_ID.CO = '1' and cop_pipe_ID.func = "010000") else '0'; ctrl_out.RE <= status(25); ctrl_out.user_mode <= status(1); - ctrl_out.int <= eflags.Int; + ctrl_out.int <= eval_int(ip) and status(0); cop_pipe_ID.reg_ptr <= cop_pipe_ID.rd when cop_pipe_ID.opc = "010000" else cop_pipe_ID.rt; @@ -137,58 +139,71 @@ begin eflags.Sys <= ctrl_in.events.syscall; eflags.Bp <= ctrl_in.events.break; eflags.RI <= ctrl_in.events.illegal; - eflags.Int <= eval_int(ip) and status(0); + eflags.Int <= ctrl_in.events.int; - exception <= eflags.Ov or eflags.Sys or eflags.Bp or eflags.RI or eflags.IAdEL or eflags.IAdEK or eflags.DAdEL or eflags.DAdES or eflags.Int after 1 ns; - exception_state: - process(exc_state, ctrl_in, exception) + process(exc_state, ctrl_in, cop_pipe_ID) begin - exc_enable <= '0'; + ctrl_out.exc_inject <= '0'; ctrl_out.exc_commit <= '0'; ctrl_out.exc_pending <= '0'; + ctrl_out.exc_exit <= '0'; epc_reg_we <= '0'; code_reg_we <= '0'; status_save <= '0'; - eflags_reg_we <= '0'; + status_rest <= '0'; + imem_addr_we <= '0'; exc_staten <= exc_state; case exc_state is - when exc_init => - exc_staten <= exc_idle; - when exc_idle => - exc_enable <= '1'; - if exception = '1' then - status_save <= '1'; - eflags_reg_we <= '1'; - code_reg_we <= '1'; - exc_staten <= exc_commit_ID; + if cop_pipe_ID.RFE = '1' then + exc_staten <= exc_leave; + ctrl_out.exc_exit <= '1'; + ctrl_out.exc_commit <= '1'; + elsif ctrl_in.exc_req = '1' then + exc_staten <= exc_pipe_flush; + imem_addr_we <= '1'; end if; - when exc_commit_ID => + when exc_pipe_flush => + ctrl_out.exc_pending <= '1'; + ctrl_out.exc_commit <= '1'; + if ctrl_in.exc_ack = '1' then + exc_staten <= exc_commit; + end if; + + when exc_commit => ctrl_out.exc_pending <= '1'; ctrl_out.exc_commit <= '1'; if ctrl_in.sdu.ID_stall = '0' then - exc_staten <= exc_commit_EX; - end if; - - when exc_commit_EX => - ctrl_out.exc_pending <= '1'; - ctrl_out.exc_commit <= '1'; - if ctrl_in.sdu.stall_all = '0' then - exc_staten <= exc_commit_MEM; + exc_staten <= exc_inject; end if; - when exc_commit_MEM => + when exc_inject => ctrl_out.exc_pending <= '1'; - if ctrl_in.sdu.stall_all = '0' then - epc_reg_we <= '1'; - exc_staten <= exc_idle; - end if; + ctrl_out.exc_inject <= '1'; + ctrl_out.exc_commit <= '1'; + code_reg_we <= '1'; + status_save <= '1'; + epc_reg_we <= '1'; + exc_staten <= exc_enter; + + when exc_enter => + ctrl_out.exc_pending <= '1'; + exc_staten <= exc_idle; + + when exc_leave => + exc_staten <= exc_left; + status_rest <= '1'; + ctrl_out.exc_exit <= '1'; + ctrl_out.exc_commit <= '1'; + + when exc_left => + exc_staten <= exc_idle; when others => exc_staten <= exc_idle; @@ -196,12 +211,22 @@ exception_state: end case; end process; +exception_last_imem_addr: + process(clk) + begin + if rising_edge(clk) then + if imem_addr_we = '1' then + imem_addr <= ctrl_in.imem_addr; + end if; + end if; + end process; + exception_state_next: process(clk) begin if rising_edge(clk) then if rst = '1' then - exc_state <= exc_init; + exc_state <= exc_idle; else exc_state <= exc_staten; end if; @@ -244,10 +269,10 @@ cop_exception_map: exc_code <= "01010"; elsif eflags.IAdEL = '1' then exc_code <= "00100"; - BadVAddr <= ctrl_in.imem_addr; + BadVAddr <= imem_addr; elsif eflags.IAdEK = '1' then exc_code <= "00100"; - BadVAddr <= ctrl_in.imem_addr; + BadVAddr <= imem_addr; elsif eflags.DAdEL = '1' then exc_code <= "00100"; BadVAddr <= ctrl_in.dmem_addr; @@ -261,9 +286,6 @@ cop_exception_map: end if; end process; - status_rest <= exception_end and ctrl_in.exc_left; - - ctrl_out.icache.inv_addr <= test_reg; ctrl_out.dcache.inv_addr <= test_reg; @@ -292,25 +314,6 @@ cop_cache_op: end if; end process; -cop_status_restore: - process(clk) - begin - if rising_edge(clk) then - if rst = '1' then - exception_end <= '0'; - ctrl_out.exc_exit <= '0'; - else - if cop_pipe_ID.CO = '1' and cop_pipe_ID.func = "010000" and exception_end = '0' then -- RFE - exception_end <= cop_pipe_ID.cs; - ctrl_out.exc_exit <= cop_pipe_ID.cs; - elsif exception_end = '1' and ctrl_in.exc_left = '1' then - exception_end <= '0'; - ctrl_out.exc_exit <= '0'; - end if; - end if; - end if; - end process; - cop_ip_reg_write: process(clk) begin @@ -322,7 +325,7 @@ cop_ip_reg_write: ip(1 downto 0) <= din(9 downto 8) and im(1 downto 0); end if; end if; - ip(7 downto 2) <= ctrl_in.events.Int and im(7 downto 2); + ip(7 downto 2) <= int and im(7 downto 2); end if; end process;