iu.vhd
来自「sparc org, vhdl rtl code」· VHDL 代码 · 共 1,813 行 · 第 1/5 页
VHD
1,813 行
when "01" =>
if (op3(2) and not op3(3)) = '1' then -- ST
rs1 := rd; rs1mod := '1';
end if;
case op3 is
when LDD | LDDA | LDDC =>
rd(0) := '1'; alusel := ALU_RES_ADD;
when LDDF =>
rd(0) := '1'; alusel := ALU_RES_ADD;
if FPEN then fpld := '1'; end if;
when STFSR => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_FSR; end if;
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
alusel := ALU_RES_ADD;
when STF | STDF =>
if ((FPIFTYPE = serial) and FPEN) then
aluop := ALU_PASS1; fpst := '1';
end if;
when others =>
aluop := ALU_PASS1;
if op3(2) = '1' then -- ST
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;
rs1 := rd; rs1mod := '1';
if op3(2) = '1' then -- ST
if (op3(3) and not op3(1))= '1' then aluop := ALU_ONES; -- LDSTUB/A
elsif op3(3 downto 0) = "0111" then
rs1(0) := '1'; -- STD/F/A
if ((FPIFTYPE = serial) and FPEN) and (op3(5) = '1') then fpst := '1'; end if;
end if;
end if;
when others =>
end case;
end case;
exin.aluop <= aluop; exin.alusel <= alusel; exin.aluadd <= aluadd;
exin.mulstep <= mulstep; exin.mulinsn <= mulinsn;
-- Alu operand select
operand2_select := ALU_SIMM;
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 FPOP1 | FPOP2 => if ((FPIFTYPE = serial) and FPEN) then operand2_select := ALU_RS2; end if;
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('0' & 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
immediate_data := (others => '0');
case op is
when FMT2 =>
immediate_data := de.inst(21 downto 0) & "0000000000";
when FMT3 =>
case op3 is
when RDPSR => immediate_data(31 downto 5) := std_logic_vector(IMPL) &
std_logic_vector(VER) & icc & "000000" & sregs.ec & sregs.ef &
sregs.pil & su & sregs.ps & et;
immediate_data(NWINLOG2-1 downto 0) := de.cwp;
when RDTBR => immediate_data(31 downto 4) := sregs.tba & sregs.tt;
when RDWIM => immediate_data(NWINDOWS-1 downto 0) := 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
if RS1OPT then
if rs1mod = '1' then
read_addr1 := regdec(de.cwp, de.inst(29 downto 26) & rs1(0), (fpst or fpop));
else
read_addr1 := regdec(de.cwp, de.inst(18 downto 15) & rs1(0), (fpst or fpop));
end if;
else
read_addr1 := regdec(de.cwp, rs1, (fpst or fpop));
end if;
read_addr2 := regdec(de.cwp, rs2, fpop);
-- register write address generation
write_reg := '0'; fsr_ld := '0';
case op is
when CALL =>
write_reg := '1'; rd := "01111"; -- CALL saves PC in r[15] (%o7)
when FMT2 =>
if (op2 = SETHI) then write_reg := '1'; end if;
when FMT3 =>
case op3 is
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = none then write_reg := '1'; end if;
if MULTIPLIER = m32x32 then write_reg := '1'; end if;
if MULTIPLIER = iterative then
if de.cnt = "10" then write_reg := '1'; end if;
end if;
when UDIV | SDIV | UDIVCC | SDIVCC =>
if DIVIDER /= none then write_reg := '0'; else write_reg := '1'; end if;
when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
when FPOP1 | FPOP2 => null;
when CPOP1 | CPOP2 => null;
when others => write_reg := '1';
end case;
when LDST =>
ctrl.ld := not op3(2);
if (op3(2) = '0') and
not ((CPEN or (FPIFTYPE = parallel)) and (op3(5) = '1'))
then write_reg := '1'; end if;
case op3 is
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
if de.cnt = "00" then write_reg := '1'; end if;
when LDFSR => if ((FPIFTYPE = serial) and FPEN) then write_reg := '0'; fsr_ld := '1'; end if;
when others => null;
end case;
when others => null;
end case;
if (rd = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpld = '1')) then
write_reg := '0';
end if;
ctrl.rd := regdec(cwp_new, rd, (fpld or fpop));
if RDOPT then chkrd := regdec(de.cwp, rd, (fpld or fpop));
else chkrd := ctrl.rd; end if;
-- LD/BICC/TICC delay interlock generation
ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0';
ldchkex := '1'; ldchkme := '1'; bicc_hold := '0'; icc_check := '0';
fsr_check := '0'; fsr_ld_check := '0'; fsr_lock := '0';
if (de.annul = '0') then
case op is
when FMT2 =>
if (op2 = BICC) and (cond(2 downto 0) /= "000") then
icc_check := '1';
end if;
when FMT3 =>
ldcheck1 := '1'; ldcheck2 := not i;
case op3 is
when TICC =>
if (cond(2 downto 0) /= "000") then icc_check := '1'; end if;
when RDY | RDWIM | RDTBR =>
ldcheck1 := '0'; ldcheck2 := '0';
when RDPSR =>
ldcheck1 := '0'; ldcheck2 := '0';
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
when ADDX | ADDXCC | SUBX | SUBXCC =>
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
when UMUL | SMUL | UMULCC | SMULCC =>
if MULTIPLIER = iterative then
ldcheck1 := '0'; ldcheck2 := '0';
if (de.cnt = "00") then ldcheck1 := '1'; end if;
if (de.cnt = "01") then ldcheck2 := not i; end if;
end if;
when FPOP1 | FPOP2 =>
if ((FPIFTYPE = serial) and FPEN) then
ldcheck1 := '0'; ldcheck2 := '0';
case opf is
when FITOS | FITOD | FSTOI | FDTOI | FSTOD | FDTOS | FMOVS |
FNEGS | FABSS | FSQRTS | FSQRTD =>
ldcheck2 := '1';
when others => ldcheck1 := '1'; ldcheck2 := '1';
end case;
if de.cnt /= "00" then ldchkex := '0'; end if;
fsr_ld_check := '1';
end if;
when others =>
end case;
when LDST =>
ldcheck1 := '1'; ldchkex := '0';
case de.cnt is
when "00" => -- check store data dependency if 2-cycle load delay
if (LDDELAY = 2) and (op3(2) = '1') and not (((FPIFTYPE = serial) and FPEN) and (op3 = STFSR))
then ldcheck3 := '1'; end if;
ldcheck2 := not i; ldchkex := '1';
when "01" => ldcheck2 := not i;
when others => ldchkme := '0';
end case;
if ((FPIFTYPE = serial) and FPEN) and ((op3 = LDFSR) or (op3 = STFSR)) then
fsr_check := '1';
if (op3 = STFSR) then fsr_ld_check := '1'; end if;
end if;
when others => null;
end case;
end if;
-- MAC has two-cycle latency, check for data-dependecies
if MACEN then
if ((ex.mulinsn and ex.ctrl.inst(24) and ldchkex and not ex.ctrl.annul) = '1') and
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
then ldlock := '1'; end if;
end if;
if MACEN or (MULTIPLIER = m32x32) then
bicc_hold := icc_check and ex.write_icc and ex.mulinsn and not ex.ctrl.annul;
end if;
if ICC_HOLD then
bicc_hold := bicc_hold or (icc_check and ex.write_icc and not ex.ctrl.annul);
end if;
if ((ex.ctrl.ld and ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
then ldlock := '1'; end if;
if ((me.ctrl.ld and me.write_reg and ldchkme and not me.ctrl.annul) = '1') and
((LDDELAY = 2) or ((fsr_ld_check and not fsr_check) = '1')) and
(((ldcheck1 = '1') and (me.ctrl.rd = read_addr1)) or
((ldcheck2 = '1') and (me.ctrl.rd = read_addr2)))
then ldlock := '1'; end if;
if ((FPIFTYPE = serial) and FPEN) then
if (fsr_check = '1') then
fsr_lock := ((xorv(fpu_reg.ex.fpop) and not ex.ctrl.annul) or
(xorv(fpu_reg.me.fpop) and not me.ctrl.annul) or
(xorv(fpu_reg.wr.fpop) and not wr.ctrl.annul));
end if;
if fsr_ld_check = '1' then
fsr_lock := fsr_lock or (fpu_reg.ex.ldfsr and not ex.ctrl.annul)
or (fpu_reg.me.ldfsr and not me.ctrl.annul)
or (fpu_reg.wr.ldfsr and not wr.ctrl.annul);
end if;
end if;
ldlock := ldlock or bicc_hold or fsr_lock;
cpldlock := ldlock; fpldlock := ldlock;
if CPEN then
if FPIFTYPE = parallel then cpldlock := cpldlock or fpo.ldlock; end if;
ldlock := ldlock or cpo.ldlock;
end if;
if FPIFTYPE = parallel then
if CPEN then fpldlock := fpldlock or cpo.ldlock; end if;
ldlock := ldlock or fpo.ldlock;
end if;
-- data forwarding detection. Forward data if destination and source
-- registers are equal and destination register will be written.
rs1data := rfo.data1(31 downto 0); ldbp1 := '0';
if (rs1 = "00000") and not (((FPIFTYPE = serial) and FPEN) and ((fpop or fpst) = '1')) 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;
else
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
rs1data := mein.bpresult;
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;
else rfenable1 := '1'; end if;
end if;
end if;
rs2data := rfo.data2(31 downto 0); ldbp2 := '0';
if (operand2_select = ALU_SIMM) then
rs2data := immediate_data;
elsif (rs2 = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpop = '1')) 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;
else
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
rs2data := mein.bpresult;
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;
else rfenable2 := '1'; end if;
end if;
end if;
-- 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 or me.ctrl.trap)) = '1' then
y0 := me.my(0);
else
y0 := wr.y(0);
end if;
ymsb := '-';
-- mul/div unit
divi.y <= (wr.y(31) and op3(0)) & wr.y;
divstart := '0'; mulstart := '0';
case op is
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?