📄 iu.vhd
字号:
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 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'); rfenable2 := '0'; ldbp2 := '0'; end if; when UMUL | SMUL | UMULCC | SMULCC => if MULTIPLIER = iterative then case de.cnt is when "00" => rs2data := (others => '0'); ymsb := rs1data(0); rfenable2 := '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'; rfenable2 := '0'; end if; when others => if (op3 = UMUL) or (op3 = UMULCC) then rs2data := ex.result; rfenable2 := '1'; if rfo.data2(31) = '0' then rs1data := (others => '0'); end if; else rs1data := ex.result; rfenable1 := '1'; if rfo.data1(31) = '0' then rs2data := (others => '0'); rfenable2 := '0'; end if; end if; end case; end if; when others => null; end case; when others => null; end case; exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -