📄 dcache.vhd
字号:
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_on
end ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -