📄 iu.vhd
字号:
memory_stage : process(me, wr, sregs, sregsin, sysi, dco)
variable op : std_logic_vector(1 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);
begin
-- common initialisation
op := me.ctrl.inst(31 downto 30);
op3 := me.ctrl.inst(24 downto 19);
ctrl := me.ctrl;
ctrl.annul := ctrl.annul or wr.annul_all;
nullify := ctrl.annul;
iflush := '0';
cwp := me.cwp; write_cwp := me.write_cwp;
-- external interrupt handling
-- use sregsin.pil and sregsin.et since a WRPSR should affect ET and PIL
-- without delay (SPARC V8 ISP, p.183)
if ((ctrl.annul or ctrl.trap) = '0') and ((sregsin.et and ctrl.pv) = '1') then
if (sysi.irl = "1111") or (sysi.irl > sregsin.pil) then
ctrl.trap := '1'; ctrl.tt := "01" & sysi.irl;
if op = LDST then nullify := '1'; end if;
end if;
end if;
if ((ctrl.annul or ctrl.trap) /= '1') then
case op is
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;
when JMPL | RETT =>
if me.addr_misal = '1' then ctrl.trap := '1'; ctrl.tt := UNALA_TT; end if;
when TADDCCTV | TSUBCCTV =>
if me.icc(1) = '1' then ctrl.trap := '1'; ctrl.tt := TAG_TT; end if;
when FLUSH => iflush := '1';
when others => null;
end case;
when LDST =>
if ctrl.cnt = "00" then
case op3 is
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 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;
if (me.memory_load or not dco.mds) = '1' then
wrin.result <= dco.data;
else
wrin.result <= me.result; -- data load bus
end if;
if ((ctrl.annul or ctrl.trap) /= '1') and (me.write_y = '1') then
wrin.y <= me.y;
else
wrin.y <= wr.y;
end if;
wrin.cwp <= cwp; wrin.write_cwp <= write_cwp;
wrin.ctrl <= ctrl;
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)
variable op : std_logic_vector(1 downto 0);
variable op3 : std_logic_vector(5 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 icc : std_logic_vector(3 downto 0);
variable tt : std_logic_vector(7 downto 0);
variable tba : std_logic_vector(19 downto 0);
variable wim : std_logic_vector(NWINDOWS-1 downto 0);
variable pil : std_logic_vector(3 downto 0);
variable ec, ef, ps, s, et : std_logic;
variable exception : std_logic;
variable trapping : std_logic;
variable save_pc : std_logic;
variable error : std_logic;
variable intack : std_logic;
variable tpcsel : std_logic_vector(1 downto 0);
variable trap_address : std_logic_vector(31 downto PCLOW); -- trap address
begin
-- common initialisation
op := wr.ctrl.inst(31 downto 30);
op3 := wr.ctrl.inst(24 downto 19);
rd_address := wr.ctrl.rd;
write_reg := '0';
annul_all := '0'; exception := '0';
trapping := wr.trapping; tpcsel := "00";
save_pc := '0'; error := wr.error; intack := '0';
trap_address(31 downto 4) := sregs.tba & sregs.tt;
trap_address(3 downto PCLOW) := (others => '0');
-- special registers write handling
icc := sregs.icc; cwp := sregs.cwp; ef := sregs.ef; ec := sregs.ec;
pil := sregs.pil; s := sregs.s; ps := sregs.ps; et := sregs.et;
tba := sregs.tba; tt := sregs.tt; wim := sregs.wim;
if (wr.ctrl.annul or wr.ctrl.trap) /= '1' then
if wr.write_cwp = '1' then
cwp := wr.cwp;
end if;
write_reg := wr.write_reg;
case op is
when FMT3 =>
case op3 is
when WRPSR =>
cwp := wr.result(NWINLOG2-1 downto 0);
icc := wr.result(23 downto 20);
ec := wr.result(13);
ef := wr.result(12);
pil := wr.result(11 downto 8);
s := wr.result(7);
ps := wr.result(6);
et := wr.result(5);
when WRWIM =>
wim := wr.result(NWINDOWS-1 downto 0);
when WRTBR =>
tba := wr.result(31 downto 12);
when RETT =>
s := ps;
et := '1';
when others => null;
end case;
when others => null;
end case;
if wr.write_icc = '1' then
icc := wr.icc;
end if;
end if;
-- trap handling
if (((wr.ctrl.trap and not wr.ctrl.annul) or wr.mexc or trapping) = '1') then
if trapping = '0' then -- first trap cycle
if et = '0' then
error := HALTONERROR;
end if;
annul_all := '1'; trapping := '1'; ps := s; s := '1';
if wr.wexc = '1' then tt := "00" & DSEX_TT;
elsif wr.mexc = '1' then tt := "00" & DAEX_TT;
elsif wr.ctrl.tt = TICC_TT then tt := '1' & wr.result(6 downto 0);
else tt := "00" & wr.ctrl.tt; end if;
write_reg := '1'; save_pc := '1';
-- pragma translate_off
if not is_x(cwp) then
-- pragma translate_on
rd_address := (others => '0');
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0001";
-- pragma translate_off
end if;
-- pragma translate_on
if ((not me.ctrl.annul) and me.ctrl.pv) = '1' then tpcsel := "00";
elsif ((not ex.ctrl.annul) and ex.ctrl.pv) = '1' then tpcsel := "01";
elsif ((not de.annul) and de.pv) = '1' then tpcsel := "10";
else tpcsel := "11"; end if;
else -- second trap cycle
if error = '1' then
annul_all := '1'; trapping := '1';
else
trapping := '0'; annul_all := '1';
if sregs.tt(5 downto 4) = "01" then intack := '1'; end if;
write_reg := '1'; save_pc := '1';
-- pragma translate_off
if not is_x(cwp) then
-- pragma translate_on
rd_address := (others => '0');
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0010";
-- pragma translate_off
end if;
-- pragma translate_on
-- pragma translate_off
if not is_x(cwp) then
-- pragma translate_on
if (not CWPOPT) and (cwp = CWPMIN) then cwp := CWPMAX;
else cwp := cwp - 1; end if;
-- pragma translate_off
end if;
-- pragma translate_on
end if;
exception := '1'; et := '0';
end if;
if ((not sregs.et) and (not HALTONERROR)) = '1' then
trap_address(11 downto 4) := (others => '0');
end if;
end if;
-- pragma translate_off
if DEBUGPORT then
debug.tt <= tt;
debug.trap <= trapping;
end if;
-- pragma translate_on
-- reset handling
if Rst = '0' then
et := '0'; s := '1'; annul_all := '1';
trapping := '0'; save_pc := '0'; exception := '0'; error := '0';
end if;
if save_pc = '1' then
case wr.tpcsel is
when "00" => rfi.wrdata <= wr.ctrl.pc(31 downto 2) & "00";
when "01" => rfi.wrdata <= me.ctrl.pc(31 downto 2) & "00";
when "10" => rfi.wrdata <= ex.ctrl.pc(31 downto 2) & "00";
when others => rfi.wrdata <= de.pc(31 downto 2) & "00";
end case;
else
rfi.wrdata <= wr.result;
end if;
syso.error <= not wr.error;
syso.intack <= wr.intack;
syso.irqvec <= sregs.tt(3 downto 0);
wr.annul_all <= annul_all;
wrin.trapping <= trapping;
wrin.tpcsel <= tpcsel;
wrin.error <= error;
wrin.intack <= intack;
sregsin.cwp <= cwp;
sregsin.icc <= icc;
sregsin.ec <= ec;
sregsin.ef <= ef;
sregsin.pil <= pil;
sregsin.s <= s;
sregsin.ps <= ps;
sregsin.et <= et;
sregsin.wim <= wim;
sregsin.tba <= tba;
sregsin.tt <= tt;
rfi.wraddr <= rd_address;
rfi.wren <= write_reg;
fecomb.exception <= exception;
fecomb.trap_address <= trap_address;
end process;
-- missed instruction and data registers
instmux : process(dein, ico, de, fecomb)
begin
if (ico.mds and fecomb.hold_pc) = '1' then
dein.inst <= de.inst;
dein.mexc <= de.mexc;
else
dein.inst <= ico.data;
dein.mexc <= ico.exception;
end if;
end process;
ir0: if GATEDCLK generate -- use generate to make sure no gates are placed
iregs : process (iclk) -- on the clock line during synthesis
begin
if iclk'event and (iclk = '1') then
de.inst <= dein.inst;
de.mexc <= dein.mexc;
end if;
end process;
dregs : process(dclk)
begin
if dclk'event and dclk = '1' then
wr.result <= wrin.result;
wr.mexc <= dco.mexc;
wr.wexc <= dco.wexc;
end if;
end process;
end generate;
ir1: if not GATEDCLK generate
iregs : process (clk)
begin
if clk'event and (clk = '1') then
if (holdn or (not ico.mds)) = '1' then
de.inst <= dein.inst;
de.mexc <= dein.mexc;
end if;
end if;
end process;
dregs : process(clk)
begin
if clk'event and clk = '1' then
if (holdn or (not dco.mds)) = '1' then
wr.mexc <= dco.mexc;
wr.wexc <= dco.wexc;
wr.result <= wrin.result;
end if;
end if;
end process;
end generate;
-- normal registers
pregs : process (clk)
begin
if clk'event and (clk = '1') then
if (holdn = '1') or GATEDCLK then
-- fetch stage
fe <= fein;
-- decode stage
de.annul <= dein.annul;
de.cnt <= dein.cnt;
de.mulcnt <= dein.mulcnt;
de.cwp <= dein.cwp;
de.pv <= dein.pv;
de.pc <= dein.pc;
-- execute stage
ex.ctrl <= exin.ctrl;
ex.write_reg <= exin.write_reg;
ex.ctrl.rd <= exin.ctrl.rd;
ex.write_cwp <= exin.write_cwp;
ex.cwp <= exin.cwp;
ex.write_y <= exin.write_y;
ex.rst_mey <= exin.rst_mey;
ex.write_icc <= exin.write_icc;
ex.rs1data <= exin.rs1data;
ex.rs2data <= exin.rs2data;
ex.alu_cin <= exin.alu_cin;
ex.aluop <= exin.aluop;
ex.alusel <= exin.alusel;
ex.aluadd <= exin.aluadd;
ex.mulstep <= exin.mulstep;
ex.mulinsn <= exin.mulinsn;
ex.ycarry <= exin.ycarry;
ex.ymsb <= exin.ymsb;
dci.write <= dciin.write;
dci.asi <= dciin.asi;
dci.enaddr <= dciin.enaddr;
dci.read <= dciin.read;
dci.lock <= dciin.lock;
-- memory stage
me.result <= mein.result;
me.y <= mein.y;
me.ctrl <= mein.ctrl;
dci.size <= mein.ld_size;
me.memory_load <= mein.memory_load;
dci.signed <= mein.signed;
me.write_reg <= ex.write_reg;
me.ctrl.rd <= ex.ctrl.rd;
me.write_cwp <= ex.write_cwp;
me.cwp <= ex.cwp;
me.write_y <= ex.write_y;
me.write_icc <= ex.write_icc;
me.icc <= mein.icc;
me.addr_misal <= mein.addr_misal;
-- write stage
wr.y <= wrin.y;
wr.ctrl <= wrin.ctrl;
wr.write_reg <= me.write_reg;
wr.ctrl.rd <= me.ctrl.rd;
wr.write_cwp <= wrin.write_cwp;
wr.cwp <= wrin.cwp;
wr.write_icc <= me.write_icc;
wr.icc <= me.icc;
wr.tpcsel <= wrin.tpcsel;
wr.trapping <= wrin.trapping;
wr.error <= wrin.error;
wr.intack <= wrin.intack;
-- special registers
sregs.cwp <= sregsin.cwp;
sregs.icc <= sregsin.icc;
sregs.tt <= sregsin.tt;
sregs.tba <= sregsin.tba;
sregs.wim <= sregsin.wim;
sregs.ec <= sregsin.ec;
sregs.ef <= sregsin.ef;
sregs.et <= sregsin.et;
sregs.ps <= sregsin.ps;
sregs.s <= sregsin.s;
sregs.pil <= sregsin.pil;
end if;
end if;
end process;
ldbpr0 : if LDDELAY = 1 generate
lb : process(clk)
begin
if clk'event and (clk = '1') then
if (holdn = '1') or GATEDCLK then
ex.ldbp1 <= exin.ldbp1;
ex.ldbp2 <= exin.ldbp2;
end if;
end if;
end process;
end generate;
-- debugging support
-- pragma translate_off
debug0 : if DEBUGPORT generate
debug.clk <= clk;
debug.rst <= rst;
debug.holdn <= holdn;
debug.ex <= ex.ctrl;
debug.me <= me.ctrl;
debug.wr <= wr.ctrl;
end generate;
-- pragma translate_on
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -