📄 iu.vhd
字号:
variable fp_exception : std_logic; -- STDFQ trap variable ctrl : pipeline_control_type; variable ldbp1, ldbp2 : std_logic; -- load bypass enable variable mulcnt : std_logic_vector(4 downto 0); -- multiply cycle number variable ymsb : std_logic; -- next msb of Y during MUL variable rst_mey : std_logic; -- reset me stage Y register variable fpld, fpst, fpop : std_logic; -- FPU instructions variable fpmov : std_logic; -- FPU instructions variable fbres, fbranch_true : std_logic; -- FBCC branch result variable cbres, cbranch_true : std_logic; -- CBCC branch result variable fcc : std_logic_vector(1 downto 0); -- FPU condition codes variable ccc : std_logic_vector(1 downto 0); -- CP condition codes variable cwpmax : std_logic_vector(4 downto 0); variable bicc_hold, icc_check : std_logic; variable fsr_ld, fsr_ld_check, fsr_check, fsr_lock : std_logic; variable fpexin : fpu_ctrl1_type; variable rs1mod : std_logic; variable step : std_logic; variable divstart,mulstart : std_logic; -- start multiply or divide variable cpldlock, fpldlock, annul_current_cp : std_logic; constant RDOPT : boolean := FASTDECODE;-- optimise dest reg address generation constant RS1OPT : boolean := FASTDECODE;-- optimise src1 reg address generation function regdec(cwp, regin : std_logic_vector; fp : std_logic) return std_logic_vector is variable reg : std_logic_vector(4 downto 0); variable ra : std_logic_vector(RABITS -1 downto 0); begin reg := regin; ra(4 downto 0) := reg; if (FPIFTYPE = serial) and (fp = '1') then ra(RABITS -1 downto 5) := F0ADDR(RABITS-5 downto 1); elsif reg(4 downto 3) = "00" then ra(RABITS -1 downto 4) := R0ADDR; else-- pragma translate_off if not (is_x(cwp & ra(4))) then-- pragma translate_on ra(NWINLOG2+3 downto 4) := (cwp + ra(4)); if CWPOPT then ra(RABITS-1) := '0'; elsif ra(RABITS-1 downto 4) = R0ADDR then ra(RABITS-1 downto 4) := (others => '0'); end if;-- pragma translate_off end if;-- pragma translate_on end if; return(ra); end;begin-- instruction bit-field decoding op := de.inst(31 downto 30); op2 := de.inst(24 downto 22); op3 := de.inst(24 downto 19); opf := de.inst(13 downto 5); cond := de.inst(28 downto 25); annul := de.inst(29); rs1 := de.inst(18 downto 14); rs2 := de.inst(4 downto 0); rd := de.inst(29 downto 25); i := de.inst(13);-- common initialisation ctrl.annul := de.annul; ctrl.cnt := de.cnt; ctrl.pv := de.pv; pv := '1'; cnt := "00"; ctrl.tt := "000000"; ctrl.ld := '0'; ctrl.rett := '0'; ctrl.pc := de.pc; ctrl.inst := de.inst; mulcnt := de.mulcnt; write_y := '0'; fpld := '0'; fpst := '0'; fpop := '0'; fp_exception := '0'; fpmov := '0'; step := '0'; fpexin.fpop := "00"; fpexin.dsz := '0'; fpexin.ldfsr := '0'; winovf_exception := '0'; winunf_exception := '0'; write_cwp := '0'; cwp_new := de.cwp; rs1mod := '0'; rfenable1 := '0'; rfenable2 := '0'; -- detect RETT instruction in the pipeline and set the local psr.su and psr.et if ((ex.ctrl.rett and not ex.ctrl.annul) or (me.ctrl.rett and not me.ctrl.annul) or (wr.ctrl.rett and not wr.ctrl.annul)) = '1' then su := sregs.ps; et := '1'; else su := sregs.s; et := sregs.et; end if;-- Check for illegal and privileged instructions illegal_inst := '0'; privileged_inst := '0'; cp_disabled := '0'; fp_disabled := '0'; case op is when CALL => null; when FMT2 => case op2 is when SETHI | BICC => null; when FBFCC => if FPEN then fp_disabled := not sregs.ef; else fp_disabled := '1'; end if; when CBCCC => if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if; when others => illegal_inst := '1'; end case; when FMT3 => case op3 is when IAND | ANDCC | ANDN | ANDNCC | IOR | ORCC | ORN | ORNCC | IXOR | XORCC | IXNOR | XNORCC | ISLL | ISRL | ISRA | MULSCC | IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV | FLUSH | JMPL | TICC | SAVE | RESTORE | RDY => null; when UMAC | SMAC => if not MACEN then illegal_inst := '1'; end if; when UMUL | SMUL | UMULCC | SMULCC => if MULTIPLIER = none then illegal_inst := '1'; end if; when UDIV | SDIV | UDIVCC | SDIVCC => if DIVIDER = none then illegal_inst := '1'; end if; when RETT => illegal_inst := et; privileged_inst := not su; when RDPSR | RDTBR | RDWIM => privileged_inst := not su; when WRY => if not ((rd = "00000") or ((rd = "10010") and MACEN) or ((rd(4 downto 3) = "11") and (WATCHPOINTS > 0))) then illegal_inst := '1'; end if; when WRPSR => privileged_inst := not su; when WRWIM | WRTBR => privileged_inst := not su; when FPOP1 | FPOP2 => if FPEN then fp_disabled := not sregs.ef; fpop := '1'; else fp_disabled := '1'; fpop := '0'; end if; when CPOP1 | CPOP2 => if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if; when others => illegal_inst := '1'; end case; when others => -- LDST case op3 is when LDD | ISTD => illegal_inst := rd(0); -- trap if odd destination register when LD | LDUB | LDSTUB | LDUH | LDSB | LDSH | ST | STB | STH | SWAP => null; when LDDA | STDA => illegal_inst := i or rd(0); privileged_inst := not su; when LDA | LDUBA| LDSTUBA | LDUHA | LDSBA | LDSHA | STA | STBA | STHA | SWAPA => illegal_inst := i; privileged_inst := not su; when LDDF | STDF | LDF | LDFSR | STF | STFSR => if FPEN then fp_disabled := not sregs.ef; else fp_disabled := '1'; end if; when STDFQ => privileged_inst := not su; if (not FPEN) or (sregs.ef = '0') then fp_disabled := '1'; end if; when STDCQ => privileged_inst := not su; if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if; when LDC | LDCSR | LDDC | STC | STCSR | STDC => if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if; when others => illegal_inst := '1'; end case; end case;-- branch address adder branch_address := (others => '0'); if op = CALL then branch_address(31 downto 2) := de.inst(29 downto 0); else branch_address(31 downto 2) := de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21 downto 0); end if;-- pragma translate_off if not (is_x(branch_address) or is_x(de.pc)) then-- pragma translate_on branch_address := branch_address + de.pc; -- address adder (branch)-- pragma translate_off else branch_address := (others => 'X'); end if;-- pragma translate_on fecomb.branch_address <= branch_address;-- ICC pipeline and forwarding if (me.write_icc and not me.ctrl.annul) = '1' then icc := wrin.icc; elsif (wr.write_icc and not wr.ctrl.annul) = '1' then icc := wr.icc; else icc := sregs.icc; end if; br_icc := icc; if ((ex.write_icc and not ex.ctrl.annul) = '1') then icc := ex.icc; if not ICC_HOLD then br_icc := icc; end if; end if; write_icc := '0'; alu_cin := '0'; case op is when FMT3 => case op3 is when SUBCC | TSUBCC | TSUBCCTV => write_icc := '1'; when ADDCC | ANDCC | ORCC | XORCC | ANDNCC | ORNCC | XNORCC | MULSCC | TADDCC | TADDCCTV => write_icc := '1'; when UMULCC | SMULCC => if MULTIPLIER = iterative then if de.cnt /= "11" then write_icc := '1'; end if; end if; if MULTIPLIER = m32x32 then write_icc := '1'; end if; when ADDX | SUBX => alu_cin := icc(0); when ADDXCC | SUBXCC => write_icc := '1'; alu_cin := icc(0); when others => null; end case; when others => null; end case; exin.write_icc <= write_icc; exin.alu_cin <= alu_cin;-- BICC/TICC evaluation n := br_icc(3); z := br_icc(2); v := br_icc(1); c := br_icc(0); case cond(2 downto 0) is when "000" => bres := '0'; -- bn, ba when "001" => bres := z; -- be, bne when "010" => bres := z or (n xor v); -- ble, bg when "011" => bres := n xor v; -- bl, bge when "100" => bres := c or z; -- blue, bgu when "101" => bres := c; -- bcs, bcc when "110" => bres := n; -- bneg, bpos when others => bres := v; -- bvs. bvc end case; branch_true := cond(3) xor bres;-- FBFCC evaluation if FPEN then if FPIFTYPE = serial then if (fpu_reg.me.fpop = "10") and (me.ctrl.annul = '0') then fcc := fpu_reg.me.fcc; elsif (fpu_reg.wr.fpop = "10") and (wr.ctrl.annul = '0') then fcc := fpu_reg.wr.fcc; else fcc := fpu_reg.fsr.fcc; end if; else fcc := fpo.cc; end if; case cond(2 downto 0) is when "000" => fbres := '0'; -- fba, fbn when "001" => fbres := fcc(1) or fcc(0); when "010" => fbres := fcc(1) xor fcc(0); when "011" => fbres := fcc(0); when "100" => fbres := (not fcc(1)) and fcc(0); when "101" => fbres := fcc(1); when "110" => fbres := fcc(1) and not fcc(0); when others => fbres := fcc(1) and fcc(0); end case; fbranch_true := cond(3) xor fbres;-- decode some FPU instruction types case opf is when FMOVS | FABSS | FNEGS => fpmov := '1'; when FITOD | FSTOD | FSQRTD | FADDD | FSUBD | FMULD | FDIVD => fpexin.dsz := '1'; when others => null; end case; end if;-- CBCCC evaluation if CPEN then ccc := cpo.cc; case cond(2 downto 0) is when "000" => cbres := '0'; when "001" => cbres := ccc(1) or ccc(0); when "010" => cbres := ccc(1) xor ccc(0); when "011" => cbres := ccc(0); when "100" => cbres := (not ccc(1)) and ccc(0); when "101" => cbres := ccc(1); when "110" => cbres := ccc(1) and not ccc(0); when others => cbres := ccc(1) and ccc(0); end case; cbranch_true := cond(3) xor cbres; end if;-- Alu operation generation aluop := ALU_NOP; alusel := ALU_RES_MISC; aluadd := '1'; mulstep := '0'; mulinsn := '0'; case op is when FMT2 => case op2 is when SETHI => aluop := ALU_PASS2; when others => 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; if MULTIPLIER > iterative then mulinsn := '1'; 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; if MULTIPLIER > iterative then mulinsn := '1'; end if; when UMAC | SMAC => if MACEN then mulinsn := '1'; end if; when UDIV | UDIVCC | SDIV | SDIVCC => if DIVIDER /= none then aluop := ALU_DIV; alusel := ALU_RES_LOGIC; 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 FPOP1 | FPOP2 => if ((FPIFTYPE = serial) and FPEN) then if de.cnt /= "00" then if opf(1) = '1' then rs1(0) := '1'; rs2(0) := '1'; end if; if fpexin.dsz = '1' then rd(0) := '1'; end if; end if; if op3 = FPOP1 then fpexin.fpop := "01"; else fpexin.fpop := "10"; end if; if fpmov = '1' then aluop := ALU_FOP; fpexin.fpop := "11"; else aluop := ALU_PASS2; end if; end if; when others => end case; when others => -- LDST case de.cnt is when "00" => alusel := ALU_RES_ADD; if FPEN then fpld := (op3(5) and not op3(2)); else fpld := '0'; end if; when "01" => if (op3(2) and not op3(3)) = '1' then -- ST rs1 := rd; rs1mod := '1'; end if; case op3 is when LDD | LDDA | LDDC => rd(0) := '1'; alusel := ALU_RES_ADD; when LDDF => rd(0) := '1'; alusel := ALU_RES_ADD; if FPEN then fpld := '1'; end if; when STFSR => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_FSR; end if; when SWAP | SWAPA | LDSTUB | LDSTUBA => alusel := ALU_RES_ADD; when STF | STDF => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_PASS1; fpst := '1'; end if; when others => aluop := ALU_PASS1; if op3(2) = '1' then -- ST 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -