1 |
2 |
dimamali |
------------------------------------------------------------------------------
|
2 |
|
|
-- This file is a part of the GRLIB VHDL IP LIBRARY
|
3 |
|
|
-- Copyright (C) 2003, Gaisler Research
|
4 |
|
|
--
|
5 |
|
|
-- This program is free software; you can redistribute it and/or modify
|
6 |
|
|
-- it under the terms of the GNU General Public License as published by
|
7 |
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
8 |
|
|
-- (at your option) any later version.
|
9 |
|
|
--
|
10 |
|
|
-- This program is distributed in the hope that it will be useful,
|
11 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
|
|
-- GNU General Public License for more details.
|
14 |
|
|
--
|
15 |
|
|
-- You should have received a copy of the GNU General Public License
|
16 |
|
|
-- along with this program; if not, write to the Free Software
|
17 |
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18 |
|
|
-----------------------------------------------------------------------------
|
19 |
|
|
-- Entity: iu3
|
20 |
|
|
-- File: iu3.vhd
|
21 |
|
|
-- Author: Jiri Gaisler, Edvin Catovic, Gaisler Research
|
22 |
|
|
-- Description: LEON3 7-stage integer pipline
|
23 |
|
|
------------------------------------------------------------------------------
|
24 |
|
|
|
25 |
|
|
library ieee;
|
26 |
|
|
use ieee.std_logic_1164.all;
|
27 |
|
|
use ieee.numeric_std.all;
|
28 |
|
|
library grlib;
|
29 |
|
|
use grlib.sparc.all;
|
30 |
|
|
use grlib.stdlib.all;
|
31 |
|
|
library techmap;
|
32 |
|
|
use techmap.gencomp.all;
|
33 |
|
|
library gaisler;
|
34 |
|
|
use gaisler.leon3.all;
|
35 |
|
|
use gaisler.libiu.all;
|
36 |
|
|
use gaisler.arith.all;
|
37 |
|
|
-- pragma translate_off
|
38 |
|
|
use grlib.sparc_disas.all;
|
39 |
|
|
-- pragma translate_on
|
40 |
|
|
|
41 |
|
|
entity iu3 is
|
42 |
|
|
generic (
|
43 |
|
|
nwin : integer range 2 to 32 := 8;
|
44 |
|
|
isets : integer range 1 to 4 := 1;
|
45 |
|
|
dsets : integer range 1 to 4 := 1;
|
46 |
|
|
fpu : integer range 0 to 15 := 0;
|
47 |
|
|
v8 : integer range 0 to 63 := 0;
|
48 |
|
|
cp, mac : integer range 0 to 1 := 0;
|
49 |
|
|
dsu : integer range 0 to 1 := 0;
|
50 |
|
|
nwp : integer range 0 to 4 := 0;
|
51 |
|
|
pclow : integer range 0 to 2 := 2;
|
52 |
|
|
notag : integer range 0 to 1 := 0;
|
53 |
|
|
index : integer range 0 to 15:= 0;
|
54 |
|
|
lddel : integer range 1 to 2 := 2;
|
55 |
|
|
irfwt : integer range 0 to 1 := 0;
|
56 |
|
|
disas : integer range 0 to 2 := 0;
|
57 |
|
|
tbuf : integer range 0 to 64 := 0; -- trace buf size in kB (0 - no trace buffer)
|
58 |
|
|
pwd : integer range 0 to 2 := 0; -- power-down
|
59 |
|
|
svt : integer range 0 to 1 := 0; -- single-vector trapping
|
60 |
|
|
rstaddr : integer := 16#00000#; -- reset vector MSB address
|
61 |
|
|
smp : integer range 0 to 15 := 0; -- support SMP systems
|
62 |
|
|
fabtech : integer range 0 to NTECH := 0;
|
63 |
|
|
clk2x : integer := 0
|
64 |
|
|
);
|
65 |
|
|
port (
|
66 |
|
|
clk : in std_ulogic;
|
67 |
|
|
rstn : in std_ulogic;
|
68 |
|
|
holdn : in std_ulogic;
|
69 |
|
|
ici : out icache_in_type;
|
70 |
|
|
ico : in icache_out_type;
|
71 |
|
|
dci : out dcache_in_type;
|
72 |
|
|
dco : in dcache_out_type;
|
73 |
|
|
rfi : out iregfile_in_type;
|
74 |
|
|
rfo : in iregfile_out_type;
|
75 |
|
|
irqi : in l3_irq_in_type;
|
76 |
|
|
irqo : out l3_irq_out_type;
|
77 |
|
|
dbgi : in l3_debug_in_type;
|
78 |
|
|
dbgo : out l3_debug_out_type;
|
79 |
|
|
muli : out mul32_in_type;
|
80 |
|
|
mulo : in mul32_out_type;
|
81 |
|
|
divi : out div32_in_type;
|
82 |
|
|
divo : in div32_out_type;
|
83 |
|
|
fpo : in fpc_out_type;
|
84 |
|
|
fpi : out fpc_in_type;
|
85 |
|
|
cpo : in fpc_out_type;
|
86 |
|
|
cpi : out fpc_in_type;
|
87 |
|
|
tbo : in tracebuf_out_type;
|
88 |
|
|
tbi : out tracebuf_in_type;
|
89 |
|
|
sclk : in std_ulogic
|
90 |
|
|
);
|
91 |
|
|
end;
|
92 |
|
|
|
93 |
|
|
architecture rtl of iu3 is
|
94 |
|
|
|
95 |
|
|
constant ISETMSB : integer := log2x(isets)-1;
|
96 |
|
|
constant DSETMSB : integer := log2x(dsets)-1;
|
97 |
|
|
constant RFBITS : integer range 6 to 10 := log2(NWIN+1) + 4;
|
98 |
|
|
constant NWINLOG2 : integer range 1 to 5 := log2(NWIN);
|
99 |
|
|
constant CWPOPT : boolean := (NWIN = (2**NWINLOG2));
|
100 |
|
|
constant CWPMIN : std_logic_vector(NWINLOG2-1 downto 0) := (others => '0');
|
101 |
|
|
constant CWPMAX : std_logic_vector(NWINLOG2-1 downto 0) :=
|
102 |
|
|
conv_std_logic_vector(NWIN-1, NWINLOG2);
|
103 |
|
|
constant FPEN : boolean := (fpu /= 0);
|
104 |
|
|
constant CPEN : boolean := (cp = 1);
|
105 |
|
|
constant MULEN : boolean := (v8 /= 0);
|
106 |
|
|
constant MULTYPE: integer := (v8 / 16);
|
107 |
|
|
constant DIVEN : boolean := (v8 /= 0);
|
108 |
|
|
constant MACEN : boolean := (mac = 1);
|
109 |
|
|
constant MACPIPE: boolean := (mac = 1) and (v8/2 = 1);
|
110 |
|
|
constant IMPL : integer := 15;
|
111 |
|
|
constant VER : integer := 3;
|
112 |
|
|
constant DBGUNIT : boolean := (dsu = 1);
|
113 |
|
|
constant TRACEBUF : boolean := (tbuf /= 0);
|
114 |
|
|
constant TBUFBITS : integer := 10 + log2(tbuf) - 4;
|
115 |
|
|
constant PWRD1 : boolean := false; --(pwd = 1) and not (index /= 0);
|
116 |
|
|
constant PWRD2 : boolean := pwd /= 0; --(pwd = 2) or (index /= 0);
|
117 |
|
|
constant RS1OPT : boolean := (is_fpga(FABTECH) /= 0);
|
118 |
|
|
constant DYNRST : boolean := (rstaddr = 16#FFFFF#);
|
119 |
|
|
|
120 |
|
|
subtype word is std_logic_vector(31 downto 0);
|
121 |
|
|
subtype pctype is std_logic_vector(31 downto PCLOW);
|
122 |
|
|
subtype rfatype is std_logic_vector(RFBITS-1 downto 0);
|
123 |
|
|
subtype cwptype is std_logic_vector(NWINLOG2-1 downto 0);
|
124 |
|
|
type icdtype is array (0 to isets-1) of word;
|
125 |
|
|
type dcdtype is array (0 to dsets-1) of word;
|
126 |
|
|
|
127 |
|
|
type dc_in_type is record
|
128 |
|
|
signed, enaddr, read, write, lock , dsuen : std_ulogic;
|
129 |
|
|
size : std_logic_vector(1 downto 0);
|
130 |
|
|
asi : std_logic_vector(7 downto 0);
|
131 |
|
|
end record;
|
132 |
|
|
|
133 |
|
|
type pipeline_ctrl_type is record
|
134 |
|
|
pc : pctype;
|
135 |
|
|
inst : word;
|
136 |
|
|
cnt : std_logic_vector(1 downto 0);
|
137 |
|
|
rd : rfatype;
|
138 |
|
|
tt : std_logic_vector(5 downto 0);
|
139 |
|
|
trap : std_ulogic;
|
140 |
|
|
annul : std_ulogic;
|
141 |
|
|
wreg : std_ulogic;
|
142 |
|
|
wicc : std_ulogic;
|
143 |
|
|
wy : std_ulogic;
|
144 |
|
|
ld : std_ulogic;
|
145 |
|
|
pv : std_ulogic;
|
146 |
|
|
rett : std_ulogic;
|
147 |
|
|
end record;
|
148 |
|
|
|
149 |
|
|
type fetch_reg_type is record
|
150 |
|
|
pc : pctype;
|
151 |
|
|
branch : std_ulogic;
|
152 |
|
|
end record;
|
153 |
|
|
|
154 |
|
|
type decode_reg_type is record
|
155 |
|
|
pc : pctype;
|
156 |
|
|
inst : icdtype;
|
157 |
|
|
cwp : cwptype;
|
158 |
|
|
set : std_logic_vector(ISETMSB downto 0);
|
159 |
|
|
mexc : std_ulogic;
|
160 |
|
|
cnt : std_logic_vector(1 downto 0);
|
161 |
|
|
pv : std_ulogic;
|
162 |
|
|
annul : std_ulogic;
|
163 |
|
|
inull : std_ulogic;
|
164 |
|
|
step : std_ulogic;
|
165 |
|
|
end record;
|
166 |
|
|
|
167 |
|
|
type regacc_reg_type is record
|
168 |
|
|
ctrl : pipeline_ctrl_type;
|
169 |
|
|
rs1 : std_logic_vector(4 downto 0);
|
170 |
|
|
rfa1, rfa2 : rfatype;
|
171 |
|
|
rsel1, rsel2 : std_logic_vector(2 downto 0);
|
172 |
|
|
rfe1, rfe2 : std_ulogic;
|
173 |
|
|
cwp : cwptype;
|
174 |
|
|
imm : word;
|
175 |
|
|
ldcheck1 : std_ulogic;
|
176 |
|
|
ldcheck2 : std_ulogic;
|
177 |
|
|
ldchkra : std_ulogic;
|
178 |
|
|
ldchkex : std_ulogic;
|
179 |
|
|
su : std_ulogic;
|
180 |
|
|
et : std_ulogic;
|
181 |
|
|
wovf : std_ulogic;
|
182 |
|
|
wunf : std_ulogic;
|
183 |
|
|
ticc : std_ulogic;
|
184 |
|
|
jmpl : std_ulogic;
|
185 |
|
|
step : std_ulogic;
|
186 |
|
|
mulstart : std_ulogic;
|
187 |
|
|
divstart : std_ulogic;
|
188 |
|
|
end record;
|
189 |
|
|
|
190 |
|
|
type execute_reg_type is record
|
191 |
|
|
ctrl : pipeline_ctrl_type;
|
192 |
|
|
op1 : word;
|
193 |
|
|
op2 : word;
|
194 |
|
|
aluop : std_logic_vector(2 downto 0); -- Alu operation
|
195 |
|
|
alusel : std_logic_vector(1 downto 0); -- Alu result select
|
196 |
|
|
aluadd : std_ulogic;
|
197 |
|
|
alucin : std_ulogic;
|
198 |
|
|
ldbp1, ldbp2 : std_ulogic;
|
199 |
|
|
invop2 : std_ulogic;
|
200 |
|
|
shcnt : std_logic_vector(4 downto 0); -- shift count
|
201 |
|
|
sari : std_ulogic; -- shift msb
|
202 |
|
|
shleft : std_ulogic; -- shift left/right
|
203 |
|
|
ymsb : std_ulogic; -- shift left/right
|
204 |
|
|
rd : std_logic_vector(4 downto 0);
|
205 |
|
|
jmpl : std_ulogic;
|
206 |
|
|
su : std_ulogic;
|
207 |
|
|
et : std_ulogic;
|
208 |
|
|
cwp : cwptype;
|
209 |
|
|
icc : std_logic_vector(3 downto 0);
|
210 |
|
|
mulstep: std_ulogic;
|
211 |
|
|
mul : std_ulogic;
|
212 |
|
|
mac : std_ulogic;
|
213 |
|
|
end record;
|
214 |
|
|
|
215 |
|
|
type memory_reg_type is record
|
216 |
|
|
ctrl : pipeline_ctrl_type;
|
217 |
|
|
result : word;
|
218 |
|
|
y : word;
|
219 |
|
|
icc : std_logic_vector(3 downto 0);
|
220 |
|
|
nalign : std_ulogic;
|
221 |
|
|
dci : dc_in_type;
|
222 |
|
|
werr : std_ulogic;
|
223 |
|
|
wcwp : std_ulogic;
|
224 |
|
|
irqen : std_ulogic;
|
225 |
|
|
irqen2 : std_ulogic;
|
226 |
|
|
mac : std_ulogic;
|
227 |
|
|
divz : std_ulogic;
|
228 |
|
|
su : std_ulogic;
|
229 |
|
|
mul : std_ulogic;
|
230 |
|
|
end record;
|
231 |
|
|
|
232 |
|
|
type exception_state is (run, trap, dsu1, dsu2);
|
233 |
|
|
|
234 |
|
|
type exception_reg_type is record
|
235 |
|
|
ctrl : pipeline_ctrl_type;
|
236 |
|
|
result : word;
|
237 |
|
|
y : word;
|
238 |
|
|
icc : std_logic_vector( 3 downto 0);
|
239 |
|
|
annul_all : std_ulogic;
|
240 |
|
|
data : dcdtype;
|
241 |
|
|
set : std_logic_vector(DSETMSB downto 0);
|
242 |
|
|
mexc : std_ulogic;
|
243 |
|
|
dci : dc_in_type;
|
244 |
|
|
laddr : std_logic_vector(1 downto 0);
|
245 |
|
|
rstate : exception_state;
|
246 |
|
|
npc : std_logic_vector(2 downto 0);
|
247 |
|
|
intack : std_ulogic;
|
248 |
|
|
ipend : std_ulogic;
|
249 |
|
|
mac : std_ulogic;
|
250 |
|
|
debug : std_ulogic;
|
251 |
|
|
nerror : std_ulogic;
|
252 |
|
|
end record;
|
253 |
|
|
|
254 |
|
|
type dsu_registers is record
|
255 |
|
|
tt : std_logic_vector(7 downto 0);
|
256 |
|
|
err : std_ulogic;
|
257 |
|
|
tbufcnt : std_logic_vector(TBUFBITS-1 downto 0);
|
258 |
|
|
asi : std_logic_vector(7 downto 0);
|
259 |
|
|
crdy : std_logic_vector(2 downto 1); -- diag cache access ready
|
260 |
|
|
end record;
|
261 |
|
|
|
262 |
|
|
type irestart_register is record
|
263 |
|
|
addr : pctype;
|
264 |
|
|
pwd : std_ulogic;
|
265 |
|
|
end record;
|
266 |
|
|
|
267 |
|
|
type pwd_register_type is record
|
268 |
|
|
pwd : std_ulogic;
|
269 |
|
|
error : std_ulogic;
|
270 |
|
|
end record;
|
271 |
|
|
|
272 |
|
|
type special_register_type is record
|
273 |
|
|
cwp : cwptype; -- current window pointer
|
274 |
|
|
icc : std_logic_vector(3 downto 0); -- integer condition codes
|
275 |
|
|
tt : std_logic_vector(7 downto 0); -- trap type
|
276 |
|
|
tba : std_logic_vector(19 downto 0); -- trap base address
|
277 |
|
|
wim : std_logic_vector(NWIN-1 downto 0); -- window invalid mask
|
278 |
|
|
pil : std_logic_vector(3 downto 0); -- processor interrupt level
|
279 |
|
|
ec : std_ulogic; -- enable CP
|
280 |
|
|
ef : std_ulogic; -- enable FP
|
281 |
|
|
ps : std_ulogic; -- previous supervisor flag
|
282 |
|
|
s : std_ulogic; -- supervisor flag
|
283 |
|
|
et : std_ulogic; -- enable traps
|
284 |
|
|
y : word;
|
285 |
|
|
asr18 : word;
|
286 |
|
|
svt : std_ulogic; -- enable traps
|
287 |
|
|
dwt : std_ulogic; -- disable write error trap
|
288 |
|
|
end record;
|
289 |
|
|
|
290 |
|
|
type write_reg_type is record
|
291 |
|
|
s : special_register_type;
|
292 |
|
|
result : word;
|
293 |
|
|
wa : rfatype;
|
294 |
|
|
wreg : std_ulogic;
|
295 |
|
|
except : std_ulogic;
|
296 |
|
|
end record;
|
297 |
|
|
|
298 |
|
|
type registers is record
|
299 |
|
|
f : fetch_reg_type;
|
300 |
|
|
d : decode_reg_type;
|
301 |
|
|
a : regacc_reg_type;
|
302 |
|
|
e : execute_reg_type;
|
303 |
|
|
m : memory_reg_type;
|
304 |
|
|
x : exception_reg_type;
|
305 |
|
|
w : write_reg_type;
|
306 |
|
|
end record;
|
307 |
|
|
|
308 |
|
|
type exception_type is record
|
309 |
|
|
pri : std_ulogic;
|
310 |
|
|
ill : std_ulogic;
|
311 |
|
|
fpdis : std_ulogic;
|
312 |
|
|
cpdis : std_ulogic;
|
313 |
|
|
wovf : std_ulogic;
|
314 |
|
|
wunf : std_ulogic;
|
315 |
|
|
ticc : std_ulogic;
|
316 |
|
|
end record;
|
317 |
|
|
|
318 |
|
|
type watchpoint_register is record
|
319 |
|
|
addr : std_logic_vector(31 downto 2); -- watchpoint address
|
320 |
|
|
mask : std_logic_vector(31 downto 2); -- watchpoint mask
|
321 |
|
|
exec : std_ulogic; -- trap on instruction
|
322 |
|
|
load : std_ulogic; -- trap on load
|
323 |
|
|
store : std_ulogic; -- trap on store
|
324 |
|
|
end record;
|
325 |
|
|
|
326 |
|
|
type watchpoint_registers is array (0 to 3) of watchpoint_register;
|
327 |
|
|
|
328 |
|
|
constant wpr_none : watchpoint_register := (
|
329 |
|
|
zero32(31 downto 2), zero32(31 downto 2), '0', '0', '0');
|
330 |
|
|
|
331 |
|
|
function dbgexc(r : registers; dbgi : l3_debug_in_type; trap : std_ulogic; tt : std_logic_vector(7 downto 0)) return std_ulogic is
|
332 |
|
|
variable dmode : std_ulogic;
|
333 |
|
|
begin
|
334 |
|
|
dmode := '0';
|
335 |
|
|
if (not r.x.ctrl.annul and trap) = '1' then
|
336 |
|
|
if (((tt = "00" & TT_WATCH) and (dbgi.bwatch = '1')) or
|
337 |
|
|
((dbgi.bsoft = '1') and (tt = "10000001")) or
|
338 |
|
|
(dbgi.btrapa = '1') or
|
339 |
|
|
((dbgi.btrape = '1') and not ((tt(5 downto 0) = TT_PRIV) or
|
340 |
|
|
(tt(5 downto 0) = TT_FPDIS) or (tt(5 downto 0) = TT_WINOF) or
|
341 |
|
|
(tt(5 downto 0) = TT_WINUF) or (tt(5 downto 4) = "01") or (tt(7) = '1'))) or
|
342 |
|
|
(((not r.w.s.et) and dbgi.berror) = '1')) then
|
343 |
|
|
dmode := '1';
|
344 |
|
|
end if;
|
345 |
|
|
end if;
|
346 |
|
|
return(dmode);
|
347 |
|
|
end;
|
348 |
|
|
|
349 |
|
|
function dbgerr(r : registers; dbgi : l3_debug_in_type;
|
350 |
|
|
tt : std_logic_vector(7 downto 0))
|
351 |
|
|
return std_ulogic is
|
352 |
|
|
variable err : std_ulogic;
|
353 |
|
|
begin
|
354 |
|
|
err := not r.w.s.et;
|
355 |
|
|
if (((dbgi.dbreak = '1') and (tt = ("00" & TT_WATCH))) or
|
356 |
|
|
((dbgi.bsoft = '1') and (tt = ("10000001")))) then
|
357 |
|
|
err := '0';
|
358 |
|
|
end if;
|
359 |
|
|
return(err);
|
360 |
|
|
end;
|
361 |
|
|
|
362 |
|
|
procedure diagwr(r : in registers;
|
363 |
|
|
dsur : in dsu_registers;
|
364 |
|
|
ir : in irestart_register;
|
365 |
|
|
dbg : in l3_debug_in_type;
|
366 |
|
|
wpr : in watchpoint_registers;
|
367 |
|
|
s : out special_register_type;
|
368 |
|
|
vwpr : out watchpoint_registers;
|
369 |
|
|
asi : out std_logic_vector(7 downto 0);
|
370 |
|
|
pc, npc : out pctype;
|
371 |
|
|
tbufcnt : out std_logic_vector(TBUFBITS-1 downto 0);
|
372 |
|
|
wr : out std_ulogic;
|
373 |
|
|
addr : out std_logic_vector(9 downto 0);
|
374 |
|
|
data : out word;
|
375 |
|
|
fpcwr : out std_ulogic) is
|
376 |
|
|
variable i : integer range 0 to 3;
|
377 |
|
|
begin
|
378 |
|
|
s := r.w.s; pc := r.f.pc; npc := ir.addr; wr := '0';
|
379 |
|
|
vwpr := wpr; asi := dsur.asi; addr := (others => '0');
|
380 |
|
|
data := dbg.ddata;
|
381 |
|
|
tbufcnt := dsur.tbufcnt; fpcwr := '0';
|
382 |
|
|
if (dbg.dsuen and dbg.denable and dbg.dwrite) = '1' then
|
383 |
|
|
case dbg.daddr(23 downto 20) is
|
384 |
|
|
when "0001" =>
|
385 |
|
|
if (dbg.daddr(16) = '1') and TRACEBUF then -- trace buffer control reg
|
386 |
|
|
tbufcnt := dbg.ddata(TBUFBITS-1 downto 0);
|
387 |
|
|
end if;
|
388 |
|
|
when "0011" => -- IU reg file
|
389 |
|
|
if dbg.daddr(12) = '0' then
|
390 |
|
|
wr := '1';
|
391 |
|
|
addr := (others => '0');
|
392 |
|
|
addr(RFBITS-1 downto 0) := dbg.daddr(RFBITS+1 downto 2);
|
393 |
|
|
else -- FPC
|
394 |
|
|
fpcwr := '1';
|
395 |
|
|
end if;
|
396 |
|
|
when "0100" => -- IU special registers
|
397 |
|
|
case dbg.daddr(7 downto 6) is
|
398 |
|
|
when "00" => -- IU regs Y - TBUF ctrl reg
|
399 |
|
|
case dbg.daddr(5 downto 2) is
|
400 |
|
|
when "0000" => -- Y
|
401 |
|
|
s.y := dbg.ddata;
|
402 |
|
|
when "0001" => -- PSR
|
403 |
|
|
s.cwp := dbg.ddata(NWINLOG2-1 downto 0);
|
404 |
|
|
s.icc := dbg.ddata(23 downto 20);
|
405 |
|
|
s.ec := dbg.ddata(13);
|
406 |
|
|
if FPEN then s.ef := dbg.ddata(12); end if;
|
407 |
|
|
s.pil := dbg.ddata(11 downto 8);
|
408 |
|
|
s.s := dbg.ddata(7);
|
409 |
|
|
s.ps := dbg.ddata(6);
|
410 |
|
|
s.et := dbg.ddata(5);
|
411 |
|
|
when "0010" => -- WIM
|
412 |
|
|
s.wim := dbg.ddata(NWIN-1 downto 0);
|
413 |
|
|
when "0011" => -- TBR
|
414 |
|
|
s.tba := dbg.ddata(31 downto 12);
|
415 |
|
|
s.tt := dbg.ddata(11 downto 4);
|
416 |
|
|
when "0100" => -- PC
|
417 |
|
|
pc := dbg.ddata(31 downto PCLOW);
|
418 |
|
|
when "0101" => -- NPC
|
419 |
|
|
npc := dbg.ddata(31 downto PCLOW);
|
420 |
|
|
when "0110" => --FSR
|
421 |
|
|
fpcwr := '1';
|
422 |
|
|
when "0111" => --CFSR
|
423 |
|
|
when "1001" => -- ASI reg
|
424 |
|
|
asi := dbg.ddata(7 downto 0);
|
425 |
|
|
--when "1001" => -- TBUF ctrl reg
|
426 |
|
|
-- tbufcnt := dbg.ddata(TBUFBITS-1 downto 0);
|
427 |
|
|
when others =>
|
428 |
|
|
end case;
|
429 |
|
|
when "01" => -- ASR16 - ASR31
|
430 |
|
|
case dbg.daddr(5 downto 2) is
|
431 |
|
|
when "0001" => -- %ASR17
|
432 |
|
|
s.dwt := dbg.ddata(14);
|
433 |
|
|
s.svt := dbg.ddata(13);
|
434 |
|
|
when "0010" => -- %ASR18
|
435 |
|
|
if MACEN then s.asr18 := dbg.ddata; end if;
|
436 |
|
|
when "1000" => -- %ASR24 - %ASR31
|
437 |
|
|
vwpr(0).addr := dbg.ddata(31 downto 2);
|
438 |
|
|
vwpr(0).exec := dbg.ddata(0);
|
439 |
|
|
when "1001" =>
|
440 |
|
|
vwpr(0).mask := dbg.ddata(31 downto 2);
|
441 |
|
|
vwpr(0).load := dbg.ddata(1);
|
442 |
|
|
vwpr(0).store := dbg.ddata(0);
|
443 |
|
|
when "1010" =>
|
444 |
|
|
vwpr(1).addr := dbg.ddata(31 downto 2);
|
445 |
|
|
vwpr(1).exec := dbg.ddata(0);
|
446 |
|
|
when "1011" =>
|
447 |
|
|
vwpr(1).mask := dbg.ddata(31 downto 2);
|
448 |
|
|
vwpr(1).load := dbg.ddata(1);
|
449 |
|
|
vwpr(1).store := dbg.ddata(0);
|
450 |
|
|
when "1100" =>
|
451 |
|
|
vwpr(2).addr := dbg.ddata(31 downto 2);
|
452 |
|
|
vwpr(2).exec := dbg.ddata(0);
|
453 |
|
|
when "1101" =>
|
454 |
|
|
vwpr(2).mask := dbg.ddata(31 downto 2);
|
455 |
|
|
vwpr(2).load := dbg.ddata(1);
|
456 |
|
|
vwpr(2).store := dbg.ddata(0);
|
457 |
|
|
when "1110" =>
|
458 |
|
|
vwpr(3).addr := dbg.ddata(31 downto 2);
|
459 |
|
|
vwpr(3).exec := dbg.ddata(0);
|
460 |
|
|
when "1111" => --
|
461 |
|
|
vwpr(3).mask := dbg.ddata(31 downto 2);
|
462 |
|
|
vwpr(3).load := dbg.ddata(1);
|
463 |
|
|
vwpr(3).store := dbg.ddata(0);
|
464 |
|
|
when others => --
|
465 |
|
|
end case;
|
466 |
|
|
-- disabled due to bug in XST
|
467 |
|
|
-- i := conv_integer(dbg.daddr(4 downto 3));
|
468 |
|
|
-- if dbg.daddr(2) = '0' then
|
469 |
|
|
-- vwpr(i).addr := dbg.ddata(31 downto 2);
|
470 |
|
|
-- vwpr(i).exec := dbg.ddata(0);
|
471 |
|
|
-- else
|
472 |
|
|
-- vwpr(i).mask := dbg.ddata(31 downto 2);
|
473 |
|
|
-- vwpr(i).load := dbg.ddata(1);
|
474 |
|
|
-- vwpr(i).store := dbg.ddata(0);
|
475 |
|
|
-- end if;
|
476 |
|
|
when others =>
|
477 |
|
|
end case;
|
478 |
|
|
when others =>
|
479 |
|
|
end case;
|
480 |
|
|
end if;
|
481 |
|
|
end;
|
482 |
|
|
|
483 |
|
|
function asr17_gen ( r : in registers) return word is
|
484 |
|
|
variable asr17 : word;
|
485 |
|
|
variable fpu2 : integer range 0 to 3;
|
486 |
|
|
begin
|
487 |
|
|
asr17 := zero32;
|
488 |
|
|
asr17(31 downto 28) := conv_std_logic_vector(index, 4);
|
489 |
|
|
if (clk2x > 8) then
|
490 |
|
|
asr17(16 downto 15) := conv_std_logic_vector(clk2x-8, 2);
|
491 |
|
|
asr17(17) := '1';
|
492 |
|
|
elsif (clk2x > 0) then
|
493 |
|
|
asr17(16 downto 15) := conv_std_logic_vector(clk2x, 2);
|
494 |
|
|
end if;
|
495 |
|
|
asr17(14) := r.w.s.dwt;
|
496 |
|
|
if svt = 1 then asr17(13) := r.w.s.svt; end if;
|
497 |
|
|
if lddel = 2 then asr17(12) := '1'; end if;
|
498 |
|
|
if (fpu > 0) and (fpu < 8) then fpu2 := 1;
|
499 |
|
|
elsif (fpu >= 8) and (fpu < 15) then fpu2 := 3;
|
500 |
|
|
elsif fpu = 15 then fpu2 := 2;
|
501 |
|
|
else fpu2 := 0; end if;
|
502 |
|
|
asr17(11 downto 10) := conv_std_logic_vector(fpu2, 2);
|
503 |
|
|
if mac = 1 then asr17(9) := '1'; end if;
|
504 |
|
|
if v8 /= 0 then asr17(8) := '1'; end if;
|
505 |
|
|
asr17(7 downto 5) := conv_std_logic_vector(nwp, 3);
|
506 |
|
|
asr17(4 downto 0) := conv_std_logic_vector(nwin-1, 5);
|
507 |
|
|
return(asr17);
|
508 |
|
|
end;
|
509 |
|
|
|
510 |
|
|
procedure diagread(dbgi : in l3_debug_in_type;
|
511 |
|
|
r : in registers;
|
512 |
|
|
dsur : in dsu_registers;
|
513 |
|
|
ir : in irestart_register;
|
514 |
|
|
wpr : in watchpoint_registers;
|
515 |
|
|
dco : in dcache_out_type;
|
516 |
|
|
tbufo : in tracebuf_out_type;
|
517 |
|
|
data : out word) is
|
518 |
|
|
variable cwp : std_logic_vector(4 downto 0);
|
519 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
520 |
|
|
variable i : integer range 0 to 3;
|
521 |
|
|
begin
|
522 |
|
|
data := (others => '0'); cwp := (others => '0');
|
523 |
|
|
cwp(NWINLOG2-1 downto 0) := r.w.s.cwp;
|
524 |
|
|
case dbgi.daddr(22 downto 20) is
|
525 |
|
|
when "001" => -- trace buffer
|
526 |
|
|
if TRACEBUF then
|
527 |
|
|
if dbgi.daddr(16) = '1' then -- trace buffer control reg
|
528 |
|
|
if TRACEBUF then data(TBUFBITS-1 downto 0) := dsur.tbufcnt; end if;
|
529 |
|
|
else
|
530 |
|
|
case dbgi.daddr(3 downto 2) is
|
531 |
|
|
when "00" => data := tbufo.data(127 downto 96);
|
532 |
|
|
when "01" => data := tbufo.data(95 downto 64);
|
533 |
|
|
when "10" => data := tbufo.data(63 downto 32);
|
534 |
|
|
when others => data := tbufo.data(31 downto 0);
|
535 |
|
|
end case;
|
536 |
|
|
end if;
|
537 |
|
|
end if;
|
538 |
|
|
when "011" => -- IU reg file
|
539 |
|
|
if dbgi.daddr(12) = '0' then
|
540 |
|
|
data := rfo.data1(31 downto 0);
|
541 |
|
|
if (dbgi.daddr(11) = '1') and (is_fpga(fabtech) = 0) then
|
542 |
|
|
data := rfo.data2(31 downto 0);
|
543 |
|
|
end if;
|
544 |
|
|
else data := fpo.dbg.data; end if;
|
545 |
|
|
when "100" => -- IU regs
|
546 |
|
|
case dbgi.daddr(7 downto 6) is
|
547 |
|
|
when "00" => -- IU regs Y - TBUF ctrl reg
|
548 |
|
|
case dbgi.daddr(5 downto 2) is
|
549 |
|
|
when "0000" =>
|
550 |
|
|
data := r.w.s.y;
|
551 |
|
|
when "0001" =>
|
552 |
|
|
data := conv_std_logic_vector(IMPL, 4) & conv_std_logic_vector(VER, 4) &
|
553 |
|
|
r.w.s.icc & "000000" & r.w.s.ec & r.w.s.ef & r.w.s.pil &
|
554 |
|
|
r.w.s.s & r.w.s.ps & r.w.s.et & cwp;
|
555 |
|
|
when "0010" =>
|
556 |
|
|
data(NWIN-1 downto 0) := r.w.s.wim;
|
557 |
|
|
when "0011" =>
|
558 |
|
|
data := r.w.s.tba & r.w.s.tt & "0000";
|
559 |
|
|
when "0100" =>
|
560 |
|
|
data(31 downto PCLOW) := r.f.pc;
|
561 |
|
|
when "0101" =>
|
562 |
|
|
data(31 downto PCLOW) := ir.addr;
|
563 |
|
|
when "0110" => -- FSR
|
564 |
|
|
data := fpo.dbg.data;
|
565 |
|
|
when "0111" => -- CPSR
|
566 |
|
|
when "1000" => -- TT reg
|
567 |
|
|
data(12 downto 4) := dsur.err & dsur.tt;
|
568 |
|
|
when "1001" => -- ASI reg
|
569 |
|
|
data(7 downto 0) := dsur.asi;
|
570 |
|
|
when others =>
|
571 |
|
|
end case;
|
572 |
|
|
when "01" =>
|
573 |
|
|
if dbgi.daddr(5) = '0' then -- %ASR17
|
574 |
|
|
if dbgi.daddr(4 downto 2) = "001" then -- %ASR17
|
575 |
|
|
data := asr17_gen(r);
|
576 |
|
|
elsif MACEN and dbgi.daddr(4 downto 2) = "010" then -- %ASR18
|
577 |
|
|
data := r.w.s.asr18;
|
578 |
|
|
end if;
|
579 |
|
|
else -- %ASR24 - %ASR31
|
580 |
|
|
i := conv_integer(dbgi.daddr(4 downto 3)); --
|
581 |
|
|
if dbgi.daddr(2) = '0' then
|
582 |
|
|
data(31 downto 2) := wpr(i).addr;
|
583 |
|
|
data(0) := wpr(i).exec;
|
584 |
|
|
else
|
585 |
|
|
data(31 downto 2) := wpr(i).mask;
|
586 |
|
|
data(1) := wpr(i).load;
|
587 |
|
|
data(0) := wpr(i).store;
|
588 |
|
|
end if;
|
589 |
|
|
end if;
|
590 |
|
|
when others =>
|
591 |
|
|
end case;
|
592 |
|
|
when "111" =>
|
593 |
|
|
data := r.x.data(conv_integer(r.x.set));
|
594 |
|
|
when others =>
|
595 |
|
|
end case;
|
596 |
|
|
end;
|
597 |
|
|
|
598 |
|
|
|
599 |
|
|
procedure itrace(r : in registers;
|
600 |
|
|
dsur : in dsu_registers;
|
601 |
|
|
vdsu : in dsu_registers;
|
602 |
|
|
res : in word;
|
603 |
|
|
exc : in std_ulogic;
|
604 |
|
|
dbgi : in l3_debug_in_type;
|
605 |
|
|
error : in std_ulogic;
|
606 |
|
|
trap : in std_ulogic;
|
607 |
|
|
tbufcnt : out std_logic_vector(TBUFBITS-1 downto 0);
|
608 |
|
|
di : out tracebuf_in_type) is
|
609 |
|
|
variable meminst : std_ulogic;
|
610 |
|
|
begin
|
611 |
|
|
di.addr := (others => '0'); di.data := (others => '0');
|
612 |
|
|
di.enable := '0'; di.write := (others => '0');
|
613 |
|
|
tbufcnt := vdsu.tbufcnt;
|
614 |
|
|
meminst := r.x.ctrl.inst(31) and r.x.ctrl.inst(30);
|
615 |
|
|
if TRACEBUF then
|
616 |
|
|
di.addr(TBUFBITS-1 downto 0) := dsur.tbufcnt;
|
617 |
|
|
di.data(127) := '0';
|
618 |
|
|
di.data(126) := not r.x.ctrl.pv;
|
619 |
|
|
di.data(125 downto 96) := dbgi.timer(29 downto 0);
|
620 |
|
|
di.data(95 downto 64) := res;
|
621 |
|
|
di.data(63 downto 34) := r.x.ctrl.pc(31 downto 2);
|
622 |
|
|
di.data(33) := trap;
|
623 |
|
|
di.data(32) := error;
|
624 |
|
|
di.data(31 downto 0) := r.x.ctrl.inst;
|
625 |
|
|
if (dbgi.tenable = '0') or (r.x.rstate = dsu2) then
|
626 |
|
|
if ((dbgi.dsuen and dbgi.denable) = '1') and (dbgi.daddr(23 downto 20) & dbgi.daddr(16) = "00010") then
|
627 |
|
|
di.enable := '1';
|
628 |
|
|
di.addr(TBUFBITS-1 downto 0) := dbgi.daddr(TBUFBITS-1+4 downto 4);
|
629 |
|
|
if dbgi.dwrite = '1' then
|
630 |
|
|
case dbgi.daddr(3 downto 2) is
|
631 |
|
|
when "00" => di.write(3) := '1';
|
632 |
|
|
when "01" => di.write(2) := '1';
|
633 |
|
|
when "10" => di.write(1) := '1';
|
634 |
|
|
when others => di.write(0) := '1';
|
635 |
|
|
end case;
|
636 |
|
|
di.data := dbgi.ddata & dbgi.ddata & dbgi.ddata & dbgi.ddata;
|
637 |
|
|
end if;
|
638 |
|
|
end if;
|
639 |
|
|
elsif (not r.x.ctrl.annul and (r.x.ctrl.pv or meminst) and not r.x.debug) = '1' then
|
640 |
|
|
di.enable := '1'; di.write := (others => '1');
|
641 |
|
|
tbufcnt := dsur.tbufcnt + 1;
|
642 |
|
|
end if;
|
643 |
|
|
di.diag := dco.testen & "000";
|
644 |
|
|
if dco.scanen = '1' then di.enable := '0'; end if;
|
645 |
|
|
end if;
|
646 |
|
|
end;
|
647 |
|
|
|
648 |
|
|
procedure dbg_cache(holdn : in std_ulogic;
|
649 |
|
|
dbgi : in l3_debug_in_type;
|
650 |
|
|
r : in registers;
|
651 |
|
|
dsur : in dsu_registers;
|
652 |
|
|
mresult : in word;
|
653 |
|
|
dci : in dc_in_type;
|
654 |
|
|
mresult2 : out word;
|
655 |
|
|
dci2 : out dc_in_type
|
656 |
|
|
) is
|
657 |
|
|
begin
|
658 |
|
|
mresult2 := mresult; dci2 := dci; dci2.dsuen := '0';
|
659 |
|
|
if DBGUNIT then
|
660 |
|
|
if r.x.rstate = dsu2 then
|
661 |
|
|
dci2.asi := dsur.asi;
|
662 |
|
|
if (dbgi.daddr(22 downto 20) = "111") and (dbgi.dsuen = '1') then
|
663 |
|
|
dci2.dsuen := (dbgi.denable or r.m.dci.dsuen) and not dsur.crdy(2);
|
664 |
|
|
dci2.enaddr := dbgi.denable;
|
665 |
|
|
dci2.size := "10"; dci2.read := '1'; dci2.write := '0';
|
666 |
|
|
if (dbgi.denable and not r.m.dci.enaddr) = '1' then
|
667 |
|
|
mresult2 := (others => '0'); mresult2(19 downto 2) := dbgi.daddr(19 downto 2);
|
668 |
|
|
else
|
669 |
|
|
mresult2 := dbgi.ddata;
|
670 |
|
|
end if;
|
671 |
|
|
if dbgi.dwrite = '1' then
|
672 |
|
|
dci2.read := '0'; dci2.write := '1';
|
673 |
|
|
end if;
|
674 |
|
|
end if;
|
675 |
|
|
end if;
|
676 |
|
|
end if;
|
677 |
|
|
end;
|
678 |
|
|
|
679 |
|
|
procedure fpexack(r : in registers; fpexc : out std_ulogic) is
|
680 |
|
|
begin
|
681 |
|
|
fpexc := '0';
|
682 |
|
|
if FPEN then
|
683 |
|
|
if r.x.ctrl.tt = TT_FPEXC then fpexc := '1'; end if;
|
684 |
|
|
end if;
|
685 |
|
|
end;
|
686 |
|
|
|
687 |
|
|
procedure diagrdy(denable : in std_ulogic;
|
688 |
|
|
dsur : in dsu_registers;
|
689 |
|
|
dci : in dc_in_type;
|
690 |
|
|
mds : in std_ulogic;
|
691 |
|
|
ico : in icache_out_type;
|
692 |
|
|
crdy : out std_logic_vector(2 downto 1)) is
|
693 |
|
|
begin
|
694 |
|
|
crdy := dsur.crdy(1) & '0';
|
695 |
|
|
if dci.dsuen = '1' then
|
696 |
|
|
case dsur.asi(4 downto 0) is
|
697 |
|
|
when ASI_ITAG | ASI_IDATA | ASI_UINST | ASI_SINST =>
|
698 |
|
|
crdy(2) := ico.diagrdy and not dsur.crdy(2);
|
699 |
|
|
when ASI_DTAG | ASI_MMUSNOOP_DTAG | ASI_DDATA | ASI_UDATA | ASI_SDATA =>
|
700 |
|
|
crdy(1) := not denable and dci.enaddr and not dsur.crdy(1);
|
701 |
|
|
when others =>
|
702 |
|
|
crdy(2) := dci.enaddr and denable;
|
703 |
|
|
end case;
|
704 |
|
|
end if;
|
705 |
|
|
end;
|
706 |
|
|
|
707 |
|
|
|
708 |
|
|
signal r, rin : registers;
|
709 |
|
|
signal wpr, wprin : watchpoint_registers;
|
710 |
|
|
signal dsur, dsuin : dsu_registers;
|
711 |
|
|
signal ir, irin : irestart_register;
|
712 |
|
|
signal rp, rpin : pwd_register_type;
|
713 |
|
|
|
714 |
|
|
-- execute stage operations
|
715 |
|
|
|
716 |
|
|
constant EXE_AND : std_logic_vector(2 downto 0) := "000";
|
717 |
|
|
constant EXE_XOR : std_logic_vector(2 downto 0) := "001"; -- must be equal to EXE_PASS2
|
718 |
|
|
constant EXE_OR : std_logic_vector(2 downto 0) := "010";
|
719 |
|
|
constant EXE_XNOR : std_logic_vector(2 downto 0) := "011";
|
720 |
|
|
constant EXE_ANDN : std_logic_vector(2 downto 0) := "100";
|
721 |
|
|
constant EXE_ORN : std_logic_vector(2 downto 0) := "101";
|
722 |
|
|
constant EXE_DIV : std_logic_vector(2 downto 0) := "110";
|
723 |
|
|
|
724 |
|
|
constant EXE_PASS1 : std_logic_vector(2 downto 0) := "000";
|
725 |
|
|
constant EXE_PASS2 : std_logic_vector(2 downto 0) := "001";
|
726 |
|
|
constant EXE_STB : std_logic_vector(2 downto 0) := "010";
|
727 |
|
|
constant EXE_STH : std_logic_vector(2 downto 0) := "011";
|
728 |
|
|
constant EXE_ONES : std_logic_vector(2 downto 0) := "100";
|
729 |
|
|
constant EXE_RDY : std_logic_vector(2 downto 0) := "101";
|
730 |
|
|
constant EXE_SPR : std_logic_vector(2 downto 0) := "110";
|
731 |
|
|
constant EXE_LINK : std_logic_vector(2 downto 0) := "111";
|
732 |
|
|
|
733 |
|
|
constant EXE_SLL : std_logic_vector(2 downto 0) := "001";
|
734 |
|
|
constant EXE_SRL : std_logic_vector(2 downto 0) := "010";
|
735 |
|
|
constant EXE_SRA : std_logic_vector(2 downto 0) := "100";
|
736 |
|
|
|
737 |
|
|
constant EXE_NOP : std_logic_vector(2 downto 0) := "000";
|
738 |
|
|
|
739 |
|
|
-- EXE result select
|
740 |
|
|
|
741 |
|
|
constant EXE_RES_ADD : std_logic_vector(1 downto 0) := "00";
|
742 |
|
|
constant EXE_RES_SHIFT : std_logic_vector(1 downto 0) := "01";
|
743 |
|
|
constant EXE_RES_LOGIC : std_logic_vector(1 downto 0) := "10";
|
744 |
|
|
constant EXE_RES_MISC : std_logic_vector(1 downto 0) := "11";
|
745 |
|
|
|
746 |
|
|
-- Load types
|
747 |
|
|
|
748 |
|
|
constant SZBYTE : std_logic_vector(1 downto 0) := "00";
|
749 |
|
|
constant SZHALF : std_logic_vector(1 downto 0) := "01";
|
750 |
|
|
constant SZWORD : std_logic_vector(1 downto 0) := "10";
|
751 |
|
|
constant SZDBL : std_logic_vector(1 downto 0) := "11";
|
752 |
|
|
|
753 |
|
|
-- calculate register file address
|
754 |
|
|
|
755 |
|
|
procedure regaddr(cwp : std_logic_vector; reg : std_logic_vector(4 downto 0);
|
756 |
|
|
rao : out rfatype) is
|
757 |
|
|
variable ra : rfatype;
|
758 |
|
|
constant globals : std_logic_vector(RFBITS-5 downto 0) :=
|
759 |
|
|
conv_std_logic_vector(NWIN, RFBITS-4);
|
760 |
|
|
begin
|
761 |
|
|
ra := (others => '0'); ra(4 downto 0) := reg;
|
762 |
|
|
if reg(4 downto 3) = "00" then ra(RFBITS -1 downto 4) := globals;
|
763 |
|
|
else
|
764 |
|
|
ra(NWINLOG2+3 downto 4) := cwp + ra(4);
|
765 |
|
|
if ra(RFBITS-1 downto 4) = globals then
|
766 |
|
|
ra(RFBITS-1 downto 4) := (others => '0');
|
767 |
|
|
end if;
|
768 |
|
|
end if;
|
769 |
|
|
rao := ra;
|
770 |
|
|
end;
|
771 |
|
|
|
772 |
|
|
-- branch adder
|
773 |
|
|
|
774 |
|
|
function branch_address(inst : word; pc : pctype) return std_logic_vector is
|
775 |
|
|
variable baddr, caddr, tmp : pctype;
|
776 |
|
|
begin
|
777 |
|
|
caddr := (others => '0'); caddr(31 downto 2) := inst(29 downto 0);
|
778 |
|
|
caddr(31 downto 2) := caddr(31 downto 2) + pc(31 downto 2);
|
779 |
|
|
baddr := (others => '0'); baddr(31 downto 24) := (others => inst(21));
|
780 |
|
|
baddr(23 downto 2) := inst(21 downto 0);
|
781 |
|
|
baddr(31 downto 2) := baddr(31 downto 2) + pc(31 downto 2);
|
782 |
|
|
if inst(30) = '1' then tmp := caddr; else tmp := baddr; end if;
|
783 |
|
|
return(tmp);
|
784 |
|
|
end;
|
785 |
|
|
|
786 |
|
|
-- evaluate branch condition
|
787 |
|
|
|
788 |
|
|
function branch_true(icc : std_logic_vector(3 downto 0); inst : word)
|
789 |
|
|
return std_ulogic is
|
790 |
|
|
variable n, z, v, c, branch : std_ulogic;
|
791 |
|
|
begin
|
792 |
|
|
n := icc(3); z := icc(2); v := icc(1); c := icc(0);
|
793 |
|
|
case inst(27 downto 25) is
|
794 |
|
|
when "000" => branch := inst(28) xor '0'; -- bn, ba
|
795 |
|
|
when "001" => branch := inst(28) xor z; -- be, bne
|
796 |
|
|
when "010" => branch := inst(28) xor (z or (n xor v)); -- ble, bg
|
797 |
|
|
when "011" => branch := inst(28) xor (n xor v); -- bl, bge
|
798 |
|
|
when "100" => branch := inst(28) xor (c or z); -- bleu, bgu
|
799 |
|
|
when "101" => branch := inst(28) xor c; -- bcs, bcc
|
800 |
|
|
when "110" => branch := inst(28) xor n; -- bneg, bpos
|
801 |
|
|
when others => branch := inst(28) xor v; -- bvs, bvc
|
802 |
|
|
end case;
|
803 |
|
|
return(branch);
|
804 |
|
|
end;
|
805 |
|
|
|
806 |
|
|
-- detect RETT instruction in the pipeline and set the local psr.su and psr.et
|
807 |
|
|
|
808 |
|
|
procedure su_et_select(r : in registers; xc_ps, xc_s, xc_et : in std_ulogic;
|
809 |
|
|
su, et : out std_ulogic) is
|
810 |
|
|
begin
|
811 |
|
|
if ((r.a.ctrl.rett or r.e.ctrl.rett or r.m.ctrl.rett or r.x.ctrl.rett) = '1')
|
812 |
|
|
and (r.x.annul_all = '0')
|
813 |
|
|
then su := xc_ps; et := '1';
|
814 |
|
|
else su := xc_s; et := xc_et; end if;
|
815 |
|
|
end;
|
816 |
|
|
|
817 |
|
|
-- detect watchpoint trap
|
818 |
|
|
|
819 |
|
|
function wphit(r : registers; wpr : watchpoint_registers; debug : l3_debug_in_type)
|
820 |
|
|
return std_ulogic is
|
821 |
|
|
variable exc : std_ulogic;
|
822 |
|
|
begin
|
823 |
|
|
exc := '0';
|
824 |
|
|
for i in 1 to NWP loop
|
825 |
|
|
if ((wpr(i-1).exec and r.a.ctrl.pv and not r.a.ctrl.annul) = '1') then
|
826 |
|
|
if (((wpr(i-1).addr xor r.a.ctrl.pc(31 downto 2)) and wpr(i-1).mask) = Zero32(31 downto 2)) then
|
827 |
|
|
exc := '1';
|
828 |
|
|
end if;
|
829 |
|
|
end if;
|
830 |
|
|
end loop;
|
831 |
|
|
|
832 |
|
|
if DBGUNIT then
|
833 |
|
|
if (debug.dsuen and not r.a.ctrl.annul) = '1' then
|
834 |
|
|
exc := exc or (r.a.ctrl.pv and ((debug.dbreak and debug.bwatch) or r.a.step));
|
835 |
|
|
end if;
|
836 |
|
|
end if;
|
837 |
|
|
return(exc);
|
838 |
|
|
end;
|
839 |
|
|
|
840 |
|
|
-- 32-bit shifter
|
841 |
|
|
|
842 |
|
|
function shift3(r : registers; aluin1, aluin2 : word) return word is
|
843 |
|
|
variable shiftin : unsigned(63 downto 0);
|
844 |
|
|
variable shiftout : unsigned(63 downto 0);
|
845 |
|
|
variable cnt : natural range 0 to 31;
|
846 |
|
|
begin
|
847 |
|
|
|
848 |
|
|
cnt := conv_integer(r.e.shcnt);
|
849 |
|
|
if r.e.shleft = '1' then
|
850 |
|
|
shiftin(30 downto 0) := (others => '0');
|
851 |
|
|
shiftin(63 downto 31) := '0' & unsigned(aluin1);
|
852 |
|
|
else
|
853 |
|
|
shiftin(63 downto 32) := (others => r.e.sari);
|
854 |
|
|
shiftin(31 downto 0) := unsigned(aluin1);
|
855 |
|
|
end if;
|
856 |
|
|
shiftout := SHIFT_RIGHT(shiftin, cnt);
|
857 |
|
|
return(std_logic_vector(shiftout(31 downto 0)));
|
858 |
|
|
|
859 |
|
|
end;
|
860 |
|
|
|
861 |
|
|
function shift2(r : registers; aluin1, aluin2 : word) return word is
|
862 |
|
|
variable ushiftin : unsigned(31 downto 0);
|
863 |
|
|
variable sshiftin : signed(32 downto 0);
|
864 |
|
|
variable cnt : natural range 0 to 31;
|
865 |
|
|
begin
|
866 |
|
|
|
867 |
|
|
cnt := conv_integer(r.e.shcnt);
|
868 |
|
|
ushiftin := unsigned(aluin1);
|
869 |
|
|
sshiftin := signed('0' & aluin1);
|
870 |
|
|
if r.e.shleft = '1' then
|
871 |
|
|
return(std_logic_vector(SHIFT_LEFT(ushiftin, cnt)));
|
872 |
|
|
else
|
873 |
|
|
if r.e.sari = '1' then sshiftin(32) := aluin1(31); end if;
|
874 |
|
|
sshiftin := SHIFT_RIGHT(sshiftin, cnt);
|
875 |
|
|
return(std_logic_vector(sshiftin(31 downto 0)));
|
876 |
|
|
-- else
|
877 |
|
|
-- ushiftin := SHIFT_RIGHT(ushiftin, cnt);
|
878 |
|
|
-- return(std_logic_vector(ushiftin));
|
879 |
|
|
-- end if;
|
880 |
|
|
end if;
|
881 |
|
|
|
882 |
|
|
end;
|
883 |
|
|
|
884 |
|
|
function shift(r : registers; aluin1, aluin2 : word;
|
885 |
|
|
shiftcnt : std_logic_vector(4 downto 0); sari : std_ulogic ) return word is
|
886 |
|
|
variable shiftin : std_logic_vector(63 downto 0);
|
887 |
|
|
begin
|
888 |
|
|
shiftin := zero32 & aluin1;
|
889 |
|
|
if r.e.shleft = '1' then
|
890 |
|
|
shiftin(31 downto 0) := zero32; shiftin(63 downto 31) := '0' & aluin1;
|
891 |
|
|
else shiftin(63 downto 32) := (others => sari); end if;
|
892 |
|
|
if shiftcnt (4) = '1' then shiftin(47 downto 0) := shiftin(63 downto 16); end if;
|
893 |
|
|
if shiftcnt (3) = '1' then shiftin(39 downto 0) := shiftin(47 downto 8); end if;
|
894 |
|
|
if shiftcnt (2) = '1' then shiftin(35 downto 0) := shiftin(39 downto 4); end if;
|
895 |
|
|
if shiftcnt (1) = '1' then shiftin(33 downto 0) := shiftin(35 downto 2); end if;
|
896 |
|
|
if shiftcnt (0) = '1' then shiftin(31 downto 0) := shiftin(32 downto 1); end if;
|
897 |
|
|
return(shiftin(31 downto 0));
|
898 |
|
|
end;
|
899 |
|
|
|
900 |
|
|
-- Check for illegal and privileged instructions
|
901 |
|
|
|
902 |
|
|
procedure exception_detect(r : registers; wpr : watchpoint_registers; dbgi : l3_debug_in_type;
|
903 |
|
|
trapin : in std_ulogic; ttin : in std_logic_vector(5 downto 0);
|
904 |
|
|
trap : out std_ulogic; tt : out std_logic_vector(5 downto 0)) is
|
905 |
|
|
variable illegal_inst, privileged_inst : std_ulogic;
|
906 |
|
|
variable cp_disabled, fp_disabled, fpop : std_ulogic;
|
907 |
|
|
variable op : std_logic_vector(1 downto 0);
|
908 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
909 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
910 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
911 |
|
|
variable inst : word;
|
912 |
|
|
variable wph : std_ulogic;
|
913 |
|
|
begin
|
914 |
|
|
inst := r.a.ctrl.inst; trap := trapin; tt := ttin;
|
915 |
|
|
if r.a.ctrl.annul = '0' then
|
916 |
|
|
op := inst(31 downto 30); op2 := inst(24 downto 22);
|
917 |
|
|
op3 := inst(24 downto 19); rd := inst(29 downto 25);
|
918 |
|
|
illegal_inst := '0'; privileged_inst := '0'; cp_disabled := '0';
|
919 |
|
|
fp_disabled := '0'; fpop := '0';
|
920 |
|
|
case op is
|
921 |
|
|
when CALL => null;
|
922 |
|
|
when FMT2 =>
|
923 |
|
|
case op2 is
|
924 |
|
|
when SETHI | BICC => null;
|
925 |
|
|
when FBFCC =>
|
926 |
|
|
if FPEN then fp_disabled := not r.w.s.ef; else fp_disabled := '1'; end if;
|
927 |
|
|
when CBCCC =>
|
928 |
|
|
if (not CPEN) or (r.w.s.ec = '0') then cp_disabled := '1'; end if;
|
929 |
|
|
when others => illegal_inst := '1';
|
930 |
|
|
end case;
|
931 |
|
|
when FMT3 =>
|
932 |
|
|
case op3 is
|
933 |
|
|
when IAND | ANDCC | ANDN | ANDNCC | IOR | ORCC | ORN | ORNCC | IXOR |
|
934 |
|
|
XORCC | IXNOR | XNORCC | ISLL | ISRL | ISRA | MULSCC | IADD | ADDX |
|
935 |
|
|
ADDCC | ADDXCC | ISUB | SUBX | SUBCC | SUBXCC | FLUSH | JMPL | TICC |
|
936 |
|
|
SAVE | RESTORE | RDY => null;
|
937 |
|
|
when TADDCC | TADDCCTV | TSUBCC | TSUBCCTV =>
|
938 |
|
|
if notag = 1 then illegal_inst := '1'; end if;
|
939 |
|
|
when UMAC | SMAC =>
|
940 |
|
|
if not MACEN then illegal_inst := '1'; end if;
|
941 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
942 |
|
|
if not MULEN then illegal_inst := '1'; end if;
|
943 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
944 |
|
|
if not DIVEN then illegal_inst := '1'; end if;
|
945 |
|
|
when RETT => illegal_inst := r.a.et; privileged_inst := not r.a.su;
|
946 |
|
|
when RDPSR | RDTBR | RDWIM => privileged_inst := not r.a.su;
|
947 |
|
|
when WRY => null;
|
948 |
|
|
when WRPSR =>
|
949 |
|
|
privileged_inst := not r.a.su;
|
950 |
|
|
when WRWIM | WRTBR => privileged_inst := not r.a.su;
|
951 |
|
|
when FPOP1 | FPOP2 =>
|
952 |
|
|
if FPEN then fp_disabled := not r.w.s.ef; fpop := '1';
|
953 |
|
|
else fp_disabled := '1'; fpop := '0'; end if;
|
954 |
|
|
when CPOP1 | CPOP2 =>
|
955 |
|
|
if (not CPEN) or (r.w.s.ec = '0') then cp_disabled := '1'; end if;
|
956 |
|
|
when others => illegal_inst := '1';
|
957 |
|
|
end case;
|
958 |
|
|
when others => -- LDST
|
959 |
|
|
case op3 is
|
960 |
|
|
when LDD | ISTD => illegal_inst := rd(0); -- trap if odd destination register
|
961 |
|
|
when LD | LDUB | LDSTUB | LDUH | LDSB | LDSH | ST | STB | STH | SWAP =>
|
962 |
|
|
null;
|
963 |
|
|
when LDDA | STDA =>
|
964 |
|
|
illegal_inst := inst(13) or rd(0); privileged_inst := not r.a.su;
|
965 |
|
|
when LDA | LDUBA| LDSTUBA | LDUHA | LDSBA | LDSHA | STA | STBA | STHA |
|
966 |
|
|
SWAPA =>
|
967 |
|
|
illegal_inst := inst(13); privileged_inst := not r.a.su;
|
968 |
|
|
when LDDF | STDF | LDF | LDFSR | STF | STFSR =>
|
969 |
|
|
if FPEN then fp_disabled := not r.w.s.ef;
|
970 |
|
|
else fp_disabled := '1'; end if;
|
971 |
|
|
when STDFQ =>
|
972 |
|
|
privileged_inst := not r.a.su;
|
973 |
|
|
if (not FPEN) or (r.w.s.ef = '0') then fp_disabled := '1'; end if;
|
974 |
|
|
when STDCQ =>
|
975 |
|
|
privileged_inst := not r.a.su;
|
976 |
|
|
if (not CPEN) or (r.w.s.ec = '0') then cp_disabled := '1'; end if;
|
977 |
|
|
when LDC | LDCSR | LDDC | STC | STCSR | STDC =>
|
978 |
|
|
if (not CPEN) or (r.w.s.ec = '0') then cp_disabled := '1'; end if;
|
979 |
|
|
when others => illegal_inst := '1';
|
980 |
|
|
end case;
|
981 |
|
|
end case;
|
982 |
|
|
|
983 |
|
|
wph := wphit(r, wpr, dbgi);
|
984 |
|
|
|
985 |
|
|
trap := '1';
|
986 |
|
|
if r.a.ctrl.trap = '1' then tt := TT_IAEX;
|
987 |
|
|
elsif privileged_inst = '1' then tt := TT_PRIV;
|
988 |
|
|
elsif illegal_inst = '1' then tt := TT_IINST;
|
989 |
|
|
elsif fp_disabled = '1' then tt := TT_FPDIS;
|
990 |
|
|
elsif cp_disabled = '1' then tt := TT_CPDIS;
|
991 |
|
|
elsif wph = '1' then tt := TT_WATCH;
|
992 |
|
|
elsif r.a.wovf= '1' then tt := TT_WINOF;
|
993 |
|
|
elsif r.a.wunf= '1' then tt := TT_WINUF;
|
994 |
|
|
elsif r.a.ticc= '1' then tt := TT_TICC;
|
995 |
|
|
else trap := '0'; tt:= (others => '0'); end if;
|
996 |
|
|
end if;
|
997 |
|
|
end;
|
998 |
|
|
|
999 |
|
|
-- instructions that write the condition codes (psr.icc)
|
1000 |
|
|
|
1001 |
|
|
procedure wicc_y_gen(inst : word; wicc, wy : out std_ulogic) is
|
1002 |
|
|
begin
|
1003 |
|
|
wicc := '0'; wy := '0';
|
1004 |
|
|
if inst(31 downto 30) = FMT3 then
|
1005 |
|
|
case inst(24 downto 19) is
|
1006 |
|
|
when SUBCC | TSUBCC | TSUBCCTV | ADDCC | ANDCC | ORCC | XORCC | ANDNCC |
|
1007 |
|
|
ORNCC | XNORCC | TADDCC | TADDCCTV | ADDXCC | SUBXCC | WRPSR =>
|
1008 |
|
|
wicc := '1';
|
1009 |
|
|
when WRY =>
|
1010 |
|
|
if r.d.inst(conv_integer(r.d.set))(29 downto 25) = "00000" then wy := '1'; end if;
|
1011 |
|
|
when MULSCC =>
|
1012 |
|
|
wicc := '1'; wy := '1';
|
1013 |
|
|
when UMAC | SMAC =>
|
1014 |
|
|
if MACEN then wy := '1'; end if;
|
1015 |
|
|
when UMULCC | SMULCC =>
|
1016 |
|
|
if MULEN and (((mulo.nready = '1') and (r.d.cnt /= "00")) or (MULTYPE /= 0)) then
|
1017 |
|
|
wicc := '1'; wy := '1';
|
1018 |
|
|
end if;
|
1019 |
|
|
when UMUL | SMUL =>
|
1020 |
|
|
if MULEN and (((mulo.nready = '1') and (r.d.cnt /= "00")) or (MULTYPE /= 0)) then
|
1021 |
|
|
wy := '1';
|
1022 |
|
|
end if;
|
1023 |
|
|
when UDIVCC | SDIVCC =>
|
1024 |
|
|
if DIVEN and (divo.nready = '1') and (r.d.cnt /= "00") then
|
1025 |
|
|
wicc := '1';
|
1026 |
|
|
end if;
|
1027 |
|
|
when others =>
|
1028 |
|
|
end case;
|
1029 |
|
|
end if;
|
1030 |
|
|
end;
|
1031 |
|
|
|
1032 |
|
|
-- select cwp
|
1033 |
|
|
|
1034 |
|
|
procedure cwp_gen(r, v : registers; annul, wcwp : std_ulogic; ncwp : cwptype;
|
1035 |
|
|
cwp : out cwptype) is
|
1036 |
|
|
begin
|
1037 |
|
|
if (r.x.rstate = trap) or (r.x.rstate = dsu2) or (rstn = '0') then cwp := v.w.s.cwp;
|
1038 |
|
|
elsif (wcwp = '1') and (annul = '0') then cwp := ncwp;
|
1039 |
|
|
elsif r.m.wcwp = '1' then cwp := r.m.result(NWINLOG2-1 downto 0);
|
1040 |
|
|
else cwp := r.d.cwp; end if;
|
1041 |
|
|
end;
|
1042 |
|
|
|
1043 |
|
|
-- generate wcwp in ex stage
|
1044 |
|
|
|
1045 |
|
|
procedure cwp_ex(r : in registers; wcwp : out std_ulogic) is
|
1046 |
|
|
begin
|
1047 |
|
|
if (r.e.ctrl.inst(31 downto 30) = FMT3) and
|
1048 |
|
|
(r.e.ctrl.inst(24 downto 19) = WRPSR)
|
1049 |
|
|
then wcwp := not r.e.ctrl.annul; else wcwp := '0'; end if;
|
1050 |
|
|
end;
|
1051 |
|
|
|
1052 |
|
|
-- generate next cwp & window under- and overflow traps
|
1053 |
|
|
|
1054 |
|
|
procedure cwp_ctrl(r : in registers; xc_wim : in std_logic_vector(NWIN-1 downto 0);
|
1055 |
|
|
inst : word; de_cwp : out cwptype; wovf_exc, wunf_exc, wcwp : out std_ulogic) is
|
1056 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1057 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1058 |
|
|
variable wim : word;
|
1059 |
|
|
variable ncwp : cwptype;
|
1060 |
|
|
begin
|
1061 |
|
|
op := inst(31 downto 30); op3 := inst(24 downto 19);
|
1062 |
|
|
wovf_exc := '0'; wunf_exc := '0'; wim := (others => '0');
|
1063 |
|
|
wim(NWIN-1 downto 0) := xc_wim; ncwp := r.d.cwp; wcwp := '0';
|
1064 |
|
|
|
1065 |
|
|
if (op = FMT3) and ((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE)) then
|
1066 |
|
|
wcwp := '1';
|
1067 |
|
|
if (op3 = SAVE) then
|
1068 |
|
|
if (not CWPOPT) and (r.d.cwp = CWPMIN) then ncwp := CWPMAX;
|
1069 |
|
|
else ncwp := r.d.cwp - 1 ; end if;
|
1070 |
|
|
else
|
1071 |
|
|
if (not CWPOPT) and (r.d.cwp = CWPMAX) then ncwp := CWPMIN;
|
1072 |
|
|
else ncwp := r.d.cwp + 1; end if;
|
1073 |
|
|
end if;
|
1074 |
|
|
if wim(conv_integer(ncwp)) = '1' then
|
1075 |
|
|
if op3 = SAVE then wovf_exc := '1'; else wunf_exc := '1'; end if;
|
1076 |
|
|
end if;
|
1077 |
|
|
end if;
|
1078 |
|
|
de_cwp := ncwp;
|
1079 |
|
|
end;
|
1080 |
|
|
|
1081 |
|
|
-- generate register read address 1
|
1082 |
|
|
|
1083 |
|
|
procedure rs1_gen(r : registers; inst : word; rs1 : out std_logic_vector(4 downto 0);
|
1084 |
|
|
rs1mod : out std_ulogic) is
|
1085 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1086 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1087 |
|
|
begin
|
1088 |
|
|
op := inst(31 downto 30); op3 := inst(24 downto 19);
|
1089 |
|
|
rs1 := inst(18 downto 14); rs1mod := '0';
|
1090 |
|
|
if (op = LDST) then
|
1091 |
|
|
if ((r.d.cnt = "01") and ((op3(2) and not op3(3)) = '1')) or
|
1092 |
|
|
(r.d.cnt = "10")
|
1093 |
|
|
then rs1mod := '1'; rs1 := inst(29 downto 25); end if;
|
1094 |
|
|
if ((r.d.cnt = "10") and (op3(3 downto 0) = "0111")) then
|
1095 |
|
|
rs1(0) := '1';
|
1096 |
|
|
end if;
|
1097 |
|
|
end if;
|
1098 |
|
|
end;
|
1099 |
|
|
|
1100 |
|
|
-- load/icc interlock detection
|
1101 |
|
|
|
1102 |
|
|
procedure lock_gen(r : registers; rs2, rd : std_logic_vector(4 downto 0);
|
1103 |
|
|
rfa1, rfa2, rfrd : rfatype; inst : word; fpc_lock, mulinsn, divinsn : std_ulogic;
|
1104 |
|
|
lldcheck1, lldcheck2, lldlock, lldchkra, lldchkex : out std_ulogic) is
|
1105 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1106 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1107 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1108 |
|
|
variable cond : std_logic_vector(3 downto 0);
|
1109 |
|
|
variable rs1 : std_logic_vector(4 downto 0);
|
1110 |
|
|
variable i, ldcheck1, ldcheck2, ldchkra, ldchkex, ldcheck3 : std_ulogic;
|
1111 |
|
|
variable ldlock, icc_check, bicc_hold, chkmul, y_check : std_ulogic;
|
1112 |
|
|
variable lddlock : boolean;
|
1113 |
|
|
begin
|
1114 |
|
|
op := inst(31 downto 30); op3 := inst(24 downto 19);
|
1115 |
|
|
op2 := inst(24 downto 22); cond := inst(28 downto 25);
|
1116 |
|
|
rs1 := inst(18 downto 14); lddlock := false; i := inst(13);
|
1117 |
|
|
ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0';
|
1118 |
|
|
ldchkra := '1'; ldchkex := '1'; icc_check := '0'; bicc_hold := '0';
|
1119 |
|
|
y_check := '0';
|
1120 |
|
|
|
1121 |
|
|
if (r.d.annul = '0') then
|
1122 |
|
|
case op is
|
1123 |
|
|
when FMT2 =>
|
1124 |
|
|
if (op2 = BICC) and (cond(2 downto 0) /= "000") then
|
1125 |
|
|
icc_check := '1';
|
1126 |
|
|
end if;
|
1127 |
|
|
when FMT3 =>
|
1128 |
|
|
ldcheck1 := '1'; ldcheck2 := not i;
|
1129 |
|
|
case op3 is
|
1130 |
|
|
when TICC =>
|
1131 |
|
|
if (cond(2 downto 0) /= "000") then icc_check := '1'; end if;
|
1132 |
|
|
when RDY =>
|
1133 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
1134 |
|
|
if MACPIPE then y_check := '1'; end if;
|
1135 |
|
|
when RDWIM | RDTBR =>
|
1136 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
1137 |
|
|
when RDPSR =>
|
1138 |
|
|
ldcheck1 := '0'; ldcheck2 := '0'; icc_check := '1';
|
1139 |
|
|
if MULEN then icc_check := '1'; end if;
|
1140 |
|
|
-- when ADDX | ADDXCC | SUBX | SUBXCC =>
|
1141 |
|
|
-- if MULEN then icc_check := '1'; end if;
|
1142 |
|
|
when SDIV | SDIVCC | UDIV | UDIVCC =>
|
1143 |
|
|
if DIVEN then y_check := '1'; end if;
|
1144 |
|
|
when FPOP1 | FPOP2 => ldcheck1:= '0'; ldcheck2 := '0';
|
1145 |
|
|
when others =>
|
1146 |
|
|
end case;
|
1147 |
|
|
when LDST =>
|
1148 |
|
|
ldcheck1 := '1'; ldchkra := '0';
|
1149 |
|
|
case r.d.cnt is
|
1150 |
|
|
when "00" =>
|
1151 |
|
|
if (lddel = 2) and (op3(2) = '1') then ldcheck3 := '1'; end if;
|
1152 |
|
|
ldcheck2 := not i; ldchkra := '1';
|
1153 |
|
|
when "01" => ldcheck2 := not i;
|
1154 |
|
|
when others => ldchkex := '0';
|
1155 |
|
|
end case;
|
1156 |
|
|
if (op3(2 downto 0) = "011") then lddlock := true; end if;
|
1157 |
|
|
when others => null;
|
1158 |
|
|
end case;
|
1159 |
|
|
end if;
|
1160 |
|
|
|
1161 |
|
|
if MULEN or DIVEN then
|
1162 |
|
|
chkmul := mulinsn;
|
1163 |
|
|
bicc_hold := bicc_hold or (icc_check and r.m.ctrl.wicc and (r.m.ctrl.cnt(0) or r.m.mul));
|
1164 |
|
|
else chkmul := '0'; end if;
|
1165 |
|
|
if DIVEN then
|
1166 |
|
|
bicc_hold := bicc_hold or (y_check and (r.a.ctrl.wy or r.e.ctrl.wy));
|
1167 |
|
|
chkmul := chkmul or divinsn;
|
1168 |
|
|
end if;
|
1169 |
|
|
|
1170 |
|
|
bicc_hold := bicc_hold or (icc_check and (r.a.ctrl.wicc or r.e.ctrl.wicc));
|
1171 |
|
|
|
1172 |
|
|
if (((r.a.ctrl.ld or chkmul) and r.a.ctrl.wreg and ldchkra) = '1') and
|
1173 |
|
|
(((ldcheck1 = '1') and (r.a.ctrl.rd = rfa1)) or
|
1174 |
|
|
((ldcheck2 = '1') and (r.a.ctrl.rd = rfa2)) or
|
1175 |
|
|
((ldcheck3 = '1') and (r.a.ctrl.rd = rfrd)))
|
1176 |
|
|
then ldlock := '1'; end if;
|
1177 |
|
|
|
1178 |
|
|
if (((r.e.ctrl.ld or r.e.mac) and r.e.ctrl.wreg and ldchkex) = '1') and
|
1179 |
|
|
((lddel = 2) or (MACPIPE and (r.e.mac = '1')) or ((MULTYPE = 3) and (r.e.mul = '1'))) and
|
1180 |
|
|
(((ldcheck1 = '1') and (r.e.ctrl.rd = rfa1)) or
|
1181 |
|
|
((ldcheck2 = '1') and (r.e.ctrl.rd = rfa2)))
|
1182 |
|
|
then ldlock := '1'; end if;
|
1183 |
|
|
|
1184 |
|
|
ldlock := ldlock or bicc_hold or fpc_lock;
|
1185 |
|
|
|
1186 |
|
|
lldcheck1 := ldcheck1; lldcheck2:= ldcheck2; lldlock := ldlock;
|
1187 |
|
|
lldchkra := ldchkra; lldchkex := ldchkex;
|
1188 |
|
|
end;
|
1189 |
|
|
|
1190 |
|
|
procedure fpbranch(inst : in word; fcc : in std_logic_vector(1 downto 0);
|
1191 |
|
|
branch : out std_ulogic) is
|
1192 |
|
|
variable cond : std_logic_vector(3 downto 0);
|
1193 |
|
|
variable fbres : std_ulogic;
|
1194 |
|
|
begin
|
1195 |
|
|
cond := inst(28 downto 25);
|
1196 |
|
|
case cond(2 downto 0) is
|
1197 |
|
|
when "000" => fbres := '0'; -- fba, fbn
|
1198 |
|
|
when "001" => fbres := fcc(1) or fcc(0);
|
1199 |
|
|
when "010" => fbres := fcc(1) xor fcc(0);
|
1200 |
|
|
when "011" => fbres := fcc(0);
|
1201 |
|
|
when "100" => fbres := (not fcc(1)) and fcc(0);
|
1202 |
|
|
when "101" => fbres := fcc(1);
|
1203 |
|
|
when "110" => fbres := fcc(1) and not fcc(0);
|
1204 |
|
|
when others => fbres := fcc(1) and fcc(0);
|
1205 |
|
|
end case;
|
1206 |
|
|
branch := cond(3) xor fbres;
|
1207 |
|
|
end;
|
1208 |
|
|
|
1209 |
|
|
-- PC generation
|
1210 |
|
|
|
1211 |
|
|
procedure ic_ctrl(r : registers; inst : word; annul_all, ldlock, branch_true,
|
1212 |
|
|
fbranch_true, cbranch_true, fccv, cccv : in std_ulogic;
|
1213 |
|
|
cnt : out std_logic_vector(1 downto 0);
|
1214 |
|
|
de_pc : out pctype; de_branch, ctrl_annul, de_annul, jmpl_inst, inull,
|
1215 |
|
|
de_pv, ctrl_pv, de_hold_pc, ticc_exception, rett_inst, mulstart,
|
1216 |
|
|
divstart : out std_ulogic) is
|
1217 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1218 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1219 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1220 |
|
|
variable cond : std_logic_vector(3 downto 0);
|
1221 |
|
|
variable hold_pc, annul_current, annul_next, branch, annul, pv : std_ulogic;
|
1222 |
|
|
variable de_jmpl : std_ulogic;
|
1223 |
|
|
begin
|
1224 |
|
|
branch := '0'; annul_next := '0'; annul_current := '0'; pv := '1';
|
1225 |
|
|
hold_pc := '0'; ticc_exception := '0'; rett_inst := '0';
|
1226 |
|
|
op := inst(31 downto 30); op3 := inst(24 downto 19);
|
1227 |
|
|
op2 := inst(24 downto 22); cond := inst(28 downto 25);
|
1228 |
|
|
annul := inst(29); de_jmpl := '0'; cnt := "00";
|
1229 |
|
|
mulstart := '0'; divstart := '0';
|
1230 |
|
|
if r.d.annul = '0' then
|
1231 |
|
|
case inst(31 downto 30) is
|
1232 |
|
|
when CALL =>
|
1233 |
|
|
branch := '1';
|
1234 |
|
|
if r.d.inull = '1' then
|
1235 |
|
|
hold_pc := '1'; annul_current := '1';
|
1236 |
|
|
end if;
|
1237 |
|
|
when FMT2 =>
|
1238 |
|
|
if (op2 = BICC) or (FPEN and (op2 = FBFCC)) or (CPEN and (op2 = CBCCC)) then
|
1239 |
|
|
if (FPEN and (op2 = FBFCC)) then
|
1240 |
|
|
branch := fbranch_true;
|
1241 |
|
|
if fccv /= '1' then hold_pc := '1'; annul_current := '1'; end if;
|
1242 |
|
|
elsif (CPEN and (op2 = CBCCC)) then
|
1243 |
|
|
branch := cbranch_true;
|
1244 |
|
|
if cccv /= '1' then hold_pc := '1'; annul_current := '1'; end if;
|
1245 |
|
|
else branch := branch_true; end if;
|
1246 |
|
|
if hold_pc = '0' then
|
1247 |
|
|
if (branch = '1') then
|
1248 |
|
|
if (cond = BA) and (annul = '1') then annul_next := '1'; end if;
|
1249 |
|
|
else annul_next := annul; end if;
|
1250 |
|
|
if r.d.inull = '1' then -- contention with JMPL
|
1251 |
|
|
hold_pc := '1'; annul_current := '1'; annul_next := '0';
|
1252 |
|
|
end if;
|
1253 |
|
|
end if;
|
1254 |
|
|
end if;
|
1255 |
|
|
when FMT3 =>
|
1256 |
|
|
case op3 is
|
1257 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
1258 |
|
|
if MULEN and (MULTYPE /= 0) then mulstart := '1'; end if;
|
1259 |
|
|
if MULEN and (MULTYPE = 0) then
|
1260 |
|
|
case r.d.cnt is
|
1261 |
|
|
when "00" =>
|
1262 |
|
|
cnt := "01"; hold_pc := '1'; pv := '0'; mulstart := '1';
|
1263 |
|
|
when "01" =>
|
1264 |
|
|
if mulo.nready = '1' then cnt := "00";
|
1265 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
1266 |
|
|
when others => null;
|
1267 |
|
|
end case;
|
1268 |
|
|
end if;
|
1269 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
1270 |
|
|
if DIVEN then
|
1271 |
|
|
case r.d.cnt is
|
1272 |
|
|
when "00" =>
|
1273 |
|
|
cnt := "01"; hold_pc := '1'; pv := '0';
|
1274 |
|
|
divstart := '1';
|
1275 |
|
|
when "01" =>
|
1276 |
|
|
if divo.nready = '1' then cnt := "00";
|
1277 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
1278 |
|
|
when others => null;
|
1279 |
|
|
end case;
|
1280 |
|
|
end if;
|
1281 |
|
|
when TICC =>
|
1282 |
|
|
if branch_true = '1' then ticc_exception := '1'; end if;
|
1283 |
|
|
when RETT =>
|
1284 |
|
|
rett_inst := '1'; --su := sregs.ps;
|
1285 |
|
|
when JMPL =>
|
1286 |
|
|
de_jmpl := '1';
|
1287 |
|
|
when WRY =>
|
1288 |
|
|
if PWRD1 then
|
1289 |
|
|
if inst(29 downto 25) = "10011" then -- %ASR19
|
1290 |
|
|
case r.d.cnt is
|
1291 |
|
|
when "00" =>
|
1292 |
|
|
pv := '0'; cnt := "00"; hold_pc := '1';
|
1293 |
|
|
if r.x.ipend = '1' then cnt := "01"; end if;
|
1294 |
|
|
when "01" =>
|
1295 |
|
|
cnt := "00";
|
1296 |
|
|
when others =>
|
1297 |
|
|
end case;
|
1298 |
|
|
end if;
|
1299 |
|
|
end if;
|
1300 |
|
|
when others => null;
|
1301 |
|
|
end case;
|
1302 |
|
|
when others => -- LDST
|
1303 |
|
|
case r.d.cnt is
|
1304 |
|
|
when "00" =>
|
1305 |
|
|
if (op3(2) = '1') or (op3(1 downto 0) = "11") then -- ST/LDST/SWAP/LDD
|
1306 |
|
|
cnt := "01"; hold_pc := '1'; pv := '0';
|
1307 |
|
|
end if;
|
1308 |
|
|
when "01" =>
|
1309 |
|
|
if (op3(2 downto 0) = "111") or (op3(3 downto 0) = "1101") or
|
1310 |
|
|
((CPEN or FPEN) and ((op3(5) & op3(2 downto 0)) = "1110"))
|
1311 |
|
|
then -- LDD/STD/LDSTUB/SWAP
|
1312 |
|
|
cnt := "10"; pv := '0'; hold_pc := '1';
|
1313 |
|
|
else
|
1314 |
|
|
cnt := "00";
|
1315 |
|
|
end if;
|
1316 |
|
|
when "10" =>
|
1317 |
|
|
cnt := "00";
|
1318 |
|
|
when others => null;
|
1319 |
|
|
end case;
|
1320 |
|
|
end case;
|
1321 |
|
|
end if;
|
1322 |
|
|
|
1323 |
|
|
if ldlock = '1' then
|
1324 |
|
|
cnt := r.d.cnt; annul_next := '0'; pv := '1';
|
1325 |
|
|
end if;
|
1326 |
|
|
hold_pc := (hold_pc or ldlock) and not annul_all;
|
1327 |
|
|
|
1328 |
|
|
if hold_pc = '1' then de_pc := r.d.pc; else de_pc := r.f.pc; end if;
|
1329 |
|
|
|
1330 |
|
|
annul_current := (annul_current or ldlock or annul_all);
|
1331 |
|
|
ctrl_annul := r.d.annul or annul_all or annul_current;
|
1332 |
|
|
pv := pv and not ((r.d.inull and not hold_pc) or annul_all);
|
1333 |
|
|
jmpl_inst := de_jmpl and not annul_current;
|
1334 |
|
|
annul_next := (r.d.inull and not hold_pc) or annul_next or annul_all;
|
1335 |
|
|
if (annul_next = '1') or (rstn = '0') then
|
1336 |
|
|
cnt := (others => '0');
|
1337 |
|
|
end if;
|
1338 |
|
|
|
1339 |
|
|
de_hold_pc := hold_pc; de_branch := branch; de_annul := annul_next;
|
1340 |
|
|
de_pv := pv; ctrl_pv := r.d.pv and
|
1341 |
|
|
not ((r.d.annul and not r.d.pv) or annul_all or annul_current);
|
1342 |
|
|
inull := (not rstn) or r.d.inull or hold_pc or annul_all;
|
1343 |
|
|
|
1344 |
|
|
end;
|
1345 |
|
|
|
1346 |
|
|
-- register write address generation
|
1347 |
|
|
|
1348 |
|
|
procedure rd_gen(r : registers; inst : word; wreg, ld : out std_ulogic;
|
1349 |
|
|
rdo : out std_logic_vector(4 downto 0)) is
|
1350 |
|
|
variable write_reg : std_ulogic;
|
1351 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1352 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1353 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1354 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
1355 |
|
|
begin
|
1356 |
|
|
|
1357 |
|
|
op := inst(31 downto 30);
|
1358 |
|
|
op2 := inst(24 downto 22);
|
1359 |
|
|
op3 := inst(24 downto 19);
|
1360 |
|
|
|
1361 |
|
|
write_reg := '0'; rd := inst(29 downto 25); ld := '0';
|
1362 |
|
|
|
1363 |
|
|
case op is
|
1364 |
|
|
when CALL =>
|
1365 |
|
|
write_reg := '1'; rd := "01111"; -- CALL saves PC in r[15] (%o7)
|
1366 |
|
|
when FMT2 =>
|
1367 |
|
|
if (op2 = SETHI) then write_reg := '1'; end if;
|
1368 |
|
|
when FMT3 =>
|
1369 |
|
|
case op3 is
|
1370 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
1371 |
|
|
if MULEN then
|
1372 |
|
|
if (((mulo.nready = '1') and (r.d.cnt /= "00")) or (MULTYPE /= 0)) then
|
1373 |
|
|
write_reg := '1';
|
1374 |
|
|
end if;
|
1375 |
|
|
else write_reg := '1'; end if;
|
1376 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
1377 |
|
|
if DIVEN then
|
1378 |
|
|
if (divo.nready = '1') and (r.d.cnt /= "00") then
|
1379 |
|
|
write_reg := '1';
|
1380 |
|
|
end if;
|
1381 |
|
|
else write_reg := '1'; end if;
|
1382 |
|
|
when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
|
1383 |
|
|
when FPOP1 | FPOP2 => null;
|
1384 |
|
|
when CPOP1 | CPOP2 => null;
|
1385 |
|
|
when others => write_reg := '1';
|
1386 |
|
|
end case;
|
1387 |
|
|
when others => -- LDST
|
1388 |
|
|
ld := not op3(2);
|
1389 |
|
|
if (op3(2) = '0') and not ((CPEN or FPEN) and (op3(5) = '1'))
|
1390 |
|
|
then write_reg := '1'; end if;
|
1391 |
|
|
case op3 is
|
1392 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
|
1393 |
|
|
if r.d.cnt = "00" then write_reg := '1'; ld := '1'; end if;
|
1394 |
|
|
when others => null;
|
1395 |
|
|
end case;
|
1396 |
|
|
if r.d.cnt = "01" then
|
1397 |
|
|
case op3 is
|
1398 |
|
|
when LDD | LDDA | LDDC | LDDF => rd(0) := '1';
|
1399 |
|
|
when others =>
|
1400 |
|
|
end case;
|
1401 |
|
|
end if;
|
1402 |
|
|
end case;
|
1403 |
|
|
|
1404 |
|
|
if (rd = "00000") then write_reg := '0'; end if;
|
1405 |
|
|
wreg := write_reg; rdo := rd;
|
1406 |
|
|
end;
|
1407 |
|
|
|
1408 |
|
|
-- immediate data generation
|
1409 |
|
|
|
1410 |
|
|
function imm_data (r : registers; insn : word)
|
1411 |
|
|
return word is
|
1412 |
|
|
variable immediate_data, inst : word;
|
1413 |
|
|
begin
|
1414 |
|
|
immediate_data := (others => '0'); inst := insn;
|
1415 |
|
|
case inst(31 downto 30) is
|
1416 |
|
|
when FMT2 =>
|
1417 |
|
|
immediate_data := inst(21 downto 0) & "0000000000";
|
1418 |
|
|
when others => -- LDST
|
1419 |
|
|
immediate_data(31 downto 13) := (others => inst(12));
|
1420 |
|
|
immediate_data(12 downto 0) := inst(12 downto 0);
|
1421 |
|
|
end case;
|
1422 |
|
|
return(immediate_data);
|
1423 |
|
|
end;
|
1424 |
|
|
|
1425 |
|
|
-- read special registers
|
1426 |
|
|
function get_spr (r : registers) return word is
|
1427 |
|
|
variable spr : word;
|
1428 |
|
|
begin
|
1429 |
|
|
spr := (others => '0');
|
1430 |
|
|
case r.e.ctrl.inst(24 downto 19) is
|
1431 |
|
|
when RDPSR => spr(31 downto 5) := conv_std_logic_vector(IMPL,4) &
|
1432 |
|
|
conv_std_logic_vector(VER,4) & r.m.icc & "000000" & r.w.s.ec & r.w.s.ef &
|
1433 |
|
|
r.w.s.pil & r.e.su & r.w.s.ps & r.e.et;
|
1434 |
|
|
spr(NWINLOG2-1 downto 0) := r.e.cwp;
|
1435 |
|
|
when RDTBR => spr(31 downto 4) := r.w.s.tba & r.w.s.tt;
|
1436 |
|
|
when RDWIM => spr(NWIN-1 downto 0) := r.w.s.wim;
|
1437 |
|
|
when others =>
|
1438 |
|
|
end case;
|
1439 |
|
|
return(spr);
|
1440 |
|
|
end;
|
1441 |
|
|
|
1442 |
|
|
-- immediate data select
|
1443 |
|
|
|
1444 |
|
|
function imm_select(inst : word) return boolean is
|
1445 |
|
|
variable imm : boolean;
|
1446 |
|
|
begin
|
1447 |
|
|
imm := false;
|
1448 |
|
|
case inst(31 downto 30) is
|
1449 |
|
|
when FMT2 =>
|
1450 |
|
|
case inst(24 downto 22) is
|
1451 |
|
|
when SETHI => imm := true;
|
1452 |
|
|
when others =>
|
1453 |
|
|
end case;
|
1454 |
|
|
when FMT3 =>
|
1455 |
|
|
case inst(24 downto 19) is
|
1456 |
|
|
when RDWIM | RDPSR | RDTBR => imm := true;
|
1457 |
|
|
when others => if (inst(13) = '1') then imm := true; end if;
|
1458 |
|
|
end case;
|
1459 |
|
|
when LDST =>
|
1460 |
|
|
if (inst(13) = '1') then imm := true; end if;
|
1461 |
|
|
when others =>
|
1462 |
|
|
end case;
|
1463 |
|
|
return(imm);
|
1464 |
|
|
end;
|
1465 |
|
|
|
1466 |
|
|
-- EXE operation
|
1467 |
|
|
|
1468 |
|
|
procedure alu_op(r : in registers; iop1, iop2 : in word; me_icc : std_logic_vector(3 downto 0);
|
1469 |
|
|
my, ldbp : std_ulogic; aop1, aop2 : out word; aluop : out std_logic_vector(2 downto 0);
|
1470 |
|
|
alusel : out std_logic_vector(1 downto 0); aluadd : out std_ulogic;
|
1471 |
|
|
shcnt : out std_logic_vector(4 downto 0); sari, shleft, ymsb,
|
1472 |
|
|
mulins, divins, mulstep, macins, ldbp2, invop2 : out std_ulogic) is
|
1473 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1474 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1475 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1476 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
1477 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
1478 |
|
|
variable y0 : std_ulogic;
|
1479 |
|
|
begin
|
1480 |
|
|
|
1481 |
|
|
op := r.a.ctrl.inst(31 downto 30);
|
1482 |
|
|
op2 := r.a.ctrl.inst(24 downto 22);
|
1483 |
|
|
op3 := r.a.ctrl.inst(24 downto 19);
|
1484 |
|
|
aop1 := iop1; aop2 := iop2; ldbp2 := ldbp;
|
1485 |
|
|
aluop := EXE_NOP; alusel := EXE_RES_MISC; aluadd := '1';
|
1486 |
|
|
shcnt := iop2(4 downto 0); sari := '0'; shleft := '0'; invop2 := '0';
|
1487 |
|
|
ymsb := iop1(0); mulins := '0'; divins := '0'; mulstep := '0';
|
1488 |
|
|
macins := '0';
|
1489 |
|
|
|
1490 |
|
|
if r.e.ctrl.wy = '1' then y0 := my;
|
1491 |
|
|
elsif r.m.ctrl.wy = '1' then y0 := r.m.y(0);
|
1492 |
|
|
elsif r.x.ctrl.wy = '1' then y0 := r.x.y(0);
|
1493 |
|
|
else y0 := r.w.s.y(0); end if;
|
1494 |
|
|
|
1495 |
|
|
if r.e.ctrl.wicc = '1' then icc := me_icc;
|
1496 |
|
|
elsif r.m.ctrl.wicc = '1' then icc := r.m.icc;
|
1497 |
|
|
elsif r.x.ctrl.wicc = '1' then icc := r.x.icc;
|
1498 |
|
|
else icc := r.w.s.icc; end if;
|
1499 |
|
|
|
1500 |
|
|
case op is
|
1501 |
|
|
when CALL =>
|
1502 |
|
|
aluop := EXE_LINK;
|
1503 |
|
|
when FMT2 =>
|
1504 |
|
|
case op2 is
|
1505 |
|
|
when SETHI => aluop := EXE_PASS2;
|
1506 |
|
|
when others =>
|
1507 |
|
|
end case;
|
1508 |
|
|
when FMT3 =>
|
1509 |
|
|
case op3 is
|
1510 |
|
|
when IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | SAVE | RESTORE |
|
1511 |
|
|
TICC | JMPL | RETT => alusel := EXE_RES_ADD;
|
1512 |
|
|
when ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV =>
|
1513 |
|
|
alusel := EXE_RES_ADD; aluadd := '0'; aop2 := not iop2; invop2 := '1';
|
1514 |
|
|
when MULSCC => alusel := EXE_RES_ADD;
|
1515 |
|
|
aop1 := (icc(3) xor icc(1)) & iop1(31 downto 1);
|
1516 |
|
|
if y0 = '0' then aop2 := (others => '0'); ldbp2 := '0'; end if;
|
1517 |
|
|
mulstep := '1';
|
1518 |
|
|
when UMUL | UMULCC | SMUL | SMULCC =>
|
1519 |
|
|
if MULEN then mulins := '1'; end if;
|
1520 |
|
|
when UMAC | SMAC =>
|
1521 |
|
|
if MACEN then mulins := '1'; macins := '1'; end if;
|
1522 |
|
|
when UDIV | UDIVCC | SDIV | SDIVCC =>
|
1523 |
|
|
if DIVEN then
|
1524 |
|
|
aluop := EXE_DIV; alusel := EXE_RES_LOGIC; divins := '1';
|
1525 |
|
|
end if;
|
1526 |
|
|
when IAND | ANDCC => aluop := EXE_AND; alusel := EXE_RES_LOGIC;
|
1527 |
|
|
when ANDN | ANDNCC => aluop := EXE_ANDN; alusel := EXE_RES_LOGIC;
|
1528 |
|
|
when IOR | ORCC => aluop := EXE_OR; alusel := EXE_RES_LOGIC;
|
1529 |
|
|
when ORN | ORNCC => aluop := EXE_ORN; alusel := EXE_RES_LOGIC;
|
1530 |
|
|
when IXNOR | XNORCC => aluop := EXE_XNOR; alusel := EXE_RES_LOGIC;
|
1531 |
|
|
when XORCC | IXOR | WRPSR | WRWIM | WRTBR | WRY =>
|
1532 |
|
|
aluop := EXE_XOR; alusel := EXE_RES_LOGIC;
|
1533 |
|
|
when RDPSR | RDTBR | RDWIM => aluop := EXE_SPR;
|
1534 |
|
|
when RDY => aluop := EXE_RDY;
|
1535 |
|
|
when ISLL => aluop := EXE_SLL; alusel := EXE_RES_SHIFT; shleft := '1';
|
1536 |
|
|
shcnt := not iop2(4 downto 0); invop2 := '1';
|
1537 |
|
|
when ISRL => aluop := EXE_SRL; alusel := EXE_RES_SHIFT;
|
1538 |
|
|
when ISRA => aluop := EXE_SRA; alusel := EXE_RES_SHIFT; sari := iop1(31);
|
1539 |
|
|
when FPOP1 | FPOP2 =>
|
1540 |
|
|
when others =>
|
1541 |
|
|
end case;
|
1542 |
|
|
when others => -- LDST
|
1543 |
|
|
case r.a.ctrl.cnt is
|
1544 |
|
|
when "00" =>
|
1545 |
|
|
alusel := EXE_RES_ADD;
|
1546 |
|
|
when "01" =>
|
1547 |
|
|
case op3 is
|
1548 |
|
|
when LDD | LDDA | LDDC => alusel := EXE_RES_ADD;
|
1549 |
|
|
when LDDF => alusel := EXE_RES_ADD;
|
1550 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA => alusel := EXE_RES_ADD;
|
1551 |
|
|
when STF | STDF =>
|
1552 |
|
|
when others =>
|
1553 |
|
|
aluop := EXE_PASS1;
|
1554 |
|
|
if op3(2) = '1' then
|
1555 |
|
|
if op3(1 downto 0) = "01" then aluop := EXE_STB;
|
1556 |
|
|
elsif op3(1 downto 0) = "10" then aluop := EXE_STH; end if;
|
1557 |
|
|
end if;
|
1558 |
|
|
end case;
|
1559 |
|
|
when "10" =>
|
1560 |
|
|
aluop := EXE_PASS1;
|
1561 |
|
|
if op3(2) = '1' then -- ST
|
1562 |
|
|
if (op3(3) and not op3(1))= '1' then aluop := EXE_ONES; end if; -- LDSTUB/A
|
1563 |
|
|
end if;
|
1564 |
|
|
when others =>
|
1565 |
|
|
end case;
|
1566 |
|
|
end case;
|
1567 |
|
|
end;
|
1568 |
|
|
|
1569 |
|
|
function ra_inull_gen(r, v : registers) return std_ulogic is
|
1570 |
|
|
variable de_inull : std_ulogic;
|
1571 |
|
|
begin
|
1572 |
|
|
de_inull := '0';
|
1573 |
|
|
if ((v.e.jmpl or v.e.ctrl.rett) and not v.e.ctrl.annul and not (r.e.jmpl and not r.e.ctrl.annul)) = '1' then de_inull := '1'; end if;
|
1574 |
|
|
if ((v.a.jmpl or v.a.ctrl.rett) and not v.a.ctrl.annul and not (r.a.jmpl and not r.a.ctrl.annul)) = '1' then de_inull := '1'; end if;
|
1575 |
|
|
return(de_inull);
|
1576 |
|
|
end;
|
1577 |
|
|
|
1578 |
|
|
-- operand generation
|
1579 |
|
|
|
1580 |
|
|
procedure op_mux(r : in registers; rfd, ed, md, xd, im : in word;
|
1581 |
|
|
rsel : in std_logic_vector(2 downto 0);
|
1582 |
|
|
ldbp : out std_ulogic; d : out word) is
|
1583 |
|
|
begin
|
1584 |
|
|
ldbp := '0';
|
1585 |
|
|
case rsel is
|
1586 |
|
|
when "000" => d := rfd;
|
1587 |
|
|
when "001" => d := ed;
|
1588 |
|
|
when "010" => d := md; if lddel = 1 then ldbp := r.m.ctrl.ld; end if;
|
1589 |
|
|
when "011" => d := xd;
|
1590 |
|
|
when "100" => d := im;
|
1591 |
|
|
when "101" => d := (others => '0');
|
1592 |
|
|
when "110" => d := r.w.result;
|
1593 |
|
|
when others => d := (others => '-');
|
1594 |
|
|
end case;
|
1595 |
|
|
end;
|
1596 |
|
|
|
1597 |
|
|
procedure op_find(r : in registers; ldchkra : std_ulogic; ldchkex : std_ulogic;
|
1598 |
|
|
rs1 : std_logic_vector(4 downto 0); ra : rfatype; im : boolean; rfe : out std_ulogic;
|
1599 |
|
|
osel : out std_logic_vector(2 downto 0); ldcheck : std_ulogic) is
|
1600 |
|
|
begin
|
1601 |
|
|
rfe := '0';
|
1602 |
|
|
if im then osel := "100";
|
1603 |
|
|
elsif rs1 = "00000" then osel := "101"; -- %g0
|
1604 |
|
|
elsif ((r.a.ctrl.wreg and ldchkra) = '1') and (ra = r.a.ctrl.rd) then osel := "001";
|
1605 |
|
|
elsif ((r.e.ctrl.wreg and ldchkex) = '1') and (ra = r.e.ctrl.rd) then osel := "010";
|
1606 |
|
|
elsif r.m.ctrl.wreg = '1' and (ra = r.m.ctrl.rd) then osel := "011";
|
1607 |
|
|
elsif (irfwt = 0) and r.x.ctrl.wreg = '1' and (ra = r.x.ctrl.rd) then osel := "110";
|
1608 |
|
|
else osel := "000"; rfe := ldcheck; end if;
|
1609 |
|
|
end;
|
1610 |
|
|
|
1611 |
|
|
-- generate carry-in for alu
|
1612 |
|
|
|
1613 |
|
|
procedure cin_gen(r : registers; me_cin : in std_ulogic; cin : out std_ulogic) is
|
1614 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1615 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1616 |
|
|
variable ncin : std_ulogic;
|
1617 |
|
|
begin
|
1618 |
|
|
|
1619 |
|
|
op := r.a.ctrl.inst(31 downto 30); op3 := r.a.ctrl.inst(24 downto 19);
|
1620 |
|
|
if r.e.ctrl.wicc = '1' then ncin := me_cin;
|
1621 |
|
|
else ncin := r.m.icc(0); end if;
|
1622 |
|
|
cin := '0';
|
1623 |
|
|
case op is
|
1624 |
|
|
when FMT3 =>
|
1625 |
|
|
case op3 is
|
1626 |
|
|
when ISUB | SUBCC | TSUBCC | TSUBCCTV => cin := '1';
|
1627 |
|
|
when ADDX | ADDXCC => cin := ncin;
|
1628 |
|
|
when SUBX | SUBXCC => cin := not ncin;
|
1629 |
|
|
when others => null;
|
1630 |
|
|
end case;
|
1631 |
|
|
when others => null;
|
1632 |
|
|
end case;
|
1633 |
|
|
end;
|
1634 |
|
|
|
1635 |
|
|
procedure logic_op(r : registers; aluin1, aluin2, mey : word;
|
1636 |
|
|
ymsb : std_ulogic; logicres, y : out word) is
|
1637 |
|
|
variable logicout : word;
|
1638 |
|
|
begin
|
1639 |
|
|
case r.e.aluop is
|
1640 |
|
|
when EXE_AND => logicout := aluin1 and aluin2;
|
1641 |
|
|
when EXE_ANDN => logicout := aluin1 and not aluin2;
|
1642 |
|
|
when EXE_OR => logicout := aluin1 or aluin2;
|
1643 |
|
|
when EXE_ORN => logicout := aluin1 or not aluin2;
|
1644 |
|
|
when EXE_XOR => logicout := aluin1 xor aluin2;
|
1645 |
|
|
when EXE_XNOR => logicout := aluin1 xor not aluin2;
|
1646 |
|
|
when EXE_DIV =>
|
1647 |
|
|
if DIVEN then logicout := aluin2;
|
1648 |
|
|
else logicout := (others => '-'); end if;
|
1649 |
|
|
when others => logicout := (others => '-');
|
1650 |
|
|
end case;
|
1651 |
|
|
if (r.e.ctrl.wy and r.e.mulstep) = '1' then
|
1652 |
|
|
y := ymsb & r.m.y(31 downto 1);
|
1653 |
|
|
elsif r.e.ctrl.wy = '1' then y := logicout;
|
1654 |
|
|
elsif r.m.ctrl.wy = '1' then y := mey;
|
1655 |
|
|
elsif MACPIPE and (r.x.mac = '1') then y := mulo.result(63 downto 32);
|
1656 |
|
|
elsif r.x.ctrl.wy = '1' then y := r.x.y;
|
1657 |
|
|
else y := r.w.s.y; end if;
|
1658 |
|
|
logicres := logicout;
|
1659 |
|
|
end;
|
1660 |
|
|
|
1661 |
|
|
procedure misc_op(r : registers; wpr : watchpoint_registers;
|
1662 |
|
|
aluin1, aluin2, ldata, mey : word;
|
1663 |
|
|
mout, edata : out word) is
|
1664 |
|
|
variable miscout, bpdata, stdata : word;
|
1665 |
|
|
variable wpi : integer;
|
1666 |
|
|
begin
|
1667 |
|
|
wpi := 0; miscout := r.e.ctrl.pc(31 downto 2) & "00";
|
1668 |
|
|
edata := aluin1; bpdata := aluin1;
|
1669 |
|
|
if ((r.x.ctrl.wreg and r.x.ctrl.ld and not r.x.ctrl.annul) = '1') and
|
1670 |
|
|
(r.x.ctrl.rd = r.e.ctrl.rd) and (r.e.ctrl.inst(31 downto 30) = LDST) and
|
1671 |
|
|
(r.e.ctrl.cnt /= "10")
|
1672 |
|
|
then bpdata := ldata; end if;
|
1673 |
|
|
|
1674 |
|
|
case r.e.aluop is
|
1675 |
|
|
when EXE_STB => miscout := bpdata(7 downto 0) & bpdata(7 downto 0) &
|
1676 |
|
|
bpdata(7 downto 0) & bpdata(7 downto 0);
|
1677 |
|
|
edata := miscout;
|
1678 |
|
|
when EXE_STH => miscout := bpdata(15 downto 0) & bpdata(15 downto 0);
|
1679 |
|
|
edata := miscout;
|
1680 |
|
|
when EXE_PASS1 => miscout := bpdata; edata := miscout;
|
1681 |
|
|
when EXE_PASS2 => miscout := aluin2;
|
1682 |
|
|
when EXE_ONES => miscout := (others => '1');
|
1683 |
|
|
edata := miscout;
|
1684 |
|
|
when EXE_RDY =>
|
1685 |
|
|
if MULEN and (r.m.ctrl.wy = '1') then miscout := mey;
|
1686 |
|
|
else miscout := r.m.y; end if;
|
1687 |
|
|
if (NWP > 0) and (r.e.ctrl.inst(18 downto 17) = "11") then
|
1688 |
|
|
wpi := conv_integer(r.e.ctrl.inst(16 downto 15));
|
1689 |
|
|
if r.e.ctrl.inst(14) = '0' then miscout := wpr(wpi).addr & '0' & wpr(wpi).exec;
|
1690 |
|
|
else miscout := wpr(wpi).mask & wpr(wpi).load & wpr(wpi).store; end if;
|
1691 |
|
|
end if;
|
1692 |
|
|
if (r.e.ctrl.inst(18 downto 17) = "10") and (r.e.ctrl.inst(14) = '1') then --%ASR17
|
1693 |
|
|
miscout := asr17_gen(r);
|
1694 |
|
|
end if;
|
1695 |
|
|
if MACEN then
|
1696 |
|
|
if (r.e.ctrl.inst(18 downto 14) = "10010") then --%ASR18
|
1697 |
|
|
if ((r.m.mac = '1') and not MACPIPE) or ((r.x.mac = '1') and MACPIPE) then
|
1698 |
|
|
miscout := mulo.result(31 downto 0); -- data forward of asr18
|
1699 |
|
|
else miscout := r.w.s.asr18; end if;
|
1700 |
|
|
else
|
1701 |
|
|
if ((r.m.mac = '1') and not MACPIPE) or ((r.x.mac = '1') and MACPIPE) then
|
1702 |
|
|
miscout := mulo.result(63 downto 32); -- data forward Y
|
1703 |
|
|
end if;
|
1704 |
|
|
end if;
|
1705 |
|
|
end if;
|
1706 |
|
|
when EXE_SPR =>
|
1707 |
|
|
miscout := get_spr(r);
|
1708 |
|
|
when others => null;
|
1709 |
|
|
end case;
|
1710 |
|
|
mout := miscout;
|
1711 |
|
|
end;
|
1712 |
|
|
|
1713 |
|
|
procedure alu_select(r : registers; addout : std_logic_vector(32 downto 0);
|
1714 |
|
|
op1, op2 : word; shiftout, logicout, miscout : word; res : out word;
|
1715 |
|
|
me_icc : std_logic_vector(3 downto 0);
|
1716 |
|
|
icco : out std_logic_vector(3 downto 0); divz : out std_ulogic) is
|
1717 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1718 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1719 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
1720 |
|
|
variable aluresult : word;
|
1721 |
|
|
begin
|
1722 |
|
|
op := r.e.ctrl.inst(31 downto 30); op3 := r.e.ctrl.inst(24 downto 19);
|
1723 |
|
|
icc := (others => '0');
|
1724 |
|
|
case r.e.alusel is
|
1725 |
|
|
when EXE_RES_ADD =>
|
1726 |
|
|
aluresult := addout(32 downto 1);
|
1727 |
|
|
if r.e.aluadd = '0' then
|
1728 |
|
|
icc(0) := ((not op1(31)) and not op2(31)) or -- Carry
|
1729 |
|
|
(addout(32) and ((not op1(31)) or not op2(31)));
|
1730 |
|
|
icc(1) := (op1(31) and (op2(31)) and not addout(32)) or -- Overflow
|
1731 |
|
|
(addout(32) and (not op1(31)) and not op2(31));
|
1732 |
|
|
else
|
1733 |
|
|
icc(0) := (op1(31) and op2(31)) or -- Carry
|
1734 |
|
|
((not addout(32)) and (op1(31) or op2(31)));
|
1735 |
|
|
icc(1) := (op1(31) and op2(31) and not addout(32)) or -- Overflow
|
1736 |
|
|
(addout(32) and (not op1(31)) and (not op2(31)));
|
1737 |
|
|
end if;
|
1738 |
|
|
if notag = 0 then
|
1739 |
|
|
case op is
|
1740 |
|
|
when FMT3 =>
|
1741 |
|
|
case op3 is
|
1742 |
|
|
when TADDCC | TADDCCTV =>
|
1743 |
|
|
icc(1) := op1(0) or op1(1) or op2(0) or op2(1) or icc(1);
|
1744 |
|
|
when TSUBCC | TSUBCCTV =>
|
1745 |
|
|
icc(1) := op1(0) or op1(1) or (not op2(0)) or (not op2(1)) or icc(1);
|
1746 |
|
|
when others => null;
|
1747 |
|
|
end case;
|
1748 |
|
|
when others => null;
|
1749 |
|
|
end case;
|
1750 |
|
|
end if;
|
1751 |
|
|
|
1752 |
|
|
if aluresult = zero32 then icc(2) := '1'; end if;
|
1753 |
|
|
when EXE_RES_SHIFT => aluresult := shiftout;
|
1754 |
|
|
when EXE_RES_LOGIC => aluresult := logicout;
|
1755 |
|
|
if aluresult = zero32 then icc(2) := '1'; end if;
|
1756 |
|
|
when others => aluresult := miscout;
|
1757 |
|
|
end case;
|
1758 |
|
|
if r.e.jmpl = '1' then aluresult := r.e.ctrl.pc(31 downto 2) & "00"; end if;
|
1759 |
|
|
icc(3) := aluresult(31); divz := icc(2);
|
1760 |
|
|
if r.e.ctrl.wicc = '1' then
|
1761 |
|
|
if (op = FMT3) and (op3 = WRPSR) then icco := logicout(23 downto 20);
|
1762 |
|
|
else icco := icc; end if;
|
1763 |
|
|
elsif r.m.ctrl.wicc = '1' then icco := me_icc;
|
1764 |
|
|
elsif r.x.ctrl.wicc = '1' then icco := r.x.icc;
|
1765 |
|
|
else icco := r.w.s.icc; end if;
|
1766 |
|
|
res := aluresult;
|
1767 |
|
|
end;
|
1768 |
|
|
|
1769 |
|
|
procedure dcache_gen(r, v : registers; dci : out dc_in_type;
|
1770 |
|
|
link_pc, jump, force_a2, load : out std_ulogic) is
|
1771 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1772 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1773 |
|
|
variable su : std_ulogic;
|
1774 |
|
|
begin
|
1775 |
|
|
op := r.e.ctrl.inst(31 downto 30); op3 := r.e.ctrl.inst(24 downto 19);
|
1776 |
|
|
dci.signed := '0'; dci.lock := '0'; dci.dsuen := '0'; dci.size := SZWORD;
|
1777 |
|
|
if op = LDST then
|
1778 |
|
|
case op3 is
|
1779 |
|
|
when LDUB | LDUBA => dci.size := SZBYTE;
|
1780 |
|
|
when LDSTUB | LDSTUBA => dci.size := SZBYTE; dci.lock := '1';
|
1781 |
|
|
when LDUH | LDUHA => dci.size := SZHALF;
|
1782 |
|
|
when LDSB | LDSBA => dci.size := SZBYTE; dci.signed := '1';
|
1783 |
|
|
when LDSH | LDSHA => dci.size := SZHALF; dci.signed := '1';
|
1784 |
|
|
when LD | LDA | LDF | LDC => dci.size := SZWORD;
|
1785 |
|
|
when SWAP | SWAPA => dci.size := SZWORD; dci.lock := '1';
|
1786 |
|
|
when LDD | LDDA | LDDF | LDDC => dci.size := SZDBL;
|
1787 |
|
|
when STB | STBA => dci.size := SZBYTE;
|
1788 |
|
|
when STH | STHA => dci.size := SZHALF;
|
1789 |
|
|
when ST | STA | STF => dci.size := SZWORD;
|
1790 |
|
|
when ISTD | STDA => dci.size := SZDBL;
|
1791 |
|
|
when STDF | STDFQ => if FPEN then dci.size := SZDBL; end if;
|
1792 |
|
|
when STDC | STDCQ => if CPEN then dci.size := SZDBL; end if;
|
1793 |
|
|
when others => dci.size := SZWORD; dci.lock := '0'; dci.signed := '0';
|
1794 |
|
|
end case;
|
1795 |
|
|
end if;
|
1796 |
|
|
|
1797 |
|
|
link_pc := '0'; jump:= '0'; force_a2 := '0'; load := '0';
|
1798 |
|
|
dci.write := '0'; dci.enaddr := '0'; dci.read := not op3(2);
|
1799 |
|
|
|
1800 |
|
|
-- load/store control decoding
|
1801 |
|
|
|
1802 |
|
|
if (r.e.ctrl.annul = '0') then
|
1803 |
|
|
case op is
|
1804 |
|
|
when CALL => link_pc := '1';
|
1805 |
|
|
when FMT3 =>
|
1806 |
|
|
case op3 is
|
1807 |
|
|
when JMPL => jump := '1'; link_pc := '1';
|
1808 |
|
|
when RETT => jump := '1';
|
1809 |
|
|
when others => null;
|
1810 |
|
|
end case;
|
1811 |
|
|
when LDST =>
|
1812 |
|
|
case r.e.ctrl.cnt is
|
1813 |
|
|
when "00" =>
|
1814 |
|
|
dci.read := op3(3) or not op3(2); -- LD/LDST/SWAP
|
1815 |
|
|
load := op3(3) or not op3(2);
|
1816 |
|
|
dci.enaddr := '1';
|
1817 |
|
|
when "01" =>
|
1818 |
|
|
force_a2 := not op3(2); -- LDD
|
1819 |
|
|
load := not op3(2); dci.enaddr := not op3(2);
|
1820 |
|
|
if op3(3 downto 2) = "01" then -- ST/STD
|
1821 |
|
|
dci.write := '1';
|
1822 |
|
|
end if;
|
1823 |
|
|
if op3(3 downto 2) = "11" then -- LDST/SWAP
|
1824 |
|
|
dci.enaddr := '1';
|
1825 |
|
|
end if;
|
1826 |
|
|
when "10" => -- STD/LDST/SWAP
|
1827 |
|
|
dci.write := '1';
|
1828 |
|
|
when others => null;
|
1829 |
|
|
end case;
|
1830 |
|
|
if (r.e.ctrl.trap or (v.x.ctrl.trap and not v.x.ctrl.annul)) = '1' then
|
1831 |
|
|
dci.enaddr := '0';
|
1832 |
|
|
end if;
|
1833 |
|
|
when others => null;
|
1834 |
|
|
end case;
|
1835 |
|
|
end if;
|
1836 |
|
|
|
1837 |
|
|
if ((r.x.ctrl.rett and not r.x.ctrl.annul) = '1') then su := r.w.s.ps;
|
1838 |
|
|
else su := r.w.s.s; end if;
|
1839 |
|
|
if su = '1' then dci.asi := "00001011"; else dci.asi := "00001010"; end if;
|
1840 |
|
|
if (op3(4) = '1') and ((op3(5) = '0') or not CPEN) then
|
1841 |
|
|
dci.asi := r.e.ctrl.inst(12 downto 5);
|
1842 |
|
|
end if;
|
1843 |
|
|
|
1844 |
|
|
end;
|
1845 |
|
|
|
1846 |
|
|
procedure fpstdata(r : in registers; edata, eres : in word; fpstdata : in std_logic_vector(31 downto 0);
|
1847 |
|
|
edata2, eres2 : out word) is
|
1848 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1849 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1850 |
|
|
begin
|
1851 |
|
|
edata2 := edata; eres2 := eres;
|
1852 |
|
|
op := r.e.ctrl.inst(31 downto 30); op3 := r.e.ctrl.inst(24 downto 19);
|
1853 |
|
|
if FPEN then
|
1854 |
|
|
if FPEN and (op = LDST) and ((op3(5 downto 4) & op3(2)) = "101") and (r.e.ctrl.cnt /= "00") then
|
1855 |
|
|
edata2 := fpstdata; eres2 := fpstdata;
|
1856 |
|
|
end if;
|
1857 |
|
|
end if;
|
1858 |
|
|
end;
|
1859 |
|
|
|
1860 |
|
|
function ld_align(data : dcdtype; set : std_logic_vector(DSETMSB downto 0);
|
1861 |
|
|
size, laddr : std_logic_vector(1 downto 0); signed : std_ulogic) return word is
|
1862 |
|
|
variable align_data, rdata : word;
|
1863 |
|
|
begin
|
1864 |
|
|
align_data := data(conv_integer(set)); rdata := (others => '0');
|
1865 |
|
|
case size is
|
1866 |
|
|
when "00" => -- byte read
|
1867 |
|
|
case laddr is
|
1868 |
|
|
when "00" =>
|
1869 |
|
|
rdata(7 downto 0) := align_data(31 downto 24);
|
1870 |
|
|
if signed = '1' then rdata(31 downto 8) := (others => align_data(31)); end if;
|
1871 |
|
|
when "01" =>
|
1872 |
|
|
rdata(7 downto 0) := align_data(23 downto 16);
|
1873 |
|
|
if signed = '1' then rdata(31 downto 8) := (others => align_data(23)); end if;
|
1874 |
|
|
when "10" =>
|
1875 |
|
|
rdata(7 downto 0) := align_data(15 downto 8);
|
1876 |
|
|
if signed = '1' then rdata(31 downto 8) := (others => align_data(15)); end if;
|
1877 |
|
|
when others =>
|
1878 |
|
|
rdata(7 downto 0) := align_data(7 downto 0);
|
1879 |
|
|
if signed = '1' then rdata(31 downto 8) := (others => align_data(7)); end if;
|
1880 |
|
|
end case;
|
1881 |
|
|
when "01" => -- half-word read
|
1882 |
|
|
if laddr(1) = '1' then
|
1883 |
|
|
rdata(15 downto 0) := align_data(15 downto 0);
|
1884 |
|
|
if signed = '1' then rdata(31 downto 15) := (others => align_data(15)); end if;
|
1885 |
|
|
else
|
1886 |
|
|
rdata(15 downto 0) := align_data(31 downto 16);
|
1887 |
|
|
if signed = '1' then rdata(31 downto 15) := (others => align_data(31)); end if;
|
1888 |
|
|
end if;
|
1889 |
|
|
when others => -- single and double word read
|
1890 |
|
|
rdata := align_data;
|
1891 |
|
|
end case;
|
1892 |
|
|
return(rdata);
|
1893 |
|
|
end;
|
1894 |
|
|
|
1895 |
|
|
procedure mem_trap(r : registers; wpr : watchpoint_registers;
|
1896 |
|
|
annul, holdn : in std_ulogic;
|
1897 |
|
|
trapout, iflush, nullify, werrout : out std_ulogic;
|
1898 |
|
|
tt : out std_logic_vector(5 downto 0)) is
|
1899 |
|
|
variable cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
1900 |
|
|
variable cwpx : std_logic_vector(5 downto NWINLOG2);
|
1901 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1902 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1903 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1904 |
|
|
variable nalign_d : std_ulogic;
|
1905 |
|
|
variable trap, werr : std_ulogic;
|
1906 |
|
|
begin
|
1907 |
|
|
op := r.m.ctrl.inst(31 downto 30); op2 := r.m.ctrl.inst(24 downto 22);
|
1908 |
|
|
op3 := r.m.ctrl.inst(24 downto 19);
|
1909 |
|
|
cwpx := r.m.result(5 downto NWINLOG2); cwpx(5) := '0';
|
1910 |
|
|
iflush := '0'; trap := r.m.ctrl.trap; nullify := annul;
|
1911 |
|
|
tt := r.m.ctrl.tt; werr := (dco.werr or r.m.werr) and not r.w.s.dwt;
|
1912 |
|
|
nalign_d := r.m.nalign or r.m.result(2);
|
1913 |
|
|
if ((annul or trap) /= '1') and (r.m.ctrl.pv = '1') then
|
1914 |
|
|
if (werr and holdn) = '1' then
|
1915 |
|
|
trap := '1'; tt := TT_DSEX; werr := '0';
|
1916 |
|
|
if op = LDST then nullify := '1'; end if;
|
1917 |
|
|
end if;
|
1918 |
|
|
end if;
|
1919 |
|
|
if ((annul or trap) /= '1') then
|
1920 |
|
|
case op is
|
1921 |
|
|
when FMT2 =>
|
1922 |
|
|
case op2 is
|
1923 |
|
|
when FBFCC =>
|
1924 |
|
|
if FPEN and (fpo.exc = '1') then trap := '1'; tt := TT_FPEXC; end if;
|
1925 |
|
|
when CBCCC =>
|
1926 |
|
|
if CPEN and (cpo.exc = '1') then trap := '1'; tt := TT_CPEXC; end if;
|
1927 |
|
|
when others => null;
|
1928 |
|
|
end case;
|
1929 |
|
|
when FMT3 =>
|
1930 |
|
|
case op3 is
|
1931 |
|
|
when WRPSR =>
|
1932 |
|
|
if (orv(cwpx) = '1') then trap := '1'; tt := TT_IINST; end if;
|
1933 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
1934 |
|
|
if DIVEN then
|
1935 |
|
|
if r.m.divz = '1' then trap := '1'; tt := TT_DIV; end if;
|
1936 |
|
|
end if;
|
1937 |
|
|
when JMPL | RETT =>
|
1938 |
|
|
if r.m.nalign = '1' then trap := '1'; tt := TT_UNALA; end if;
|
1939 |
|
|
when TADDCCTV | TSUBCCTV =>
|
1940 |
|
|
if (notag = 0) and (r.m.icc(1) = '1') then
|
1941 |
|
|
trap := '1'; tt := TT_TAG;
|
1942 |
|
|
end if;
|
1943 |
|
|
when FLUSH => iflush := '1';
|
1944 |
|
|
when FPOP1 | FPOP2 =>
|
1945 |
|
|
if FPEN and (fpo.exc = '1') then trap := '1'; tt := TT_FPEXC; end if;
|
1946 |
|
|
when CPOP1 | CPOP2 =>
|
1947 |
|
|
if CPEN and (cpo.exc = '1') then trap := '1'; tt := TT_CPEXC; end if;
|
1948 |
|
|
when others => null;
|
1949 |
|
|
end case;
|
1950 |
|
|
when LDST =>
|
1951 |
|
|
if r.m.ctrl.cnt = "00" then
|
1952 |
|
|
case op3 is
|
1953 |
|
|
when LDDF | STDF | STDFQ =>
|
1954 |
|
|
if FPEN then
|
1955 |
|
|
if nalign_d = '1' then
|
1956 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1957 |
|
|
elsif (fpo.exc and r.m.ctrl.pv) = '1'
|
1958 |
|
|
then trap := '1'; tt := TT_FPEXC; nullify := '1'; end if;
|
1959 |
|
|
end if;
|
1960 |
|
|
when LDDC | STDC | STDCQ =>
|
1961 |
|
|
if CPEN then
|
1962 |
|
|
if nalign_d = '1' then
|
1963 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1964 |
|
|
elsif ((cpo.exc and r.m.ctrl.pv) = '1')
|
1965 |
|
|
then trap := '1'; tt := TT_CPEXC; nullify := '1'; end if;
|
1966 |
|
|
end if;
|
1967 |
|
|
when LDD | ISTD | LDDA | STDA =>
|
1968 |
|
|
if r.m.result(2 downto 0) /= "000" then
|
1969 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1970 |
|
|
end if;
|
1971 |
|
|
when LDF | LDFSR | STFSR | STF =>
|
1972 |
|
|
if FPEN and (r.m.nalign = '1') then
|
1973 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1974 |
|
|
elsif FPEN and ((fpo.exc and r.m.ctrl.pv) = '1')
|
1975 |
|
|
then trap := '1'; tt := TT_FPEXC; nullify := '1'; end if;
|
1976 |
|
|
when LDC | LDCSR | STCSR | STC =>
|
1977 |
|
|
if CPEN and (r.m.nalign = '1') then
|
1978 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1979 |
|
|
elsif CPEN and ((cpo.exc and r.m.ctrl.pv) = '1')
|
1980 |
|
|
then trap := '1'; tt := TT_CPEXC; nullify := '1'; end if;
|
1981 |
|
|
when LD | LDA | ST | STA | SWAP | SWAPA =>
|
1982 |
|
|
if r.m.result(1 downto 0) /= "00" then
|
1983 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1984 |
|
|
end if;
|
1985 |
|
|
when LDUH | LDUHA | LDSH | LDSHA | STH | STHA =>
|
1986 |
|
|
if r.m.result(0) /= '0' then
|
1987 |
|
|
trap := '1'; tt := TT_UNALA; nullify := '1';
|
1988 |
|
|
end if;
|
1989 |
|
|
when others => null;
|
1990 |
|
|
end case;
|
1991 |
|
|
for i in 1 to NWP loop
|
1992 |
|
|
if ((((wpr(i-1).load and not op3(2)) or (wpr(i-1).store and op3(2))) = '1') and
|
1993 |
|
|
(((wpr(i-1).addr xor r.m.result(31 downto 2)) and wpr(i-1).mask) = zero32(31 downto 2)))
|
1994 |
|
|
then trap := '1'; tt := TT_WATCH; nullify := '1'; end if;
|
1995 |
|
|
end loop;
|
1996 |
|
|
end if;
|
1997 |
|
|
when others => null;
|
1998 |
|
|
end case;
|
1999 |
|
|
end if;
|
2000 |
|
|
if (rstn = '0') or (r.x.rstate = dsu2) then werr := '0'; end if;
|
2001 |
|
|
trapout := trap; werrout := werr;
|
2002 |
|
|
end;
|
2003 |
|
|
|
2004 |
|
|
procedure irq_trap(r : in registers;
|
2005 |
|
|
ir : in irestart_register;
|
2006 |
|
|
irl : in std_logic_vector(3 downto 0);
|
2007 |
|
|
annul : in std_ulogic;
|
2008 |
|
|
pv : in std_ulogic;
|
2009 |
|
|
trap : in std_ulogic;
|
2010 |
|
|
tt : in std_logic_vector(5 downto 0);
|
2011 |
|
|
nullify : in std_ulogic;
|
2012 |
|
|
irqen : out std_ulogic;
|
2013 |
|
|
irqen2 : out std_ulogic;
|
2014 |
|
|
nullify2 : out std_ulogic;
|
2015 |
|
|
trap2, ipend : out std_ulogic;
|
2016 |
|
|
tt2 : out std_logic_vector(5 downto 0)) is
|
2017 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2018 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2019 |
|
|
variable pend : std_ulogic;
|
2020 |
|
|
begin
|
2021 |
|
|
nullify2 := nullify; trap2 := trap; tt2 := tt;
|
2022 |
|
|
op := r.m.ctrl.inst(31 downto 30); op3 := r.m.ctrl.inst(24 downto 19);
|
2023 |
|
|
irqen := '1'; irqen2 := r.m.irqen;
|
2024 |
|
|
|
2025 |
|
|
if (annul or trap) = '0' then
|
2026 |
|
|
if ((op = FMT3) and (op3 = WRPSR)) then irqen := '0'; end if;
|
2027 |
|
|
end if;
|
2028 |
|
|
|
2029 |
|
|
if (irl = "1111") or (irl > r.w.s.pil) then
|
2030 |
|
|
pend := r.m.irqen and r.m.irqen2 and r.w.s.et and not ir.pwd;
|
2031 |
|
|
else pend := '0'; end if;
|
2032 |
|
|
ipend := pend;
|
2033 |
|
|
|
2034 |
|
|
if ((not annul) and pv and (not trap) and pend) = '1' then
|
2035 |
|
|
trap2 := '1'; tt2 := "01" & irl;
|
2036 |
|
|
if op = LDST then nullify2 := '1'; end if;
|
2037 |
|
|
end if;
|
2038 |
|
|
end;
|
2039 |
|
|
|
2040 |
|
|
procedure irq_intack(r : in registers; holdn : in std_ulogic; intack: out std_ulogic) is
|
2041 |
|
|
begin
|
2042 |
|
|
intack := '0';
|
2043 |
|
|
if r.x.rstate = trap then
|
2044 |
|
|
if r.w.s.tt(7 downto 4) = "0001" then intack := '1'; end if;
|
2045 |
|
|
end if;
|
2046 |
|
|
end;
|
2047 |
|
|
|
2048 |
|
|
-- write special registers
|
2049 |
|
|
|
2050 |
|
|
procedure sp_write (r : registers; wpr : watchpoint_registers;
|
2051 |
|
|
s : out special_register_type; vwpr : out watchpoint_registers) is
|
2052 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2053 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
2054 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2055 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
2056 |
|
|
variable i : integer range 0 to 3;
|
2057 |
|
|
begin
|
2058 |
|
|
|
2059 |
|
|
op := r.x.ctrl.inst(31 downto 30);
|
2060 |
|
|
op2 := r.x.ctrl.inst(24 downto 22);
|
2061 |
|
|
op3 := r.x.ctrl.inst(24 downto 19);
|
2062 |
|
|
s := r.w.s;
|
2063 |
|
|
rd := r.x.ctrl.inst(29 downto 25);
|
2064 |
|
|
vwpr := wpr;
|
2065 |
|
|
|
2066 |
|
|
case op is
|
2067 |
|
|
when FMT3 =>
|
2068 |
|
|
case op3 is
|
2069 |
|
|
when WRY =>
|
2070 |
|
|
if rd = "00000" then
|
2071 |
|
|
s.y := r.x.result;
|
2072 |
|
|
elsif MACEN and (rd = "10010") then
|
2073 |
|
|
s.asr18 := r.x.result;
|
2074 |
|
|
elsif (rd = "10001") then
|
2075 |
|
|
s.dwt := r.x.result(14);
|
2076 |
|
|
if (svt = 1) then s.svt := r.x.result(13); end if;
|
2077 |
|
|
elsif rd(4 downto 3) = "11" then -- %ASR24 - %ASR31
|
2078 |
|
|
case rd(2 downto 0) is
|
2079 |
|
|
when "000" =>
|
2080 |
|
|
vwpr(0).addr := r.x.result(31 downto 2);
|
2081 |
|
|
vwpr(0).exec := r.x.result(0);
|
2082 |
|
|
when "001" =>
|
2083 |
|
|
vwpr(0).mask := r.x.result(31 downto 2);
|
2084 |
|
|
vwpr(0).load := r.x.result(1);
|
2085 |
|
|
vwpr(0).store := r.x.result(0);
|
2086 |
|
|
when "010" =>
|
2087 |
|
|
vwpr(1).addr := r.x.result(31 downto 2);
|
2088 |
|
|
vwpr(1).exec := r.x.result(0);
|
2089 |
|
|
when "011" =>
|
2090 |
|
|
vwpr(1).mask := r.x.result(31 downto 2);
|
2091 |
|
|
vwpr(1).load := r.x.result(1);
|
2092 |
|
|
vwpr(1).store := r.x.result(0);
|
2093 |
|
|
when "100" =>
|
2094 |
|
|
vwpr(2).addr := r.x.result(31 downto 2);
|
2095 |
|
|
vwpr(2).exec := r.x.result(0);
|
2096 |
|
|
when "101" =>
|
2097 |
|
|
vwpr(2).mask := r.x.result(31 downto 2);
|
2098 |
|
|
vwpr(2).load := r.x.result(1);
|
2099 |
|
|
vwpr(2).store := r.x.result(0);
|
2100 |
|
|
when "110" =>
|
2101 |
|
|
vwpr(3).addr := r.x.result(31 downto 2);
|
2102 |
|
|
vwpr(3).exec := r.x.result(0);
|
2103 |
|
|
when others => -- "111"
|
2104 |
|
|
vwpr(3).mask := r.x.result(31 downto 2);
|
2105 |
|
|
vwpr(3).load := r.x.result(1);
|
2106 |
|
|
vwpr(3).store := r.x.result(0);
|
2107 |
|
|
end case;
|
2108 |
|
|
end if;
|
2109 |
|
|
when WRPSR =>
|
2110 |
|
|
s.cwp := r.x.result(NWINLOG2-1 downto 0);
|
2111 |
|
|
s.icc := r.x.result(23 downto 20);
|
2112 |
|
|
s.ec := r.x.result(13);
|
2113 |
|
|
if FPEN then s.ef := r.x.result(12); end if;
|
2114 |
|
|
s.pil := r.x.result(11 downto 8);
|
2115 |
|
|
s.s := r.x.result(7);
|
2116 |
|
|
s.ps := r.x.result(6);
|
2117 |
|
|
s.et := r.x.result(5);
|
2118 |
|
|
when WRWIM =>
|
2119 |
|
|
s.wim := r.x.result(NWIN-1 downto 0);
|
2120 |
|
|
when WRTBR =>
|
2121 |
|
|
s.tba := r.x.result(31 downto 12);
|
2122 |
|
|
when SAVE =>
|
2123 |
|
|
if (not CWPOPT) and (r.w.s.cwp = CWPMIN) then s.cwp := CWPMAX;
|
2124 |
|
|
else s.cwp := r.w.s.cwp - 1 ; end if;
|
2125 |
|
|
when RESTORE =>
|
2126 |
|
|
if (not CWPOPT) and (r.w.s.cwp = CWPMAX) then s.cwp := CWPMIN;
|
2127 |
|
|
else s.cwp := r.w.s.cwp + 1; end if;
|
2128 |
|
|
when RETT =>
|
2129 |
|
|
if (not CWPOPT) and (r.w.s.cwp = CWPMAX) then s.cwp := CWPMIN;
|
2130 |
|
|
else s.cwp := r.w.s.cwp + 1; end if;
|
2131 |
|
|
s.s := r.w.s.ps;
|
2132 |
|
|
s.et := '1';
|
2133 |
|
|
when others => null;
|
2134 |
|
|
end case;
|
2135 |
|
|
when others => null;
|
2136 |
|
|
end case;
|
2137 |
|
|
if r.x.ctrl.wicc = '1' then s.icc := r.x.icc; end if;
|
2138 |
|
|
if r.x.ctrl.wy = '1' then s.y := r.x.y; end if;
|
2139 |
|
|
if MACPIPE and (r.x.mac = '1') then
|
2140 |
|
|
s.asr18 := mulo.result(31 downto 0);
|
2141 |
|
|
s.y := mulo.result(63 downto 32);
|
2142 |
|
|
end if;
|
2143 |
|
|
end;
|
2144 |
|
|
|
2145 |
|
|
function npc_find (r : registers) return std_logic_vector is
|
2146 |
|
|
variable npc : std_logic_vector(2 downto 0);
|
2147 |
|
|
begin
|
2148 |
|
|
npc := "011";
|
2149 |
|
|
if r.m.ctrl.pv = '1' then npc := "000";
|
2150 |
|
|
elsif r.e.ctrl.pv = '1' then npc := "001";
|
2151 |
|
|
elsif r.a.ctrl.pv = '1' then npc := "010";
|
2152 |
|
|
elsif r.d.pv = '1' then npc := "011";
|
2153 |
|
|
elsif v8 /= 0 then npc := "100"; end if;
|
2154 |
|
|
return(npc);
|
2155 |
|
|
end;
|
2156 |
|
|
|
2157 |
|
|
function npc_gen (r : registers) return word is
|
2158 |
|
|
variable npc : std_logic_vector(31 downto 0);
|
2159 |
|
|
begin
|
2160 |
|
|
npc := r.a.ctrl.pc(31 downto 2) & "00";
|
2161 |
|
|
case r.x.npc is
|
2162 |
|
|
when "000" => npc(31 downto 2) := r.x.ctrl.pc(31 downto 2);
|
2163 |
|
|
when "001" => npc(31 downto 2) := r.m.ctrl.pc(31 downto 2);
|
2164 |
|
|
when "010" => npc(31 downto 2) := r.e.ctrl.pc(31 downto 2);
|
2165 |
|
|
when "011" => npc(31 downto 2) := r.a.ctrl.pc(31 downto 2);
|
2166 |
|
|
when others =>
|
2167 |
|
|
if v8 /= 0 then npc(31 downto 2) := r.d.pc(31 downto 2); end if;
|
2168 |
|
|
end case;
|
2169 |
|
|
return(npc);
|
2170 |
|
|
end;
|
2171 |
|
|
|
2172 |
|
|
procedure mul_res(r : registers; asr18in : word; result, y, asr18 : out word;
|
2173 |
|
|
icc : out std_logic_vector(3 downto 0)) is
|
2174 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2175 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2176 |
|
|
begin
|
2177 |
|
|
op := r.m.ctrl.inst(31 downto 30); op3 := r.m.ctrl.inst(24 downto 19);
|
2178 |
|
|
result := r.m.result; y := r.m.y; icc := r.m.icc; asr18 := asr18in;
|
2179 |
|
|
case op is
|
2180 |
|
|
when FMT3 =>
|
2181 |
|
|
case op3 is
|
2182 |
|
|
when UMUL | SMUL =>
|
2183 |
|
|
if MULEN then
|
2184 |
|
|
result := mulo.result(31 downto 0);
|
2185 |
|
|
y := mulo.result(63 downto 32);
|
2186 |
|
|
end if;
|
2187 |
|
|
when UMULCC | SMULCC =>
|
2188 |
|
|
if MULEN then
|
2189 |
|
|
result := mulo.result(31 downto 0); icc := mulo.icc;
|
2190 |
|
|
y := mulo.result(63 downto 32);
|
2191 |
|
|
end if;
|
2192 |
|
|
when UMAC | SMAC =>
|
2193 |
|
|
if MACEN and not MACPIPE then
|
2194 |
|
|
result := mulo.result(31 downto 0);
|
2195 |
|
|
asr18 := mulo.result(31 downto 0);
|
2196 |
|
|
y := mulo.result(63 downto 32);
|
2197 |
|
|
end if;
|
2198 |
|
|
when UDIV | SDIV =>
|
2199 |
|
|
if DIVEN then
|
2200 |
|
|
result := divo.result(31 downto 0);
|
2201 |
|
|
end if;
|
2202 |
|
|
when UDIVCC | SDIVCC =>
|
2203 |
|
|
if DIVEN then
|
2204 |
|
|
result := divo.result(31 downto 0); icc := divo.icc;
|
2205 |
|
|
end if;
|
2206 |
|
|
when others => null;
|
2207 |
|
|
end case;
|
2208 |
|
|
when others => null;
|
2209 |
|
|
end case;
|
2210 |
|
|
end;
|
2211 |
|
|
|
2212 |
|
|
function powerdwn(r : registers; trap : std_ulogic; rp : pwd_register_type) return std_ulogic is
|
2213 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2214 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2215 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
2216 |
|
|
variable pd : std_ulogic;
|
2217 |
|
|
begin
|
2218 |
|
|
op := r.x.ctrl.inst(31 downto 30);
|
2219 |
|
|
op3 := r.x.ctrl.inst(24 downto 19);
|
2220 |
|
|
rd := r.x.ctrl.inst(29 downto 25);
|
2221 |
|
|
pd := '0';
|
2222 |
|
|
if (not (r.x.ctrl.annul or trap) and r.x.ctrl.pv) = '1' then
|
2223 |
|
|
if ((op = FMT3) and (op3 = WRY) and (rd = "10011")) then pd := '1'; end if;
|
2224 |
|
|
pd := pd or rp.pwd;
|
2225 |
|
|
end if;
|
2226 |
|
|
return(pd);
|
2227 |
|
|
end;
|
2228 |
|
|
|
2229 |
|
|
signal dummy : std_ulogic;
|
2230 |
|
|
signal cpu_index : std_logic_vector(3 downto 0);
|
2231 |
|
|
signal disasen : std_ulogic;
|
2232 |
|
|
|
2233 |
|
|
begin
|
2234 |
|
|
|
2235 |
|
|
comb : process(ico, dco, rfo, r, wpr, ir, dsur, rstn, holdn, irqi, dbgi, fpo, cpo, tbo,
|
2236 |
|
|
mulo, divo, dummy, rp)
|
2237 |
|
|
|
2238 |
|
|
variable v : registers;
|
2239 |
|
|
variable vp : pwd_register_type;
|
2240 |
|
|
variable vwpr : watchpoint_registers;
|
2241 |
|
|
variable vdsu : dsu_registers;
|
2242 |
|
|
variable npc : std_logic_vector(31 downto PCLOW);
|
2243 |
|
|
variable de_raddr1, de_raddr2 : std_logic_vector(9 downto 0);
|
2244 |
|
|
variable de_rs2, de_rd : std_logic_vector(4 downto 0);
|
2245 |
|
|
variable de_hold_pc, de_branch, de_fpop, de_ldlock : std_ulogic;
|
2246 |
|
|
variable de_cwp, de_cwp2 : cwptype;
|
2247 |
|
|
variable de_inull : std_ulogic;
|
2248 |
|
|
variable de_ren1, de_ren2 : std_ulogic;
|
2249 |
|
|
variable de_wcwp : std_ulogic;
|
2250 |
|
|
variable de_inst : word;
|
2251 |
|
|
variable de_branch_address : pctype;
|
2252 |
|
|
variable de_icc : std_logic_vector(3 downto 0);
|
2253 |
|
|
variable de_fbranch, de_cbranch : std_ulogic;
|
2254 |
|
|
variable de_rs1mod : std_ulogic;
|
2255 |
|
|
|
2256 |
|
|
variable ra_op1, ra_op2 : word;
|
2257 |
|
|
variable ra_div : std_ulogic;
|
2258 |
|
|
|
2259 |
|
|
variable ex_jump, ex_link_pc : std_ulogic;
|
2260 |
|
|
variable ex_jump_address : pctype;
|
2261 |
|
|
variable ex_add_res : std_logic_vector(32 downto 0);
|
2262 |
|
|
variable ex_shift_res, ex_logic_res, ex_misc_res : word;
|
2263 |
|
|
variable ex_edata, ex_edata2 : word;
|
2264 |
|
|
variable ex_dci : dc_in_type;
|
2265 |
|
|
variable ex_force_a2, ex_load, ex_ymsb : std_ulogic;
|
2266 |
|
|
variable ex_op1, ex_op2, ex_result, ex_result2, mul_op2 : word;
|
2267 |
|
|
variable ex_shcnt : std_logic_vector(4 downto 0);
|
2268 |
|
|
variable ex_dsuen : std_ulogic;
|
2269 |
|
|
variable ex_ldbp2 : std_ulogic;
|
2270 |
|
|
variable ex_sari : std_ulogic;
|
2271 |
|
|
|
2272 |
|
|
variable me_inull, me_nullify, me_nullify2 : std_ulogic;
|
2273 |
|
|
variable me_iflush : std_ulogic;
|
2274 |
|
|
variable me_newtt : std_logic_vector(5 downto 0);
|
2275 |
|
|
variable me_asr18 : word;
|
2276 |
|
|
variable me_signed : std_ulogic;
|
2277 |
|
|
variable me_size, me_laddr : std_logic_vector(1 downto 0);
|
2278 |
|
|
variable me_icc : std_logic_vector(3 downto 0);
|
2279 |
|
|
|
2280 |
|
|
|
2281 |
|
|
variable xc_result : word;
|
2282 |
|
|
variable xc_df_result : word;
|
2283 |
|
|
variable xc_waddr : std_logic_vector(9 downto 0);
|
2284 |
|
|
variable xc_exception, xc_wreg : std_ulogic;
|
2285 |
|
|
variable xc_trap_address : pctype;
|
2286 |
|
|
variable xc_vectt : std_logic_vector(7 downto 0);
|
2287 |
|
|
variable xc_trap : std_ulogic;
|
2288 |
|
|
variable xc_fpexack : std_ulogic;
|
2289 |
|
|
variable xc_rstn, xc_halt : std_ulogic;
|
2290 |
|
|
|
2291 |
|
|
-- variable wr_rf1_data, wr_rf2_data : word;
|
2292 |
|
|
variable diagdata : word;
|
2293 |
|
|
variable tbufi : tracebuf_in_type;
|
2294 |
|
|
variable dbgm : std_ulogic;
|
2295 |
|
|
variable fpcdbgwr : std_ulogic;
|
2296 |
|
|
variable vfpi : fpc_in_type;
|
2297 |
|
|
variable dsign : std_ulogic;
|
2298 |
|
|
variable pwrd, sidle : std_ulogic;
|
2299 |
|
|
variable vir : irestart_register;
|
2300 |
|
|
variable icnt : std_ulogic;
|
2301 |
|
|
variable tbufcntx : std_logic_vector(TBUFBITS-1 downto 0);
|
2302 |
|
|
|
2303 |
|
|
begin
|
2304 |
|
|
|
2305 |
|
|
v := r; vwpr := wpr; vdsu := dsur; vp := rp;
|
2306 |
|
|
xc_fpexack := '0'; sidle := '0';
|
2307 |
|
|
fpcdbgwr := '0'; vir := ir; xc_rstn := rstn;
|
2308 |
|
|
|
2309 |
|
|
-----------------------------------------------------------------------
|
2310 |
|
|
-- WRITE STAGE
|
2311 |
|
|
-----------------------------------------------------------------------
|
2312 |
|
|
|
2313 |
|
|
-- wr_rf1_data := rfo.data1; wr_rf2_data := rfo.data2;
|
2314 |
|
|
-- if irfwt = 0 then
|
2315 |
|
|
-- if r.w.wreg = '1' then
|
2316 |
|
|
-- if r.a.rfa1 = r.w.wa then wr_rf1_data := r.w.result; end if;
|
2317 |
|
|
-- if r.a.rfa2 = r.w.wa then wr_rf2_data := r.w.result; end if;
|
2318 |
|
|
-- end if;
|
2319 |
|
|
-- end if;
|
2320 |
|
|
|
2321 |
|
|
-----------------------------------------------------------------------
|
2322 |
|
|
-- EXCEPTION STAGE
|
2323 |
|
|
-----------------------------------------------------------------------
|
2324 |
|
|
|
2325 |
|
|
xc_exception := '0'; xc_halt := '0'; icnt := '0';
|
2326 |
|
|
xc_waddr := (others => '0');
|
2327 |
|
|
xc_waddr(RFBITS-1 downto 0) := r.x.ctrl.rd(RFBITS-1 downto 0);
|
2328 |
|
|
xc_trap := r.x.mexc or r.x.ctrl.trap;
|
2329 |
|
|
v.x.nerror := rp.error;
|
2330 |
|
|
|
2331 |
|
|
if r.x.mexc = '1' then xc_vectt := "00" & TT_DAEX;
|
2332 |
|
|
elsif r.x.ctrl.tt = TT_TICC then
|
2333 |
|
|
xc_vectt := '1' & r.x.result(6 downto 0);
|
2334 |
|
|
else xc_vectt := "00" & r.x.ctrl.tt; end if;
|
2335 |
|
|
if r.w.s.svt = '0' then
|
2336 |
|
|
xc_trap_address(31 downto 4) := r.w.s.tba & xc_vectt;
|
2337 |
|
|
else
|
2338 |
|
|
xc_trap_address(31 downto 4) := r.w.s.tba & "00000000";
|
2339 |
|
|
end if;
|
2340 |
|
|
xc_trap_address(3 downto PCLOW) := (others => '0');
|
2341 |
|
|
xc_wreg := '0'; v.x.annul_all := '0';
|
2342 |
|
|
if (r.x.ctrl.ld = '1') then
|
2343 |
|
|
if (lddel = 2) then
|
2344 |
|
|
xc_result := ld_align(r.x.data, r.x.set, r.x.dci.size, r.x.laddr, r.x.dci.signed);
|
2345 |
|
|
else xc_result := r.x.data(0); end if;
|
2346 |
|
|
elsif MACEN and MACPIPE and (r.x.mac = '1') then
|
2347 |
|
|
xc_result := mulo.result(31 downto 0);
|
2348 |
|
|
else xc_result := r.x.result; end if;
|
2349 |
|
|
xc_df_result := xc_result;
|
2350 |
|
|
if DBGUNIT then
|
2351 |
|
|
dbgm := dbgexc(r, dbgi, xc_trap, xc_vectt);
|
2352 |
|
|
if (dbgi.dsuen and dbgi.dbreak) = '0'then v.x.debug := '0'; end if;
|
2353 |
|
|
else dbgm := '0'; v.x.debug := '0'; end if;
|
2354 |
|
|
if PWRD2 then pwrd := powerdwn(r, xc_trap, rp); else pwrd := '0'; end if;
|
2355 |
|
|
|
2356 |
|
|
case r.x.rstate is
|
2357 |
|
|
when run =>
|
2358 |
|
|
if (not r.x.ctrl.annul and r.x.ctrl.pv and not r.x.debug) = '1' then
|
2359 |
|
|
icnt := holdn;
|
2360 |
|
|
end if;
|
2361 |
|
|
if dbgm = '1' then
|
2362 |
|
|
v.x.annul_all := '1'; vir.addr := r.x.ctrl.pc;
|
2363 |
|
|
v.x.rstate := dsu1; v.x.debug := '1';
|
2364 |
|
|
v.x.npc := npc_find(r);
|
2365 |
|
|
vdsu.tt := xc_vectt; vdsu.err := dbgerr(r, dbgi, xc_vectt);
|
2366 |
|
|
elsif (pwrd = '1') and (ir.pwd = '0') then
|
2367 |
|
|
v.x.annul_all := '1'; vir.addr := r.x.ctrl.pc;
|
2368 |
|
|
v.x.rstate := dsu1; v.x.npc := npc_find(r); vp.pwd := '1';
|
2369 |
|
|
elsif (r.x.ctrl.annul or xc_trap) = '0' then
|
2370 |
|
|
xc_wreg := r.x.ctrl.wreg;
|
2371 |
|
|
sp_write (r, wpr, v.w.s, vwpr);
|
2372 |
|
|
vir.pwd := '0';
|
2373 |
|
|
elsif ((not r.x.ctrl.annul) and xc_trap) = '1' then
|
2374 |
|
|
xc_exception := '1'; xc_result := r.x.ctrl.pc(31 downto 2) & "00";
|
2375 |
|
|
xc_wreg := '1'; v.w.s.tt := xc_vectt; v.w.s.ps := r.w.s.s;
|
2376 |
|
|
v.w.s.s := '1'; v.x.annul_all := '1'; v.x.rstate := trap;
|
2377 |
|
|
xc_waddr := (others => '0');
|
2378 |
|
|
xc_waddr(NWINLOG2 + 3 downto 0) := r.w.s.cwp & "0001";
|
2379 |
|
|
v.x.npc := npc_find(r);
|
2380 |
|
|
fpexack(r, xc_fpexack);
|
2381 |
|
|
if r.w.s.et = '0' then
|
2382 |
|
|
-- v.x.rstate := dsu1; xc_wreg := '0'; vp.error := '1';
|
2383 |
|
|
xc_wreg := '0';
|
2384 |
|
|
end if;
|
2385 |
|
|
end if;
|
2386 |
|
|
when trap =>
|
2387 |
|
|
xc_result := npc_gen(r); xc_wreg := '1';
|
2388 |
|
|
xc_waddr := (others => '0');
|
2389 |
|
|
xc_waddr(NWINLOG2 + 3 downto 0) := r.w.s.cwp & "0010";
|
2390 |
|
|
if (r.w.s.et = '1') then
|
2391 |
|
|
v.w.s.et := '0'; v.x.rstate := run;
|
2392 |
|
|
if (not CWPOPT) and (r.w.s.cwp = CWPMIN) then v.w.s.cwp := CWPMAX;
|
2393 |
|
|
else v.w.s.cwp := r.w.s.cwp - 1 ; end if;
|
2394 |
|
|
else
|
2395 |
|
|
v.x.rstate := dsu1; xc_wreg := '0'; vp.error := '1';
|
2396 |
|
|
end if;
|
2397 |
|
|
when dsu1 =>
|
2398 |
|
|
xc_exception := '1'; v.x.annul_all := '1';
|
2399 |
|
|
xc_trap_address(31 downto PCLOW) := r.f.pc;
|
2400 |
|
|
if DBGUNIT or PWRD2 or (smp /= 0) then
|
2401 |
|
|
xc_trap_address(31 downto PCLOW) := ir.addr;
|
2402 |
|
|
vir.addr := npc_gen(r)(31 downto PCLOW);
|
2403 |
|
|
v.x.rstate := dsu2;
|
2404 |
|
|
end if;
|
2405 |
|
|
if DBGUNIT then v.x.debug := r.x.debug; end if;
|
2406 |
|
|
when dsu2 =>
|
2407 |
|
|
xc_exception := '1'; v.x.annul_all := '1';
|
2408 |
|
|
xc_trap_address(31 downto PCLOW) := r.f.pc;
|
2409 |
|
|
if DBGUNIT or PWRD2 or (smp /= 0) then
|
2410 |
|
|
sidle := (rp.pwd or rp.error) and ico.idle and dco.idle and not r.x.debug;
|
2411 |
|
|
if DBGUNIT then
|
2412 |
|
|
if dbgi.reset = '1' then
|
2413 |
|
|
if smp /=0 then vp.pwd := not irqi.run; else vp.pwd := '0'; end if;
|
2414 |
|
|
vp.error := '0';
|
2415 |
|
|
end if;
|
2416 |
|
|
if (dbgi.dsuen and dbgi.dbreak) = '1'then v.x.debug := '1'; end if;
|
2417 |
|
|
diagwr(r, dsur, ir, dbgi, wpr, v.w.s, vwpr, vdsu.asi, xc_trap_address,
|
2418 |
|
|
vir.addr, vdsu.tbufcnt, xc_wreg, xc_waddr, xc_result, fpcdbgwr);
|
2419 |
|
|
xc_halt := dbgi.halt;
|
2420 |
|
|
end if;
|
2421 |
|
|
if r.x.ipend = '1' then vp.pwd := '0'; end if;
|
2422 |
|
|
if (rp.error or rp.pwd or r.x.debug or xc_halt) = '0' then
|
2423 |
|
|
v.x.rstate := run; v.x.annul_all := '0'; vp.error := '0';
|
2424 |
|
|
xc_trap_address(31 downto PCLOW) := ir.addr; v.x.debug := '0';
|
2425 |
|
|
vir.pwd := '1';
|
2426 |
|
|
end if;
|
2427 |
|
|
if (smp /= 0) and (irqi.rst = '1') then
|
2428 |
|
|
vp.pwd := '0'; vp.error := '0';
|
2429 |
|
|
end if;
|
2430 |
|
|
end if;
|
2431 |
|
|
when others =>
|
2432 |
|
|
end case;
|
2433 |
|
|
|
2434 |
|
|
irq_intack(r, holdn, v.x.intack);
|
2435 |
|
|
itrace(r, dsur, vdsu, xc_result, xc_exception, dbgi, rp.error, xc_trap, tbufcntx, tbufi);
|
2436 |
|
|
vdsu.tbufcnt := tbufcntx;
|
2437 |
|
|
|
2438 |
|
|
v.w.except := xc_exception; v.w.result := xc_result;
|
2439 |
|
|
if (r.x.rstate = dsu2) then v.w.except := '0'; end if;
|
2440 |
|
|
v.w.wa := xc_waddr(RFBITS-1 downto 0); v.w.wreg := xc_wreg and holdn;
|
2441 |
|
|
|
2442 |
|
|
rfi.wdata <= xc_result; rfi.waddr <= xc_waddr;
|
2443 |
|
|
rfi.wren <= (xc_wreg and holdn) and not dco.scanen;
|
2444 |
|
|
irqo.intack <= r.x.intack and holdn;
|
2445 |
|
|
irqo.irl <= r.w.s.tt(3 downto 0);
|
2446 |
|
|
irqo.pwd <= rp.pwd;
|
2447 |
|
|
dbgo.halt <= xc_halt;
|
2448 |
|
|
dbgo.pwd <= rp.pwd;
|
2449 |
|
|
dbgo.idle <= sidle;
|
2450 |
|
|
dbgo.icnt <= icnt;
|
2451 |
|
|
dci.intack <= r.x.intack and holdn;
|
2452 |
|
|
|
2453 |
|
|
if (xc_rstn = '0') then
|
2454 |
|
|
v.w.except := '0'; v.w.s.et := '0'; v.w.s.svt := '0'; v.w.s.dwt := '0';
|
2455 |
|
|
v.x.annul_all := '1'; v.x.rstate := run; vir.pwd := '0';
|
2456 |
|
|
vp.pwd := '0'; v.x.debug := '0'; --vp.error := '0';
|
2457 |
|
|
v.x.nerror := '0';
|
2458 |
|
|
if svt = 1 then v.w.s.tt := (others => '0'); end if;
|
2459 |
|
|
if DBGUNIT then
|
2460 |
|
|
if (dbgi.dsuen and dbgi.dbreak) = '1' then
|
2461 |
|
|
v.x.rstate := dsu1; v.x.debug := '1';
|
2462 |
|
|
end if;
|
2463 |
|
|
end if;
|
2464 |
|
|
if (smp /= 0) and (irqi.run = '0') and (rstn = '0') then
|
2465 |
|
|
v.x.rstate := dsu1; vp.pwd := '1';
|
2466 |
|
|
end if;
|
2467 |
|
|
end if;
|
2468 |
|
|
|
2469 |
|
|
if not FPEN then v.w.s.ef := '0'; end if;
|
2470 |
|
|
|
2471 |
|
|
-----------------------------------------------------------------------
|
2472 |
|
|
-- MEMORY STAGE
|
2473 |
|
|
-----------------------------------------------------------------------
|
2474 |
|
|
|
2475 |
|
|
v.x.ctrl := r.m.ctrl; v.x.dci := r.m.dci;
|
2476 |
|
|
v.x.ctrl.rett := r.m.ctrl.rett and not r.m.ctrl.annul;
|
2477 |
|
|
v.x.mac := r.m.mac; v.x.laddr := r.m.result(1 downto 0);
|
2478 |
|
|
v.x.ctrl.annul := r.m.ctrl.annul or v.x.annul_all;
|
2479 |
|
|
|
2480 |
|
|
mul_res(r, v.w.s.asr18, v.x.result, v.x.y, me_asr18, me_icc);
|
2481 |
|
|
mem_trap(r, wpr, v.x.ctrl.annul, holdn, v.x.ctrl.trap, me_iflush,
|
2482 |
|
|
me_nullify, v.m.werr, v.x.ctrl.tt);
|
2483 |
|
|
me_newtt := v.x.ctrl.tt;
|
2484 |
|
|
|
2485 |
|
|
irq_trap(r, ir, irqi.irl, v.x.ctrl.annul, v.x.ctrl.pv, v.x.ctrl.trap, me_newtt, me_nullify,
|
2486 |
|
|
v.m.irqen, v.m.irqen2, me_nullify2, v.x.ctrl.trap,
|
2487 |
|
|
v.x.ipend, v.x.ctrl.tt);
|
2488 |
|
|
|
2489 |
|
|
if (r.m.ctrl.ld or not dco.mds) = '1' then
|
2490 |
|
|
for i in 0 to dsets-1 loop v.x.data(i) := dco.data(i); end loop;
|
2491 |
|
|
v.x.set := dco.set(DSETMSB downto 0);
|
2492 |
|
|
if dco.mds = '0' then
|
2493 |
|
|
me_size := r.x.dci.size; me_laddr := r.x.laddr; me_signed := r.x.dci.signed;
|
2494 |
|
|
else
|
2495 |
|
|
me_size := v.x.dci.size; me_laddr := v.x.laddr; me_signed := v.x.dci.signed;
|
2496 |
|
|
end if;
|
2497 |
|
|
if lddel /= 2 then
|
2498 |
|
|
v.x.data(0) := ld_align(v.x.data, v.x.set, me_size, me_laddr, me_signed);
|
2499 |
|
|
end if;
|
2500 |
|
|
end if;
|
2501 |
|
|
v.x.mexc := dco.mexc;
|
2502 |
|
|
|
2503 |
|
|
v.x.icc := me_icc;
|
2504 |
|
|
v.x.ctrl.wicc := r.m.ctrl.wicc and not v.x.annul_all;
|
2505 |
|
|
|
2506 |
|
|
if MACEN and ((v.x.ctrl.annul or v.x.ctrl.trap) = '0') then
|
2507 |
|
|
v.w.s.asr18 := me_asr18;
|
2508 |
|
|
end if;
|
2509 |
|
|
|
2510 |
|
|
if (r.x.rstate = dsu2) then
|
2511 |
|
|
me_nullify2 := '0'; v.x.set := dco.set(DSETMSB downto 0);
|
2512 |
|
|
end if;
|
2513 |
|
|
|
2514 |
|
|
dci.maddress <= r.m.result;
|
2515 |
|
|
dci.enaddr <= r.m.dci.enaddr;
|
2516 |
|
|
dci.asi <= r.m.dci.asi;
|
2517 |
|
|
dci.size <= r.m.dci.size;
|
2518 |
|
|
dci.nullify <= me_nullify2;
|
2519 |
|
|
dci.lock <= r.m.dci.lock and not r.m.ctrl.annul;
|
2520 |
|
|
dci.read <= r.m.dci.read;
|
2521 |
|
|
dci.write <= r.m.dci.write;
|
2522 |
|
|
dci.flush <= me_iflush;
|
2523 |
|
|
dci.dsuen <= r.m.dci.dsuen;
|
2524 |
|
|
dci.msu <= r.m.su;
|
2525 |
|
|
dci.esu <= r.e.su;
|
2526 |
|
|
dbgo.ipend <= v.x.ipend;
|
2527 |
|
|
|
2528 |
|
|
-----------------------------------------------------------------------
|
2529 |
|
|
-- EXECUTE STAGE
|
2530 |
|
|
-----------------------------------------------------------------------
|
2531 |
|
|
|
2532 |
|
|
v.m.ctrl := r.e.ctrl; ex_op1 := r.e.op1; ex_op2 := r.e.op2;
|
2533 |
|
|
v.m.ctrl.rett := r.e.ctrl.rett and not r.e.ctrl.annul;
|
2534 |
|
|
v.m.ctrl.wreg := r.e.ctrl.wreg and not v.x.annul_all;
|
2535 |
|
|
ex_ymsb := r.e.ymsb; mul_op2 := ex_op2; ex_shcnt := r.e.shcnt;
|
2536 |
|
|
v.e.cwp := r.a.cwp; ex_sari := r.e.sari;
|
2537 |
|
|
v.m.su := r.e.su;
|
2538 |
|
|
if MULTYPE = 3 then v.m.mul := r.e.mul; else v.m.mul := '0'; end if;
|
2539 |
|
|
|
2540 |
|
|
if lddel = 1 then
|
2541 |
|
|
if r.e.ldbp1 = '1' then
|
2542 |
|
|
ex_op1 := r.x.data(0);
|
2543 |
|
|
ex_sari := r.x.data(0)(31) and r.e.ctrl.inst(19) and r.e.ctrl.inst(20);
|
2544 |
|
|
end if;
|
2545 |
|
|
if r.e.ldbp2 = '1' then
|
2546 |
|
|
ex_op2 := r.x.data(0); ex_ymsb := r.x.data(0)(0);
|
2547 |
|
|
mul_op2 := ex_op2; ex_shcnt := r.x.data(0)(4 downto 0);
|
2548 |
|
|
if r.e.invop2 = '1' then
|
2549 |
|
|
ex_op2 := not ex_op2; ex_shcnt := not ex_shcnt;
|
2550 |
|
|
end if;
|
2551 |
|
|
end if;
|
2552 |
|
|
end if;
|
2553 |
|
|
|
2554 |
|
|
ex_add_res := (ex_op1 & '1') + (ex_op2 & r.e.alucin);
|
2555 |
|
|
|
2556 |
|
|
if ex_add_res(2 downto 1) = "00" then v.m.nalign := '0';
|
2557 |
|
|
else v.m.nalign := '1'; end if;
|
2558 |
|
|
|
2559 |
|
|
dcache_gen(r, v, ex_dci, ex_link_pc, ex_jump, ex_force_a2, ex_load );
|
2560 |
|
|
ex_jump_address := ex_add_res(32 downto PCLOW+1);
|
2561 |
|
|
logic_op(r, ex_op1, ex_op2, v.x.y, ex_ymsb, ex_logic_res, v.m.y);
|
2562 |
|
|
ex_shift_res := shift(r, ex_op1, ex_op2, ex_shcnt, ex_sari);
|
2563 |
|
|
misc_op(r, wpr, ex_op1, ex_op2, xc_df_result, v.x.y, ex_misc_res, ex_edata);
|
2564 |
|
|
ex_add_res(3):= ex_add_res(3) or ex_force_a2;
|
2565 |
|
|
alu_select(r, ex_add_res, ex_op1, ex_op2, ex_shift_res, ex_logic_res,
|
2566 |
|
|
ex_misc_res, ex_result, me_icc, v.m.icc, v.m.divz);
|
2567 |
|
|
dbg_cache(holdn, dbgi, r, dsur, ex_result, ex_dci, ex_result2, v.m.dci);
|
2568 |
|
|
fpstdata(r, ex_edata, ex_result2, fpo.data, ex_edata2, v.m.result);
|
2569 |
|
|
cwp_ex(r, v.m.wcwp);
|
2570 |
|
|
|
2571 |
|
|
v.m.ctrl.annul := v.m.ctrl.annul or v.x.annul_all;
|
2572 |
|
|
v.m.ctrl.wicc := r.e.ctrl.wicc and not v.x.annul_all;
|
2573 |
|
|
v.m.mac := r.e.mac;
|
2574 |
|
|
if (DBGUNIT and (r.x.rstate = dsu2)) then v.m.ctrl.ld := '1'; end if;
|
2575 |
|
|
dci.eenaddr <= v.m.dci.enaddr;
|
2576 |
|
|
dci.eaddress <= ex_add_res(32 downto 1);
|
2577 |
|
|
dci.edata <= ex_edata2;
|
2578 |
|
|
|
2579 |
|
|
-----------------------------------------------------------------------
|
2580 |
|
|
-- REGFILE STAGE
|
2581 |
|
|
-----------------------------------------------------------------------
|
2582 |
|
|
|
2583 |
|
|
v.e.ctrl := r.a.ctrl; v.e.jmpl := r.a.jmpl;
|
2584 |
|
|
v.e.ctrl.annul := r.a.ctrl.annul or v.x.annul_all;
|
2585 |
|
|
v.e.ctrl.rett := r.a.ctrl.rett and not r.a.ctrl.annul;
|
2586 |
|
|
v.e.ctrl.wreg := r.a.ctrl.wreg and not v.x.annul_all;
|
2587 |
|
|
v.e.su := r.a.su; v.e.et := r.a.et;
|
2588 |
|
|
v.e.ctrl.wicc := r.a.ctrl.wicc and not v.x.annul_all;
|
2589 |
|
|
|
2590 |
|
|
exception_detect(r, wpr, dbgi, r.a.ctrl.trap, r.a.ctrl.tt,
|
2591 |
|
|
v.e.ctrl.trap, v.e.ctrl.tt);
|
2592 |
|
|
op_mux(r, rfo.data1, v.m.result, v.x.result, xc_df_result, zero32,
|
2593 |
|
|
r.a.rsel1, v.e.ldbp1, ra_op1);
|
2594 |
|
|
op_mux(r, rfo.data2, v.m.result, v.x.result, xc_df_result, r.a.imm,
|
2595 |
|
|
r.a.rsel2, ex_ldbp2, ra_op2);
|
2596 |
|
|
alu_op(r, ra_op1, ra_op2, v.m.icc, v.m.y(0), ex_ldbp2, v.e.op1, v.e.op2,
|
2597 |
|
|
v.e.aluop, v.e.alusel, v.e.aluadd, v.e.shcnt, v.e.sari, v.e.shleft,
|
2598 |
|
|
v.e.ymsb, v.e.mul, ra_div, v.e.mulstep, v.e.mac, v.e.ldbp2, v.e.invop2);
|
2599 |
|
|
cin_gen(r, v.m.icc(0), v.e.alucin);
|
2600 |
|
|
|
2601 |
|
|
-----------------------------------------------------------------------
|
2602 |
|
|
-- DECODE STAGE
|
2603 |
|
|
-----------------------------------------------------------------------
|
2604 |
|
|
|
2605 |
|
|
if ISETS > 1 then de_inst := r.d.inst(conv_integer(r.d.set));
|
2606 |
|
|
else de_inst := r.d.inst(0); end if;
|
2607 |
|
|
|
2608 |
|
|
de_icc := r.m.icc; v.a.cwp := r.d.cwp;
|
2609 |
|
|
su_et_select(r, v.w.s.ps, v.w.s.s, v.w.s.et, v.a.su, v.a.et);
|
2610 |
|
|
wicc_y_gen(de_inst, v.a.ctrl.wicc, v.a.ctrl.wy);
|
2611 |
|
|
cwp_ctrl(r, v.w.s.wim, de_inst, de_cwp, v.a.wovf, v.a.wunf, de_wcwp);
|
2612 |
|
|
rs1_gen(r, de_inst, v.a.rs1, de_rs1mod);
|
2613 |
|
|
de_rs2 := de_inst(4 downto 0);
|
2614 |
|
|
de_raddr1 := (others => '0'); de_raddr2 := (others => '0');
|
2615 |
|
|
|
2616 |
|
|
if RS1OPT then
|
2617 |
|
|
if de_rs1mod = '1' then
|
2618 |
|
|
regaddr(r.d.cwp, de_inst(29 downto 26) & v.a.rs1(0), de_raddr1(RFBITS-1 downto 0));
|
2619 |
|
|
else
|
2620 |
|
|
regaddr(r.d.cwp, de_inst(18 downto 15) & v.a.rs1(0), de_raddr1(RFBITS-1 downto 0));
|
2621 |
|
|
end if;
|
2622 |
|
|
else
|
2623 |
|
|
regaddr(r.d.cwp, v.a.rs1, de_raddr1(RFBITS-1 downto 0));
|
2624 |
|
|
end if;
|
2625 |
|
|
regaddr(r.d.cwp, de_rs2, de_raddr2(RFBITS-1 downto 0));
|
2626 |
|
|
v.a.rfa1 := de_raddr1(RFBITS-1 downto 0);
|
2627 |
|
|
v.a.rfa2 := de_raddr2(RFBITS-1 downto 0);
|
2628 |
|
|
|
2629 |
|
|
rd_gen(r, de_inst, v.a.ctrl.wreg, v.a.ctrl.ld, de_rd);
|
2630 |
|
|
regaddr(de_cwp, de_rd, v.a.ctrl.rd);
|
2631 |
|
|
|
2632 |
|
|
fpbranch(de_inst, fpo.cc, de_fbranch);
|
2633 |
|
|
fpbranch(de_inst, cpo.cc, de_cbranch);
|
2634 |
|
|
v.a.imm := imm_data(r, de_inst);
|
2635 |
|
|
lock_gen(r, de_rs2, de_rd, v.a.rfa1, v.a.rfa2, v.a.ctrl.rd, de_inst,
|
2636 |
|
|
fpo.ldlock, v.e.mul, ra_div, v.a.ldcheck1, v.a.ldcheck2, de_ldlock,
|
2637 |
|
|
v.a.ldchkra, v.a.ldchkex);
|
2638 |
|
|
ic_ctrl(r, de_inst, v.x.annul_all, de_ldlock, branch_true(de_icc, de_inst),
|
2639 |
|
|
de_fbranch, de_cbranch, fpo.ccv, cpo.ccv, v.d.cnt, v.d.pc, de_branch,
|
2640 |
|
|
v.a.ctrl.annul, v.d.annul, v.a.jmpl, de_inull, v.d.pv, v.a.ctrl.pv,
|
2641 |
|
|
de_hold_pc, v.a.ticc, v.a.ctrl.rett, v.a.mulstart, v.a.divstart);
|
2642 |
|
|
|
2643 |
|
|
cwp_gen(r, v, v.a.ctrl.annul, de_wcwp, de_cwp, v.d.cwp);
|
2644 |
|
|
|
2645 |
|
|
v.d.inull := ra_inull_gen(r, v);
|
2646 |
|
|
|
2647 |
|
|
op_find(r, v.a.ldchkra, v.a.ldchkex, v.a.rs1, v.a.rfa1,
|
2648 |
|
|
false, v.a.rfe1, v.a.rsel1, v.a.ldcheck1);
|
2649 |
|
|
op_find(r, v.a.ldchkra, v.a.ldchkex, de_rs2, v.a.rfa2,
|
2650 |
|
|
imm_select(de_inst), v.a.rfe2, v.a.rsel2, v.a.ldcheck2);
|
2651 |
|
|
|
2652 |
|
|
de_branch_address := branch_address(de_inst, r.d.pc);
|
2653 |
|
|
|
2654 |
|
|
v.a.ctrl.annul := v.a.ctrl.annul or v.x.annul_all;
|
2655 |
|
|
v.a.ctrl.wicc := v.a.ctrl.wicc and not v.a.ctrl.annul;
|
2656 |
|
|
v.a.ctrl.wreg := v.a.ctrl.wreg and not v.a.ctrl.annul;
|
2657 |
|
|
v.a.ctrl.rett := v.a.ctrl.rett and not v.a.ctrl.annul;
|
2658 |
|
|
v.a.ctrl.wy := v.a.ctrl.wy and not v.a.ctrl.annul;
|
2659 |
|
|
|
2660 |
|
|
v.a.ctrl.trap := r.d.mexc;
|
2661 |
|
|
v.a.ctrl.tt := "000000";
|
2662 |
|
|
v.a.ctrl.inst := de_inst;
|
2663 |
|
|
v.a.ctrl.pc := r.d.pc;
|
2664 |
|
|
v.a.ctrl.cnt := r.d.cnt;
|
2665 |
|
|
v.a.step := r.d.step;
|
2666 |
|
|
|
2667 |
|
|
if holdn = '0' then
|
2668 |
|
|
de_raddr1(RFBITS-1 downto 0) := r.a.rfa1;
|
2669 |
|
|
de_raddr2(RFBITS-1 downto 0) := r.a.rfa2;
|
2670 |
|
|
de_ren1 := r.a.rfe1; de_ren2 := r.a.rfe2;
|
2671 |
|
|
else
|
2672 |
|
|
de_ren1 := v.a.rfe1; de_ren2 := v.a.rfe2;
|
2673 |
|
|
end if;
|
2674 |
|
|
|
2675 |
|
|
if DBGUNIT then
|
2676 |
|
|
if ((dbgi.denable and not dbgi.dwrite) = '1') and (r.x.rstate = dsu2) then
|
2677 |
|
|
de_raddr1(RFBITS-1 downto 0) := dbgi.daddr(RFBITS+1 downto 2); de_ren1 := '1';
|
2678 |
|
|
end if;
|
2679 |
|
|
v.d.step := dbgi.step and not r.d.annul;
|
2680 |
|
|
end if;
|
2681 |
|
|
|
2682 |
|
|
rfi.raddr1 <= de_raddr1; rfi.raddr2 <= de_raddr2;
|
2683 |
|
|
rfi.ren1 <= de_ren1 and not dco.scanen;
|
2684 |
|
|
rfi.ren2 <= de_ren2 and not dco.scanen;
|
2685 |
|
|
rfi.diag <= dco.testen & "000";
|
2686 |
|
|
ici.inull <= de_inull;
|
2687 |
|
|
ici.flush <= me_iflush;
|
2688 |
|
|
if (xc_rstn = '0') then v.d.cnt := (others => '0'); end if;
|
2689 |
|
|
|
2690 |
|
|
-----------------------------------------------------------------------
|
2691 |
|
|
-- FETCH STAGE
|
2692 |
|
|
-----------------------------------------------------------------------
|
2693 |
|
|
|
2694 |
|
|
npc := r.f.pc;
|
2695 |
|
|
if (xc_rstn = '0') then
|
2696 |
|
|
v.f.pc := (others => '0'); v.f.branch := '0';
|
2697 |
|
|
if DYNRST then v.f.pc(31 downto 12) := irqi.rstvec;
|
2698 |
|
|
else
|
2699 |
|
|
v.f.pc(31 downto 12) := conv_std_logic_vector(rstaddr, 20);
|
2700 |
|
|
end if;
|
2701 |
|
|
elsif xc_exception = '1' then -- exception
|
2702 |
|
|
v.f.branch := '1'; v.f.pc := xc_trap_address;
|
2703 |
|
|
npc := v.f.pc;
|
2704 |
|
|
-- elsif (not ra_inull and de_hold_pc) = '1' then
|
2705 |
|
|
elsif de_hold_pc = '1' then
|
2706 |
|
|
v.f.pc := r.f.pc; v.f.branch := r.f.branch;
|
2707 |
|
|
if ex_jump = '1' then
|
2708 |
|
|
v.f.pc := ex_jump_address; v.f.branch := '1';
|
2709 |
|
|
npc := v.f.pc;
|
2710 |
|
|
end if;
|
2711 |
|
|
elsif ex_jump = '1' then
|
2712 |
|
|
v.f.pc := ex_jump_address; v.f.branch := '1';
|
2713 |
|
|
npc := v.f.pc;
|
2714 |
|
|
elsif de_branch = '1' then
|
2715 |
|
|
v.f.pc := branch_address(de_inst, r.d.pc); v.f.branch := '1';
|
2716 |
|
|
npc := v.f.pc;
|
2717 |
|
|
else
|
2718 |
|
|
v.f.branch := '0';
|
2719 |
|
|
v.f.pc(31 downto 2) := r.f.pc(31 downto 2) + 1; -- Address incrementer
|
2720 |
|
|
npc := v.f.pc;
|
2721 |
|
|
end if;
|
2722 |
|
|
|
2723 |
|
|
ici.dpc <= r.d.pc(31 downto 2) & "00";
|
2724 |
|
|
ici.fpc <= r.f.pc(31 downto 2) & "00";
|
2725 |
|
|
ici.rpc <= npc(31 downto 2) & "00";
|
2726 |
|
|
ici.fbranch <= r.f.branch;
|
2727 |
|
|
ici.rbranch <= v.f.branch;
|
2728 |
|
|
ici.su <= v.a.su;
|
2729 |
|
|
ici.fline <= (others => '0');
|
2730 |
|
|
ici.flushl <= '0';
|
2731 |
|
|
|
2732 |
|
|
if (ico.mds and de_hold_pc) = '0' then
|
2733 |
|
|
for i in 0 to isets-1 loop
|
2734 |
|
|
v.d.inst(i) := ico.data(i); -- latch instruction
|
2735 |
|
|
end loop;
|
2736 |
|
|
v.d.set := ico.set(ISETMSB downto 0); -- latch instruction
|
2737 |
|
|
v.d.mexc := ico.mexc; -- latch instruction
|
2738 |
|
|
end if;
|
2739 |
|
|
|
2740 |
|
|
-----------------------------------------------------------------------
|
2741 |
|
|
-----------------------------------------------------------------------
|
2742 |
|
|
|
2743 |
|
|
if DBGUNIT then -- DSU diagnostic read
|
2744 |
|
|
diagread(dbgi, r, dsur, ir, wpr, dco, tbo, diagdata);
|
2745 |
|
|
diagrdy(dbgi.denable, dsur, r.m.dci, dco.mds, ico, vdsu.crdy);
|
2746 |
|
|
end if;
|
2747 |
|
|
|
2748 |
|
|
-----------------------------------------------------------------------
|
2749 |
|
|
-- OUTPUTS
|
2750 |
|
|
-----------------------------------------------------------------------
|
2751 |
|
|
|
2752 |
|
|
rin <= v; wprin <= vwpr; dsuin <= vdsu; irin <= vir;
|
2753 |
|
|
muli.start <= r.a.mulstart and not r.a.ctrl.annul;
|
2754 |
|
|
muli.signed <= r.e.ctrl.inst(19);
|
2755 |
|
|
muli.op1 <= (ex_op1(31) and r.e.ctrl.inst(19)) & ex_op1;
|
2756 |
|
|
muli.op2 <= (mul_op2(31) and r.e.ctrl.inst(19)) & mul_op2;
|
2757 |
|
|
muli.mac <= r.e.ctrl.inst(24);
|
2758 |
|
|
if MACPIPE then muli.acc(39 downto 32) <= r.w.s.y(7 downto 0);
|
2759 |
|
|
else muli.acc(39 downto 32) <= r.x.y(7 downto 0); end if;
|
2760 |
|
|
muli.acc(31 downto 0) <= r.w.s.asr18;
|
2761 |
|
|
muli.flush <= r.x.annul_all;
|
2762 |
|
|
divi.start <= r.a.divstart and not r.a.ctrl.annul;
|
2763 |
|
|
divi.signed <= r.e.ctrl.inst(19);
|
2764 |
|
|
divi.flush <= r.x.annul_all;
|
2765 |
|
|
divi.op1 <= (ex_op1(31) and r.e.ctrl.inst(19)) & ex_op1;
|
2766 |
|
|
divi.op2 <= (ex_op2(31) and r.e.ctrl.inst(19)) & ex_op2;
|
2767 |
|
|
if (r.a.divstart and not r.a.ctrl.annul) = '1' then
|
2768 |
|
|
dsign := r.a.ctrl.inst(19);
|
2769 |
|
|
else dsign := r.e.ctrl.inst(19); end if;
|
2770 |
|
|
divi.y <= (r.m.y(31) and dsign) & r.m.y;
|
2771 |
|
|
rpin <= vp;
|
2772 |
|
|
|
2773 |
|
|
if DBGUNIT then
|
2774 |
|
|
dbgo.dsu <= '1'; dbgo.dsumode <= r.x.debug; dbgo.crdy <= dsur.crdy(2);
|
2775 |
|
|
dbgo.data <= diagdata;
|
2776 |
|
|
if TRACEBUF then tbi <= tbufi; else
|
2777 |
|
|
tbi.addr <= (others => '0'); tbi.data <= (others => '0');
|
2778 |
|
|
tbi.enable <= '0'; tbi.write <= (others => '0'); tbi.diag <= "0000";
|
2779 |
|
|
end if;
|
2780 |
|
|
else
|
2781 |
|
|
dbgo.dsu <= '0'; dbgo.data <= (others => '0'); dbgo.crdy <= '0';
|
2782 |
|
|
dbgo.dsumode <= '0';
|
2783 |
|
|
tbi.addr <= (others => '0'); tbi.data <= (others => '0');
|
2784 |
|
|
tbi.enable <= '0'; tbi.write <= (others => '0'); tbi.diag <= "0000";
|
2785 |
|
|
end if;
|
2786 |
|
|
dbgo.error <= dummy and not r.x.nerror;
|
2787 |
|
|
|
2788 |
|
|
-- pragma translate_off
|
2789 |
|
|
if FPEN then
|
2790 |
|
|
-- pragma translate_on
|
2791 |
|
|
vfpi.flush := v.x.annul_all; vfpi.exack := xc_fpexack; vfpi.a_rs1 := r.a.rs1; vfpi.d.inst := de_inst;
|
2792 |
|
|
vfpi.d.cnt := r.d.cnt; vfpi.d.annul := v.x.annul_all or r.d.annul; vfpi.d.trap := r.d.mexc;
|
2793 |
|
|
vfpi.d.pc(1 downto 0) := (others => '0'); vfpi.d.pc(31 downto PCLOW) := r.d.pc(31 downto PCLOW);
|
2794 |
|
|
vfpi.d.pv := r.d.pv;
|
2795 |
|
|
vfpi.a.pc(1 downto 0) := (others => '0'); vfpi.a.pc(31 downto PCLOW) := r.a.ctrl.pc(31 downto PCLOW);
|
2796 |
|
|
vfpi.a.inst := r.a.ctrl.inst; vfpi.a.cnt := r.a.ctrl.cnt; vfpi.a.trap := r.a.ctrl.trap;
|
2797 |
|
|
vfpi.a.annul := r.a.ctrl.annul; vfpi.a.pv := r.a.ctrl.pv;
|
2798 |
|
|
vfpi.e.pc(1 downto 0) := (others => '0'); vfpi.e.pc(31 downto PCLOW) := r.e.ctrl.pc(31 downto PCLOW);
|
2799 |
|
|
vfpi.e.inst := r.e.ctrl.inst; vfpi.e.cnt := r.e.ctrl.cnt; vfpi.e.trap := r.e.ctrl.trap; vfpi.e.annul := r.e.ctrl.annul;
|
2800 |
|
|
vfpi.e.pv := r.e.ctrl.pv;
|
2801 |
|
|
vfpi.m.pc(1 downto 0) := (others => '0'); vfpi.m.pc(31 downto PCLOW) := r.m.ctrl.pc(31 downto PCLOW);
|
2802 |
|
|
vfpi.m.inst := r.m.ctrl.inst; vfpi.m.cnt := r.m.ctrl.cnt; vfpi.m.trap := r.m.ctrl.trap; vfpi.m.annul := r.m.ctrl.annul;
|
2803 |
|
|
vfpi.m.pv := r.m.ctrl.pv;
|
2804 |
|
|
vfpi.x.pc(1 downto 0) := (others => '0'); vfpi.x.pc(31 downto PCLOW) := r.x.ctrl.pc(31 downto PCLOW);
|
2805 |
|
|
vfpi.x.inst := r.x.ctrl.inst; vfpi.x.cnt := r.x.ctrl.cnt; vfpi.x.trap := xc_trap;
|
2806 |
|
|
vfpi.x.annul := r.x.ctrl.annul; vfpi.x.pv := r.x.ctrl.pv; vfpi.lddata := xc_df_result;--xc_result;
|
2807 |
|
|
if r.x.rstate = dsu2 then vfpi.dbg.enable := dbgi.denable;
|
2808 |
|
|
else vfpi.dbg.enable := '0'; end if;
|
2809 |
|
|
vfpi.dbg.write := fpcdbgwr;
|
2810 |
|
|
vfpi.dbg.fsr := dbgi.daddr(22); -- IU reg access
|
2811 |
|
|
vfpi.dbg.addr := dbgi.daddr(6 downto 2);
|
2812 |
|
|
vfpi.dbg.data := dbgi.ddata;
|
2813 |
|
|
fpi <= vfpi;
|
2814 |
|
|
cpi <= vfpi; -- dummy, just to kill some warnings ...
|
2815 |
|
|
-- pragma translate_off
|
2816 |
|
|
end if;
|
2817 |
|
|
-- pragma translate_on
|
2818 |
|
|
|
2819 |
|
|
end process;
|
2820 |
|
|
|
2821 |
|
|
preg : process (sclk)
|
2822 |
|
|
begin
|
2823 |
|
|
if rising_edge(sclk) then
|
2824 |
|
|
rp <= rpin;
|
2825 |
|
|
if rstn = '0' then rp.error <= '0'; end if;
|
2826 |
|
|
end if;
|
2827 |
|
|
end process;
|
2828 |
|
|
|
2829 |
|
|
reg : process (clk)
|
2830 |
|
|
begin
|
2831 |
|
|
if rising_edge(clk) then
|
2832 |
|
|
if (holdn = '1') then
|
2833 |
|
|
r <= rin;
|
2834 |
|
|
else
|
2835 |
|
|
r.x.ipend <= rin.x.ipend;
|
2836 |
|
|
r.m.werr <= rin.m.werr;
|
2837 |
|
|
if (holdn or ico.mds) = '0' then
|
2838 |
|
|
r.d.inst <= rin.d.inst; r.d.mexc <= rin.d.mexc;
|
2839 |
|
|
r.d.set <= rin.d.set;
|
2840 |
|
|
end if;
|
2841 |
|
|
if (holdn or dco.mds) = '0' then
|
2842 |
|
|
r.x.data <= rin.x.data; r.x.mexc <= rin.x.mexc;
|
2843 |
|
|
r.x.set <= rin.x.set;
|
2844 |
|
|
end if;
|
2845 |
|
|
end if;
|
2846 |
|
|
if rstn = '0' then
|
2847 |
|
|
r.w.s.s <= '1';
|
2848 |
|
|
if fabtech = axcel then
|
2849 |
|
|
r.d.inst <= (others => (others => '0'));
|
2850 |
|
|
end if;
|
2851 |
|
|
end if;
|
2852 |
|
|
end if;
|
2853 |
|
|
end process;
|
2854 |
|
|
|
2855 |
|
|
|
2856 |
|
|
dsugen : if DBGUNIT generate
|
2857 |
|
|
dsureg : process(clk) begin
|
2858 |
|
|
if rising_edge(clk) then
|
2859 |
|
|
if holdn = '1' then
|
2860 |
|
|
dsur <= dsuin;
|
2861 |
|
|
else
|
2862 |
|
|
dsur.crdy <= dsuin.crdy;
|
2863 |
|
|
end if;
|
2864 |
|
|
end if;
|
2865 |
|
|
end process;
|
2866 |
|
|
end generate;
|
2867 |
|
|
|
2868 |
|
|
nodsugen : if not DBGUNIT generate
|
2869 |
|
|
dsur.err <= '0'; dsur.tbufcnt <= (others => '0'); dsur.tt <= (others => '0');
|
2870 |
|
|
dsur.asi <= (others => '0'); dsur.crdy <= (others => '0');
|
2871 |
|
|
end generate;
|
2872 |
|
|
|
2873 |
|
|
irreg : if (DBGUNIT or PWRD2) generate
|
2874 |
|
|
dsureg : process(clk) begin
|
2875 |
|
|
if rising_edge(clk) then
|
2876 |
|
|
if holdn = '1' then ir <= irin; end if;
|
2877 |
|
|
end if;
|
2878 |
|
|
end process;
|
2879 |
|
|
end generate;
|
2880 |
|
|
|
2881 |
|
|
nirreg : if not (DBGUNIT or PWRD2) generate
|
2882 |
|
|
ir.pwd <= '0'; ir.addr <= (others => '0');
|
2883 |
|
|
end generate;
|
2884 |
|
|
|
2885 |
|
|
wpgen : for i in 0 to 3 generate
|
2886 |
|
|
wpg0 : if nwp > i generate
|
2887 |
|
|
wpreg : process(clk) begin
|
2888 |
|
|
if rising_edge(clk) then
|
2889 |
|
|
if holdn = '1' then wpr(i) <= wprin(i); end if;
|
2890 |
|
|
if rstn = '0' then
|
2891 |
|
|
wpr(i).exec <= '0'; wpr(i).load <= '0'; wpr(i).store <= '0';
|
2892 |
|
|
end if;
|
2893 |
|
|
end if;
|
2894 |
|
|
end process;
|
2895 |
|
|
end generate;
|
2896 |
|
|
wpg1 : if nwp <= i generate
|
2897 |
|
|
wpr(i) <= wpr_none;
|
2898 |
|
|
end generate;
|
2899 |
|
|
end generate;
|
2900 |
|
|
|
2901 |
|
|
-- pragma translate_off
|
2902 |
|
|
dis1 : if disas = 1 generate
|
2903 |
|
|
trc : process(clk)
|
2904 |
|
|
variable valid : boolean;
|
2905 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2906 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2907 |
|
|
variable fpins, fpld : boolean;
|
2908 |
|
|
begin
|
2909 |
|
|
if (disas = 1) and rising_edge(clk) and (rstn = '1') then
|
2910 |
|
|
if (fpu /= 0) then
|
2911 |
|
|
op := r.x.ctrl.inst(31 downto 30); op3 := r.x.ctrl.inst(24 downto 19);
|
2912 |
|
|
fpins := (op = FMT3) and ((op3 = FPOP1) or (op3 = FPOP2));
|
2913 |
|
|
fpld := (op = LDST) and ((op3 = LDF) or (op3 = LDDF) or (op3 = LDFSR));
|
2914 |
|
|
else
|
2915 |
|
|
fpins := false; fpld := false;
|
2916 |
|
|
end if;
|
2917 |
|
|
valid := (((not r.x.ctrl.annul) and r.x.ctrl.pv) = '1') and
|
2918 |
|
|
(not ((fpins or fpld) and (r.x.ctrl.trap = '0')));
|
2919 |
|
|
valid := valid and (holdn = '1');
|
2920 |
|
|
if rising_edge(clk) and (rstn = '1') then
|
2921 |
|
|
print_insn (index, r.x.ctrl.pc(31 downto 2) & "00", r.x.ctrl.inst,
|
2922 |
|
|
rin.w.result, valid, r.x.ctrl.trap = '1', rin.w.wreg = '1', false);
|
2923 |
|
|
end if;
|
2924 |
|
|
end if;
|
2925 |
|
|
end process;
|
2926 |
|
|
end generate;
|
2927 |
|
|
-- pragma translate_on
|
2928 |
|
|
|
2929 |
|
|
dis0 : if disas < 2 generate dummy <= '1'; end generate;
|
2930 |
|
|
|
2931 |
|
|
dis2 : if disas > 1 generate
|
2932 |
|
|
disasen <= '1' when disas /= 0 else '0';
|
2933 |
|
|
cpu_index <= conv_std_logic_vector(index, 4);
|
2934 |
|
|
x0 : cpu_disasx
|
2935 |
|
|
port map (clk, rstn, dummy, r.x.ctrl.inst, r.x.ctrl.pc(31 downto 2),
|
2936 |
|
|
rin.w.result, cpu_index, rin.w.wreg, r.x.ctrl.annul, holdn,
|
2937 |
|
|
r.x.ctrl.pv, r.x.ctrl.trap, disasen);
|
2938 |
|
|
end generate;
|
2939 |
|
|
end;
|