📄 mmutlb.vhd
字号:
fault_pro := '0'; fault_pri := '0'; fault_mexc := '0'; fault_trans := '0'; fault_inv := '0'; fault_access := '0'; twi_walk_op_ur := '0'; twi_areq_ur := '0'; twi_aaddr := dr1_dataout&"00"; finish := '0'; store := '0'; v.hold := '0'; savewalk := '0'; tlbo_s1finished := '0'; selstate := '0'; cam_hitaddr := (others => '0'); cam_hit_all := '0'; NEEDSYNC := '0'; for i in entries-1 downto 0 loop NEEDSYNC := NEEDSYNC or tlbcamo(i).NEEDSYNC; if (tlbcamo(i).hit) = '1' then cam_hitaddr(entries_log-1 downto 0) := cam_hitaddr(entries_log-1 downto 0) or conv_std_logic_vector(i, entries_log); cam_hit_all := '1'; end if; end loop; -- tlbcam write operation tlbcam_tagwrite := TLB_CreateCamWrite( two.data, r.s2_read, two.lvl, tlbi.mmctrl1.ctx, r.s2_data); -- replacement position reppos := (others => '0'); if tlb_rep = 0 then reppos := lruo.pos(entries_log-1 downto 0); v.touch := '0'; elsif tlb_rep = 1 then reppos := r.nrep; end if; i_reppos := conv_integer(reppos); -- tw two_error := two.fault_mexc or two.fault_trans or two.fault_inv; twACC := two.data(PTE_ACC_U downto PTE_ACC_D); twLVL := two.lvl; twPTE := two.data; twNEEDSYNC := (not two.data(PTE_R)) or ((not r.s2_read) and (not two.data(PTE_M))); -- tw : writeback on next flush case r.s2_tlbstate is when idle => if (tlbi.s2valid) = '1' then if r.s2_flush = '1' then v.s2_tlbstate := pack; else v.walk_fault.fault_pri := '0'; v.walk_fault.fault_pro := '0'; v.walk_fault.fault_access := '0'; v.walk_fault.fault_trans := '0'; v.walk_fault.fault_inv := '0'; v.walk_fault.fault_mexc := '0'; if (r.s2_hm and not tlbi.mmctrl1.tlbdis ) = '1' then if r.s2_needsync = '1' then v.s2_tlbstate := sync; else finish := '1'; end if; if tlb_rep = 0 then v.tpos := r.s2_entry; v.touch := '1'; -- touch lru end if; else v.s2_entry := reppos; v.s2_tlbstate := walk; if tlb_rep = 0 then lrui_touchmin := '1'; -- lru element consumed end if; end if; end if; end if; when walk => if (two.finish = '1') then if ( two_error ) = '0' then tlbcam_write_op := decode(r.s2_entry); dr1write := '1'; TLB_CheckFault( twACC, r.s2_isid, r.s2_su, r.s2_read, v.walk_fault.fault_pro, v.walk_fault.fault_pri ); end if; TLB_MergeData( two.lvl , two.data, r.s2_data, v.walk_transdata.data ); v.walk_transdata.cache := two.data(PTE_C); v.walk_fault.fault_lvl := two.fault_lvl; v.walk_fault.fault_access := '0'; v.walk_fault.fault_mexc := two.fault_mexc; v.walk_fault.fault_trans := two.fault_trans; v.walk_fault.fault_inv := two.fault_inv; v.walk_use := '1'; if ( twNEEDSYNC = '0' or two_error = '1') then v.s2_tlbstate := pack; else v.s2_tlbstate := sync; v.sync_isw := '1'; end if; if tlb_rep = 1 then if (r.nrep = entries_max) then v.nrep := (others => '0'); else v.nrep := r.nrep + 1; end if; end if; else twi_walk_op_ur := '1'; end if; when pack => v.s2_flush := '0'; v.walk_use := '0'; finish := '1'; v.s2_tlbstate := idle; when sync => tlbcam_trans_op := '1'; if ( v.sync_isw = '1') then -- pte address is currently written to syncram, wait one cycle before issuing twi_areq_ur v.sync_isw := '0'; else if (two.finish = '1') then v.s2_tlbstate := pack; v.walk_fault.fault_mexc := two.fault_mexc; if (two.fault_mexc) = '1' then v.walk_use := '1'; end if; else twi_areq_ur := '1'; end if; end if; when others => v .s2_tlbstate := idle; end case; if selstate = '1' then if tlbi.trans_op = '1' then elsif tlbi.flush_op = '1' then end if; end if; i_entry := conv_integer(r.s2_entry); ACC := tlbcamo(i_entry).pteout(PTE_ACC_U downto PTE_ACC_D); PTE := tlbcamo(i_entry).pteout; LVL := tlbcamo(i_entry).LVL; CAC := tlbcamo(i_entry).pteout(PTE_C); transdata.cache := CAC; --# fault, todo: should we flush on a fault? TLB_CheckFault( ACC, r.s2_isid, r.s2_su, r.s2_read, fault_pro, fault_pri ); fault.fault_pro := '0'; fault.fault_pri := '0'; fault.fault_access := '0'; fault.fault_mexc := '0'; fault.fault_trans := '0'; fault.fault_inv := '0'; if finish = '1' and (r.s2_flush = '0') then --protect flush path fault.fault_pro := fault_pro; fault.fault_pri := fault_pri; fault.fault_access := fault_access; fault.fault_mexc := fault_mexc; fault.fault_trans := fault_trans; fault.fault_inv := fault_inv; end if; if (M_TLB_FASTWRITE /= 0) then wb_i_entry := conv_integer(cam_hitaddr(entries_log-1 downto 0)); wb_ACC := tlbcamo(wb_i_entry).pteout(PTE_ACC_U downto PTE_ACC_D); wb_PTE := tlbcamo(wb_i_entry).pteout; wb_LVL := tlbcamo(wb_i_entry).LVL; wb_CAC := tlbcamo(wb_i_entry).pteout(PTE_C); wb_WBNEEDSYNC := tlbcamo(wb_i_entry).WBNEEDSYNC; wb_transdata.cache := wb_CAC; TLB_MergeData( wb_LVL, wb_PTE, tlbi.transdata.data, wb_transdata.data ); --# fault, todo: should we flush on a fault? TLB_CheckFault( wb_ACC, tlbi.transdata.isid, tlbi.transdata.su, tlbi.transdata.read, wb_fault_pro, wb_fault_pri ); wb_transdata.accexc := wb_fault_pro or wb_fault_pri or wb_WBNEEDSYNC or (not cam_hit_all); end if; --# merge data TLB_MergeData( LVL, PTE, r.s2_data, transdata.data ); --# reset if (rst = '0') then v.s2_flush := '0'; v.s2_tlbstate := idle; if tlb_rep = 1 then v.nrep := (others => '0'); end if; if tlb_rep = 0 then v.touch := '0'; end if; v.sync_isw := '0'; end if; if (finish = '1') or (tlbi.s2valid = '0') then tlbo_s1finished := '1'; v.s2_hm := cam_hit_all; v.s2_entry := cam_hitaddr(entries_log-1 downto 0); v.s2_needsync := NEEDSYNC; v.s2_data := tlbi.transdata.data; v.s2_read := tlbi.transdata.read; v.s2_su := tlbi.transdata.su; v.s2_isid := tlbi.transdata.isid; v.s2_flush := tlbi.flush_op; end if; -- translation operation tag mtag := TLB_CreateCamTrans( cam_addr, tlbi.transdata.read, tlbi.mmctrl1.ctx ); tlbcam_tagin := mtag; -- flush/(probe) operation tag ftag := TLB_CreateCamFlush( r.s2_data, tlbi.mmctrl1.ctx ); if (r.s2_flush = '1') then tlbcam_tagin := ftag; end if; if r.walk_use = '1' then transdata := r.walk_transdata; fault := r.walk_fault; end if; fault.fault_read := r.s2_read; fault.fault_su := r.s2_su; fault.fault_isid := r.s2_isid; fault.fault_addr := r.s2_data; transdata.finish := finish; transdata.accexc := '0'; twi_adata := PTE; --# drive signals tlbo.wbtransdata <= wb_transdata; tlbo.transdata <= transdata; tlbo.fault <= fault; tlbo.nexttrans <= store; tlbo.s1finished <= tlbo_s1finished; tlbo.tlbcamo <= (others => mmutlbcam_out_none); twi.walk_op_ur <= twi_walk_op_ur; twi.data <= r.s2_data; twi.areq_ur <= twi_areq_ur; twi.adata <= twi_adata; twi.aaddr <= twi_aaddr; if tlb_rep = 0 then lrui.flush <= r.s2_flush; lrui.touch <= r.touch; lrui.touchmin <= lrui_touchmin; lrui.pos <= (others => '0'); lrui.pos(entries_log-1 downto 0) <= r.tpos; lrui.mmctrl1 <= tlbi.mmctrl1; end if; dr1_addr <= r.s2_entry; dr1_datain <= two.addr(31 downto 2); dr1_enable <= '1'; dr1_write <= dr1write; for i in entries-1 downto 0 loop tlbcami(i).tagin <= tlbcam_tagin; tlbcami(i).trans_op <= tlbi.trans_op; --tlbcam_trans_op; tlbcami(i).wb_op <= tlbi.wb_op; --tlbcam_trans_op; tlbcami(i).flush_op <= r.s2_flush; tlbcami(i).mmuen <= tlbi.mmctrl1.e; tlbcami(i).tagwrite <= tlbcam_tagwrite; tlbcami(i).write_op <= tlbcam_write_op(i); tlbcami(i).mset <= '0'; end loop; -- i for i in M_ENT_MAX-1 downto entries loop tlbcami(i).tagin <= tlbcam_tfp_none; tlbcami(i).trans_op <= '0'; tlbcami(i).wb_op <= '0'; tlbcami(i).flush_op <= '0'; tlbcami(i).mmuen <= '0'; tlbcami(i).tagwrite <= tlbcam_reg_none; tlbcami(i).write_op <= '0'; tlbcami(i).mset <= '0'; end loop; c <= v; end process p0; p1: process (clk) begin if rising_edge(clk) then r <= c; end if; end process p1; -- tag-cam tlb entries tlbcam0: for i in entries-1 downto 0 generate tag0 : mmutlbcam generic map ( tlb_type ) port map (rst, clk, tlbcami(i), tlbcamo(i)); end generate tlbcam0; tlbcamnone: for i in M_ENT_MAX-1 downto entries generate tlbcamo(i) <= mmutlbcam_out_none; end generate ; -- data-ram syncram dataram : syncram generic map ( tech => tech, dbits => 30, abits => entries_log) port map ( clk, dr1_addr, dr1_datain, dr1_dataout, dr1_enable, dr1_write); -- lru lru0: if tlb_rep = 0 generate lru : mmulru generic map ( entries => entries) port map ( clk, rst, lrui, lruo ); end generate lru0;end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -