📄 mmutlb.vhd
字号:
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 std_logic_vector(conv_unsigned(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 = replruarray then
reppos := lruo.pos(entries_log-1 downto 0);
v.touch := '0';
elsif TLB_REP = repincrement then
reppos := r.nrep;
end if;
-- pragma translate_off
if not is_x(reppos) then
-- pragma translate_on
i_reppos := conv_integer(unsigned(reppos));
-- pragma translate_off
end if;
-- pragma translate_on
-- 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;
v.s2_flush := '0';
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 = replruarray then
v.tpos := r.s2_entry; v.touch := '1'; -- touch lru
end if;
else
v.s2_tlbstate := walk;
if TLB_REP = replruarray 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 = repincrement 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.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;
-- pragma translate_off
if not is_x(r.s2_entry) then
-- pragma translate_on
i_entry := conv_integer(unsigned(r.s2_entry));
-- pragma translate_off
end if;
-- pragma translate_on
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' then
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;
--# merge data
TLB_MergeData( LVL, PTE, r.s2_data, transdata.data );
--# reset
if (rst = '0') then
v.s2_tlbstate := idle;
if TLB_REP = repincrement then
v.nrep := (others => '0');
end if;
if TLB_REP = replruarray then
v.touch := '0';
end if;
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( tlbi.transdata.data, 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.transdata <= transdata;
tlbo.fault <= fault;
tlbo.nexttrans <= store;
tlbo.s1finished <= tlbo_s1finished;
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 = replruarray then
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).flush_op <= r.s2_flush;
tlbcami(i).mmuen <= tlbi.mmctrl1.e;
tlbcami(i).tagwrite <= tlbcam_tagwrite;
tlbcami(i).write_op <= tlbcam_write_op(i);
end loop; -- i
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 port map (rst, clk, tlbcami(i), tlbcamo(i));
end generate tlbcam0;
-- data-ram syncram
dataram : syncram
generic map ( dbits => 30, abits => entries_log)
port map ( dr1_addr, clk, dr1_datain, dr1_dataout, dr1_enable, dr1_write);
-- lru
lru0: if TLB_REP = replruarray 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 + -