iu.vhd
来自「sparc org, vhdl rtl code」· VHDL 代码 · 共 1,813 行 · 第 1/5 页
VHD
1,813 行
when FMT3 =>
case op3 is
when MULSCC =>
ymsb := rs1data(0); rs1data := (icc(3) xor icc(1)) & rs1data(31 downto 1);
if y0 = '0' then
rs2data := (others => '0'); rfenable2 := '0'; ldbp2 := '0';
end if;
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
case de.cnt is
when "00" =>
rs2data := (others => '0'); ymsb := rs1data(0); rfenable2 := '0';
when "01" | "10" =>
ymsb := ex.result(0);
rs1data := (ex.micc(3) xor ex.micc(1)) & ex.result(31 downto 1);
if (mein.y(0) = '0') or (de.cnt = "10") then
rs2data := (others => '0'); ldbp2 := '0'; rfenable2 := '0';
end if;
when others =>
if (op3 = UMUL) or (op3 = UMULCC) then
rs2data := ex.result; rfenable2 := '1';
if rfo.data2(31) = '0' then
rs1data := (others => '0');
end if;
else
rs1data := ex.result; rfenable1 := '1';
if rfo.data1(31) = '0' then
rs2data := (others => '0'); rfenable2 := '0';
end if;
end if;
end case;
end if;
when others => null;
end case;
when others => null;
end case;
exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;
-- 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 + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?