From 81698e23910735d5c564d52e1113fc892cef091a Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Sun, 18 Aug 2013 18:56:42 +0000 Subject: [PATCH] - integrated ITLB and DTLB into pipeline. TLB queries come from pipeline if generic PIPE_ITLB or PIPE_DTLB is true. Cache query is then disabled. If generic PIPE_ITLB or PIPE_DTLB set to false queries come from cache. Piped TLB queries are piped translations with latency of two clocks. Piped translation allow physically indexed and physically tagged caches - reworked PC logic - prepared for individual BCUs in EX, MEM and WB stage - changed LTS and LTU generation in ALU 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/branches/BRANCH_MIPS_TLB@1015 cc03376c-175c-47c8-b038-4cd826a8556b --- lib/CPUs/MIPS/src/core/mips_alu.vhd | 19 +- lib/CPUs/MIPS/src/core/mips_bcu.vhd | 2 +- lib/CPUs/MIPS/src/core/mips_bui.vhd | 42 +++-- lib/CPUs/MIPS/src/core/mips_cop.vhd | 36 ++-- lib/CPUs/MIPS/src/core/mips_pipeline.vhd | 214 ++++++++++++++++++----- lib/CPUs/MIPS/src/core/mips_tlb.vhd | 66 ++++--- lib/CPUs/MIPS/src/core/mips_top.vhd | 36 ++-- lib/CPUs/MIPS/src/core/mips_types.vhd | 52 +++--- 8 files changed, 321 insertions(+), 146 deletions(-) diff --git a/lib/CPUs/MIPS/src/core/mips_alu.vhd b/lib/CPUs/MIPS/src/core/mips_alu.vhd index a64b5a4..7b5c6d8 100644 --- a/lib/CPUs/MIPS/src/core/mips_alu.vhd +++ b/lib/CPUs/MIPS/src/core/mips_alu.vhd @@ -56,21 +56,24 @@ architecture Behavioral of alu is -------------------------------------------------------------------------- begin - eq <= '1' when op1_in = op2_in else '0' after 3 ns; + eq <= '1' when op1_in = op2_in else '0' after 1 ns; sa <= op1_in(op1_in'left); sb <= op2_in(op2_in'left); sr <= sum_res(sum_res'left); - z <= '1' when op1_in = (data_width-1 downto 0 => '0') else '0' after 2 ns; + z <= '1' when op1_in = (data_width-1 downto 0 => '0') else '0'; flags.uvf <= (not ctrl.add) and ((sa and (not sb) and (not sr)) or ((not sa) and sb and sr)); flags.ovf <= ctrl.add and ((sa and sb and (not sr)) or ((not sa) and (not sb) and sr)); --- lts <= (not eq) and (((not c) and sa and sb) or (((not sr) and sa) or (sa and (not sb)) or (sr and (not sb)))); - lts <= not eq and ((not c and sa) or (not sb and sa) or (not sb and sr)); + +-- lts <= not eq and ((not c and sa) or (not sb and sa) or (not sb and sr)); + lts <= '1' when signed(op1_in) < signed(op2_in) else '0'; + +-- ltu <= (not eq) and (not c); + ltu <= '1' when op1_in < op2_in else '0'; - ltu <= (not eq) and (not c); - flags.lts <= lts; - flags.ltu <= ltu; - flags.c <= c; + flags.lts <= lts after 1 ns; + flags.ltu <= ltu after 1 ns; + flags.c <= c after 1 ns; -------------------------------------------------------------------------- proc_op_and: diff --git a/lib/CPUs/MIPS/src/core/mips_bcu.vhd b/lib/CPUs/MIPS/src/core/mips_bcu.vhd index 51b5ed7..1bb28bd 100644 --- a/lib/CPUs/MIPS/src/core/mips_bcu.vhd +++ b/lib/CPUs/MIPS/src/core/mips_bcu.vhd @@ -45,7 +45,7 @@ architecture Behavioral of bcu is -------------------------------------------------------------------------- begin - flags.eq <= '1' when op1_in = op2_in else '0' after 3 ns; + flags.eq <= '1' when ((op1_in xor op2_in) = (data_width-1 downto 0 => '0')) else '0' after 3 ns; flags.ltz <= op1_in(op1_in'left) after 1 ns; -------------------------------------------------------------------------- diff --git a/lib/CPUs/MIPS/src/core/mips_bui.vhd b/lib/CPUs/MIPS/src/core/mips_bui.vhd index 86ca064..d0af208 100644 --- a/lib/CPUs/MIPS/src/core/mips_bui.vhd +++ b/lib/CPUs/MIPS/src/core/mips_bui.vhd @@ -38,7 +38,9 @@ entity biu is DCACHE_SIZE : natural := 2048; -- words DCACHE_LINE : natural := 8; -- words WRITE_FIFO_SIZE : natural := 4; -- words - WITH_TLB : boolean := true + WITH_TLB : boolean := true; + ITLB_PIPE : boolean := false; + DTLB_PIPE : boolean := false ); Port ( @@ -137,6 +139,11 @@ architecture behavior of biu is signal icache_bus_gnt : std_logic; signal dcache_bus_gnt : std_logic; + signal i_cache_tlb_qry_out : tlb_query_in_t; + signal i_cache_tlb_qry_in : tlb_query_out_t; + signal d_cache_tlb_qry_out : tlb_query_in_t; + signal d_cache_tlb_qry_in : tlb_query_out_t; + begin @@ -145,8 +152,8 @@ begin imem_rdy <= i_cache_rdy; dmem_rdy <= d_cache_rdy; - ctrl_out.itlb <= i_tlb_ctrl_out; - ctrl_out.dtlb <= d_tlb_ctrl_out; + ctrl_out.itlb_ctrl <= i_tlb_ctrl_out; + ctrl_out.dtlb_ctrl <= d_tlb_ctrl_out; biu_busy_state: @@ -207,8 +214,9 @@ inst_i_tlb : entity work.tlb GENERIC MAP ( NUM_ENTRIES => TLB_NUM_ENTRIES, - CACHE_KSEG1 => false, - USE_TLB => WITH_TLB + CACHE_KSEG1 => false, + USE_TLB => WITH_TLB, + REGISTERED_OUTPUT => ITLB_PIPE ) PORT MAP ( @@ -227,8 +235,10 @@ inst_i_tlb : entity work.tlb ); - i_tlb_ctrl_in <= ctrl_in.itlb; - + i_tlb_ctrl_in <= ctrl_in.itlb_ctrl; + i_tlb_qry_in <= ctrl_in.itlb_qry when ITLB_PIPE else i_cache_tlb_qry_out; + i_cache_tlb_qry_in <= i_tlb_qry_out; + inst_icache: entity work.icache GENERIC MAP ( @@ -248,8 +258,8 @@ inst_icache: entity work.icache -- Cache control ctrl_in => ctrl_in.icache, - tlb_query_in => i_tlb_qry_out, - tlb_query_out => i_tlb_qry_in, + tlb_query_in => i_cache_tlb_qry_in, + tlb_query_out => i_cache_tlb_qry_out, -- busmaster data bus_din => bus_dout, @@ -270,7 +280,8 @@ inst_d_tlb : entity work.tlb ( NUM_ENTRIES => TLB_NUM_ENTRIES, CACHE_KSEG1 => false, - USE_TLB => WITH_TLB + USE_TLB => WITH_TLB, + REGISTERED_OUTPUT => DTLB_PIPE ) PORT MAP ( @@ -289,8 +300,10 @@ inst_d_tlb : entity work.tlb ); - d_tlb_ctrl_in <= ctrl_in.dtlb; - + d_tlb_ctrl_in <= ctrl_in.dtlb_ctrl; + d_tlb_qry_in <= ctrl_in.dtlb_qry when DTLB_PIPE else d_cache_tlb_qry_out; + d_cache_tlb_qry_in <= d_tlb_qry_out; + inst_dcache: entity work.dcache GENERIC MAP ( @@ -314,8 +327,8 @@ inst_dcache: entity work.dcache -- Cache control ctrl_in => ctrl_in.dcache, - tlb_query_in => d_tlb_qry_out, - tlb_query_out => d_tlb_qry_in, + tlb_query_in => d_cache_tlb_qry_in, + tlb_query_out => d_cache_tlb_qry_out, -- busmaster data bus_din => bus_dout, @@ -334,6 +347,7 @@ inst_dcache: entity work.dcache bus_cyc_complete => bus_cyc_complete ); + bus_state_next: process(clk) begin diff --git a/lib/CPUs/MIPS/src/core/mips_cop.vhd b/lib/CPUs/MIPS/src/core/mips_cop.vhd index 03c5389..1d701b1 100644 --- a/lib/CPUs/MIPS/src/core/mips_cop.vhd +++ b/lib/CPUs/MIPS/src/core/mips_cop.vhd @@ -236,24 +236,24 @@ architecture Behavioral of cop is begin -- Pass to pipeline TLB status - ctrl_out.pipe.ITLB <= ctrl_in.itlb.stat; - ctrl_out.pipe.DTLB <= ctrl_in.dtlb.stat; + ctrl_out.pipe.ITLB_stat <= ctrl_in.itlb_ctrl.stat; + ctrl_out.pipe.DTLB_stat <= ctrl_in.dtlb_ctrl.stat; -- I-TLB stuff - ctrl_out.itlb.entry_re <= '1'; -- cop_pipe_ID.TLBR and not tlb_sel; -- on tlbr - ctrl_out.itlb.entry_we <= (cop_pipe_EX.TLBWI or cop_pipe_EX.TLBWR) and not tlb_sel; -- on tlbwi or tlbwr - ctrl_out.itlb.entry_rd_idx <= index; - ctrl_out.itlb.entry_wr_idx <= random when cop_pipe_EX.TLBWR = '1' else index; - ctrl_out.itlb.entry_lo <= itlb_entry_lo; - ctrl_out.itlb.entry_hi <= itlb_entry_hi; + ctrl_out.itlb_ctrl.entry_re <= '1'; -- cop_pipe_ID.TLBR and not tlb_sel; -- on tlbr + ctrl_out.itlb_ctrl.entry_we <= (cop_pipe_EX.TLBWI or cop_pipe_EX.TLBWR) and not tlb_sel; -- on tlbwi or tlbwr + ctrl_out.itlb_ctrl.entry_rd_idx <= index; + ctrl_out.itlb_ctrl.entry_wr_idx <= random when cop_pipe_EX.TLBWR = '1' else index; + ctrl_out.itlb_ctrl.entry_lo <= itlb_entry_lo; + ctrl_out.itlb_ctrl.entry_hi <= itlb_entry_hi; -- D-TLB stuff - ctrl_out.dtlb.entry_re <= '1'; -- cop_pipe_ID.TLBR and tlb_sel; -- on tlbr - ctrl_out.dtlb.entry_we <= (cop_pipe_EX.TLBWI or cop_pipe_EX.TLBWR) and tlb_sel; -- on tlbwi or tlbwr - ctrl_out.dtlb.entry_rd_idx <= index; - ctrl_out.dtlb.entry_wr_idx <= random when cop_pipe_EX.TLBWR = '1' else index; - ctrl_out.dtlb.entry_lo <= dtlb_entry_lo; - ctrl_out.dtlb.entry_hi <= dtlb_entry_hi; + ctrl_out.dtlb_ctrl.entry_re <= '1'; -- cop_pipe_ID.TLBR and tlb_sel; -- on tlbr + ctrl_out.dtlb_ctrl.entry_we <= (cop_pipe_EX.TLBWI or cop_pipe_EX.TLBWR) and tlb_sel; -- on tlbwi or tlbwr + ctrl_out.dtlb_ctrl.entry_rd_idx <= index; + ctrl_out.dtlb_ctrl.entry_wr_idx <= random when cop_pipe_EX.TLBWR = '1' else index; + ctrl_out.dtlb_ctrl.entry_lo <= dtlb_entry_lo; + ctrl_out.dtlb_ctrl.entry_hi <= dtlb_entry_hi; cop_pipe_ID.cs <= ir_en; cop_pipe_ID.opc <= extract_opc(ir); @@ -741,7 +741,7 @@ itlb_entrylo_register: if rst = '1' then itlb_entry_lo <= to_tlb_entry_lo(to_unsigned(0, 32)); elsif cop_pipe_EX.TLBR = '1' then - itlb_entry_lo <= ctrl_in.itlb.entry_lo; + itlb_entry_lo <= ctrl_in.itlb_ctrl.entry_lo; elsif EX_reg_we(COP0_ENTRY_LO) = '1' and tlb_sel = '0' then itlb_entry_lo <= to_tlb_entry_lo(din); end if; @@ -758,7 +758,7 @@ itlb_entryhi_register: elsif itlb_exc = '1' then itlb_entry_hi <= to_tlb_entry_hi(itlb_entry_hi, regs.badvaddr); elsif cop_pipe_EX.TLBR = '1' then - itlb_entry_hi <= ctrl_in.itlb.entry_hi; + itlb_entry_hi <= ctrl_in.itlb_ctrl.entry_hi; elsif EX_reg_we(COP0_ENTRY_HI) = '1' and tlb_sel = '0' then itlb_entry_hi <= to_tlb_entry_hi(din); end if; @@ -773,7 +773,7 @@ dtlb_entrylo_register: if rst = '1' then dtlb_entry_lo <= to_tlb_entry_lo(to_unsigned(0, 32)); elsif cop_pipe_EX.TLBR = '1' then - dtlb_entry_lo <= ctrl_in.dtlb.entry_lo; + dtlb_entry_lo <= ctrl_in.dtlb_ctrl.entry_lo; elsif EX_reg_we(COP0_ENTRY_LO) = '1' and tlb_sel = '1' then dtlb_entry_lo <= to_tlb_entry_lo(din); end if; @@ -790,7 +790,7 @@ dtlb_entryhi_register: elsif dtlb_exc = '1' then dtlb_entry_hi <= to_tlb_entry_hi(dtlb_entry_hi, regs.badvaddr); elsif cop_pipe_EX.TLBR = '1' then - dtlb_entry_hi <= ctrl_in.dtlb.entry_hi; + dtlb_entry_hi <= ctrl_in.dtlb_ctrl.entry_hi; elsif EX_reg_we(COP0_ENTRY_HI) = '1' and tlb_sel = '1' then dtlb_entry_hi <= to_tlb_entry_hi(din); end if; diff --git a/lib/CPUs/MIPS/src/core/mips_pipeline.vhd b/lib/CPUs/MIPS/src/core/mips_pipeline.vhd index 07a35e9..4388ed5 100644 --- a/lib/CPUs/MIPS/src/core/mips_pipeline.vhd +++ b/lib/CPUs/MIPS/src/core/mips_pipeline.vhd @@ -173,7 +173,9 @@ architecture Behavioral of pipeline is signal stage_rst : unsigned(3 downto 0); signal pipe_rst : STD_LOGIC; - signal pc : pc_t; + signal pc : pc_t; + signal pc_alt : pc_t; + signal bcu_flags_alt : bcu_flags_t; -------------------------------------------------------------------------- begin @@ -208,7 +210,7 @@ begin ctrl_out.exc_ack <= '1'; cop_ir <= ID_stage.IR; cop_ir_en <= ID_stage.ctrl.cop_instr_en; - cop_dout <= EX_stage.reg_b; -- dmem_din when MEM_stage.ctrl.dmem_en = '1' else MEM_stage.ex_result; + cop_dout <= EX_stage.reg_b_in; -- dmem_din when MEM_stage.ctrl.dmem_en = '1' else MEM_stage.ex_result; -------------------------------------------------------------------------- -- Muldiv @@ -220,7 +222,7 @@ inst_muldiv: muldiv clk => clk, hilo_we => EX_stage.ctrl.mul_hilo_we, din_hi => EX_stage.reg_a, - din_lo => EX_stage.reg_b, + din_lo => EX_stage.reg_b_in, mul_divn => EX_stage.ctrl.mul_mul_divn, start => EX_stage.ctrl.mul_start, s_un => EX_stage.ctrl.mul_s_un, @@ -232,7 +234,7 @@ inst_muldiv: muldiv -------------------------------------------------------------------------- -- IF stage -------------------------------------------------------------------------- - imem_addr <= pc.curr; + imem_addr <= pc_alt.curr; pipe_rst <= stage_rst(0); @@ -326,6 +328,128 @@ proc_stage_branch: end if; end process; +-------------------------------------------------------------------------- +-- alt pc +-------------------------------------------------------------------------- +ctrl_out.itlb_qry.vld2 <= cpu_run and not (sdu.mul_dep or sdu.dmem_dep or ctrl_in.exc_commit) and imem_rdy; +ctrl_out.itlb_qry.vld <= '1'; +ctrl_out.itlb_qry.write <= '0'; +ctrl_out.itlb_qry.vaddr <= pc_alt.nxt; + +inst_bcu_alt_ID: bcu + GENERIC MAP + ( + data_width => word_t'length + ) + PORT MAP + ( + op1_in => ID_stage.reg_a, + op2_in => ID_stage.reg_b, + flags => ID_stage.bcu_flags + ); + +inst_bcu_alt_EX: bcu + GENERIC MAP + ( + data_width => word_t'length + ) + PORT MAP + ( + op1_in => EX_stage.reg_a, + op2_in => EX_stage.reg_b, + flags => EX_stage.bcu_flags + ); + +inst_bcu_alt_MEM: bcu + GENERIC MAP + ( + data_width => word_t'length + ) + PORT MAP + ( + op1_in => MEM_stage.reg_a, + op2_in => MEM_stage.reg_b, + flags => MEM_stage.bcu_flags + ); + +inst_bcu_alt_WB: bcu + GENERIC MAP + ( + data_width => word_t'length + ) + PORT MAP + ( + op1_in => WB_stage.reg_a, + op2_in => WB_stage.reg_b, + flags => WB_stage.bcu_flags + ); + +proc_stage_branch_alt: + process(ID_stage) + begin + pc_alt.branch_take <= '0'; + if ID_stage.ctrl.branch = '1' then + + case ID_stage.ctrl.bc_src is + + when bc_eq_ne => + pc_alt.branch_take <= ID_stage.ctrl.bc_not xor ID_stage.bcu_flags.eq; + + when bc_lez_gtz => + pc_alt.branch_take <= ID_stage.ctrl.bc_not xor (ID_stage.bcu_flags.eq or ID_stage.bcu_flags.ltz); + + when bc_ltz_gez => + pc_alt.branch_take <= ID_stage.ctrl.bc_not xor ID_stage.bcu_flags.ltz; + + when others => null; + end case; + end if; + end process; + +proc_stage_pc_next_alt: + process(ctrl_in, sdu, ID_stage, pc_alt) + begin + pc_alt.nxt <= pc_alt.curr; + if sdu.ID_stall = '0' then + pc_alt.nxt <= ctrl_in.exc_vec; + if ctrl_in.exc_inject = '0' then + pc_alt.nxt <= pc_alt.plus4; + if ID_stage.ctrl.jump = '1' then + pc_alt.nxt <= ID_stage.jimm32; + elsif ID_stage.ctrl.jump_long = '1' then + pc_alt.nxt <= ID_stage.reg_a; + elsif pc_alt.branch_take = '1' then + pc_alt.nxt <= pc_alt.pc_branch; + end if; + end if; + end if; + end process; + +proc_stage_pc_plus_4_alt: + process(clk_2) + begin + if rising_edge(clk_2) then + if rst = '1' then + pc_alt.plus4 <= ctrl_in.exc_vec; + elsif cpu_run = '1' then + pc_alt.plus4 <= pc_alt.curr + 4; + pc_alt.pc_branch <= pc_alt.curr + ID_stage.bimm18; + end if; + end if; + end process; + +proc_stage_pc_reg_alt: + process(clk_1) + begin + if rising_edge(clk_1) then + if rst = '1' then + pc_alt.curr <= ctrl_in.exc_vec; + elsif cpu_run = '1' and (sdu.ID_stall = '0' or ctrl_in.exc_inject = '1') then + pc_alt.curr <= pc_alt.nxt; + end if; + end if; + end process; + -------------------------------------------------------------------------- -- ID stage -------------------------------------------------------------------------- @@ -350,9 +474,9 @@ proc_ID_except: ID_stage.events <= events_clr; ID_stage.events.inst_load_err <= not ctrl_in.exc_pending and (pc.nxt(1) or pc.nxt(0)); ID_stage.events.inst_priv_addr <= not ctrl_in.exc_pending and (pc.nxt(word_t'left) and ctrl_in.user_mode); - ID_stage.events.ITLB_LOAD <= ctrl_in.ITLB.exc_vld and ctrl_in.ITLB.exc_miss and not ctrl_in.ITLB.write; - ID_stage.events.ITLB_STORE <= ctrl_in.ITLB.exc_vld and ctrl_in.ITLB.exc_miss and ctrl_in.ITLB.write; - ID_stage.events.ITLB_MOD <= ctrl_in.ITLB.exc_vld and ctrl_in.ITLB.exc_dirty; + ID_stage.events.ITLB_LOAD <= ctrl_in.ITLB_stat.vld and ctrl_in.ITLB_stat.exc_miss and not ctrl_in.ITLB_stat.write; + ID_stage.events.ITLB_STORE <= ctrl_in.ITLB_stat.vld and ctrl_in.ITLB_stat.exc_miss and ctrl_in.ITLB_stat.write; + ID_stage.events.ITLB_MOD <= ctrl_in.ITLB_stat.vld and ctrl_in.ITLB_stat.exc_dirty; end process; proc_stage_hdu: @@ -388,36 +512,31 @@ proc_stage_fwd_a: begin data := reg_a; if hdu.alu_fwd_a_ex then - data := EX_stage.result; + data := EX_stage.reg_b; elsif hdu.alu_fwd_a_mem then - data := MEM_stage.reg_data; + data := MEM_stage.reg_b; elsif hdu.alu_fwd_a_wb then - data := WB_stage.reg_data; + data := WB_stage.reg_b; end if; - for i in 0 to 31 loop - if data(i) = '1' then - ID_stage.reg_a(i) <= '1' after 1 ns; - else - ID_stage.reg_a(i) <= '0' after 1 ns; - end if; - end loop; + ID_stage.reg_a <= to_mips_01(data) after 1 ns; end process; proc_stage_fwd_b: - process(reg_b, hdu, EX_stage, MEM_stage, WB_stage) + process(reg_b, hdu, EX_stage, MEM_stage, WB_stage, bcu_flags_alt) variable data : word_t; begin data := reg_b; if hdu.alu_fwd_b_ex then - data := EX_stage.result; + data := EX_stage.reg_b; elsif hdu.alu_fwd_b_mem then - data := MEM_stage.reg_data; + data := MEM_stage.reg_b; elsif hdu.alu_fwd_b_wb then - data := WB_stage.reg_data; + data := WB_stage.reg_b; end if; - ID_stage.reg_b <= to_mips_01(data) after 1 ns; + + ID_stage.reg_b <= to_mips_01(data) after 1 ns; end process; @@ -459,7 +578,7 @@ inst_reg_dual: reg_dual we => WB_stage.reg_we, en => '1', wptr => WB_stage.reg_wptr, - din => WB_stage.reg_data, + din => WB_stage.reg_b, rptr_a => ID_stage.reg_a_rptr, rptr_b => ID_stage.reg_b_rptr, dout_a => reg_a, @@ -471,7 +590,7 @@ inst_reg_dual: reg_dual -------------------------------------------------------------------------- EX_stage.reg_a_rptr <= extract_rs(EX_stage.IR); EX_stage.reg_b_rptr <= extract_rt(EX_stage.IR); - EX_stage.result <= alu_result when EX_stage.ctrl.mul_access = '0' else mul_result; + EX_stage.reg_b <= alu_result when EX_stage.ctrl.mul_access = '0' else mul_result; proc_stage_ID_EX_1: process(clk_1) @@ -492,7 +611,7 @@ proc_stage_ID_EX_1: EX_stage.va <= ID_stage.va; EX_stage.reg_a <= ID_stage.reg_a; - EX_stage.reg_b <= ID_stage.reg_b; + EX_stage.reg_b_in <= ID_stage.reg_b; EX_stage.events_in <= ID_stage.events; EX_stage.ctrl <= ID_stage.ctrl; EX_stage.reg_write <= ID_stage.reg_write; @@ -535,23 +654,23 @@ proc_stage_EX_mem_except: begin if rising_edge(clk_1) then if pipe_rst = '1' then - dmem_en <= '0'; + EX_stage.dmem_en <= '0'; elsif sdu.EX_stall = '0' then EX_events_mem <= events_clr; - dmem_en <= '0'; + EX_stage.dmem_en <= '0'; if ID_stage.ctrl.dmem_en = '1' then - dmem_en <= '1'; + EX_stage.dmem_en <= '1'; if ID_stage.ctrl.except_en = '1' then if ID_stage.ctrl.word2_en = '1' then if ID_stage.va(0) = '1' then EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we; EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we; - dmem_en <= '0'; + EX_stage.dmem_en <= '0'; end if; elsif ID_stage.va(1 downto 0) /= "00" then EX_events_mem.data_load_err <= not ID_stage.ctrl.dmem_we; EX_events_mem.data_store_err <= ID_stage.ctrl.dmem_we; - dmem_en <= '0'; + EX_stage.dmem_en <= '0'; end if; end if; end if; @@ -559,8 +678,10 @@ proc_stage_EX_mem_except: end if; end process; - ctrl_out.dtlb_va <= ID_stage.va; - ctrl_out.dtlb_en <= ID_stage.ctrl.dmem_en; +ctrl_out.dtlb_qry.vld2 <= EX_stage.dmem_en and dmem_rdy; +ctrl_out.dtlb_qry.vld <= ID_stage.ctrl.dmem_en; +ctrl_out.dtlb_qry.write <= ID_stage.ctrl.dmem_we; +ctrl_out.dtlb_qry.vaddr <= ID_stage.va; proc_stage_DMEM_ADDR: process(clk_1) @@ -579,8 +700,9 @@ proc_stage_DMEM_ADDR: end if; end if; end process; - dmem_src <= cop_din when EX_stage.ctrl.cop_instr_en = '1' else EX_stage.reg_b; + dmem_src <= cop_din when EX_stage.ctrl.cop_instr_en = '1' else EX_stage.reg_b_in; dmem_be <= store_be(EX_stage.pa_off, EX_stage.ctrl.dmem_en, EX_stage.ctrl.word2_en, EX_stage.ctrl.word4_en, EX_stage.ctrl.align_left, EX_stage.ctrl.shift_byp) after 1 ns; + dmem_en <= EX_stage.dmem_en; dmem_we <= EX_stage.ctrl.dmem_we; dmem_dout <= store_shift(dmem_src, EX_stage.pa_off, EX_stage.ctrl.shift_offset, EX_stage.ctrl.shift_byp) after 1ns; dmem_addr <= EX_stage.va; @@ -699,7 +821,7 @@ inst_shifter: shifter PORT MAP ( shift_ctrl => EX_stage.shift_ctrl, - din => EX_stage.reg_b, + din => EX_stage.reg_b_in, dout => EX_stage.alu_op2_s ); @@ -745,6 +867,8 @@ proc_stage_MEM_n: MEM_stage.events_in <= events_clr; elsif sdu.MEM_stall = '0' then MEM_stage.nop <= sdu.MEM_nop; + MEM_stage.reg_a <= EX_stage.reg_a; + MEM_stage.reg_b_in <= EX_stage.reg_b; MEM_stage.op <= EX_stage.op; MEM_stage.epc <= EX_stage.epc; MEM_stage.pcn <= EX_stage.pcn; @@ -758,17 +882,17 @@ proc_stage_MEM_n: MEM_stage.reg_wptr <= EX_stage.reg_wptr; if MEM_stage.reg_wptr = EX_stage.reg_wptr then if (EX_stage.ctrl.dmem_en and MEM_stage.ctrl.dmem_en) = '1' then - MEM_stage.ex_result <= MEM_stage.reg_data; + MEM_stage.reg_b_in <= MEM_stage.reg_b; end if; else - MEM_stage.ex_result <= EX_stage.reg_b; + MEM_stage.reg_b_in <= EX_stage.reg_b_in; end if; if EX_stage.ctrl.cop_instr_en = '1' then if EX_stage.ctrl.cop_read = '1' then - MEM_stage.ex_result <= cop_din; + MEM_stage.reg_b_in <= cop_din; end if; elsif EX_stage.ctrl.dmem_en = '0' then - MEM_stage.ex_result <= EX_stage.result; + MEM_stage.reg_b_in <= EX_stage.reg_b; end if; if sdu.MEM_nop = '1' then MEM_stage.reg_we <= '0'; @@ -785,7 +909,7 @@ proc_stage_MEM_mux: variable data : word_t; variable be : unsigned(3 downto 0); begin - data := MEM_stage.ex_result; + data := MEM_stage.reg_b_in; if MEM_stage.ctrl.reg_link = '1' then data := MEM_stage.epc + 8; elsif MEM_stage.ctrl.dmem_en = '1' then @@ -805,7 +929,7 @@ proc_stage_MEM_mux: data(31 downto 24) := temp2(31 downto 24); end if; end if; - MEM_stage.reg_data <= data after 1 ns; + MEM_stage.reg_b <= data after 1 ns; end process; @@ -815,9 +939,9 @@ proc_stage_MEM_except: MEM_stage.events <= MEM_stage.events_in; MEM_stage.events.Int <= ctrl_in.int; MEM_stage.events.NMI <= ctrl_in.NMI; - MEM_stage.events.DTLB_LOAD <= ctrl_in.DTLB.exc_vld and ctrl_in.DTLB.exc_miss and not ctrl_in.DTLB.write; - MEM_stage.events.DTLB_STORE <= ctrl_in.DTLB.exc_vld and ctrl_in.DTLB.exc_miss and ctrl_in.DTLB.write; - MEM_stage.events.DTLB_MOD <= ctrl_in.DTLB.exc_vld and ctrl_in.DTLB.exc_dirty; + MEM_stage.events.DTLB_LOAD <= ctrl_in.DTLB_stat.vld and ctrl_in.DTLB_stat.exc_miss and not ctrl_in.DTLB_stat.write; + MEM_stage.events.DTLB_STORE <= ctrl_in.DTLB_stat.vld and ctrl_in.DTLB_stat.exc_miss and ctrl_in.DTLB_stat.write; + MEM_stage.events.DTLB_MOD <= ctrl_in.DTLB_stat.vld and ctrl_in.DTLB_stat.exc_dirty; end process; MEM_stage.exc <= event_is_active(MEM_stage.events); @@ -840,8 +964,9 @@ proc_stage_WB_p: WB_stage.exc <= '0'; elsif sdu.WB_stall = '0' then WB_stage.nop <= sdu.WB_nop; + WB_stage.reg_a <= MEM_stage.reg_a; + WB_stage.reg_b <= MEM_stage.reg_b; WB_stage.op <= MEM_stage.op; - WB_stage.epc_last <= WB_stage.epc; WB_stage.epc <= MEM_stage.epc; branch_delay := MEM_stage.ctrl.branch or MEM_stage.ctrl.jump or MEM_stage.ctrl.jump_long; -- Todo: works WB_stage.bd <= branch_delay; @@ -849,7 +974,6 @@ proc_stage_WB_p: WB_stage.exc <= MEM_stage.exc; WB_stage.reg_we <= MEM_stage.reg_we; WB_stage.reg_wptr <= MEM_stage.reg_wptr; - WB_stage.reg_data <= MEM_stage.reg_data; WB_stage.events <= MEM_stage.events; if sdu.stall_all = '0' then if MEM_stage.exc = '1' and WB_stage.exc = '0' then diff --git a/lib/CPUs/MIPS/src/core/mips_tlb.vhd b/lib/CPUs/MIPS/src/core/mips_tlb.vhd index 7fae13d..518fbe8 100644 --- a/lib/CPUs/MIPS/src/core/mips_tlb.vhd +++ b/lib/CPUs/MIPS/src/core/mips_tlb.vhd @@ -12,7 +12,8 @@ ENTITY tlb IS NUM_ENTRIES : natural := 8; CACHE_KSEG1 : boolean := false; TRANSLATE_KSEG0_1 : boolean := true; - USE_TLB : boolean := false + USE_TLB : boolean := false; + REGISTERED_OUTPUT : boolean := false ); Port ( @@ -49,10 +50,12 @@ ARCHITECTURE behavior OF tlb IS signal entry_lo_res : tlb_entry_lo_t; signal qry_res : tlb_query_out_t; signal stat_res : tlb_status_t; + signal qry_res_r : tlb_query_out_t; + signal stat_res_r : tlb_status_t; signal pa : word_t; signal hit : STD_LOGIC; - signal valid : STD_LOGIC; + signal vld_r : STD_LOGIC; signal cam_rdy : STD_LOGIC; signal cam_hit_vld : STD_LOGIC; @@ -151,7 +154,7 @@ begin clk_rd <= clk; rdy <= cam_rdy; - stat_res.exc_vld <= valid; + stat_res.vld <= vld_r; stat_res.exc_miss <= not hit; stat_res.exc_dirty <= hit and qry_res.flags.D and query_in.write; stat_res.write <= query_in.write; @@ -162,11 +165,11 @@ begin qry_res.flags.D <= entry_lo_res.D; qry_res.flags.V <= entry_lo_res.V; qry_res.exc <= stat_res.exc_miss or stat_res.exc_dirty; - qry_res.vld <= valid; + qry_res.vld <= vld_r; qry_res.idx <= (hit_umc or hit_umuc) & reg_qry_entry_lo_addr; - query_out <= qry_res; - ctrl_out.stat <= stat_res; + query_out <= qry_res_r when REGISTERED_OUTPUT else qry_res; + ctrl_out.stat <= stat_res_r when REGISTERED_OUTPUT else stat_res; pa <= entry_lo_res.PFN & vaddr_reg(lg2(TLB_PAGE_SIZE)-1 downto 0); @@ -180,6 +183,37 @@ begin ctrl_out.entry_hi <= to_entry_hi(to_mips_01(reg_ctrl_entry_hi_dout)); reg_ctrl_entry_hi_din <= to_reg_hi(ctrl_in.entry_hi); +registered_ctrl_out: + process(clk) + begin + if rising_edge(clk) then + if query_in.vld = '1' then + vaddr_reg <= query_in.vaddr; + end if; + vld_r <= query_in.vld; + if ce = '1' then + if ctrl_in.entry_re = '1' then + + ctrl_out.entry_lo <= to_entry_lo(to_mips_01(reg_ctrl_entry_lo_dout)); + ctrl_out.entry_vld <= '1'; + end if; + end if; + end if; + end process; + +registered_qry_out: + process(clk) + begin + if rising_edge(clk) then + qry_res_r.vld <= '0'; + stat_res_r.vld <= '0'; + if query_in.vld2 = '1' then + qry_res_r <= qry_res; + stat_res_r <= stat_res; + end if; + end if; + end process; + inst_reg_entry_lo: entity work.reg_dual GENERIC MAP ( @@ -326,25 +360,5 @@ if USE_TLB = false generate end process; end generate; -registered_output: - process(clk) - begin - if rising_edge(clk) then - if query_in.vld = '1' then - vaddr_reg <= query_in.vaddr; - end if; - valid <= query_in.vld; - if ce = '1' then - if ctrl_in.entry_re = '1' then - - ctrl_out.entry_lo <= to_entry_lo(to_mips_01(reg_ctrl_entry_lo_dout)); - ctrl_out.entry_vld <= '1'; - end if; - end if; - end if; - end process; - - - ------------------------------------------------------------------ end behavior; diff --git a/lib/CPUs/MIPS/src/core/mips_top.vhd b/lib/CPUs/MIPS/src/core/mips_top.vhd index 984f6a4..25bd9a1 100644 --- a/lib/CPUs/MIPS/src/core/mips_top.vhd +++ b/lib/CPUs/MIPS/src/core/mips_top.vhd @@ -31,11 +31,13 @@ use work.mips_types.all; entity mips_top is Generic ( - icache_size : natural := 8192; -- words - icache_line : natural := 8; -- words - dcache_size : natural := 4096; -- words - dcache_line : natural := 8; -- words - WITH_TLB : boolean := true + icache_size : natural := 8192; -- words + icache_line : natural := 8; -- words + dcache_size : natural := 4096; -- words + dcache_line : natural := 8; -- words + WITH_TLB : boolean := true; + ITLB_PIPE : boolean := true; + DTLB_PIPE : boolean := true ); Port ( @@ -162,7 +164,9 @@ architecture rtl of mips_top is dcache_size : natural; dcache_line : natural; WRITE_FIFO_SIZE : natural; - WITH_TLB : boolean + WITH_TLB : boolean; + ITLB_PIPE : boolean; + DTLB_PIPE : boolean ); PORT ( @@ -281,9 +285,9 @@ inst_cop: cop din => pipe_cop_dout ); - cop0_ctrl_in.pipe <= pipe_ctrl_out; - cop0_ctrl_in.itlb <= biu_ctrl_out.itlb; - cop0_ctrl_in.dtlb <= biu_ctrl_out.dtlb; + cop0_ctrl_in.pipe <= pipe_ctrl_out; + cop0_ctrl_in.itlb_ctrl <= biu_ctrl_out.itlb_ctrl; + cop0_ctrl_in.dtlb_ctrl <= biu_ctrl_out.dtlb_ctrl; inst_biu: biu GENERIC MAP @@ -293,7 +297,9 @@ inst_biu: biu dcache_size => dcache_size, -- words dcache_line => dcache_line, -- words WRITE_FIFO_SIZE => 4, - WITH_TLB => WITH_TLB + WITH_TLB => WITH_TLB, + ITLB_PIPE => ITLB_PIPE, + DTLB_PIPE => DTLB_PIPE ) PORT MAP ( @@ -333,10 +339,12 @@ inst_biu: biu ); - biu_ctrl_in.dcache <= cop0_ctrl_out.dcache; - biu_ctrl_in.icache <= cop0_ctrl_out.icache; - biu_ctrl_in.dtlb <= cop0_ctrl_out.dtlb; - biu_ctrl_in.itlb <= cop0_ctrl_out.itlb; + biu_ctrl_in.dcache <= cop0_ctrl_out.dcache; + biu_ctrl_in.icache <= cop0_ctrl_out.icache; + biu_ctrl_in.dtlb_ctrl <= cop0_ctrl_out.dtlb_ctrl; + biu_ctrl_in.itlb_ctrl <= cop0_ctrl_out.itlb_ctrl; + biu_ctrl_in.dtlb_qry <= pipe_ctrl_out.dtlb_qry; + biu_ctrl_in.itlb_qry <= pipe_ctrl_out.itlb_qry; ------------------------------------------- -- debug diff --git a/lib/CPUs/MIPS/src/core/mips_types.vhd b/lib/CPUs/MIPS/src/core/mips_types.vhd index 86112d4..df30cad 100644 --- a/lib/CPUs/MIPS/src/core/mips_types.vhd +++ b/lib/CPUs/MIPS/src/core/mips_types.vhd @@ -178,6 +178,7 @@ package mips_types is nxt : word_t; pc_branch : word_t; branch_take : std_logic; + plus4 : word_t; end record; type alu_outsel_t is @@ -302,6 +303,7 @@ package mips_types is type tlb_query_in_t is record vld : std_logic; + vld2 : std_logic; write : std_logic; vaddr : word_t; idx : unsigned (lg2(TLB_NUM_ENTRIES) downto 0); @@ -317,7 +319,7 @@ package mips_types is end record; type tlb_status_t is record - exc_vld : std_logic; + vld : std_logic; exc_miss : std_logic; exc_dirty : std_logic; write : std_logic; @@ -341,17 +343,19 @@ package mips_types is end record; type biu_ctrl_in_t is record - itlb : tlb_ctrl_in_t; - dtlb : tlb_ctrl_in_t; + itlb_ctrl : tlb_ctrl_in_t; + dtlb_ctrl : tlb_ctrl_in_t; icache : cache_ctrl_t; dcache : cache_ctrl_t; - dtlb_va : word_t; - dtlb_en : STD_LOGIC; + itlb_qry : tlb_query_in_t; + dtlb_qry : tlb_query_in_t; end record; type biu_ctrl_out_t is record - itlb : tlb_ctrl_out_t; - dtlb : tlb_ctrl_out_t; + itlb_ctrl : tlb_ctrl_out_t; + dtlb_ctrl : tlb_ctrl_out_t; + itlb_qry : tlb_query_out_t; + dtlb_qry : tlb_query_out_t; end record; type pipe_ctrl_in_t is record @@ -364,8 +368,10 @@ package mips_types is NMI : STD_LOGIC; int : STD_LOGIC; exc_vec : word_t; - ITLB : tlb_status_t; - DTLB : tlb_status_t; + ITLB_stat : tlb_status_t; + DTLB_stat : tlb_status_t; + itlb_qry : tlb_query_out_t; + dtlb_qry : tlb_query_out_t; end record; type pipe_ctrl_out_t is record @@ -377,20 +383,20 @@ package mips_types is dmem_addr : word_t; exc_req : STD_LOGIC; exc_ack : STD_LOGIC; - dtlb_va : word_t; - dtlb_en : STD_LOGIC; + itlb_qry : tlb_query_in_t; + dtlb_qry : tlb_query_in_t; end record; type cop0_ctrl_in_t is record pipe : pipe_ctrl_out_t; - itlb : tlb_ctrl_out_t; - dtlb : tlb_ctrl_out_t; + itlb_ctrl : tlb_ctrl_out_t; + dtlb_ctrl : tlb_ctrl_out_t; end record; type cop0_ctrl_out_t is record pipe : pipe_ctrl_in_t; - itlb : tlb_ctrl_in_t; - dtlb : tlb_ctrl_in_t; + itlb_ctrl : tlb_ctrl_in_t; + dtlb_ctrl : tlb_ctrl_in_t; icache : cache_ctrl_t; dcache : cache_ctrl_t; end record; @@ -467,6 +473,7 @@ package mips_types is reg_a : word_t; reg_b : word_t; events : event_t; + bcu_flags : bcu_flags_t; end record; type EX_t is record @@ -478,22 +485,24 @@ package mips_types is pcn : word_t; reg_a : word_t; reg_b : word_t; + reg_b_in : word_t; ctrl : ctrl_lines_t; shift_ctrl : shift_ctrl_t; alu_op1 : word_t; alu_op2 : word_t; alu_op2_s : word_t; alu_flags : alu_flags_t; - result : word_t; reg_write : STD_LOGIC; reg_we : STD_LOGIC; reg_wptr : reg_ptr_t; reg_a_rptr : reg_ptr_t; reg_b_rptr : reg_ptr_t; va : word_t; + dmem_en : STD_LOGIC; pa_off : unsigned(1 downto 0); events_in : event_t; events : event_t; + bcu_flags : bcu_flags_t; end record; type MEM_t is record @@ -502,21 +511,24 @@ package mips_types is op : op_t; epc : word_t; pcn : word_t; + reg_a : word_t; + reg_b : word_t; + reg_b_in : word_t; ctrl : ctrl_lines_t; - ex_result : word_t; reg_wptr : reg_ptr_t; reg_we : STD_LOGIC; - reg_data : word_t; va : word_t; pa_off : unsigned(1 downto 0); events_in : event_t; events : event_t; + bcu_flags : bcu_flags_t; end record; type WB_t is record nop : STD_LOGIC; epc : word_t; - epc_last : word_t; + reg_a : word_t; + reg_b : word_t; bd : STD_LOGIC; exc : std_logic; exc_last : std_logic; @@ -524,8 +536,8 @@ package mips_types is op : op_t; reg_wptr : reg_ptr_t; reg_we : STD_LOGIC; - reg_data : word_t; va : word_t; + bcu_flags : bcu_flags_t; end record;