📄 iu3.vhd
字号:
variable op3 : std_logic_vector(5 downto 0);variable wim : word;variable ncwp : cwptype;begin op := inst(31 downto 30); op3 := inst(24 downto 19); wovf_exc := '0'; wunf_exc := '0'; wim := (others => '0'); wim(NWIN-1 downto 0) := xc_wim; ncwp := r.d.cwp; wcwp := '0'; if (op = FMT3) and ((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE)) then wcwp := '1'; if (op3 = SAVE) then if (not CWPOPT) and (r.d.cwp = CWPMIN) then ncwp := CWPMAX; else ncwp := r.d.cwp - 1 ; end if; else if (not CWPOPT) and (r.d.cwp = CWPMAX) then ncwp := CWPMIN; else ncwp := r.d.cwp + 1; end if; end if; if wim(conv_integer(ncwp)) = '1' then if op3 = SAVE then wovf_exc := '1'; else wunf_exc := '1'; end if; end if; end if; de_cwp := ncwp;end;-- generate register read address 1procedure rs1_gen(r : registers; inst : word; rs1 : out std_logic_vector(4 downto 0); rs1mod : out std_ulogic) isvariable op : std_logic_vector(1 downto 0);variable op3 : std_logic_vector(5 downto 0);begin op := inst(31 downto 30); op3 := inst(24 downto 19); rs1 := inst(18 downto 14); rs1mod := '0'; if (op = LDST) then if ((r.d.cnt = "01") and ((op3(2) and not op3(3)) = '1')) or (r.d.cnt = "10") then rs1mod := '1'; rs1 := inst(29 downto 25); end if; if ((r.d.cnt = "10") and (op3(3 downto 0) = "0111")) then rs1(0) := '1'; end if; end if;end;-- load/icc interlock detection procedure lock_gen(r : registers; rs2, rd : std_logic_vector(4 downto 0); rfa1, rfa2, rfrd : rfatype; inst : word; fpc_lock, mulinsn, divinsn : std_ulogic; lldcheck1, lldcheck2, lldlock, lldchkra, lldchkex : out std_ulogic) is variable op : std_logic_vector(1 downto 0); variable op2 : std_logic_vector(2 downto 0); variable op3 : std_logic_vector(5 downto 0); variable cond : std_logic_vector(3 downto 0); variable rs1 : std_logic_vector(4 downto 0); variable i, ldcheck1, ldcheck2, ldchkra, ldchkex, ldcheck3 : std_ulogic; variable ldlock, icc_check, bicc_hold, chkmul, y_check : std_ulogic; variable lddlock : boolean; begin op := inst(31 downto 30); op3 := inst(24 downto 19); op2 := inst(24 downto 22); cond := inst(28 downto 25); rs1 := inst(18 downto 14); lddlock := false; i := inst(13); ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0'; ldchkra := '1'; ldchkex := '1'; icc_check := '0'; bicc_hold := '0'; y_check := '0'; if (r.d.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 => ldcheck1 := '0'; ldcheck2 := '0'; if MACPIPE then y_check := '1'; end if; when RDWIM | RDTBR => ldcheck1 := '0'; ldcheck2 := '0'; when RDPSR => ldcheck1 := '0'; ldcheck2 := '0'; icc_check := '1'; if MULEN then icc_check := '1'; end if;-- when ADDX | ADDXCC | SUBX | SUBXCC =>-- if MULEN then icc_check := '1'; end if; when SDIV | SDIVCC | UDIV | UDIVCC => if DIVEN then y_check := '1'; end if; when FPOP1 | FPOP2 => ldcheck1:= '0'; ldcheck2 := '0'; when others => end case; when LDST => ldcheck1 := '1'; ldchkra := '0'; case r.d.cnt is when "00" => if (lddel = 2) and (op3(2) = '1') then ldcheck3 := '1'; end if; ldcheck2 := not i; ldchkra := '1'; when "01" => ldcheck2 := not i; when others => ldchkex := '0'; end case; if (op3(2 downto 0) = "011") then lddlock := true; end if; when others => null; end case; end if; if MULEN or DIVEN then chkmul := mulinsn; bicc_hold := bicc_hold or (icc_check and r.m.ctrl.wicc and (r.m.ctrl.cnt(0) or r.m.mul)); else chkmul := '0'; end if; if DIVEN then bicc_hold := bicc_hold or (y_check and (r.a.ctrl.wy or r.e.ctrl.wy)); chkmul := chkmul or divinsn; end if; bicc_hold := bicc_hold or (icc_check and (r.a.ctrl.wicc or r.e.ctrl.wicc)); if (((r.a.ctrl.ld or chkmul) and r.a.ctrl.wreg and ldchkra) = '1') and (((ldcheck1 = '1') and (r.a.ctrl.rd = rfa1)) or ((ldcheck2 = '1') and (r.a.ctrl.rd = rfa2)) or ((ldcheck3 = '1') and (r.a.ctrl.rd = rfrd))) then ldlock := '1'; end if; if (((r.e.ctrl.ld or r.e.mac) and r.e.ctrl.wreg and ldchkex) = '1') and ((lddel = 2) or (MACPIPE and (r.e.mac = '1')) or ((MULTYPE = 3) and (r.e.mul = '1'))) and (((ldcheck1 = '1') and (r.e.ctrl.rd = rfa1)) or ((ldcheck2 = '1') and (r.e.ctrl.rd = rfa2))) then ldlock := '1'; end if; ldlock := ldlock or bicc_hold or fpc_lock; lldcheck1 := ldcheck1; lldcheck2:= ldcheck2; lldlock := ldlock; lldchkra := ldchkra; lldchkex := ldchkex; end; procedure fpbranch(inst : in word; fcc : in std_logic_vector(1 downto 0); branch : out std_ulogic) is variable cond : std_logic_vector(3 downto 0); variable fbres : std_ulogic; begin cond := inst(28 downto 25); 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; branch := cond(3) xor fbres; end;-- PC generation procedure ic_ctrl(r : registers; inst : word; annul_all, ldlock, branch_true, fbranch_true, cbranch_true, fccv, cccv : in std_ulogic; cnt : out std_logic_vector(1 downto 0); de_pc : out pctype; de_branch, ctrl_annul, de_annul, jmpl_inst, inull, de_pv, ctrl_pv, de_hold_pc, ticc_exception, rett_inst, mulstart, divstart : out std_ulogic) is variable op : std_logic_vector(1 downto 0); variable op2 : std_logic_vector(2 downto 0); variable op3 : std_logic_vector(5 downto 0); variable cond : std_logic_vector(3 downto 0); variable hold_pc, annul_current, annul_next, branch, annul, pv : std_ulogic; variable de_jmpl : std_ulogic; begin branch := '0'; annul_next := '0'; annul_current := '0'; pv := '1'; hold_pc := '0'; ticc_exception := '0'; rett_inst := '0'; op := inst(31 downto 30); op3 := inst(24 downto 19); op2 := inst(24 downto 22); cond := inst(28 downto 25); annul := inst(29); de_jmpl := '0'; cnt := "00"; mulstart := '0'; divstart := '0'; if r.d.annul = '0' then case inst(31 downto 30) is when CALL => branch := '1'; if r.d.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 fccv /= '1' then hold_pc := '1'; annul_current := '1'; end if; elsif (CPEN and (op2 = CBCCC)) then branch := cbranch_true; if cccv /= '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 r.d.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 UMUL | SMUL | UMULCC | SMULCC => if MULEN and (MULTYPE /= 0) then mulstart := '1'; end if; if MULEN and (MULTYPE = 0) then case r.d.cnt is when "00" => cnt := "01"; hold_pc := '1'; pv := '0'; mulstart := '1'; when "01" => if mulo.nready = '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 DIVEN then case r.d.cnt is when "00" => cnt := "01"; hold_pc := '1'; pv := '0'; divstart := '1'; when "01" => if divo.nready = '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 => rett_inst := '1'; --su := sregs.ps; when JMPL => de_jmpl := '1'; when WRY => if PWRD1 then if inst(29 downto 25) = "10011" then -- %ASR19 case r.d.cnt is when "00" => pv := '0'; cnt := "00"; hold_pc := '1'; if r.x.ipend = '1' then cnt := "01"; end if; when "01" => cnt := "00"; when others => end case; end if; end if; when others => null; end case; when others => -- LDST case r.d.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; end case; end if; if ldlock = '1' then cnt := r.d.cnt; annul_next := '0'; pv := '1'; end if; hold_pc := (hold_pc or ldlock) and not annul_all; if hold_pc = '1' then de_pc := r.d.pc; else de_pc := r.f.pc; end if; annul_current := (annul_current or ldlock or annul_all); ctrl_annul := r.d.annul or annul_all or annul_current; pv := pv and not ((r.d.inull and not hold_pc) or annul_all); jmpl_inst := de_jmpl and not annul_current; annul_next := (r.d.inull and not hold_pc) or annul_next or annul_all; if (annul_next = '1') or (rstn = '0') then cnt := (others => '0'); end if; de_hold_pc := hold_pc; de_branch := branch; de_annul := annul_next; de_pv := pv; ctrl_pv := r.d.pv and not ((r.d.annul and not r.d.pv) or annul_all or annul_current); inull := (not rstn) or r.d.inull or hold_pc or annul_all; end;-- register write address generation procedure rd_gen(r : registers; inst : word; wreg, ld : out std_ulogic; rdo : out std_logic_vector(4 downto 0)) is variable write_reg : std_ulogic; variable op : std_logic_vector(1 downto 0); variable op2 : std_logic_vector(2 downto 0); variable op3 : std_logic_vector(5 downto 0); variable rd : std_logic_vector(4 downto 0); begin op := inst(31 downto 30); op2 := inst(24 downto 22); op3 := inst(24 downto 19); write_reg := '0'; rd := inst(29 downto 25); 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 MULEN then if (((mulo.nready = '1') and (r.d.cnt /= "00")) or (MULTYPE /= 0)) then write_reg := '1'; end if; else write_reg := '1'; end if; when UDIV | SDIV | UDIVCC | SDIVCC => if DIVEN then if (divo.nready = '1') and (r.d.cnt /= "00") then write_reg := '1'; end if; 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 others => -- LDST ld := not op3(2); if (op3(2) = '0') and not ((CPEN or FPEN) and (op3(5) = '1')) then write_reg := '1'; end if; case op3 is when SWAP | SWAPA | LDSTUB | LDSTUBA => if r.d.cnt = "00" then write_reg := '1'; ld := '1'; end if; when others => null; end case; if r.d.cnt = "01" then case op3 is when LDD | LDDA | LDDC | LDDF => rd(0) := '1'; when others => end case; end if; end case; if (rd = "00000") then write_reg := '0'; end if; wreg := write_reg; rdo := rd; end;-- immediate data generation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -