📄 dcache.vhd
字号:
when "01" => -- half-word read if maddress(1) = '1' then rdata(15 downto 0) := mcdo.data(15 downto 0); if signed = '1' then rdata(31 downto 15) := (others => mcdo.data(15)); end if; else rdata(15 downto 0) := mcdo.data(31 downto 16); if signed = '1' then rdata(31 downto 15) := (others => mcdo.data(31)); end if; end if; when others => -- single and double word read rdata := mcdo.data; end case; else rdata := (others => '0'); for i in 0 to DSETS-1 loop case size is when "00" => -- byte read case maddrlow is when "00" => rdatav(i)(7 downto 0) := dcramov.ddramout(i).data(31 downto 24); if signed = '1' then rdatav(i)(31 downto 8) := (others => dcramov.ddramout(i).data(31)); end if; when "01" => rdatav(i)(7 downto 0) := dcramov.ddramout(i).data(23 downto 16); if signed = '1' then rdatav(i)(31 downto 8) := (others => dcramov.ddramout(i).data(23)); end if; when "10" => rdatav(i)(7 downto 0) := dcramov.ddramout(i).data(15 downto 8); if signed = '1' then rdatav(i)(31 downto 8) := (others => dcramov.ddramout(i).data(15)); end if; when others => rdatav(i)(7 downto 0) := dcramov.ddramout(i).data(7 downto 0); if signed = '1' then rdatav(i)(31 downto 8) := (others => dcramov.ddramout(i).data(7)); end if; end case; when "01" => -- half-word read if maddress(1) = '1' then rdatav(i)(15 downto 0) := dcramov.ddramout(i).data(15 downto 0); if signed = '1' then rdatav(i)(31 downto 15) := (others => dcramov.ddramout(i).data(15)); end if; else rdatav(i)(15 downto 0) := dcramov.ddramout(i).data(31 downto 16); if signed = '1' then rdatav(i)(31 downto 15) := (others => dcramov.ddramout(i).data(31)); end if; end if; when others => -- single and double word read rdatav(i) := dcramov.ddramout(i).data; end case; if validrawv(i) = '1' then rdata := rdata or rdatav(i); end if; end loop; end if; else if rdatasel = ddata then align_data := dcramov.ddramout(set).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 if; end case;-- select which data to update the data cache with if DWRITE_FAST then for i in 0 to DSETS-1 loop case size is -- merge data during partial write when "00" => case maddrlow is when "00" => ddatainv(i) := edata(7 downto 0) & dcramov.ddramout(i).data(23 downto 0); when "01" => ddatainv(i) := dcramov.ddramout(i).data(31 downto 24) & edata(7 downto 0) & dcramov.ddramout(i).data(15 downto 0); when "10" => ddatainv(i) := dcramov.ddramout(i).data(31 downto 16) & edata(7 downto 0) & dcramov.ddramout(i).data(7 downto 0); when others => ddatainv(i) := dcramov.ddramout(i).data(31 downto 8) & edata(7 downto 0); end case; when "01" => if maddress(1) = '0' then ddatainv(i) := edata(15 downto 0) & dcramov.ddramout(i).data(15 downto 0); else ddatainv(i) := dcramov.ddramout(i).data(31 downto 16) & edata(15 downto 0); end if; when others => ddatainv(i) := edata; end case; end loop; ddatain := ddatainv(set); else case size is -- merge data during partial write when "00" => case maddrlow is when "00" => ddatain := edata(7 downto 0) & dcramov.ddramout(set).data(23 downto 0); when "01" => ddatain := dcramov.ddramout(set).data(31 downto 24) & edata(7 downto 0) & dcramov.ddramout(set).data(15 downto 0); when "10" => ddatain := dcramov.ddramout(set).data(31 downto 16) & edata(7 downto 0) & dcramov.ddramout(set).data(7 downto 0); when others => ddatain := dcramov.ddramout(set).data(31 downto 8) & edata(7 downto 0); end case; when "01" => if maddress(1) = '0' then ddatain := edata(15 downto 0) & dcramov.ddramout(set).data(15 downto 0); else ddatain := dcramov.ddramout(set).data(31 downto 16) & edata(15 downto 0); end if; when others => ddatain := edata; end case; end if;-- handle double load with pipeline hold if (r.dstate = "000") and (r.nomds = '1') then rdata := r.wb.data2; mexc := r.mexc; end if;-- Handle AHB retry. Re-generate bus request and burst if mcdo.retry = '1' then v.req := '1'; v.burst := r.wb.size(0) and r.wb.size(1) and not r.wb.addr(2); end if;-- 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 := dcramov.dtramout(set).valid or vmaskraw; vmask := ivalid 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 (DSETS>1) and (DCREPLACE = lru) and (tdiagwrite = '0') then vl.write := '1'; vl.set := setrepl; end if; end if; if (DSETS>1) and (DCREPLACE = 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; if tdiagwrite = '1' then -- diagnostic tag write if DEBUG_UNIT and (dci.dsuen = '1') then vmask := dci.maddress(DLINE_SIZE - 1 downto 0); else vmask := dci.edata(DLINE_SIZE - 1 downto 0); newtag(TAG_HIGH downto TAG_LOW) := dci.edata(TAG_HIGH downto TAG_LOW); for i in 0 to 1 loop wlrr(i) := dci.edata(DCTAG_LRRPOS); end loop; for i in 0 to DSETS-1 loop wlock(i) := dci.edata(DCTAG_LOCKPOS); end loop; end if; end if;-- cache flush if (dci.flush or flush or mcdo.dflush) = '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; wlrr := (others => '0'); if (r.faddr(DOFFSET_BITS -1) and not v.faddr(DOFFSET_BITS -1)) = '1' then v.flush := '0'; end if; end if;-- AHB snoop handling (2), bypass write data on read/write contention if DSNOOP then-- pragma translate_off if not is_x(setrepl) then-- pragma translate_on if tdiagwrite = '1' then snoopset2 := ddset; else snoopset2 := conv_integer(setrepl); end if;-- pragma translate_off end if;-- pragma translate_on if DSNOOP_FAST then vh.taddr := taddr(OFFSET_HIGH downto OFFSET_LOW); vh.set := std_logic_vector(conv_unsigned(set, SETBITS)); if twrite = '1' then -- pragma translate_off if not is_x(taddr(OFFSET_HIGH downto OFFSET_LOW)) then-- pragma translate_on vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW)))(snoopset2) := '0';-- pragma translate_off end if;-- pragma translate_on end if; else if rs.addr(OFFSET_HIGH downto OFFSET_LOW) = taddr(OFFSET_HIGH downto OFFSET_LOW) then if twrite = '0' then if snoopwe = '1' then vs.writebp(snoopset) := '1'; end if; else if (snoopwe = '1') and (conv_integer(setrepl) = snoopset) then twrite := '0'; end if; -- avoid write/write contention end if; end if; end if; end if;-- update cache with memory data during read miss if read = '1' then ddatain := mcdo.data; end if;-- cache write signals if twrite = '1' then if tdiagwrite = '1' then ctwrite(ddset) := '1'; else ctwrite(conv_integer(setrepl)) := '1'; end if; end if; if dwrite = '1' then if ddiagwrite = '1' then cdwrite(ddset) := '1'; else cdwrite(conv_integer(setrepl)) := '1'; end if; end if; csnoopwe := (others => '0'); if (snoopwe = '1') then csnoopwe(snoopset) := '1'; end if; if (r.flush and twrite) = '1' then -- flush ctwrite := (others => '1'); wlrr := (others => '0'); wlock := (others => '0'); end if; if (r.flush or (not rst)) = '1' then vl.lru := (others => (others => '0')); 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'; v.rndcnt := (others => '0'); v.setrepl := (others => '0'); v.dsuset := (others => '0'); v.lrr := '0'; v.lock := '0'; end if;-- Drive signals c <= v; cs <= vs; ch <= vh; -- register inputs cl <= vl; -- tag ram inputs dcrami.dtramin.valid <= vmask; dcrami.dtramin.tag <= newtag(TAG_HIGH downto TAG_LOW); dcrami.dtramin.lrr <= wlrr; dcrami.dtramin.lock <= wlock; dcrami.dtramin.enable <= enable; dcrami.dtramin.write <= ctwrite; dcrami.dtramin.flush <= r.flush; dcrami.dtraminsn.enable <= vs.snoop or rs.snoop; dcrami.dtraminsn.write <= csnoopwe; dcrami.dtraminsn.address<= snoopaddr; dcrami.dtraminsn.tag <= rs.addr(TAG_HIGH downto TAG_LOW); -- data ram inputs dcrami.ddramin.enable <= enable; dcrami.ddramin.address <= taddr; dcrami.ddramin.data <= ddatain; dcrami.ddramin.write <= cdwrite; dcrami.ldramin.address <= laddr(LOCAL_RAM_BITS+1 downto 2); dcrami.ldramin.enable <= lramcs or lramwr; dcrami.ldramin.read <= r.lramrd or lramrd; dcrami.ldramin.write <= lramwr; -- memory controller inputs mcdi.address <= r.wb.addr; mcdi.data <= r.wb.data1; mcdi.burst <= r.burst; mcdi.size <= r.wb.size; mcdi.read <= r.wb.read; mcdi.asi <= r.wb.asi; mcdi.lock <= r.wb.lock or dci.lock; mcdi.req <= r.req; mcdi.flush <= r.flush; -- diagnostic instruction cache access dco.icdiag.flush <= iflush or mcdo.iflush; dco.icdiag.read <= read; dco.icdiag.tag <= not r.asi(0); dco.icdiag.addr <= r.xaddress; dco.icdiag.enable <= r.icenable; dco.dsudata <= dsudata; -- debug unit -- 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 reg1 : process(clk) begin if rising_edge(clk ) then r <= c; end if; end process; sn2 : if DSNOOP generate reg2 : process(clk) begin if rising_edge(clk ) then rs <= cs; end if; end process; end generate; sn3 : if DSNOOP_FAST generate reg3 : process(clk) begin if rising_edge(clk ) then rh <= ch; end if; end process; end generate; reg2 : if (DSETS>1) and (DCREPLACE = lru) generate reg2 : process(clk) begin if rising_edge(clk ) then rl <= cl; end if; end process; end generate; -- pragma translate_off chk : process begin assert not ((DSETS > 2) and (DCREPLACE = lrr)) report "Wrong data cache configuration detected: LRR replacement requires 2 sets" severity failure; wait; end process;-- pragma translate_onend ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -