📄 prefetch_buffer_gti.vhd
字号:
end if; end process ibuffer_DFF; end generate The_IBuffers; ----------------------------------------------------------------------------- -- Handling which buffer to load on the next incoming instruction fetch ----------------------------------------------------------------------------- Handle_ib_ibuf_en : process (Clk) is begin -- process Handle_ib_ibuf_en if Clk'event and Clk = '1' then -- rising clock edge if jump_load then -- synchronous reset (active true) ib_ibuf_en <= ex_ibuf_en; else if (((valid_fetch_i = '1'))) then ib_ibuf_en(ib_ibuf_en'left+1 to ib_ibuf_en'right) <= ib_ibuf_en(ib_ibuf_en'left to ib_ibuf_en'right - 1); ib_ibuf_en(ib_ibuf_en'left) <= ib_ibuf_en(ib_ibuf_en'right); end if; end if; end if; end process Handle_ib_ibuf_en; ----------------------------------------------------------------------------- -- Handling which buffer to select for the instruction in the OF stage -- Normal the next register is just an increment of the current value -- On jumps the next value is ex_buf_sel -- The value of the of_ibuf_sel can only change when of_piperun is active ----------------------------------------------------------------------------- Handle_of_ibuf_sel : process (Clk) is begin -- process Handle_of_ibuf_sel if Clk'event and Clk = '1' then -- rising clock edge if (reset) then of_ibuf_sel <= (others => '0'); elsif (OF_PipeRun = '1') then if (jump_load_i) then of_ibuf_sel <= ex_ibuf_sel; else of_ibuf_sel <= std_logic_vector(unsigned(of_ibuf_sel) + 1); end if; elsif (jump_load and not ex_branch_with_delayslot) then of_ibuf_sel <= ex_ibuf_sel; end if; end if; end process Handle_of_ibuf_sel; ----------------------------------------------------------------------------- -- Need to hold the jump_load condition until the current instruction in the -- OF stage has moved into the EX stage (of_piperun active) ----------------------------------------------------------------------------- Jump_load_Hold_DFF : process (Clk) is begin -- process Jump_load_Hold_DFF if Clk'event and Clk = '1' then -- rising clock edge if (reset) then jump_load_hold <= false; elsif (OF_PipeRun = '1') then jump_load_hold <= false; elsif (jump_load and ex_branch_with_delayslot) then jump_load_hold <= true; end if; end if; end process Jump_load_Hold_DFF; -- To maintain a correct jump_load_i even if the rest of the pipeline is -- moving except the of stage jump_load_i <= jump_load or jump_load_hold; ----------------------------------------------------------------------------- -- Creating the new ex_ibuf_sel and ex_ibuf_en that will be used on a branch -- If there is a branch with delay slot the target address instruction will be -- loaded after the delay slot instruction position. -- With branches without delayslot the branch target address instruction will be -- loaded at the position after the branch instruction posistion ----------------------------------------------------------------------------- Branch_Handling : process (Clk) is variable sel_tmp : std_logic_vector(0 to 1); begin -- process Branch_Handling if Clk'event and Clk = '1' then -- rising clock edge if Reset then -- synchronous reset (active high) ex_ibuf_sel <= "00"; ex_ibuf_en <= (others => '0'); ex_ibuf_en(ex_ibuf_en'left) <= '1'; elsif (OF_PipeRun = '1') then if (of_branch_with_delayslot) then sel_tmp := std_logic_vector((unsigned(of_ibuf_sel) + 2) mod 4); else sel_tmp := std_logic_vector((unsigned(of_ibuf_sel) + 1) mod 4); end if; ex_ibuf_sel <= sel_tmp; ex_ibuf_en <= (others => '0'); ex_ibuf_en(to_integer(unsigned(sel_tmp))) <= '1'; end if; end if; end process Branch_Handling; EX_Branch_With_Delayslot_DFF : process (Clk) is begin -- process EX_Branch_With_Delayslot_DFF if Clk'event and Clk = '1' then -- rising clock edge if Reset or WB_Dbg_exception then -- synchronous reset (active high) ex_branch_with_delayslot_i <= false; elsif (OF_PipeRun = '1') then ex_branch_with_delayslot_i <= of_branch_with_delayslot; end if; end if; end process EX_Branch_With_Delayslot_DFF; ex_branch_with_delayslot <= ex_branch_with_delayslot_i and not WB_Dbg_exception; Valid_Fetch <= valid_fetch_i; -- Share the booleans so that we do not need to make these resolved booleans OF_Valid <= (of_Valid_I = '1'); Buffer_Full <= (buffer_Full_I = '1'); buffer_Full_I <= (ib_ibuf_length(1) or ib_ibuf_length_2and3) and -- (buffer > 2) of_Valid_I; -- but not Empty ----------------------------------------------------------------------------- -- Determine if to increment or decrement the buffer length ------------------------------------------------------------------------------- Ib_ibuf_length_Counter : process (valid_fetch_i, OF_PipeRun) is-- begin -- process Ib_ibuf_length_Counter-- if (valid_fetch_i = '1') and (OF_PipeRun = '0') then -- Loading and not moving the-- -- pipeline (PipeStall)-- ib_ibuf_length_incr <= "001";-- elsif (valid_fetch_i = '0') and (OF_PipeRun = '1') then -- Not loading but moving the-- -- pipeline (Using 1 instruction)-- ib_ibuf_length_incr <= "111";-- else-- ib_ibuf_length_incr <= "000";-- end if;-- end process Ib_ibuf_length_Counter;-- new_ib_ibuf_length <= std_logic_vector(unsigned(ib_ibuf_length) + unsigned(ib_ibuf_length_incr)); -- new_ib_ibuf_length_carry(4) <= valid_fetch_i;-- new_ib_ibuf_length_calc : for I in 1 to 3 generate-- new_ib_ibuf_length_sum(I) <= ib_ibuf_length(I) xor of_PipeRun;-- new_ib_ibuf_length_MUXCY_L : MUXCY_L-- port map (-- DI => of_PipeRun, -- [in std_logic]-- CI => new_ib_ibuf_length_carry(I+1), -- [in std_logic]-- S => new_ib_ibuf_length_sum(I), -- [in std_logic]-- LO => new_ib_ibuf_length_carry(I)); -- [out std_logic]-- new_ib_ibuf_length_XORCY_I : XORCY-- port map (-- LI => new_ib_ibuf_length_sum(I), -- [in std_logic]-- CI => new_ib_ibuf_length_carry(I+1), -- [in std_logic]-- O => new_ib_ibuf_length(I)); -- [out std_logic]-- end generate new_ib_ibuf_length_calc; --bit 3 new_ib_ibuf_length(3) <= ib_ibuf_length(3) xor (of_PipeRun xor valid_fetch_i); -- bit 2 Bit_2: process (ib_ibuf_length,of_PipeRun,valid_fetch_i) is variable two_low_bits : std_logic_vector(0 to 1); begin -- process Bit_2 new_ib_ibuf_length_1_carry <= '0'; two_low_bits := ib_ibuf_length(2 to 3); new_ib_ibuf_length(2) <= ib_ibuf_length(2); case two_low_bits is when "00" => if (valid_fetch_i = '0') and (OF_PipeRun = '1') then new_ib_ibuf_length(2) <= '1'; end if; when "01" => if (valid_fetch_i = '1') and (OF_PipeRun = '0') then new_ib_ibuf_length(2) <= '1'; end if; when "10" => if (valid_fetch_i = '0') and (OF_PipeRun = '1') then new_ib_ibuf_length(2) <= '0'; end if; when "11" => new_ib_ibuf_length_1_carry <= '1'; if (valid_fetch_i = '1') and (OF_PipeRun = '0') then new_ib_ibuf_length(2) <= '0'; end if; when others => null; end case; end process Bit_2; --bit 1 bit_1: process (OF_PipeRun, ib_ibuf_length, new_ib_ibuf_length_1_carry, valid_fetch_i) is begin -- process bit_1 new_ib_ibuf_length(1) <= ib_ibuf_length(1); if (new_ib_ibuf_length_1_carry = '1') and (valid_fetch_i = '1') and (OF_PipeRun = '0') then new_ib_ibuf_length(1) <= '1'; elsif (valid_fetch_i = '0') and (OF_PipeRun = '1') then new_ib_ibuf_length(1) <= '0'; end if; end process bit_1; ----------------------------------------------------------------------------- -- This process keep tracks on the correct number of instructions in the -- prefetch buffer. ----------------------------------------------------------------------------- Ib_ibuf_length_DFF : process (Clk) variable jump_already_taken : boolean; begin -- process Ib_ibuf_length_DFF if Clk'event and Clk = '1' then -- rising clock edge if (reset) then ib_ibuf_length <= (others => '0'); ib_ibuf_length_2and3 <= '0'; jump_already_taken := false; elsif jump_load and not jump_already_taken then -- synchronous reset (active true) ib_ibuf_length_2and3 <= '0'; if (ex_branch_with_delayslot) then Ib_ibuf_length <= "001"; else Ib_ibuf_length <= (others => '0'); end if; -- If we consumes the delay slot instruction at the same time as we do -- the jump, we need to set the buffer to empty if (OF_PipeRun = '1') then Ib_ibuf_length <= (others => '0'); else jump_already_taken := true; end if; else ib_ibuf_length_2and3 <= new_ib_ibuf_length(2) and new_ib_ibuf_length(3); Ib_ibuf_length <= new_ib_ibuf_length; end if; if (OF_PipeRun = '1') then jump_already_taken := false; end if; end if; end process Ib_ibuf_length_DFF; -- Calculate the next of_valid-- of_valid_early <= (new_ib_ibuf_length(1) or new_ib_ibuf_length(2) or new_ib_ibuf_length(3)); -- can also be calculated by this -- ib_buf_length=0 and valid_ifetch=0 => of_valid_early <= 0 -- ib_buf_length=0 and valid_ifetch=1 and OF_PipeRun=1 => of_valid_early <= 0 -- ib_buf_length=1 and valid_ifetch=0 and OF_PipeRun=1 => of_valid_early <= 0 -- All other cases => of_valid_early <= 1 of_valid_early <= '0' when (ib_ibuf_length = "000" and valid_fetch_i = '0') or-- This combination looks impossible (ib_ibuf_length = "000" and valid_fetch_i = '1' and OF_PipeRun = '1') or (ib_ibuf_length = "001" and valid_fetch_i = '0' and OF_PipeRun = '1') else '1'; of_Valid_DFF : process (Clk) is begin -- process of_Valid_DFF if Clk'event and Clk = '1' then -- rising clock edge if jump_load_i then -- synchronous reset (active true) if (ex_branch_with_delayslot) then of_Valid_I <= not OF_PipeRun; else of_Valid_I <= '0'; end if; else of_Valid_I <= of_valid_early; end if; end if; end process of_Valid_DFF;end architecture IMP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -