📄 fp1eu.vhd
字号:
when others => null; end case; when others => null; end case; if ((cpi.flush or cpi.dtrap or cpi.dannul or ldlock) = '1') then ctrl.cpins := none; ctrl.acsr := '0'; rxv.state := rx.state; rxv.csr.tt := rx.csr.tt; end if; if ((cpi.flush or cpi.dtrap or cpi.dannul) = '1') then ldlock := '0'; 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.pc(31 downto 2) & "00"; else stdata := eu.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" & std_logic_vector(FPUVER) & rx.csr.tt & qne & '0' & rx.csr.cc & rx.csr.aexc & rx.csr.cexc; end if; cpo.data <= stdata; -- check if an execution unit is available if (ex.cpins = cpop) and (holdn = '1') and (cpi.ex.annul = '0') then ccv := ccv or ex.wrcc; if (eu.status = free) or ((eu.status = ready) and (wb = '1')) then rxv.start := '1'; euiv.start := '1'; if cpi.flush = '0' then euv.status := started; end if; euv.rd := cpi.ex.inst(29 downto 25); euv.rs1 := cpi.ex.inst(18 downto 14); euv.rs2 := cpi.ex.inst(4 downto 0); euv.wreg := ex.wreg; euv.rreg1 := ex.rreg1; euv.rreg2 := ex.rreg2; euv.rs1d := ex.rs1d; euv.rs2d := ex.rs2d; euv.rdd := ex.rdd; euv.wrcc := ex.wrcc; else rxv.holdn := '0'; rv.start := '1'; end if; end if; if cpi.flush = '1' then rxv.start := '0'; euiv.start := '0'; end if;--------------------------------------------------------------- memory stage------------------------------------------------------------- euiv.load := rx.start or rx.starty; if (rx.holdn = '0') and (xholdn = '1') and (cpi.flush = '0') and (euo.busy = '0') then euiv.start := not rx.startx; euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5); end if; if (rx.holdn = '0') and ((eu.status <= free) or (wb = '1')) then euiv.load := rx.starty; euiv.start := not (rx.starty or rx.startx); euv.status := started; euv.rs1 := cpi.me.inst(18 downto 14); euv.rs2 := cpi.me.inst(4 downto 0); euv.rd := cpi.me.inst(29 downto 25); euv.wreg := me.wreg; euv.rreg1 := me.rreg1; euv.rreg2 := me.rreg2; euv.rs1d := me.rs1d; euv.rs2d := me.rs2d; euv.rdd := me.rdd; euv.wrcc := me.wrcc; euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5); rxv.holdn := '1'; end if; euiv.start := euiv.start and not cpi.flush; rxv.starty := euiv.start; rxv.startx := (rx.startx or euiv.start) and (not holdn) and not cpi.flush; ccv := ccv or me.wrcc; if (cpi.flush = '1') or (rx.state /= nominal) then rxv.holdn := '1'; end if; if holdn = '0' then rxv.wbok := rx.wbok; end if; if (me.cpins = cpop) and (holdn = '1') then if ((cpi.flush and not eu.wbok) = '1') then euv.rst := '1'; else rxv.wbok := not cpi.me.annul; end if; 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 euiv.op1 := op1; euiv.op2 := op2; cpo.holdn <= rx.holdn;--------------------------------------------------------------- write stage------------------------------------------------------------- wrdata := cpi.lddata & cpi.lddata; if (cpi.wr.annul or 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.status := free; euv.rst := '1'; euv.wbok := '0'; else rxv.state := nominal; end if; end if; when cpop => -- dont assign PC and inst until here in case previous cpop trapped if holdn = '1' then euv.wbok := rx.wbok; end if; euv.inst := cpi.wr.inst; euv.pc := cpi.wr.pc; when others => null; end case; end if; if (wr.cpins = cpop) and (holdn = '1') and (eu.wbok = '0') and ((cpi.flush or cpi.wr.annul) = '1') then if rx.state = nominal then euv.status := free; end if; euv.rst := '1'; euv.wbok := '0'; end if; waddr := cpi.wr.inst(29 downto 26);--------------------------------------------------------------- retire stage------------------------------------------------------------- rtaddr := eu.rd(4 downto 1); if eu.rdd = '1' then rtdata := euo.res; else rtdata(63 downto 32) := euo.res(63) & euo.res(59 downto 29); rtdata(31 downto 0) := rtdata(63 downto 32); end if; wren := wren and (holdn & holdn); if ((euo.exc(4 downto 0) and rx.csr.tem) /= "00000") or (euo.exc(5) = '1') then cpexc := '1'; end if; if (wren = "00") and (eu.status = ready) and (rx.state = nominal) and ((eu.wbok = '1') or ((cpi.flush = '0') and (rx.wbok = '1'))) then waddr := rtaddr; wrdata := rtdata; euv.wbok := '0'; if (holdn = '0') then rxv.wbok := '0'; end if; if cpexc = '0' then if (eu.wreg) = '1' then if (eu.rdd) = '1' then wren := "11"; else wren(0) := not eu.rd(0); wren(1) := eu.rd(0); end if; end if; if eu.wrcc = '1' then rxv.csr.cc := euo.cc; end if; rxv.csr.aexc := rx.csr.aexc or euo.exc(4 downto 0); if euv.status = ready then euv.status := free; end if; wbv := '1'; rxv.csr.cexc := euo.exc(4 downto 0); else rxv.state := excpend; if (euo.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 rxv.holdn := '1'; rv.start := '0'; rxv.state := nominal; rxv.csr.tt := (others => '0'); rxv.startx := '0'; euv.status := free; euv.wbok := '0'; end if; euin <= euv; eui <= euiv; exin <= ctrl; rin <= rv; rxin <= rxv; wb <= wbv; end process;-- registers regs : process(clk) variable pc : std_logic_vector(31 downto 0); begin if rising_edge(clk) then if holdn = '1' then ex <= exin; me <= ex; wr <= me; r <= rin; end if; rx <= rxin; eu <= euin;-- pragma translate_off if DEBUGFPU then if wb = '1' then pc := eu.pc; else pc := cpi.wr.pc; end if; if (rfi.wren(0) = '1') then print(tostf(pc) & ": %f" & tost(rfi.waddr & '0') & " = " & tost(rfi.wdata(63 downto 32))); end if; if (rfi.wren(1) = '1') then print(tostf(pc) & ": %f" & tost(rfi.waddr & '1') & " = " & tost(rfi.wdata(31 downto 0))); end if; end if;-- pragma translate_on end if; end process;-- regfile rf0: regfile_ss generic map (4, 32, 16) port map (clk, rfi.wdata(63 downto 32), rfi.raddr1, rfi.raddr2, rfi.waddr, vcc, rfi.wren(0), rfo.rdata1(63 downto 32), rfo.rdata2(63 downto 32)); rf1: regfile_ss generic map (4, 32, 16) port map (clk, rfi.wdata(31 downto 0), rfi.raddr1, rfi.raddr2, rfi.waddr, vcc, rfi.wren(1), rfo.rdata1(31 downto 0), rfo.rdata2(31 downto 0)); fpu0 : fpu port map ( ss_clock => clk, FpInst => eui.opcode, FpOp => eui.start, FpLd => eui.load, Reset => eui.flush, fprf_dout1 => eui.op1, fprf_dout2 => eui.op2, RoundingMode => rx.csr.rd, FpBusy => euo.busy, FracResult => euo.res(51 downto 0), ExpResult => euo.res(62 downto 52), SignResult => euo.res(63), SNnotDB => open, Excep => euo.exc, ConditionCodes => euo.cc, ss_scan_mode => gnd, fp_ctl_scan_in => gnd, fp_ctl_scan_out => open);end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -