⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmu_dcache.vhd

📁 sparc org, vhdl rtl code
💻 VHD
📖 第 1 页 / 共 4 页
字号:
            v.paddress := mmudco.transdata.data;
            if v.wbinit = '1' then
              v.wb.addr := mmudco.transdata.data;
              v.req := '1';
            end if;
          end if;
        else
          --mmudci_trans_op := '1';  -- start translation
        end if;
      end if;

    when wread => 		-- read miss, wait for memory data
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
      newtag := r.xaddress(TAG_HIGH downto TAG_LOW);
      v.nomds := r.nomds and not eholdn;
      v.holdn := v.nomds; rdatasel := memory;
      for i in 0 to DSETS-1 loop wlock(i) := r.lock; end loop;
      for i in 0 to 1 loop wlrr(i) := r.lrr; end loop;
      if (r.stpend = '0') and (r.ready = '0') then

        if mcdo.ready = '1' then
          mds := r.holdn or r.nomds; v.xaddress(2) := '1'; v.holdn := '1';
          if (mcdo.dcs = "01") then 
	    v.hit := mcdo.cache and r.hit and r.cache; twrite := v.hit;
          elsif (mcdo.dcs(1) = '1') then 
	    v.hit := mcdo.cache and (r.hit or not r.asi(2)) and r.cache; twrite := v.hit;
	  end if; 
          dwrite := twrite; rdatasel := memory;
          mexc := mcdo.mexc;

	  if r.req = '0' then

	    if (((dci.enaddr and not mds) = '1') or 
              ((dci.eenaddr and mds and eholdn) = '1')) and (mcdo.dcs(0) = '1') then
	      v.dstate := loadpend; v.holdn := '0';
	    else v.dstate := idle; end if;
	  else v.nomds := '1'; end if;
        end if;
	v.mexc := mcdo.mexc; v.wb.data2 := mcdo.data;
      else
	if (r.ready or (mcdo.ready and not r.req)) = '1' then	-- wait for store queue
	  v.burst := r.size(1) and r.size(0) and not r.xaddress(2);
          if (mmuisdis = '1') then
            v.wb.addr := r.xaddress;
          else
            v.wb.addr := r.paddress;
          end if;

          v.wb.size := r.size; 
	  v.wb.read := r.read; v.wb.data1 := dci.maddress; v.req := '1'; 
	  v.wb.lock := dci.lock; v.wb.asi := r.asi(3 downto 0); v.ready := '0';
        end if;
      end if;
    when loadpend =>		-- return from read miss with load pending
      taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW);
      v.dstate := idle; 
    when dblwrite => 		-- second part of double store cycle
      v.dstate := idle; v.wb.data2 := dci.edata; 
      edata := dci.edata;  -- needed for STD store hit
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); 
      if (mcdo.dcs(0) = '1') and (r.hit = '1') then dwrite := '1'; end if;

    when asi_idtag =>		-- icache diag access
      rdatasel := icache; v.icenable := '1'; v.holdn := '0';
      if  ico.diagrdy = '1' then
	v.dstate := loadpend; v.icenable := '0'; mds := not r.read;
      end if;
      
    when wtrans =>
      edata := dci.edata;  -- needed for STD store hit
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); 
          
      if M_EN then
        if r.stpend = '1' then
          if ((mcdo.ready and not r.req) = '1') then	
            v.ready := '1';       -- buffer store finish
          end if;
        end if;

        -- fetch dblwrite data 2, does the same as state dblwrite,
        -- except that init of data2 is omitted to end of translation or in wwrite
        if ((r.dblwdata) = '1') and ((r.size) = "11") then  
          v.dblwdata := '0';
          --if (mcdo.dcs(0) = '1') and (r.hit = '1') then dwrite := '1'; end if;
        end if;
        
        v.holdn := '0';
        if mmudco.transdata.finish = '1' then        
          if (mmudco.transdata.accexc) = '1' then
            v.holdn := '1'; v.dstate := idle;
            mds := '0'; mexc := not r.mmctrl1.nf;
            
            tagclear := mcdo.dcs(0) and r.hit;
            twrite := tagclear;
            
	    if (twrite = '1') and (((dci.enaddr and not mds) = '1') or 
              ((dci.eenaddr and mds and eholdn) = '1')) and (mcdo.dcs(0) = '1') then
	      v.dstate := loadpend; v.holdn := '0';
	    end if;
            
          else
            v.dstate := wwrite;
            v.cache := mmudco.transdata.cache;
            --v.xaddress := mmudco.data;
            v.paddress := mmudco.transdata.data;
            
            if (r.wbinit) = '1' then
              v.wb.data2 := dci.edata; 
              v.wb.addr := mmudco.transdata.data;
              v.dstate := idle;  v.holdn := '1'; 
              v.req := '1'; v.stpend := '1';
              v.burst := r.size(1) and r.size(0) and not v.wb.addr(2);

              if (mcdo.dcs(0) = '1') and (r.hit = '1') and (r.size = "11")  then  -- write hit
                dwrite := '1';
              end if;
            end if;
          end if;
        else
          -- mmudci_trans_op := '1';  -- start translation
        end if;

      end if;
        
    when wwrite => 		-- wait for store buffer to empty (store access)
      edata := dci.edata;  -- needed for STD store hit

      if (v.ready or (mcdo.ready and not r.req)) = '1' then	-- store queue emptied

        --if (mmuisdis = '1') then
          if (mcdo.dcs(0) = '1') and (r.hit = '1') and (r.size = "11")  then  -- write hit
            taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); dwrite := '1';
          end if;
        --end if;
        v.dstate := idle; 

	v.req := '1'; v.burst := r.size(1) and r.size(0); v.stpend := '1';

        if (mmuisdis = '1') then
          v.wb.addr := r.xaddress;
        else
          v.wb.addr := r.paddress;
        end if;
        
	--v.wb.addr := r.xaddress;
        v.wb.size := r.size;
	v.wb.read := r.read; v.wb.data1 := dci.maddress;
	v.wb.lock := dci.lock; v.wb.data2 := dci.edata;
	v.wb.asi := r.asi(3 downto 0); 
	if r.size = "11" then v.wb.addr(2) := '0'; end if;
      else  -- hold cpu until buffer empty
        v.holdn := '0';
      end if;
      
    when wflush => 
      v.holdn := '0';
      if mmudco.transdata.finish = '1' then        
        v.dstate := idle; v.holdn := '1';
      end if;
      
    when others => v.dstate := idle;
    end case;

    if M_EN then
      if DEBUG_UNIT and dci.dsuen = '1' then 
	mmudiagaddr := r.xaddress(4 downto 2); 
	mmuregw := dci.write and not dci.eenaddr; mmuwdata := dci.maddress;
      else 
	mmudiagaddr := dci.maddress(CNR_U downto CNR_D); mmuwdata := dci.edata;
      end if;
      case mmudiagaddr is
      when CNR_CTRL => 
        mmudata(MMCTRL_E) := r.mmctrl1.e; 
        mmudata(MMCTRL_NF) := r.mmctrl1.nf; 
        mmudata(MMCTRL_PSO) := r.mmctrl1.pso;
        mmudata(MMCTRL_VER_U downto MMCTRL_VER_D) := "0000";
        mmudata(MMCTRL_IMPL_U downto MMCTRL_IMPL_D) := "0000";
        mmudata(23 downto 21) := std_logic_vector(conv_unsigned(M_ENT_ILOG,3));
        mmudata(20 downto 18) := std_logic_vector(conv_unsigned(M_ENT_DLOG,3));
	if M_TLB_TYPE = splittlb then mmudata(17) := '1'; else
          mmudata(23 downto 21) := std_logic_vector(conv_unsigned(M_ENT_CLOG,3));
          mmudata(20 downto 18) := (others => '0');
	end if;
        mmudata(MMCTRL_TLBDIS) := r.mmctrl1.tlbdis;
        --custom 
      when CNR_CTXP =>
        mmudata(MMCTXP_U downto MMCTXP_D) := r.mmctrl1.ctxp; 
      when CNR_CTX => 
        mmudata(MMCTXNR_U downto MMCTXNR_D) := r.mmctrl1.ctx; 
      when CNR_F =>
        mmudata(FS_OW) := mmudco.mmctrl2.fs.ow;
        mmudata(FS_FAV) := mmudco.mmctrl2.fs.fav;
        mmudata(FS_FT_U downto FS_FT_D) := mmudco.mmctrl2.fs.ft;
        mmudata(FS_AT_LS) := mmudco.mmctrl2.fs.at_ls;
        mmudata(FS_AT_ID) := mmudco.mmctrl2.fs.at_id;
        mmudata(FS_AT_SU) := mmudco.mmctrl2.fs.at_su;
        mmudata(FS_L_U downto FS_L_D) := mmudco.mmctrl2.fs.l;
        mmudata(FS_EBE_U downto FS_EBE_D) := mmudco.mmctrl2.fs.ebe;
      when CNR_FADDR => 
        mmudata(VA_I_U downto VA_I_D) := mmudco.mmctrl2.fa; 
      when others => null; 
      end case;
      if mmuregw = '1' then
        case mmudiagaddr is
        when CNR_CTRL =>
          v.mmctrl1.e      := mmuwdata(MMCTRL_E);
          v.mmctrl1.nf     := mmuwdata(MMCTRL_NF);
          v.mmctrl1.pso    := mmuwdata(MMCTRL_PSO);
          v.mmctrl1.tlbdis := mmuwdata(MMCTRL_TLBDIS);
          --custom 
          -- Note: before tlb disable tlb flush is required !!!  
        when CNR_CTXP =>
          v.mmctrl1.ctxp := mmuwdata(MMCTXP_U downto MMCTXP_D);
        when CNR_CTX =>
          v.mmctrl1.ctx  := mmuwdata(MMCTXNR_U downto MMCTXNR_D);
        when CNR_F => null;
        when CNR_FADDR => null;
        when others => null;
        end case;
      end if;
      miscdata := mmudata;
    end if;

    dsudata := (others => '0');
    if DEBUG_UNIT and dci.dsuen = '1' then
      if (DSETS > 1) then
-- pragma translate_off
        if not is_x(r.xaddress) then
-- pragma translate_on          
          v.dsuset := r.xaddress(TAG_LOW+SETBITS-1 downto TAG_LOW);
-- pragma translate_off          
        end if;
        if not is_x(r.dsuset) then
-- pragma translate_on          
        rdsuset := conv_integer(r.dsuset);
-- pragma translate_off          
        end if;
-- pragma translate_on          

      end if;
      case dci.asi(4 downto 0) is
      when ASI_ITAG | ASI_IDATA =>		-- Read/write Icache tags
	v.icenable := not ico.diagrdy;
        dsudata := ico.diagdata;
      when ASI_DTAG  => 
	if dci.write = '1' then 
	  twrite := not dci.eenaddr; tdiagwrite := '1';
        end if;
        dsudata(TAG_HIGH downto TAG_LOW) := dcramov.dtramout(rdsuset).tag;
        dsudata(DLINE_SIZE -1 downto 0)  := dcramov.dtramout(rdsuset).valid;
        dsudata(DCTAG_LRRPOS)  := dcramov.dtramout(rdsuset).lrr;
        dsudata(DCTAG_LOCKPOS) := dcramov.dtramout(rdsuset).lock;
      when ASI_DCTX =>
        dsudata(M_CTX_SZ-1 downto 0) := dcramov.dtramout(rdsuset).ctx;
      when ASI_DDATA =>
	--if (dci.write and r.dsuwren) = '1' then dwrite := '1'; ddiagwrite := '1'; end if;
        if dci.write = '1' then
          dwrite := not dci.eenaddr; ddiagwrite := '1';
        end if;
        dsudata := dcramov.ddramout(rdsuset).data;
--      when ASI_MMUREGS =>
      when ASI_MMU_DSU =>
   	if M_EN then dsudata := mmudata; end if;
      when others =>
      end case;
    end if;

-- select data to return on read access
-- align if byte/half word read from cache or memory.

    rdata := (others => '0'); 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 misc =>
      if M_EN then
        rdata := miscdata;
      end if;
    when dddata => 
      rdata := dcramov.ddramout(ddset).data;
    when dtag => 
      rdata(TAG_HIGH downto TAG_LOW) := dcramov.dtramout(ddset).tag;
      rdata(DLINE_SIZE -1 downto 0) := dcramov.dtramout(ddset).valid;
      rdata(DCTAG_LRRPOS)  := dcramov.dtramout(ddset).lrr;
      rdata(DCTAG_LOCKPOS) := dcramov.dtramout(ddset).lock;
    when dctx =>
      rdata(M_CTX_SZ-1 downto 0) := dcramov.dtramout(ddset).ctx;
    when icache => rdata := ico.diagdata;       
    when ddata | memory =>
      if DREAD_FAST then
        if rdatasel = memory then
        case size is
        when "00" => 			-- byte read
          case maddrlow is
	  when "00" => 
	    rdata(7 downto 0) := mcdo.data(31 downto 24);
	    if signed = '1' then rdata(31 downto 8) := (others => mcdo.data(31)); end if;
	  when "01" => 
	    rdata(7 downto 0) := mcdo.data(23 downto 16);
	    if signed = '1' then rdata(31 downto 8) := (others => mcdo.data(23)); end if;
	  when "10" => 
	    rdata(7 downto 0) := mcdo.data(15 downto 8);
	    if signed = '1' then rdata(31 downto 8) := (others => mcdo.data(15)); end if;
	  when others => 
	    rdata(7 downto 0) := mcdo.data(7 downto 0);
	    if signed = '1' then rdata(31 downto 8) := (others => mcdo.data(7)); end if;
          end case;
        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" => 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -