📄 iu.vhd
字号:
shiftout := shiftin(31 downto 0);-- generate overflow for tagged add/sub case op is when FMT3 => case op3 is when TADDCC | TADDCCTV | TSUBCC | TSUBCCTV => icc(1) := aluin1(0) or aluin1(1) or aluin2(0) or aluin2(1) or icc(1); when others => null; end case; when others => null; end case;-- select alu output aluresult := (others => '0'); if link_pc = '1' then aluresult := ex.ctrl.pc(31 downto 2) & "00"; -- save PC during jmpl else case ex.alusel is when ALU_RES_ADD => aluresult := addout; when ALU_RES_SHIFT => aluresult := shiftout; when ALU_RES_LOGIC => aluresult := logicout; when others => aluresult := miscout; end case; end if; ex.icc <= icc;-- FPU interface if ((FPTYPE = meiko) and FPEN) then-- pragma translate_off if is_x(aluin1) then aluin1 := (others => '0'); end if; if is_x(aluin2) then aluin2 := (others => '0'); end if; if is_x(de.inst(19) & de.inst(13 downto 5)) then fpui.FpInst <= (others => '0'); else-- pragma translate_on fpui.FpInst <= de.inst(19) & de.inst(13 downto 5);-- pragma translate_off end if; if is_x(fpu_reg.fsr.rd) then fpui.RoundingMode <= (others => '0'); else -- pragma translate_on fpui.RoundingMode <= fpu_reg.fsr.rd;-- pragma translate_off end if;-- pragma translate_on fpui.ss_scan_mode <= '0'; fpui.fp_ctl_scan_in <= '0'; if (ex.ctrl.cnt = "00") or (opf(1) = '0') then fpui.fprf_dout1 <= aluin1 & aluin1; fpui.fprf_dout2 <= aluin2 & aluin2; else fpui.fprf_dout1 <= fpu_reg.op1h & aluin1; fpui.fprf_dout2 <= me.result & aluin2; end if; fpu_regin.op1h <= aluin1; if fpu_reg.ex.fpop = "01" and (ex.write_reg = '1') then if fpu_reg.ex.dsz = '1' then if (ex.ctrl.cnt /= "00") then aluresult := fpuo.FracResult(34 downto 3); end if; else aluresult := fpuo.SignResult & fpuo.ExpResult(7 downto 0) & fpuo.FracResult(54 downto 32); end if; end if; fpu_regin.me <= fpmein; end if; ex.result <= aluresult;-- generate Y micc := icc; licc := icc; nexty := y; if ex.mulstep = '1' then nexty := ymsb & y(31 downto 1); elsif ex.mulinsn = '1' then if MULTIPLIER = iterative then case ex.ctrl.cnt is when "00" => nexty := y; when "01" => nexty := ymsb & me.y(31 downto 1); when "10" => aluresult := ymsb & me.y(31 downto 1); licc(3) := ymsb; licc(1 downto 0) := "00"; if aluresult = zero32 then licc(2) := '1'; else licc(2) := '0'; end if; nexty := me.y; when others => null; end case; end if; elsif (ex.rst_mey or ex.write_y) = '1' then if ex.ctrl.cnt = "11" then nexty := addout; else nexty := logicout; end if; end if; micc(3) := icc(3) and not ex.rst_mey; micc(1) := icc(1) and not ex.rst_mey;-- data address generation eaddress := miscout; if ex.alusel = ALU_RES_ADD then addout(2) := addout(2) or force_a2; eaddress := addout; end if; if CPEN and (op = LDST) and ((op3(5 downto 4) & op3(2)) = "111") and (ex.ctrl.cnt /= "00") then dci.edata <= cpo.data; -- store co-processor aluresult := cpo.data; elsif (FPTYPE = fpc) and (op = LDST) and ((op3(5 downto 4) & op3(2)) = "101") and (ex.ctrl.cnt /= "00") then dci.edata <= fpo.data; -- store fpu co-processor aluresult := fpo.data; else dci.edata <= miscout; aluresult(2) := aluresult(2) or force_a2; end if; mein.y <= nexty; dciin.enaddr <= enaddr; dciin.read <= read; dciin.write <= dcache_write; dciin.asi <= asi; dciin.lock <= lock; dci.eenaddr <= enaddr; dci.eaddress <= eaddress; fecomb.jump <= jump; ex.micc <= micc; mein.inull <= inull; mein.icc <= licc; mein.memory_load <= memory_load; mein.ld_size <= ld_size; mein.signed <= signed; mein.addr_misal <= addr_misal; mein.result <= aluresult; mein.write_reg <= write_reg; mein.ctrl <= ctrl; end process;--------------------------------------------------------------------------------- memory stage------------------------------------------------------------------------------- memory_stage : process(ex, me, wr, sregs, sregsin, iui, dco, fpuo, fpu_reg, cpo, fpo, rst, holdn) 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 ctrl : pipeline_control_type; variable nullify : std_logic; variable iflush : std_logic; variable write_cwp : std_logic; variable cwp : std_logic_vector(NWINLOG2-1 downto 0); variable result : std_logic_vector(31 downto 0); variable write_reg : std_logic; variable werr : std_logic; variable fpexc : std_logic; variable opf : std_logic_vector(8 downto 0); variable fpwrin : fpu_ctrl2_type; variable jmpl_rett : std_logic; variable pil : std_logic_vector(3 downto 0); variable irqen : std_logic; variable ipend : std_logic; begin-- common initialisation op := me.ctrl.inst(31 downto 30); op2 := me.ctrl.inst(24 downto 22); op3 := me.ctrl.inst(24 downto 19); opf := me.ctrl.inst(13 downto 5); ctrl := me.ctrl; ctrl.annul := ctrl.annul or wr.annul_all; nullify := ctrl.annul; iflush := '0'; cwp := me.cwp; write_cwp := me.write_cwp; result := me.result; write_reg := me.write_reg; fpwrin := fpu_reg.me; jmpl_rett := '0'; werr := (me.werr or dco.werr) and rst;-- external interrupt handling -- use sregsin.pil and sregsin.et or disable interrupts for one -- clock after a WRPSR, since a WRPSR should affect ET and PIL -- without delay (SPARC V8 ISP, p.183) if PILOPT then irqen := me.irqen and sregs.et; pil := sregs.pil; else irqen := sregsin.et; pil := sregsin.pil; end if; if (iui.irl = "1111") or (iui.irl > pil) then ipend := '1'; else ipend := '0'; end if; if ((ctrl.annul or ctrl.trap) = '0') and (ctrl.pv = '1') then if (werr and holdn) = '1' then ctrl.trap := '1'; ctrl.tt := DSEX_TT; werr := '0'; if op = LDST then nullify := '1'; end if; elsif (irqen = '1') then if ipend = '1' then ctrl.trap := '1'; ctrl.tt := "01" & iui.irl; if op = LDST then nullify := '1'; end if; end if; end if; end if; iuo.ipend <= ipend;-- some trap generation irqen := '1'; if ((ctrl.annul or ctrl.trap) /= '1') then case op is when FMT2 => case op2 is when FBFCC => if (FPTYPE = fpc) and (fpo.exc = '1') then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if; when CBCCC => if CPEN and (cpo.exc = '1') then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if; when others => null; end case; when FMT3 => case op3 is when WRPSR => if me.result(4 downto NWINLOG2) /= CWPFILL then ctrl.trap := '1'; ctrl.tt := IINST_TT; else cwp := me.result(NWINLOG2-1 downto 0); write_cwp := '1'; end if; irqen := '0'; when JMPL | RETT => if me.addr_misal = '1' then ctrl.trap := '1'; ctrl.tt := UNALA_TT; end if; jmpl_rett := '1'; when TADDCCTV | TSUBCCTV => if me.icc(1) = '1' then ctrl.trap := '1'; ctrl.tt := TAG_TT; end if; when FLUSH => iflush := '1'; when FPOP1 | FPOP2 => if (FPTYPE = fpc) and (fpo.exc = '1') then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if; when CPOP1 | CPOP2 => if CPEN and (cpo.exc = '1') then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if; when others => null; end case; when LDST => if ctrl.cnt = "00" then case op3 is when LDDF | STDF | STDFQ => if FPEN and (me.result(2 downto 0) /= "000") then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; elsif (FPTYPE = fpc) and ((fpo.exc and ctrl.pv) = '1') then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if; when LDDC | STDC | STDCQ => if CPEN and (me.result(2 downto 0) /= "000") then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; elsif CPEN and ((cpo.exc and ctrl.pv) = '1') then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if; when LDD | ISTD | LDDA | STDA => if me.result(2 downto 0) /= "000" then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; end if; when LDF | LDFSR | STFSR | STF => if FPEN and (me.result(1 downto 0) /= "00") then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; elsif (FPTYPE = fpc) and ((fpo.exc and ctrl.pv) = '1') then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if; when LDC | LDCSR | STCSR | STC => if CPEN and (me.result(1 downto 0) /= "00") then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; elsif CPEN and ((cpo.exc and ctrl.pv) = '1') then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if; when LD | LDA | ST | STA | SWAP => if me.result(1 downto 0) /= "00" then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; end if; when LDUH | LDUHA | LDSH | LDSHA | STH | STHA => if me.result(0) /= '0' then ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1'; end if; when others => null; end case; end if; when others => null; end case; end if; mein.irqen <= irqen;-- FPU MSW data store fpexc := '0'; if ((FPTYPE = meiko) and FPEN) then if (xorv(fpu_reg.me.fpop) = '1') then if (me.ctrl.cnt = "00") and ((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1') then fpwrin.fcc := fpuo.ConditionCodes; fpwrin.cexc := fpuo.Excep(4 downto 0); end if; if ((ctrl.annul or ctrl.trap) /= '1') then if ((fpu_reg.me.dsz and me.write_reg) = '1') and (me.ctrl.cnt = "00") then result := fpuo.SignResult & fpuo.ExpResult & fpuo.FracResult(54 downto 35); end if; if ((fpu_reg.fsr.tem and fpwrin.cexc) /= "00000" ) then fpexc := '1'; if ((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1') and (me.ctrl.cnt = "00") then fpexc := '0'; write_reg := '0'; else ctrl.trap := '1'; end if; end if; end if; end if; fpu_regin.fpexc <= fpexc; fpu_regin.wr <= fpwrin; end if; mein.bpresult <= result; -- FPU bypass-- load data from cache if (me.memory_load or not dco.mds) = '1' then result := dco.data; end if;-- Y register if ((ctrl.annul or ctrl.trap) /= '1') and (me.write_y = '1') then wrin.y <= me.y; else wrin.y <= wr.y; end if; mein.werr <= werr; wrin.result <= result; me.jmpl_rett <= jmpl_rett; wrin.cwp <= cwp; wrin.write_cwp <= write_cwp; wrin.ctrl <= ctrl; wrin.write_reg <= write_reg; ici.flush <= iflush; dci.flush <= iflush; dci.nullify <= nullify; dci.maddress <= me.result; end process;--------------------------------------------------------------------------------- write stage------------------------------------------------------------------------------- write_stage : process(rst, wr, sregs, de, ex, me, fpu_reg) variable op : std_logic_vector(1 downto 0); variable op3 : std_logic_vector(5 downto 0); variable rd : std_logic_vector(4 downto 0); variable rd_address : std_logic_vector(RABITS-1 downto 0); variable write_reg : std_logic; variable annul_all : std_logic; variable cwp : std_logic_vector(NWINLOG2-1 downto 0); variable ic
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -