From 52e9decf7847867456f3d6f7338e28011d6b6ffa Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Wed, 18 Mar 2009 23:30:08 +0000 Subject: [PATCH] - added instructions 'lwc0' and 'swc0' for testing (which are usually invalid) - due to cop_reg_we in MEM_Stage, the output register is removed (timing is slightly degraded). The reg pointer is delayed instead by one cycle - test-reg is now writable in user mode regardles of cop0 usability. 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@406 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/src/core/mips_cop.vhd | 73 +++++++++++++++-------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/lib/CPUs/MIPS/src/core/mips_cop.vhd b/lib/CPUs/MIPS/src/core/mips_cop.vhd index 9952ab9..48c3878 100644 --- a/lib/CPUs/MIPS/src/core/mips_cop.vhd +++ b/lib/CPUs/MIPS/src/core/mips_cop.vhd @@ -77,8 +77,11 @@ architecture Behavioral of cop is signal dcache_info : unsigned(7 downto 0); type cop_pipe_t is record + opc : opcode_t; + reg_ptr : reg_ptr_t; rs : reg_ptr_t; rd : reg_ptr_t; + rt : reg_ptr_t; func : func_t; we : std_logic; re : std_logic; @@ -108,17 +111,21 @@ begin icache_info <= "00" & to_unsigned(lg2(icache_line), 3) & to_unsigned(lg2(icache_size)-8, 3); dcache_info <= "00" & to_unsigned(lg2(dcache_line), 3) & to_unsigned(lg2(dcache_size)-8, 3); cop_pipe_ID.cs <= ir_en; + cop_pipe_ID.opc <= extract_opc(ir); cop_pipe_ID.rs <= extract_rs(ir); cop_pipe_ID.rd <= extract_rd(ir); + cop_pipe_ID.rt <= extract_rt(ir); cop_pipe_ID.func <= extract_func(ir); - cop_pipe_ID.re <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00000" else '0'; - cop_pipe_ID.we <= cop_pipe_ID.cs when cop_pipe_ID.rs = "00100" else '0'; + cop_pipe_ID.re <= cop_pipe_ID.cs when (cop_pipe_ID.opc = "111000" or 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.rs = "00100") else '0'; cop_EX_en <= exc_enable and not status_save; ctrl_out.RE <= status(25); ctrl_out.user_mode <= status(1); ctrl_out.int <= eflags.Int; - + + cop_pipe_ID.reg_ptr <= cop_pipe_ID.rd when cop_pipe_ID.opc = "010000" else cop_pipe_ID.rt; + im <= status(15 downto 8); cause <= bd & (30 downto 16 => '0') & ip & '0' & exc_code & "00"; @@ -307,44 +314,40 @@ cop_pipe: cop_pipe_EX.cs <= '0'; cop_pipe_EX.we <= '0'; cop_pipe_EX.re <= '0'; - else - if ctrl_in.sdu.stall_all = '0' then - cop_pipe_EX <= cop_pipe_ID; - end if; + elsif ctrl_in.sdu.stall_all = '0' then + cop_pipe_EX <= cop_pipe_ID; end if; end if; end process; cop_register_read: - process(clk) + process(cop_pipe_EX, BadVAddr, status, cause, epc, dcache_info, icache_info, test_reg) variable reg : word_t; begin - if rising_edge(clk) and cop_pipe_ID.re = '1' and ctrl_in.sdu.stall_all = '0' then - case cop_pipe_ID.rd is - when "01000" => -- BadVAddr - reg := BadVAddr; + case cop_pipe_EX.reg_ptr is + when "01000" => -- BadVAddr + reg := BadVAddr; - when "01100" => -- Status - reg := status; + when "01100" => -- Status + reg := status; - when "01101" => -- Cause - reg := cause; + when "01101" => -- Cause + reg := cause; - when "01110" => -- EPC (Exception Program Counter) - reg := epc; + when "01110" => -- EPC (Exception Program Counter) + reg := epc; - when "01111" => -- PRId (Processor Revision Register) - reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8); + when "01111" => -- PRId (Processor Revision Register) + reg := dcache_info & icache_info & X"02" & to_unsigned(REVISION ,8); - when "11111" => -- test_reg - reg := test_reg; + when "11111" => -- test_reg + reg := test_reg; - when others => - reg := (others => '-'); + when others => + reg := (others => '-'); - end case; - dout <= reg after 1 ns; - end if; + end case; + dout <= reg after 2 ns; end process; cop_we_gen: @@ -355,20 +358,20 @@ cop_we_gen: test_reg_we <= '0'; stat_reg_we <= '0'; ip_reg_we <= '0'; - else + elsif ctrl_in.sdu.stall_all = '0' then test_reg_we <= '0'; stat_reg_we <= '0'; ip_reg_we <= '0'; if (cop_EX_en and cop_pipe_EX.we) = '1' then - case cop_pipe_EX.rd is + case cop_pipe_EX.reg_ptr is when "01100" => stat_reg_we <= not status(1) or status(28); when "01101" => ip_reg_we <= not status(1) or status(28); when "11111" => - test_reg_we <= not status(1) or status(28); + test_reg_we <= '1'; -- not status(1) or status(28); when others => null; end case; @@ -384,7 +387,7 @@ cop_test_reg_write: if rising_edge(clk) then if rst = '1' then test_reg <= (others => '0'); - else --if ce = '1' then + elsif ctrl_in.sdu.WB_nop = '0' then if test_reg_we = '1' then test_reg <= din; end if; @@ -406,9 +409,11 @@ cop_status_reg_write: elsif status_rest = '1' then status(1 downto 0) <= status(3 downto 2); status(3 downto 2) <= status(5 downto 4); - elsif stat_reg_we = '1' then - status <= din; - end if; + elsif ctrl_in.sdu.WB_nop = '0' then + if stat_reg_we = '1' then + status <= din; + end if; + end if; end if; end if; end process;