📄 iu3.vhd
字号:
function imm_data (r : registers; insn : word) return word is variable immediate_data, inst : word; begin immediate_data := (others => '0'); inst := insn; case inst(31 downto 30) is when FMT2 => immediate_data := inst(21 downto 0) & "0000000000"; when others => -- LDST immediate_data(31 downto 13) := (others => inst(12)); immediate_data(12 downto 0) := inst(12 downto 0); end case; return(immediate_data); end;-- read special registers function get_spr (r : registers) return word is variable spr : word; begin spr := (others => '0'); case r.e.ctrl.inst(24 downto 19) is when RDPSR => spr(31 downto 5) := conv_std_logic_vector(IMPL,4) & conv_std_logic_vector(VER,4) & r.m.icc & "000000" & r.w.s.ec & r.w.s.ef & r.w.s.pil & r.e.su & r.w.s.ps & r.e.et; spr(NWINLOG2-1 downto 0) := r.e.cwp; when RDTBR => spr(31 downto 4) := r.w.s.tba & r.w.s.tt; when RDWIM => spr(NWIN-1 downto 0) := r.w.s.wim; when others => end case; return(spr); end;-- immediate data select function imm_select(inst : word) return boolean is variable imm : boolean; begin imm := false; case inst(31 downto 30) is when FMT2 => case inst(24 downto 22) is when SETHI => imm := true; when others => end case; when FMT3 => case inst(24 downto 19) is when RDWIM | RDPSR | RDTBR => imm := true; when others => if (inst(13) = '1') then imm := true; end if; end case; when LDST => if (inst(13) = '1') then imm := true; end if; when others => end case; return(imm); end;-- EXE operation procedure alu_op(r : in registers; iop1, iop2 : in word; me_icc : std_logic_vector(3 downto 0); my, ldbp : std_ulogic; aop1, aop2 : out word; aluop : out std_logic_vector(2 downto 0); alusel : out std_logic_vector(1 downto 0); aluadd : out std_ulogic; shcnt : out std_logic_vector(4 downto 0); sari, shleft, ymsb, mulins, divins, mulstep, macins, ldbp2, invop2 : 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 rd : std_logic_vector(4 downto 0); variable icc : std_logic_vector(3 downto 0); variable y0 : std_ulogic; begin op := r.a.ctrl.inst(31 downto 30); op2 := r.a.ctrl.inst(24 downto 22); op3 := r.a.ctrl.inst(24 downto 19); aop1 := iop1; aop2 := iop2; ldbp2 := ldbp; aluop := EXE_NOP; alusel := EXE_RES_MISC; aluadd := '1'; shcnt := iop2(4 downto 0); sari := '0'; shleft := '0'; invop2 := '0'; ymsb := iop1(0); mulins := '0'; divins := '0'; mulstep := '0'; macins := '0'; if r.e.ctrl.wy = '1' then y0 := my; elsif r.m.ctrl.wy = '1' then y0 := r.m.y(0); elsif r.x.ctrl.wy = '1' then y0 := r.x.y(0); else y0 := r.w.s.y(0); end if; if r.e.ctrl.wicc = '1' then icc := me_icc; elsif r.m.ctrl.wicc = '1' then icc := r.m.icc; elsif r.x.ctrl.wicc = '1' then icc := r.x.icc; else icc := r.w.s.icc; end if; case op is when CALL => aluop := EXE_LINK; when FMT2 => case op2 is when SETHI => aluop := EXE_PASS2; when others => end case; when FMT3 => case op3 is when IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | SAVE | RESTORE | TICC | JMPL | RETT => alusel := EXE_RES_ADD; when ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV => alusel := EXE_RES_ADD; aluadd := '0'; aop2 := not iop2; invop2 := '1'; when MULSCC => alusel := EXE_RES_ADD; aop1 := (icc(3) xor icc(1)) & iop1(31 downto 1); if y0 = '0' then aop2 := (others => '0'); ldbp2 := '0'; end if; mulstep := '1'; when UMUL | UMULCC | SMUL | SMULCC => if MULEN then mulins := '1'; end if; when UMAC | SMAC => if MACEN then mulins := '1'; macins := '1'; end if; when UDIV | UDIVCC | SDIV | SDIVCC => if DIVEN then aluop := EXE_DIV; alusel := EXE_RES_LOGIC; divins := '1'; end if; when IAND | ANDCC => aluop := EXE_AND; alusel := EXE_RES_LOGIC; when ANDN | ANDNCC => aluop := EXE_ANDN; alusel := EXE_RES_LOGIC; when IOR | ORCC => aluop := EXE_OR; alusel := EXE_RES_LOGIC; when ORN | ORNCC => aluop := EXE_ORN; alusel := EXE_RES_LOGIC; when IXNOR | XNORCC => aluop := EXE_XNOR; alusel := EXE_RES_LOGIC; when XORCC | IXOR | WRPSR | WRWIM | WRTBR | WRY => aluop := EXE_XOR; alusel := EXE_RES_LOGIC; when RDPSR | RDTBR | RDWIM => aluop := EXE_SPR; when RDY => aluop := EXE_RDY; when ISLL => aluop := EXE_SLL; alusel := EXE_RES_SHIFT; shleft := '1'; shcnt := not iop2(4 downto 0); invop2 := '1'; when ISRL => aluop := EXE_SRL; alusel := EXE_RES_SHIFT; when ISRA => aluop := EXE_SRA; alusel := EXE_RES_SHIFT; sari := iop1(31); when FPOP1 | FPOP2 => when others => end case; when others => -- LDST case r.a.ctrl.cnt is when "00" => alusel := EXE_RES_ADD; when "01" => case op3 is when LDD | LDDA | LDDC => alusel := EXE_RES_ADD; when LDDF => alusel := EXE_RES_ADD; when SWAP | SWAPA | LDSTUB | LDSTUBA => alusel := EXE_RES_ADD; when STF | STDF => when others => aluop := EXE_PASS1; if op3(2) = '1' then if op3(1 downto 0) = "01" then aluop := EXE_STB; elsif op3(1 downto 0) = "10" then aluop := EXE_STH; end if; end if; end case; when "10" => aluop := EXE_PASS1; if op3(2) = '1' then -- ST if (op3(3) and not op3(1))= '1' then aluop := EXE_ONES; end if; -- LDSTUB/A end if; when others => end case; end case; end; function ra_inull_gen(r, v : registers) return std_ulogic is variable de_inull : std_ulogic; begin de_inull := '0'; if ((v.e.jmpl or v.e.ctrl.rett) and not v.e.ctrl.annul and not (r.e.jmpl and not r.e.ctrl.annul)) = '1' then de_inull := '1'; end if; if ((v.a.jmpl or v.a.ctrl.rett) and not v.a.ctrl.annul and not (r.a.jmpl and not r.a.ctrl.annul)) = '1' then de_inull := '1'; end if; return(de_inull); end;-- operand generation procedure op_mux(r : in registers; rfd, ed, md, xd, im : in word; rsel : in std_logic_vector(2 downto 0); ldbp : out std_ulogic; d : out word) is begin ldbp := '0'; case rsel is when "000" => d := rfd; when "001" => d := ed; when "010" => d := md; if lddel = 1 then ldbp := r.m.ctrl.ld; end if; when "011" => d := xd; when "100" => d := im; when "101" => d := (others => '0'); when "110" => d := r.w.result; when others => d := (others => '-'); end case; end; procedure op_find(r : in registers; ldchkra : std_ulogic; ldchkex : std_ulogic; rs1 : std_logic_vector(4 downto 0); ra : rfatype; im : boolean; rfe : out std_ulogic; osel : out std_logic_vector(2 downto 0); ldcheck : std_ulogic) is begin rfe := '0'; if im then osel := "100"; elsif rs1 = "00000" then osel := "101"; -- %g0 elsif ((r.a.ctrl.wreg and ldchkra) = '1') and (ra = r.a.ctrl.rd) then osel := "001"; elsif ((r.e.ctrl.wreg and ldchkex) = '1') and (ra = r.e.ctrl.rd) then osel := "010"; elsif r.m.ctrl.wreg = '1' and (ra = r.m.ctrl.rd) then osel := "011"; elsif (irfwt = 0) and r.x.ctrl.wreg = '1' and (ra = r.x.ctrl.rd) then osel := "110"; else osel := "000"; rfe := ldcheck; end if; end;-- generate carry-in for alu procedure cin_gen(r : registers; me_cin : in std_ulogic; cin : out std_ulogic) is variable op : std_logic_vector(1 downto 0); variable op3 : std_logic_vector(5 downto 0); variable ncin : std_ulogic; begin op := r.a.ctrl.inst(31 downto 30); op3 := r.a.ctrl.inst(24 downto 19); if r.e.ctrl.wicc = '1' then ncin := me_cin; else ncin := r.m.icc(0); end if; cin := '0'; case op is when FMT3 => case op3 is when ISUB | SUBCC | TSUBCC | TSUBCCTV => cin := '1'; when ADDX | ADDXCC => cin := ncin; when SUBX | SUBXCC => cin := not ncin; when others => null; end case; when others => null; end case; end; procedure logic_op(r : registers; aluin1, aluin2, mey : word; ymsb : std_ulogic; logicres, y : out word) is variable logicout : word; begin case r.e.aluop is when EXE_AND => logicout := aluin1 and aluin2; when EXE_ANDN => logicout := aluin1 and not aluin2; when EXE_OR => logicout := aluin1 or aluin2; when EXE_ORN => logicout := aluin1 or not aluin2; when EXE_XOR => logicout := aluin1 xor aluin2; when EXE_XNOR => logicout := aluin1 xor not aluin2; when EXE_DIV => if DIVEN then logicout := aluin2; else logicout := (others => '-'); end if; when others => logicout := (others => '-'); end case; if (r.e.ctrl.wy and r.e.mulstep) = '1' then y := ymsb & r.m.y(31 downto 1); elsif r.e.ctrl.wy = '1' then y := logicout; elsif r.m.ctrl.wy = '1' then y := mey; elsif MACPIPE and (r.x.mac = '1') then y := mulo.result(63 downto 32); elsif r.x.ctrl.wy = '1' then y := r.x.y; else y := r.w.s.y; end if; logicres := logicout; end; procedure misc_op(r : registers; wpr : watchpoint_registers; aluin1, aluin2, ldata, mey : word; mout, edata : out word) is variable miscout, bpdata, stdata : word; variable wpi : integer; begin wpi := 0; miscout := r.e.ctrl.pc(31 downto 2) & "00"; edata := aluin1; bpdata := aluin1; if ((r.x.ctrl.wreg and r.x.ctrl.ld and not r.x.ctrl.annul) = '1') and (r.x.ctrl.rd = r.e.ctrl.rd) and (r.e.ctrl.inst(31 downto 30) = LDST) and (r.e.ctrl.cnt /= "10") then bpdata := ldata; end if; case r.e.aluop is when EXE_STB => miscout := bpdata(7 downto 0) & bpdata(7 downto 0) & bpdata(7 downto 0) & bpdata(7 downto 0); edata := miscout; when EXE_STH => miscout := bpdata(15 downto 0) & bpdata(15 downto 0); edata := miscout; when EXE_PASS1 => miscout := bpdata; edata := miscout; when EXE_PASS2 => miscout := aluin2; when EXE_ONES => miscout := (others => '1'); edata := miscout; when EXE_RDY => if MULEN and (r.m.ctrl.wy = '1') then miscout := mey; else miscout := r.m.y; end if; if (NWP > 0) and (r.e.ctrl.inst(18 downto 17) = "11") then wpi := conv_integer(r.e.ctrl.inst(16 downto 15)); if r.e.ctrl.inst(14) = '0' then miscout := wpr(wpi).addr & '0' & wpr(wpi).exec; else miscout := wpr(wpi).mask & wpr(wpi).load & wpr(wpi).store; end if; end if; if (r.e.ctrl.inst(18 downto 17) = "10") and (r.e.ctrl.inst(14) = '1') then --%ASR17 miscout := asr17_gen(r); end if; if MACEN then if (r.e.ctrl.inst(18 downto 14) = "10010") then --%ASR18 if ((r.m.mac = '1') and not MACPIPE) or ((r.x.mac = '1') and MACPIPE) then miscout := mulo.result(31 downto 0); -- data forward of asr18 else miscout := r.w.s.asr18; end if; else if ((r.m.mac = '1') and not MACPIPE) or ((r.x.mac = '1') and MACPIPE) then miscout := mulo.result(63 downto 32); -- data forward Y end if; end if; end if; when EXE_SPR => miscout := get_spr(r); when others => null; end case; mout := miscout; end; procedure alu_select(r : registers; addout : std_logic_vector(32 downto 0); op1, op2 : word; shiftout, logicout, miscout : word; res : out word; me_icc : std_logic_vector(3 downto 0); icco : out std_logic_vector(3 downto 0); divz : out std_ulogic) is variable op : std_logic_vector(1 downto 0); variable op3 : std_logic_vector(5 downto 0); variable icc : std_logic_vector(3 downto 0); variable aluresult : word; begin op := r.e.ctrl.inst(31 downto 30); op3 := r.e.ctrl.inst(24 downto 19); icc := (others => '0'); case r.e.alusel is when EXE_RES_ADD => aluresult := addout(32 downto 1); if r.e.aluadd = '0' then icc(0) := ((not op1(31)) and not op2(31)) or -- Carry (addout(32) and ((not op1(31)) or not op2(31))); icc(1) := (op1(31) and (op2(31)) and not addout(32)) or -- Overflow (addout(32) and (not op1(31)) and not op2(31)); else icc(0) := (op1(31) and op2(31)) or -- Carry ((not addout(32)) and (op1(31) or op2(31))); icc(1) := (op1(31) and op2(31) and not addout(32)) or -- Overflow (addout(32) and (not op1(31)) and (not op2(31))); end if; if notag = 0 then case op is when FMT3 => case op3 is when TADDCC | TADDCCTV => icc(1) := op1(0) or op1(1) or op2(0) or op2(1) or icc(1); when TSUBCC | TSUBCCTV => icc(1) := op1(0) or op1(1) or (not op2(0)) or (not op2(1)) or icc(1); when others => null; end case; when others => null; end case; end if; if aluresult = zero32 then icc(2) := '1'; end if; when EXE_RES_SHIFT => aluresult := shiftout; when EXE_RES_LOGIC => aluresult := logicout; if aluresult = zero32 then icc(2) := '1'; end if; when others => aluresult := miscout; end case; if r.e.jmpl = '1' then aluresult := r.e.ctrl.pc(31 downto 2) & "00"; end if; icc(3) := aluresult(31);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -