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

📄 iu.vhd

📁 一个航天航空用的Sparc处理器(配美国欧洲宇航局用的R_tems嵌入式操作系统)的VHDL源代码
💻 VHD
📖 第 1 页 / 共 4 页
字号:
      end case;
    when FMT3 =>
      case op3 is
      when IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | SAVE | RESTORE |
	   TICC | JMPL | RETT  => alusel := ALU_RES_ADD;
      when ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV  => 
	alusel := ALU_RES_ADD; aluadd := '0';
      when MULSCC => alusel := ALU_RES_ADD; mulstep := '1';
      when UMUL | UMULCC => 
	if MULTIPLIER = iterative then
          case de.cnt is
	  when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
	  when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
	  when others => alusel := ALU_RES_ADD;
	  end case;
	end if;
      when SMUL | SMULCC => 
	if MULTIPLIER = iterative then
          case de.cnt is
	  when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
	  when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
	  when others => alusel := ALU_RES_ADD; aluadd := '0';
	  end case;
	end if;
      when IAND | ANDCC => aluop := ALU_AND; alusel := ALU_RES_LOGIC;
      when ANDN | ANDNCC => aluop := ALU_ANDN; alusel := ALU_RES_LOGIC;
      when IOR | ORCC  => aluop := ALU_OR; alusel := ALU_RES_LOGIC;
      when ORN | ORNCC  => aluop := ALU_ORN; alusel := ALU_RES_LOGIC;
      when IXNOR | XNORCC  => aluop := ALU_XNOR; alusel := ALU_RES_LOGIC;
      when XORCC | IXOR | WRPSR | WRWIM | WRTBR | WRY  => 
	aluop := ALU_XOR; alusel := ALU_RES_LOGIC;
      when RDPSR | RDTBR | RDWIM => aluop := ALU_PASS2;
      when RDY => aluop := ALU_RDY;
      when ISLL => aluop := ALU_SLL; alusel := ALU_RES_SHIFT;
      when ISRL => aluop := ALU_SRL; alusel := ALU_RES_SHIFT;
      when ISRA => aluop := ALU_SRA; alusel := ALU_RES_SHIFT;
      when others => aluop := ALU_NOP;
      end case;
    when others =>	-- LDST
      case ctrl.cnt is
      when "00" =>
        alusel := ALU_RES_ADD;
      when "01" =>
	case op3 is
	when LDD | LDDA =>
          rd(0) := '1'; alusel := ALU_RES_ADD;
	when SWAP | SWAPA | LDSTUB | LDSTUBA =>
          alusel := ALU_RES_ADD;
	when others =>
          aluop := ALU_PASS1;
	  if op3(2) = '1' then  -- ST
	    rs1 := rd;
	    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;
	case op3 is
	when SWAP | SWAPA | LDSTUB | LDSTUBA =>
	  rs1 := rd; 
	  if op3(1) = '0' then aluop := ALU_ONES; end if; -- LDSTUB(A)
	when ISTD | STDA =>
	  rs1 := rd(4 downto 1) & '1'; 	-- STD
	when others =>
	end case;
      when others =>
      end case;

    end case;

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

-- Alu operand select

    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 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(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

    case op is
    when FMT2 =>
      immediate_data := de.inst(21 downto 0) & "0000000000";
    when FMT3 =>
      case op3 is
      when RDPSR => immediate_data := IMPL & VER & icc & "000000" &
	sregs.ec & sregs.ef & sregs.pil & su & sregs.ps & et 
	& CWPFILL & de.cwp;
      when RDTBR => immediate_data := sregs.tba & sregs.tt & "0000";
      when RDWIM => immediate_data := WIMFILL & 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

    read_addr1(3 downto 0) := rs1(3 downto 0);
    read_addr2(3 downto 0) := rs2(3 downto 0);
    if rs1(4 downto 3) = "00" then
      read_addr1(RABITS -1 downto 4) := R0ADDR;
    else
-- pragma translate_off
      if not (is_x(de.cwp & rs1(4))) then
-- pragma translate_on
        read_addr1(NWINLOG2+3 downto 4) := (de.cwp + rs1(4));
	if not CWPOPT then
	  if read_addr1(RABITS-1 downto 4) = R0ADDR then
	    read_addr1(RABITS-1 downto 4) := (others => '0');
	  end if;
	else read_addr1(RABITS-1) := '0'; end if;
-- pragma translate_off
      end if;
-- pragma translate_on
    end if;
    if i = '1' then read_addr2 := (others => '-');
    elsif rs2(4 downto 3) = "00" then
      read_addr2(RABITS -1 downto 4) := R0ADDR;
    else
-- pragma translate_off
      if not is_x(de.cwp & rs2(4)) then
-- pragma translate_on
        read_addr2(NWINLOG2+3 downto 4) := (de.cwp + rs2(4));
	if not CWPOPT then
	  if read_addr2(RABITS-1 downto 4) = R0ADDR then
	    read_addr2(RABITS-1 downto 4) := (others => '0');
	  end if;
	else read_addr2(RABITS-1) := '0'; end if;
-- pragma translate_off
      end if;
-- pragma translate_on
    end if;

    rfi.rd1addr <= read_addr1;
    rfi.rd2addr <= read_addr2;

-- LD delay interlock generation

    ldcheck1 := '0'; ldcheck2 := '0'; ldlock := '0';
    ldchkex := '1'; ldchkme := '1';

    if (de.annul = '0') then
      case op is
      when FMT3 =>
        case op3 is
        when RDY | RDWIM | RDPSR | RDTBR => null;
	when UMUL | SMUL | UMULCC | SMULCC =>
	  if MULTIPLIER = iterative then
	    if (ctrl.cnt = "00") then ldcheck1 := '1'; end if;
            if (i = '0') and (ctrl.cnt = "01") then ldcheck2 := '1'; end if;
	  end if;
        when others => 
          ldcheck1 := '1'; if  i = '0' then ldcheck2 := '1'; end if;
        end case;
      when LDST =>
        ldcheck1 := '1'; 
	if  (i = '0') then
	  ldcheck2 := '1';
	end if;
	if ctrl.cnt /= "00" then ldchkex := '0'; end if;
	if ctrl.cnt = "10" then ldchkme := '0'; end if;
      when others => null;
      end case;
    end if;

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

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

-- register write address generation

    write_reg := '0';

    if op = CALL then
      write_reg := '1'; rd := "01111";	    -- CALL saves PC in r[15] (%o7)
    elsif rd /= "00000" then	-- don't write result if destination is %g0
      case op is
      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 others => write_reg := '1';
        end case;
      when LDST =>
        if op3(2) = '0' then write_reg := '1'; end if;
        case op3 is
        when SWAP | SWAPA | LDSTUB | LDSTUBA =>
	  if ctrl.cnt = "00" then write_reg := '1'; end if;
        when others => null;
        end case;
      when others => null;
      end case;
    end if;

    ctrl.rd(3 downto 0) := rd(3 downto 0);
    if rd(4 downto 3) = "00" then
      ctrl.rd(RABITS -1 downto 4) := R0ADDR;
    else
-- pragma translate_off
      if not is_x(cwp_new & rd(4)) then
-- pragma translate_on
        ctrl.rd(NWINLOG2+3 downto 4) := (cwp_new + rd(4));
	if not CWPOPT then
	  if ctrl.rd(RABITS-1 downto 4) = R0ADDR then
	    ctrl.rd(RABITS-1 downto 4) := (others => '0');
	  end if;
	else ctrl.rd(RABITS-1) := '0'; end if;
-- pragma translate_off
      end if;
-- pragma translate_on
    end if;

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

    rs1data := rfo.data1; ldbp1 := '0';
    if rs1 = "00000" 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;
      elsif ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
        rs1data := me.result;
        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;
      end if;
    end if;

    rs2data := rfo.data2; ldbp2 := '0';
    if operand2_select = ALU_SIMM then
      rs2data := immediate_data;
    elsif rs2 = "00000" 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;
      elsif ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
        rs2data := me.result;
        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;
      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) = '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 := (n xor v) & rs1data(31 downto 1);
        if y0 = '0' then rs2data := (others => '0'); end if;
      when UMUL | SMUL | UMULCC | SMULCC =>
	if MULTIPLIER = iterative then
	  case de.cnt is
	  when "00" => 
	    rs2data := (others => '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';
	    end if;
	  when others => 
            if (op3 = UMUL) or (op3 = UMULCC) then
	      rs2data := ex.result;
	      if rfo.data2(31) = '0' then rs1data := (others => '0'); end if;
	    else
	      rs1data := ex.result;
	      if rfo.data1(31) = '0' then rs2data := (others => '0'); end if;
	    end if;
	  end case;
	end if;
      when others => null;
      end case;
    when others => null;
    end case;

    exin.rs1data <= rs1data;
    exin.rs2data <= rs2data;
    exin.ymsb <= ymsb;

-- PC generation

    branch := '0'; annul_next := '0'; annul_current := '0';
    inull := not Rst; hold_pc := '0'; ticc_exception := '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 then
          branch := branch_true;
  	  if (branch_true = '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;
      when FMT3 =>
        case op3 is
        when UMUL | SMUL | UMULCC | SMULCC =>
	  if MULTIPLIER = iterative then
            case ctrl.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 ctrl.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';

⌨️ 快捷键说明

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