📄 dcache.vhd
字号:
tdiagwrite := not dci.eenaddr and dci.enaddr and dci.write; twrite := not dci.eenaddr and dci.enaddr and dci.write; rdatasel := dtag; when ASI_DDATA => ddiagwrite := not dci.eenaddr and dci.enaddr and dci.write; dwrite := not dci.eenaddr and dci.enaddr and dci.write; rdatasel := dddata; when ASI_UDATA | ASI_SDATA => lramwr := not dci.eenaddr and dci.enaddr and dci.write;-- when ASI_UINST | ASI_SINST => when others => end case; end if; rdatav := (others => (others => '0')); align_data := (others => '0'); align_datav := (others => (others => '0')); maddrlow := maddress(1 downto 0); -- stupid Synopsys VSS bug ... case rdatasel is when dddata => rdatav := dcramov.data; if dci.dsuen = '1' then set := conv_integer(r.dsuset); else set := ddset; end if; when dtag => rdatav := dcramov.tag; if dci.dsuen = '1' then set := conv_integer(r.dsuset); else set := ddset; end if; when icache => rdatav(0) := ico.diagdata; set := 0; when ddata | memory => if rdatasel = memory then rdatav(0) := mcdo.data; set := 0; --FIXME else for i in 0 to DSETS-1 loop rdatav(i) := dcramov.data(i); end loop; end if; when sysr => set := 0; case dci.maddress(3 downto 2) is when "00" | "01" => rdatav(0)(23) := r.cctrl.dsnoop; rdatav(0)(16 downto 14) := r.cctrl.burst & ico.flush & r.flush; rdatav(0)(5 downto 0) := r.cctrl.dfrz & r.cctrl.ifrz & r.cctrl.dcs & r.cctrl.ics; when "10" => rdatav(0) := ico.cfg; when others => rdatav(0) := cache_cfg(drepl, dsets, dlinesize, dsetsize, dsetlock, dsnoop, dlram, dlramsize, dlramstart, 0); end case; end case;-- select which data to update the data cache with 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.data(i)(23 downto 0); when "01" => ddatainv(i) := dcramov.data(i)(31 downto 24) & edata(7 downto 0) & dcramov.data(i)(15 downto 0); when "10" => ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(7 downto 0) & dcramov.data(i)(7 downto 0); when others => ddatainv(i) := dcramov.data(i)(31 downto 8) & edata(7 downto 0); end case; when "01" => if maddress(1) = '0' then ddatainv(i) := edata(15 downto 0) & dcramov.data(i)(15 downto 0); else ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(15 downto 0); end if; when others => ddatainv(i) := edata; end case; end loop;-- ddatain := ddatainv(set);-- handle double load with pipeline hold if (r.dstate = "000") and (r.nomds = '1') then rdatav(0) := r.wb.data2; mexc := r.mexc; set := 0; --FIXME 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 (dlinesize - 1) loop vmaskraw(i) := vmaskdbl(i/2); end loop; else vmaskraw := decode(maddress(LINE_HIGH downto LINE_LOW)); end if; vmask := (others => vmaskraw); if r.hit = '1' then for i in 0 to DSETS-1 loop vmask(i) := r.valid(i) or vmaskraw; end loop; end if; if r.dstate = "000" then -- vmask := dcramov.dtramout(set).valid or vmaskraw; for i in 0 to DSETS-1 loop vmask(i) := dcramov.tag(i)(dlinesize-1 downto 0) or vmaskraw; end loop; else for i in 0 to DSETS-1 loop tag(i)(dlinesize-1 downto 0) := vmask(i); end loop; 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 (drepl = lru) and (tdiagwrite = '0') then vl.write := '1'; vl.set := setrepl; end if; end if; if (DSETS>1) and (drepl = 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 (dsu = 1) and (dci.dsuen = '1') then vmask := (others => dci.maddress(dlinesize - 1 downto 0)); else vmask := (others => dci.edata(dlinesize - 1 downto 0)); newtag(TAG_HIGH downto TAG_LOW) := dci.edata(TAG_HIGH downto TAG_LOW); for i in 0 to 3 loop wlrr(i) := dci.edata(CTAG_LRRPOS); end loop; for i in 0 to DSETS-1 loop wlock(i) := dci.edata(CTAG_LOCKPOS); end loop; end if; end if;-- cache flush if ((dci.flush or flush) = '1') and (dcen /= 0) then v.flush := '1'; v.faddr := (others => '0'); end if; if (r.flush = '1') and (dcen /= 0) then twrite := '1'; vmask := (others => (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; if DSNOOP = 2 then vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW))) := (others => '0'); end if; end if;-- AHB snoop handling (2), bypass write data on read/write contention if DSNOOP /= 0 then if tdiagwrite = '1' then snoopset2 := ddset; else snoopset2 := conv_integer(setrepl); end if; if DSNOOP = 2 then vh.taddr := taddr(OFFSET_HIGH downto OFFSET_LOW); vh.set := conv_std_logic_vector(set, SETBITS); if (twrite = '1') and (r.dstate /= "000") then vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW)))(snoopset2) := '0'; 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'; if DEST_RW then enable(snoopset) := '0'; end if; end if; else if (snoopwe = '1') and (conv_integer(setrepl) = snoopset) then -- avoid write/write contention twrite := '0'; if DEST_RW then enable(snoopset) := '0'; end if; end if; end if; end if; end if; if (r.dstate = "001") and ((rbphit and rs.snoop) = '1') then v.hit := '0'; end if; if DEST_RW then -- disable snoop read enable on write/read contention if taddr(OFFSET_HIGH downto OFFSET_LOW) = ahbsi.haddr(OFFSET_HIGH downto OFFSET_LOW) then for i in 0 to DSETS-1 loop if (twrite and senable(i)) = '1' then senable(i) := '0'; end if; end loop; end if; end if; end if;-- update cache with memory data during read miss if read = '1' then for i in 0 to DSETS-1 loop ddatainv(i) := mcdo.data; end loop; 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 and not mcdo.scanen) = '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.flush2 = '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.holdn := '1'; v.rndcnt := (others => '0'); v.setrepl := (others => '0'); v.dsuset := (others => '0'); v.flush2 := '1'; v.lrr := '0'; v.lock := '0'; v.ilramen := '0'; v.cctrl.dcs := "00"; v.cctrl.ics := "00"; v.cctrl.burst := '0'; v.cctrl.dsnoop := '0'; end if; if dsnoop = 0 then v.cctrl.dsnoop := '0'; end if;-- Drive signals c <= v; cs <= vs; ch <= vh; -- register inputs cl <= vl; -- tag ram inputs senable := senable and not scanen; enable := enable and not scanen; if mcdo.scanen = '1' then ctwrite := (others => '0'); end if; for i in 0 to DSETS-1 loop tag(i)(dlinesize-1 downto 0) := vmask(i); tag(i)(TAG_HIGH downto TAG_LOW) := newtag(TAG_HIGH downto TAG_LOW); tag(i)(CTAG_LRRPOS) := wlrr(i); tag(i)(CTAG_LOCKPOS) := wlock(i); end loop; dcrami.tag <= tag; dcrami.tenable <= enable; dcrami.twrite <= ctwrite; dcrami.flush <= r.flush; dcrami.senable <= senable;--vs.snoop or rs.snoop; dcrami.swrite <= csnoopwe; dcrami.saddress(19 downto (OFFSET_HIGH - OFFSET_LOW +1)) <= zero32(19 downto (OFFSET_HIGH - OFFSET_LOW +1)); dcrami.saddress(OFFSET_HIGH - OFFSET_LOW downto 0) <= snoopaddr; dcrami.stag(31 downto (TAG_HIGH - TAG_LOW +1)) <= zero32(31 downto (TAG_HIGH - TAG_LOW +1)); dcrami.stag(TAG_HIGH - TAG_LOW downto 0) <= rs.addr(TAG_HIGH downto TAG_LOW); dcrami.tdiag <= mcdo.testen & "000"; dcrami.ddiag <= mcdo.testen & "000"; -- data ram inputs dcrami.denable <= enable; dcrami.address(19 downto (OFFSET_HIGH - LINE_LOW + 1)) <= zero32(19 downto (OFFSET_HIGH - LINE_LOW + 1)); dcrami.address(OFFSET_HIGH - LINE_LOW downto 0) <= taddr; dcrami.data <= ddatainv; dcrami.dwrite <= cdwrite; dcrami.ldramin.address(23 downto 2) <= laddr(23 downto 2); dcrami.ldramin.enable <= (lramcs or lramwr) and not mcdo.scanen; dcrami.ldramin.read <= rlramrd; dcrami.ldramin.write <= lramwr; dcrami.dpar <= (others => (others => '0')); dcrami.tpar <= (others => (others => '0')); dcrami.ctx <= (others => (others => '0')); dcrami.ptag <= (others => (others => '0')); dcrami.tpwrite <= (others => '0'); -- 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; mcdi.req <= r.req; mcdi.cache <= orv(r.cctrl.dcs); -- diagnostic instruction cache access 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; dco.icdiag.ilramen <= r.ilramen; dco.icdiag.cctrl <= r.cctrl; dco.icdiag.scanen <= mcdo.scanen; dco.icdiag.pflush <= '0'; dco.icdiag.ctx <= '0'; dco.icdiag.ilock <= (others => '0'); dco.icdiag.pflushaddr <= (others => '0'); -- IU data cache inputs dco.data <= rdatav; dco.mexc <= mexc; dco.set <= conv_std_logic_vector(set, 2); dco.hold <= r.holdn; dco.mds <= mds; dco.werr <= mcdo.werr; dco.idle <= sidle and not r.stpend; dco.scanen <= mcdo.scanen; dco.testen <= mcdo.testen; end process;-- Local registers reg1 : process(clk) begin if rising_edge(clk) then r <= c; if rst = '0' then r.wb.lock <= '0'; end if; --sync reset for wb.lock must be generated here to make --gate level simulations possible with some synthesis tools end if; end process; sn2 : if DSNOOP /= 0 generate reg2 : process(sclk) begin if rising_edge(sclk ) then rs <= cs; end if; end process; end generate; nosn2 : if DSNOOP = 0 generate rs.snoop <= '0'; rs.writebp <= (others => '0'); rs.addr <= (others => '0'); rs.readbpx <= (others => '0'); end generate; sn3 : if DSNOOP = 2 generate reg3 : process(sclk) begin if rising_edge(sclk ) then rh <= ch; end if; end process; end generate; nosn3 : if DSNOOP /= 2 generate rh.hit <= (others => (others => '0')); rh.taddr <= (others => '0'); rh.set <= (others => '0'); end generate; reg2 : if (DSETS>1) and (drepl = lru) generate reg2 : process(clk) begin if rising_edge(clk ) then rl <= cl; end if; end process; end generate; noreg2 : if (DSETS = 1) or (drepl /= 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 ((DSETS > 2) and (drepl = 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 + -