iu.vhd
来自「sparc org, vhdl rtl code」· VHDL 代码 · 共 1,813 行 · 第 1/5 页
VHD
1,813 行
variable hold_pc : std_logic; -- Hold PC during multi-cycle ops
variable pv : std_logic; -- PC valid
variable ldlock, ldcheck1, ldcheck2, ldcheck3 : std_logic; -- load interlock
variable ldchkex, ldchkme : std_logic; -- load interlock for ex and me
variable illegal_inst : std_logic; -- illegal instruction
variable privileged_inst : std_logic; -- privileged instruction trap
variable cp_disabled : std_logic; -- CP disable trap
variable fp_disabled : std_logic; -- FP disable trap
variable watchpoint_exc : std_logic; -- watchpoint trap
variable winovf_exception : std_logic; -- window overflow trap
variable winunf_exception : std_logic; -- window underflow trap
variable ticc_exception : std_logic; -- TICC trap
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;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?