📄 mmu_icache.vhd
字号:
v.istate := trans; mmuici_trans_op := '1'; v.trans_op := not mmuico.grant; v.cache := '0'; --v.req := '0'; else v.req := '1'; v.cache := '1'; end if; else if (ISETS > 1) and (ICREPLACE = lru) then vl.write := '1'; end if; end if; v.waddress := ici.fpc(31 downto PCLOW); v.vaddress := ici.fpc(31 downto PCLOW); end if; if dco.icdiag.enable = '1' then diagen := '1'; end if; ddatain := dci.maddress; if (ISETS > 1) then if (ICREPLACE = lru) then vl.set := conv_std_logic_vector(set, SETBITS); vl.waddr := ici.fpc(OFFSET_HIGH downto OFFSET_LOW); end if; v.setrepl := conv_std_logic_vector(set, SETBITS); if (((not hit) and (not dparerr(set)) and (not r.flush)) = '1') then case ICREPLACE is when rnd => if ICLOCK_BIT = 1 then if lock(conv_integer(r.rndcnt)) = '0' then v.setrepl := r.rndcnt; else v.setrepl := conv_std_logic_vector(ISETS-1, SETBITS); for i in ISETS-1 downto 0 loop if (lock(i) = '0') and (i>conv_integer(r.rndcnt)) then v.setrepl := conv_std_logic_vector(i, SETBITS); end if; end loop; end if; else v.setrepl := r.rndcnt; end if; when lru => v.setrepl := lru_set(rl.lru(conv_integer(ici.fpc(OFFSET_HIGH downto OFFSET_LOW))), lock(0 to ISETS-1)); when lrr => v.setrepl := (others => '0'); if isetlock = 1 then if lock(0) = '1' then v.setrepl(0) := '1'; else v.setrepl(0) := icramo.tag(0)(CTAG_LRRPOS) xor icramo.tag(1)(CTAG_LRRPOS); end if; else v.setrepl(0) := icramo.tag(0)(CTAG_LRRPOS) xor icramo.tag(1)(CTAG_LRRPOS); end if; if v.setrepl(0) = '0' then v.lrr := not icramo.tag(0)(CTAG_LRRPOS); else v.lrr := icramo.tag(0)(CTAG_LRRPOS); end if; end case; end if; if (ICLOCK_BIT = 1) then if (hit and lock(set)) = '1' then v.lock := '1'; else v.lock := '0'; end if; end if; end if; when trans => v.holdn := '0'; if (mmuico.transdata.finish = '1') then if (mmuico.transdata.accexc) = '1' and ((mmudci.mmctrl1.nf) /= '1' or (r.su) = '1') then -- if su then always do mexc error := '1'; mds := '0'; v.holdn := '1'; v.istate := idle; v.burst := '0'; else v.cache := mmuico.transdata.cache; v.waddress := mmuico.transdata.data(31 downto PCLOW); v.istate := streaming; v.req := '1'; end if; end if; when streaming => -- streaming: update cache and send data to IU rdatasel := memory; taddr(TAG_HIGH downto LINE_LOW) := r.vaddress(TAG_HIGH downto LINE_LOW); branch := (ici.fbranch and r.overrun) or (ici.rbranch and (not r.overrun)); v.underrun := r.underrun or (write and ((ici.inull or not eholdn) and (mcio.ready and not (r.overrun and not r.underrun)))); v.overrun := (r.overrun or (eholdn and not ici.inull)) and not (write or r.underrun); if mcio.ready = '1' then mds := not (r.overrun and not r.underrun); v.burst := v.req and not (nnlastline and mcio.ready); end if; if mcio.grant = '1' then v.req := dco.icdiag.cctrl.burst and r.burst and (not (nnlastline and mcio.ready)) and (dco.icdiag.cctrl.burst or (not branch)) and not (v.underrun and not cacheon); v.burst := v.req and not (nnlastline and mcio.ready); end if; v.underrun := (v.underrun or branch) and not v.overrun; v.holdn := not (v.overrun or v.underrun); if (mcio.ready = '1') and (r.req = '0') then --(v.burst = '0') then v.underrun := '0'; v.overrun := '0'; if (dco.icdiag.cctrl.ics(0) and not r.flush2) = '1' then v.istate := stop; v.holdn := '0'; else v.istate := idle; v.flush := r.flush2; v.holdn := '1'; if r.overrun = '1' then taddr := ici.fpc(TAG_HIGH downto LINE_LOW); else taddr := ici.rpc(TAG_HIGH downto LINE_LOW); end if; end if; end if; when stop => -- return to main taddr := ici.fpc(TAG_HIGH downto LINE_LOW); v.istate := idle; v.flush := r.flush2; when others => v.istate := idle; end case; if mcio.retry = '1' then v.req := '1'; end if;-- Generate new valid bits write strobe vmaskraw := decode(r.waddress(LINE_HIGH downto LINE_LOW)); twrite := write; if cacheon = '0' then twrite := '0'; vmask := (others => '0'); elsif (dco.icdiag.cctrl.ics = "01") then twrite := twrite and r.hit; vmask := icramo.tag(set)(ilinesize-1 downto 0) or vmaskraw; else if r.hit = '1' then vmask := r.valid or vmaskraw; else vmask := vmaskraw; end if; end if; if (mcio.mexc or (not mcio.cache) or (not r.cache)) = '1' then twrite := '0'; dwrite := '0'; else dwrite := twrite; end if; if twrite = '1' then v.valid := vmask; v.hit := '1'; if (ISETS > 1) and (ICREPLACE = lru) then vl.write := '1'; end if; end if; if (ISETS > 1) and (ICREPLACE = lru) and (rl.write = '1') then vl.lru(conv_integer(rl.waddr)) := lru_calc(rl.lru(conv_integer(rl.waddr)), conv_integer(rl.set)); end if;-- cache write signals if ISETS > 1 then setrepl := r.setrepl; else setrepl := (others => '0'); end if; if twrite = '1' then ctwrite(conv_integer(setrepl)) := '1'; end if; if dwrite = '1' then cdwrite(conv_integer(setrepl)) := '1'; end if; -- diagnostic cache access if diagen = '1' then if (ISETS /= 1) then v.diagset := dco.icdiag.addr(SETBITS -1 + TAG_LOW downto TAG_LOW); end if; end if; if (ISETS /= 1) then rdiagset := conv_integer(r.diagset); vdiagset := conv_integer(v.diagset); end if; diagdata := icramo.data(rdiagset); if diagen = '1' then -- diagnostic access taddr(OFFSET_HIGH downto LINE_LOW) := dco.icdiag.addr(OFFSET_HIGH downto LINE_LOW); wtag(TAG_HIGH downto TAG_LOW) := dci.maddress(TAG_HIGH downto TAG_LOW); wlrr := dci.maddress(CTAG_LRRPOS); wlock := dci.maddress(CTAG_LOCKPOS); if dco.icdiag.tag = '1' then twrite := not dco.icdiag.read; dwrite := '0'; ctwrite := (others => '0'); cdwrite := (others => '0'); ctwrite(vdiagset) := not dco.icdiag.read; diagdata := icramo.tag(rdiagset); else dwrite := not dco.icdiag.read; twrite := '0'; cdwrite := (others => '0'); cdwrite(vdiagset) := not dco.icdiag.read; ctwrite := (others => '0'); end if; vmask := dci.maddress(ilinesize -1 downto 0); v.diagrdy := '1'; end if;-- select data to return on read access rdata := icramo.data; case rdatasel is when memory => rdata(0) := mcio.data; set := 0; when others => end case;-- cache flush if (ici.flush or dco.icdiag.flush) = '1' then v.flush := '1'; v.flush2 := '1'; v.faddr := (others => '0'); v.pflush := dco.icdiag.pflush; wtag := (others => '0'); v.pflushr := '1'; v.pflushaddr := dco.icdiag.pflushaddr; v.pflushtyp := dco.icdiag.pflushtyp; end if; if r.flush2 = '1' then twrite := '1'; ctwrite := (others => '1'); vmask := (others => '0'); v.faddr := r.faddr +1; taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr; wlrr := '0'; wlock := '0'; if (r.faddr(IOFFSET_BITS -1) and not v.faddr(IOFFSET_BITS -1)) = '1' then v.flush2 := '0'; end if; v.lrr := '0'; -- precise flush, ASI_FLUSH_PAGE & ASI_FLUSH_CTX --if M_EN then if r.pflush = '1' then twrite := '0'; ctwrite := (others => '0'); v.pflushr := not r.pflushr; if r.pflushr = '0' then for i in ISETS-1 downto 0 loop pftag(OFFSET_HIGH downto OFFSET_LOW) := r.faddr; pftag(TAG_HIGH downto TAG_LOW) := icramo.tag(i)(TAG_HIGH downto TAG_LOW); --icramo.itramout(i).tag; --if (icramo.itramout(i).ctx = mmudci.mmctrl1.ctx) and -- ((pftag(VA_I_U downto VA_I_D) = r.pflushaddr(VA_I_U downto VA_I_D)) or -- (r.pflushtyp = '1')) then ctwrite(i) := '1'; --end if; end loop; end if; end if; --end if; end if;-- reset if rst = '0' then v.istate := idle; v.req := '0'; v.burst := '0'; v.holdn := '1'; v.flush := '0'; v.flush2 := '0'; v.overrun := '0'; v.underrun := '0'; v.rndcnt := (others => '0'); v.lrr := '0'; v.setrepl := (others => '0'); v.diagset := (others => '0'); v.lock := '0'; v.trans_op := '0'; v.flush3 := '1'; end if; if r.flush3 = '1' then vl.lru := (others => (others => '0')); end if; -- Drive signals c <= v; -- register inputs cl <= vl; -- lru register inputs -- tag ram inputs for i in 0 to ISETS-1 loop tag(i) := (others => '0'); tag(i)(ilinesize-1 downto 0) := vmask; tag(i)(TAG_HIGH downto TAG_LOW) := wtag; tag(i)(CTAG_LRRPOS) := wlrr; tag(i)(CTAG_LOCKPOS) := wlock; end loop; icrami.tag <= tag; icrami.tenable <= enable; icrami.twrite <= ctwrite; icrami.flush <= r.flush2; icrami.ctx <= mmudci.mmctrl1.ctx; -- data ram inputs icrami.denable <= enable; icrami.address(19 downto (OFFSET_HIGH - LINE_LOW +1)) <= zero32(19 downto (OFFSET_HIGH - LINE_LOW +1)); icrami.address(OFFSET_HIGH - LINE_LOW downto 0) <= taddr(OFFSET_HIGH downto LINE_LOW); icrami.data <= ddatain; icrami.dwrite <= cdwrite; -- memory controller inputs mcii.address(31 downto 2) <= r.waddress(31 downto 2); mcii.address(1 downto 0) <= "00"; mcii.su <= r.su; mcii.burst <= r.burst; mcii.req <= r.req; mcii.flush <= r.flush; -- mmu <-> icache mmuici.trans_op <= mmuici_trans_op; mmuici.transdata.data <= r.waddress(31 downto 2) & "00"; mmuici.transdata.su <= r.su; mmuici.transdata.isid <= id_icache; mmuici.transdata.read <= '1'; -- IU data cache inputs ico.data <= rdata; ico.mexc <= mcio.mexc or error; ico.hold <= r.holdn; ico.mds <= mds; ico.flush <= r.flush; ico.diagdata <= diagdata; ico.diagrdy <= r.diagrdy; ico.set <= conv_std_logic_vector(set, 2); ico.cfg <= icfg; ico.idle <= sidle; end process;-- Local registers regs1 : process(clk) begin if rising_edge(clk) then r <= c; end if; end process; regs2gen : if (ISETS > 1) and (ICREPLACE = lru) generate regs2 : process(clk) begin if rising_edge(clk) then rl <= cl; end if; end process; end generate; nolru : if (ISETS = 1) or (irepl /= lru) generate rl.write <= '0'; rl.waddr <= (others => '0'); rl.set <= (others => '0'); rl.lru <= (others => (others => '0')); end generate;-- pragma translate_off chk : process begin assert not ((ISETS > 2) and (ICREPLACE = lrr)) report "Wrong instruction cache configuration detected: LRR replacement requires 2 sets" severity failure; wait; end process;-- pragma translate_on end ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -