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 + -
显示快捷键?