iu.vhd

来自「宇航级微处理器LEON2 2.2 VHDL源代码,很难找的.」· VHDL 代码 · 共 1,918 行 · 第 1/5 页

VHD
1,918
字号
        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 = iterative then	    if de.cnt = "10" then write_reg := '1'; end if;	  end if;        when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;	when FPOP1 | FPOP2 => null;        when others => write_reg := '1';        end case;      when LDST =>        ctrl.ld := not op3(2);        if (op3(2) = '0') and 	  not ((CPEN or (FPTYPE = fpc)) 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 ((FPTYPE = meiko) 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 (((FPTYPE = meiko) 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 | RDPSR | RDTBR =>           ldcheck1 := '0'; ldcheck2 := '0';	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 ((FPTYPE = meiko) 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 (((FPTYPE = meiko) 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 ((FPTYPE = meiko) 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;    if ICC_HOLD then      bicc_hold := 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 ((FPTYPE = meiko) 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 FPTYPE = fpc then cpldlock := cpldlock or fpo.ldlock; end if;      ldlock := ldlock or cpo.ldlock;     end if;    if FPTYPE = fpc 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'; echeck1 := '0';     if (rs1 = "00000") and not (((FPTYPE = meiko) 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 	  echeck1 := '1';        end if;      end if;    end if;    rs2data := rfo.data2(31 downto 0); ldbp2 := '0'; echeck2 := '0';     if (operand2_select = ALU_SIMM) then      rs2data := immediate_data;    elsif (rs2 = "00000") and not (((FPTYPE = meiko) 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 	  echeck2 := '1';        end if;      end if;    end if;    exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;-- 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.y(0);    else      y0 := wr.y(0);    end if;    ymsb := '-';    case op is    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'); echeck2 := '0'; end if;      when UMUL | SMUL | UMULCC | SMULCC =>	if MULTIPLIER = iterative then	  case de.cnt is	  when "00" => 	    rs2data := (others => '0'); echeck2 := '0'; ymsb := rs1data(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'; echeck2 := '0';	    end if;	  when others =>             if (op3 = UMUL) or (op3 = UMULCC) then	      rs2data := ex.result; echeck2 := '1';	      if rfo.data2(31) = '0' then		rs1data := (others => '0');	      end if;	    else	      rs1data := ex.result; echeck1 := '1';	      if rfo.data1(31) = '0' then		rs2data := (others => '0'); echeck2 := '0';	      end if;	    end if;	  end case;	end if;      when others => null;      end case;    when others => null;    end case;-- 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 (FPTYPE = fpc) 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 ((FPTYPE = meiko) 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;        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;--  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;    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 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;    if (annul_next = '1') or (rst = '0') then      cnt := (others => '0'); mulcnt := (others => '0');    end if;    fecomb.hold_pc <= hold_pc;    fecomb.branch <= branch;

⌨️ 快捷键说明

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