📄 iu.vhd
字号:
dein.annul <= annul_next; dein.cnt <= cnt; dein.mulcnt <= mulcnt; 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 => write_y := '1'; 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; when others => null; end case; when others => null; end case; 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 (FPTYPE = meiko) 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 FPTYPE = fpc then fpi.dannul <= annul_current_cp or fpldlock or wr.annul_all or de.annul; fpi.dtrap <= ctrl.trap; end if; end process;--------------------------------------------------------------------------------- execute stage------------------------------------------------------------------------------- execute_stage : process(rst, ex, me, wr, wrin, sregs, fpu_reg, fpu_regin, fpo, cpo, fpuo) 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 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 : std_logic; variable lock : std_logic; variable fpmein : fpu_ctrl2_type; 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.annul := ctrl.annul or wr.annul_all; read := not op3(2); dcache_write := '0'; enaddr := '0'; ld_size := LDWORD; signed := '0'; addr_misal := '0'; lock := '0'; write_reg := ex.write_reg; fpmein.fpop := fpu_reg.ex.fpop; fpmein.dsz := fpu_reg.ex.dsz; fpmein.ldfsr := fpu_reg.ex.ldfsr; fpmein.cexc := fpuo.excep(4 downto 0); fpmein.fcc := fpuo.ConditionCodes;-- load/store size decoding case op is when LDST => case op3 is when LDUB | LDUBA => ld_size := LDBYTE; when LDSTUB | LDSTUBA => ld_size := LDBYTE; lock := '1'; when LDUH | LDUHA => ld_size := LDHALF; when LDSB | LDSBA => ld_size := LDBYTE; signed := '1'; when LDSH | LDSHA => ld_size := LDHALF; signed := '1'; when LD | LDA | LDF => ld_size := LDWORD; when SWAP | SWAPA => ld_size := LDWORD; lock := '1'; when LDD | LDDA | LDDF | LDDC => ld_size := LDDBL; lock := '1'; when STB | STBA => ld_size := LDBYTE; when STH | STHA => ld_size := LDHALF; when ST | STA | STF => ld_size := LDWORD; when ISTD | STDA => ld_size := LDDBL; lock := '1'; when STDF | STDFQ => if FPEN then ld_size := LDDBL; lock := '1'; end if; when STDC | STDCQ => if CPEN then ld_size := LDDBL; lock := '1'; end if; when others => null; end case; when others => null; end case; link_pc := '0'; jump:= '0'; inull :='0'; force_a2 := '0';-- load/store control decoding if (ctrl.annul = '0') then case op is when CALL => link_pc := '1'; when FMT3 => case op3 is when JMPL => jump := '1'; link_pc := '1'; inull := me.ctrl.annul or not me.jmpl_rett; when RETT => jump := '1'; inull := me.ctrl.annul or not me.jmpl_rett; when others => null; end case; when LDST => if (ctrl.trap or (wrin.ctrl.trap and not wrin.ctrl.annul)) = '0' then case ex.ctrl.cnt is when "00" => memory_load := op3(3) or not op3(2); -- LD/LDST/SWAP read := memory_load; enaddr := '1'; when "01" => memory_load := not op3(2); -- LDD enaddr := memory_load; force_a2 := memory_load; if op3(3 downto 2) = "01" then -- ST/STD dcache_write := '1'; end if; if op3(3 downto 2) = "11" then -- LDST/SWAP enaddr := '1'; end if; when "10" => -- STD/LDST/SWAP dcache_write := '1'; when others => null; end case; end if; when others => null; end case; end if;-- supervisor bit generation if ((wr.ctrl.rett and not wr.ctrl.annul) = '1') then su := sregs.ps; else su := sregs.s; end if; if su = '1' then asi := "00001011"; else asi := "00001010"; end if; if op3(4) = '1' then asi := ex.ctrl.inst(12 downto 5); end if;-- load data bypass in case (LDDELAY = 1) aluin1 := ex.rs1data; aluin2 := ex.rs2data; ymsb := ex.ymsb; if LDDELAY = 1 then if ex.ldbp1 = '1' then aluin1 := wr.result; ymsb := wr.result(0); end if; if ex.ldbp2 = '1' then aluin2 := wr.result; end if; end if;-- ALU add/sub icc := "0000";-- pragma translate_off if not (is_x(aluin1) or is_x(aluin2)) then-- pragma translate_on-- if ido.dp.aluadd = '0' then-- aluin2 := not aluin2; cin := not cin;-- end if;-- addout := aluin1 + aluin2 + cin; if ex.aluadd = '0' then addout := aluin1 - aluin2 - ex.alu_cin; else addout := aluin1 + aluin2 + ex.alu_cin; end if;-- pragma translate_off end if;-- pragma translate_on-- addout(2) := addout(2) or force_a2;-- fast address adders if enabled if FASTJUMP then-- pragma translate_off if not (is_x(aluin1) or is_x(aluin2)) then-- pragma translate_on fecomb.jump_address <= aluin1(31 downto PCLOW) + aluin2(31 downto PCLOW); if (aluin1(1 downto 0) + aluin2(1 downto 0)) = "00" then addr_misal := '0'; else addr_misal := '1'; end if;-- pragma translate_off else fecomb.jump_address <= (others => 'X'); end if;-- pragma translate_on else fecomb.jump_address(31 downto PCLOW) <= addout(31 downto PCLOW); if addout(1 downto 0) = "00" then addr_misal := '0'; else addr_misal := '1'; end if; end if; res := (others => '-');-- alu ops which set icc case ex.aluop is when ALU_OR => logicout := aluin1 or aluin2; when ALU_ORN => logicout := aluin1 or not aluin2; when ALU_AND => logicout := aluin1 and aluin2; when ALU_ANDN => logicout := aluin1 and not aluin2; when ALU_XOR => logicout := aluin1 xor aluin2; when ALU_XNOR => logicout := aluin1 xor not aluin2; when others => logicout := (others => '-'); end case;-- generate condition codes if (ex.alusel(1) = '0') then res := addout; if ex.aluadd = '0' then icc(0) := ((not aluin1(31)) and aluin2(31)) or -- Carry (addout(31) and ((not aluin1(31)) or aluin2(31))); icc(1) := (aluin1(31) and (not aluin2(31)) and not addout(31)) or -- Overflow (addout(31) and (not aluin1(31)) and aluin2(31)); else icc(0) := (aluin1(31) and aluin2(31)) or -- Carry ((not addout(31)) and (aluin1(31) or aluin2(31))); icc(1) := (aluin1(31) and aluin2(31) and not addout(31)) or -- Overflow (addout(31) and (not aluin1(31)) and (not aluin2(31))); end if; else res := logicout; icc(1 downto 0) := "00"; end if; if res = zero32 then -- Zero icc(2) := '1'; else icc(2) := '0'; end if; icc(3) := res(31); -- Negative-- select Y if (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1' then y := me.y; else y := wr.y; end if;-- alu ops which dont set icc miscout := (others => '-'); case ex.aluop is when ALU_STB => miscout := aluin1(7 downto 0) & aluin1(7 downto 0) & aluin1(7 downto 0) & aluin1(7 downto 0); when ALU_STH => miscout := aluin1(15 downto 0) & aluin1(15 downto 0); when ALU_PASS1 => miscout := aluin1; when ALU_PASS2 => miscout := aluin2; when ALU_ONES => miscout := (others => '1'); when ALU_RDY => miscout := y; when ALU_FSR => if ((FPTYPE = meiko) and FPEN) then miscout := fpu_reg.fsr.rd & "00" & fpu_reg.fsr.tem & "000" & std_logic_vector(FPUVER) & fpu_reg.fsr.ftt & "00" & fpu_reg.fsr.fcc & fpu_reg.fsr.aexc & fpu_reg.fsr.cexc; end if; when ALU_FOP => if ((FPTYPE = meiko) and FPEN) then miscout := aluin2; case opf(3 downto 2) is when "01" => miscout(31) := not miscout(31); when "10" => miscout(31) := '0'; when others => null; end case; end if; when others => null; end case;-- shifter shiftin := zero32 & aluin1; shiftcnt := aluin2(4 downto 0); if ex.aluop = ALU_SLL then shiftin(31 downto 0) := zero32; shiftin(63 downto 31) := '0' & aluin1; shiftcnt := not shiftcnt; elsif ex.aluop = ALU_SRA then if aluin1(31) = '1' then shiftin(63 downto 32) := (others => '1'); else shiftin(63 downto 32) := zero32; end if; end if; if shiftcnt (4) = '1' then shiftin(47 downto 0) := shiftin(63 downto 16); end if; if shiftcnt (3) = '1' then shiftin(39 downto 0) := shiftin(47 downto 8); end if; if shiftcnt (2) = '1' then shiftin(35 downto 0) := shiftin(39 downto 4); end if; if shiftcnt (1) = '1' then shiftin(33 downto 0) := shiftin(35 downto 2); end if; if shiftcnt (0) = '1' then shiftin(31 downto 0) := shiftin(32 downto 1); end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -