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

📄 iu.vhd

📁 一个航天航空用的Sparc处理器(配美国欧洲宇航局用的R_tems嵌入式操作系统)的VHDL源代码
💻 VHD
📖 第 1 页 / 共 4 页
字号:
          end if;
        when "01" =>
          if (op3(2 downto 0) = "111") or	--STD/SWAP
	     (op3(3 downto 0) = "1101") then	-- LDST
 	    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 fp_exception or ticc_exception or winunf_exception or
	winovf_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 := annul_current or ldlock or wr.annul_all;
    ctrl.annul := de.annul or wr.annul_all or annul_current;
    annul_next := (mein.inull and not hold_pc) or annul_next or wr.annul_all;
    if annul_next = '1' then
      cnt := (others => '0'); mulcnt := (others => '0');
    end if;

    fecomb.hold_pc <= hold_pc;
    fecomb.branch <= branch;
    dein.annul <= annul_next;
    dein.cnt <= cnt;
    dein.mulcnt <= mulcnt;
    dein.pv <= pv;
    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 (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 | WRY =>
        write_y := '1';
      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;
      when others => null;
      end case;
    when others => null;
    end case;

    exin.write_y <= write_y;
    exin.rst_mey <= rst_mey;
  end process;

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

  execute_stage : process(ex, me, wr, wrin, sregs)
  variable op     : std_logic_vector(1 downto 0);
  variable op3    : std_logic_vector(5 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 aluresult : 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

  begin

    op    := ex.ctrl.inst(31 downto 30);
    op3   := ex.ctrl.inst(24 downto 19);

    ctrl := ex.ctrl; memory_load := '0';
    ctrl.annul := ctrl.annul or wr.annul_all;
    read := not op3(2);
    dcache_write := '0'; enaddr := '0'; 
    ld_size := LDWORD; signed := '0'; addr_misal := '0';

    case op is
    when LDST =>
      case op3 is
      when LDUB | LDUBA | LDSTUB | LDSTUBA => ld_size := LDBYTE;
      when LDUH | LDUHA => ld_size := LDHALF;
      when LDSB | LDSBA => ld_size := LDBYTE; signed := '1';
      when LDSH | LDSHA => ld_size := LDHALF; signed := '1';
      when LD | LDA => ld_size := LDWORD;
      when SWAP | SWAPA => ld_size := LDWORD;
      when LDD | LDDA => ld_size := LDDBL;
      when STB | STBA => ld_size := LDBYTE;
      when STH | STHA => ld_size := LDHALF;
      when ST | STA => ld_size := LDWORD;
      when ISTD | STDA => ld_size := LDDBL;
      when others => null;
      end case;
    when others => null;
    end case;

    link_pc := '0'; jump:= '0'; inull :='0'; force_a2 := '0';

    if (ctrl.annul = '0') then
      case op is
      when CALL =>
        link_pc := '1';
      when FMT3 =>
        case op3 is
        when JMPL =>
          jump := '1'; link_pc := '1'; inull := '1';
        when RETT =>
          jump := '1';
        when others => null;
        end case;
      when LDST =>
	if (ctrl.trap or (wrin.ctrl.trap and not wrin.ctrl.annul)) = '0' then
          case ctrl.cnt is
	  when "00" =>
            memory_load := op3(3) or not op3(2);	-- LD/LDST/SWAP
	    read := memory_load; enaddr := '1';
          when "01" =>
            memory_load := not op3(2);	-- LDD
	    enaddr := memory_load; force_a2 := memory_load;
            if op3(3 downto 2) = "01" then		-- ST
	      dcache_write := '1';
            end if;
            if op3(3 downto 2) = "11" then		-- STD/LDST/SWAP
	      enaddr := '1';
            end if;
          when "10" => 					-- STD/LDST/SWAP
            dcache_write := '1';
          when others => null;
	  end case;
	end if;
      when others => null;
      end case;
    end if;

    if ((wr.ctrl.rett and not wr.ctrl.annul) = '1') then
      su := sregs.ps;
    else 
      su := sregs.s;
    end if;
    if su = '1' then asi := "00001011"; else asi := "00001010"; end if;
    if op3(4) = '1' then asi := ex.ctrl.inst(12 downto 5); end if;

-- load data bypass in case (LDDELAY = 1)

    aluin1 := ex.rs1data;
    aluin2 := ex.rs2data;
    ymsb := ex.ymsb;

    if LDDELAY = 1 then
      if ex.ldbp1 = '1' then 
	aluin1 := wr.result; 
	ymsb := wr.result(0);
      end if;
      if ex.ldbp2 = '1' then 
	aluin2 := wr.result; 
      end if;
    end if;

-- ALU add/sub

    icc := "0000";

-- pragma translate_off
    if not (is_x(aluin1) or is_x(aluin2)) then
-- pragma translate_on
--      if ido.dp.aluadd = '0' then
--	aluin2 := not aluin2; cin := not cin;
--      end if;
--      addout := aluin1 + aluin2 + cin;
      if ex.aluadd = '0' then
        addout := aluin1 - aluin2 - ex.alu_cin;
      else
        addout := aluin1 + aluin2 + ex.alu_cin;
      end if;
-- pragma translate_off
    end if;
-- pragma translate_on
    addout(2) := addout(2) or force_a2;

-- fast address adders if enabled

    if FASTJUMP then
-- pragma translate_off
      if not (is_x(aluin1) or is_x(aluin2)) then
-- pragma translate_on
        fecomb.jump_address <= aluin1(31 downto PCLOW) + aluin2(31 downto PCLOW);
	if (aluin1(1 downto 0) + aluin2(1 downto 0)) = "00" then
	  addr_misal := '0';
	else
	  addr_misal := '1';
	end if;
-- pragma translate_off
      else
        fecomb.jump_address <= (others => 'X');
      end if;
-- pragma translate_on
    else
      fecomb.jump_address(31 downto PCLOW) <= addout(31 downto PCLOW);
      if addout(1 downto 0) = "00" then
	addr_misal := '0';
      else
	addr_misal := '1';
      end if;
    end if;

    res := (others => '-');

-- alu ops which set icc

      case ex.aluop is
      when ALU_OR    => logicout := aluin1 or aluin2;
      when ALU_ORN   => logicout := aluin1 or not aluin2;
      when ALU_AND   => logicout := aluin1 and aluin2;
      when ALU_ANDN  => logicout := aluin1 and not aluin2;
      when ALU_XOR   => logicout := aluin1 xor aluin2;
      when ALU_XNOR  => logicout := aluin1 xor not aluin2;
      when others    => logicout := (others => '-');
      end case;

-- generate condition codes

    if (ex.alusel(1) = '0') then
      res := addout;
      if ex.aluadd = '0' then
        icc(0) := ((not aluin1(31)) and aluin2(31)) or 	-- Carry
		 (addout(31) and ((not aluin1(31)) or aluin2(31)));
        icc(1) := (aluin1(31) and (not aluin2(31)) and not addout(31)) or 	-- Overflow
                 (addout(31) and (not aluin1(31)) and aluin2(31));
      else
        icc(0) := (aluin1(31) and aluin2(31)) or 	-- Carry
		 ((not addout(31)) and (aluin1(31) or aluin2(31)));
        icc(1) := (aluin1(31) and aluin2(31) and not addout(31)) or 	-- Overflow
		 (addout(31) and (not aluin1(31)) and (not aluin2(31)));
      end if;
    else
      res := logicout;
      icc(1 downto 0) := "00";
    end if;

    if res = zero32 then	-- Zero
      icc(2) := '1';
    else
      icc(2) := '0';
    end if;
    icc(3) := res(31);		-- Negative

-- alu ops which don't set icc

      case ex.aluop is
      when ALU_STB   => miscout := aluin1(7 downto 0) & aluin1(7 downto 0) &
			     aluin1(7 downto 0) & aluin1(7 downto 0);
      when ALU_STH   => miscout := aluin1(15 downto 0) & aluin1(15 downto 0);
      when ALU_PASS1 => miscout := aluin1;
      when ALU_PASS2 => miscout := aluin2;
      when ALU_ONES  => miscout := (others => '1');
      when ALU_RDY  => miscout := me.y;
      when others => miscout := (others => '-');
      end case;

-- shifter

      shiftin := zero32 & aluin1;
      shiftcnt := aluin2(4 downto 0);

      if ex.aluop = ALU_SLL then
        shiftin(31 downto 0) := zero32;
        shiftin(63 downto 31) := '0' & aluin1;
        shiftcnt := not shiftcnt;
      elsif ex.aluop = ALU_SRA then
        if aluin1(31) = '1' then
	  shiftin(63 downto 32) := (others => '1');
        else
	  shiftin(63 downto 32) := zero32;
        end if;
      end if;
      if shiftcnt (4) = '1' then
        shiftin(47 downto 0) := shiftin(63 downto 16);
      end if;
      if shiftcnt (3) = '1' then
        shiftin(39 downto 0) := shiftin(47 downto 8);
      end if;
      if shiftcnt (2) = '1' then
        shiftin(35 downto 0) := shiftin(39 downto 4);
      end if;
      if shiftcnt (1) = '1' then
        shiftin(33 downto 0) := shiftin(35 downto 2);
      end if;
      if shiftcnt (0) = '1' then
        shiftin(31 downto 0) := shiftin(32 downto 1);
      end if;
      shiftout := shiftin(31 downto 0);

-- generate overflow for tagged add/sub

    case op is 
    when FMT3 =>
      case op3 is
      when TADDCC | TADDCCTV | TSUBCC | TSUBCCTV =>
        icc(1) := aluin1(0) or aluin1(1) or aluin2(0) or aluin2(1) or icc(1);
      when others => null;
      end case;
    when others => null;
    end case;

-- select alu output

    aluresult := (others => '0');
    if link_pc = '1' then
      aluresult := ex.ctrl.pc(31 downto 2) & "00";  -- save PC during jmpl
    else
      case ex.alusel is
      when ALU_RES_ADD => aluresult := addout;
      when ALU_RES_SHIFT => aluresult := shiftout;
      when ALU_RES_LOGIC => aluresult := logicout;
      when others => aluresult := miscout;
      end case;
    end if;

    ex.result <= aluresult;
    ex.icc <= icc;

-- select Y

    if (me.write_y and not me.ctrl.annul) = '1' then y := me.y; 
    else y := wr.y; end if;

-- generate Y

    micc := icc;
    licc := icc;

    nexty := y;
    if ex.mulstep = '1' then
      nexty := ymsb & me.y(31 downto 1);
    elsif ex.mulinsn = '1' then
      if MULTIPLIER = iterative then
        case ex.ctrl.cnt is
        when "00" =>
	  nexty := y;
        when "01" =>
          nexty := ymsb & me.y(31 downto 1);
        when "10" =>
	  aluresult := ymsb & me.y(31 downto 1); 
	  licc(3) := ymsb; licc(1 downto 0) := "00";
	  if aluresult = zero32 then licc(2) := '1'; else licc(2) := '0'; end if;
	  nexty := me.y;
        when others => null;
        end case;
      end if;
    elsif (ex.rst_mey or ex.write_y) = '1' then
      if ex.ctrl.cnt = "11" then
	nexty := addout;
      else
	nexty := logicout;
      end if;
    end if;

    micc(3) := icc(3) and not ex.rst_mey;
    micc(1) := icc(1) and not ex.rst_mey;

    if ex.alusel = ALU_RES_ADD then
      dci.eaddress <= addout;
    else
      dci.eaddress <= miscout;
    end if;

    mein.y <= nexty;
    mein.result <= aluresult;
    dciin.enaddr <= enaddr;
    dciin.read <= read;
    dciin.write <= dcache_write;
    dciin.asi <= asi;
    dciin.lock <= '0';
    fecomb.jump <= jump;
    
    ex.micc <= micc;
    mein.inull <= inull;
    mein.icc <= licc;
    mein.memory_load <= memory_load;
    mein.ld_size <= ld_size;
    mein.signed <= signed;
    mein.addr_misal <= addr_misal;
    mein.ctrl <= ctrl;

  end process;

-------------------------------------------------------------------------------
-- memory stage
-------------------------------------------------------------------------------

⌨️ 快捷键说明

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