📄 fp.vhd
字号:
if (rx.holdn = '0') and (xholdn = '1') and (cpi.flush = '0') and
((r.sdep and ddep) = '0') and (euo(r.eut)(euq(r.eut).first).busy = '0')
then
euiv(r.eut)(r.eui).start := not rx.startx;
euiv(r.eut)(r.eui).opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
end if;
if (rx.holdn = '0') and (cpi.flush = '0') and
(not ((r.sdep = '1') and (ddep = '1'))) and
((eu(r.eut)(r.eui).status <= free) or
(euin(r.eut)(r.eui).wb = '1'))
then
euiv(r.eut)(r.eui).load := rx.starty;
euiv(r.eut)(r.eui).start := not (rx.starty or rx.startx);
if eu(r.eut)(r.eui).status /= exception then
euv(r.eut)(r.eui).status := started;
end if;
euv(r.eut)(r.eui).rs1 := cpi.me.inst(18 downto 14);
euv(r.eut)(r.eui).rs2 := cpi.me.inst(4 downto 0);
euv(r.eut)(r.eui).rd := cpi.me.inst(29 downto 25);
euv(r.eut)(r.eui).wreg := me.wreg;
euv(r.eut)(r.eui).rreg1 := me.rreg1;
euv(r.eut)(r.eui).rreg2 := me.rreg2;
euv(r.eut)(r.eui).rs1d := me.rs1d;
euv(r.eut)(r.eui).rs2d := me.rs2d;
euv(r.eut)(r.eui).rdd := me.rdd;
euv(r.eut)(r.eui).wrcc := me.wrcc;
euiv(r.eut)(r.eui).opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
rxv.holdn := '1';
end if;
rxv.starty := euiv(r.eut)(r.eui).start;
rxv.startx := (rx.startx or euiv(r.eut)(r.eui).start) and not holdn;
ccv := ccv or me.wrcc;
if cpi.flush = '1' then rxv.holdn := '1'; end if;
-- regfile bypass
if (rx.waddr = cpi.me.inst(18 downto 15)) then
if (rx.wren(0) = '1') then op1(63 downto 32) := rx.res(63 downto 32); end if;
if (rx.wren(1) = '1') then op1(31 downto 0) := rx.res(31 downto 0); end if;
end if;
if (rx.waddr = cpi.me.inst(4 downto 1)) then
if (rx.wren(0) = '1') then op2(63 downto 32) := rx.res(63 downto 32); end if;
if (rx.wren(1) = '1') then op2(31 downto 0) := rx.res(31 downto 0); end if;
end if;
-- optionally forward data from write stage
if rfi.wren(0) = '1' then
if cpi.me.inst(18 downto 15) = rfi.waddr then
op1(63 downto 32) := rfi.wdata(63 downto 32);
end if;
if cpi.me.inst(4 downto 1) = rfi.waddr then
op2(63 downto 32) := rfi.wdata(63 downto 32);
end if;
end if;
if rfi.wren(1) = '1' then
if cpi.me.inst(18 downto 15) = rfi.waddr then
op1(31 downto 0) := rfi.wdata(31 downto 0);
end if;
if cpi.me.inst(4 downto 1) = rfi.waddr then
op2(31 downto 0) := rfi.wdata(31 downto 0);
end if;
end if;
-- align single operands
if me.rs1d = '0' then
if cpi.me.inst(14) = '0' then op1 := op1(63 downto 32) & op1(63 downto 32);
else op1 := op1(31 downto 0) & op1(31 downto 0); end if;
end if;
if me.rs2d = '0' then
if cpi.me.inst(0) = '0' then op2 := op2(63 downto 32) & op2(63 downto 32);
else op2 := op2(31 downto 0) & op2(31 downto 0); end if;
end if;
-- drive EU operand inputs
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop
euiv(i)(j).op1 := op1; euiv(i)(j).op2 := op2;
end loop;
end loop;
cpo.holdn <= rx.holdn;
-------------------------------------------------------------
-- write stage
-------------------------------------------------------------
wrdata := cpi.lddata & cpi.lddata;
if cpi.flush = '0' then
case wr.cpins is
when load =>
if (wr.wreg = '1') then
if cpi.wr.cnt = "00" then
wren(0) := not cpi.wr.inst(25);
wren(1) := cpi.wr.inst(25);
else wren(1) := '1'; end if;
end if;
if (wr.acsr and holdn) = '1' then
rxv.csr.cexc := cpi.lddata(4 downto 0);
rxv.csr.aexc := cpi.lddata(9 downto 5);
rxv.csr.cc := cpi.lddata(11 downto 10);
rxv.csr.tem := cpi.lddata(27 downto 23);
rxv.csr.rd := cpi.lddata(31 downto 30);
end if;
when store =>
if wr.acsr = '1' then rxv.csr.tt := (others => '0'); end if;
if (cpi.wr.inst(20 downto 19) = "10") then -- STDFQ
if qne = '1'then
euv(euti)(euqi).status := free;
euv(euti)(euqi).rst := '1';
if euq(euti).last = euconf(euti) then euqv(euti).last := 0;
else euqv(euti).last := euqv(euti).last + 1; end if;
if (euf.last /= euf.first) then
if euf.last = (EUTOT-1) then eufv.last := 0;
else eufv.last := eufv.last + 1; end if;
end if;
else
rxv.state := nominal;
end if;
end if;
when cpop =>
-- dont assign PC and inst until here in case previous cpop trapped
euv(r.weut)(r.weui).inst := cpi.wr.inst;
euv(r.weut)(r.weui).pc := cpi.wr.pc;
when others => null;
end case;
end if;
-- flush EU if trap was taken
if ((holdn and cpi.flush) = '1') and (EUTOT > 1) then
case wr.cpins is
when cpop =>
if eu(r.weut)(r.weui).status /= exception then
euv(r.weut)(r.weui).rst := '1';
euv(r.weut)(r.weui).status := free;
end if;
eufv.first := wr.first;
euqv(r.eut).first := r.eut;
euqv(r.weut).first := r.weut;
when others => null;
end case;
end if;
waddr := cpi.wr.inst(29 downto 26);
-------------------------------------------------------------
-- retire stage
-------------------------------------------------------------
rtaddr := eu(euti)(euqi).rd(4 downto 1);
if eu(euti)(euqi).rdd = '1' then rtdata := euo(euti)(euqi).res;
else
rtdata(63 downto 32) := euo(euti)(euqi).res(63) &
euo(euti)(euqi).res(59 downto 29);
rtdata(31 downto 0) := rtdata(63 downto 32);
end if;
wren := wren and (holdn & holdn);
if ((euo(euti)(euqi).exc(4 downto 0) and rx.csr.tem) /= "00000") or
(euo(euti)(euqi).exc(5) = '1')
then
cpexc := '1';
end if;
if (wren = "00") and (eu(euti)(euqi).status = ready) and
(rx.state = nominal)
then
waddr := rtaddr; wrdata := rtdata;
if cpexc = '0' then
if (eu(euti)(euqi).wreg) = '1' then
if (eu(euti)(euqi).rdd) = '1' then wren := "11";
else
wren(0) := not eu(euti)(euqi).rd(0);
wren(1) := eu(euti)(euqi).rd(0);
end if;
end if;
if eu(euti)(euqi).wrcc = '1' then
rxv.csr.cc := euo(euti)(euqi).cc;
end if;
rxv.csr.aexc := rx.csr.aexc or euo(euti)(euqi).exc(4 downto 0);
if euv(euti)(euqi).status = ready then
euv(euti)(euqi).status := free;
end if;
euv(euti)(euqi).wb := '1';
rxv.csr.cexc := euo(euti)(euqi).exc(4 downto 0);
if euq(euti).last = euconf(euti) then euqv(euti).last := 0;
else euqv(euti).last := euqv(euti).last + 1; end if;
if euf.last = (EUTOT-1) then eufv.last := 0;
else eufv.last := eufv.last + 1; end if;
else
euv(euti)(euqi).status := exception;
rxv.state := excpend;
if (euo(euti)(euqi).exc(5) = '1') then rxv.csr.tt := "011";
else rxv.csr.tt := "001"; end if;
end if;
end if;
if cpi.exack = '1' then rxv.state := exception; end if;
if rxv.state = excpend then cpo.exc <= '1'; else cpo.exc <= '0'; end if;
cpo.ccv <= not ccv;
cpo.cc <= rx.csr.cc;
rxv.res := wrdata;
rxv.waddr := waddr;
rxv.wren := wren;
rfi.waddr <= waddr;
rfi.wren <= wren;
rfi.wdata <= wrdata;
-- reset
if rst = '0' then
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop euv(i)(j).status := free; end loop;
euqv(i).first := 0; euqv(i).last := 0;
end loop;
eufv.first := 0; eufv.last := 0; rxv.holdn := '1'; rv.start := '0';
rxv.state := nominal; rxv.csr.tt := (others => '0');
rxv.startx := '0';
ctrl.first := 0;
end if;
euin <= euv;
eui <= euiv;
eufin <= eufv;
euqin <= euqv;
exin <= ctrl;
rin <= rv;
rxin <= rxv;
end process;
-- registers
regs : process(clk)
variable pc : std_logic_vector(31 downto 0);
begin
if rising_edge(clk(0)) then
if holdn = '1' then
ex <= exin; me <= ex; wr <= me; r <= rin;
end if;
euq <= euqin; euf <= eufin;
rx <= rxin; eu <= euin;
-- pragma translate_off
if DEBUGFPU then
if euin(euf.fifo(euf.last))(euq(euf.fifo(euf.last)).last).wb = '1' then
pc := eu(euf.fifo(euf.last))(euq(euf.fifo(euf.last)).last).pc;
else pc := cpi.wr.pc; end if;
if (rfi.wren(0) = '1') then
print(tost(pc) & ": %f" & tost("000" & rfi.waddr & '0') &
" = " & tost(rfi.wdata(63 downto 32)));
end if;
if (rfi.wren(1) = '1') then
print(tost(pc) & ": %f" & tost("000" & rfi.waddr & '1') &
" = " & tost(rfi.wdata(31 downto 0)));
end if;
end if;
-- pragma translate_on
end if;
end process;
-- simple 3-port register file made up of 4 parallel dprams
dp00: dpram_synp_ss generic map (4, 32, 16)
port map (rfi.wdata(63 downto 32), rfi.raddr1, rfi.waddr, vcc, rfi.wren(0),
clk(0), vcc, rfo.rdata1(63 downto 32));
dp01: dpram_synp_ss generic map (4, 32, 16)
port map (rfi.wdata(31 downto 0), rfi.raddr1, rfi.waddr, vcc, rfi.wren(1),
clk(0), vcc, rfo.rdata1(31 downto 0));
dp10: dpram_synp_ss generic map (4, 32, 16)
port map (rfi.wdata(63 downto 32), rfi.raddr2, rfi.waddr, vcc, rfi.wren(0),
clk(0), vcc, rfo.rdata2(63 downto 32));
dp11: dpram_synp_ss generic map (4, 32, 16)
port map (rfi.wdata(31 downto 0), rfi.raddr2, rfi.waddr, vcc, rfi.wren(1),
clk(0), vcc, rfo.rdata2(31 downto 0));
gl0 : for i in 0 to euconf(0) generate
fpu0 : fpu port map (
ss_clock => clk(0),
FpInst => eui(0)(i).opcode,
FpOp => eui(0)(i).start,
FpLd => eui(0)(i).load,
Reset => eui(0)(i).flush,
fprf_dout1 => eui(0)(i).op1,
fprf_dout2 => eui(0)(i).op2,
RoundingMode => rx.csr.rd,
FpBusy => euo(0)(i).busy,
FracResult => euo(0)(i).res(51 downto 0),
ExpResult => euo(0)(i).res(62 downto 52),
SignResult => euo(0)(i).res(63),
SNnotDB => open,
Excep => euo(0)(i).exc,
ConditionCodes => euo(0)(i).cc,
ss_scan_mode => gnd,
fp_ctl_scan_in => gnd,
fp_ctl_scan_out => open);
end generate;
fpauxgen : if EUTYPES > 1 generate
gl1 : for i in 0 to euconf(1) generate
eu1 : fpaux port map (rst, clk(0), eui(1)(i), euo(1)(i));
end generate;
end generate;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -