iu.vhd

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

VHD
1,813
字号
      when "01" =>
	if (op3(2) and not op3(3)) = '1' then  -- ST
	  rs1 := rd; rs1mod := '1';
	end if;
	case op3 is
	when LDD | LDDA | LDDC =>
          rd(0) := '1'; alusel := ALU_RES_ADD;
	when LDDF => 
          rd(0) := '1'; alusel := ALU_RES_ADD;
	  if FPEN then fpld := '1'; end if;
	when STFSR => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_FSR; end if;
	when SWAP | SWAPA | LDSTUB | LDSTUBA =>
          alusel := ALU_RES_ADD;
	when STF | STDF =>
	  if ((FPIFTYPE = serial) and FPEN) then
            aluop := ALU_PASS1; fpst := '1'; 
	  end if;
	when others =>
          aluop := ALU_PASS1;
	  if op3(2) = '1' then  -- ST
	    if op3(1 downto 0) = "01" then	-- store byte
	      aluop := ALU_STB;
	    elsif op3(1 downto 0) = "10" then	-- store halfword
	      aluop := ALU_STH;
	    end if;
          end if;
        end case;
      when "10" =>
        aluop := ALU_PASS1;
	rs1 := rd;  rs1mod := '1';
        if op3(2) = '1' then  -- ST
          if (op3(3) and not op3(1))= '1' then aluop := ALU_ONES;  -- LDSTUB/A
          elsif op3(3 downto 0) = "0111" then
	    rs1(0) := '1';  -- STD/F/A
	    if ((FPIFTYPE = serial) and FPEN) and (op3(5) = '1') then fpst := '1'; end if;
          end if;
        end if;
      when others =>
      end case;

    end case;

    exin.aluop <= aluop; exin.alusel <= alusel; exin.aluadd <= aluadd;
    exin.mulstep <= mulstep; exin.mulinsn <= mulinsn;

-- Alu operand select

    operand2_select := ALU_SIMM;

    case op is
    when FMT2 =>
      case op2 is
      when SETHI => operand2_select := ALU_SIMM;
      when others => operand2_select := ALU_RS2;
      end case;
    when FMT3 =>
      case op3 is
      when RDWIM | RDPSR | RDTBR => operand2_select := ALU_SIMM;
      when FPOP1 | FPOP2 => if ((FPIFTYPE = serial) and FPEN) then operand2_select := ALU_RS2; end if;
      when others =>
        if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
	else operand2_select := ALU_RS2; end if;
      end case;
    when LDST => 
      if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
      else operand2_select := ALU_RS2; end if;
    when others => operand2_select := ALU_RS2;
    end case;


-- CWP generation, pipelinig and forwarding
-- Also check for window underflow/overflow conditions

    if (op = FMT3) and ((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE)) then
      write_cwp := '1';
      if (op3 = SAVE) then
-- pragma translate_off
        if not is_x(de.cwp) then
-- pragma translate_on
	  if (not CWPOPT) and (de.cwp = CWPMIN) then cwp_new := CWPMAX;
          else cwp_new := de.cwp - 1 ; end if;
-- pragma translate_off
	end if;
-- pragma translate_on
      else
-- pragma translate_off
        if not is_x(de.cwp) then
-- pragma translate_on
	  if (not CWPOPT) and (de.cwp = CWPMAX) then cwp_new := CWPMIN;
          else cwp_new := de.cwp + 1; end if;
-- pragma translate_off
        end if;
-- pragma translate_on
      end if;

      if sregs.wim(conv_integer('0' & cwp_new)) = '1' then
	if op3 = SAVE then winovf_exception := '1';
	else winunf_exception := '1'; end if;
      end if;
    end if;
  
    exin.write_cwp <= write_cwp;
    exin.cwp <= cwp_new;

-- Immediate data generation

    immediate_data := (others => '0');
    case op is
    when FMT2 =>
      immediate_data := de.inst(21 downto 0) & "0000000000";
    when FMT3 =>
      case op3 is
      when RDPSR => immediate_data(31 downto 5) := std_logic_vector(IMPL) &
        std_logic_vector(VER) & icc & "000000" & sregs.ec & sregs.ef & 
	sregs.pil & su & sregs.ps & et;
	immediate_data(NWINLOG2-1 downto 0) := de.cwp;
      when RDTBR => immediate_data(31 downto 4) := sregs.tba & sregs.tt;
      when RDWIM => immediate_data(NWINDOWS-1 downto 0) := sregs.wim;
      when others =>
        immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
            de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
            de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
            de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
            de.inst(12 downto 0);
      end case;
    when others =>	-- LDST
      immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
          de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
          de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
          de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
          de.inst(12 downto 0);
    end case;

-- register read address generation

    if RS1OPT then
      if rs1mod = '1' then 
        read_addr1 := regdec(de.cwp, de.inst(29 downto 26) & rs1(0), (fpst or fpop)); 
      else
        read_addr1 := regdec(de.cwp, de.inst(18 downto 15) & rs1(0), (fpst or fpop)); 
      end if;
    else
      read_addr1 := regdec(de.cwp, rs1, (fpst or fpop)); 
    end if;
    read_addr2 := regdec(de.cwp, rs2, fpop); 


-- register write address generation

    write_reg := '0'; fsr_ld := '0';

    case op is
    when CALL =>
        write_reg := '1'; rd := "01111";    -- CALL saves PC in r[15] (%o7)
    when FMT2 => 
        if (op2 = SETHI) then write_reg := '1'; end if;
    when FMT3 =>
        case op3 is
	when UMUL | SMUL | UMULCC | SMULCC => 
	  if MULTIPLIER = none then write_reg := '1'; end if;
	  if MULTIPLIER = m32x32 then write_reg := '1'; end if;
	  if MULTIPLIER = iterative then
	    if de.cnt = "10" then write_reg := '1'; end if;
	  end if;
	when UDIV | SDIV | UDIVCC | SDIVCC => 
	  if DIVIDER /= none then write_reg := '0'; else write_reg := '1'; end if;
        when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
	when FPOP1 | FPOP2 => null;
	when CPOP1 | CPOP2 => null;
        when others => write_reg := '1';
        end case;
      when LDST =>
        ctrl.ld := not op3(2);
        if (op3(2) = '0') and 
	  not ((CPEN or (FPIFTYPE = parallel)) and (op3(5) = '1')) 
        then write_reg := '1'; end if;
        case op3 is
        when SWAP | SWAPA | LDSTUB | LDSTUBA =>
	  if de.cnt = "00" then write_reg := '1'; end if;
	when LDFSR => if ((FPIFTYPE = serial) and FPEN) then write_reg := '0';  fsr_ld := '1'; end if;
        when others => null;
        end case;
      when others => null;
    end case;

    if (rd = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpld = '1')) then
      write_reg := '0';
    end if;

    ctrl.rd := regdec(cwp_new, rd, (fpld or fpop)); 
    if RDOPT then chkrd := regdec(de.cwp, rd, (fpld or fpop)); 
    else chkrd := ctrl.rd; end if;

-- LD/BICC/TICC delay interlock generation

    ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0';
    ldchkex := '1'; ldchkme := '1'; bicc_hold := '0'; icc_check := '0';
    fsr_check := '0'; fsr_ld_check := '0'; fsr_lock := '0';

    if (de.annul = '0') then
      case op is
      when FMT2 =>
	if (op2 = BICC) and (cond(2 downto 0) /= "000") then 
	  icc_check := '1';
	end if;
      when FMT3 =>
        ldcheck1 := '1'; ldcheck2 := not i;
        case op3 is
	when TICC =>
	  if (cond(2 downto 0) /= "000") then icc_check := '1'; end if;
        when RDY | RDWIM | RDTBR => 
          ldcheck1 := '0'; ldcheck2 := '0';
        when RDPSR => 
          ldcheck1 := '0'; ldcheck2 := '0'; 
	  if MULTIPLIER = m32x32 then icc_check := '1'; end if;
	when ADDX | ADDXCC | SUBX | SUBXCC =>
	  if MULTIPLIER = m32x32 then icc_check := '1'; end if;
	when UMUL | SMUL | UMULCC | SMULCC =>
	  if MULTIPLIER = iterative then
            ldcheck1 := '0'; ldcheck2 := '0';
	    if (de.cnt = "00") then ldcheck1 := '1'; end if;
            if (de.cnt = "01") then ldcheck2 := not i; end if;
	  end if;
	when FPOP1 | FPOP2 =>
	  if ((FPIFTYPE = serial) and FPEN) then
            ldcheck1 := '0'; ldcheck2 := '0';
	    case opf is
	    when FITOS | FITOD | FSTOI | FDTOI | FSTOD | FDTOS | FMOVS |
	         FNEGS | FABSS | FSQRTS | FSQRTD =>
              ldcheck2 := '1';
	    when others => ldcheck1 := '1'; ldcheck2 := '1';
	    end case;
	    if de.cnt /= "00" then ldchkex := '0'; end if;
	    fsr_ld_check := '1';
	  end if;
        when others => 
        end case;
      when LDST =>
        ldcheck1 := '1'; ldchkex := '0';
	case de.cnt is
	when "00" => -- check store data dependency if 2-cycle load delay
          if (LDDELAY = 2) and (op3(2) = '1') and not (((FPIFTYPE = serial) and FPEN) and (op3 = STFSR)) 
	  then ldcheck3 := '1'; end if; 
          ldcheck2 := not i; ldchkex := '1';
	when "01" => ldcheck2 := not i;
	when others => ldchkme := '0';
        end case;
	if ((FPIFTYPE = serial) and FPEN) and ((op3 = LDFSR) or (op3 = STFSR)) then 
	  fsr_check := '1';
	  if (op3 = STFSR) then fsr_ld_check := '1'; end if;
	end if;
      when others => null;
      end case;
    end if;

-- MAC has two-cycle latency, check for data-dependecies
    if MACEN then
      if ((ex.mulinsn and ex.ctrl.inst(24) and ldchkex and not ex.ctrl.annul) = '1') and
        (((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
         ((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
         ((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
      then ldlock := '1'; end if;
    end if;

    if MACEN or (MULTIPLIER = m32x32) then
      bicc_hold := icc_check and ex.write_icc and ex.mulinsn and not ex.ctrl.annul;
    end if;
    if ICC_HOLD then
      bicc_hold := bicc_hold or (icc_check and ex.write_icc and not ex.ctrl.annul);
    end if;

    if ((ex.ctrl.ld and ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
        (((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
         ((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
         ((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
    then ldlock := '1'; end if;

    if ((me.ctrl.ld and me.write_reg and ldchkme and not me.ctrl.annul) = '1') and
      ((LDDELAY = 2) or ((fsr_ld_check and not fsr_check) = '1')) and
         (((ldcheck1 = '1') and (me.ctrl.rd = read_addr1)) or
          ((ldcheck2 = '1') and (me.ctrl.rd = read_addr2)))
    then ldlock := '1'; end if;

    if ((FPIFTYPE = serial) and FPEN) then
      if (fsr_check = '1') then
        fsr_lock := ((xorv(fpu_reg.ex.fpop) and not ex.ctrl.annul) or 
		     (xorv(fpu_reg.me.fpop) and not me.ctrl.annul) or
                     (xorv(fpu_reg.wr.fpop) and not wr.ctrl.annul));
      end if;
      if fsr_ld_check = '1' then
	fsr_lock := fsr_lock or (fpu_reg.ex.ldfsr and not ex.ctrl.annul)
	                     or (fpu_reg.me.ldfsr and not me.ctrl.annul)
	                     or (fpu_reg.wr.ldfsr and not wr.ctrl.annul);
      end if;
    end if;

    ldlock := ldlock or bicc_hold or fsr_lock; 
    cpldlock := ldlock; fpldlock := ldlock;
    if CPEN then 
      if FPIFTYPE = parallel then cpldlock := cpldlock or fpo.ldlock; end if;
      ldlock := ldlock or cpo.ldlock; 
    end if;
    if FPIFTYPE = parallel then 
      if CPEN then fpldlock := fpldlock or cpo.ldlock; end if;
      ldlock := ldlock or fpo.ldlock;
    end if;

-- data forwarding detection. Forward data if destination and source
-- registers are equal and destination register will be written.

    rs1data := rfo.data1(31 downto 0); ldbp1 := '0'; 
    if (rs1 = "00000") and not (((FPIFTYPE = serial) and FPEN) and ((fpop or fpst) = '1')) then
      rs1data := (others => '0');
    elsif ldcheck1 = '1' then
      if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and 
	  (read_addr1 = ex.ctrl.rd) 
      then
        rs1data := ex.result;
      else
	if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
          rs1data := mein.bpresult;
          if LDDELAY = 1 then ldbp1 := me.ctrl.ld; end if;
        elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr1 = wr.ctrl.rd) then
          rs1data := wr.result; 
        else rfenable1 := '1'; end if;
      end if;
    end if;

    rs2data := rfo.data2(31 downto 0); ldbp2 := '0'; 
    if (operand2_select = ALU_SIMM) then
      rs2data := immediate_data;
    elsif (rs2 = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpop = '1')) then
      rs2data := (others => '0');
    elsif ldcheck2 = '1' then
      if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and (read_addr2 = ex.ctrl.rd) then
        rs2data := ex.result;
      else
	if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
          rs2data := mein.bpresult;
          if LDDELAY = 1 then ldbp2 := me.ctrl.ld; end if;
        elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr2 = wr.ctrl.rd) then
          rs2data := wr.result;
        else rfenable2 := '1'; end if;
      end if;
    end if;

-- multiply operand generation

    if (ex.write_y and not ex.ctrl.annul) = '1' then
      y0 := mein.y(0);
    elsif (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1' then
      y0 := me.my(0);
    else
      y0 := wr.y(0);
    end if;

    ymsb := '-';

-- mul/div unit

    divi.y   <= (wr.y(31) and op3(0)) & wr.y;
    divstart := '0'; mulstart := '0';
    case op is

⌨️ 快捷键说明

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