iu.vhd

来自「sparc org, vhdl rtl code」· VHDL 代码 · 共 1,813 行 · 第 1/5 页

VHD
1,813
字号
    when FMT3 =>
      case op3 is
      when MULSCC =>
	ymsb := rs1data(0); rs1data := (icc(3) xor icc(1)) & rs1data(31 downto 1);
        if y0 = '0' then 
	  rs2data := (others => '0'); rfenable2 := '0'; ldbp2 := '0';
	end if;
      when UMUL | SMUL | UMULCC | SMULCC =>
	if MULTIPLIER = iterative then
	  case de.cnt is
	  when "00" => 
	    rs2data := (others => '0'); ymsb := rs1data(0); rfenable2 := '0';
	  when "01" | "10" =>
	    ymsb := ex.result(0);
            rs1data := (ex.micc(3) xor ex.micc(1)) & ex.result(31 downto 1);
            if (mein.y(0) = '0') or (de.cnt = "10") then
	      rs2data := (others => '0'); ldbp2 := '0'; rfenable2 := '0';
	    end if;
	  when others => 
            if (op3 = UMUL) or (op3 = UMULCC) then
	      rs2data := ex.result; rfenable2 := '1';
	      if rfo.data2(31) = '0' then
		rs1data := (others => '0');
	      end if;
	    else
	      rs1data := ex.result; rfenable1 := '1';
	      if rfo.data1(31) = '0' then
		rs2data := (others => '0'); rfenable2 := '0';
	      end if;
	    end if;
	  end case;
	end if;
      when others => null;
      end case;
    when others => null;
    end case;

    exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;

-- PC generation

    branch := '0'; annul_next := '0'; annul_current := '0';
    inull := not Rst; hold_pc := '0'; ticc_exception := '0';
    fpop := '0'; fpld := '0';
    if ((ldlock or de.annul) = '0') then
      case op is
      when CALL =>
        branch := '1';
	if mein.inull = '1' then 
	  hold_pc := '1'; annul_current := '1';
	end if;
      when FMT2 =>
        if (op2 = BICC) or (FPEN and (op2 = FBFCC)) or (CPEN and (op2 = CBCCC)) then
          if (FPEN and (op2 = FBFCC)) then 
	    branch := fbranch_true;
	    if (FPIFTYPE = parallel) and (fpo.ccv /= '1') then 
	      hold_pc := '1'; annul_current := '1';
	    end if;
          elsif (CPEN and (op2 = CBCCC)) then 
	    branch := cbranch_true;
	    if cpo.ccv /= '1' then hold_pc := '1'; annul_current := '1'; end if;
	  else branch := branch_true; end if;
	  if hold_pc = '0' then
  	    if (branch = '1') then
              if (cond = BA) and (annul = '1') then annul_next := '1'; end if;
            else annul_next := annul; end if;
	    if mein.inull = '1' then -- contention with JMPL
	      hold_pc := '1'; annul_current := '1'; annul_next := '0';
	    end if;
	  end if;
        end if;
      when FMT3 =>
        case op3 is
	when FPOP1 | FPOP2 =>
	  if ((FPIFTYPE = serial) and FPEN) then
            case de.cnt is
            when "00" =>
	      if (opf(1) or fpexin.dsz) = '1' then 
		hold_pc := '1'; pv := '0'; cnt := "01";
	      end if;
	      if (opf(1) or fpmov) = '0' then fpop := holdn; end if;
	      if op3 = FPOP1 then write_reg := not (opf(1) and not fpexin.dsz); end if;
            when others =>
	      if op3 = FPOP1 then write_reg := '1'; end if;
	      fpop := opf(1) and holdn; cnt := "00";
	    end case;
	  end if;
        when UMUL | SMUL | UMULCC | SMULCC =>
	  if MULTIPLIER = iterative then
            case de.cnt is
            when "00" =>
 	      cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
            when "01" =>
 	      hold_pc := '1'; pv := '0'; cnt := "01"; mulcnt := mulcnt + 1;
 	      if (de.mulcnt = "11111") then cnt := "10"; end if;
            when "10" =>
 	      cnt := "11"; pv := '0'; hold_pc := '1';
            when "11" =>
 	      cnt := "00"; 
            when others => null;
	    end case;
	  end if;
	  if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then
            case de.cnt is
            when "00" =>
 	      cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
	      mulstart := '1';
            when "01" =>
 	      if mulo.ready = '1' then cnt := "00"; 
              else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
            when others => null;
	    end case;
	  end if;
        when UDIV | SDIV | UDIVCC | SDIVCC =>
	  if DIVIDER /= none then
            case de.cnt is
            when "00" =>
 	      cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
	      divstart := '1';
            when "01" =>
 	      if divo.ready = '1' then cnt := "00"; 
              else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
            when others => null;
	    end case;
	  end if;
        when TICC =>
	  if branch_true = '1' then ticc_exception := '1'; end if;
        when RETT =>
          ctrl.rett := '1'; su := sregs.ps; 
        when others => null;
        end case;
      when LDST =>
        case de.cnt is
        when "00" =>
          if (op3(2) = '1') or (op3(1 downto 0) = "11") then -- ST/LDST/SWAP/LDD
 	    cnt := "01"; hold_pc := '1'; pv := '0';
          end if;
        when "01" =>
          if (op3(2 downto 0) = "111") or (op3(3 downto 0) = "1101") or
             ((CPEN or FPEN) and ((op3(5) & op3(2 downto 0)) = "1110"))
	  then	-- LDD/STD/LDSTUB/SWAP
 	    cnt := "10"; pv := '0'; hold_pc := '1';
	  else
 	    cnt := "00";
          end if;
        when "10" =>
 	  cnt := "00";
        when others => null;
	end case;
      when others => null;
      end case;
    end if;

    muli.start  <= mulstart;
    divi.start  <= divstart;

-- instruction watchpoints

    watchpoint_exc := '0';
    for i in 0 to WATCHPOINTS-1 loop
      if ((tr(i).exec and not de.annul) = '1') then
         if (((tr(i).addr xor de.pc(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)) then
           watchpoint_exc := '1';
	 end if;
      end if;
    end loop;

    if DEBUG_UNIT then
      if  ((iui.debug.dsuen and iui.debug.bwatch and not de.annul) = '1') then
        watchpoint_exc := de.pv and (watchpoint_exc or iui.debug.dbreak or de.step);
      end if;
    end if;

--  prioritise traps

    ctrl.trap := de.mexc or privileged_inst or illegal_inst or fp_disabled or
	cp_disabled or ticc_exception or winunf_exception or
	winovf_exception or fp_exception or watchpoint_exc;

    if de.mexc = '1' then ctrl.tt := IAEX_TT;
    elsif privileged_inst = '1' then ctrl.tt := PRIV_TT; 
    elsif illegal_inst = '1' then ctrl.tt := IINST_TT;
    elsif fp_disabled = '1' then ctrl.tt := FPDIS_TT;
    elsif cp_disabled = '1' then ctrl.tt := CPDIS_TT;
    elsif watchpoint_exc = '1' then ctrl.tt := WATCH_TT;
    elsif winovf_exception = '1' then ctrl.tt := WINOF_TT;
    elsif winunf_exception = '1' then ctrl.tt := WINUF_TT;
    elsif fp_exception = '1' then ctrl.tt := FPEXC_TT;
    elsif ticc_exception = '1' then ctrl.tt := TICC_TT;
    end if;


    hold_pc := (hold_pc or ldlock) and not wr.annul_all;

    if hold_pc = '1' then dein.pc <= de.pc;
    else dein.pc <= fe.pc; end if;

    annul_current_cp := annul_current;
    annul_current := (annul_current or ldlock or wr.annul_all);
    ctrl.annul := de.annul or wr.annul_all or annul_current;
    pv := pv and not ((mein.inull and not hold_pc) or wr.annul_all);
    annul_next := (mein.inull and not hold_pc) or annul_next or wr.annul_all
                  or (ldlock and de.annul);                                    
    if (annul_next = '1') or (rst = '0') then
      cnt := (others => '0'); mulcnt := (others => '0');
    end if;

    if DEBUG_UNIT then
      step := iui.debug.step and pv and not de.annul;
    end if;
    fecomb.hold_pc <= hold_pc;
    fecomb.branch <= branch;
    dein.annul <= annul_next;
    dein.cnt <= cnt;
    dein.mulcnt <= mulcnt;
    dein.step <= step;
    dein.pv <= pv;
    -- pv means that the corresponding pc can be save on a trap
    ctrl.pv := de.pv and 
		not ((de.annul and not de.pv) or wr.annul_all or annul_current);
    inull := inull or mein.inull or hold_pc or wr.annul_all;

    ici.nullify <= inull;
    ici.su <= su;
    exin.ctrl <= ctrl;
    exin.write_reg <= write_reg;

-- latch next cwp

    if wr.trapping = '1' then
      dein.cwp <= sregsin.cwp;
    elsif (write_cwp and not ctrl.annul) = '1' then
      dein.cwp <= cwp_new;
    elsif (ex.write_cwp and not ex.ctrl.annul) = '1' then
      dein.cwp <= ex.cwp;
    elsif (me.write_cwp and not me.ctrl.annul) = '1' then
      dein.cwp <= me.cwp;
    elsif (wr.write_cwp and not wr.ctrl.annul) = '1' then
      dein.cwp <= wr.cwp;
    else
      dein.cwp <= sregs.cwp;
    end if;


-- y-register write select and forwarding

    rst_mey := '0';

    case op is
    when FMT3 =>
      case op3 is
      when MULSCC => write_y := '1';
      when WRY => if rd = "00000" then write_y := '1'; end if;
      when  UMAC | SMAC  =>
	if MACEN then write_y := '1'; end if;
      when  UMUL | SMUL | UMULCC | SMULCC =>
	if MULTIPLIER = iterative then
          if de.cnt = "00" then rst_mey := '1'; end if;
	  if de.cnt = "11" then write_y := '1'; end if;
	end if;
	if MULTIPLIER = m32x32 then write_y := '1'; end if;
      when others => null;
      end case;
    when others => null;
    end case;

-- debug unit diagnostic regfile read
    if DEBUG_UNIT and (dsur.dmode and iui.debug.denable) = '1' then
      read_addr1 := iui.debug.daddr(RABITS+1 downto 2); rfenable1 := '1';
    end if;

    exin.write_y <= write_y;
    exin.rst_mey <= rst_mey;
    exin.rs1data <= rs1data;
    exin.rs2data <= rs2data;
    exin.ymsb <= ymsb;
    rfi.rd1addr <= read_addr1; rfi.rd2addr <= read_addr2;

-- CP/FPU interface

    if (FPIFTYPE = serial) then
      fpu_regin.fpop <= fpop and (not fpu_reg.fpld) and not ctrl.annul;
      fpexin.ldfsr := fsr_ld;
      fpu_regin.ex <= fpexin;
    end if;

    if CPEN then
      cpi.dannul <= annul_current_cp or cpldlock or wr.annul_all or de.annul;
      cpi.dtrap  <= ctrl.trap;
    end if;

    if FPIFTYPE = parallel then
      fpi.dannul <= annul_current_cp or fpldlock or wr.annul_all or de.annul;
      fpi.dtrap  <= ctrl.trap;
      fpi.fdata  <= ico.data;
      fpi.frdy <= (not ico.mds) or (holdn and not hold_pc);            
    end if;


    if RF_LOWPOW = false then rfenable1 := '1'; rfenable2 := '1';  end if;
    rfi.ren1 <= rfenable1; rfi.ren2 <= rfenable2;

  end process;

-------------------------------------------------------------------------------
-- execute stage
-------------------------------------------------------------------------------


  execute_stage : process(rst, de, ex, me, wr, wrin, sregs, fpu_reg, fpu_regin, 
			  fpo, cpo, fpuo, mulo, divo, tr, iui, dsur, sum32)

  variable op     : std_logic_vector(1 downto 0);
  variable op3    : std_logic_vector(5 downto 0);
  variable opf    : std_logic_vector(8 downto 0);
  variable rs1    : std_logic_vector(4 downto 0);
  variable inull, jump, link_pc : std_logic;
  variable dcache_write : std_logic;	-- Load or store cycle
  variable memory_load : std_logic;
  variable signed           : std_logic;
  variable enaddr           : std_logic;
  variable force_a2         : std_logic;     -- force A(2) in second LDD cycle
  variable addr_misal       : std_logic;     -- misaligned address (JMPL/RETT)
  variable ld_size          : std_logic_vector(1 downto 0); -- Load size
  variable read             : std_logic;
  variable su      : std_logic;			-- Local supervisor bit
  variable asi              : std_logic_vector(7 downto 0); -- Local ASI
  variable ctrl : pipeline_control_type;
  variable res, y : std_logic_vector(31 downto 0);
  variable icc, licc, micc : std_logic_vector(3 downto 0);
  variable addout : std_logic_vector(31 downto 0);
  variable shiftout : std_logic_vector(31 downto 0);
  variable logicout : std_logic_vector(31 downto 0);
  variable miscout : std_logic_vector(31 downto 0);
  variable edata : std_logic_vector(31 downto 0);
  variable aluresult : std_logic_vector(31 downto 0);
  variable eaddress : std_logic_vector(31 downto 0);
  variable nexty : std_logic_vector(31 downto 0);
  variable aluin1, aluin2 : std_logic_vector(31 downto 0);
  variable shiftin : std_logic_vector(63 downto 0);
  variable shiftcnt : std_logic_vector(4 downto 0);
  variable ymsb : std_logic;		-- next msb of Y during MUL
  variable write_reg, write_icc, write_y : std_logic;
  variable lock : std_logic;
  variable dsu_cache : std_logic;
  variable fpmein : fpu_ctrl2_type;
  variable mulop1, mulop2 : std_logic_vector(32 downto 0);
  variable wpi : integer range 0 to 3;  -- watchpoint index
  variable addin2 : std_logic_vector(31 downto 0);
  variable cin : std_logic;

  begin

-- op-code decoding

    op    := ex.ctrl.inst(31 downto 30);
    op3   := ex.ctrl.inst(24 downto 19);
    opf   := ex.ctrl.inst(13 downto 5);
    rs1   := ex.ctrl.inst(18 downto 14);

-- common initialisation

    ctrl := ex.ctrl; memory_load := '0';

⌨️ 快捷键说明

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