📄 fp.vhd
字号:
variable rs : std_logic_vector(4 downto 0);
begin
lock := '0'; rs := rsin;
if (eu.wreg = '1') and (rs(4 downto 1) = eu.rd(4 downto 1)) then
if ((dbl or eu.rdd) = '1') or (rs(0) = eu.rd(0)) then lock := '1'; end if;
end if;
return(lock);
end;
function ddepcheck (rs1, rs2 : std_logic_vector;
rreg1, rreg2, rs1d, rs2d : std_logic; eu : unit_ctrl_arr_arr;
euo : euo_arr_arr) return std_logic is
variable ddep : std_logic;
variable r1, r2 : std_logic_vector(4 downto 0);
begin
ddep := '0'; r1 := rs1; r2 := rs2;
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop
if (eu(i)(j).status = started) or (eu(i)(j).status = ready) then
if rreg1 = '1' then ddep := ddep or srccheck(r1, rs1d, eu(i)(j)); end if;
if rreg2 = '1' then ddep := ddep or srccheck(r2, rs2d, eu(i)(j)); end if;
end if;
end loop;
end loop;
return(ddep);
end;
begin
vcc <= '1'; gnd <= '1';
-- instruction decoding
pipeline : process(cpi, ex, me, wr, eu, euin, r, rx, rfi, rfo, holdn, xholdn,
euo, euf, euq, rst)
variable op : std_logic_vector(1 downto 0);
variable op3 : std_logic_vector(5 downto 0);
variable opc : std_logic_vector(8 downto 0);
variable stdata : std_logic_vector(31 downto 0);
variable rs1, rs2, rd : std_logic_vector(4 downto 0);
variable ctrl : pl_ctrl;
variable ldlock : std_logic;
variable wren : std_logic_vector(1 downto 0);
variable waddr : std_logic_vector(3 downto 0);
variable rtaddr : std_logic_vector(3 downto 0);
variable wrdata : std_logic_vector(63 downto 0);
variable rtdata : std_logic_vector(63 downto 0);
variable rv : reg_type;
variable rxv : regx_type;
variable euv : unit_ctrl_arr_arr;
variable euqv : euq_arr;
variable euiv : eui_arr_arr;
variable eufv : eu_fifo_type;
variable euti : eumindex;
variable euqi : euindex;
variable ddep : std_logic;
variable cpexc : std_logic;
variable fpill : std_logic;
variable ccv : std_logic;
variable qne : std_logic;
variable op1 : std_logic_vector (63 downto 0); -- operand1
variable op2 : std_logic_vector (63 downto 0); -- operand2
variable opcode : std_logic_vector (9 downto 0); -- FP opcode
begin
-------------------------------------------------------------
-- decode stage
-------------------------------------------------------------
op := cpi.dinst(31 downto 30);
op3 := cpi.dinst(24 downto 19);
opc := cpi.dinst(13 downto 5);
rs1 := cpi.dinst(18 downto 14);
rs2 := cpi.dinst(4 downto 0);
rd := cpi.dinst(29 downto 25);
rv := r; rxv := rx; ctrl.first := ex.first;
ctrl.cpins := none; ctrl.wreg := '0'; ctrl.rdd := '0';
ctrl.wrcc := '0'; ctrl.acsr := '0'; ldlock := '0';
ctrl.rreg1 := '0'; ctrl.rreg2 := '0';
ctrl.rs1d := '0'; ctrl.rs2d := '0'; fpill := '0';
stdata := (others => '-'); wren := "00"; cpexc := '0';
ccv := '0'; rv.start := '0';
rv.weut := r.eut; rv.weui := r.eui;
rxv.start := '0'; rv.eut := 0; rv.eui := 0; rv.sdep := '0';
euv := eu; euqv := euq; eufv := euf;
euti := euf.fifo(euf.last); euqi := euq(euti).last;
if (euf.last /= euf.first) or (eu(euti)(euqi).status = exception)
then qne := '1'; else qne := '0'; end if;
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop
euiv(i)(j).opcode := cpi.ex.inst(19) & cpi.ex.inst(13 downto 5);
euiv(i)(j).start := '0'; euiv(i)(j).load := '0';
euiv(i)(j).flush := eu(i)(j).rst or euin(i)(j).rst;
euv(i)(j).wb := '0';
euv(i)(j).rst := not rst;
if (eu(i)(j).status = started) and (euo(i)(j).busy = '0') then
euv(i)(j).status := ready;
end if;
if (eu(i)(j).status > free) then
ccv := ccv or eu(i)(j).wrcc;
end if;
end loop;
end loop;
-- decode CP instructions
case op is
when FMT3 =>
case op3 is
when FPOP1 =>
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
elsif rx.state = nominal then
ctrl.cpins := cpop; ctrl.wreg := '1';
case opc is
when FMOVS | FABSS | FNEGS => ctrl.rreg2 := '1';
when FITOS | FSTOI => ctrl.rreg2 := '1';
when FITOD | FSTOD => ctrl.rreg2 := '1'; ctrl.rdd := '1';
when FDTOI | FDTOS => ctrl.rreg2 := '1'; ctrl.rs2d := '1';
when FSQRTS => ctrl.rreg2 := '1';
when FSQRTD => ctrl.rreg2 := '1'; ctrl.rs2d := '1'; ctrl.rdd := '1';
when FADDS | FSUBS | FMULS | FDIVS =>
ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
when FADDD | FSUBD | FMULD | FDIVD =>
ctrl.rreg1 := '1'; ctrl.rreg2 := '1'; ctrl.rs1d := '1';
ctrl.rs2d := '1'; ctrl.rdd := '1';
when others => fpill := '1'; -- illegal instuction
end case;
end if;
when FPOP2 =>
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
elsif rx.state = nominal then
ctrl.cpins := cpop; ctrl.wrcc := '1';
ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
case opc is
when FCMPD | FCMPED =>
ctrl.rs1d := '1'; ctrl.rs2d := '1';
when others => fpill := '1'; -- illegal instuction
end case;
end if;
when others => null;
end case;
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
(ex.wreg = '1')
then
if (ctrl.rreg1 = '1') and
(rs1(4 downto 1) = cpi.ex.inst(29 downto 26)) and
(((ctrl.rs1d or ex.rdd) = '1') or (rs1(0) = cpi.ex.inst(25)))
then ldlock := '1'; end if;
if (ctrl.rreg2 = '1') and
(rs2(4 downto 1) = cpi.ex.inst(29 downto 26)) and
(((ctrl.rs2d or ex.rdd) = '1') or (rs2(0) = cpi.ex.inst(25)))
then ldlock := '1'; end if;
end if;
when LDST =>
case op3 is
when LDF | LDDF =>
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
elsif rx.state = nominal then
ctrl.rdd := op3(1) and op3(0);
ctrl.cpins := load; ctrl.wreg := '1';
for i in 0 to EUTYPES-1 loop -- dst interlock
for j in 0 to euconf(i) loop
ldlock := ldlock or ldcheck(rd, ctrl.rdd, euin(i)(j));
end loop;
end loop;
end if;
when STF | STDF =>
-- check for CP register dependencies
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
(cpi.ex.cnt = "00") and
((rd = cpi.ex.inst(29 downto 25)) or
((rd(4 downto 1) = cpi.ex.inst(29 downto 26)) and
(ex.rdd = '1')))
then ldlock := '1'; end if;
if rx.state = nominal then
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop
ldlock := ldlock or stcheck(rd, (op3(1) and op3(0)), euin(i)(j));
end loop;
end loop;
end if;
if (ldlock = '0') then ctrl.cpins := store; end if;
when STFSR | LDFSR =>
if (rx.state = exception) and (op3 = LDFSR) then
rxv.state := excpend; rxv.csr.tt := "100";
else
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
(cpi.ex.cnt = "00") and (op3 = STFSR) and (ex.acsr = '1')
then ldlock := '1'; end if;
if (rx.state = nominal) then
for i in 0 to EUTYPES-1 loop
for j in 0 to euconf(i) loop
if eu(i)(j).status > free then ldlock := '1'; end if;
end loop;
end loop;
end if;
end if;
-- FIX ME - add check for not yet commited cpins in pipeline
if (ldlock = '0') then
ctrl.acsr := '1';
if op3 = STFSR then ctrl.cpins := store;
else ctrl.cpins := load; end if;
end if;
when STDFQ =>
if (rx.state = nominal) then
rxv.state := excpend; rxv.csr.tt := "100";
else ctrl.cpins := store; end if;
when others => null;
end case;
when others => null;
end case;
if ((cpi.flush or cpi.dtrap or cpi.dannul) = '1') then
ctrl.cpins := none;
rxv.state := rx.state; rxv.csr.tt := rx.csr.tt;
end if;
-------------------------------------------------------------
-- execute stage
-------------------------------------------------------------
-- generate regfile addresses
if holdn = '0' then
op := cpi.me.inst(31 downto 30);
rd := cpi.me.inst(29 downto 25);
op3 := cpi.me.inst(24 downto 19);
rs1 := cpi.me.inst(18 downto 14);
rs2 := cpi.me.inst(4 downto 0);
else
op := cpi.ex.inst(31 downto 30);
rd := cpi.ex.inst(29 downto 25);
op3 := cpi.ex.inst(24 downto 19);
rs1 := cpi.ex.inst(18 downto 14);
rs2 := cpi.ex.inst(4 downto 0);
end if;
if (op = LDST) and (op3(2) = '1') then rs1 := rd; end if;
rfi.raddr1 <= rs1(4 downto 1); rfi.raddr2 <= rs2(4 downto 1);
cpo.ldlock <= ldlock;
op1 := rfo.rdata1; op2 := rfo.rdata2;
-- generate store data
if (cpi.ex.inst(20 downto 19) = "10") then -- STDFQ
if (cpi.ex.cnt /= "10") then stdata := eu(euti)(euqi).pc;
else stdata := eu(euti)(euqi).inst; end if;
elsif ((cpi.ex.inst(25) = '0') and (cpi.ex.cnt /= "10")) then -- STF/STDF
stdata := op1(63 downto 32);
else stdata := op1(31 downto 0); end if;
if (ex.cpins = store) and (ex.acsr = '1') then -- STFSR
stdata := rx.csr.rd & "00" & rx.csr.tem & "000" & FPUVER &
rx.csr.tt & qne & '0' & rx.csr.cc & rx.csr.aexc & rx.csr.cexc;
end if;
cpo.data <= stdata;
-- check for source operand dependency with scheduled instructions
if (ex.cpins = cpop) then
rv.sdep := ddepcheck(cpi.ex.inst(18 downto 14), cpi.ex.inst(4 downto 0),
ex.rreg1, ex.rreg2, ex.rs1d, ex.rs2d, eu, euo);
end if;
-- select execution unit type
if (cpi.ex.inst(12 downto 9) = "0000") and (EUTYPES > 1) then
rv.eut := EUTYPES-1; -- use exection unit 1
else
rv.eut := 0; -- use exection unit 0
end if;
-- check if an execution unit is available
if (ex.cpins = cpop) and (holdn = '1') and (cpi.flush = '0') then
rv.eui := euq(rv.eut).first;
ccv := ccv or ex.wrcc;
if (rv.sdep = '0') and (eu(rv.eut)(euq(rv.eut).first).status = free)
then
rxv.start := '1';
euiv(rv.eut)(rv.eui).start := '1';
euv(rv.eut)(rv.eui).status := started;
euv(rv.eut)(rv.eui).rd := cpi.ex.inst(29 downto 25);
euv(rv.eut)(rv.eui).rs1 := cpi.ex.inst(18 downto 14);
euv(rv.eut)(rv.eui).rs2 := cpi.ex.inst(4 downto 0);
euv(rv.eut)(rv.eui).wreg := ex.wreg;
euv(rv.eut)(rv.eui).rreg1 := ex.rreg1;
euv(rv.eut)(rv.eui).rreg2 := ex.rreg2;
euv(rv.eut)(rv.eui).rs1d := ex.rs1d;
euv(rv.eut)(rv.eui).rs2d := ex.rs2d;
euv(rv.eut)(rv.eui).rdd := ex.rdd;
euv(rv.eut)(rv.eui).wrcc := ex.wrcc;
else rxv.holdn := '0'; rv.start := '1'; end if;
ctrl.first := euf.first;
eufv.fifo(euf.first) := rv.eut;
if euq(rv.eut).first = euconf(rv.eut) then euqv(rv.eut).first := 0;
else euqv(rv.eut).first := euqv(rv.eut).first + 1; end if;
if euf.first = (EUTOT-1) then eufv.first := 0;
else eufv.first := eufv.first + 1; end if;
end if;
-------------------------------------------------------------
-- memory stage
-------------------------------------------------------------
ddep := ddepcheck(cpi.me.inst(18 downto 14), cpi.me.inst(4 downto 0),
me.rreg1, me.rreg2, me.rs1d, me.rs2d, eu, euo);
euiv(r.eut)(r.eui).load := rx.start or rx.starty;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -