1 |
2 |
tarookumic |
|
2 |
|
|
----------------------------------------------------------------------------
|
3 |
|
|
-- This file is a part of the LEON VHDL model
|
4 |
|
|
-- Copyright (C) 1999 European Space Agency (ESA)
|
5 |
|
|
--
|
6 |
|
|
-- This library is free software; you can redistribute it and/or
|
7 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
8 |
|
|
-- License as published by the Free Software Foundation; either
|
9 |
|
|
-- version 2 of the License, or (at your option) any later version.
|
10 |
|
|
--
|
11 |
|
|
-- See the file COPYING.LGPL for the full details of the license.
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
-----------------------------------------------------------------------------
|
15 |
|
|
-- Entity: fp
|
16 |
|
|
-- File: fp.vhd
|
17 |
|
|
-- Author: Jiri Gaisler - ESA/ESTEC
|
18 |
|
|
-- Description: Parallel floating-point co-processor interface
|
19 |
|
|
-- The interface allows any number of parallel execution unit
|
20 |
|
|
-- As an example, two Meiko FPUs and two FMOVE units have been attached
|
21 |
|
|
------------------------------------------------------------------------------
|
22 |
|
|
|
23 |
|
|
-- FPU support unit - performs FMOVS, FNEGS, FABSS
|
24 |
|
|
|
25 |
|
|
library IEEE;
|
26 |
|
|
use IEEE.std_logic_1164.all;
|
27 |
|
|
use IEEE.std_logic_unsigned."+";
|
28 |
|
|
use IEEE.std_logic_unsigned."-";
|
29 |
|
|
use IEEE.std_logic_unsigned.conv_integer;
|
30 |
|
|
use work.leon_iface.all;
|
31 |
|
|
|
32 |
|
|
entity fpaux is
|
33 |
|
|
port (
|
34 |
|
|
rst : in std_logic; -- Reset
|
35 |
|
|
clk : in std_logic; -- clock
|
36 |
|
|
eui : in cp_unit_in_type; -- inputs
|
37 |
|
|
euo : out cp_unit_out_type -- outputs
|
38 |
|
|
);
|
39 |
|
|
end;
|
40 |
|
|
|
41 |
|
|
architecture rtl of fpaux is
|
42 |
|
|
type reg_type is record
|
43 |
|
|
op : std_logic_vector (31 downto 0); -- operand
|
44 |
|
|
ins : std_logic_vector (1 downto 0); -- operand
|
45 |
|
|
end record;
|
46 |
|
|
|
47 |
|
|
signal r, rin : reg_type;
|
48 |
|
|
|
49 |
|
|
begin
|
50 |
|
|
|
51 |
|
|
comb: process(rst, eui, r)
|
52 |
|
|
variable rv : reg_type;
|
53 |
|
|
variable ready : std_logic;
|
54 |
|
|
variable sign : std_logic;
|
55 |
|
|
begin
|
56 |
|
|
|
57 |
|
|
rv := r;
|
58 |
|
|
|
59 |
|
|
if eui.start = '1' then rv.ins := eui.opcode(3 downto 2); end if;
|
60 |
|
|
if eui.load = '1' then rv.op := eui.op2(63 downto 32); end if;
|
61 |
|
|
case r.ins is
|
62 |
|
|
when "00" => sign := r.op(31); -- fmovs
|
63 |
|
|
when "01" => sign := not r.op(31); -- fnegs
|
64 |
|
|
when others => sign := '0'; -- fabss
|
65 |
|
|
end case;
|
66 |
|
|
euo.res(63 downto 29) <= sign & "000" & r.op(30 downto 0);
|
67 |
|
|
euo.res(28 downto 0) <= (others => '0');
|
68 |
|
|
euo.busy <= '0';
|
69 |
|
|
euo.exc <= (others => '0');
|
70 |
|
|
euo.cc <= (others => '0');
|
71 |
|
|
rin <= rv;
|
72 |
|
|
end process;
|
73 |
|
|
|
74 |
|
|
-- registers
|
75 |
|
|
|
76 |
|
|
regs : process(clk)
|
77 |
|
|
begin
|
78 |
|
|
if rising_edge(clk) then
|
79 |
|
|
r <= rin;
|
80 |
|
|
end if;
|
81 |
|
|
end process;
|
82 |
|
|
end;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
|
|
library IEEE;
|
87 |
|
|
use IEEE.std_logic_1164.all;
|
88 |
|
|
use IEEE.std_logic_unsigned."+";
|
89 |
|
|
use IEEE.std_logic_unsigned."-";
|
90 |
|
|
use IEEE.std_logic_unsigned.conv_integer;
|
91 |
|
|
use work.leon_config.all;
|
92 |
|
|
use work.leon_iface.all;
|
93 |
|
|
use work.sparcv8.all;
|
94 |
|
|
use work.ramlib.all;
|
95 |
|
|
use work.fpulib.all;
|
96 |
|
|
-- pragma translate_off
|
97 |
|
|
library MMS;
|
98 |
|
|
use MMS.stdioimp.all;
|
99 |
|
|
use STD.TEXTIO.all;
|
100 |
|
|
use work.debug.all;
|
101 |
|
|
-- pragma translate_on
|
102 |
|
|
|
103 |
|
|
entity fp is
|
104 |
|
|
port (
|
105 |
|
|
rst : in std_logic; -- Reset
|
106 |
|
|
clk : in clk_type; -- main clock
|
107 |
|
|
iuclk : in clk_type; -- gated IU clock
|
108 |
|
|
holdn : in std_logic; -- pipeline hold
|
109 |
|
|
xholdn : in std_logic; -- pipeline hold
|
110 |
|
|
cpi : in cp_in_type;
|
111 |
|
|
cpo : out cp_out_type
|
112 |
|
|
);
|
113 |
|
|
end;
|
114 |
|
|
|
115 |
|
|
architecture rtl of fp is
|
116 |
|
|
|
117 |
|
|
constant EUTYPES : integer := 1; -- number of execution unit types
|
118 |
|
|
--constant EUTYPES : integer := 1; -- number of execution unit types
|
119 |
|
|
constant EU1NUM : integer := 2; -- number of execution unit 1 types
|
120 |
|
|
constant EU2NUM : integer := 1; -- number of execution unit 2 types
|
121 |
|
|
constant EUMAX : integer := 2; -- maximum number of any execution unit
|
122 |
|
|
--constant EUTOT : integer := 2; -- total number of execution units
|
123 |
|
|
constant EUTOT : integer := 2; -- total number of execution units
|
124 |
|
|
subtype euindex is integer range 0 to EUMAX-1;
|
125 |
|
|
subtype eumindex is integer range 0 to EUTOT-1;
|
126 |
|
|
subtype eutindex is integer range 0 to EUTYPES-1;
|
127 |
|
|
-- array to define how many execution units of each type
|
128 |
|
|
type euconf_arr is array (0 to 2) of euindex; -- one more than necessay to avoid modeltech bug
|
129 |
|
|
constant euconf : euconf_arr := (EU1NUM-1, EU2NUM-1,0);
|
130 |
|
|
--constant euconf : euconf_arr := (EU1NUM,1);
|
131 |
|
|
type eu_fifo_arr is array (0 to EUTOT-1) of eutindex;
|
132 |
|
|
|
133 |
|
|
type eu_fifo_type is record
|
134 |
|
|
first : eumindex;
|
135 |
|
|
last : eumindex;
|
136 |
|
|
fifo : eu_fifo_arr;
|
137 |
|
|
end record;
|
138 |
|
|
|
139 |
|
|
type euq_type is record
|
140 |
|
|
first : euindex;
|
141 |
|
|
last : euindex;
|
142 |
|
|
end record;
|
143 |
|
|
|
144 |
|
|
type euq_arr is array (0 to EUTYPES-1) of euq_type;
|
145 |
|
|
|
146 |
|
|
type rfi_type is record
|
147 |
|
|
raddr1 : std_logic_vector (3 downto 0);
|
148 |
|
|
raddr2 : std_logic_vector (3 downto 0);
|
149 |
|
|
waddr : std_logic_vector (3 downto 0);
|
150 |
|
|
wdata : std_logic_vector (63 downto 0);
|
151 |
|
|
wren : std_logic_vector(1 downto 0);
|
152 |
|
|
end record;
|
153 |
|
|
|
154 |
|
|
type rfo_type is record
|
155 |
|
|
rdata1 : std_logic_vector (63 downto 0);
|
156 |
|
|
rdata2 : std_logic_vector (63 downto 0);
|
157 |
|
|
end record;
|
158 |
|
|
|
159 |
|
|
type cpins_type is (none, cpop, load, store);
|
160 |
|
|
type pl_ctrl is record -- pipeline control record
|
161 |
|
|
cpins : cpins_type; -- CP instruction
|
162 |
|
|
rreg1 : std_logic; -- using rs1
|
163 |
|
|
rreg2 : std_logic; -- using rs1
|
164 |
|
|
rs1d : std_logic; -- rs1 is double (64-bit)
|
165 |
|
|
rs2d : std_logic; -- rs2 is double (64-bit)
|
166 |
|
|
wreg : std_logic; -- write CP regfile
|
167 |
|
|
rdd : std_logic; -- rd is double (64-bit)
|
168 |
|
|
wrcc : std_logic; -- write CP condition codes
|
169 |
|
|
acsr : std_logic; -- access CP control register
|
170 |
|
|
first : euindex;
|
171 |
|
|
end record;
|
172 |
|
|
|
173 |
|
|
type unit_status_type is (exception, free, started, ready);
|
174 |
|
|
type unit_ctrl is record -- execution unit control record
|
175 |
|
|
status : unit_status_type; -- unit status
|
176 |
|
|
rs1 : std_logic_vector (4 downto 0); -- destination register
|
177 |
|
|
rs2 : std_logic_vector (4 downto 0); -- destination register
|
178 |
|
|
rd : std_logic_vector (4 downto 0); -- destination register
|
179 |
|
|
rreg1 : std_logic; -- using rs1
|
180 |
|
|
rreg2 : std_logic; -- using rs1
|
181 |
|
|
rs1d : std_logic; -- rs1 is double (64-bit)
|
182 |
|
|
rs2d : std_logic; -- rs2 is double (64-bit)
|
183 |
|
|
wreg : std_logic; -- will write CP regfile
|
184 |
|
|
rdd : std_logic; -- rd is double (64-bit)
|
185 |
|
|
wb : std_logic; -- result being written back
|
186 |
|
|
wrcc : std_logic; -- will write CP condition codes
|
187 |
|
|
rst : std_logic; -- reset register
|
188 |
|
|
pc : std_logic_vector (31 downto PCLOW); -- program counter
|
189 |
|
|
inst : std_logic_vector (31 downto 0); -- instruction
|
190 |
|
|
end record;
|
191 |
|
|
|
192 |
|
|
type csr_type is record -- CP status register
|
193 |
|
|
cc : std_logic_vector (1 downto 0); -- condition codes
|
194 |
|
|
aexc : std_logic_vector (4 downto 0); -- exception codes
|
195 |
|
|
cexc : std_logic_vector (4 downto 0); -- exception codes
|
196 |
|
|
tem : std_logic_vector (4 downto 0); -- trap enable mask
|
197 |
|
|
rd : std_logic_vector (1 downto 0); -- rounding mode
|
198 |
|
|
tt : std_logic_vector (2 downto 0); -- trap type
|
199 |
|
|
end record;
|
200 |
|
|
|
201 |
|
|
type execstate is (nominal, excpend, exception);
|
202 |
|
|
type reg_type is record -- registers clocked with pipeline
|
203 |
|
|
eufirst : euindex;
|
204 |
|
|
eulast : euindex;
|
205 |
|
|
sdep : std_logic; -- data dependency ex/me/wr
|
206 |
|
|
eut : integer range 0 to EUTYPES-1; -- type EU to start
|
207 |
|
|
eui : integer range 0 to EUMAX-1; -- index EU to start
|
208 |
|
|
start : std_logic; -- start EU
|
209 |
|
|
weut : integer range 0 to EUTYPES-1; -- write stage eut
|
210 |
|
|
weui : integer range 0 to EUMAX-1; -- write stage eui
|
211 |
|
|
end record;
|
212 |
|
|
|
213 |
|
|
type regx_type is record -- registers clocked continuously
|
214 |
|
|
res : std_logic_vector (63 downto 0); -- write stage result
|
215 |
|
|
waddr : std_logic_vector (3 downto 0); -- write stage dest
|
216 |
|
|
wren : std_logic_vector (1 downto 0); -- write stage regfile write enable
|
217 |
|
|
csr : csr_type; -- co-processor status register
|
218 |
|
|
start : std_logic; -- start EU
|
219 |
|
|
starty : std_logic; -- start EU
|
220 |
|
|
startx : std_logic; -- start EU
|
221 |
|
|
holdn : std_logic;
|
222 |
|
|
state : execstate; -- using rs1
|
223 |
|
|
end record;
|
224 |
|
|
|
225 |
|
|
type unit_ctrl_arr is array (0 to EUMAX-1) of unit_ctrl;
|
226 |
|
|
type unit_ctrl_arr_arr is array (0 to EUTYPES-1) of unit_ctrl_arr;
|
227 |
|
|
type eui_arr is array (0 to EUMAX-1) of cp_unit_in_type;
|
228 |
|
|
type euo_arr is array (0 to EUMAX-1) of cp_unit_out_type;
|
229 |
|
|
type eui_arr_arr is array (0 to EUTYPES) of eui_arr;
|
230 |
|
|
type euo_arr_arr is array (0 to EUTYPES) of euo_arr;
|
231 |
|
|
signal vcc, gnd : std_logic;
|
232 |
|
|
signal rfi : rfi_type;
|
233 |
|
|
signal rfo : rfo_type;
|
234 |
|
|
signal ex, exin, me, mein, wr, wrin : pl_ctrl;
|
235 |
|
|
signal r, rin : reg_type;
|
236 |
|
|
signal rx, rxin : regx_type;
|
237 |
|
|
signal eui : eui_arr_arr;
|
238 |
|
|
signal euo : euo_arr_arr;
|
239 |
|
|
signal eu, euin : unit_ctrl_arr_arr;
|
240 |
|
|
signal euq, euqin : euq_arr;
|
241 |
|
|
signal euf, eufin : eu_fifo_type;
|
242 |
|
|
|
243 |
|
|
component fpaux
|
244 |
|
|
port (
|
245 |
|
|
rst : in std_logic; -- Reset
|
246 |
|
|
clk : in std_logic; -- clock
|
247 |
|
|
eui : in cp_unit_in_type; -- inputs
|
248 |
|
|
euo : out cp_unit_out_type -- outputs
|
249 |
|
|
);
|
250 |
|
|
end component;
|
251 |
|
|
|
252 |
|
|
function ldcheck (rdin : std_logic_vector; ldd : std_logic; eu : unit_ctrl)
|
253 |
|
|
return std_logic is
|
254 |
|
|
variable lock : std_logic;
|
255 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
256 |
|
|
begin
|
257 |
|
|
lock := '0'; rd := rdin;
|
258 |
|
|
if (eu.status > free) then
|
259 |
|
|
if (eu.rdd = '0') then
|
260 |
|
|
if ((eu.wreg = '1') and (rd = eu.rd)) or
|
261 |
|
|
((eu.rreg1 = '1') and (rd = eu.rs1)) or
|
262 |
|
|
((eu.rreg2 = '1') and (rd = eu.rs2))
|
263 |
|
|
then lock := '1'; end if;
|
264 |
|
|
if (ldd = '1') then
|
265 |
|
|
if ((eu.wreg = '1') and ((rd(4 downto 1) & '1') = eu.rd)) or
|
266 |
|
|
((eu.rreg1 = '1') and ((rd(4 downto 1) & '1') = eu.rs1)) or
|
267 |
|
|
((eu.rreg2 = '1') and ((rd(4 downto 1) & '1') = eu.rs2))
|
268 |
|
|
then lock := '1'; end if;
|
269 |
|
|
end if;
|
270 |
|
|
else
|
271 |
|
|
if ((eu.wreg = '1') and (rd(4 downto 1) = eu.rd(4 downto 1))) or
|
272 |
|
|
((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
|
273 |
|
|
((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
|
274 |
|
|
then lock := '1'; end if;
|
275 |
|
|
end if;
|
276 |
|
|
end if;
|
277 |
|
|
return(lock);
|
278 |
|
|
end;
|
279 |
|
|
function stcheck (rdin : std_logic_vector; std : std_logic; eu : unit_ctrl)
|
280 |
|
|
return std_logic is
|
281 |
|
|
variable lock : std_logic;
|
282 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
283 |
|
|
begin
|
284 |
|
|
lock := '0'; rd := rdin;
|
285 |
|
|
if (eu.status > free) then
|
286 |
|
|
if (eu.rdd = '0') then
|
287 |
|
|
if ((eu.wreg = '1') and (rd = eu.rd)) then lock := '1'; end if;
|
288 |
|
|
if (std = '1') then
|
289 |
|
|
if ((eu.wreg = '1') and ((rd(4 downto 1) & '1') = eu.rd))
|
290 |
|
|
then lock := '1'; end if;
|
291 |
|
|
end if;
|
292 |
|
|
else
|
293 |
|
|
if ((eu.wreg = '1') and (rd(4 downto 1) = eu.rd(4 downto 1))) or
|
294 |
|
|
((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
|
295 |
|
|
((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
|
296 |
|
|
then lock := '1'; end if;
|
297 |
|
|
end if;
|
298 |
|
|
end if;
|
299 |
|
|
return(lock);
|
300 |
|
|
end;
|
301 |
|
|
|
302 |
|
|
function srccheck (rsin : std_logic_vector; dbl : std_logic; eu : unit_ctrl)
|
303 |
|
|
return std_logic is
|
304 |
|
|
variable lock : std_logic;
|
305 |
|
|
variable rs : std_logic_vector(4 downto 0);
|
306 |
|
|
begin
|
307 |
|
|
lock := '0'; rs := rsin;
|
308 |
|
|
if (eu.wreg = '1') and (rs(4 downto 1) = eu.rd(4 downto 1)) then
|
309 |
|
|
if ((dbl or eu.rdd) = '1') or (rs(0) = eu.rd(0)) then lock := '1'; end if;
|
310 |
|
|
end if;
|
311 |
|
|
return(lock);
|
312 |
|
|
end;
|
313 |
|
|
|
314 |
|
|
function ddepcheck (rs1, rs2 : std_logic_vector;
|
315 |
|
|
rreg1, rreg2, rs1d, rs2d : std_logic; eu : unit_ctrl_arr_arr;
|
316 |
|
|
euo : euo_arr_arr) return std_logic is
|
317 |
|
|
variable ddep : std_logic;
|
318 |
|
|
variable r1, r2 : std_logic_vector(4 downto 0);
|
319 |
|
|
begin
|
320 |
|
|
ddep := '0'; r1 := rs1; r2 := rs2;
|
321 |
|
|
for i in 0 to EUTYPES-1 loop
|
322 |
|
|
for j in 0 to euconf(i) loop
|
323 |
|
|
if (eu(i)(j).status = started) or (eu(i)(j).status = ready) then
|
324 |
|
|
if rreg1 = '1' then ddep := ddep or srccheck(r1, rs1d, eu(i)(j)); end if;
|
325 |
|
|
if rreg2 = '1' then ddep := ddep or srccheck(r2, rs2d, eu(i)(j)); end if;
|
326 |
|
|
end if;
|
327 |
|
|
end loop;
|
328 |
|
|
end loop;
|
329 |
|
|
return(ddep);
|
330 |
|
|
end;
|
331 |
|
|
|
332 |
|
|
begin
|
333 |
|
|
|
334 |
|
|
vcc <= '1'; gnd <= '1';
|
335 |
|
|
|
336 |
|
|
-- instruction decoding
|
337 |
|
|
|
338 |
|
|
pipeline : process(cpi, ex, me, wr, eu, euin, r, rx, rfi, rfo, holdn, xholdn,
|
339 |
|
|
euo, euf, euq, rst)
|
340 |
|
|
variable op : std_logic_vector(1 downto 0);
|
341 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
342 |
|
|
variable opc : std_logic_vector(8 downto 0);
|
343 |
|
|
variable stdata : std_logic_vector(31 downto 0);
|
344 |
|
|
variable rs1, rs2, rd : std_logic_vector(4 downto 0);
|
345 |
|
|
variable ctrl : pl_ctrl;
|
346 |
|
|
variable ldlock : std_logic;
|
347 |
|
|
variable wren : std_logic_vector(1 downto 0);
|
348 |
|
|
variable waddr : std_logic_vector(3 downto 0);
|
349 |
|
|
variable rtaddr : std_logic_vector(3 downto 0);
|
350 |
|
|
variable wrdata : std_logic_vector(63 downto 0);
|
351 |
|
|
variable rtdata : std_logic_vector(63 downto 0);
|
352 |
|
|
variable rv : reg_type;
|
353 |
|
|
variable rxv : regx_type;
|
354 |
|
|
variable euv : unit_ctrl_arr_arr;
|
355 |
|
|
variable euqv : euq_arr;
|
356 |
|
|
variable euiv : eui_arr_arr;
|
357 |
|
|
variable eufv : eu_fifo_type;
|
358 |
|
|
variable euti : eumindex;
|
359 |
|
|
variable euqi : euindex;
|
360 |
|
|
variable ddep : std_logic;
|
361 |
|
|
variable cpexc : std_logic;
|
362 |
|
|
variable fpill : std_logic;
|
363 |
|
|
variable ccv : std_logic;
|
364 |
|
|
variable qne : std_logic;
|
365 |
|
|
variable op1 : std_logic_vector (63 downto 0); -- operand1
|
366 |
|
|
variable op2 : std_logic_vector (63 downto 0); -- operand2
|
367 |
|
|
variable opcode : std_logic_vector (9 downto 0); -- FP opcode
|
368 |
|
|
begin
|
369 |
|
|
|
370 |
|
|
-------------------------------------------------------------
|
371 |
|
|
-- decode stage
|
372 |
|
|
-------------------------------------------------------------
|
373 |
|
|
op := cpi.dinst(31 downto 30);
|
374 |
|
|
op3 := cpi.dinst(24 downto 19);
|
375 |
|
|
opc := cpi.dinst(13 downto 5);
|
376 |
|
|
rs1 := cpi.dinst(18 downto 14);
|
377 |
|
|
rs2 := cpi.dinst(4 downto 0);
|
378 |
|
|
rd := cpi.dinst(29 downto 25);
|
379 |
|
|
|
380 |
|
|
rv := r; rxv := rx; ctrl.first := ex.first;
|
381 |
|
|
ctrl.cpins := none; ctrl.wreg := '0'; ctrl.rdd := '0';
|
382 |
|
|
ctrl.wrcc := '0'; ctrl.acsr := '0'; ldlock := '0';
|
383 |
|
|
ctrl.rreg1 := '0'; ctrl.rreg2 := '0';
|
384 |
|
|
ctrl.rs1d := '0'; ctrl.rs2d := '0'; fpill := '0';
|
385 |
|
|
stdata := (others => '-'); wren := "00"; cpexc := '0';
|
386 |
|
|
ccv := '0'; rv.start := '0';
|
387 |
|
|
rv.weut := r.eut; rv.weui := r.eui;
|
388 |
|
|
rxv.start := '0'; rv.eut := 0; rv.eui := 0; rv.sdep := '0';
|
389 |
|
|
euv := eu; euqv := euq; eufv := euf;
|
390 |
|
|
euti := euf.fifo(euf.last); euqi := euq(euti).last;
|
391 |
|
|
if (euf.last /= euf.first) or (eu(euti)(euqi).status = exception)
|
392 |
|
|
then qne := '1'; else qne := '0'; end if;
|
393 |
|
|
|
394 |
|
|
for i in 0 to EUTYPES-1 loop
|
395 |
|
|
for j in 0 to euconf(i) loop
|
396 |
|
|
euiv(i)(j).opcode := cpi.ex.inst(19) & cpi.ex.inst(13 downto 5);
|
397 |
|
|
euiv(i)(j).start := '0'; euiv(i)(j).load := '0';
|
398 |
|
|
euiv(i)(j).flush := eu(i)(j).rst or euin(i)(j).rst;
|
399 |
|
|
euv(i)(j).wb := '0';
|
400 |
|
|
euv(i)(j).rst := not rst;
|
401 |
|
|
if (eu(i)(j).status = started) and (euo(i)(j).busy = '0') then
|
402 |
|
|
euv(i)(j).status := ready;
|
403 |
|
|
end if;
|
404 |
|
|
if (eu(i)(j).status > free) then
|
405 |
|
|
ccv := ccv or eu(i)(j).wrcc;
|
406 |
|
|
end if;
|
407 |
|
|
end loop;
|
408 |
|
|
end loop;
|
409 |
|
|
|
410 |
|
|
-- decode CP instructions
|
411 |
|
|
case op is
|
412 |
|
|
when FMT3 =>
|
413 |
|
|
case op3 is
|
414 |
|
|
when FPOP1 =>
|
415 |
|
|
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
|
416 |
|
|
elsif rx.state = nominal then
|
417 |
|
|
ctrl.cpins := cpop; ctrl.wreg := '1';
|
418 |
|
|
case opc is
|
419 |
|
|
when FMOVS | FABSS | FNEGS => ctrl.rreg2 := '1';
|
420 |
|
|
when FITOS | FSTOI => ctrl.rreg2 := '1';
|
421 |
|
|
when FITOD | FSTOD => ctrl.rreg2 := '1'; ctrl.rdd := '1';
|
422 |
|
|
when FDTOI | FDTOS => ctrl.rreg2 := '1'; ctrl.rs2d := '1';
|
423 |
|
|
when FSQRTS => ctrl.rreg2 := '1';
|
424 |
|
|
when FSQRTD => ctrl.rreg2 := '1'; ctrl.rs2d := '1'; ctrl.rdd := '1';
|
425 |
|
|
when FADDS | FSUBS | FMULS | FDIVS =>
|
426 |
|
|
ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
|
427 |
|
|
when FADDD | FSUBD | FMULD | FDIVD =>
|
428 |
|
|
ctrl.rreg1 := '1'; ctrl.rreg2 := '1'; ctrl.rs1d := '1';
|
429 |
|
|
ctrl.rs2d := '1'; ctrl.rdd := '1';
|
430 |
|
|
when others => fpill := '1'; -- illegal instuction
|
431 |
|
|
end case;
|
432 |
|
|
end if;
|
433 |
|
|
when FPOP2 =>
|
434 |
|
|
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
|
435 |
|
|
elsif rx.state = nominal then
|
436 |
|
|
ctrl.cpins := cpop; ctrl.wrcc := '1';
|
437 |
|
|
ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
|
438 |
|
|
case opc is
|
439 |
|
|
when FCMPD | FCMPED =>
|
440 |
|
|
ctrl.rs1d := '1'; ctrl.rs2d := '1';
|
441 |
|
|
when others => fpill := '1'; -- illegal instuction
|
442 |
|
|
end case;
|
443 |
|
|
end if;
|
444 |
|
|
when others => null;
|
445 |
|
|
end case;
|
446 |
|
|
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
|
447 |
|
|
(ex.wreg = '1')
|
448 |
|
|
then
|
449 |
|
|
if (ctrl.rreg1 = '1') and
|
450 |
|
|
(rs1(4 downto 1) = cpi.ex.inst(29 downto 26)) and
|
451 |
|
|
(((ctrl.rs1d or ex.rdd) = '1') or (rs1(0) = cpi.ex.inst(25)))
|
452 |
|
|
then ldlock := '1'; end if;
|
453 |
|
|
if (ctrl.rreg2 = '1') and
|
454 |
|
|
(rs2(4 downto 1) = cpi.ex.inst(29 downto 26)) and
|
455 |
|
|
(((ctrl.rs2d or ex.rdd) = '1') or (rs2(0) = cpi.ex.inst(25)))
|
456 |
|
|
then ldlock := '1'; end if;
|
457 |
|
|
end if;
|
458 |
|
|
when LDST =>
|
459 |
|
|
case op3 is
|
460 |
|
|
when LDF | LDDF =>
|
461 |
|
|
if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
|
462 |
|
|
elsif rx.state = nominal then
|
463 |
|
|
ctrl.rdd := op3(1) and op3(0);
|
464 |
|
|
ctrl.cpins := load; ctrl.wreg := '1';
|
465 |
|
|
for i in 0 to EUTYPES-1 loop -- dst interlock
|
466 |
|
|
for j in 0 to euconf(i) loop
|
467 |
|
|
ldlock := ldlock or ldcheck(rd, ctrl.rdd, euin(i)(j));
|
468 |
|
|
end loop;
|
469 |
|
|
end loop;
|
470 |
|
|
end if;
|
471 |
|
|
when STF | STDF =>
|
472 |
|
|
-- check for CP register dependencies
|
473 |
|
|
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
|
474 |
|
|
(cpi.ex.cnt = "00") and
|
475 |
|
|
((rd = cpi.ex.inst(29 downto 25)) or
|
476 |
|
|
((rd(4 downto 1) = cpi.ex.inst(29 downto 26)) and
|
477 |
|
|
(ex.rdd = '1')))
|
478 |
|
|
then ldlock := '1'; end if;
|
479 |
|
|
if rx.state = nominal then
|
480 |
|
|
for i in 0 to EUTYPES-1 loop
|
481 |
|
|
for j in 0 to euconf(i) loop
|
482 |
|
|
ldlock := ldlock or stcheck(rd, (op3(1) and op3(0)), euin(i)(j));
|
483 |
|
|
end loop;
|
484 |
|
|
end loop;
|
485 |
|
|
end if;
|
486 |
|
|
if (ldlock = '0') then ctrl.cpins := store; end if;
|
487 |
|
|
when STFSR | LDFSR =>
|
488 |
|
|
if (rx.state = exception) and (op3 = LDFSR) then
|
489 |
|
|
rxv.state := excpend; rxv.csr.tt := "100";
|
490 |
|
|
else
|
491 |
|
|
if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
|
492 |
|
|
(cpi.ex.cnt = "00") and (op3 = STFSR) and (ex.acsr = '1')
|
493 |
|
|
then ldlock := '1'; end if;
|
494 |
|
|
if (rx.state = nominal) then
|
495 |
|
|
for i in 0 to EUTYPES-1 loop
|
496 |
|
|
for j in 0 to euconf(i) loop
|
497 |
|
|
if eu(i)(j).status > free then ldlock := '1'; end if;
|
498 |
|
|
end loop;
|
499 |
|
|
end loop;
|
500 |
|
|
end if;
|
501 |
|
|
end if;
|
502 |
|
|
-- FIX ME - add check for not yet commited cpins in pipeline
|
503 |
|
|
if (ldlock = '0') then
|
504 |
|
|
ctrl.acsr := '1';
|
505 |
|
|
if op3 = STFSR then ctrl.cpins := store;
|
506 |
|
|
else ctrl.cpins := load; end if;
|
507 |
|
|
end if;
|
508 |
|
|
when STDFQ =>
|
509 |
|
|
if (rx.state = nominal) then
|
510 |
|
|
rxv.state := excpend; rxv.csr.tt := "100";
|
511 |
|
|
else ctrl.cpins := store; end if;
|
512 |
|
|
when others => null;
|
513 |
|
|
end case;
|
514 |
|
|
when others => null;
|
515 |
|
|
end case;
|
516 |
|
|
if ((cpi.flush or cpi.dtrap or cpi.dannul) = '1') then
|
517 |
|
|
ctrl.cpins := none;
|
518 |
|
|
rxv.state := rx.state; rxv.csr.tt := rx.csr.tt;
|
519 |
|
|
end if;
|
520 |
|
|
|
521 |
|
|
-------------------------------------------------------------
|
522 |
|
|
-- execute stage
|
523 |
|
|
-------------------------------------------------------------
|
524 |
|
|
|
525 |
|
|
-- generate regfile addresses
|
526 |
|
|
if holdn = '0' then
|
527 |
|
|
op := cpi.me.inst(31 downto 30);
|
528 |
|
|
rd := cpi.me.inst(29 downto 25);
|
529 |
|
|
op3 := cpi.me.inst(24 downto 19);
|
530 |
|
|
rs1 := cpi.me.inst(18 downto 14);
|
531 |
|
|
rs2 := cpi.me.inst(4 downto 0);
|
532 |
|
|
else
|
533 |
|
|
op := cpi.ex.inst(31 downto 30);
|
534 |
|
|
rd := cpi.ex.inst(29 downto 25);
|
535 |
|
|
op3 := cpi.ex.inst(24 downto 19);
|
536 |
|
|
rs1 := cpi.ex.inst(18 downto 14);
|
537 |
|
|
rs2 := cpi.ex.inst(4 downto 0);
|
538 |
|
|
end if;
|
539 |
|
|
|
540 |
|
|
if (op = LDST) and (op3(2) = '1') then rs1 := rd; end if;
|
541 |
|
|
|
542 |
|
|
rfi.raddr1 <= rs1(4 downto 1); rfi.raddr2 <= rs2(4 downto 1);
|
543 |
|
|
cpo.ldlock <= ldlock;
|
544 |
|
|
|
545 |
|
|
op1 := rfo.rdata1; op2 := rfo.rdata2;
|
546 |
|
|
|
547 |
|
|
-- generate store data
|
548 |
|
|
if (cpi.ex.inst(20 downto 19) = "10") then -- STDFQ
|
549 |
|
|
if (cpi.ex.cnt /= "10") then stdata := eu(euti)(euqi).pc;
|
550 |
|
|
else stdata := eu(euti)(euqi).inst; end if;
|
551 |
|
|
elsif ((cpi.ex.inst(25) = '0') and (cpi.ex.cnt /= "10")) then -- STF/STDF
|
552 |
|
|
stdata := op1(63 downto 32);
|
553 |
|
|
else stdata := op1(31 downto 0); end if;
|
554 |
|
|
if (ex.cpins = store) and (ex.acsr = '1') then -- STFSR
|
555 |
|
|
stdata := rx.csr.rd & "00" & rx.csr.tem & "000" & FPUVER &
|
556 |
|
|
rx.csr.tt & qne & '0' & rx.csr.cc & rx.csr.aexc & rx.csr.cexc;
|
557 |
|
|
end if;
|
558 |
|
|
cpo.data <= stdata;
|
559 |
|
|
|
560 |
|
|
-- check for source operand dependency with scheduled instructions
|
561 |
|
|
if (ex.cpins = cpop) then
|
562 |
|
|
rv.sdep := ddepcheck(cpi.ex.inst(18 downto 14), cpi.ex.inst(4 downto 0),
|
563 |
|
|
ex.rreg1, ex.rreg2, ex.rs1d, ex.rs2d, eu, euo);
|
564 |
|
|
end if;
|
565 |
|
|
|
566 |
|
|
-- select execution unit type
|
567 |
|
|
if (cpi.ex.inst(12 downto 9) = "0000") and (EUTYPES > 1) then
|
568 |
|
|
rv.eut := EUTYPES-1; -- use exection unit 1
|
569 |
|
|
else
|
570 |
|
|
rv.eut := 0; -- use exection unit 0
|
571 |
|
|
end if;
|
572 |
|
|
|
573 |
|
|
-- check if an execution unit is available
|
574 |
|
|
if (ex.cpins = cpop) and (holdn = '1') and (cpi.flush = '0') then
|
575 |
|
|
rv.eui := euq(rv.eut).first;
|
576 |
|
|
ccv := ccv or ex.wrcc;
|
577 |
|
|
if (rv.sdep = '0') and (eu(rv.eut)(euq(rv.eut).first).status = free)
|
578 |
|
|
then
|
579 |
|
|
rxv.start := '1';
|
580 |
|
|
euiv(rv.eut)(rv.eui).start := '1';
|
581 |
|
|
euv(rv.eut)(rv.eui).status := started;
|
582 |
|
|
euv(rv.eut)(rv.eui).rd := cpi.ex.inst(29 downto 25);
|
583 |
|
|
euv(rv.eut)(rv.eui).rs1 := cpi.ex.inst(18 downto 14);
|
584 |
|
|
euv(rv.eut)(rv.eui).rs2 := cpi.ex.inst(4 downto 0);
|
585 |
|
|
euv(rv.eut)(rv.eui).wreg := ex.wreg;
|
586 |
|
|
euv(rv.eut)(rv.eui).rreg1 := ex.rreg1;
|
587 |
|
|
euv(rv.eut)(rv.eui).rreg2 := ex.rreg2;
|
588 |
|
|
euv(rv.eut)(rv.eui).rs1d := ex.rs1d;
|
589 |
|
|
euv(rv.eut)(rv.eui).rs2d := ex.rs2d;
|
590 |
|
|
euv(rv.eut)(rv.eui).rdd := ex.rdd;
|
591 |
|
|
euv(rv.eut)(rv.eui).wrcc := ex.wrcc;
|
592 |
|
|
else rxv.holdn := '0'; rv.start := '1'; end if;
|
593 |
|
|
ctrl.first := euf.first;
|
594 |
|
|
eufv.fifo(euf.first) := rv.eut;
|
595 |
|
|
if euq(rv.eut).first = euconf(rv.eut) then euqv(rv.eut).first := 0;
|
596 |
|
|
else euqv(rv.eut).first := euqv(rv.eut).first + 1; end if;
|
597 |
|
|
if euf.first = (EUTOT-1) then eufv.first := 0;
|
598 |
|
|
else eufv.first := eufv.first + 1; end if;
|
599 |
|
|
end if;
|
600 |
|
|
|
601 |
|
|
-------------------------------------------------------------
|
602 |
|
|
-- memory stage
|
603 |
|
|
-------------------------------------------------------------
|
604 |
|
|
|
605 |
|
|
ddep := ddepcheck(cpi.me.inst(18 downto 14), cpi.me.inst(4 downto 0),
|
606 |
|
|
me.rreg1, me.rreg2, me.rs1d, me.rs2d, eu, euo);
|
607 |
|
|
|
608 |
|
|
euiv(r.eut)(r.eui).load := rx.start or rx.starty;
|
609 |
|
|
if (rx.holdn = '0') and (xholdn = '1') and (cpi.flush = '0') and
|
610 |
|
|
((r.sdep and ddep) = '0') and (euo(r.eut)(euq(r.eut).first).busy = '0')
|
611 |
|
|
then
|
612 |
|
|
euiv(r.eut)(r.eui).start := not rx.startx;
|
613 |
|
|
euiv(r.eut)(r.eui).opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
|
614 |
|
|
end if;
|
615 |
|
|
if (rx.holdn = '0') and (cpi.flush = '0') and
|
616 |
|
|
(not ((r.sdep = '1') and (ddep = '1'))) and
|
617 |
|
|
((eu(r.eut)(r.eui).status <= free) or
|
618 |
|
|
(euin(r.eut)(r.eui).wb = '1'))
|
619 |
|
|
then
|
620 |
|
|
euiv(r.eut)(r.eui).load := rx.starty;
|
621 |
|
|
euiv(r.eut)(r.eui).start := not (rx.starty or rx.startx);
|
622 |
|
|
if eu(r.eut)(r.eui).status /= exception then
|
623 |
|
|
euv(r.eut)(r.eui).status := started;
|
624 |
|
|
end if;
|
625 |
|
|
euv(r.eut)(r.eui).rs1 := cpi.me.inst(18 downto 14);
|
626 |
|
|
euv(r.eut)(r.eui).rs2 := cpi.me.inst(4 downto 0);
|
627 |
|
|
euv(r.eut)(r.eui).rd := cpi.me.inst(29 downto 25);
|
628 |
|
|
euv(r.eut)(r.eui).wreg := me.wreg;
|
629 |
|
|
euv(r.eut)(r.eui).rreg1 := me.rreg1;
|
630 |
|
|
euv(r.eut)(r.eui).rreg2 := me.rreg2;
|
631 |
|
|
euv(r.eut)(r.eui).rs1d := me.rs1d;
|
632 |
|
|
euv(r.eut)(r.eui).rs2d := me.rs2d;
|
633 |
|
|
euv(r.eut)(r.eui).rdd := me.rdd;
|
634 |
|
|
euv(r.eut)(r.eui).wrcc := me.wrcc;
|
635 |
|
|
euiv(r.eut)(r.eui).opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
|
636 |
|
|
rxv.holdn := '1';
|
637 |
|
|
end if;
|
638 |
|
|
rxv.starty := euiv(r.eut)(r.eui).start;
|
639 |
|
|
rxv.startx := (rx.startx or euiv(r.eut)(r.eui).start) and not holdn;
|
640 |
|
|
ccv := ccv or me.wrcc;
|
641 |
|
|
if cpi.flush = '1' then rxv.holdn := '1'; end if;
|
642 |
|
|
|
643 |
|
|
-- regfile bypass
|
644 |
|
|
if (rx.waddr = cpi.me.inst(18 downto 15)) then
|
645 |
|
|
if (rx.wren(0) = '1') then op1(63 downto 32) := rx.res(63 downto 32); end if;
|
646 |
|
|
if (rx.wren(1) = '1') then op1(31 downto 0) := rx.res(31 downto 0); end if;
|
647 |
|
|
end if;
|
648 |
|
|
if (rx.waddr = cpi.me.inst(4 downto 1)) then
|
649 |
|
|
if (rx.wren(0) = '1') then op2(63 downto 32) := rx.res(63 downto 32); end if;
|
650 |
|
|
if (rx.wren(1) = '1') then op2(31 downto 0) := rx.res(31 downto 0); end if;
|
651 |
|
|
end if;
|
652 |
|
|
|
653 |
|
|
-- optionally forward data from write stage
|
654 |
|
|
if rfi.wren(0) = '1' then
|
655 |
|
|
if cpi.me.inst(18 downto 15) = rfi.waddr then
|
656 |
|
|
op1(63 downto 32) := rfi.wdata(63 downto 32);
|
657 |
|
|
end if;
|
658 |
|
|
if cpi.me.inst(4 downto 1) = rfi.waddr then
|
659 |
|
|
op2(63 downto 32) := rfi.wdata(63 downto 32);
|
660 |
|
|
end if;
|
661 |
|
|
end if;
|
662 |
|
|
if rfi.wren(1) = '1' then
|
663 |
|
|
if cpi.me.inst(18 downto 15) = rfi.waddr then
|
664 |
|
|
op1(31 downto 0) := rfi.wdata(31 downto 0);
|
665 |
|
|
end if;
|
666 |
|
|
if cpi.me.inst(4 downto 1) = rfi.waddr then
|
667 |
|
|
op2(31 downto 0) := rfi.wdata(31 downto 0);
|
668 |
|
|
end if;
|
669 |
|
|
end if;
|
670 |
|
|
|
671 |
|
|
-- align single operands
|
672 |
|
|
if me.rs1d = '0' then
|
673 |
|
|
if cpi.me.inst(14) = '0' then op1 := op1(63 downto 32) & op1(63 downto 32);
|
674 |
|
|
else op1 := op1(31 downto 0) & op1(31 downto 0); end if;
|
675 |
|
|
end if;
|
676 |
|
|
if me.rs2d = '0' then
|
677 |
|
|
if cpi.me.inst(0) = '0' then op2 := op2(63 downto 32) & op2(63 downto 32);
|
678 |
|
|
else op2 := op2(31 downto 0) & op2(31 downto 0); end if;
|
679 |
|
|
end if;
|
680 |
|
|
|
681 |
|
|
-- drive EU operand inputs
|
682 |
|
|
for i in 0 to EUTYPES-1 loop
|
683 |
|
|
for j in 0 to euconf(i) loop
|
684 |
|
|
euiv(i)(j).op1 := op1; euiv(i)(j).op2 := op2;
|
685 |
|
|
end loop;
|
686 |
|
|
end loop;
|
687 |
|
|
|
688 |
|
|
cpo.holdn <= rx.holdn;
|
689 |
|
|
|
690 |
|
|
-------------------------------------------------------------
|
691 |
|
|
-- write stage
|
692 |
|
|
-------------------------------------------------------------
|
693 |
|
|
|
694 |
|
|
wrdata := cpi.lddata & cpi.lddata;
|
695 |
|
|
if cpi.flush = '0' then
|
696 |
|
|
case wr.cpins is
|
697 |
|
|
when load =>
|
698 |
|
|
if (wr.wreg = '1') then
|
699 |
|
|
if cpi.wr.cnt = "00" then
|
700 |
|
|
wren(0) := not cpi.wr.inst(25);
|
701 |
|
|
wren(1) := cpi.wr.inst(25);
|
702 |
|
|
else wren(1) := '1'; end if;
|
703 |
|
|
end if;
|
704 |
|
|
if (wr.acsr and holdn) = '1' then
|
705 |
|
|
rxv.csr.cexc := cpi.lddata(4 downto 0);
|
706 |
|
|
rxv.csr.aexc := cpi.lddata(9 downto 5);
|
707 |
|
|
rxv.csr.cc := cpi.lddata(11 downto 10);
|
708 |
|
|
rxv.csr.tem := cpi.lddata(27 downto 23);
|
709 |
|
|
rxv.csr.rd := cpi.lddata(31 downto 30);
|
710 |
|
|
end if;
|
711 |
|
|
when store =>
|
712 |
|
|
if wr.acsr = '1' then rxv.csr.tt := (others => '0'); end if;
|
713 |
|
|
if (cpi.wr.inst(20 downto 19) = "10") then -- STDFQ
|
714 |
|
|
if qne = '1'then
|
715 |
|
|
euv(euti)(euqi).status := free;
|
716 |
|
|
euv(euti)(euqi).rst := '1';
|
717 |
|
|
if euq(euti).last = euconf(euti) then euqv(euti).last := 0;
|
718 |
|
|
else euqv(euti).last := euqv(euti).last + 1; end if;
|
719 |
|
|
if (euf.last /= euf.first) then
|
720 |
|
|
if euf.last = (EUTOT-1) then eufv.last := 0;
|
721 |
|
|
else eufv.last := eufv.last + 1; end if;
|
722 |
|
|
end if;
|
723 |
|
|
else
|
724 |
|
|
rxv.state := nominal;
|
725 |
|
|
end if;
|
726 |
|
|
end if;
|
727 |
|
|
when cpop =>
|
728 |
|
|
-- dont assign PC and inst until here in case previous cpop trapped
|
729 |
|
|
euv(r.weut)(r.weui).inst := cpi.wr.inst;
|
730 |
|
|
euv(r.weut)(r.weui).pc := cpi.wr.pc;
|
731 |
|
|
when others => null;
|
732 |
|
|
end case;
|
733 |
|
|
end if;
|
734 |
|
|
|
735 |
|
|
-- flush EU if trap was taken
|
736 |
|
|
if ((holdn and cpi.flush) = '1') and (EUTOT > 1) then
|
737 |
|
|
case wr.cpins is
|
738 |
|
|
when cpop =>
|
739 |
|
|
if eu(r.weut)(r.weui).status /= exception then
|
740 |
|
|
euv(r.weut)(r.weui).rst := '1';
|
741 |
|
|
euv(r.weut)(r.weui).status := free;
|
742 |
|
|
end if;
|
743 |
|
|
eufv.first := wr.first;
|
744 |
|
|
euqv(r.eut).first := r.eut;
|
745 |
|
|
euqv(r.weut).first := r.weut;
|
746 |
|
|
when others => null;
|
747 |
|
|
end case;
|
748 |
|
|
end if;
|
749 |
|
|
waddr := cpi.wr.inst(29 downto 26);
|
750 |
|
|
|
751 |
|
|
-------------------------------------------------------------
|
752 |
|
|
-- retire stage
|
753 |
|
|
-------------------------------------------------------------
|
754 |
|
|
|
755 |
|
|
rtaddr := eu(euti)(euqi).rd(4 downto 1);
|
756 |
|
|
if eu(euti)(euqi).rdd = '1' then rtdata := euo(euti)(euqi).res;
|
757 |
|
|
else
|
758 |
|
|
rtdata(63 downto 32) := euo(euti)(euqi).res(63) &
|
759 |
|
|
euo(euti)(euqi).res(59 downto 29);
|
760 |
|
|
rtdata(31 downto 0) := rtdata(63 downto 32);
|
761 |
|
|
end if;
|
762 |
|
|
|
763 |
|
|
wren := wren and (holdn & holdn);
|
764 |
|
|
|
765 |
|
|
if ((euo(euti)(euqi).exc(4 downto 0) and rx.csr.tem) /= "00000") or
|
766 |
|
|
(euo(euti)(euqi).exc(5) = '1')
|
767 |
|
|
then
|
768 |
|
|
cpexc := '1';
|
769 |
|
|
end if;
|
770 |
|
|
if (wren = "00") and (eu(euti)(euqi).status = ready) and
|
771 |
|
|
(rx.state = nominal)
|
772 |
|
|
then
|
773 |
|
|
waddr := rtaddr; wrdata := rtdata;
|
774 |
|
|
if cpexc = '0' then
|
775 |
|
|
if (eu(euti)(euqi).wreg) = '1' then
|
776 |
|
|
if (eu(euti)(euqi).rdd) = '1' then wren := "11";
|
777 |
|
|
else
|
778 |
|
|
wren(0) := not eu(euti)(euqi).rd(0);
|
779 |
|
|
wren(1) := eu(euti)(euqi).rd(0);
|
780 |
|
|
end if;
|
781 |
|
|
end if;
|
782 |
|
|
if eu(euti)(euqi).wrcc = '1' then
|
783 |
|
|
rxv.csr.cc := euo(euti)(euqi).cc;
|
784 |
|
|
end if;
|
785 |
|
|
rxv.csr.aexc := rx.csr.aexc or euo(euti)(euqi).exc(4 downto 0);
|
786 |
|
|
if euv(euti)(euqi).status = ready then
|
787 |
|
|
euv(euti)(euqi).status := free;
|
788 |
|
|
end if;
|
789 |
|
|
euv(euti)(euqi).wb := '1';
|
790 |
|
|
rxv.csr.cexc := euo(euti)(euqi).exc(4 downto 0);
|
791 |
|
|
if euq(euti).last = euconf(euti) then euqv(euti).last := 0;
|
792 |
|
|
else euqv(euti).last := euqv(euti).last + 1; end if;
|
793 |
|
|
if euf.last = (EUTOT-1) then eufv.last := 0;
|
794 |
|
|
else eufv.last := eufv.last + 1; end if;
|
795 |
|
|
else
|
796 |
|
|
euv(euti)(euqi).status := exception;
|
797 |
|
|
rxv.state := excpend;
|
798 |
|
|
if (euo(euti)(euqi).exc(5) = '1') then rxv.csr.tt := "011";
|
799 |
|
|
else rxv.csr.tt := "001"; end if;
|
800 |
|
|
end if;
|
801 |
|
|
end if;
|
802 |
|
|
|
803 |
|
|
if cpi.exack = '1' then rxv.state := exception; end if;
|
804 |
|
|
if rxv.state = excpend then cpo.exc <= '1'; else cpo.exc <= '0'; end if;
|
805 |
|
|
cpo.ccv <= not ccv;
|
806 |
|
|
cpo.cc <= rx.csr.cc;
|
807 |
|
|
|
808 |
|
|
rxv.res := wrdata;
|
809 |
|
|
rxv.waddr := waddr;
|
810 |
|
|
rxv.wren := wren;
|
811 |
|
|
rfi.waddr <= waddr;
|
812 |
|
|
rfi.wren <= wren;
|
813 |
|
|
rfi.wdata <= wrdata;
|
814 |
|
|
|
815 |
|
|
|
816 |
|
|
-- reset
|
817 |
|
|
if rst = '0' then
|
818 |
|
|
for i in 0 to EUTYPES-1 loop
|
819 |
|
|
for j in 0 to euconf(i) loop euv(i)(j).status := free; end loop;
|
820 |
|
|
euqv(i).first := 0; euqv(i).last := 0;
|
821 |
|
|
end loop;
|
822 |
|
|
eufv.first := 0; eufv.last := 0; rxv.holdn := '1'; rv.start := '0';
|
823 |
|
|
rxv.state := nominal; rxv.csr.tt := (others => '0');
|
824 |
|
|
rxv.startx := '0';
|
825 |
|
|
ctrl.first := 0;
|
826 |
|
|
end if;
|
827 |
|
|
|
828 |
|
|
euin <= euv;
|
829 |
|
|
eui <= euiv;
|
830 |
|
|
eufin <= eufv;
|
831 |
|
|
euqin <= euqv;
|
832 |
|
|
exin <= ctrl;
|
833 |
|
|
rin <= rv;
|
834 |
|
|
rxin <= rxv;
|
835 |
|
|
|
836 |
|
|
end process;
|
837 |
|
|
|
838 |
|
|
-- registers
|
839 |
|
|
|
840 |
|
|
regs : process(clk)
|
841 |
|
|
variable pc : std_logic_vector(31 downto 0);
|
842 |
|
|
begin
|
843 |
|
|
if rising_edge(clk(0)) then
|
844 |
|
|
if holdn = '1' then
|
845 |
|
|
ex <= exin; me <= ex; wr <= me; r <= rin;
|
846 |
|
|
end if;
|
847 |
|
|
euq <= euqin; euf <= eufin;
|
848 |
|
|
rx <= rxin; eu <= euin;
|
849 |
|
|
-- pragma translate_off
|
850 |
|
|
if DEBUGFPU then
|
851 |
|
|
if euin(euf.fifo(euf.last))(euq(euf.fifo(euf.last)).last).wb = '1' then
|
852 |
|
|
pc := eu(euf.fifo(euf.last))(euq(euf.fifo(euf.last)).last).pc;
|
853 |
|
|
else pc := cpi.wr.pc; end if;
|
854 |
|
|
if (rfi.wren(0) = '1') then
|
855 |
|
|
print(tost(pc) & ": %f" & tost("000" & rfi.waddr & '0') &
|
856 |
|
|
" = " & tost(rfi.wdata(63 downto 32)));
|
857 |
|
|
end if;
|
858 |
|
|
if (rfi.wren(1) = '1') then
|
859 |
|
|
print(tost(pc) & ": %f" & tost("000" & rfi.waddr & '1') &
|
860 |
|
|
" = " & tost(rfi.wdata(31 downto 0)));
|
861 |
|
|
end if;
|
862 |
|
|
end if;
|
863 |
|
|
-- pragma translate_on
|
864 |
|
|
end if;
|
865 |
|
|
end process;
|
866 |
|
|
|
867 |
|
|
-- simple 3-port register file made up of 4 parallel dprams
|
868 |
|
|
|
869 |
|
|
dp00: dpram_synp_ss generic map (4, 32, 16)
|
870 |
|
|
port map (rfi.wdata(63 downto 32), rfi.raddr1, rfi.waddr, vcc, rfi.wren(0),
|
871 |
|
|
clk(0), vcc, rfo.rdata1(63 downto 32));
|
872 |
|
|
dp01: dpram_synp_ss generic map (4, 32, 16)
|
873 |
|
|
port map (rfi.wdata(31 downto 0), rfi.raddr1, rfi.waddr, vcc, rfi.wren(1),
|
874 |
|
|
clk(0), vcc, rfo.rdata1(31 downto 0));
|
875 |
|
|
dp10: dpram_synp_ss generic map (4, 32, 16)
|
876 |
|
|
port map (rfi.wdata(63 downto 32), rfi.raddr2, rfi.waddr, vcc, rfi.wren(0),
|
877 |
|
|
clk(0), vcc, rfo.rdata2(63 downto 32));
|
878 |
|
|
dp11: dpram_synp_ss generic map (4, 32, 16)
|
879 |
|
|
port map (rfi.wdata(31 downto 0), rfi.raddr2, rfi.waddr, vcc, rfi.wren(1),
|
880 |
|
|
clk(0), vcc, rfo.rdata2(31 downto 0));
|
881 |
|
|
|
882 |
|
|
gl0 : for i in 0 to euconf(0) generate
|
883 |
|
|
fpu0 : fpu port map (
|
884 |
|
|
ss_clock => clk(0),
|
885 |
|
|
FpInst => eui(0)(i).opcode,
|
886 |
|
|
FpOp => eui(0)(i).start,
|
887 |
|
|
FpLd => eui(0)(i).load,
|
888 |
|
|
Reset => eui(0)(i).flush,
|
889 |
|
|
fprf_dout1 => eui(0)(i).op1,
|
890 |
|
|
fprf_dout2 => eui(0)(i).op2,
|
891 |
|
|
RoundingMode => rx.csr.rd,
|
892 |
|
|
FpBusy => euo(0)(i).busy,
|
893 |
|
|
FracResult => euo(0)(i).res(51 downto 0),
|
894 |
|
|
ExpResult => euo(0)(i).res(62 downto 52),
|
895 |
|
|
SignResult => euo(0)(i).res(63),
|
896 |
|
|
SNnotDB => open,
|
897 |
|
|
Excep => euo(0)(i).exc,
|
898 |
|
|
ConditionCodes => euo(0)(i).cc,
|
899 |
|
|
ss_scan_mode => gnd,
|
900 |
|
|
fp_ctl_scan_in => gnd,
|
901 |
|
|
fp_ctl_scan_out => open);
|
902 |
|
|
end generate;
|
903 |
|
|
|
904 |
|
|
fpauxgen : if EUTYPES > 1 generate
|
905 |
|
|
gl1 : for i in 0 to euconf(1) generate
|
906 |
|
|
eu1 : fpaux port map (rst, clk(0), eui(1)(i), euo(1)(i));
|
907 |
|
|
end generate;
|
908 |
|
|
end generate;
|
909 |
|
|
|
910 |
|
|
end;
|
911 |
|
|
|
912 |
|
|
|