dcache.vhd
来自「宇航级微处理器LEON2 2.2 VHDL源代码,很难找的.」· VHDL 代码 · 共 520 行 · 第 1/2 页
VHD
520 行
newtag := r.xaddress(TAG_HIGH downto TAG_LOW); v.holdn := '0'; rdatasel := memory; v.nomds := r.nomds and not eholdn; if r.stpend = '0' then v.req := r.req; v.burst := r.req and r.burst;-- and not r.xaddress(2); if mcdo.grant = '1' then v.req := v.burst; end if; if mcdo.ready = '1' then mds := r.holdn or (r.nomds and not eholdn); v.holdn := '1'; if (mcdo.dcs = "01") then twrite := mcdo.cache and r.hit; elsif (mcdo.dcs(1) = '1') then twrite := mcdo.cache; end if; dwrite := twrite; rdatasel := memory; mexc := mcdo.mexc; if r.burst = '0' then if (((dci.enaddr and not mds) = '1') or ((dci.eenaddr and mds and eholdn) = '1')) and (mcdo.dcs /= "00") then v.dstate := "011"; v.holdn := '0'; else v.dstate := "000"; end if; else v.nomds := '1'; end if; v.burst := '0'; v.req := '0'; end if; v.mexc := mcdo.mexc; v.wb.data2 := mcdo.data; else if ((mcdo.ready and not r.burst) = '1') then -- wait for store queue v.burst := r.size(1) and r.size(0); v.wb.addr := r.xaddress; v.wb.size := r.size; v.wb.asi := r.asi(3 downto 0); v.wb.read := r.read; v.wb.data1 := dci.maddress; v.req := '1'; v.wb.lock := dci.lock; end if; end if; when "011" => -- return from read miss with load pending taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW); v.dstate := "000"; when "100" => -- second part of double store cycle v.dstate := "000"; v.wb.data2 := dci.edata; edata := dci.edata; -- needed for STD store hit taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); if (mcdo.dcs /= "00") and (r.hit = '1') then dwrite := '1'; end if; when "101" => -- icache diag access rdatasel := icache; v.icenable := '1'; v.holdn := '0'; if ico.diagrdy = '1' then v.dstate := "011"; v.icenable := '0'; mds := not r.read; end if; when "110" => -- wait for store buffer to empty (store access) edata := dci.edata; -- needed for STD store hit if ((mcdo.ready and not r.burst) = '1') then -- store queue emptied if (mcdo.dcs /= "00") and (r.hit = '1') and (r.size = "11") then -- write hit taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); dwrite := '1'; end if; v.dstate := "000"; v.req := '1'; v.burst := r.size(1) and r.size(0); v.stpend := '1'; v.wb.addr := r.xaddress; v.wb.size := r.size; v.wb.asi := r.asi(3 downto 0); v.wb.read := r.read; v.wb.data1 := dci.maddress; v.wb.lock := dci.lock; v.wb.data2 := dci.edata; if r.size = "11" then v.wb.addr(2) := '0'; end if; else -- hold cpu until buffer empty v.holdn := '0'; end if; when others => v.dstate := "000"; end case;-- select data to return on read access-- align if byte/half word read from cache or memory. rdata := (others => '0'); align_data := (others => '0'); maddrlow := maddress(1 downto 0); -- stupid Synopsys VSS bug ... case rdatasel is when dtag => rdata(TAG_HIGH downto TAG_LOW) := dcramo.dtramout.tag; rdata(DLINE_SIZE -1 downto 0) := dcramo.dtramout.valid; when icache => rdata := ico.diagdata; when ddata | memory => if rdatasel = ddata then align_data := dcramo.ddramout.data; else align_data := mcdo.data; end if; case size is when "00" => -- byte read case maddrlow is when "00" => rdata(7 downto 0) := align_data(31 downto 24); if signed = '1' then rdata(31 downto 8) := (others => align_data(31)); end if; when "01" => rdata(7 downto 0) := align_data(23 downto 16); if signed = '1' then rdata(31 downto 8) := (others => align_data(23)); end if; when "10" => rdata(7 downto 0) := align_data(15 downto 8); if signed = '1' then rdata(31 downto 8) := (others => align_data(15)); end if; when others => rdata(7 downto 0) := align_data(7 downto 0); if signed = '1' then rdata(31 downto 8) := (others => align_data(7)); end if; end case; when "01" => -- half-word read if maddress(1) = '1' then rdata(15 downto 0) := align_data(15 downto 0); if signed = '1' then rdata(31 downto 15) := (others => align_data(15)); end if; else rdata(15 downto 0) := align_data(31 downto 16); if signed = '1' then rdata(31 downto 15) := (others => align_data(31)); end if; end if; when others => -- single and double word read rdata := align_data; end case; end case;-- select which data to update the data cache with case size is -- merge data during partial write when "00" => case maddrlow is when "00" => ddatain := edata(7 downto 0) & dcramo.ddramout.data(23 downto 0); when "01" => ddatain := dcramo.ddramout.data(31 downto 24) & edata(7 downto 0) & dcramo.ddramout.data(15 downto 0); when "10" => ddatain := dcramo.ddramout.data(31 downto 16) & edata(7 downto 0) & dcramo.ddramout.data(7 downto 0); when others => ddatain := dcramo.ddramout.data(31 downto 8) & edata(7 downto 0); end case; when "01" => if maddress(1) = '0' then ddatain := edata(15 downto 0) & dcramo.ddramout.data(15 downto 0); else ddatain := dcramo.ddramout.data(31 downto 16) & edata(15 downto 0); end if; when others => ddatain := edata; end case;-- handle double load from non-cacheble areas if (r.dstate = "000") and (r.nomds = '1') then rdata := r.wb.data2; mexc := r.mexc; end if;-- Handle AHB retry v.req := v.req or mcdo.retry;-- Generate new valid bits vmaskdbl := decode(maddress(LINE_HIGH downto LINE_LOW+1)); if (size = "11") and (read = '0') then for i in 0 to (DLINE_SIZE - 1) loop vmaskraw(i) := vmaskdbl(i/2); end loop; else vmaskraw := decode(maddress(LINE_HIGH downto LINE_LOW)); end if; vmask := vmaskraw; if r.hit = '1' then vmask := r.valid or vmaskraw; end if; if r.dstate = "000" then vmask := dcramo.dtramout.valid or vmaskraw; end if; if (mcdo.mexc or r.flush) = '1' then twrite := '0'; dwrite := '0'; end if; if twrite = '1' then v.valid := vmask; if (r.dstate = "010") then v.hit := mcdo.cache; end if; end if; if tdiagwrite = '1' then -- diagnostic tag write vmask := dci.edata(DLINE_SIZE - 1 downto 0); end if;-- cache flush if (dci.flush or flush) = '1' then v.flush := '1'; v.faddr := (others => '0'); end if; if r.flush = '1' then twrite := '1'; vmask := (others => '0'); v.faddr := r.faddr +1; newtag(TAG_HIGH downto TAG_LOW) := (others => '0'); taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;-- taddr(OFFSET_LOW-1 downto LINE_LOW) := (others => '0'); if (r.faddr(DOFFSET_BITS -1) and not v.faddr(DOFFSET_BITS -1)) = '1' then v.flush := '0'; end if; end if;-- update cache with memory data during read miss if read = '1' then ddatain := mcdo.data; end if;-- reset if rst = '0' then v.dstate := "000"; v.stpend := '0'; v.req := '0'; v.burst := '0'; v.read := '0'; v.flush := '0'; v.nomds := '0'; if BOOTCACHE then twrite := '0'; dwrite := '0'; end if; end if;-- Drive signals c <= v; -- register inputs -- tag ram inputs dcrami.dtramin.valid <= vmask; dcrami.dtramin.tag <= newtag(TAG_HIGH downto TAG_LOW); dcrami.dtramin.enable <= enable; dcrami.dtramin.write <= twrite; -- data ram inputs dcrami.ddramin.enable <= enable; dcrami.ddramin.address <= taddr; dcrami.ddramin.data <= ddatain; dcrami.ddramin.write <= dwrite; -- memory controller inputs mcdi.address <= r.wb.addr; mcdi.data <= r.wb.data1; mcdi.asi <= r.wb.asi; mcdi.burst <= r.burst; mcdi.size <= r.wb.size; mcdi.read <= r.wb.read; mcdi.lock <= r.wb.lock; mcdi.req <= r.req; mcdi.flush <= r.flush; -- diagnostic instruction cache dco.icdiag.flush <= iflush; dco.icdiag.read <= read; dco.icdiag.tag <= not r.asi(0); dco.icdiag.addr <= r.xaddress; dco.icdiag.enable <= r.icenable; -- IU data cache inputs dco.data <= rdata; dco.mexc <= mexc; dco.hold <= r.holdn; dco.mds <= mds; dco.werr <= mcdo.werr; end process;-- Local registers dlat : process(clk) begin if rising_edge(clk) then r <= c; end if; end process;end ;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?