📄 fp1eu.vhd
字号:
----------------------------------------------------------------------------
-- This file is a part of the LEON VHDL model
-- Copyright (C) 1999 European Space Agency (ESA)
--
-- This library is free software; you can redistribute it and/or
-- modify it under the terms of the GNU Lesser General Public
-- License as published by the Free Software Foundation; either
-- version 2 of the License, or (at your option) any later version.
--
-- See the file COPYING.LGPL for the full details of the license.
-----------------------------------------------------------------------------
-- Entity: fp
-- File: fp.vhd
-- Author: Jiri Gaisler - ESA/ESTEC
-- Description: Parallel floating-point and co-processor interface
-- The interface allows one execution unit
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use work.leon_config.all;
use work.leon_iface.all;
use work.sparcv8.all;
use work.tech_map.all;
use work.fpulib.all;
-- pragma translate_off
use STD.TEXTIO.all;
use work.debug.all;
-- pragma translate_on
entity fp1eu is
port (
rst : in std_logic; -- Reset
clk : in clk_type;
holdn : in std_logic; -- pipeline hold
xholdn : in std_logic; -- pipeline hold
cpi : in cp_in_type;
cpo : out cp_out_type
);
end;
architecture rtl of fp1eu is
type cpins_type is (none, cpop, load, store);
type pl_ctrl is record -- pipeline control record
cpins : cpins_type; -- CP instruction
rreg1 : std_logic; -- using rs1
rreg2 : std_logic; -- using rs1
rs1d : std_logic; -- rs1 is double (64-bit)
rs2d : std_logic; -- rs2 is double (64-bit)
wreg : std_logic; -- write CP regfile
rdd : std_logic; -- rd is double (64-bit)
wrcc : std_logic; -- write CP condition codes
acsr : std_logic; -- access CP control register
end record;
type unit_status_type is (free, started, ready);
type unit_ctrl is record -- execution unit control record
status : unit_status_type; -- unit status
rs1 : std_logic_vector (4 downto 0); -- destination register
rs2 : std_logic_vector (4 downto 0); -- destination register
rd : std_logic_vector (4 downto 0); -- destination register
rreg1 : std_logic; -- using rs1
rreg2 : std_logic; -- using rs1
rs1d : std_logic; -- rs1 is double (64-bit)
rs2d : std_logic; -- rs2 is double (64-bit)
wreg : std_logic; -- will write CP regfile
rdd : std_logic; -- rd is double (64-bit)
wbok : std_logic; -- ok to write result
wrcc : std_logic; -- will write CP condition codes
rst : std_logic; -- reset register
pc : std_logic_vector (31 downto PCLOW); -- program counter
inst : std_logic_vector (31 downto 0); -- instruction
end record;
type csr_type is record -- CP status register
cc : std_logic_vector (1 downto 0); -- condition codes
aexc : std_logic_vector (4 downto 0); -- exception codes
cexc : std_logic_vector (4 downto 0); -- exception codes
tem : std_logic_vector (4 downto 0); -- trap enable mask
rd : std_logic_vector (1 downto 0); -- rounding mode
tt : std_logic_vector (2 downto 0); -- trap type
end record;
type execstate is (nominal, excpend, exception);
type reg_type is record -- registers clocked with pipeline
start : std_logic; -- start EU
end record;
type regx_type is record -- registers clocked continuously
res : std_logic_vector (63 downto 0); -- write stage result
waddr : std_logic_vector (3 downto 0); -- write stage dest
wren : std_logic_vector (1 downto 0); -- write stage regfile write enable
csr : csr_type; -- co-processor status register
start : std_logic; -- start EU
starty : std_logic; -- start EU
startx : std_logic; -- start EU
holdn : std_logic;
wbok : std_logic; -- ok to write result
state : execstate; -- FP/CP state
end record;
signal vcc, gnd, wb, snnotdb, fp_ctl_scan_out : std_logic;
signal rfi1, rfi2 : rf_cp_in_type;
signal rfo1, rfo2 : rf_cp_out_type;
signal ex, exin, me, mein, wr, wrin : pl_ctrl;
signal r, rin : reg_type;
signal rx, rxin : regx_type;
signal eui : cp_unit_in_type;
signal euo : cp_unit_out_type;
signal eu, euin : unit_ctrl;
function ldcheck (rdin : std_logic_vector; ldd : std_logic; eu : unit_ctrl)
return std_logic is
variable lock : std_logic;
variable rd : std_logic_vector(4 downto 0);
begin
lock := '0'; rd := rdin;
if (eu.status > free) then
if (eu.rdd = '0') then
if ((eu.wreg = '1') and (rd = eu.rd)) or
((eu.rreg1 = '1') and (rd = eu.rs1)) or
((eu.rreg2 = '1') and (rd = eu.rs2))
then lock := '1'; end if;
if (ldd = '1') then
if ((eu.wreg = '1') and ((rd(4 downto 1) & '1') = eu.rd)) or
((eu.rreg1 = '1') and ((rd(4 downto 1) & '1') = eu.rs1)) or
((eu.rreg2 = '1') and ((rd(4 downto 1) & '1') = eu.rs2))
then lock := '1'; end if;
end if;
else
if ((eu.wreg = '1') and (rd(4 downto 1) = eu.rd(4 downto 1))) or
((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
then lock := '1'; end if;
end if;
end if;
return(lock);
end;
function stcheck (rdin : std_logic_vector; std : std_logic; eu : unit_ctrl)
return std_logic is
variable lock : std_logic;
variable rd : std_logic_vector(4 downto 0);
begin
lock := '0'; rd := rdin;
if (eu.status > free) then
if (eu.rdd = '0') then
if ((eu.wreg = '1') and (rd = eu.rd)) then lock := '1'; end if;
if (std = '1') then
if ((eu.wreg = '1') and ((rd(4 downto 1) & '1') = eu.rd))
then lock := '1'; end if;
end if;
else
if ((eu.wreg = '1') and (rd(4 downto 1) = eu.rd(4 downto 1))) or
((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
then lock := '1'; end if;
end if;
end if;
return(lock);
end;
function srccheck (rsin : std_logic_vector; dbl : std_logic; eu : unit_ctrl)
return std_logic is
variable lock : std_logic;
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;
begin
vcc <= '1'; gnd <= '1';
-- instruction decoding
pipeline : process(cpi, ex, me, wr, eu, euin, r, rx, rfi1, rfi2, rfo1, rfo2,
holdn, xholdn,
euo, rst, wb)
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;
variable euiv : cp_unit_in_type;
variable ddep : std_logic;
variable cpexc : std_logic;
variable fpill : std_logic;
variable ccv : std_logic;
variable qne : std_logic;
variable wbv : 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.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'; rxv.wbok := '0';
rxv.start := '0';
euv := eu;
if eu.status /= free then qne := '1'; else qne := '0'; end if;
euiv.opcode := cpi.ex.inst(19) & cpi.ex.inst(13 downto 5);
euiv.start := '0'; euiv.load := '0';
euiv.flush := eu.rst or euin.rst;
wbv := '0';
euv.rst := not rst;
if (eu.status = started) and (euo.busy = '0') then
euv.status := ready;
end if;
if (eu.status > free) then ccv := ccv or eu.wrcc; end if;
-- 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';
-- dst interlock
ldlock := ldlock or ldcheck(rd, ctrl.rdd, euin);
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
ldlock := ldlock or stcheck(rd, (op3(1) and op3(0)), euin);
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
if (((cpi.ex.annul or cpi.ex.trap) = '0') and (ex.cpins = cpop))
or (eu.status > free)
then ldlock := '1'; end if;
end if;
end if;
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 or ldlock) = '1') then
ctrl.cpins := none; ctrl.acsr := '0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -