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 + -
显示快捷键?