📄 iu.vhd
字号:
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') and ((op3(5) = '0') or not CPEN) 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;-- bypassed operands to multiplier muli.signed <= op3(0); divi.signed <= op3(0); mulop1 := (aluin1(31) and op3(0)) & aluin1; mulop2 := (aluin2(31) and op3(0)) & aluin2; if (ex.mulinsn = '0') and not INFER_MULT then -- try to minimise power mulop1 := (others => '0'); mulop2 := (others => '0'); end if; muli.op1 <= mulop1; muli.op2 <= mulop2; divi.op1 <= (aluin1(31) and op3(0)) & aluin1; divi.op2 <= (aluin2(31) and op3(0)) & aluin2;-- ALU add/sub icc := "0000";-- pragma translate_off if not (is_x(aluin1) or is_x(aluin2)) then-- pragma translate_on cin := ex.alu_cin; addin2 := aluin2; if ex.aluadd = '0' then addin2 := not aluin2; cin := not cin; end if;-- addout := aluin1 + addin2 + cin; if FASTADD then addout := sum32; else if ex.aluadd = '0' then addout := aluin1 - aluin2 - ex.alu_cin; else addout := aluin1 + aluin2 + ex.alu_cin; end if; end if;-- pragma translate_off end if;-- pragma translate_on add32in1 <= aluin1; add32in2 <= addin2; add32cin <= cin;-- 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 ALU_DIV => if DIVIDER /= none then logicout := aluin2; else logicout := (others => '-'); end if; 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.my; else y := wr.y; end if;-- alu ops which dont set icc miscout := (others => '-'); edata := (others => '-'); case ex.aluop is when ALU_STB => edata := aluin1(7 downto 0) & aluin1(7 downto 0) & aluin1(7 downto 0) & aluin1(7 downto 0); miscout := edata; when ALU_STH => edata := aluin1(15 downto 0) & aluin1(15 downto 0); miscout := edata; when ALU_PASS1 => miscout := aluin1; edata := aluin1; when ALU_PASS2 => miscout := aluin2; when ALU_ONES => miscout := (others => '1'); edata := (others => '1'); when ALU_RDY => miscout := y; if (WATCHPOINTS > 0) and (rs1(4 downto 3) = "11") then wpi := conv_integer(unsigned(rs1(2 downto 1))); if rs1(0) = '0' then miscout := tr(wpi).addr & '0' & tr(wpi).exec; else miscout := tr(wpi).mask & tr(wpi).load & tr(wpi).store; end if; end if; when ALU_FSR => if ((FPIFTYPE = serial) and FPEN) then edata := 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; miscout := edata; end if; when ALU_FOP => if ((FPIFTYPE = serial) 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; 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 ((FPIFTYPE = serial) 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 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; if (MULTIPLIER = m32x32) and (ex.mulinsn = '1') then aluresult := mulo.result(31 downto 0); end if; if MACEN then if ex.aluop = ALU_RDY then if rs1 = "10010" then if ((me.mulinsn and me.ctrl.inst(24)) = '1') then aluresult := mulo.result(31 downto 0); else aluresult := wr.asr18; end if; else if ((me.mulinsn and me.ctrl.inst(24)) = '1') then aluresult := mulo.result(63 downto 32); end if; end if; end if; 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') and (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; elsif ((ex.rst_mey or ex.write_y) = '1') and (MULTIPLIER = iterative) then if ex.ctrl.cnt = "11" then nexty := addout; else nexty := logicout; end if; elsif ex.write_y = '1' then nexty := logicout; end if; if (MULTIPLIER = iterative) then micc(3) := icc(3) and not ex.rst_mey; micc(1) := icc(1) and not ex.rst_mey; end if;-- 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 (FPIFTYPE = parallel) 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -