📄 iu.vhd
字号:
-- 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 (FPIFTYPE = parallel) 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 ((FPIFTYPE = serial) 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; if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then case de.cnt is when "00" => cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0'; mulstart := '1'; when "01" => if mulo.ready = '1' then cnt := "00"; else cnt := "01"; pv := '0'; hold_pc := '1'; end if; when others => null; end case; end if; when UDIV | SDIV | UDIVCC | SDIVCC => if DIVIDER /= none then case de.cnt is when "00" => cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0'; divstart := '1'; when "01" => if divo.ready = '1' then cnt := "00"; else cnt := "01"; pv := '0'; hold_pc := '1'; end if; 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; muli.start <= mulstart; divi.start <= divstart;-- instruction watchpoints watchpoint_exc := '0'; for i in 0 to WATCHPOINTS-1 loop if ((tr(i).exec and not de.annul) = '1') then if (((tr(i).addr xor de.pc(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)) then watchpoint_exc := '1'; end if; end if; end loop; if DEBUG_UNIT then if ((iui.debug.dsuen and iui.debug.bwatch and not de.annul) = '1') then watchpoint_exc := de.pv and (watchpoint_exc or iui.debug.dbreak or de.step); end if; 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 or watchpoint_exc; 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 watchpoint_exc = '1' then ctrl.tt := WATCH_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 or (ldlock and de.annul); if (annul_next = '1') or (rst = '0') then cnt := (others => '0'); mulcnt := (others => '0'); end if; if DEBUG_UNIT then step := iui.debug.step and pv and not de.annul; end if; fecomb.hold_pc <= hold_pc; fecomb.branch <= branch; dein.annul <= annul_next; dein.cnt <= cnt; dein.mulcnt <= mulcnt; dein.step <= step; dein.pv <= pv; -- pv means that the corresponding pc can be save on a trap ctrl.pv := de.pv and not ((de.annul and not de.pv) or wr.annul_all or annul_current); 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 wr.trapping = '1' then dein.cwp <= sregsin.cwp; elsif (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 => write_y := '1'; when WRY => if rd = "00000" then write_y := '1'; end if; when UMAC | SMAC => if MACEN then write_y := '1'; end if; 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; if MULTIPLIER = m32x32 then write_y := '1'; end if; when others => null; end case; when others => null; end case;-- debug unit diagnostic regfile read if DEBUG_UNIT and (dsur.dmode and iui.debug.denable) = '1' then read_addr1 := iui.debug.daddr(RABITS+1 downto 2); rfenable1 := '1'; end if; exin.write_y <= write_y; exin.rst_mey <= rst_mey; exin.rs1data <= rs1data; exin.rs2data <= rs2data; exin.ymsb <= ymsb; rfi.rd1addr <= read_addr1; rfi.rd2addr <= read_addr2;-- CP/FPU interface if (FPIFTYPE = serial) then fpu_regin.fpop <= fpop and (not fpu_reg.fpld) and not ctrl.annul; fpexin.ldfsr := fsr_ld; fpu_regin.ex <= fpexin; end if; if CPEN then cpi.dannul <= annul_current_cp or cpldlock or wr.annul_all or de.annul; cpi.dtrap <= ctrl.trap; end if; if FPIFTYPE = parallel then fpi.dannul <= annul_current_cp or fpldlock or wr.annul_all or de.annul; fpi.dtrap <= ctrl.trap; fpi.fdata <= ico.data; fpi.frdy <= (not ico.mds) or (holdn and not hold_pc); end if; if RF_LOWPOW = false then rfenable1 := '1'; rfenable2 := '1'; end if; rfi.ren1 <= rfenable1; rfi.ren2 <= rfenable2; end process;--------------------------------------------------------------------------------- execute stage------------------------------------------------------------------------------- execute_stage : process(rst, de, ex, me, wr, wrin, sregs, fpu_reg, fpu_regin, fpo, cpo, fpuo, mulo, divo, tr, iui, dsur, sum32) variable op : std_logic_vector(1 downto 0); variable op3 : std_logic_vector(5 downto 0); variable opf : std_logic_vector(8 downto 0); variable rs1 : std_logic_vector(4 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 edata : std_logic_vector(31 downto 0); variable aluresult : std_logic_vector(31 downto 0); variable eaddress : 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 variable write_reg, write_icc, write_y : std_logic; variable lock : std_logic; variable dsu_cache : std_logic; variable fpmein : fpu_ctrl2_type; variable mulop1, mulop2 : std_logic_vector(32 downto 0); variable wpi : integer range 0 to 3; -- watchpoint index variable addin2 : std_logic_vector(31 downto 0); variable cin : std_logic; begin-- op-code decoding op := ex.ctrl.inst(31 downto 30); op3 := ex.ctrl.inst(24 downto 19); opf := ex.ctrl.inst(13 downto 5); rs1 := ex.ctrl.inst(18 downto 14);-- common initialisation ctrl := ex.ctrl; memory_load := '0'; ctrl.annul := ctrl.annul or wr.annul_all; read := not op3(2); dcache_write := '0'; enaddr := '0'; wpi := 0; ld_size := LDWORD; signed := '0'; addr_misal := '0'; lock := '0'; write_reg := ex.write_reg; write_icc := ex.write_icc; write_y := ex.write_y; fpmein.fpop := fpu_reg.ex.fpop; fpmein.dsz := fpu_reg.ex.dsz; fpmein.ldfsr := fpu_reg.ex.ldfsr; fpmein.cexc := fpuo.excep(4 downto 0); fpmein.fcc := fpuo.ConditionCodes; muli.mac <= op3(5); dsu_cache := '0';-- load/store size decoding case op is when LDST => case op3 is when LDUB | LDUBA => ld_size := LDBYTE; when LDSTUB | LDSTUBA => ld_size := LDBYTE; lock := '1'; 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 | LDF | LDC => ld_size := LDWORD; when SWAP | SWAPA => ld_size := LDWORD; lock := '1'; when LDD | LDDA | LDDF | LDDC => ld_size := LDDBL; when STB | STBA => ld_size := LDBYTE; when STH | STHA => ld_size := LDHALF; when ST | STA | STF => ld_size := LDWORD; when ISTD | STDA => ld_size := LDDBL; when STDF | STDFQ => if FPEN then ld_size := LDDBL; end if; when STDC | STDCQ => if CPEN then ld_size := LDDBL; end if; when others => null; end case; when others => null; end case; link_pc := '0'; jump:= '0'; inull :='0'; force_a2 := '0';-- load/store control decoding 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';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -