📄 iu.vhd
字号:
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;
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;
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 others => aluop := ALU_NOP;
end case;
when others => -- LDST
case ctrl.cnt is
when "00" =>
alusel := ALU_RES_ADD;
when "01" =>
case op3 is
when LDD | LDDA =>
rd(0) := '1'; alusel := ALU_RES_ADD;
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
alusel := ALU_RES_ADD;
when others =>
aluop := ALU_PASS1;
if op3(2) = '1' then -- ST
rs1 := rd;
if op3(1 downto 0) = "01" then -- store byte
aluop := ALU_STB;
elsif op3(1 downto 0) = "10" then -- store halfword
aluop := ALU_STH;
end if;
end if;
end case;
when "10" =>
aluop := ALU_PASS1;
case op3 is
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
rs1 := rd;
if op3(1) = '0' then aluop := ALU_ONES; end if; -- LDSTUB(A)
when ISTD | STDA =>
rs1 := rd(4 downto 1) & '1'; -- STD
when others =>
end case;
when others =>
end case;
end case;
exin.aluop <= aluop;
exin.alusel <= alusel;
exin.aluadd <= aluadd;
exin.mulstep <= mulstep;
exin.mulinsn <= mulinsn;
-- Alu operand select
case op is
when FMT2 =>
case op2 is
when SETHI => operand2_select := ALU_SIMM;
when others => operand2_select := ALU_RS2;
end case;
when FMT3 =>
case op3 is
when RDWIM | RDPSR | RDTBR => operand2_select := ALU_SIMM;
when others =>
if (de.inst(13) = '1') then
operand2_select := ALU_SIMM;
else
operand2_select := ALU_RS2;
end if;
end case;
when LDST =>
if (de.inst(13) = '1') then
operand2_select := ALU_SIMM;
else
operand2_select := ALU_RS2;
end if;
when others => operand2_select := ALU_RS2;
end case;
-- CWP generation, pipelinig and forwarding
-- Also check for window underflow/overflow conditions
if (op = FMT3) and
((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE))
then
write_cwp := '1';
if (op3 = SAVE) then
-- pragma translate_off
if not is_x(de.cwp) then
-- pragma translate_on
if (not CWPOPT) and (de.cwp = CWPMIN) then
cwp_new := CWPMAX;
else
cwp_new := de.cwp - 1 ;
end if;
-- pragma translate_off
end if;
-- pragma translate_on
else
-- pragma translate_off
if not is_x(de.cwp) then
-- pragma translate_on
if (not CWPOPT) and (de.cwp = CWPMAX) then
cwp_new := CWPMIN;
else
cwp_new := de.cwp + 1;
end if;
-- pragma translate_off
end if;
-- pragma translate_on
end if;
if sregs.wim(conv_integer(cwp_new)) = '1' then
if op3 = SAVE then
winovf_exception := '1';
else
winunf_exception := '1';
end if;
end if;
end if;
exin.write_cwp <= write_cwp;
exin.cwp <= cwp_new;
-- Immediate data generation
case op is
when FMT2 =>
immediate_data := de.inst(21 downto 0) & "0000000000";
when FMT3 =>
case op3 is
when RDPSR => immediate_data := IMPL & VER & icc & "000000" &
sregs.ec & sregs.ef & sregs.pil & su & sregs.ps & et
& CWPFILL & de.cwp;
when RDTBR => immediate_data := sregs.tba & sregs.tt & "0000";
when RDWIM => immediate_data := WIMFILL & sregs.wim;
when others =>
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12 downto 0);
end case;
when others => -- LDST
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
de.inst(12 downto 0);
end case;
-- register read address generation
read_addr1(3 downto 0) := rs1(3 downto 0);
read_addr2(3 downto 0) := rs2(3 downto 0);
if rs1(4 downto 3) = "00" then
read_addr1(RABITS -1 downto 4) := R0ADDR;
else
-- pragma translate_off
if not (is_x(de.cwp & rs1(4))) then
-- pragma translate_on
read_addr1(NWINLOG2+3 downto 4) := (de.cwp + rs1(4));
if not CWPOPT then
if read_addr1(RABITS-1 downto 4) = R0ADDR then
read_addr1(RABITS-1 downto 4) := (others => '0');
end if;
else read_addr1(RABITS-1) := '0'; end if;
-- pragma translate_off
end if;
-- pragma translate_on
end if;
if i = '1' then read_addr2 := (others => '-');
elsif rs2(4 downto 3) = "00" then
read_addr2(RABITS -1 downto 4) := R0ADDR;
else
-- pragma translate_off
if not is_x(de.cwp & rs2(4)) then
-- pragma translate_on
read_addr2(NWINLOG2+3 downto 4) := (de.cwp + rs2(4));
if not CWPOPT then
if read_addr2(RABITS-1 downto 4) = R0ADDR then
read_addr2(RABITS-1 downto 4) := (others => '0');
end if;
else read_addr2(RABITS-1) := '0'; end if;
-- pragma translate_off
end if;
-- pragma translate_on
end if;
rfi.rd1addr <= read_addr1;
rfi.rd2addr <= read_addr2;
-- LD delay interlock generation
ldcheck1 := '0'; ldcheck2 := '0'; ldlock := '0';
ldchkex := '1'; ldchkme := '1';
if (de.annul = '0') then
case op is
when FMT3 =>
case op3 is
when RDY | RDWIM | RDPSR | RDTBR => null;
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
if (ctrl.cnt = "00") then ldcheck1 := '1'; end if;
if (i = '0') and (ctrl.cnt = "01") then ldcheck2 := '1'; end if;
end if;
when others =>
ldcheck1 := '1'; if i = '0' then ldcheck2 := '1'; end if;
end case;
when LDST =>
ldcheck1 := '1';
if (i = '0') then
ldcheck2 := '1';
end if;
if ctrl.cnt /= "00" then ldchkex := '0'; end if;
if ctrl.cnt = "10" then ldchkme := '0'; end if;
when others => null;
end case;
end if;
if (ex.ctrl.ld and ex.write_reg and ldchkex and not ex.ctrl.annul) = '1' then
if ((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2))
then
ldlock := '1';
end if;
end if;
if (me.ctrl.ld and me.write_reg and ldchkme and not me.ctrl.annul) = '1' then
if (LDDELAY = 2) then
if ((ldcheck1 = '1') and (me.ctrl.rd = read_addr1)) or
((ldcheck2 = '1') and (me.ctrl.rd = read_addr2))
then
ldlock := '1';
end if;
end if;
end if;
-- register write address generation
write_reg := '0';
if op = CALL then
write_reg := '1'; rd := "01111"; -- CALL saves PC in r[15] (%o7)
elsif rd /= "00000" then -- don't write result if destination is %g0
case op is
when FMT2 =>
if (op2 = SETHI) then write_reg := '1'; end if;
when FMT3 =>
case op3 is
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
if de.cnt = "10" then write_reg := '1'; end if;
end if;
when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
when others => write_reg := '1';
end case;
when LDST =>
if op3(2) = '0' then write_reg := '1'; end if;
case op3 is
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
if ctrl.cnt = "00" then write_reg := '1'; end if;
when others => null;
end case;
when others => null;
end case;
end if;
ctrl.rd(3 downto 0) := rd(3 downto 0);
if rd(4 downto 3) = "00" then
ctrl.rd(RABITS -1 downto 4) := R0ADDR;
else
-- pragma translate_off
if not is_x(cwp_new & rd(4)) then
-- pragma translate_on
ctrl.rd(NWINLOG2+3 downto 4) := (cwp_new + rd(4));
if not CWPOPT then
if ctrl.rd(RABITS-1 downto 4) = R0ADDR then
ctrl.rd(RABITS-1 downto 4) := (others => '0');
end if;
else ctrl.rd(RABITS-1) := '0'; end if;
-- pragma translate_off
end if;
-- pragma translate_on
end if;
-- data forwarding detection. Forward data if destination and source
-- registers are equal and destination register will be written.
rs1data := rfo.data1; ldbp1 := '0';
if rs1 = "00000" then
rs1data := (others => '0');
elsif ldcheck1 = '1' then
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
(read_addr1 = ex.ctrl.rd)
then
rs1data := ex.result;
elsif ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
rs1data := me.result;
if LDDELAY = 1 then ldbp1 := me.ctrl.ld; end if;
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr1 = wr.ctrl.rd) then
rs1data := wr.result;
end if;
end if;
rs2data := rfo.data2; ldbp2 := '0';
if operand2_select = ALU_SIMM then
rs2data := immediate_data;
elsif rs2 = "00000" then
rs2data := (others => '0');
elsif ldcheck2 = '1' then
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and (read_addr2 = ex.ctrl.rd) then
rs2data := ex.result;
elsif ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
rs2data := me.result;
if LDDELAY = 1 then ldbp2 := me.ctrl.ld; end if;
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr2 = wr.ctrl.rd) then
rs2data := wr.result;
end if;
end if;
exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;
-- multiply operand generation
if (ex.write_y and not ex.ctrl.annul) = '1' then
y0 := mein.y(0);
elsif (me.write_y and not me.ctrl.annul) = '1' then
y0 := me.y(0);
else
y0 := wr.y(0);
end if;
ymsb := '-';
case op is
when FMT3 =>
case op3 is
when MULSCC =>
ymsb := rs1data(0); rs1data := (n xor v) & rs1data(31 downto 1);
if y0 = '0' then rs2data := (others => '0'); end if;
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
case de.cnt is
when "00" =>
rs2data := (others => '0'); ymsb := rs1data(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';
end if;
when others =>
if (op3 = UMUL) or (op3 = UMULCC) then
rs2data := ex.result;
if rfo.data2(31) = '0' then rs1data := (others => '0'); end if;
else
rs1data := ex.result;
if rfo.data1(31) = '0' then rs2data := (others => '0'); end if;
end if;
end case;
end if;
when others => null;
end case;
when others => null;
end case;
exin.rs1data <= rs1data;
exin.rs2data <= rs2data;
exin.ymsb <= ymsb;
-- PC generation
branch := '0'; annul_next := '0'; annul_current := '0';
inull := not Rst; hold_pc := '0'; ticc_exception := '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 then
branch := branch_true;
if (branch_true = '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;
when FMT3 =>
case op3 is
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
case ctrl.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;
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 ctrl.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';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -