1 |
2 |
tarookumic |
|
2 |
|
|
|
3 |
|
|
|
4 |
|
|
|
5 |
|
|
----------------------------------------------------------------------------
|
6 |
|
|
-- This file is a part of the LEON VHDL model
|
7 |
|
|
-- Copyright (C) 1999 European Space Agency (ESA)
|
8 |
|
|
--
|
9 |
|
|
-- This library is free software; you can redistribute it and/or
|
10 |
|
|
-- modify it under the terms of the GNU Lesser General Public
|
11 |
|
|
-- License as published by the Free Software Foundation; either
|
12 |
|
|
-- version 2 of the License, or (at your option) any later version.
|
13 |
|
|
--
|
14 |
|
|
-- See the file COPYING.LGPL for the full details of the license.
|
15 |
|
|
|
16 |
|
|
|
17 |
|
|
-----------------------------------------------------------------------------
|
18 |
|
|
-- Entity: iu
|
19 |
|
|
-- File: iu.vhd
|
20 |
|
|
-- Author: Jiri Gaisler - ESA/ESTEC
|
21 |
|
|
-- Description: LEON integer unit. Consists of 5 pipline stages: fetch,
|
22 |
|
|
-- decode, execute, memory and write-back. Each stage is
|
23 |
|
|
-- implemented in a separate process.
|
24 |
|
|
------------------------------------------------------------------------------
|
25 |
|
|
|
26 |
|
|
library IEEE;
|
27 |
|
|
use IEEE.std_logic_1164.all;
|
28 |
|
|
use IEEE.std_logic_arith.all;
|
29 |
|
|
use IEEE.std_logic_unsigned."+";
|
30 |
|
|
use IEEE.std_logic_unsigned."-";
|
31 |
|
|
use IEEE.std_logic_unsigned.conv_integer;
|
32 |
|
|
use work.leon_target.all;
|
33 |
|
|
use work.leon_config.all;
|
34 |
|
|
use work.mmuconfig.all;
|
35 |
|
|
use work.sparcv8.all;
|
36 |
|
|
use work.leon_iface.all;
|
37 |
|
|
use work.macro.all;
|
38 |
|
|
use work.tech_map.all;
|
39 |
|
|
use work.multlib.all;
|
40 |
|
|
|
41 |
|
|
entity iu is
|
42 |
|
|
port (
|
43 |
|
|
rst : in std_logic;
|
44 |
|
|
clk : in clk_type;
|
45 |
|
|
holdn : in std_logic;
|
46 |
|
|
ici : out icache_in_type; -- icache input
|
47 |
|
|
ico : in icache_out_type; -- icache output
|
48 |
|
|
dci : out dcache_in_type; -- dcache input
|
49 |
|
|
dco : in dcache_out_type; -- dcache output
|
50 |
|
|
fpui : out fpu_in_type; -- FPU input
|
51 |
|
|
fpuo : in fpu_out_type; -- FPU output
|
52 |
|
|
iui : in iu_in_type; -- system input
|
53 |
|
|
iuo : out iu_out_type; -- system output
|
54 |
|
|
rfi : out rf_in_type; -- register-file input
|
55 |
|
|
rfo : in rf_out_type; -- register-file output
|
56 |
|
|
cpi : out cp_in_type; -- CP input
|
57 |
|
|
cpo : in cp_out_type; -- CP output
|
58 |
|
|
fpi : out cp_in_type; -- FP input
|
59 |
|
|
fpo : in cp_out_type -- FP output
|
60 |
|
|
);
|
61 |
|
|
end;
|
62 |
|
|
|
63 |
|
|
architecture rtl of iu is
|
64 |
|
|
|
65 |
|
|
-- pipeline_control type is defined in package iface
|
66 |
|
|
|
67 |
|
|
type fetch_stage_inputs is record
|
68 |
|
|
branch : std_logic; -- select branch address
|
69 |
|
|
jump : std_logic; -- select jump address
|
70 |
|
|
exception : std_logic; -- select exception address
|
71 |
|
|
hold_pc : std_logic; -- hold PC (multi-cycle inst.)
|
72 |
|
|
branch_address : std_logic_vector(31 downto PCLOW); -- branch address
|
73 |
|
|
jump_address : std_logic_vector(31 downto PCLOW); -- jump address
|
74 |
|
|
trap_address : std_logic_vector(31 downto PCLOW); -- trap address
|
75 |
|
|
end record;
|
76 |
|
|
|
77 |
|
|
type fetch_stage_registers is record
|
78 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
79 |
|
|
branch : std_logic; -- branch indicator
|
80 |
|
|
end record;
|
81 |
|
|
|
82 |
|
|
type decode_stage_type is record
|
83 |
|
|
inst : std_logic_vector(31 downto 0); -- instruction
|
84 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
85 |
|
|
mexc : std_logic; -- memory exception (fetch)
|
86 |
|
|
annul : std_logic; -- instruction annul bit
|
87 |
|
|
cnt : std_logic_vector(1 downto 0); -- cycle number (multi-cycle inst)
|
88 |
|
|
mulcnt : std_logic_vector(4 downto 0); -- cycle number (multiplier)
|
89 |
|
|
pv : std_logic; -- PC valid flag
|
90 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
91 |
|
|
step : std_logic; -- single step
|
92 |
|
|
end record;
|
93 |
|
|
|
94 |
|
|
type execute_stage_type is record
|
95 |
|
|
write_cwp, write_icc, write_reg, write_y, rst_mey : std_logic;
|
96 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
97 |
|
|
icc : std_logic_vector(3 downto 0); -- integer condition codes
|
98 |
|
|
alu_cin : std_logic; -- ALU carry-in
|
99 |
|
|
ymsb : std_logic; -- MULSCC Y(msb)
|
100 |
|
|
rs1data : std_logic_vector(31 downto 0); -- source operand 1
|
101 |
|
|
rs2data : std_logic_vector(31 downto 0); -- source operand 2
|
102 |
|
|
aluop : std_logic_vector(2 downto 0); -- Alu operation
|
103 |
|
|
alusel : std_logic_vector(1 downto 0); -- Alu result select
|
104 |
|
|
aluadd : std_logic; -- add/sub select
|
105 |
|
|
mulstep : std_logic; -- MULSCC
|
106 |
|
|
mulinsn : std_logic; -- SMUL/UMUL
|
107 |
|
|
ldbp1, ldbp2 : std_logic; -- load bypass enable
|
108 |
|
|
ctrl : pipeline_control_type;
|
109 |
|
|
result : std_logic_vector(31 downto 0); -- data forward from execute stage
|
110 |
|
|
micc : std_logic_vector(3 downto 0); -- icc for multiply insn
|
111 |
|
|
licc : std_logic_vector(3 downto 0); -- icc to me stage
|
112 |
|
|
end record;
|
113 |
|
|
|
114 |
|
|
type memory_stage_type is record
|
115 |
|
|
inull : std_logic;
|
116 |
|
|
signed : std_logic; -- signed load
|
117 |
|
|
addr_misal : std_logic; -- misaligned address
|
118 |
|
|
write_cwp, write_icc, write_reg, write_y : std_logic;
|
119 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
120 |
|
|
icc : std_logic_vector(3 downto 0);
|
121 |
|
|
result : std_logic_vector(31 downto 0);
|
122 |
|
|
bpresult : std_logic_vector(31 downto 0); -- result for bypass to de & me
|
123 |
|
|
y : std_logic_vector(31 downto 0); -- pipeline Y register
|
124 |
|
|
my : std_logic_vector(31 downto 0); -- me stage Y feedback
|
125 |
|
|
memory_load : std_logic;
|
126 |
|
|
mulinsn : std_logic; -- SMUL/UMUL
|
127 |
|
|
ld_size : std_logic_vector(1 downto 0); -- memory load size
|
128 |
|
|
ctrl : pipeline_control_type;
|
129 |
|
|
jmpl_rett : std_logic;
|
130 |
|
|
irqen : std_logic;
|
131 |
|
|
ipend : std_logic;
|
132 |
|
|
werr : std_logic; -- store error
|
133 |
|
|
su : std_logic; -- supervisor mode
|
134 |
|
|
end record;
|
135 |
|
|
|
136 |
|
|
type write_stage_type is record
|
137 |
|
|
write_cwp, write_icc, write_reg : std_logic;
|
138 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
139 |
|
|
icc : std_logic_vector(3 downto 0);
|
140 |
|
|
result : std_logic_vector(31 downto 0);
|
141 |
|
|
y : std_logic_vector(31 downto 0);
|
142 |
|
|
asr18 : std_logic_vector(31 downto 0);
|
143 |
|
|
annul_all : std_logic;
|
144 |
|
|
trapping : std_logic;
|
145 |
|
|
error : std_logic;
|
146 |
|
|
nerror : std_logic;
|
147 |
|
|
mexc : std_logic;
|
148 |
|
|
intack : std_logic;
|
149 |
|
|
tpcsel : std_logic_vector(1 downto 0); -- Trap pc select
|
150 |
|
|
dsutrap : std_logic; -- debug unit trap (optional)
|
151 |
|
|
ctrl : pipeline_control_type;
|
152 |
|
|
|
153 |
|
|
end record;
|
154 |
|
|
|
155 |
|
|
type special_register_type is record
|
156 |
|
|
cwp : std_logic_vector(NWINLOG2-1 downto 0); -- current window pointer
|
157 |
|
|
icc : std_logic_vector(3 downto 0); -- integer condition codes
|
158 |
|
|
tt : std_logic_vector(7 downto 0); -- trap type
|
159 |
|
|
tba : std_logic_vector(19 downto 0); -- trap base address
|
160 |
|
|
wim : std_logic_vector(NWINDOWS-1 downto 0); -- window invalid mask
|
161 |
|
|
pil : std_logic_vector(3 downto 0); -- processor interrupt level
|
162 |
|
|
ec : std_logic; -- enable CP
|
163 |
|
|
ef : std_logic; -- enable FP
|
164 |
|
|
ps : std_logic; -- previous supervisor flag
|
165 |
|
|
s : std_logic; -- supervisor flag
|
166 |
|
|
et : std_logic; -- enable traps
|
167 |
|
|
end record;
|
168 |
|
|
|
169 |
|
|
type fsr_type is record
|
170 |
|
|
cexc : std_logic_vector(4 downto 0); -- current exceptions
|
171 |
|
|
aexc : std_logic_vector(4 downto 0); -- accrued exceptions
|
172 |
|
|
fcc : std_logic_vector(1 downto 0); -- FPU condition codes
|
173 |
|
|
ftt : std_logic_vector(2 downto 0); -- FPU trap type
|
174 |
|
|
tem : std_logic_vector(4 downto 0); -- trap enable mask
|
175 |
|
|
rd : std_logic_vector(1 downto 0); -- rounding mode
|
176 |
|
|
end record;
|
177 |
|
|
|
178 |
|
|
type fpu_ctrl1_type is record
|
179 |
|
|
fpop : std_logic_vector(1 downto 0); -- FPOP type
|
180 |
|
|
dsz : std_logic; -- destination size (0=single, 1=double)
|
181 |
|
|
ldfsr : std_logic; -- LDFSR in progress
|
182 |
|
|
end record;
|
183 |
|
|
|
184 |
|
|
type fpu_ctrl2_type is record
|
185 |
|
|
fpop : std_logic_vector(1 downto 0);
|
186 |
|
|
dsz : std_logic;
|
187 |
|
|
fcc : std_logic_vector(1 downto 0);
|
188 |
|
|
cexc : std_logic_vector(4 downto 0); -- current FPU excetion bits
|
189 |
|
|
ldfsr : std_logic;
|
190 |
|
|
end record;
|
191 |
|
|
|
192 |
|
|
type fpu_reg_type is record
|
193 |
|
|
fsr : fsr_type;
|
194 |
|
|
fpop : std_logic;
|
195 |
|
|
reset : std_logic;
|
196 |
|
|
rstdel : std_logic_vector(1 downto 0);
|
197 |
|
|
fpbusy : std_logic;
|
198 |
|
|
fpld : std_logic;
|
199 |
|
|
fpexc : std_logic;
|
200 |
|
|
op1h : std_logic_vector(31 downto 0);
|
201 |
|
|
ex : fpu_ctrl1_type;
|
202 |
|
|
me, wr : fpu_ctrl2_type;
|
203 |
|
|
end record;
|
204 |
|
|
|
205 |
|
|
constant WPALEN : integer := 30;
|
206 |
|
|
type watchpoint_register is record
|
207 |
|
|
addr : std_logic_vector(WPALEN+1 downto 2); -- watchpoint address
|
208 |
|
|
mask : std_logic_vector(WPALEN+1 downto 2); -- watchpoint mask
|
209 |
|
|
exec : std_logic; -- trap on instruction
|
210 |
|
|
load : std_logic; -- trap on load
|
211 |
|
|
store : std_logic; -- trap on store
|
212 |
|
|
end record;
|
213 |
|
|
|
214 |
|
|
type watchpoint_registers is array (0 to 3) of watchpoint_register;
|
215 |
|
|
|
216 |
|
|
type dsu_registers is record
|
217 |
|
|
pc : std_logic_vector(31 downto PCLOW); -- program counter
|
218 |
|
|
dmode : std_logic; -- debug mode active
|
219 |
|
|
dmode2 : std_logic; -- debug mode active (delayed)
|
220 |
|
|
dstate : std_logic; -- debug state
|
221 |
|
|
tt : std_logic_vector(7 downto 0); -- trap type
|
222 |
|
|
error : std_logic; -- trap would cause error
|
223 |
|
|
dsuen : std_logic;
|
224 |
|
|
end record;
|
225 |
|
|
|
226 |
|
|
component div
|
227 |
|
|
port (
|
228 |
|
|
rst : in std_logic;
|
229 |
|
|
clk : in clk_type;
|
230 |
|
|
holdn : in std_logic;
|
231 |
|
|
divi : in div_in_type;
|
232 |
|
|
divo : out div_out_type
|
233 |
|
|
);
|
234 |
|
|
end component;
|
235 |
|
|
|
236 |
|
|
component mul
|
237 |
|
|
port (
|
238 |
|
|
rst : in std_logic;
|
239 |
|
|
clk : in clk_type;
|
240 |
|
|
holdn : in std_logic;
|
241 |
|
|
muli : in mul_in_type;
|
242 |
|
|
mulo : out mul_out_type
|
243 |
|
|
);
|
244 |
|
|
end component;
|
245 |
|
|
|
246 |
|
|
-- registers
|
247 |
|
|
|
248 |
|
|
constant FASTADD : boolean := false;
|
249 |
|
|
constant PILOPT : boolean := FASTDECODE;
|
250 |
|
|
constant Zero32: std_logic_vector(31 downto 0) := "00000000000000000000000000000000";
|
251 |
|
|
signal fecomb : fetch_stage_inputs;
|
252 |
|
|
signal fe, fein : fetch_stage_registers;
|
253 |
|
|
signal de, dein : decode_stage_type;
|
254 |
|
|
signal ex, exin : execute_stage_type;
|
255 |
|
|
signal me, mein : memory_stage_type;
|
256 |
|
|
signal wr, wrin : write_stage_type;
|
257 |
|
|
signal sregsin, sregs : special_register_type;
|
258 |
|
|
signal dciin : dcache_in_type;
|
259 |
|
|
signal fpu_reg, fpu_regin : fpu_reg_type;
|
260 |
|
|
signal tr, trin : watchpoint_registers;
|
261 |
|
|
signal dsur, dsurin : dsu_registers;
|
262 |
|
|
signal muli : mul_in_type; -- multiplier input
|
263 |
|
|
signal mulo : mul_out_type; -- muliplier output
|
264 |
|
|
signal divi : div_in_type; -- divider input
|
265 |
|
|
signal divo : div_out_type; -- divider output
|
266 |
|
|
signal sum32, add32in1, add32in2 : std_logic_vector(31 downto 0);
|
267 |
|
|
signal add32cin : std_logic;
|
268 |
|
|
|
269 |
|
|
begin
|
270 |
|
|
|
271 |
|
|
-------------------------------------------------------------------------------
|
272 |
|
|
-- Instruction fetch stage
|
273 |
|
|
-------------------------------------------------------------------------------
|
274 |
|
|
|
275 |
|
|
fetch_stage : process(fecomb, fe, rst, de, mein)
|
276 |
|
|
variable v : fetch_stage_registers;
|
277 |
|
|
variable npc : std_logic_vector(31 downto PCLOW);
|
278 |
|
|
begin
|
279 |
|
|
|
280 |
|
|
v := fe;
|
281 |
|
|
|
282 |
|
|
-- pc generation
|
283 |
|
|
|
284 |
|
|
npc := fe.pc;
|
285 |
|
|
if (rst = '0') then
|
286 |
|
|
v.pc := (others => '0'); v.branch := '0';
|
287 |
|
|
elsif fecomb.exception = '1' then -- exception
|
288 |
|
|
v.branch := '1'; v.pc := fecomb.trap_address;
|
289 |
|
|
npc := v.pc;
|
290 |
|
|
elsif (not mein.inull and fecomb.hold_pc) = '1' then
|
291 |
|
|
v.pc := fe.pc; v.branch := fe.branch;
|
292 |
|
|
elsif fecomb.jump = '1' then
|
293 |
|
|
v.pc := fecomb.jump_address; v.branch := '1';
|
294 |
|
|
npc := v.pc;
|
295 |
|
|
elsif fecomb.branch = '1' then
|
296 |
|
|
v.pc := fecomb.branch_address; v.branch := '1';
|
297 |
|
|
npc := v.pc;
|
298 |
|
|
else
|
299 |
|
|
v.branch := '0';
|
300 |
|
|
-- pragma translate_off
|
301 |
|
|
if not is_x(fe.pc) then
|
302 |
|
|
-- pragma translate_on
|
303 |
|
|
v.pc(31 downto 2) := fe.pc(31 downto 2) + 1; -- Address incrementer
|
304 |
|
|
-- pragma translate_off
|
305 |
|
|
else
|
306 |
|
|
v.pc := (others => 'X');
|
307 |
|
|
end if;
|
308 |
|
|
-- pragma translate_on
|
309 |
|
|
npc := v.pc;
|
310 |
|
|
end if;
|
311 |
|
|
|
312 |
|
|
-- drive register inputs
|
313 |
|
|
|
314 |
|
|
fein <= v;
|
315 |
|
|
|
316 |
|
|
-- drive some icache inputs
|
317 |
|
|
|
318 |
|
|
-- ici.rpc(31 downto PCLOW) <= v.pc(31 downto PCLOW);
|
319 |
|
|
ici.rpc(31 downto PCLOW) <= npc;
|
320 |
|
|
ici.fpc(31 downto PCLOW) <= fe.pc(31 downto PCLOW);
|
321 |
|
|
ici.dpc(31 downto PCLOW) <= de.pc(31 downto PCLOW);
|
322 |
|
|
ici.fbranch <= fe.branch;
|
323 |
|
|
ici.rbranch <= v.branch;
|
324 |
|
|
|
325 |
|
|
end process;
|
326 |
|
|
|
327 |
|
|
-------------------------------------------------------------------------------
|
328 |
|
|
-- Instruction decode stage
|
329 |
|
|
-------------------------------------------------------------------------------
|
330 |
|
|
|
331 |
|
|
|
332 |
|
|
decode_stage : process(rst, fe, de, ex, me, mein, wrin, wr, sregs, ico, rfo,
|
333 |
|
|
sregsin, fpo, cpo, dco, holdn, fpu_reg, mulo, divo, tr,
|
334 |
|
|
iui, dsur)
|
335 |
|
|
|
336 |
|
|
variable rfenable1, rfenable2 : std_logic; -- regfile enable strobes
|
337 |
|
|
variable op : std_logic_vector(1 downto 0);
|
338 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
339 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
340 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
341 |
|
|
variable cond : std_logic_vector(3 downto 0);
|
342 |
|
|
variable rs1, rs2, rd : std_logic_vector(4 downto 0);
|
343 |
|
|
variable write_cwp, write_icc, write_reg, write_y : std_logic;
|
344 |
|
|
variable cnt : std_logic_vector(1 downto 0); -- cycle number
|
345 |
|
|
variable cwp_new : std_logic_vector(NWINLOG2-1 downto 0);
|
346 |
|
|
variable icc, br_icc : std_logic_vector(3 downto 0);
|
347 |
|
|
variable alu_cin : std_logic;
|
348 |
|
|
variable immediate_data : std_logic_vector(31 downto 0);
|
349 |
|
|
variable n, z, v, c : std_logic; -- temporary condition codes
|
350 |
|
|
variable i : std_logic; -- immidiate data bit
|
351 |
|
|
variable su : std_logic; -- local supervisor bit;
|
352 |
|
|
variable et : std_logic; -- local enable trap bit
|
353 |
|
|
variable inull, annul, annul_current : std_logic;
|
354 |
|
|
variable branch, annul_next, bres, branch_true: std_logic;
|
355 |
|
|
variable aluop : std_logic_vector(2 downto 0);
|
356 |
|
|
variable alusel : std_logic_vector(1 downto 0);
|
357 |
|
|
variable aluadd : std_logic;
|
358 |
|
|
variable mulstep : std_logic;
|
359 |
|
|
variable mulinsn : std_logic;
|
360 |
|
|
variable y0 : std_logic;
|
361 |
|
|
variable branch_address : std_logic_vector(31 downto PCLOW);
|
362 |
|
|
variable rs1data, rs2data : std_logic_vector(31 downto 0);
|
363 |
|
|
variable operand2_select : std_logic;
|
364 |
|
|
variable read_addr1, read_addr2, chkrd : std_logic_vector(RABITS-1 downto 0);
|
365 |
|
|
variable hold_pc : std_logic; -- Hold PC during multi-cycle ops
|
366 |
|
|
variable pv : std_logic; -- PC valid
|
367 |
|
|
variable ldlock, ldcheck1, ldcheck2, ldcheck3 : std_logic; -- load interlock
|
368 |
|
|
variable ldchkex, ldchkme : std_logic; -- load interlock for ex and me
|
369 |
|
|
variable illegal_inst : std_logic; -- illegal instruction
|
370 |
|
|
variable privileged_inst : std_logic; -- privileged instruction trap
|
371 |
|
|
variable cp_disabled : std_logic; -- CP disable trap
|
372 |
|
|
variable fp_disabled : std_logic; -- FP disable trap
|
373 |
|
|
variable watchpoint_exc : std_logic; -- watchpoint trap
|
374 |
|
|
variable winovf_exception : std_logic; -- window overflow trap
|
375 |
|
|
variable winunf_exception : std_logic; -- window underflow trap
|
376 |
|
|
variable ticc_exception : std_logic; -- TICC trap
|
377 |
|
|
variable fp_exception : std_logic; -- STDFQ trap
|
378 |
|
|
variable ctrl : pipeline_control_type;
|
379 |
|
|
variable ldbp1, ldbp2 : std_logic; -- load bypass enable
|
380 |
|
|
variable mulcnt : std_logic_vector(4 downto 0); -- multiply cycle number
|
381 |
|
|
variable ymsb : std_logic; -- next msb of Y during MUL
|
382 |
|
|
variable rst_mey : std_logic; -- reset me stage Y register
|
383 |
|
|
variable fpld, fpst, fpop : std_logic; -- FPU instructions
|
384 |
|
|
variable fpmov : std_logic; -- FPU instructions
|
385 |
|
|
variable fbres, fbranch_true : std_logic; -- FBCC branch result
|
386 |
|
|
variable cbres, cbranch_true : std_logic; -- CBCC branch result
|
387 |
|
|
variable fcc : std_logic_vector(1 downto 0); -- FPU condition codes
|
388 |
|
|
variable ccc : std_logic_vector(1 downto 0); -- CP condition codes
|
389 |
|
|
variable cwpmax : std_logic_vector(4 downto 0);
|
390 |
|
|
variable bicc_hold, icc_check : std_logic;
|
391 |
|
|
variable fsr_ld, fsr_ld_check, fsr_check, fsr_lock : std_logic;
|
392 |
|
|
variable fpexin : fpu_ctrl1_type;
|
393 |
|
|
variable rs1mod : std_logic;
|
394 |
|
|
variable step : std_logic;
|
395 |
|
|
variable divstart,mulstart : std_logic; -- start multiply or divide
|
396 |
|
|
variable cpldlock, fpldlock, annul_current_cp : std_logic;
|
397 |
|
|
constant RDOPT : boolean := FASTDECODE;-- optimise dest reg address generation
|
398 |
|
|
constant RS1OPT : boolean := FASTDECODE;-- optimise src1 reg address generation
|
399 |
|
|
|
400 |
|
|
function regdec(cwp, regin : std_logic_vector; fp : std_logic)
|
401 |
|
|
return std_logic_vector is
|
402 |
|
|
variable reg : std_logic_vector(4 downto 0);
|
403 |
|
|
variable ra : std_logic_vector(RABITS -1 downto 0);
|
404 |
|
|
begin
|
405 |
|
|
reg := regin; ra(4 downto 0) := reg;
|
406 |
|
|
if (FPIFTYPE = serial) and (fp = '1') then
|
407 |
|
|
ra(RABITS -1 downto 5) := F0ADDR(RABITS-5 downto 1);
|
408 |
|
|
elsif reg(4 downto 3) = "00" then ra(RABITS -1 downto 4) := R0ADDR;
|
409 |
|
|
else
|
410 |
|
|
-- pragma translate_off
|
411 |
|
|
if not (is_x(cwp & ra(4))) then
|
412 |
|
|
-- pragma translate_on
|
413 |
|
|
ra(NWINLOG2+3 downto 4) := (cwp + ra(4));
|
414 |
|
|
if CWPOPT then ra(RABITS-1) := '0';
|
415 |
|
|
elsif ra(RABITS-1 downto 4) = R0ADDR then
|
416 |
|
|
ra(RABITS-1 downto 4) := (others => '0');
|
417 |
|
|
end if;
|
418 |
|
|
-- pragma translate_off
|
419 |
|
|
end if;
|
420 |
|
|
-- pragma translate_on
|
421 |
|
|
end if;
|
422 |
|
|
return(ra);
|
423 |
|
|
end;
|
424 |
|
|
|
425 |
|
|
begin
|
426 |
|
|
|
427 |
|
|
-- instruction bit-field decoding
|
428 |
|
|
|
429 |
|
|
op := de.inst(31 downto 30);
|
430 |
|
|
op2 := de.inst(24 downto 22);
|
431 |
|
|
op3 := de.inst(24 downto 19);
|
432 |
|
|
opf := de.inst(13 downto 5);
|
433 |
|
|
cond := de.inst(28 downto 25);
|
434 |
|
|
annul := de.inst(29);
|
435 |
|
|
rs1 := de.inst(18 downto 14);
|
436 |
|
|
rs2 := de.inst(4 downto 0);
|
437 |
|
|
rd := de.inst(29 downto 25);
|
438 |
|
|
i := de.inst(13);
|
439 |
|
|
|
440 |
|
|
-- common initialisation
|
441 |
|
|
|
442 |
|
|
ctrl.annul := de.annul; ctrl.cnt := de.cnt; ctrl.pv := de.pv; pv := '1';
|
443 |
|
|
cnt := "00"; ctrl.tt := "000000"; ctrl.ld := '0'; ctrl.rett := '0';
|
444 |
|
|
ctrl.pc := de.pc; ctrl.inst := de.inst; mulcnt := de.mulcnt;
|
445 |
|
|
write_y := '0'; fpld := '0'; fpst := '0'; fpop := '0';
|
446 |
|
|
fp_exception := '0'; fpmov := '0'; step := '0';
|
447 |
|
|
fpexin.fpop := "00"; fpexin.dsz := '0'; fpexin.ldfsr := '0';
|
448 |
|
|
|
449 |
|
|
winovf_exception := '0'; winunf_exception := '0';
|
450 |
|
|
write_cwp := '0'; cwp_new := de.cwp; rs1mod := '0';
|
451 |
|
|
rfenable1 := '0'; rfenable2 := '0';
|
452 |
|
|
|
453 |
|
|
-- detect RETT instruction in the pipeline and set the local psr.su and psr.et
|
454 |
|
|
|
455 |
|
|
if ((ex.ctrl.rett and not ex.ctrl.annul) or (me.ctrl.rett and not me.ctrl.annul) or
|
456 |
|
|
(wr.ctrl.rett and not wr.ctrl.annul)) = '1'
|
457 |
|
|
then
|
458 |
|
|
su := sregs.ps; et := '1';
|
459 |
|
|
else
|
460 |
|
|
su := sregs.s; et := sregs.et;
|
461 |
|
|
end if;
|
462 |
|
|
|
463 |
|
|
-- Check for illegal and privileged instructions
|
464 |
|
|
|
465 |
|
|
illegal_inst := '0'; privileged_inst := '0'; cp_disabled := '0';
|
466 |
|
|
fp_disabled := '0';
|
467 |
|
|
case op is
|
468 |
|
|
when CALL => null;
|
469 |
|
|
when FMT2 =>
|
470 |
|
|
case op2 is
|
471 |
|
|
when SETHI | BICC => null;
|
472 |
|
|
when FBFCC =>
|
473 |
|
|
if FPEN then fp_disabled := not sregs.ef;
|
474 |
|
|
else fp_disabled := '1'; end if;
|
475 |
|
|
when CBCCC =>
|
476 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
477 |
|
|
when others => illegal_inst := '1';
|
478 |
|
|
end case;
|
479 |
|
|
when FMT3 =>
|
480 |
|
|
case op3 is
|
481 |
|
|
when IAND | ANDCC | ANDN | ANDNCC | IOR | ORCC | ORN | ORNCC | IXOR |
|
482 |
|
|
XORCC | IXNOR | XNORCC | ISLL | ISRL | ISRA | MULSCC | IADD | ADDX |
|
483 |
|
|
ADDCC | ADDXCC | TADDCC | TADDCCTV | ISUB | SUBX | SUBCC | SUBXCC |
|
484 |
|
|
TSUBCC | TSUBCCTV | FLUSH | JMPL | TICC | SAVE | RESTORE | RDY => null;
|
485 |
|
|
when UMAC | SMAC =>
|
486 |
|
|
if not MACEN then illegal_inst := '1'; end if;
|
487 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
488 |
|
|
if MULTIPLIER = none then illegal_inst := '1'; end if;
|
489 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
490 |
|
|
if DIVIDER = none then illegal_inst := '1'; end if;
|
491 |
|
|
when RETT => illegal_inst := et; privileged_inst := not su;
|
492 |
|
|
when RDPSR | RDTBR | RDWIM => privileged_inst := not su;
|
493 |
|
|
when WRY =>
|
494 |
|
|
|
495 |
|
|
if not ((rd = "00000") or ((rd = "10010") and MACEN) or
|
496 |
|
|
((rd(4 downto 3) = "11") and (WATCHPOINTS > 0)))
|
497 |
|
|
then
|
498 |
|
|
|
499 |
|
|
illegal_inst := '1';
|
500 |
|
|
end if;
|
501 |
|
|
when WRPSR =>
|
502 |
|
|
privileged_inst := not su;
|
503 |
|
|
when WRWIM | WRTBR => privileged_inst := not su;
|
504 |
|
|
when FPOP1 | FPOP2 =>
|
505 |
|
|
if FPEN then fp_disabled := not sregs.ef; fpop := '1';
|
506 |
|
|
else fp_disabled := '1'; fpop := '0'; end if;
|
507 |
|
|
when CPOP1 | CPOP2 =>
|
508 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
509 |
|
|
when others => illegal_inst := '1';
|
510 |
|
|
end case;
|
511 |
|
|
when others => -- LDST
|
512 |
|
|
case op3 is
|
513 |
|
|
when LDD | ISTD => illegal_inst := rd(0); -- trap if odd destination register
|
514 |
|
|
when LD | LDUB | LDSTUB | LDUH | LDSB | LDSH | ST | STB | STH | SWAP =>
|
515 |
|
|
null;
|
516 |
|
|
when LDDA | STDA =>
|
517 |
|
|
illegal_inst := i or rd(0); privileged_inst := not su;
|
518 |
|
|
when LDA | LDUBA| LDSTUBA | LDUHA | LDSBA | LDSHA | STA | STBA | STHA |
|
519 |
|
|
SWAPA =>
|
520 |
|
|
illegal_inst := i; privileged_inst := not su;
|
521 |
|
|
when LDDF | STDF | LDF | LDFSR | STF | STFSR =>
|
522 |
|
|
if FPEN then fp_disabled := not sregs.ef;
|
523 |
|
|
else fp_disabled := '1'; end if;
|
524 |
|
|
when STDFQ =>
|
525 |
|
|
privileged_inst := not su;
|
526 |
|
|
if (not FPEN) or (sregs.ef = '0') then fp_disabled := '1'; end if;
|
527 |
|
|
when STDCQ =>
|
528 |
|
|
privileged_inst := not su;
|
529 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
530 |
|
|
when LDC | LDCSR | LDDC | STC | STCSR | STDC =>
|
531 |
|
|
if (not CPEN) or (sregs.ec = '0') then cp_disabled := '1'; end if;
|
532 |
|
|
when others => illegal_inst := '1';
|
533 |
|
|
end case;
|
534 |
|
|
end case;
|
535 |
|
|
|
536 |
|
|
-- branch address adder
|
537 |
|
|
|
538 |
|
|
branch_address := (others => '0');
|
539 |
|
|
if op = CALL then branch_address(31 downto 2) := de.inst(29 downto 0);
|
540 |
|
|
else branch_address(31 downto 2) := de.inst(21) & de.inst(21) & de.inst(21) &
|
541 |
|
|
de.inst(21) & de.inst(21) & de.inst(21) & de.inst(21) &
|
542 |
|
|
de.inst(21) & de.inst(21 downto 0);
|
543 |
|
|
end if;
|
544 |
|
|
|
545 |
|
|
-- pragma translate_off
|
546 |
|
|
if not (is_x(branch_address) or is_x(de.pc)) then
|
547 |
|
|
-- pragma translate_on
|
548 |
|
|
branch_address := branch_address + de.pc; -- address adder (branch)
|
549 |
|
|
-- pragma translate_off
|
550 |
|
|
else
|
551 |
|
|
branch_address := (others => 'X');
|
552 |
|
|
end if;
|
553 |
|
|
-- pragma translate_on
|
554 |
|
|
|
555 |
|
|
fecomb.branch_address <= branch_address;
|
556 |
|
|
|
557 |
|
|
-- ICC pipeline and forwarding
|
558 |
|
|
|
559 |
|
|
if (me.write_icc and not me.ctrl.annul) = '1' then icc := wrin.icc;
|
560 |
|
|
elsif (wr.write_icc and not wr.ctrl.annul) = '1' then icc := wr.icc;
|
561 |
|
|
else icc := sregs.icc; end if;
|
562 |
|
|
|
563 |
|
|
br_icc := icc;
|
564 |
|
|
|
565 |
|
|
if ((ex.write_icc and not ex.ctrl.annul) = '1') then
|
566 |
|
|
icc := ex.icc;
|
567 |
|
|
if not ICC_HOLD then br_icc := icc; end if;
|
568 |
|
|
end if;
|
569 |
|
|
|
570 |
|
|
write_icc := '0'; alu_cin := '0';
|
571 |
|
|
|
572 |
|
|
case op is
|
573 |
|
|
when FMT3 =>
|
574 |
|
|
case op3 is
|
575 |
|
|
when SUBCC | TSUBCC | TSUBCCTV =>
|
576 |
|
|
write_icc := '1';
|
577 |
|
|
when ADDCC | ANDCC | ORCC | XORCC | ANDNCC | ORNCC | XNORCC | MULSCC |
|
578 |
|
|
TADDCC | TADDCCTV =>
|
579 |
|
|
write_icc := '1';
|
580 |
|
|
when UMULCC | SMULCC =>
|
581 |
|
|
if MULTIPLIER = iterative then
|
582 |
|
|
if de.cnt /= "11" then write_icc := '1'; end if;
|
583 |
|
|
end if;
|
584 |
|
|
if MULTIPLIER = m32x32 then write_icc := '1'; end if;
|
585 |
|
|
when ADDX | SUBX =>
|
586 |
|
|
alu_cin := icc(0);
|
587 |
|
|
when ADDXCC | SUBXCC =>
|
588 |
|
|
write_icc := '1'; alu_cin := icc(0);
|
589 |
|
|
when others => null;
|
590 |
|
|
end case;
|
591 |
|
|
when others => null;
|
592 |
|
|
end case;
|
593 |
|
|
|
594 |
|
|
exin.write_icc <= write_icc; exin.alu_cin <= alu_cin;
|
595 |
|
|
|
596 |
|
|
-- BICC/TICC evaluation
|
597 |
|
|
|
598 |
|
|
n := br_icc(3); z := br_icc(2); v := br_icc(1); c := br_icc(0);
|
599 |
|
|
case cond(2 downto 0) is
|
600 |
|
|
when "000" => bres := '0'; -- bn, ba
|
601 |
|
|
when "001" => bres := z; -- be, bne
|
602 |
|
|
when "010" => bres := z or (n xor v); -- ble, bg
|
603 |
|
|
when "011" => bres := n xor v; -- bl, bge
|
604 |
|
|
when "100" => bres := c or z; -- blue, bgu
|
605 |
|
|
when "101" => bres := c; -- bcs, bcc
|
606 |
|
|
when "110" => bres := n; -- bneg, bpos
|
607 |
|
|
when others => bres := v; -- bvs. bvc
|
608 |
|
|
end case;
|
609 |
|
|
branch_true := cond(3) xor bres;
|
610 |
|
|
|
611 |
|
|
-- FBFCC evaluation
|
612 |
|
|
|
613 |
|
|
if FPEN then
|
614 |
|
|
if FPIFTYPE = serial then
|
615 |
|
|
if (fpu_reg.me.fpop = "10") and (me.ctrl.annul = '0') then
|
616 |
|
|
fcc := fpu_reg.me.fcc;
|
617 |
|
|
elsif (fpu_reg.wr.fpop = "10") and (wr.ctrl.annul = '0') then
|
618 |
|
|
fcc := fpu_reg.wr.fcc;
|
619 |
|
|
else fcc := fpu_reg.fsr.fcc; end if;
|
620 |
|
|
else fcc := fpo.cc; end if;
|
621 |
|
|
case cond(2 downto 0) is
|
622 |
|
|
when "000" => fbres := '0'; -- fba, fbn
|
623 |
|
|
when "001" => fbres := fcc(1) or fcc(0);
|
624 |
|
|
when "010" => fbres := fcc(1) xor fcc(0);
|
625 |
|
|
when "011" => fbres := fcc(0);
|
626 |
|
|
when "100" => fbres := (not fcc(1)) and fcc(0);
|
627 |
|
|
when "101" => fbres := fcc(1);
|
628 |
|
|
when "110" => fbres := fcc(1) and not fcc(0);
|
629 |
|
|
when others => fbres := fcc(1) and fcc(0);
|
630 |
|
|
end case;
|
631 |
|
|
fbranch_true := cond(3) xor fbres;
|
632 |
|
|
|
633 |
|
|
-- decode some FPU instruction types
|
634 |
|
|
case opf is
|
635 |
|
|
when FMOVS | FABSS | FNEGS => fpmov := '1';
|
636 |
|
|
when FITOD | FSTOD | FSQRTD | FADDD | FSUBD | FMULD | FDIVD =>
|
637 |
|
|
fpexin.dsz := '1';
|
638 |
|
|
when others => null;
|
639 |
|
|
end case;
|
640 |
|
|
end if;
|
641 |
|
|
|
642 |
|
|
-- CBCCC evaluation
|
643 |
|
|
|
644 |
|
|
if CPEN then
|
645 |
|
|
ccc := cpo.cc;
|
646 |
|
|
case cond(2 downto 0) is
|
647 |
|
|
when "000" => cbres := '0';
|
648 |
|
|
when "001" => cbres := ccc(1) or ccc(0);
|
649 |
|
|
when "010" => cbres := ccc(1) xor ccc(0);
|
650 |
|
|
when "011" => cbres := ccc(0);
|
651 |
|
|
when "100" => cbres := (not ccc(1)) and ccc(0);
|
652 |
|
|
when "101" => cbres := ccc(1);
|
653 |
|
|
when "110" => cbres := ccc(1) and not ccc(0);
|
654 |
|
|
when others => cbres := ccc(1) and ccc(0);
|
655 |
|
|
end case;
|
656 |
|
|
cbranch_true := cond(3) xor cbres;
|
657 |
|
|
end if;
|
658 |
|
|
|
659 |
|
|
-- Alu operation generation
|
660 |
|
|
|
661 |
|
|
aluop := ALU_NOP; alusel := ALU_RES_MISC; aluadd := '1';
|
662 |
|
|
mulstep := '0'; mulinsn := '0';
|
663 |
|
|
case op is
|
664 |
|
|
when FMT2 =>
|
665 |
|
|
case op2 is
|
666 |
|
|
when SETHI => aluop := ALU_PASS2;
|
667 |
|
|
when others =>
|
668 |
|
|
end case;
|
669 |
|
|
when FMT3 =>
|
670 |
|
|
case op3 is
|
671 |
|
|
when IADD | ADDX | ADDCC | ADDXCC | TADDCC | TADDCCTV | SAVE | RESTORE |
|
672 |
|
|
TICC | JMPL | RETT => alusel := ALU_RES_ADD;
|
673 |
|
|
when ISUB | SUBX | SUBCC | SUBXCC | TSUBCC | TSUBCCTV =>
|
674 |
|
|
alusel := ALU_RES_ADD; aluadd := '0';
|
675 |
|
|
when MULSCC => alusel := ALU_RES_ADD; mulstep := '1';
|
676 |
|
|
when UMUL | UMULCC =>
|
677 |
|
|
if MULTIPLIER = iterative then
|
678 |
|
|
case de.cnt is
|
679 |
|
|
when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
|
680 |
|
|
when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
|
681 |
|
|
when others => alusel := ALU_RES_ADD;
|
682 |
|
|
end case;
|
683 |
|
|
end if;
|
684 |
|
|
if MULTIPLIER > iterative then mulinsn := '1'; end if;
|
685 |
|
|
when SMUL | SMULCC =>
|
686 |
|
|
if MULTIPLIER = iterative then
|
687 |
|
|
case de.cnt is
|
688 |
|
|
when "00" => aluop := ALU_XOR; alusel := ALU_RES_MISC;
|
689 |
|
|
when "01" | "10" => alusel := ALU_RES_ADD; mulinsn := '1';
|
690 |
|
|
when others => alusel := ALU_RES_ADD; aluadd := '0';
|
691 |
|
|
end case;
|
692 |
|
|
end if;
|
693 |
|
|
if MULTIPLIER > iterative then mulinsn := '1'; end if;
|
694 |
|
|
when UMAC | SMAC =>
|
695 |
|
|
if MACEN then mulinsn := '1'; end if;
|
696 |
|
|
when UDIV | UDIVCC | SDIV | SDIVCC =>
|
697 |
|
|
if DIVIDER /= none then aluop := ALU_DIV; alusel := ALU_RES_LOGIC; end if;
|
698 |
|
|
when IAND | ANDCC => aluop := ALU_AND; alusel := ALU_RES_LOGIC;
|
699 |
|
|
when ANDN | ANDNCC => aluop := ALU_ANDN; alusel := ALU_RES_LOGIC;
|
700 |
|
|
when IOR | ORCC => aluop := ALU_OR; alusel := ALU_RES_LOGIC;
|
701 |
|
|
when ORN | ORNCC => aluop := ALU_ORN; alusel := ALU_RES_LOGIC;
|
702 |
|
|
when IXNOR | XNORCC => aluop := ALU_XNOR; alusel := ALU_RES_LOGIC;
|
703 |
|
|
when XORCC | IXOR | WRPSR | WRWIM | WRTBR | WRY =>
|
704 |
|
|
aluop := ALU_XOR; alusel := ALU_RES_LOGIC;
|
705 |
|
|
when RDPSR | RDTBR | RDWIM => aluop := ALU_PASS2;
|
706 |
|
|
when RDY => aluop := ALU_RDY;
|
707 |
|
|
when ISLL => aluop := ALU_SLL; alusel := ALU_RES_SHIFT;
|
708 |
|
|
when ISRL => aluop := ALU_SRL; alusel := ALU_RES_SHIFT;
|
709 |
|
|
when ISRA => aluop := ALU_SRA; alusel := ALU_RES_SHIFT;
|
710 |
|
|
when FPOP1 | FPOP2 =>
|
711 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
712 |
|
|
if de.cnt /= "00" then
|
713 |
|
|
if opf(1) = '1' then rs1(0) := '1'; rs2(0) := '1'; end if;
|
714 |
|
|
if fpexin.dsz = '1' then rd(0) := '1'; end if;
|
715 |
|
|
end if;
|
716 |
|
|
if op3 = FPOP1 then fpexin.fpop := "01"; else fpexin.fpop := "10"; end if;
|
717 |
|
|
if fpmov = '1' then aluop := ALU_FOP; fpexin.fpop := "11";
|
718 |
|
|
else aluop := ALU_PASS2; end if;
|
719 |
|
|
end if;
|
720 |
|
|
when others =>
|
721 |
|
|
end case;
|
722 |
|
|
when others => -- LDST
|
723 |
|
|
case de.cnt is
|
724 |
|
|
when "00" =>
|
725 |
|
|
alusel := ALU_RES_ADD;
|
726 |
|
|
if FPEN then fpld := (op3(5) and not op3(2));
|
727 |
|
|
else fpld := '0'; end if;
|
728 |
|
|
when "01" =>
|
729 |
|
|
if (op3(2) and not op3(3)) = '1' then -- ST
|
730 |
|
|
rs1 := rd; rs1mod := '1';
|
731 |
|
|
end if;
|
732 |
|
|
case op3 is
|
733 |
|
|
when LDD | LDDA | LDDC =>
|
734 |
|
|
rd(0) := '1'; alusel := ALU_RES_ADD;
|
735 |
|
|
when LDDF =>
|
736 |
|
|
rd(0) := '1'; alusel := ALU_RES_ADD;
|
737 |
|
|
if FPEN then fpld := '1'; end if;
|
738 |
|
|
when STFSR => if ((FPIFTYPE = serial) and FPEN) then aluop := ALU_FSR; end if;
|
739 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
|
740 |
|
|
alusel := ALU_RES_ADD;
|
741 |
|
|
when STF | STDF =>
|
742 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
743 |
|
|
aluop := ALU_PASS1; fpst := '1';
|
744 |
|
|
end if;
|
745 |
|
|
when others =>
|
746 |
|
|
aluop := ALU_PASS1;
|
747 |
|
|
if op3(2) = '1' then -- ST
|
748 |
|
|
if op3(1 downto 0) = "01" then -- store byte
|
749 |
|
|
aluop := ALU_STB;
|
750 |
|
|
elsif op3(1 downto 0) = "10" then -- store halfword
|
751 |
|
|
aluop := ALU_STH;
|
752 |
|
|
end if;
|
753 |
|
|
end if;
|
754 |
|
|
end case;
|
755 |
|
|
when "10" =>
|
756 |
|
|
aluop := ALU_PASS1;
|
757 |
|
|
rs1 := rd; rs1mod := '1';
|
758 |
|
|
if op3(2) = '1' then -- ST
|
759 |
|
|
if (op3(3) and not op3(1))= '1' then aluop := ALU_ONES; -- LDSTUB/A
|
760 |
|
|
elsif op3(3 downto 0) = "0111" then
|
761 |
|
|
rs1(0) := '1'; -- STD/F/A
|
762 |
|
|
if ((FPIFTYPE = serial) and FPEN) and (op3(5) = '1') then fpst := '1'; end if;
|
763 |
|
|
end if;
|
764 |
|
|
end if;
|
765 |
|
|
when others =>
|
766 |
|
|
end case;
|
767 |
|
|
|
768 |
|
|
end case;
|
769 |
|
|
|
770 |
|
|
exin.aluop <= aluop; exin.alusel <= alusel; exin.aluadd <= aluadd;
|
771 |
|
|
exin.mulstep <= mulstep; exin.mulinsn <= mulinsn;
|
772 |
|
|
|
773 |
|
|
-- Alu operand select
|
774 |
|
|
|
775 |
|
|
operand2_select := ALU_SIMM;
|
776 |
|
|
|
777 |
|
|
case op is
|
778 |
|
|
when FMT2 =>
|
779 |
|
|
case op2 is
|
780 |
|
|
when SETHI => operand2_select := ALU_SIMM;
|
781 |
|
|
when others => operand2_select := ALU_RS2;
|
782 |
|
|
end case;
|
783 |
|
|
when FMT3 =>
|
784 |
|
|
case op3 is
|
785 |
|
|
when RDWIM | RDPSR | RDTBR => operand2_select := ALU_SIMM;
|
786 |
|
|
when FPOP1 | FPOP2 => if ((FPIFTYPE = serial) and FPEN) then operand2_select := ALU_RS2; end if;
|
787 |
|
|
when others =>
|
788 |
|
|
if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
|
789 |
|
|
else operand2_select := ALU_RS2; end if;
|
790 |
|
|
end case;
|
791 |
|
|
when LDST =>
|
792 |
|
|
if (de.inst(13) = '1') then operand2_select := ALU_SIMM;
|
793 |
|
|
else operand2_select := ALU_RS2; end if;
|
794 |
|
|
when others => operand2_select := ALU_RS2;
|
795 |
|
|
end case;
|
796 |
|
|
|
797 |
|
|
|
798 |
|
|
-- CWP generation, pipelinig and forwarding
|
799 |
|
|
-- Also check for window underflow/overflow conditions
|
800 |
|
|
|
801 |
|
|
if (op = FMT3) and ((op3 = RETT) or (op3 = RESTORE) or (op3 = SAVE)) then
|
802 |
|
|
write_cwp := '1';
|
803 |
|
|
if (op3 = SAVE) then
|
804 |
|
|
-- pragma translate_off
|
805 |
|
|
if not is_x(de.cwp) then
|
806 |
|
|
-- pragma translate_on
|
807 |
|
|
if (not CWPOPT) and (de.cwp = CWPMIN) then cwp_new := CWPMAX;
|
808 |
|
|
else cwp_new := de.cwp - 1 ; end if;
|
809 |
|
|
-- pragma translate_off
|
810 |
|
|
end if;
|
811 |
|
|
-- pragma translate_on
|
812 |
|
|
else
|
813 |
|
|
-- pragma translate_off
|
814 |
|
|
if not is_x(de.cwp) then
|
815 |
|
|
-- pragma translate_on
|
816 |
|
|
if (not CWPOPT) and (de.cwp = CWPMAX) then cwp_new := CWPMIN;
|
817 |
|
|
else cwp_new := de.cwp + 1; end if;
|
818 |
|
|
-- pragma translate_off
|
819 |
|
|
end if;
|
820 |
|
|
-- pragma translate_on
|
821 |
|
|
end if;
|
822 |
|
|
|
823 |
|
|
if sregs.wim(conv_integer('0' & cwp_new)) = '1' then
|
824 |
|
|
if op3 = SAVE then winovf_exception := '1';
|
825 |
|
|
else winunf_exception := '1'; end if;
|
826 |
|
|
end if;
|
827 |
|
|
end if;
|
828 |
|
|
|
829 |
|
|
exin.write_cwp <= write_cwp;
|
830 |
|
|
exin.cwp <= cwp_new;
|
831 |
|
|
|
832 |
|
|
-- Immediate data generation
|
833 |
|
|
|
834 |
|
|
immediate_data := (others => '0');
|
835 |
|
|
case op is
|
836 |
|
|
when FMT2 =>
|
837 |
|
|
immediate_data := de.inst(21 downto 0) & "0000000000";
|
838 |
|
|
when FMT3 =>
|
839 |
|
|
case op3 is
|
840 |
|
|
when RDPSR => immediate_data(31 downto 5) := std_logic_vector(IMPL) &
|
841 |
|
|
std_logic_vector(VER) & icc & "000000" & sregs.ec & sregs.ef &
|
842 |
|
|
sregs.pil & su & sregs.ps & et;
|
843 |
|
|
immediate_data(NWINLOG2-1 downto 0) := de.cwp;
|
844 |
|
|
when RDTBR => immediate_data(31 downto 4) := sregs.tba & sregs.tt;
|
845 |
|
|
when RDWIM => immediate_data(NWINDOWS-1 downto 0) := sregs.wim;
|
846 |
|
|
when others =>
|
847 |
|
|
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
848 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
849 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
850 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
851 |
|
|
de.inst(12 downto 0);
|
852 |
|
|
end case;
|
853 |
|
|
when others => -- LDST
|
854 |
|
|
immediate_data := de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
855 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
856 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
857 |
|
|
de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) & de.inst(12) &
|
858 |
|
|
de.inst(12 downto 0);
|
859 |
|
|
end case;
|
860 |
|
|
|
861 |
|
|
-- register read address generation
|
862 |
|
|
|
863 |
|
|
if RS1OPT then
|
864 |
|
|
if rs1mod = '1' then
|
865 |
|
|
read_addr1 := regdec(de.cwp, de.inst(29 downto 26) & rs1(0), (fpst or fpop));
|
866 |
|
|
else
|
867 |
|
|
read_addr1 := regdec(de.cwp, de.inst(18 downto 15) & rs1(0), (fpst or fpop));
|
868 |
|
|
end if;
|
869 |
|
|
else
|
870 |
|
|
read_addr1 := regdec(de.cwp, rs1, (fpst or fpop));
|
871 |
|
|
end if;
|
872 |
|
|
read_addr2 := regdec(de.cwp, rs2, fpop);
|
873 |
|
|
|
874 |
|
|
|
875 |
|
|
-- register write address generation
|
876 |
|
|
|
877 |
|
|
write_reg := '0'; fsr_ld := '0';
|
878 |
|
|
|
879 |
|
|
case op is
|
880 |
|
|
when CALL =>
|
881 |
|
|
write_reg := '1'; rd := "01111"; -- CALL saves PC in r[15] (%o7)
|
882 |
|
|
when FMT2 =>
|
883 |
|
|
if (op2 = SETHI) then write_reg := '1'; end if;
|
884 |
|
|
when FMT3 =>
|
885 |
|
|
case op3 is
|
886 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
887 |
|
|
if MULTIPLIER = none then write_reg := '1'; end if;
|
888 |
|
|
if MULTIPLIER = m32x32 then write_reg := '1'; end if;
|
889 |
|
|
if MULTIPLIER = iterative then
|
890 |
|
|
if de.cnt = "10" then write_reg := '1'; end if;
|
891 |
|
|
end if;
|
892 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
893 |
|
|
if DIVIDER /= none then write_reg := '0'; else write_reg := '1'; end if;
|
894 |
|
|
when RETT | WRPSR | WRY | WRWIM | WRTBR | TICC | FLUSH => null;
|
895 |
|
|
when FPOP1 | FPOP2 => null;
|
896 |
|
|
when CPOP1 | CPOP2 => null;
|
897 |
|
|
when others => write_reg := '1';
|
898 |
|
|
end case;
|
899 |
|
|
when LDST =>
|
900 |
|
|
ctrl.ld := not op3(2);
|
901 |
|
|
if (op3(2) = '0') and
|
902 |
|
|
not ((CPEN or (FPIFTYPE = parallel)) and (op3(5) = '1'))
|
903 |
|
|
then write_reg := '1'; end if;
|
904 |
|
|
case op3 is
|
905 |
|
|
when SWAP | SWAPA | LDSTUB | LDSTUBA =>
|
906 |
|
|
if de.cnt = "00" then write_reg := '1'; end if;
|
907 |
|
|
when LDFSR => if ((FPIFTYPE = serial) and FPEN) then write_reg := '0'; fsr_ld := '1'; end if;
|
908 |
|
|
when others => null;
|
909 |
|
|
end case;
|
910 |
|
|
when others => null;
|
911 |
|
|
end case;
|
912 |
|
|
|
913 |
|
|
if (rd = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpld = '1')) then
|
914 |
|
|
write_reg := '0';
|
915 |
|
|
end if;
|
916 |
|
|
|
917 |
|
|
ctrl.rd := regdec(cwp_new, rd, (fpld or fpop));
|
918 |
|
|
if RDOPT then chkrd := regdec(de.cwp, rd, (fpld or fpop));
|
919 |
|
|
else chkrd := ctrl.rd; end if;
|
920 |
|
|
|
921 |
|
|
-- LD/BICC/TICC delay interlock generation
|
922 |
|
|
|
923 |
|
|
ldcheck1 := '0'; ldcheck2 := '0'; ldcheck3 := '0'; ldlock := '0';
|
924 |
|
|
ldchkex := '1'; ldchkme := '1'; bicc_hold := '0'; icc_check := '0';
|
925 |
|
|
fsr_check := '0'; fsr_ld_check := '0'; fsr_lock := '0';
|
926 |
|
|
|
927 |
|
|
if (de.annul = '0') then
|
928 |
|
|
case op is
|
929 |
|
|
when FMT2 =>
|
930 |
|
|
if (op2 = BICC) and (cond(2 downto 0) /= "000") then
|
931 |
|
|
icc_check := '1';
|
932 |
|
|
end if;
|
933 |
|
|
when FMT3 =>
|
934 |
|
|
ldcheck1 := '1'; ldcheck2 := not i;
|
935 |
|
|
case op3 is
|
936 |
|
|
when TICC =>
|
937 |
|
|
if (cond(2 downto 0) /= "000") then icc_check := '1'; end if;
|
938 |
|
|
when RDY | RDWIM | RDTBR =>
|
939 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
940 |
|
|
when RDPSR =>
|
941 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
942 |
|
|
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
|
943 |
|
|
when ADDX | ADDXCC | SUBX | SUBXCC =>
|
944 |
|
|
if MULTIPLIER = m32x32 then icc_check := '1'; end if;
|
945 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
946 |
|
|
if MULTIPLIER = iterative then
|
947 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
948 |
|
|
if (de.cnt = "00") then ldcheck1 := '1'; end if;
|
949 |
|
|
if (de.cnt = "01") then ldcheck2 := not i; end if;
|
950 |
|
|
end if;
|
951 |
|
|
when FPOP1 | FPOP2 =>
|
952 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
953 |
|
|
ldcheck1 := '0'; ldcheck2 := '0';
|
954 |
|
|
case opf is
|
955 |
|
|
when FITOS | FITOD | FSTOI | FDTOI | FSTOD | FDTOS | FMOVS |
|
956 |
|
|
FNEGS | FABSS | FSQRTS | FSQRTD =>
|
957 |
|
|
ldcheck2 := '1';
|
958 |
|
|
when others => ldcheck1 := '1'; ldcheck2 := '1';
|
959 |
|
|
end case;
|
960 |
|
|
if de.cnt /= "00" then ldchkex := '0'; end if;
|
961 |
|
|
fsr_ld_check := '1';
|
962 |
|
|
end if;
|
963 |
|
|
when others =>
|
964 |
|
|
end case;
|
965 |
|
|
when LDST =>
|
966 |
|
|
ldcheck1 := '1'; ldchkex := '0';
|
967 |
|
|
case de.cnt is
|
968 |
|
|
when "00" => -- check store data dependency if 2-cycle load delay
|
969 |
|
|
if (LDDELAY = 2) and (op3(2) = '1') and not (((FPIFTYPE = serial) and FPEN) and (op3 = STFSR))
|
970 |
|
|
then ldcheck3 := '1'; end if;
|
971 |
|
|
ldcheck2 := not i; ldchkex := '1';
|
972 |
|
|
when "01" => ldcheck2 := not i;
|
973 |
|
|
when others => ldchkme := '0';
|
974 |
|
|
end case;
|
975 |
|
|
if ((FPIFTYPE = serial) and FPEN) and ((op3 = LDFSR) or (op3 = STFSR)) then
|
976 |
|
|
fsr_check := '1';
|
977 |
|
|
if (op3 = STFSR) then fsr_ld_check := '1'; end if;
|
978 |
|
|
end if;
|
979 |
|
|
when others => null;
|
980 |
|
|
end case;
|
981 |
|
|
end if;
|
982 |
|
|
|
983 |
|
|
-- MAC has two-cycle latency, check for data-dependecies
|
984 |
|
|
if MACEN then
|
985 |
|
|
if ((ex.mulinsn and ex.ctrl.inst(24) and ldchkex and not ex.ctrl.annul) = '1') and
|
986 |
|
|
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
|
987 |
|
|
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
|
988 |
|
|
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
|
989 |
|
|
then ldlock := '1'; end if;
|
990 |
|
|
end if;
|
991 |
|
|
|
992 |
|
|
if MACEN or (MULTIPLIER = m32x32) then
|
993 |
|
|
bicc_hold := icc_check and ex.write_icc and ex.mulinsn and not ex.ctrl.annul;
|
994 |
|
|
end if;
|
995 |
|
|
if ICC_HOLD then
|
996 |
|
|
bicc_hold := bicc_hold or (icc_check and ex.write_icc and not ex.ctrl.annul);
|
997 |
|
|
end if;
|
998 |
|
|
|
999 |
|
|
if ((ex.ctrl.ld and ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
|
1000 |
|
|
(((ldcheck1 = '1') and (ex.ctrl.rd = read_addr1)) or
|
1001 |
|
|
((ldcheck2 = '1') and (ex.ctrl.rd = read_addr2)) or
|
1002 |
|
|
((ldcheck3 = '1') and (ex.ctrl.rd = chkrd)))
|
1003 |
|
|
then ldlock := '1'; end if;
|
1004 |
|
|
|
1005 |
|
|
if ((me.ctrl.ld and me.write_reg and ldchkme and not me.ctrl.annul) = '1') and
|
1006 |
|
|
((LDDELAY = 2) or ((fsr_ld_check and not fsr_check) = '1')) and
|
1007 |
|
|
(((ldcheck1 = '1') and (me.ctrl.rd = read_addr1)) or
|
1008 |
|
|
((ldcheck2 = '1') and (me.ctrl.rd = read_addr2)))
|
1009 |
|
|
then ldlock := '1'; end if;
|
1010 |
|
|
|
1011 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
1012 |
|
|
if (fsr_check = '1') then
|
1013 |
|
|
fsr_lock := ((xorv(fpu_reg.ex.fpop) and not ex.ctrl.annul) or
|
1014 |
|
|
(xorv(fpu_reg.me.fpop) and not me.ctrl.annul) or
|
1015 |
|
|
(xorv(fpu_reg.wr.fpop) and not wr.ctrl.annul));
|
1016 |
|
|
end if;
|
1017 |
|
|
if fsr_ld_check = '1' then
|
1018 |
|
|
fsr_lock := fsr_lock or (fpu_reg.ex.ldfsr and not ex.ctrl.annul)
|
1019 |
|
|
or (fpu_reg.me.ldfsr and not me.ctrl.annul)
|
1020 |
|
|
or (fpu_reg.wr.ldfsr and not wr.ctrl.annul);
|
1021 |
|
|
end if;
|
1022 |
|
|
end if;
|
1023 |
|
|
|
1024 |
|
|
ldlock := ldlock or bicc_hold or fsr_lock;
|
1025 |
|
|
cpldlock := ldlock; fpldlock := ldlock;
|
1026 |
|
|
if CPEN then
|
1027 |
|
|
if FPIFTYPE = parallel then cpldlock := cpldlock or fpo.ldlock; end if;
|
1028 |
|
|
ldlock := ldlock or cpo.ldlock;
|
1029 |
|
|
end if;
|
1030 |
|
|
if FPIFTYPE = parallel then
|
1031 |
|
|
if CPEN then fpldlock := fpldlock or cpo.ldlock; end if;
|
1032 |
|
|
ldlock := ldlock or fpo.ldlock;
|
1033 |
|
|
end if;
|
1034 |
|
|
|
1035 |
|
|
-- data forwarding detection. Forward data if destination and source
|
1036 |
|
|
-- registers are equal and destination register will be written.
|
1037 |
|
|
|
1038 |
|
|
rs1data := rfo.data1(31 downto 0); ldbp1 := '0';
|
1039 |
|
|
if (rs1 = "00000") and not (((FPIFTYPE = serial) and FPEN) and ((fpop or fpst) = '1')) then
|
1040 |
|
|
rs1data := (others => '0');
|
1041 |
|
|
elsif ldcheck1 = '1' then
|
1042 |
|
|
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and
|
1043 |
|
|
(read_addr1 = ex.ctrl.rd)
|
1044 |
|
|
then
|
1045 |
|
|
rs1data := ex.result;
|
1046 |
|
|
else
|
1047 |
|
|
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr1 = me.ctrl.rd) then
|
1048 |
|
|
rs1data := mein.bpresult;
|
1049 |
|
|
if LDDELAY = 1 then ldbp1 := me.ctrl.ld; end if;
|
1050 |
|
|
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr1 = wr.ctrl.rd) then
|
1051 |
|
|
rs1data := wr.result;
|
1052 |
|
|
else rfenable1 := '1'; end if;
|
1053 |
|
|
end if;
|
1054 |
|
|
end if;
|
1055 |
|
|
|
1056 |
|
|
rs2data := rfo.data2(31 downto 0); ldbp2 := '0';
|
1057 |
|
|
if (operand2_select = ALU_SIMM) then
|
1058 |
|
|
rs2data := immediate_data;
|
1059 |
|
|
elsif (rs2 = "00000") and not (((FPIFTYPE = serial) and FPEN) and (fpop = '1')) then
|
1060 |
|
|
rs2data := (others => '0');
|
1061 |
|
|
elsif ldcheck2 = '1' then
|
1062 |
|
|
if ((ex.write_reg and ldchkex and not ex.ctrl.annul) = '1') and (read_addr2 = ex.ctrl.rd) then
|
1063 |
|
|
rs2data := ex.result;
|
1064 |
|
|
else
|
1065 |
|
|
if ((me.write_reg and ldchkme and not me.ctrl.annul) = '1') and (read_addr2 = me.ctrl.rd) then
|
1066 |
|
|
rs2data := mein.bpresult;
|
1067 |
|
|
if LDDELAY = 1 then ldbp2 := me.ctrl.ld; end if;
|
1068 |
|
|
elsif ((wr.write_reg and not wr.ctrl.annul) = '1') and (read_addr2 = wr.ctrl.rd) then
|
1069 |
|
|
rs2data := wr.result;
|
1070 |
|
|
else rfenable2 := '1'; end if;
|
1071 |
|
|
end if;
|
1072 |
|
|
end if;
|
1073 |
|
|
|
1074 |
|
|
-- multiply operand generation
|
1075 |
|
|
|
1076 |
|
|
if (ex.write_y and not ex.ctrl.annul) = '1' then
|
1077 |
|
|
y0 := mein.y(0);
|
1078 |
|
|
elsif (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1' then
|
1079 |
|
|
y0 := me.my(0);
|
1080 |
|
|
else
|
1081 |
|
|
y0 := wr.y(0);
|
1082 |
|
|
end if;
|
1083 |
|
|
|
1084 |
|
|
ymsb := '-';
|
1085 |
|
|
|
1086 |
|
|
-- mul/div unit
|
1087 |
|
|
|
1088 |
|
|
divi.y <= (wr.y(31) and op3(0)) & wr.y;
|
1089 |
|
|
divstart := '0'; mulstart := '0';
|
1090 |
|
|
case op is
|
1091 |
|
|
when FMT3 =>
|
1092 |
|
|
case op3 is
|
1093 |
|
|
when MULSCC =>
|
1094 |
|
|
ymsb := rs1data(0); rs1data := (icc(3) xor icc(1)) & rs1data(31 downto 1);
|
1095 |
|
|
if y0 = '0' then
|
1096 |
|
|
rs2data := (others => '0'); rfenable2 := '0'; ldbp2 := '0';
|
1097 |
|
|
end if;
|
1098 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
1099 |
|
|
if MULTIPLIER = iterative then
|
1100 |
|
|
case de.cnt is
|
1101 |
|
|
when "00" =>
|
1102 |
|
|
rs2data := (others => '0'); ymsb := rs1data(0); rfenable2 := '0';
|
1103 |
|
|
when "01" | "10" =>
|
1104 |
|
|
ymsb := ex.result(0);
|
1105 |
|
|
rs1data := (ex.micc(3) xor ex.micc(1)) & ex.result(31 downto 1);
|
1106 |
|
|
if (mein.y(0) = '0') or (de.cnt = "10") then
|
1107 |
|
|
rs2data := (others => '0'); ldbp2 := '0'; rfenable2 := '0';
|
1108 |
|
|
end if;
|
1109 |
|
|
when others =>
|
1110 |
|
|
if (op3 = UMUL) or (op3 = UMULCC) then
|
1111 |
|
|
rs2data := ex.result; rfenable2 := '1';
|
1112 |
|
|
if rfo.data2(31) = '0' then
|
1113 |
|
|
rs1data := (others => '0');
|
1114 |
|
|
end if;
|
1115 |
|
|
else
|
1116 |
|
|
rs1data := ex.result; rfenable1 := '1';
|
1117 |
|
|
if rfo.data1(31) = '0' then
|
1118 |
|
|
rs2data := (others => '0'); rfenable2 := '0';
|
1119 |
|
|
end if;
|
1120 |
|
|
end if;
|
1121 |
|
|
end case;
|
1122 |
|
|
end if;
|
1123 |
|
|
when others => null;
|
1124 |
|
|
end case;
|
1125 |
|
|
when others => null;
|
1126 |
|
|
end case;
|
1127 |
|
|
|
1128 |
|
|
exin.ldbp1 <= ldbp1; exin.ldbp2 <= ldbp2;
|
1129 |
|
|
|
1130 |
|
|
-- PC generation
|
1131 |
|
|
|
1132 |
|
|
branch := '0'; annul_next := '0'; annul_current := '0';
|
1133 |
|
|
inull := not Rst; hold_pc := '0'; ticc_exception := '0';
|
1134 |
|
|
fpop := '0'; fpld := '0';
|
1135 |
|
|
if ((ldlock or de.annul) = '0') then
|
1136 |
|
|
case op is
|
1137 |
|
|
when CALL =>
|
1138 |
|
|
branch := '1';
|
1139 |
|
|
if mein.inull = '1' then
|
1140 |
|
|
hold_pc := '1'; annul_current := '1';
|
1141 |
|
|
end if;
|
1142 |
|
|
when FMT2 =>
|
1143 |
|
|
if (op2 = BICC) or (FPEN and (op2 = FBFCC)) or (CPEN and (op2 = CBCCC)) then
|
1144 |
|
|
if (FPEN and (op2 = FBFCC)) then
|
1145 |
|
|
branch := fbranch_true;
|
1146 |
|
|
if (FPIFTYPE = parallel) and (fpo.ccv /= '1') then
|
1147 |
|
|
hold_pc := '1'; annul_current := '1';
|
1148 |
|
|
end if;
|
1149 |
|
|
elsif (CPEN and (op2 = CBCCC)) then
|
1150 |
|
|
branch := cbranch_true;
|
1151 |
|
|
if cpo.ccv /= '1' then hold_pc := '1'; annul_current := '1'; end if;
|
1152 |
|
|
else branch := branch_true; end if;
|
1153 |
|
|
if hold_pc = '0' then
|
1154 |
|
|
if (branch = '1') then
|
1155 |
|
|
if (cond = BA) and (annul = '1') then annul_next := '1'; end if;
|
1156 |
|
|
else annul_next := annul; end if;
|
1157 |
|
|
if mein.inull = '1' then -- contention with JMPL
|
1158 |
|
|
hold_pc := '1'; annul_current := '1'; annul_next := '0';
|
1159 |
|
|
end if;
|
1160 |
|
|
end if;
|
1161 |
|
|
end if;
|
1162 |
|
|
when FMT3 =>
|
1163 |
|
|
case op3 is
|
1164 |
|
|
when FPOP1 | FPOP2 =>
|
1165 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
1166 |
|
|
case de.cnt is
|
1167 |
|
|
when "00" =>
|
1168 |
|
|
if (opf(1) or fpexin.dsz) = '1' then
|
1169 |
|
|
hold_pc := '1'; pv := '0'; cnt := "01";
|
1170 |
|
|
end if;
|
1171 |
|
|
if (opf(1) or fpmov) = '0' then fpop := holdn; end if;
|
1172 |
|
|
if op3 = FPOP1 then write_reg := not (opf(1) and not fpexin.dsz); end if;
|
1173 |
|
|
when others =>
|
1174 |
|
|
if op3 = FPOP1 then write_reg := '1'; end if;
|
1175 |
|
|
fpop := opf(1) and holdn; cnt := "00";
|
1176 |
|
|
end case;
|
1177 |
|
|
end if;
|
1178 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
1179 |
|
|
if MULTIPLIER = iterative then
|
1180 |
|
|
case de.cnt is
|
1181 |
|
|
when "00" =>
|
1182 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
1183 |
|
|
when "01" =>
|
1184 |
|
|
hold_pc := '1'; pv := '0'; cnt := "01"; mulcnt := mulcnt + 1;
|
1185 |
|
|
if (de.mulcnt = "11111") then cnt := "10"; end if;
|
1186 |
|
|
when "10" =>
|
1187 |
|
|
cnt := "11"; pv := '0'; hold_pc := '1';
|
1188 |
|
|
when "11" =>
|
1189 |
|
|
cnt := "00";
|
1190 |
|
|
when others => null;
|
1191 |
|
|
end case;
|
1192 |
|
|
end if;
|
1193 |
|
|
if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then
|
1194 |
|
|
case de.cnt is
|
1195 |
|
|
when "00" =>
|
1196 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
1197 |
|
|
mulstart := '1';
|
1198 |
|
|
when "01" =>
|
1199 |
|
|
if mulo.ready = '1' then cnt := "00";
|
1200 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
1201 |
|
|
when others => null;
|
1202 |
|
|
end case;
|
1203 |
|
|
end if;
|
1204 |
|
|
when UDIV | SDIV | UDIVCC | SDIVCC =>
|
1205 |
|
|
if DIVIDER /= none then
|
1206 |
|
|
case de.cnt is
|
1207 |
|
|
when "00" =>
|
1208 |
|
|
cnt := "01"; hold_pc := '1'; mulcnt := (others => '0'); pv := '0';
|
1209 |
|
|
divstart := '1';
|
1210 |
|
|
when "01" =>
|
1211 |
|
|
if divo.ready = '1' then cnt := "00";
|
1212 |
|
|
else cnt := "01"; pv := '0'; hold_pc := '1'; end if;
|
1213 |
|
|
when others => null;
|
1214 |
|
|
end case;
|
1215 |
|
|
end if;
|
1216 |
|
|
when TICC =>
|
1217 |
|
|
if branch_true = '1' then ticc_exception := '1'; end if;
|
1218 |
|
|
when RETT =>
|
1219 |
|
|
ctrl.rett := '1'; su := sregs.ps;
|
1220 |
|
|
when others => null;
|
1221 |
|
|
end case;
|
1222 |
|
|
when LDST =>
|
1223 |
|
|
case de.cnt is
|
1224 |
|
|
when "00" =>
|
1225 |
|
|
if (op3(2) = '1') or (op3(1 downto 0) = "11") then -- ST/LDST/SWAP/LDD
|
1226 |
|
|
cnt := "01"; hold_pc := '1'; pv := '0';
|
1227 |
|
|
end if;
|
1228 |
|
|
when "01" =>
|
1229 |
|
|
if (op3(2 downto 0) = "111") or (op3(3 downto 0) = "1101") or
|
1230 |
|
|
((CPEN or FPEN) and ((op3(5) & op3(2 downto 0)) = "1110"))
|
1231 |
|
|
then -- LDD/STD/LDSTUB/SWAP
|
1232 |
|
|
cnt := "10"; pv := '0'; hold_pc := '1';
|
1233 |
|
|
else
|
1234 |
|
|
cnt := "00";
|
1235 |
|
|
end if;
|
1236 |
|
|
when "10" =>
|
1237 |
|
|
cnt := "00";
|
1238 |
|
|
when others => null;
|
1239 |
|
|
end case;
|
1240 |
|
|
when others => null;
|
1241 |
|
|
end case;
|
1242 |
|
|
end if;
|
1243 |
|
|
|
1244 |
|
|
muli.start <= mulstart;
|
1245 |
|
|
divi.start <= divstart;
|
1246 |
|
|
|
1247 |
|
|
-- instruction watchpoints
|
1248 |
|
|
|
1249 |
|
|
watchpoint_exc := '0';
|
1250 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
1251 |
|
|
if ((tr(i).exec and not de.annul) = '1') then
|
1252 |
|
|
if (((tr(i).addr xor de.pc(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)) then
|
1253 |
|
|
watchpoint_exc := '1';
|
1254 |
|
|
end if;
|
1255 |
|
|
end if;
|
1256 |
|
|
end loop;
|
1257 |
|
|
|
1258 |
|
|
if DEBUG_UNIT then
|
1259 |
|
|
if ((iui.debug.dsuen and iui.debug.bwatch and not de.annul) = '1') then
|
1260 |
|
|
watchpoint_exc := de.pv and (watchpoint_exc or iui.debug.dbreak or de.step);
|
1261 |
|
|
end if;
|
1262 |
|
|
end if;
|
1263 |
|
|
|
1264 |
|
|
-- prioritise traps
|
1265 |
|
|
|
1266 |
|
|
ctrl.trap := de.mexc or privileged_inst or illegal_inst or fp_disabled or
|
1267 |
|
|
cp_disabled or ticc_exception or winunf_exception or
|
1268 |
|
|
winovf_exception or fp_exception or watchpoint_exc;
|
1269 |
|
|
|
1270 |
|
|
if de.mexc = '1' then ctrl.tt := IAEX_TT;
|
1271 |
|
|
elsif privileged_inst = '1' then ctrl.tt := PRIV_TT;
|
1272 |
|
|
elsif illegal_inst = '1' then ctrl.tt := IINST_TT;
|
1273 |
|
|
elsif fp_disabled = '1' then ctrl.tt := FPDIS_TT;
|
1274 |
|
|
elsif cp_disabled = '1' then ctrl.tt := CPDIS_TT;
|
1275 |
|
|
elsif watchpoint_exc = '1' then ctrl.tt := WATCH_TT;
|
1276 |
|
|
elsif winovf_exception = '1' then ctrl.tt := WINOF_TT;
|
1277 |
|
|
elsif winunf_exception = '1' then ctrl.tt := WINUF_TT;
|
1278 |
|
|
elsif fp_exception = '1' then ctrl.tt := FPEXC_TT;
|
1279 |
|
|
elsif ticc_exception = '1' then ctrl.tt := TICC_TT;
|
1280 |
|
|
end if;
|
1281 |
|
|
|
1282 |
|
|
|
1283 |
|
|
hold_pc := (hold_pc or ldlock) and not wr.annul_all;
|
1284 |
|
|
|
1285 |
|
|
if hold_pc = '1' then dein.pc <= de.pc;
|
1286 |
|
|
else dein.pc <= fe.pc; end if;
|
1287 |
|
|
|
1288 |
|
|
annul_current_cp := annul_current;
|
1289 |
|
|
annul_current := (annul_current or ldlock or wr.annul_all);
|
1290 |
|
|
ctrl.annul := de.annul or wr.annul_all or annul_current;
|
1291 |
|
|
pv := pv and not ((mein.inull and not hold_pc) or wr.annul_all);
|
1292 |
|
|
annul_next := (mein.inull and not hold_pc) or annul_next or wr.annul_all
|
1293 |
|
|
or (ldlock and de.annul);
|
1294 |
|
|
if (annul_next = '1') or (rst = '0') then
|
1295 |
|
|
cnt := (others => '0'); mulcnt := (others => '0');
|
1296 |
|
|
end if;
|
1297 |
|
|
|
1298 |
|
|
if DEBUG_UNIT then
|
1299 |
|
|
step := iui.debug.step and pv and not de.annul;
|
1300 |
|
|
end if;
|
1301 |
|
|
fecomb.hold_pc <= hold_pc;
|
1302 |
|
|
fecomb.branch <= branch;
|
1303 |
|
|
dein.annul <= annul_next;
|
1304 |
|
|
dein.cnt <= cnt;
|
1305 |
|
|
dein.mulcnt <= mulcnt;
|
1306 |
|
|
dein.step <= step;
|
1307 |
|
|
dein.pv <= pv;
|
1308 |
|
|
-- pv means that the corresponding pc can be save on a trap
|
1309 |
|
|
ctrl.pv := de.pv and
|
1310 |
|
|
not ((de.annul and not de.pv) or wr.annul_all or annul_current);
|
1311 |
|
|
inull := inull or mein.inull or hold_pc or wr.annul_all;
|
1312 |
|
|
|
1313 |
|
|
ici.nullify <= inull;
|
1314 |
|
|
ici.su <= su;
|
1315 |
|
|
exin.ctrl <= ctrl;
|
1316 |
|
|
exin.write_reg <= write_reg;
|
1317 |
|
|
|
1318 |
|
|
-- latch next cwp
|
1319 |
|
|
|
1320 |
|
|
if wr.trapping = '1' then
|
1321 |
|
|
dein.cwp <= sregsin.cwp;
|
1322 |
|
|
elsif (write_cwp and not ctrl.annul) = '1' then
|
1323 |
|
|
dein.cwp <= cwp_new;
|
1324 |
|
|
elsif (ex.write_cwp and not ex.ctrl.annul) = '1' then
|
1325 |
|
|
dein.cwp <= ex.cwp;
|
1326 |
|
|
elsif (me.write_cwp and not me.ctrl.annul) = '1' then
|
1327 |
|
|
dein.cwp <= me.cwp;
|
1328 |
|
|
elsif (wr.write_cwp and not wr.ctrl.annul) = '1' then
|
1329 |
|
|
dein.cwp <= wr.cwp;
|
1330 |
|
|
else
|
1331 |
|
|
dein.cwp <= sregs.cwp;
|
1332 |
|
|
end if;
|
1333 |
|
|
|
1334 |
|
|
|
1335 |
|
|
-- y-register write select and forwarding
|
1336 |
|
|
|
1337 |
|
|
rst_mey := '0';
|
1338 |
|
|
|
1339 |
|
|
case op is
|
1340 |
|
|
when FMT3 =>
|
1341 |
|
|
case op3 is
|
1342 |
|
|
when MULSCC => write_y := '1';
|
1343 |
|
|
when WRY => if rd = "00000" then write_y := '1'; end if;
|
1344 |
|
|
when UMAC | SMAC =>
|
1345 |
|
|
if MACEN then write_y := '1'; end if;
|
1346 |
|
|
when UMUL | SMUL | UMULCC | SMULCC =>
|
1347 |
|
|
if MULTIPLIER = iterative then
|
1348 |
|
|
if de.cnt = "00" then rst_mey := '1'; end if;
|
1349 |
|
|
if de.cnt = "11" then write_y := '1'; end if;
|
1350 |
|
|
end if;
|
1351 |
|
|
if MULTIPLIER = m32x32 then write_y := '1'; end if;
|
1352 |
|
|
when others => null;
|
1353 |
|
|
end case;
|
1354 |
|
|
when others => null;
|
1355 |
|
|
end case;
|
1356 |
|
|
|
1357 |
|
|
-- debug unit diagnostic regfile read
|
1358 |
|
|
if DEBUG_UNIT and (dsur.dmode and iui.debug.denable) = '1' then
|
1359 |
|
|
read_addr1 := iui.debug.daddr(RABITS+1 downto 2); rfenable1 := '1';
|
1360 |
|
|
end if;
|
1361 |
|
|
|
1362 |
|
|
exin.write_y <= write_y;
|
1363 |
|
|
exin.rst_mey <= rst_mey;
|
1364 |
|
|
exin.rs1data <= rs1data;
|
1365 |
|
|
exin.rs2data <= rs2data;
|
1366 |
|
|
exin.ymsb <= ymsb;
|
1367 |
|
|
rfi.rd1addr <= read_addr1; rfi.rd2addr <= read_addr2;
|
1368 |
|
|
|
1369 |
|
|
-- CP/FPU interface
|
1370 |
|
|
|
1371 |
|
|
if (FPIFTYPE = serial) then
|
1372 |
|
|
fpu_regin.fpop <= fpop and (not fpu_reg.fpld) and not ctrl.annul;
|
1373 |
|
|
fpexin.ldfsr := fsr_ld;
|
1374 |
|
|
fpu_regin.ex <= fpexin;
|
1375 |
|
|
end if;
|
1376 |
|
|
|
1377 |
|
|
if CPEN then
|
1378 |
|
|
cpi.dannul <= annul_current_cp or cpldlock or wr.annul_all or de.annul;
|
1379 |
|
|
cpi.dtrap <= ctrl.trap;
|
1380 |
|
|
end if;
|
1381 |
|
|
|
1382 |
|
|
if FPIFTYPE = parallel then
|
1383 |
|
|
fpi.dannul <= annul_current_cp or fpldlock or wr.annul_all or de.annul;
|
1384 |
|
|
fpi.dtrap <= ctrl.trap;
|
1385 |
|
|
fpi.fdata <= ico.data;
|
1386 |
|
|
fpi.frdy <= (not ico.mds) or (holdn and not hold_pc);
|
1387 |
|
|
end if;
|
1388 |
|
|
|
1389 |
|
|
|
1390 |
|
|
if RF_LOWPOW = false then rfenable1 := '1'; rfenable2 := '1'; end if;
|
1391 |
|
|
rfi.ren1 <= rfenable1; rfi.ren2 <= rfenable2;
|
1392 |
|
|
|
1393 |
|
|
end process;
|
1394 |
|
|
|
1395 |
|
|
-------------------------------------------------------------------------------
|
1396 |
|
|
-- execute stage
|
1397 |
|
|
-------------------------------------------------------------------------------
|
1398 |
|
|
|
1399 |
|
|
|
1400 |
|
|
execute_stage : process(rst, de, ex, me, wr, wrin, sregs, fpu_reg, fpu_regin,
|
1401 |
|
|
fpo, cpo, fpuo, mulo, divo, tr, iui, dsur, sum32)
|
1402 |
|
|
|
1403 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1404 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1405 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
1406 |
|
|
variable rs1 : std_logic_vector(4 downto 0);
|
1407 |
|
|
variable inull, jump, link_pc : std_logic;
|
1408 |
|
|
variable dcache_write : std_logic; -- Load or store cycle
|
1409 |
|
|
variable memory_load : std_logic;
|
1410 |
|
|
variable signed : std_logic;
|
1411 |
|
|
variable enaddr : std_logic;
|
1412 |
|
|
variable force_a2 : std_logic; -- force A(2) in second LDD cycle
|
1413 |
|
|
variable addr_misal : std_logic; -- misaligned address (JMPL/RETT)
|
1414 |
|
|
variable ld_size : std_logic_vector(1 downto 0); -- Load size
|
1415 |
|
|
variable read : std_logic;
|
1416 |
|
|
variable su : std_logic; -- Local supervisor bit
|
1417 |
|
|
variable asi : std_logic_vector(7 downto 0); -- Local ASI
|
1418 |
|
|
variable ctrl : pipeline_control_type;
|
1419 |
|
|
variable res, y : std_logic_vector(31 downto 0);
|
1420 |
|
|
variable icc, licc, micc : std_logic_vector(3 downto 0);
|
1421 |
|
|
variable addout : std_logic_vector(31 downto 0);
|
1422 |
|
|
variable shiftout : std_logic_vector(31 downto 0);
|
1423 |
|
|
variable logicout : std_logic_vector(31 downto 0);
|
1424 |
|
|
variable miscout : std_logic_vector(31 downto 0);
|
1425 |
|
|
variable edata : std_logic_vector(31 downto 0);
|
1426 |
|
|
variable aluresult : std_logic_vector(31 downto 0);
|
1427 |
|
|
variable eaddress : std_logic_vector(31 downto 0);
|
1428 |
|
|
variable nexty : std_logic_vector(31 downto 0);
|
1429 |
|
|
variable aluin1, aluin2 : std_logic_vector(31 downto 0);
|
1430 |
|
|
variable shiftin : std_logic_vector(63 downto 0);
|
1431 |
|
|
variable shiftcnt : std_logic_vector(4 downto 0);
|
1432 |
|
|
variable ymsb : std_logic; -- next msb of Y during MUL
|
1433 |
|
|
variable write_reg, write_icc, write_y : std_logic;
|
1434 |
|
|
variable lock : std_logic;
|
1435 |
|
|
variable dsu_cache : std_logic;
|
1436 |
|
|
variable fpmein : fpu_ctrl2_type;
|
1437 |
|
|
variable mulop1, mulop2 : std_logic_vector(32 downto 0);
|
1438 |
|
|
variable wpi : integer range 0 to 3; -- watchpoint index
|
1439 |
|
|
variable addin2 : std_logic_vector(31 downto 0);
|
1440 |
|
|
variable cin : std_logic;
|
1441 |
|
|
|
1442 |
|
|
begin
|
1443 |
|
|
|
1444 |
|
|
-- op-code decoding
|
1445 |
|
|
|
1446 |
|
|
op := ex.ctrl.inst(31 downto 30);
|
1447 |
|
|
op3 := ex.ctrl.inst(24 downto 19);
|
1448 |
|
|
opf := ex.ctrl.inst(13 downto 5);
|
1449 |
|
|
rs1 := ex.ctrl.inst(18 downto 14);
|
1450 |
|
|
|
1451 |
|
|
-- common initialisation
|
1452 |
|
|
|
1453 |
|
|
ctrl := ex.ctrl; memory_load := '0';
|
1454 |
|
|
ctrl.annul := ctrl.annul or wr.annul_all;
|
1455 |
|
|
read := not op3(2);
|
1456 |
|
|
dcache_write := '0'; enaddr := '0'; wpi := 0;
|
1457 |
|
|
ld_size := LDWORD; signed := '0'; addr_misal := '0'; lock := '0';
|
1458 |
|
|
write_reg := ex.write_reg;
|
1459 |
|
|
write_icc := ex.write_icc;
|
1460 |
|
|
write_y := ex.write_y;
|
1461 |
|
|
fpmein.fpop := fpu_reg.ex.fpop;
|
1462 |
|
|
fpmein.dsz := fpu_reg.ex.dsz;
|
1463 |
|
|
fpmein.ldfsr := fpu_reg.ex.ldfsr;
|
1464 |
|
|
fpmein.cexc := fpuo.excep(4 downto 0);
|
1465 |
|
|
fpmein.fcc := fpuo.ConditionCodes;
|
1466 |
|
|
muli.mac <= op3(5);
|
1467 |
|
|
dsu_cache := '0';
|
1468 |
|
|
|
1469 |
|
|
-- load/store size decoding
|
1470 |
|
|
|
1471 |
|
|
case op is
|
1472 |
|
|
when LDST =>
|
1473 |
|
|
case op3 is
|
1474 |
|
|
when LDUB | LDUBA => ld_size := LDBYTE;
|
1475 |
|
|
when LDSTUB | LDSTUBA => ld_size := LDBYTE; lock := '1';
|
1476 |
|
|
when LDUH | LDUHA => ld_size := LDHALF;
|
1477 |
|
|
when LDSB | LDSBA => ld_size := LDBYTE; signed := '1';
|
1478 |
|
|
when LDSH | LDSHA => ld_size := LDHALF; signed := '1';
|
1479 |
|
|
when LD | LDA | LDF | LDC => ld_size := LDWORD;
|
1480 |
|
|
when SWAP | SWAPA => ld_size := LDWORD; lock := '1';
|
1481 |
|
|
when LDD | LDDA | LDDF | LDDC => ld_size := LDDBL;
|
1482 |
|
|
when STB | STBA => ld_size := LDBYTE;
|
1483 |
|
|
when STH | STHA => ld_size := LDHALF;
|
1484 |
|
|
when ST | STA | STF => ld_size := LDWORD;
|
1485 |
|
|
when ISTD | STDA => ld_size := LDDBL;
|
1486 |
|
|
when STDF | STDFQ => if FPEN then ld_size := LDDBL; end if;
|
1487 |
|
|
when STDC | STDCQ => if CPEN then ld_size := LDDBL; end if;
|
1488 |
|
|
when others => null;
|
1489 |
|
|
end case;
|
1490 |
|
|
when others => null;
|
1491 |
|
|
end case;
|
1492 |
|
|
|
1493 |
|
|
link_pc := '0'; jump:= '0'; inull :='0'; force_a2 := '0';
|
1494 |
|
|
|
1495 |
|
|
-- load/store control decoding
|
1496 |
|
|
|
1497 |
|
|
if (ctrl.annul = '0') then
|
1498 |
|
|
case op is
|
1499 |
|
|
when CALL =>
|
1500 |
|
|
link_pc := '1';
|
1501 |
|
|
when FMT3 =>
|
1502 |
|
|
case op3 is
|
1503 |
|
|
when JMPL =>
|
1504 |
|
|
jump := '1'; link_pc := '1';
|
1505 |
|
|
inull := me.ctrl.annul or not me.jmpl_rett;
|
1506 |
|
|
when RETT =>
|
1507 |
|
|
jump := '1'; inull := me.ctrl.annul or not me.jmpl_rett;
|
1508 |
|
|
when others => null;
|
1509 |
|
|
end case;
|
1510 |
|
|
when LDST =>
|
1511 |
|
|
if (ctrl.trap or (wrin.ctrl.trap and not wrin.ctrl.annul)) = '0' then
|
1512 |
|
|
case ex.ctrl.cnt is
|
1513 |
|
|
when "00" =>
|
1514 |
|
|
memory_load := op3(3) or not op3(2); -- LD/LDST/SWAP
|
1515 |
|
|
read := memory_load; enaddr := '1';
|
1516 |
|
|
when "01" =>
|
1517 |
|
|
memory_load := not op3(2); -- LDD
|
1518 |
|
|
enaddr := memory_load;
|
1519 |
|
|
force_a2 := memory_load;
|
1520 |
|
|
if op3(3 downto 2) = "01" then -- ST/STD
|
1521 |
|
|
dcache_write := '1';
|
1522 |
|
|
end if;
|
1523 |
|
|
if op3(3 downto 2) = "11" then -- LDST/SWAP
|
1524 |
|
|
enaddr := '1';
|
1525 |
|
|
end if;
|
1526 |
|
|
when "10" => -- STD/LDST/SWAP
|
1527 |
|
|
dcache_write := '1';
|
1528 |
|
|
when others => null;
|
1529 |
|
|
end case;
|
1530 |
|
|
end if;
|
1531 |
|
|
when others => null;
|
1532 |
|
|
end case;
|
1533 |
|
|
end if;
|
1534 |
|
|
|
1535 |
|
|
-- supervisor bit generation
|
1536 |
|
|
|
1537 |
|
|
if ((wr.ctrl.rett and not wr.ctrl.annul) = '1') then su := sregs.ps;
|
1538 |
|
|
else su := sregs.s; end if;
|
1539 |
|
|
if su = '1' then asi := "00001011"; else asi := "00001010"; end if;
|
1540 |
|
|
if (op3(4) = '1') and ((op3(5) = '0') or not CPEN) then
|
1541 |
|
|
asi := ex.ctrl.inst(12 downto 5);
|
1542 |
|
|
end if;
|
1543 |
|
|
|
1544 |
|
|
|
1545 |
|
|
-- load data bypass in case (LDDELAY = 1)
|
1546 |
|
|
|
1547 |
|
|
aluin1 := ex.rs1data; aluin2 := ex.rs2data; ymsb := ex.ymsb;
|
1548 |
|
|
|
1549 |
|
|
if LDDELAY = 1 then
|
1550 |
|
|
if ex.ldbp1 = '1' then aluin1 := wr.result; ymsb := wr.result(0); end if;
|
1551 |
|
|
if ex.ldbp2 = '1' then aluin2 := wr.result; end if;
|
1552 |
|
|
end if;
|
1553 |
|
|
|
1554 |
|
|
-- bypassed operands to multiplier
|
1555 |
|
|
|
1556 |
|
|
muli.signed <= op3(0); divi.signed <= op3(0);
|
1557 |
|
|
mulop1 := (aluin1(31) and op3(0)) & aluin1;
|
1558 |
|
|
mulop2 := (aluin2(31) and op3(0)) & aluin2;
|
1559 |
|
|
if (ex.mulinsn = '0') and not INFER_MULT then -- try to minimise power
|
1560 |
|
|
mulop1 := (others => '0'); mulop2 := (others => '0');
|
1561 |
|
|
end if;
|
1562 |
|
|
muli.op1 <= mulop1; muli.op2 <= mulop2;
|
1563 |
|
|
|
1564 |
|
|
divi.op1 <= (aluin1(31) and op3(0)) & aluin1;
|
1565 |
|
|
divi.op2 <= (aluin2(31) and op3(0)) & aluin2;
|
1566 |
|
|
|
1567 |
|
|
-- ALU add/sub
|
1568 |
|
|
|
1569 |
|
|
icc := "0000";
|
1570 |
|
|
|
1571 |
|
|
-- pragma translate_off
|
1572 |
|
|
if not (is_x(aluin1) or is_x(aluin2)) then
|
1573 |
|
|
-- pragma translate_on
|
1574 |
|
|
cin := ex.alu_cin; addin2 := aluin2;
|
1575 |
|
|
if ex.aluadd = '0' then
|
1576 |
|
|
addin2 := not aluin2; cin := not cin;
|
1577 |
|
|
end if;
|
1578 |
|
|
-- addout := aluin1 + addin2 + cin;
|
1579 |
|
|
if FASTADD then addout := sum32;
|
1580 |
|
|
else
|
1581 |
|
|
if ex.aluadd = '0' then addout := aluin1 - aluin2 - ex.alu_cin;
|
1582 |
|
|
else addout := aluin1 + aluin2 + ex.alu_cin; end if;
|
1583 |
|
|
end if;
|
1584 |
|
|
-- pragma translate_off
|
1585 |
|
|
end if;
|
1586 |
|
|
-- pragma translate_on
|
1587 |
|
|
|
1588 |
|
|
add32in1 <= aluin1;
|
1589 |
|
|
add32in2 <= addin2;
|
1590 |
|
|
add32cin <= cin;
|
1591 |
|
|
|
1592 |
|
|
-- fast address adders if enabled
|
1593 |
|
|
|
1594 |
|
|
if FASTJUMP then
|
1595 |
|
|
-- pragma translate_off
|
1596 |
|
|
if not (is_x(aluin1) or is_x(aluin2)) then
|
1597 |
|
|
-- pragma translate_on
|
1598 |
|
|
fecomb.jump_address <= aluin1(31 downto PCLOW) + aluin2(31 downto PCLOW);
|
1599 |
|
|
if (aluin1(1 downto 0) + aluin2(1 downto 0)) = "00" then
|
1600 |
|
|
addr_misal := '0';
|
1601 |
|
|
else
|
1602 |
|
|
addr_misal := '1';
|
1603 |
|
|
end if;
|
1604 |
|
|
-- pragma translate_off
|
1605 |
|
|
else
|
1606 |
|
|
fecomb.jump_address <= (others => 'X');
|
1607 |
|
|
end if;
|
1608 |
|
|
-- pragma translate_on
|
1609 |
|
|
else
|
1610 |
|
|
fecomb.jump_address(31 downto PCLOW) <= addout(31 downto PCLOW);
|
1611 |
|
|
if addout(1 downto 0) = "00" then
|
1612 |
|
|
addr_misal := '0';
|
1613 |
|
|
else
|
1614 |
|
|
addr_misal := '1';
|
1615 |
|
|
end if;
|
1616 |
|
|
end if;
|
1617 |
|
|
|
1618 |
|
|
res := (others => '-');
|
1619 |
|
|
|
1620 |
|
|
-- alu ops which set icc
|
1621 |
|
|
|
1622 |
|
|
case ex.aluop is
|
1623 |
|
|
when ALU_OR => logicout := aluin1 or aluin2;
|
1624 |
|
|
when ALU_ORN => logicout := aluin1 or not aluin2;
|
1625 |
|
|
when ALU_AND => logicout := aluin1 and aluin2;
|
1626 |
|
|
when ALU_ANDN => logicout := aluin1 and not aluin2;
|
1627 |
|
|
when ALU_XOR => logicout := aluin1 xor aluin2;
|
1628 |
|
|
when ALU_XNOR => logicout := aluin1 xor not aluin2;
|
1629 |
|
|
when ALU_DIV =>
|
1630 |
|
|
if DIVIDER /= none then logicout := aluin2;
|
1631 |
|
|
else logicout := (others => '-'); end if;
|
1632 |
|
|
when others => logicout := (others => '-');
|
1633 |
|
|
end case;
|
1634 |
|
|
|
1635 |
|
|
-- generate condition codes
|
1636 |
|
|
|
1637 |
|
|
if (ex.alusel(1) = '0') then
|
1638 |
|
|
res := addout;
|
1639 |
|
|
if ex.aluadd = '0' then
|
1640 |
|
|
icc(0) := ((not aluin1(31)) and aluin2(31)) or -- Carry
|
1641 |
|
|
(addout(31) and ((not aluin1(31)) or aluin2(31)));
|
1642 |
|
|
icc(1) := (aluin1(31) and (not aluin2(31)) and not addout(31)) or -- Overflow
|
1643 |
|
|
(addout(31) and (not aluin1(31)) and aluin2(31));
|
1644 |
|
|
else
|
1645 |
|
|
icc(0) := (aluin1(31) and aluin2(31)) or -- Carry
|
1646 |
|
|
((not addout(31)) and (aluin1(31) or aluin2(31)));
|
1647 |
|
|
icc(1) := (aluin1(31) and aluin2(31) and not addout(31)) or -- Overflow
|
1648 |
|
|
(addout(31) and (not aluin1(31)) and (not aluin2(31)));
|
1649 |
|
|
end if;
|
1650 |
|
|
else
|
1651 |
|
|
res := logicout;
|
1652 |
|
|
icc(1 downto 0) := "00";
|
1653 |
|
|
end if;
|
1654 |
|
|
|
1655 |
|
|
if res = zero32 then -- Zero
|
1656 |
|
|
icc(2) := '1';
|
1657 |
|
|
else
|
1658 |
|
|
icc(2) := '0';
|
1659 |
|
|
end if;
|
1660 |
|
|
icc(3) := res(31); -- Negative
|
1661 |
|
|
|
1662 |
|
|
-- select Y
|
1663 |
|
|
|
1664 |
|
|
if (me.write_y and not (me.ctrl.annul or me.ctrl.trap)) = '1'
|
1665 |
|
|
then y := me.my; else y := wr.y; end if;
|
1666 |
|
|
|
1667 |
|
|
-- alu ops which dont set icc
|
1668 |
|
|
|
1669 |
|
|
miscout := (others => '-'); edata := (others => '-');
|
1670 |
|
|
case ex.aluop is
|
1671 |
|
|
when ALU_STB => edata := aluin1(7 downto 0) & aluin1(7 downto 0) &
|
1672 |
|
|
aluin1(7 downto 0) & aluin1(7 downto 0);
|
1673 |
|
|
miscout := edata;
|
1674 |
|
|
when ALU_STH => edata := aluin1(15 downto 0) & aluin1(15 downto 0);
|
1675 |
|
|
miscout := edata;
|
1676 |
|
|
when ALU_PASS1 => miscout := aluin1; edata := aluin1;
|
1677 |
|
|
when ALU_PASS2 => miscout := aluin2;
|
1678 |
|
|
when ALU_ONES => miscout := (others => '1'); edata := (others => '1');
|
1679 |
|
|
when ALU_RDY =>
|
1680 |
|
|
miscout := y;
|
1681 |
|
|
|
1682 |
|
|
if (WATCHPOINTS > 0) and (rs1(4 downto 3) = "11") then
|
1683 |
|
|
wpi := conv_integer(unsigned(rs1(2 downto 1)));
|
1684 |
|
|
if rs1(0) = '0' then miscout := tr(wpi).addr & '0' & tr(wpi).exec;
|
1685 |
|
|
else miscout := tr(wpi).mask & tr(wpi).load & tr(wpi).store; end if;
|
1686 |
|
|
end if;
|
1687 |
|
|
when ALU_FSR =>
|
1688 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
1689 |
|
|
edata := fpu_reg.fsr.rd & "00" & fpu_reg.fsr.tem & "000" &
|
1690 |
|
|
std_logic_vector(FPUVER) & fpu_reg.fsr.ftt & "00" & fpu_reg.fsr.fcc &
|
1691 |
|
|
fpu_reg.fsr.aexc & fpu_reg.fsr.cexc;
|
1692 |
|
|
miscout := edata;
|
1693 |
|
|
end if;
|
1694 |
|
|
when ALU_FOP =>
|
1695 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
1696 |
|
|
miscout := aluin2;
|
1697 |
|
|
case opf(3 downto 2) is
|
1698 |
|
|
when "01" => miscout(31) := not miscout(31);
|
1699 |
|
|
when "10" => miscout(31) := '0';
|
1700 |
|
|
when others => null;
|
1701 |
|
|
end case;
|
1702 |
|
|
end if;
|
1703 |
|
|
when others => null;
|
1704 |
|
|
end case;
|
1705 |
|
|
|
1706 |
|
|
-- shifter
|
1707 |
|
|
|
1708 |
|
|
shiftin := zero32 & aluin1;
|
1709 |
|
|
shiftcnt := aluin2(4 downto 0);
|
1710 |
|
|
|
1711 |
|
|
if ex.aluop = ALU_SLL then
|
1712 |
|
|
shiftin(31 downto 0) := zero32;
|
1713 |
|
|
shiftin(63 downto 31) := '0' & aluin1;
|
1714 |
|
|
shiftcnt := not shiftcnt;
|
1715 |
|
|
elsif ex.aluop = ALU_SRA then
|
1716 |
|
|
if aluin1(31) = '1' then
|
1717 |
|
|
shiftin(63 downto 32) := (others => '1');
|
1718 |
|
|
else
|
1719 |
|
|
shiftin(63 downto 32) := zero32;
|
1720 |
|
|
end if;
|
1721 |
|
|
end if;
|
1722 |
|
|
if shiftcnt (4) = '1' then
|
1723 |
|
|
shiftin(47 downto 0) := shiftin(63 downto 16);
|
1724 |
|
|
end if;
|
1725 |
|
|
if shiftcnt (3) = '1' then
|
1726 |
|
|
shiftin(39 downto 0) := shiftin(47 downto 8);
|
1727 |
|
|
end if;
|
1728 |
|
|
if shiftcnt (2) = '1' then
|
1729 |
|
|
shiftin(35 downto 0) := shiftin(39 downto 4);
|
1730 |
|
|
end if;
|
1731 |
|
|
if shiftcnt (1) = '1' then
|
1732 |
|
|
shiftin(33 downto 0) := shiftin(35 downto 2);
|
1733 |
|
|
end if;
|
1734 |
|
|
if shiftcnt (0) = '1' then
|
1735 |
|
|
shiftin(31 downto 0) := shiftin(32 downto 1);
|
1736 |
|
|
end if;
|
1737 |
|
|
shiftout := shiftin(31 downto 0);
|
1738 |
|
|
|
1739 |
|
|
-- generate overflow for tagged add/sub
|
1740 |
|
|
|
1741 |
|
|
case op is
|
1742 |
|
|
when FMT3 =>
|
1743 |
|
|
case op3 is
|
1744 |
|
|
when TADDCC | TADDCCTV | TSUBCC | TSUBCCTV =>
|
1745 |
|
|
icc(1) := aluin1(0) or aluin1(1) or aluin2(0) or aluin2(1) or icc(1);
|
1746 |
|
|
when others => null;
|
1747 |
|
|
end case;
|
1748 |
|
|
when others => null;
|
1749 |
|
|
end case;
|
1750 |
|
|
|
1751 |
|
|
-- select alu output
|
1752 |
|
|
|
1753 |
|
|
aluresult := (others => '0');
|
1754 |
|
|
if link_pc = '1' then
|
1755 |
|
|
aluresult := ex.ctrl.pc(31 downto 2) & "00"; -- save PC during jmpl
|
1756 |
|
|
else
|
1757 |
|
|
case ex.alusel is
|
1758 |
|
|
when ALU_RES_ADD => aluresult := addout;
|
1759 |
|
|
when ALU_RES_SHIFT => aluresult := shiftout;
|
1760 |
|
|
when ALU_RES_LOGIC => aluresult := logicout;
|
1761 |
|
|
when others => aluresult := miscout;
|
1762 |
|
|
end case;
|
1763 |
|
|
end if;
|
1764 |
|
|
|
1765 |
|
|
ex.icc <= icc;
|
1766 |
|
|
|
1767 |
|
|
-- FPU interface
|
1768 |
|
|
|
1769 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
1770 |
|
|
-- pragma translate_off
|
1771 |
|
|
if is_x(aluin1) then aluin1 := (others => '0'); end if;
|
1772 |
|
|
if is_x(aluin2) then aluin2 := (others => '0'); end if;
|
1773 |
|
|
if is_x(de.inst(19) & de.inst(13 downto 5)) then
|
1774 |
|
|
fpui.FpInst <= (others => '0');
|
1775 |
|
|
else
|
1776 |
|
|
-- pragma translate_on
|
1777 |
|
|
fpui.FpInst <= de.inst(19) & de.inst(13 downto 5);
|
1778 |
|
|
-- pragma translate_off
|
1779 |
|
|
end if;
|
1780 |
|
|
if is_x(fpu_reg.fsr.rd) then fpui.RoundingMode <= (others => '0');
|
1781 |
|
|
else
|
1782 |
|
|
-- pragma translate_on
|
1783 |
|
|
fpui.RoundingMode <= fpu_reg.fsr.rd;
|
1784 |
|
|
-- pragma translate_off
|
1785 |
|
|
end if;
|
1786 |
|
|
-- pragma translate_on
|
1787 |
|
|
if (ex.ctrl.cnt = "00") or (opf(1) = '0') then
|
1788 |
|
|
fpui.fprf_dout1 <= aluin1 & aluin1;
|
1789 |
|
|
fpui.fprf_dout2 <= aluin2 & aluin2;
|
1790 |
|
|
else
|
1791 |
|
|
fpui.fprf_dout1 <= fpu_reg.op1h & aluin1;
|
1792 |
|
|
fpui.fprf_dout2 <= me.result & aluin2;
|
1793 |
|
|
end if;
|
1794 |
|
|
fpu_regin.op1h <= aluin1;
|
1795 |
|
|
if fpu_reg.ex.fpop = "01" and (ex.write_reg = '1') then
|
1796 |
|
|
if fpu_reg.ex.dsz = '1' then
|
1797 |
|
|
if (ex.ctrl.cnt /= "00") then
|
1798 |
|
|
aluresult := fpuo.FracResult(34 downto 3);
|
1799 |
|
|
end if;
|
1800 |
|
|
else
|
1801 |
|
|
aluresult := fpuo.SignResult & fpuo.ExpResult(7 downto 0) &
|
1802 |
|
|
fpuo.FracResult(54 downto 32);
|
1803 |
|
|
end if;
|
1804 |
|
|
end if;
|
1805 |
|
|
fpu_regin.me <= fpmein;
|
1806 |
|
|
end if;
|
1807 |
|
|
|
1808 |
|
|
if (MULTIPLIER = m32x32) and (ex.mulinsn = '1') then
|
1809 |
|
|
aluresult := mulo.result(31 downto 0);
|
1810 |
|
|
end if;
|
1811 |
|
|
if MACEN then
|
1812 |
|
|
if ex.aluop = ALU_RDY then
|
1813 |
|
|
if rs1 = "10010" then
|
1814 |
|
|
if ((me.mulinsn and me.ctrl.inst(24)) = '1') then
|
1815 |
|
|
aluresult := mulo.result(31 downto 0);
|
1816 |
|
|
else aluresult := wr.asr18; end if;
|
1817 |
|
|
else
|
1818 |
|
|
if ((me.mulinsn and me.ctrl.inst(24)) = '1') then
|
1819 |
|
|
aluresult := mulo.result(63 downto 32);
|
1820 |
|
|
end if;
|
1821 |
|
|
end if;
|
1822 |
|
|
end if;
|
1823 |
|
|
end if;
|
1824 |
|
|
|
1825 |
|
|
ex.result <= aluresult;
|
1826 |
|
|
|
1827 |
|
|
-- generate Y
|
1828 |
|
|
|
1829 |
|
|
micc := icc;
|
1830 |
|
|
licc := icc;
|
1831 |
|
|
|
1832 |
|
|
nexty := y;
|
1833 |
|
|
if ex.mulstep = '1' then
|
1834 |
|
|
nexty := ymsb & y(31 downto 1);
|
1835 |
|
|
elsif (ex.mulinsn = '1') and (MULTIPLIER = iterative) then
|
1836 |
|
|
case ex.ctrl.cnt is
|
1837 |
|
|
when "00" => nexty := y;
|
1838 |
|
|
when "01" => nexty := ymsb & me.y(31 downto 1);
|
1839 |
|
|
when "10" =>
|
1840 |
|
|
aluresult := ymsb & me.y(31 downto 1);
|
1841 |
|
|
licc(3) := ymsb; licc(1 downto 0) := "00";
|
1842 |
|
|
if aluresult = zero32 then
|
1843 |
|
|
licc(2) := '1'; else licc(2) := '0';
|
1844 |
|
|
end if;
|
1845 |
|
|
nexty := me.y;
|
1846 |
|
|
when others => null;
|
1847 |
|
|
end case;
|
1848 |
|
|
elsif ((ex.rst_mey or ex.write_y) = '1') and (MULTIPLIER = iterative) then
|
1849 |
|
|
if ex.ctrl.cnt = "11" then nexty := addout;
|
1850 |
|
|
else nexty := logicout; end if;
|
1851 |
|
|
elsif ex.write_y = '1' then
|
1852 |
|
|
nexty := logicout;
|
1853 |
|
|
end if;
|
1854 |
|
|
|
1855 |
|
|
if (MULTIPLIER = iterative) then
|
1856 |
|
|
micc(3) := icc(3) and not ex.rst_mey;
|
1857 |
|
|
micc(1) := icc(1) and not ex.rst_mey;
|
1858 |
|
|
end if;
|
1859 |
|
|
|
1860 |
|
|
-- data address generation
|
1861 |
|
|
|
1862 |
|
|
eaddress := miscout;
|
1863 |
|
|
if ex.alusel = ALU_RES_ADD then
|
1864 |
|
|
addout(2) := addout(2) or force_a2; eaddress := addout;
|
1865 |
|
|
end if;
|
1866 |
|
|
|
1867 |
|
|
if CPEN and (op = LDST) and ((op3(5 downto 4) & op3(2)) = "111") and
|
1868 |
|
|
(ex.ctrl.cnt /= "00")
|
1869 |
|
|
then
|
1870 |
|
|
dci.edata <= cpo.data; -- store co-processor
|
1871 |
|
|
aluresult := cpo.data;
|
1872 |
|
|
elsif (FPIFTYPE = parallel) and (op = LDST) and
|
1873 |
|
|
((op3(5 downto 4) & op3(2)) = "101") and (ex.ctrl.cnt /= "00")
|
1874 |
|
|
then
|
1875 |
|
|
dci.edata <= fpo.data; -- store fpu co-processor
|
1876 |
|
|
aluresult := fpo.data;
|
1877 |
|
|
else
|
1878 |
|
|
dci.edata <= edata;
|
1879 |
|
|
aluresult(2) := aluresult(2) or force_a2;
|
1880 |
|
|
end if;
|
1881 |
|
|
|
1882 |
|
|
if (MULTIPLIER > iterative) and (MULTIPLIER /= m32x32) then
|
1883 |
|
|
write_reg := write_reg or mulo.ready;
|
1884 |
|
|
write_y := write_y or mulo.ready;
|
1885 |
|
|
write_icc := write_icc or (mulo.ready and op3(4));
|
1886 |
|
|
end if;
|
1887 |
|
|
if DIVIDER /= none then
|
1888 |
|
|
write_reg := write_reg or divo.ready;
|
1889 |
|
|
write_icc := write_icc or (divo.ready and op3(4));
|
1890 |
|
|
end if;
|
1891 |
|
|
|
1892 |
|
|
-- debug unit cache access
|
1893 |
|
|
if DEBUG_UNIT then
|
1894 |
|
|
if dsur.dmode = '1' then
|
1895 |
|
|
dcache_write := '0'; read := '1'; dsu_cache := '0';
|
1896 |
|
|
if (iui.debug.denable and iui.debug.daddr(20)) = '1' then
|
1897 |
|
|
enaddr := '1';
|
1898 |
|
|
asi(4 downto 0) := iui.debug.daddr(17) & "11" & iui.debug.daddr(19 downto 18);
|
1899 |
|
|
if M_EN and iui.debug.daddr(21) = '1' then
|
1900 |
|
|
-- ASI_ICTX "10101" 0x90300000-0x90340000
|
1901 |
|
|
-- ASI_DCTX "10100" 0x90380000-0x903c0000
|
1902 |
|
|
asi(4 downto 0) := "1010" & not (iui.debug.daddr(19));
|
1903 |
|
|
end if;
|
1904 |
|
|
dsu_cache := '1'; ld_size := LDWORD;
|
1905 |
|
|
if iui.debug.dwrite = '1' then
|
1906 |
|
|
dcache_write := '1'; read := '0';
|
1907 |
|
|
end if;
|
1908 |
|
|
if (dsur.dsuen and iui.debug.dwrite) = '1' then aluresult := iui.debug.ddata;
|
1909 |
|
|
else aluresult(21 downto 2) := iui.debug.daddr; end if;
|
1910 |
|
|
end if;
|
1911 |
|
|
end if;
|
1912 |
|
|
end if;
|
1913 |
|
|
|
1914 |
|
|
mein.y <= nexty;
|
1915 |
|
|
dciin.enaddr <= enaddr;
|
1916 |
|
|
dciin.read <= read;
|
1917 |
|
|
dciin.write <= dcache_write;
|
1918 |
|
|
dciin.asi <= asi;
|
1919 |
|
|
dciin.lock <= lock;
|
1920 |
|
|
dci.eenaddr <= enaddr;
|
1921 |
|
|
dci.eaddress <= eaddress;
|
1922 |
|
|
dci.dsuen <= dsur.dsuen;
|
1923 |
|
|
dci.esu <= su;
|
1924 |
|
|
|
1925 |
|
|
fecomb.jump <= jump;
|
1926 |
|
|
|
1927 |
|
|
ex.micc <= micc;
|
1928 |
|
|
mein.inull <= inull;
|
1929 |
|
|
mein.icc <= licc;
|
1930 |
|
|
mein.memory_load <= memory_load;
|
1931 |
|
|
mein.ld_size <= ld_size;
|
1932 |
|
|
mein.signed <= signed;
|
1933 |
|
|
mein.addr_misal <= addr_misal;
|
1934 |
|
|
|
1935 |
|
|
mein.result <= aluresult;
|
1936 |
|
|
mein.write_reg <= write_reg;
|
1937 |
|
|
mein.write_icc <= write_icc;
|
1938 |
|
|
mein.write_y <= write_y;
|
1939 |
|
|
mein.ctrl <= ctrl;
|
1940 |
|
|
mein.su <= su;
|
1941 |
|
|
|
1942 |
|
|
end process;
|
1943 |
|
|
|
1944 |
|
|
-------------------------------------------------------------------------------
|
1945 |
|
|
-- memory stage
|
1946 |
|
|
-------------------------------------------------------------------------------
|
1947 |
|
|
|
1948 |
|
|
|
1949 |
|
|
memory_stage : process(ex, me, wr, sregs, sregsin, iui, dco, fpuo, fpu_reg,
|
1950 |
|
|
cpo, fpo, rst, holdn, mulo, divo, tr, dsur)
|
1951 |
|
|
|
1952 |
|
|
variable op : std_logic_vector(1 downto 0);
|
1953 |
|
|
variable op2 : std_logic_vector(2 downto 0);
|
1954 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
1955 |
|
|
variable rd,rs1: std_logic_vector(4 downto 0);
|
1956 |
|
|
variable ctrl : pipeline_control_type;
|
1957 |
|
|
variable nullify : std_logic;
|
1958 |
|
|
variable iflush : std_logic;
|
1959 |
|
|
variable ipend : std_logic;
|
1960 |
|
|
variable write_cwp : std_logic;
|
1961 |
|
|
variable cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
1962 |
|
|
variable cwpx : std_logic_vector(5 downto NWINLOG2);
|
1963 |
|
|
variable result : std_logic_vector(31 downto 0);
|
1964 |
|
|
variable write_reg : std_logic;
|
1965 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
1966 |
|
|
variable werr : std_logic;
|
1967 |
|
|
variable fpexc : std_logic;
|
1968 |
|
|
variable opf : std_logic_vector(8 downto 0);
|
1969 |
|
|
variable fpwrin : fpu_ctrl2_type;
|
1970 |
|
|
variable jmpl_rett : std_logic;
|
1971 |
|
|
variable pil : std_logic_vector(3 downto 0);
|
1972 |
|
|
variable irqen : std_logic;
|
1973 |
|
|
variable dsutrap : std_logic;
|
1974 |
|
|
variable y, asr18 : std_logic_vector(31 downto 0);
|
1975 |
|
|
variable trv : watchpoint_registers;
|
1976 |
|
|
variable wpi : integer range 0 to 3; -- watchpoint index
|
1977 |
|
|
|
1978 |
|
|
begin
|
1979 |
|
|
|
1980 |
|
|
-- common initialisation
|
1981 |
|
|
|
1982 |
|
|
op := me.ctrl.inst(31 downto 30);
|
1983 |
|
|
op2 := me.ctrl.inst(24 downto 22);
|
1984 |
|
|
op3 := me.ctrl.inst(24 downto 19);
|
1985 |
|
|
opf := me.ctrl.inst(13 downto 5);
|
1986 |
|
|
rd := me.ctrl.inst(29 downto 25);
|
1987 |
|
|
rs1 := me.ctrl.inst(18 downto 14);
|
1988 |
|
|
ctrl := me.ctrl;
|
1989 |
|
|
ctrl.annul := ctrl.annul or wr.annul_all;
|
1990 |
|
|
nullify := ctrl.annul;
|
1991 |
|
|
iflush := '0';
|
1992 |
|
|
cwp := me.cwp; write_cwp := me.write_cwp;
|
1993 |
|
|
result := me.result;
|
1994 |
|
|
write_reg := me.write_reg;
|
1995 |
|
|
icc := me.icc;
|
1996 |
|
|
fpwrin := fpu_reg.me;
|
1997 |
|
|
jmpl_rett := '0';
|
1998 |
|
|
werr := (me.werr or dco.werr) and rst;
|
1999 |
|
|
y := me.y; asr18 := wr.asr18;
|
2000 |
|
|
trv := tr; wpi := 0; dsutrap := '0';
|
2001 |
|
|
cwpx := me.result(5 downto NWINLOG2); cwpx(5) := '0';
|
2002 |
|
|
|
2003 |
|
|
-- external interrupt handling
|
2004 |
|
|
|
2005 |
|
|
-- disable interrupts for one clock after a WRPSR, since a
|
2006 |
|
|
-- WRPSR should affect ET and PIL without delay (SPARC V8 ISP, p.183)
|
2007 |
|
|
irqen := me.irqen and sregs.et; pil := sregs.pil;
|
2008 |
|
|
if (iui.irl = "1111") or (iui.irl > pil) then ipend := irqen;
|
2009 |
|
|
else ipend := '0'; end if;
|
2010 |
|
|
if (ctrl.annul = '0') and (ctrl.pv = '1') then
|
2011 |
|
|
if (werr and holdn) = '1' then
|
2012 |
|
|
ctrl.trap := '1'; ctrl.tt := DSEX_TT; werr := '0';
|
2013 |
|
|
if op = LDST then nullify := '1'; end if;
|
2014 |
|
|
elsif (irqen and not me.ctrl.trap) = '1' then
|
2015 |
|
|
|
2016 |
|
|
if ipend = '1' then
|
2017 |
|
|
|
2018 |
|
|
ctrl.trap := '1'; ctrl.tt := "01" & iui.irl;
|
2019 |
|
|
if op = LDST then nullify := '1'; end if;
|
2020 |
|
|
end if;
|
2021 |
|
|
end if;
|
2022 |
|
|
end if;
|
2023 |
|
|
|
2024 |
|
|
iuo.ipend <= me.ipend;
|
2025 |
|
|
|
2026 |
|
|
-- some trap generation
|
2027 |
|
|
|
2028 |
|
|
irqen := '1';
|
2029 |
|
|
if ((ctrl.annul or ctrl.trap) /= '1') then
|
2030 |
|
|
case op is
|
2031 |
|
|
when FMT2 =>
|
2032 |
|
|
case op2 is
|
2033 |
|
|
when FBFCC =>
|
2034 |
|
|
if (FPIFTYPE = parallel) and (fpo.exc = '1')
|
2035 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if;
|
2036 |
|
|
when CBCCC =>
|
2037 |
|
|
if CPEN and (cpo.exc = '1')
|
2038 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if;
|
2039 |
|
|
when others => null;
|
2040 |
|
|
end case;
|
2041 |
|
|
when FMT3 =>
|
2042 |
|
|
case op3 is
|
2043 |
|
|
when WRY =>
|
2044 |
|
|
if MACEN and (rd = "10010") then asr18 := me.result; end if;
|
2045 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
2046 |
|
|
if rd(4 downto 1) = std_logic_vector(conv_unsigned(12+i, 4)) then
|
2047 |
|
|
if rd(0) = '0' then
|
2048 |
|
|
trv(i).addr := me.result(31 downto 2);
|
2049 |
|
|
trv(i).exec := me.result(0);
|
2050 |
|
|
else
|
2051 |
|
|
trv(i).mask := me.result(31 downto 2);
|
2052 |
|
|
trv(i).load := me.result(1); trv(i).store := me.result(0);
|
2053 |
|
|
end if;
|
2054 |
|
|
end if;
|
2055 |
|
|
end loop;
|
2056 |
|
|
when WRPSR =>
|
2057 |
|
|
if (orv(cwpx) = '1') then
|
2058 |
|
|
ctrl.trap := '1'; ctrl.tt := IINST_TT;
|
2059 |
|
|
else cwp := me.result(NWINLOG2-1 downto 0); write_cwp := '1'; end if;
|
2060 |
|
|
when UDIV | SDIV =>
|
2061 |
|
|
if (DIVIDER /= none) then
|
2062 |
|
|
if icc(2) = '1' then ctrl.trap := '1'; ctrl.tt := DIV_TT; end if;
|
2063 |
|
|
end if;
|
2064 |
|
|
when UDIVCC | SDIVCC =>
|
2065 |
|
|
if (DIVIDER /= none) then
|
2066 |
|
|
if icc(2) = '1' then ctrl.trap := '1'; ctrl.tt := DIV_TT; end if;
|
2067 |
|
|
end if;
|
2068 |
|
|
when JMPL | RETT =>
|
2069 |
|
|
-- jmpl_rett := '1';
|
2070 |
|
|
if me.addr_misal = '1' then
|
2071 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT;
|
2072 |
|
|
end if;
|
2073 |
|
|
when TADDCCTV | TSUBCCTV =>
|
2074 |
|
|
if me.icc(1) = '1' then ctrl.trap := '1'; ctrl.tt := TAG_TT; end if;
|
2075 |
|
|
when FLUSH => iflush := '1';
|
2076 |
|
|
when FPOP1 | FPOP2 =>
|
2077 |
|
|
if (FPIFTYPE = parallel) and (fpo.exc = '1')
|
2078 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; end if;
|
2079 |
|
|
when CPOP1 | CPOP2 =>
|
2080 |
|
|
if CPEN and (cpo.exc = '1')
|
2081 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; end if;
|
2082 |
|
|
when others => null;
|
2083 |
|
|
end case;
|
2084 |
|
|
when LDST =>
|
2085 |
|
|
if ctrl.cnt = "00" then
|
2086 |
|
|
case op3 is
|
2087 |
|
|
when LDDF | STDF | STDFQ =>
|
2088 |
|
|
if FPEN then
|
2089 |
|
|
if FPEN and (me.result(2 downto 0) /= "000") then
|
2090 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2091 |
|
|
elsif ((FPIFTYPE = parallel) and ((fpo.exc and ctrl.pv) = '1'))
|
2092 |
|
|
or ((FPIFTYPE = serial) and (op3 = STDFQ) and (ctrl.pv = '1'))
|
2093 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if;
|
2094 |
|
|
end if;
|
2095 |
|
|
when LDDC | STDC | STDCQ =>
|
2096 |
|
|
if CPEN and (me.result(2 downto 0) /= "000") then
|
2097 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2098 |
|
|
elsif CPEN and ((cpo.exc and ctrl.pv) = '1')
|
2099 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if;
|
2100 |
|
|
when LDD | ISTD | LDDA | STDA =>
|
2101 |
|
|
if me.result(2 downto 0) /= "000" then
|
2102 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2103 |
|
|
end if;
|
2104 |
|
|
when LDF | LDFSR | STFSR | STF =>
|
2105 |
|
|
if FPEN and (me.result(1 downto 0) /= "00") then
|
2106 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2107 |
|
|
elsif (FPIFTYPE = parallel) and ((fpo.exc and ctrl.pv) = '1')
|
2108 |
|
|
then ctrl.trap := '1'; ctrl.tt := FPEXC_TT; nullify := '1'; end if;
|
2109 |
|
|
when LDC | LDCSR | STCSR | STC =>
|
2110 |
|
|
if CPEN and (me.result(1 downto 0) /= "00") then
|
2111 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2112 |
|
|
elsif CPEN and ((cpo.exc and ctrl.pv) = '1')
|
2113 |
|
|
then ctrl.trap := '1'; ctrl.tt := CPEXC_TT; nullify := '1'; end if;
|
2114 |
|
|
when LD | LDA | ST | STA | SWAP | SWAPA =>
|
2115 |
|
|
if me.result(1 downto 0) /= "00" then
|
2116 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2117 |
|
|
end if;
|
2118 |
|
|
when LDUH | LDUHA | LDSH | LDSHA | STH | STHA =>
|
2119 |
|
|
if me.result(0) /= '0' then
|
2120 |
|
|
ctrl.trap := '1'; ctrl.tt := UNALA_TT; nullify := '1';
|
2121 |
|
|
end if;
|
2122 |
|
|
when others => null;
|
2123 |
|
|
end case;
|
2124 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
2125 |
|
|
if ((((tr(i).load and not op3(2)) or (tr(i).store and op3(2))) = '1') and
|
2126 |
|
|
(((tr(i).addr xor me.result(31 downto 2)) and tr(i).mask) = Zero32(31 downto 2)))
|
2127 |
|
|
or (DEBUG_UNIT and ((iui.debug.dsuen and iui.debug.bwatch and iui.debug.dbreak) = '1'))
|
2128 |
|
|
then
|
2129 |
|
|
ctrl.trap := '1'; ctrl.tt := WATCH_TT; nullify := '1';
|
2130 |
|
|
end if;
|
2131 |
|
|
end loop;
|
2132 |
|
|
end if;
|
2133 |
|
|
when others => null;
|
2134 |
|
|
end case;
|
2135 |
|
|
end if;
|
2136 |
|
|
|
2137 |
|
|
-- get result from multiplier and divider
|
2138 |
|
|
|
2139 |
|
|
case op is
|
2140 |
|
|
when FMT3 =>
|
2141 |
|
|
case op3 is
|
2142 |
|
|
when JMPL | RETT =>
|
2143 |
|
|
jmpl_rett := '1';
|
2144 |
|
|
when UMUL | SMUL =>
|
2145 |
|
|
if (MULTIPLIER > iterative) then
|
2146 |
|
|
if (MULTIPLIER /= m32x32) then
|
2147 |
|
|
result := mulo.result(31 downto 0);
|
2148 |
|
|
end if;
|
2149 |
|
|
y := mulo.result(63 downto 32);
|
2150 |
|
|
end if;
|
2151 |
|
|
when UMULCC | SMULCC =>
|
2152 |
|
|
if (MULTIPLIER > iterative) then
|
2153 |
|
|
if (MULTIPLIER /= m32x32) then
|
2154 |
|
|
result := mulo.result(31 downto 0); icc := mulo.icc;
|
2155 |
|
|
else
|
2156 |
|
|
icc := me.result(31) & "000";
|
2157 |
|
|
if me.result = Zero32 then icc(2) := '1'; end if;
|
2158 |
|
|
end if;
|
2159 |
|
|
y := mulo.result(63 downto 32);
|
2160 |
|
|
end if;
|
2161 |
|
|
when UMAC | SMAC =>
|
2162 |
|
|
if MACEN then
|
2163 |
|
|
result := mulo.result(31 downto 0);
|
2164 |
|
|
asr18 := mulo.result(31 downto 0);
|
2165 |
|
|
y := mulo.result(63 downto 32);
|
2166 |
|
|
end if;
|
2167 |
|
|
when UDIV | SDIV =>
|
2168 |
|
|
if (DIVIDER /= none) then
|
2169 |
|
|
result := divo.result(31 downto 0);
|
2170 |
|
|
end if;
|
2171 |
|
|
when UDIVCC | SDIVCC =>
|
2172 |
|
|
if (DIVIDER /= none) then
|
2173 |
|
|
result := divo.result(31 downto 0); icc := divo.icc;
|
2174 |
|
|
end if;
|
2175 |
|
|
when WRPSR => irqen := '0';
|
2176 |
|
|
when others => null;
|
2177 |
|
|
end case;
|
2178 |
|
|
when others => null;
|
2179 |
|
|
end case;
|
2180 |
|
|
|
2181 |
|
|
mein.irqen <= irqen;
|
2182 |
|
|
|
2183 |
|
|
-- FPU MSW data store
|
2184 |
|
|
|
2185 |
|
|
fpexc := '0';
|
2186 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
2187 |
|
|
if (xorv(fpu_reg.me.fpop) = '1') then
|
2188 |
|
|
if (me.ctrl.cnt = "00") and
|
2189 |
|
|
((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1')
|
2190 |
|
|
then
|
2191 |
|
|
fpwrin.fcc := fpuo.ConditionCodes;
|
2192 |
|
|
fpwrin.cexc := fpuo.Excep(4 downto 0);
|
2193 |
|
|
end if;
|
2194 |
|
|
if ((ctrl.annul or ctrl.trap) /= '1') then
|
2195 |
|
|
if ((fpu_reg.me.dsz and me.write_reg) = '1') and
|
2196 |
|
|
(me.ctrl.cnt = "00")
|
2197 |
|
|
then
|
2198 |
|
|
result := fpuo.SignResult & fpuo.ExpResult &
|
2199 |
|
|
fpuo.FracResult(54 downto 35);
|
2200 |
|
|
end if;
|
2201 |
|
|
if ((fpu_reg.fsr.tem and fpwrin.cexc) /= "00000" ) then
|
2202 |
|
|
fpexc := '1';
|
2203 |
|
|
if ((fpu_reg.me.dsz or me.ctrl.inst(6)) = '1') and
|
2204 |
|
|
(me.ctrl.cnt = "00")
|
2205 |
|
|
then fpexc := '0'; write_reg := '0';
|
2206 |
|
|
else ctrl.trap := '1'; end if;
|
2207 |
|
|
end if;
|
2208 |
|
|
end if;
|
2209 |
|
|
end if;
|
2210 |
|
|
fpu_regin.fpexc <= fpexc;
|
2211 |
|
|
fpu_regin.wr <= fpwrin;
|
2212 |
|
|
end if;
|
2213 |
|
|
|
2214 |
|
|
mein.bpresult <= result; -- FPU bypass
|
2215 |
|
|
|
2216 |
|
|
-- load data from cache
|
2217 |
|
|
|
2218 |
|
|
if (me.memory_load or not dco.mds) = '1' then result := dco.data; end if;
|
2219 |
|
|
|
2220 |
|
|
-- Y register
|
2221 |
|
|
|
2222 |
|
|
if (me.write_y = '0') or (me.ctrl.annul = '1') then y := wr.y; end if;
|
2223 |
|
|
me.my <= y; -- fast Y feedback
|
2224 |
|
|
if ((ctrl.annul or ctrl.trap) = '1') then y := wr.y; end if;
|
2225 |
|
|
|
2226 |
|
|
if MACEN and ((ctrl.annul or ctrl.trap) = '1') then
|
2227 |
|
|
asr18 := wr.asr18;
|
2228 |
|
|
end if;
|
2229 |
|
|
|
2230 |
|
|
if DEBUG_UNIT then
|
2231 |
|
|
if (iui.debug.dwrite and iui.debug.denable) = '1' then
|
2232 |
|
|
if iui.debug.daddr(20 downto 19) = "01" then
|
2233 |
|
|
if iui.debug.daddr(7 downto 2) = "000000" then
|
2234 |
|
|
y := iui.debug.ddata;
|
2235 |
|
|
end if;
|
2236 |
|
|
end if;
|
2237 |
|
|
end if;
|
2238 |
|
|
end if;
|
2239 |
|
|
|
2240 |
|
|
wrin.y <= y;
|
2241 |
|
|
|
2242 |
|
|
|
2243 |
|
|
|
2244 |
|
|
-- debug unit ASR write access
|
2245 |
|
|
|
2246 |
|
|
if DEBUG_UNIT and
|
2247 |
|
|
((dsur.dmode and iui.debug.dwrite and iui.debug.denable) = '1') and
|
2248 |
|
|
(iui.debug.daddr(20 downto 19) = "01")
|
2249 |
|
|
then
|
2250 |
|
|
case iui.debug.daddr(7 downto 2) is
|
2251 |
|
|
when "010010" => -- %ASR18
|
2252 |
|
|
asr18 := iui.debug.ddata;
|
2253 |
|
|
when others => -- %ASR24 - 31
|
2254 |
|
|
if (WATCHPOINTS > 0) and (iui.debug.daddr(7 downto 5) = "011") then
|
2255 |
|
|
wpi := conv_integer(unsigned(iui.debug.daddr(4 downto 3)));
|
2256 |
|
|
if iui.debug.daddr(2) = '0' then
|
2257 |
|
|
trv(wpi).addr := iui.debug.ddata(31 downto 2);
|
2258 |
|
|
trv(wpi).exec := iui.debug.ddata(0);
|
2259 |
|
|
else
|
2260 |
|
|
trv(wpi).mask := iui.debug.ddata(31 downto 2);
|
2261 |
|
|
trv(wpi).load := iui.debug.ddata(1);
|
2262 |
|
|
trv(wpi).store := iui.debug.ddata(0);
|
2263 |
|
|
end if;
|
2264 |
|
|
end if;
|
2265 |
|
|
end case;
|
2266 |
|
|
end if;
|
2267 |
|
|
|
2268 |
|
|
-- debug unit trap generation + diagnostic write data
|
2269 |
|
|
if DEBUG_UNIT and (iui.debug.dsuen = '1') and
|
2270 |
|
|
(ctrl.annul = '0') and (ctrl.pv = '1') and (ctrl.trap = '1') and
|
2271 |
|
|
((iui.debug.btrapa = '1') or
|
2272 |
|
|
((iui.debug.btrape = '1') and not ((ctrl.tt = PRIV_TT) or
|
2273 |
|
|
(ctrl.tt = FPDIS_TT) or (ctrl.tt = WINOF_TT) or
|
2274 |
|
|
(ctrl.tt = WINUF_TT) or (ctrl.tt(5 downto 4) = "01") or
|
2275 |
|
|
(ctrl.tt = TICC_TT))) or
|
2276 |
|
|
((iui.debug.bwatch = '1') and (ctrl.tt = WATCH_TT)) or
|
2277 |
|
|
((iui.debug.bsoft = '1') and (ctrl.tt = TICC_TT) and
|
2278 |
|
|
(me.result(6 downto 0) = "0000001")))
|
2279 |
|
|
then dsutrap := '1'; end if;
|
2280 |
|
|
if DEBUG_UNIT and (dsur.dmode = '1') then result := iui.debug.ddata; end if;
|
2281 |
|
|
|
2282 |
|
|
if rst = '0' then
|
2283 |
|
|
for i in 0 to WATCHPOINTS-1 loop
|
2284 |
|
|
trv(i).exec := '0'; trv(i).load := '0'; trv(i).store := '0';
|
2285 |
|
|
end loop;
|
2286 |
|
|
end if;
|
2287 |
|
|
|
2288 |
|
|
mein.werr <= werr;
|
2289 |
|
|
mein.ipend <= ipend;
|
2290 |
|
|
wrin.result <= result;
|
2291 |
|
|
wrin.icc <= icc;
|
2292 |
|
|
me.jmpl_rett <= jmpl_rett;
|
2293 |
|
|
|
2294 |
|
|
wrin.cwp <= cwp; wrin.write_cwp <= write_cwp;
|
2295 |
|
|
wrin.ctrl <= ctrl;
|
2296 |
|
|
wrin.write_reg <= write_reg;
|
2297 |
|
|
wrin.asr18 <= asr18;
|
2298 |
|
|
ici.flush <= iflush;
|
2299 |
|
|
dci.flush <= iflush;
|
2300 |
|
|
dci.nullify <= nullify;
|
2301 |
|
|
dci.maddress <= me.result;
|
2302 |
|
|
dci.msu <= me.su;
|
2303 |
|
|
trin <= trv;
|
2304 |
|
|
wrin.dsutrap <= dsutrap;
|
2305 |
|
|
|
2306 |
|
|
end process;
|
2307 |
|
|
|
2308 |
|
|
-------------------------------------------------------------------------------
|
2309 |
|
|
-- write stage
|
2310 |
|
|
-------------------------------------------------------------------------------
|
2311 |
|
|
|
2312 |
|
|
|
2313 |
|
|
write_stage : process(rst, holdn, wr, sregs, fe, de, ex, me, fpu_reg, iui, dsur)
|
2314 |
|
|
|
2315 |
|
|
variable op : std_logic_vector(1 downto 0);
|
2316 |
|
|
variable op3 : std_logic_vector(5 downto 0);
|
2317 |
|
|
variable rd : std_logic_vector(4 downto 0);
|
2318 |
|
|
variable rd_address : std_logic_vector(RABITS-1 downto 0);
|
2319 |
|
|
variable write_reg : std_logic;
|
2320 |
|
|
variable annul_all : std_logic;
|
2321 |
|
|
variable cwp : std_logic_vector(NWINLOG2-1 downto 0);
|
2322 |
|
|
variable icc : std_logic_vector(3 downto 0);
|
2323 |
|
|
variable tt : std_logic_vector(7 downto 0);
|
2324 |
|
|
variable tba : std_logic_vector(19 downto 0);
|
2325 |
|
|
variable wim : std_logic_vector(NWINDOWS-1 downto 0);
|
2326 |
|
|
variable pil : std_logic_vector(3 downto 0);
|
2327 |
|
|
variable ec, ef, ps, s, et : std_logic;
|
2328 |
|
|
variable exception : std_logic;
|
2329 |
|
|
variable trapping : std_logic;
|
2330 |
|
|
variable save_pc : std_logic;
|
2331 |
|
|
variable error : std_logic;
|
2332 |
|
|
variable intack : std_logic;
|
2333 |
|
|
variable tpcsel : std_logic_vector(1 downto 0);
|
2334 |
|
|
variable npc : std_logic_vector(31 downto PCLOW);
|
2335 |
|
|
variable trap_address : std_logic_vector(31 downto PCLOW); -- trap address
|
2336 |
|
|
variable wrdata : std_logic_vector(RDBITS-1 downto 0);
|
2337 |
|
|
variable newtt, vectt : std_logic_vector(7 downto 0);
|
2338 |
|
|
variable vfsr : fsr_type;
|
2339 |
|
|
variable write_icc : std_logic;
|
2340 |
|
|
variable cpexack : std_logic;
|
2341 |
|
|
variable fpexack : std_logic;
|
2342 |
|
|
variable dsutrap : std_logic;
|
2343 |
|
|
variable vdsu : dsu_registers;
|
2344 |
|
|
variable fp_dwrite, fp_dwrite_fsr : std_logic;
|
2345 |
|
|
|
2346 |
|
|
|
2347 |
|
|
begin
|
2348 |
|
|
|
2349 |
|
|
-- common initialisation
|
2350 |
|
|
|
2351 |
|
|
op := wr.ctrl.inst(31 downto 30);
|
2352 |
|
|
op3 := wr.ctrl.inst(24 downto 19);
|
2353 |
|
|
rd := wr.ctrl.inst(29 downto 25);
|
2354 |
|
|
|
2355 |
|
|
rd_address := wr.ctrl.rd; write_reg := '0'; write_icc := wr.write_icc;
|
2356 |
|
|
|
2357 |
|
|
annul_all := '0'; exception := '0';
|
2358 |
|
|
trapping := wr.trapping; tpcsel := "00";
|
2359 |
|
|
save_pc := '0'; error := wr.error; intack := '0';
|
2360 |
|
|
newtt := (others => '-'); vectt := (others => '-'); vdsu := dsur;
|
2361 |
|
|
vdsu.dsuen := iui.debug.denable; cpexack := '0'; fpexack := '0';
|
2362 |
|
|
vdsu.dmode2 := dsur.dmode2 and wr.ctrl.annul; dsutrap := '0';
|
2363 |
|
|
vfsr := fpu_reg.fsr;
|
2364 |
|
|
fp_dwrite := '0'; fp_dwrite_fsr := '0';
|
2365 |
|
|
|
2366 |
|
|
|
2367 |
|
|
-- special registers write handling
|
2368 |
|
|
|
2369 |
|
|
icc := sregs.icc; cwp := sregs.cwp; ef := sregs.ef; ec := sregs.ec;
|
2370 |
|
|
pil := sregs.pil; s := sregs.s; ps := sregs.ps; et := sregs.et;
|
2371 |
|
|
tba := sregs.tba; tt := sregs.tt; wim := sregs.wim;
|
2372 |
|
|
|
2373 |
|
|
if (wr.ctrl.annul or wr.ctrl.trap) /= '1' then
|
2374 |
|
|
if wr.write_cwp = '1' then
|
2375 |
|
|
cwp := wr.cwp;
|
2376 |
|
|
end if;
|
2377 |
|
|
write_reg := wr.write_reg;
|
2378 |
|
|
case op is
|
2379 |
|
|
when FMT3 =>
|
2380 |
|
|
case op3 is
|
2381 |
|
|
when WRY =>
|
2382 |
|
|
|
2383 |
|
|
when WRPSR =>
|
2384 |
|
|
cwp := wr.result(NWINLOG2-1 downto 0);
|
2385 |
|
|
icc := wr.result(23 downto 20);
|
2386 |
|
|
ec := wr.result(13);
|
2387 |
|
|
ef := wr.result(12);
|
2388 |
|
|
pil := wr.result(11 downto 8);
|
2389 |
|
|
s := wr.result(7);
|
2390 |
|
|
ps := wr.result(6);
|
2391 |
|
|
et := wr.result(5);
|
2392 |
|
|
when WRWIM =>
|
2393 |
|
|
wim := wr.result(NWINDOWS-1 downto 0);
|
2394 |
|
|
when WRTBR =>
|
2395 |
|
|
tba := wr.result(31 downto 12);
|
2396 |
|
|
when RETT =>
|
2397 |
|
|
s := ps;
|
2398 |
|
|
et := '1';
|
2399 |
|
|
|
2400 |
|
|
when FPOP1 | FPOP2 =>
|
2401 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
2402 |
|
|
|
2403 |
|
|
if (wr.write_reg = '1') and ((wr.ctrl.cnt = "00") or
|
2404 |
|
|
((wr.ctrl.cnt = "01") and (fpu_reg.wr.dsz = '0')))
|
2405 |
|
|
then
|
2406 |
|
|
vfsr.ftt := (others => '0');
|
2407 |
|
|
vfsr.cexc := fpu_reg.wr.cexc;
|
2408 |
|
|
vfsr.aexc := fpu_reg.wr.cexc or fpu_reg.fsr.aexc;
|
2409 |
|
|
end if;
|
2410 |
|
|
if (op3 = FPOP2) and
|
2411 |
|
|
not ((wr.ctrl.inst(6) = '1') and (wr.ctrl.cnt = "00")) then
|
2412 |
|
|
vfsr.fcc := fpu_reg.wr.fcc;
|
2413 |
|
|
vfsr.ftt := (others => '0');
|
2414 |
|
|
vfsr.cexc := fpu_reg.wr.cexc;
|
2415 |
|
|
vfsr.aexc := fpu_reg.wr.cexc or fpu_reg.fsr.aexc;
|
2416 |
|
|
end if;
|
2417 |
|
|
|
2418 |
|
|
end if;
|
2419 |
|
|
when others => null;
|
2420 |
|
|
end case;
|
2421 |
|
|
when LDST =>
|
2422 |
|
|
case op3 is
|
2423 |
|
|
when STFSR =>
|
2424 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
2425 |
|
|
vfsr.ftt := (others => '0');
|
2426 |
|
|
end if;
|
2427 |
|
|
when LDFSR =>
|
2428 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
2429 |
|
|
vfsr.cexc := wr.result(4 downto 0);
|
2430 |
|
|
vfsr.aexc := wr.result(9 downto 5);
|
2431 |
|
|
vfsr.fcc := wr.result(11 downto 10);
|
2432 |
|
|
vfsr.tem := wr.result(27 downto 23);
|
2433 |
|
|
vfsr.rd := wr.result(31 downto 30);
|
2434 |
|
|
end if;
|
2435 |
|
|
|
2436 |
|
|
when others => null;
|
2437 |
|
|
end case;
|
2438 |
|
|
when others => null;
|
2439 |
|
|
end case;
|
2440 |
|
|
if write_icc = '1' then icc := wr.icc; end if;
|
2441 |
|
|
end if;
|
2442 |
|
|
|
2443 |
|
|
-- trap handling
|
2444 |
|
|
|
2445 |
|
|
-- nPC selection
|
2446 |
|
|
if me.ctrl.pv = '1' then tpcsel := "00";
|
2447 |
|
|
elsif ex.ctrl.pv = '1' then tpcsel := "01";
|
2448 |
|
|
elsif de.pv = '1' then tpcsel := "10";
|
2449 |
|
|
else tpcsel := "11"; end if;
|
2450 |
|
|
case wr.tpcsel is
|
2451 |
|
|
when "00" => npc := wr.ctrl.pc(31 downto PCLOW);
|
2452 |
|
|
when "01" => npc := me.ctrl.pc(31 downto PCLOW);
|
2453 |
|
|
when "10" => npc := ex.ctrl.pc(31 downto PCLOW);
|
2454 |
|
|
when others => npc := de.pc(31 downto PCLOW);
|
2455 |
|
|
end case;
|
2456 |
|
|
|
2457 |
|
|
-- standard trap handling
|
2458 |
|
|
if DEBUG_UNIT and
|
2459 |
|
|
((wr.mexc and (iui.debug.btrape or iui.debug.btrapa)) = '1')
|
2460 |
|
|
then dsutrap := '1'; end if;
|
2461 |
|
|
if wr.mexc = '1' then newtt := "00" & DAEX_TT;
|
2462 |
|
|
elsif ((FPIFTYPE = serial) and FPEN) and (fpu_reg.fpexc = '1') then
|
2463 |
|
|
newtt := "00" & FPEXC_TT; vfsr.ftt := FPIEEE_ERR;
|
2464 |
|
|
elsif ((FPIFTYPE = serial) and FPEN) and (wr.ctrl.tt = FPEXC_TT) then
|
2465 |
|
|
newtt := "00" & FPEXC_TT; vfsr.ftt := FPSEQ_ERR;
|
2466 |
|
|
elsif wr.ctrl.tt = TICC_TT then newtt := '1' & wr.result(6 downto 0);
|
2467 |
|
|
else newtt := "00" & wr.ctrl.tt; end if;
|
2468 |
|
|
|
2469 |
|
|
if ((wr.ctrl.trap and not wr.ctrl.annul) = '1')
|
2470 |
|
|
or ((wr.mexc or trapping) = '1')
|
2471 |
|
|
then
|
2472 |
|
|
|
2473 |
|
|
vdsu.pc := wr.ctrl.pc;
|
2474 |
|
|
if DEBUG_UNIT and
|
2475 |
|
|
(iui.debug.dsuen = '1') and ((wr.ctrl.annul or dsur.dmode) = '0') and
|
2476 |
|
|
(((wr.dsutrap or dsutrap) = '1') or ((iui.debug.berror and not sregs.et) = '1'))
|
2477 |
|
|
then
|
2478 |
|
|
annul_all := '1'; vdsu.tt := newtt; vdsu.dmode := '1';
|
2479 |
|
|
write_reg := '0';
|
2480 |
|
|
if (sregs.et = '0') and not
|
2481 |
|
|
(((iui.debug.dbreak = '1') and (newtt = ("00" & WATCH_TT))) or
|
2482 |
|
|
((iui.debug.bsoft = '1') and (newtt = ("10000001"))))
|
2483 |
|
|
then vdsu.error := '1'; else vdsu.error := '0'; end if;
|
2484 |
|
|
elsif trapping = '0' then -- first trap cycle
|
2485 |
|
|
annul_all := '1'; trapping := '1'; ps := s; s := '1';
|
2486 |
|
|
exception := '1'; et := '0';
|
2487 |
|
|
if sregs.et = '0' then
|
2488 |
|
|
if not NOHALT then error := '1'; end if;
|
2489 |
|
|
if ((op = FMT3) and (op3 = RETT)) then tt := newtt; end if;
|
2490 |
|
|
vectt := (others => '0');
|
2491 |
|
|
else
|
2492 |
|
|
write_reg := '1'; save_pc := '1'; tt := newtt; vectt := newtt;
|
2493 |
|
|
end if;
|
2494 |
|
|
if CPEN and (tt = ("00" & CPEXC_TT)) then cpexack := '1'; end if;
|
2495 |
|
|
if (FPIFTYPE = parallel) and (tt = ("00" & FPEXC_TT)) then fpexack := '1'; end if;
|
2496 |
|
|
-- pragma translate_off
|
2497 |
|
|
if not is_x(cwp) then
|
2498 |
|
|
-- pragma translate_on
|
2499 |
|
|
rd_address := (others => '0');
|
2500 |
|
|
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0001";
|
2501 |
|
|
-- pragma translate_off
|
2502 |
|
|
end if;
|
2503 |
|
|
-- pragma translate_on
|
2504 |
|
|
|
2505 |
|
|
elsif trapping = '1' then -- second trap cycle
|
2506 |
|
|
if error = '1' then
|
2507 |
|
|
annul_all := '1'; trapping := '1';
|
2508 |
|
|
if DEBUG_UNIT and (iui.debug.dbreak = '1') then
|
2509 |
|
|
vdsu.dmode := '1';
|
2510 |
|
|
end if;
|
2511 |
|
|
else
|
2512 |
|
|
trapping := '0';
|
2513 |
|
|
if sregs.tt(5 downto 4) = "01" then intack := '1'; end if;
|
2514 |
|
|
write_reg := '1'; save_pc := '1';
|
2515 |
|
|
-- pragma translate_off
|
2516 |
|
|
if not is_x(cwp) then
|
2517 |
|
|
-- pragma translate_on
|
2518 |
|
|
rd_address := (others => '0');
|
2519 |
|
|
rd_address (NWINLOG2 + 3 downto 0) := cwp & "0010";
|
2520 |
|
|
-- pragma translate_off
|
2521 |
|
|
end if;
|
2522 |
|
|
-- pragma translate_on
|
2523 |
|
|
-- pragma translate_off
|
2524 |
|
|
if not is_x(cwp) then
|
2525 |
|
|
-- pragma translate_on
|
2526 |
|
|
if (not CWPOPT) and (cwp = CWPMIN) then cwp := CWPMAX;
|
2527 |
|
|
else cwp := cwp - 1; end if;
|
2528 |
|
|
-- pragma translate_off
|
2529 |
|
|
end if;
|
2530 |
|
|
-- pragma translate_on
|
2531 |
|
|
end if;
|
2532 |
|
|
end if;
|
2533 |
|
|
end if;
|
2534 |
|
|
|
2535 |
|
|
trap_address(31 downto 4) := sregs.tba & vectt;
|
2536 |
|
|
trap_address(3 downto PCLOW) := (others => '0');
|
2537 |
|
|
|
2538 |
|
|
-- debug mode
|
2539 |
|
|
|
2540 |
|
|
if DEBUG_UNIT then
|
2541 |
|
|
iuo.debug.dbreak <= iui.debug.dbreak;
|
2542 |
|
|
-- iuo.debug.dbreak <= iui.debug.dsuen and iui.debug.dbreak;
|
2543 |
|
|
if iui.debug.rerror = '1' then trapping := '0'; error := '0'; end if;
|
2544 |
|
|
if (dsur.dmode = '1') then
|
2545 |
|
|
if dsur.dstate = '0' then
|
2546 |
|
|
annul_all := '1'; trap_address := dsur.pc; exception := '1';
|
2547 |
|
|
vdsu.pc := npc; vdsu.dstate := '1';
|
2548 |
|
|
else
|
2549 |
|
|
annul_all := '1'; trap_address := fe.pc; exception := '1';
|
2550 |
|
|
if (iui.debug.dsuen and iui.debug.dbreak) = '0' then
|
2551 |
|
|
annul_all := '0'; vdsu.dmode := '0'; vdsu.dstate := '0';
|
2552 |
|
|
trap_address := dsur.pc;
|
2553 |
|
|
end if;
|
2554 |
|
|
if (iui.debug.dwrite and iui.debug.denable) = '1' then
|
2555 |
|
|
if iui.debug.daddr(20 downto 19) = "00" then -- write regfile
|
2556 |
|
|
write_reg := dsur.dsuen;
|
2557 |
|
|
rd_address := iui.debug.daddr(RABITS+1 downto 2);
|
2558 |
|
|
if (FPIFTYPE = parallel) and FPEN then
|
2559 |
|
|
if iui.debug.daddr(17 downto 16) = "11" then
|
2560 |
|
|
fp_dwrite := dsur.dsuen;
|
2561 |
|
|
write_reg := '0';
|
2562 |
|
|
end if;
|
2563 |
|
|
end if;
|
2564 |
|
|
elsif iui.debug.daddr(20 downto 19) = "01" then -- write special registers
|
2565 |
|
|
case iui.debug.daddr(7 downto 2) is
|
2566 |
|
|
when "000001" => -- PSR
|
2567 |
|
|
cwp := iui.debug.ddata(NWINLOG2-1 downto 0);
|
2568 |
|
|
icc := iui.debug.ddata(23 downto 20);
|
2569 |
|
|
ec := iui.debug.ddata(13);
|
2570 |
|
|
ef := iui.debug.ddata(12);
|
2571 |
|
|
pil := iui.debug.ddata(11 downto 8);
|
2572 |
|
|
s := iui.debug.ddata(7);
|
2573 |
|
|
ps := iui.debug.ddata(6);
|
2574 |
|
|
et := iui.debug.ddata(5);
|
2575 |
|
|
when "000010" => -- WIM
|
2576 |
|
|
wim := iui.debug.ddata(NWINDOWS-1 downto 0);
|
2577 |
|
|
when "000011" => tba := iui.debug.ddata(31 downto 12); -- TBR
|
2578 |
|
|
when "000100" => trap_address := iui.debug.ddata(31 downto PCLOW); -- PC
|
2579 |
|
|
when "000101" => vdsu.pc := iui.debug.ddata(31 downto PCLOW); -- NPC
|
2580 |
|
|
when "000110" => -- FSR
|
2581 |
|
|
if (FPIFTYPE = serial) and FPEN then
|
2582 |
|
|
vfsr.cexc := iui.debug.ddata(4 downto 0);
|
2583 |
|
|
vfsr.aexc := iui.debug.ddata(9 downto 5);
|
2584 |
|
|
vfsr.fcc := iui.debug.ddata(11 downto 10);
|
2585 |
|
|
vfsr.tem := iui.debug.ddata(27 downto 23);
|
2586 |
|
|
vfsr.rd := iui.debug.ddata(31 downto 30);
|
2587 |
|
|
elsif (FPIFTYPE = parallel) and FPEN then
|
2588 |
|
|
fp_dwrite_fsr := '1';
|
2589 |
|
|
end if;
|
2590 |
|
|
when others =>
|
2591 |
|
|
end case;
|
2592 |
|
|
end if;
|
2593 |
|
|
end if;
|
2594 |
|
|
end if;
|
2595 |
|
|
else -- break-in in during error mode
|
2596 |
|
|
if (iui.debug.dbreak and error) = '1' then vdsu.dmode := '1'; end if;
|
2597 |
|
|
end if;
|
2598 |
|
|
vdsu.dmode2 := vdsu.dmode or vdsu.dmode2;
|
2599 |
|
|
iuo.debug.error <= wr.error;
|
2600 |
|
|
end if;
|
2601 |
|
|
|
2602 |
|
|
write_reg := write_reg and holdn;
|
2603 |
|
|
if save_pc = '1' then wrdata(31 downto 0) := npc(31 downto 2) & "00";
|
2604 |
|
|
else wrdata(31 downto 0) := wr.result; end if;
|
2605 |
|
|
|
2606 |
|
|
if DEBUGPORT then
|
2607 |
|
|
iuo.debug.tt <= tt;
|
2608 |
|
|
iuo.debug.trap <= trapping;
|
2609 |
|
|
iuo.debug.result <= wrdata(31 downto 0);
|
2610 |
|
|
iuo.debug.wr <= wr.ctrl;
|
2611 |
|
|
iuo.debug.dmode <= vdsu.dstate;
|
2612 |
|
|
iuo.debug.dmode2 <= dsur.dmode2;
|
2613 |
|
|
iuo.debug.vdmode <= vdsu.dmode;
|
2614 |
|
|
iuo.debug.psrtt <= sregs.tt;
|
2615 |
|
|
iuo.debug.psrpil <= sregs.pil;
|
2616 |
|
|
|
2617 |
|
|
iuo.debug.write_reg <= write_reg;
|
2618 |
|
|
|
2619 |
|
|
end if;
|
2620 |
|
|
|
2621 |
|
|
-- reset handling
|
2622 |
|
|
|
2623 |
|
|
if rst = '0' then
|
2624 |
|
|
et := '0'; s := '1'; annul_all := '1';
|
2625 |
|
|
trapping := '0'; save_pc := '0'; exception := '0'; error := '0';
|
2626 |
|
|
vdsu.dmode := '0'; vdsu.dstate := '0'; vdsu.error := '0';
|
2627 |
|
|
|
2628 |
|
|
end if;
|
2629 |
|
|
|
2630 |
|
|
if not FPEN then ef := '0'; end if;
|
2631 |
|
|
if not CPEN then ec := '0'; end if;
|
2632 |
|
|
|
2633 |
|
|
if CPEN then
|
2634 |
|
|
cpi.exack <= cpexack;
|
2635 |
|
|
cpi.dcnt <= de.cnt;
|
2636 |
|
|
cpi.dinst <= de.inst;
|
2637 |
|
|
cpi.ex <= ex.ctrl;
|
2638 |
|
|
cpi.me <= me.ctrl;
|
2639 |
|
|
cpi.wr <= wr.ctrl;
|
2640 |
|
|
cpi.flush <= annul_all;
|
2641 |
|
|
cpi.lddata <= wr.result;
|
2642 |
|
|
end if;
|
2643 |
|
|
|
2644 |
|
|
if (FPIFTYPE = parallel) then
|
2645 |
|
|
fpi.exack <= fpexack;
|
2646 |
|
|
fpi.dcnt <= de.cnt;
|
2647 |
|
|
fpi.dinst <= de.inst;
|
2648 |
|
|
fpi.ex <= ex.ctrl;
|
2649 |
|
|
fpi.me <= me.ctrl;
|
2650 |
|
|
fpi.wr <= wr.ctrl;
|
2651 |
|
|
fpi.flush <= annul_all;
|
2652 |
|
|
fpi.lddata <= wr.result;
|
2653 |
|
|
fpi.debug.daddr <= iui.debug.daddr(6 downto 2);
|
2654 |
|
|
fpi.debug.dwrite_fsr <= fp_dwrite_fsr;
|
2655 |
|
|
fpi.debug.denable <= iui.debug.denable and dsur.dmode;
|
2656 |
|
|
fpi.debug.dwrite <= fp_dwrite;
|
2657 |
|
|
fpi.debug.ddata <= iui.debug.ddata;
|
2658 |
|
|
end if;
|
2659 |
|
|
|
2660 |
|
|
iuo.error <= wr.nerror;
|
2661 |
|
|
iuo.intack <= wr.intack and holdn;
|
2662 |
|
|
iuo.irqvec <= sregs.tt(3 downto 0);
|
2663 |
|
|
wr.annul_all <= annul_all;
|
2664 |
|
|
wrin.trapping <= trapping;
|
2665 |
|
|
wrin.tpcsel <= tpcsel;
|
2666 |
|
|
wrin.error <= error;
|
2667 |
|
|
wrin.nerror <= not error;
|
2668 |
|
|
wrin.intack <= intack;
|
2669 |
|
|
sregsin.cwp <= cwp;
|
2670 |
|
|
sregsin.icc <= icc;
|
2671 |
|
|
sregsin.ec <= ec;
|
2672 |
|
|
sregsin.ef <= ef;
|
2673 |
|
|
sregsin.pil <= pil;
|
2674 |
|
|
sregsin.s <= s;
|
2675 |
|
|
sregsin.ps <= ps;
|
2676 |
|
|
sregsin.et <= et;
|
2677 |
|
|
sregsin.wim <= wim;
|
2678 |
|
|
sregsin.tba <= tba;
|
2679 |
|
|
sregsin.tt <= tt;
|
2680 |
|
|
rfi.wraddr <= rd_address;
|
2681 |
|
|
rfi.wrdata <= wrdata;
|
2682 |
|
|
rfi.wren <= write_reg;
|
2683 |
|
|
fecomb.exception <= exception;
|
2684 |
|
|
fecomb.trap_address <= trap_address;
|
2685 |
|
|
fpu_regin.fsr <= vfsr;
|
2686 |
|
|
muli.flush <= wr.annul_all;
|
2687 |
|
|
divi.flush <= wr.annul_all;
|
2688 |
|
|
muli.y <= wr.y(7 downto 0);
|
2689 |
|
|
muli.asr18 <= wr.asr18;
|
2690 |
|
|
dsurin <= vdsu;
|
2691 |
|
|
|
2692 |
|
|
end process;
|
2693 |
|
|
|
2694 |
|
|
-- optional multiplier
|
2695 |
|
|
|
2696 |
|
|
mgen : if MULTIPLIER > iterative generate
|
2697 |
|
|
mul0 : mul port map (rst, clk, holdn, muli, mulo);
|
2698 |
|
|
end generate;
|
2699 |
|
|
|
2700 |
|
|
-- optional divider
|
2701 |
|
|
|
2702 |
|
|
dgen : if DIVIDER /= none generate
|
2703 |
|
|
div0 : div port map (rst, clk, holdn, divi, divo);
|
2704 |
|
|
end generate;
|
2705 |
|
|
|
2706 |
|
|
-- missed instruction and data registers
|
2707 |
|
|
|
2708 |
|
|
instmux : process(dein, ico, de, fecomb)
|
2709 |
|
|
begin
|
2710 |
|
|
if (ico.mds and fecomb.hold_pc) = '1' then
|
2711 |
|
|
dein.inst <= de.inst;
|
2712 |
|
|
dein.mexc <= de.mexc;
|
2713 |
|
|
else
|
2714 |
|
|
dein.inst <= ico.data;
|
2715 |
|
|
dein.mexc <= ico.exception;
|
2716 |
|
|
end if;
|
2717 |
|
|
end process;
|
2718 |
|
|
|
2719 |
|
|
-- debug unit diagnostic read
|
2720 |
|
|
|
2721 |
|
|
dsuread : if DEBUG_UNIT generate
|
2722 |
|
|
dsrd : process(iui, wr, sregs, tr, fe, dsur, fpu_reg, rfo, dco)
|
2723 |
|
|
variable rdata : std_logic_vector(31 downto 0);
|
2724 |
|
|
variable cwp : std_logic_vector(4 downto 0);
|
2725 |
|
|
variable wpi : integer;
|
2726 |
|
|
variable fp_dread_fsr : std_logic;
|
2727 |
|
|
begin
|
2728 |
|
|
rdata := (others => '0'); wpi := 0; cwp := (others => '0');
|
2729 |
|
|
fp_dread_fsr := '0';
|
2730 |
|
|
case iui.debug.daddr(20 downto 19) is
|
2731 |
|
|
when "00" =>
|
2732 |
|
|
rdata := rfo.data1(31 downto 0);
|
2733 |
|
|
if (FPIFTYPE = parallel) and FPEN then
|
2734 |
|
|
if iui.debug.daddr(17 downto 16) = "11" then
|
2735 |
|
|
rdata := fpo.data;
|
2736 |
|
|
end if;
|
2737 |
|
|
end if;
|
2738 |
|
|
when "01" =>
|
2739 |
|
|
case iui.debug.daddr(7 downto 2) is
|
2740 |
|
|
when "000000" => rdata := wr.y; -- Y
|
2741 |
|
|
when "000001" => cwp(NWINLOG2-1 downto 0) := sregs.cwp;
|
2742 |
|
|
rdata := std_logic_vector(IMPL) & std_logic_vector(VER) &
|
2743 |
|
|
sregs.icc & "000000" & sregs.ec & sregs.ef & sregs.pil & sregs.s
|
2744 |
|
|
& sregs.ps & sregs.et & cwp;
|
2745 |
|
|
when "000010" => rdata(NWINDOWS-1 downto 0) := sregs.wim; -- WIM
|
2746 |
|
|
when "000011" => rdata := sregs.tba & sregs.tt & "0000"; -- TBR
|
2747 |
|
|
when "000100" => rdata(31 downto PCLOW) := fe.pc; -- PC
|
2748 |
|
|
when "000101" => rdata(31 downto PCLOW) := dsur.pc; -- NPC
|
2749 |
|
|
when "000110" =>
|
2750 |
|
|
if ((FPIFTYPE = serial) and FPEN) then
|
2751 |
|
|
rdata := fpu_reg.fsr.rd & "00" &
|
2752 |
|
|
fpu_reg.fsr.tem & "000" & std_logic_vector(FPUVER) &
|
2753 |
|
|
fpu_reg.fsr.ftt & "00" & fpu_reg.fsr.fcc & fpu_reg.fsr.aexc &
|
2754 |
|
|
fpu_reg.fsr.cexc;
|
2755 |
|
|
elsif ((FPIFTYPE = parallel) and FPEN) then
|
2756 |
|
|
fp_dread_fsr := '1';
|
2757 |
|
|
rdata := fpo.data;
|
2758 |
|
|
end if;
|
2759 |
|
|
when "000111" => rdata(12 downto 4) := dsur.error & dsur.tt; -- DSU TT
|
2760 |
|
|
|
2761 |
|
|
when others =>
|
2762 |
|
|
if (WATCHPOINTS > 0) and (iui.debug.daddr(7 downto 5) = "011") then
|
2763 |
|
|
wpi := conv_integer(unsigned(iui.debug.daddr(4 downto 3)));
|
2764 |
|
|
if iui.debug.daddr(2) = '0' then
|
2765 |
|
|
rdata := tr(wpi).addr & '0' & tr(wpi).exec;
|
2766 |
|
|
else rdata := tr(wpi).mask & tr(wpi).load & tr(wpi).store; end if;
|
2767 |
|
|
end if;
|
2768 |
|
|
end case;
|
2769 |
|
|
when others =>
|
2770 |
|
|
rdata := dco.dsudata;
|
2771 |
|
|
end case;
|
2772 |
|
|
iuo.debug.ddata <= rdata;
|
2773 |
|
|
fpi.debug.dread_fsr <= fp_dread_fsr;
|
2774 |
|
|
end process;
|
2775 |
|
|
end generate;
|
2776 |
|
|
|
2777 |
|
|
|
2778 |
|
|
|
2779 |
|
|
iregs : process (clk)
|
2780 |
|
|
begin
|
2781 |
|
|
if rising_edge(clk) then
|
2782 |
|
|
if (holdn or (not ico.mds)) = '1' then
|
2783 |
|
|
de.inst <= dein.inst;
|
2784 |
|
|
de.mexc <= dein.mexc;
|
2785 |
|
|
end if;
|
2786 |
|
|
end if;
|
2787 |
|
|
end process;
|
2788 |
|
|
dregs : process(clk)
|
2789 |
|
|
begin
|
2790 |
|
|
if rising_edge(clk) then
|
2791 |
|
|
if (holdn or (not dco.mds)) = '1' then
|
2792 |
|
|
wr.mexc <= dco.mexc;
|
2793 |
|
|
wr.result <= wrin.result;
|
2794 |
|
|
end if;
|
2795 |
|
|
end if;
|
2796 |
|
|
end process;
|
2797 |
|
|
|
2798 |
|
|
-- normal registers
|
2799 |
|
|
|
2800 |
|
|
|
2801 |
|
|
pregs : process (clk)
|
2802 |
|
|
begin
|
2803 |
|
|
if rising_edge(clk) then
|
2804 |
|
|
me.werr <= mein.werr;
|
2805 |
|
|
me.ipend <= mein.ipend;
|
2806 |
|
|
if (holdn = '1') then
|
2807 |
|
|
|
2808 |
|
|
-- fetch stage
|
2809 |
|
|
fe <= fein;
|
2810 |
|
|
-- decode stage
|
2811 |
|
|
de.annul <= dein.annul;
|
2812 |
|
|
de.cnt <= dein.cnt;
|
2813 |
|
|
de.mulcnt <= dein.mulcnt;
|
2814 |
|
|
de.cwp <= dein.cwp;
|
2815 |
|
|
de.pv <= dein.pv;
|
2816 |
|
|
de.pc <= dein.pc;
|
2817 |
|
|
|
2818 |
|
|
-- execute stage
|
2819 |
|
|
ex.ctrl <= exin.ctrl;
|
2820 |
|
|
ex.write_reg <= exin.write_reg;
|
2821 |
|
|
ex.write_cwp <= exin.write_cwp;
|
2822 |
|
|
ex.cwp <= exin.cwp;
|
2823 |
|
|
ex.write_y <= exin.write_y;
|
2824 |
|
|
ex.rst_mey <= exin.rst_mey;
|
2825 |
|
|
ex.write_icc <= exin.write_icc;
|
2826 |
|
|
ex.rs1data <= exin.rs1data;
|
2827 |
|
|
ex.rs2data <= exin.rs2data;
|
2828 |
|
|
ex.alu_cin <= exin.alu_cin;
|
2829 |
|
|
ex.aluop <= exin.aluop;
|
2830 |
|
|
ex.alusel <= exin.alusel;
|
2831 |
|
|
ex.aluadd <= exin.aluadd;
|
2832 |
|
|
ex.mulstep <= exin.mulstep;
|
2833 |
|
|
ex.mulinsn <= exin.mulinsn;
|
2834 |
|
|
ex.ymsb <= exin.ymsb;
|
2835 |
|
|
dci.write <= dciin.write;
|
2836 |
|
|
dci.asi <= dciin.asi;
|
2837 |
|
|
dci.enaddr <= dciin.enaddr;
|
2838 |
|
|
dci.read <= dciin.read;
|
2839 |
|
|
dci.lock <= dciin.lock;
|
2840 |
|
|
|
2841 |
|
|
-- memory stage
|
2842 |
|
|
me.result <= mein.result;
|
2843 |
|
|
me.y <= mein.y;
|
2844 |
|
|
me.ctrl <= mein.ctrl;
|
2845 |
|
|
dci.size <= mein.ld_size;
|
2846 |
|
|
me.memory_load <= mein.memory_load;
|
2847 |
|
|
dci.signed <= mein.signed;
|
2848 |
|
|
me.write_reg <= mein.write_reg;
|
2849 |
|
|
me.write_cwp <= ex.write_cwp;
|
2850 |
|
|
me.cwp <= ex.cwp;
|
2851 |
|
|
me.write_y <= mein.write_y;
|
2852 |
|
|
me.write_icc <= mein.write_icc;
|
2853 |
|
|
me.icc <= mein.icc;
|
2854 |
|
|
me.addr_misal <= mein.addr_misal;
|
2855 |
|
|
me.irqen <= mein.irqen;
|
2856 |
|
|
me.su <= mein.su;
|
2857 |
|
|
|
2858 |
|
|
-- write stage
|
2859 |
|
|
wr.y <= wrin.y;
|
2860 |
|
|
wr.ctrl <= wrin.ctrl;
|
2861 |
|
|
wr.write_reg <= wrin.write_reg;
|
2862 |
|
|
wr.write_cwp <= wrin.write_cwp;
|
2863 |
|
|
wr.cwp <= wrin.cwp;
|
2864 |
|
|
wr.write_icc <= me.write_icc;
|
2865 |
|
|
wr.icc <= wrin.icc;
|
2866 |
|
|
wr.tpcsel <= wrin.tpcsel;
|
2867 |
|
|
wr.trapping <= wrin.trapping;
|
2868 |
|
|
wr.error <= wrin.error;
|
2869 |
|
|
wr.nerror <= wrin.nerror;
|
2870 |
|
|
wr.intack <= wrin.intack;
|
2871 |
|
|
|
2872 |
|
|
-- special registers
|
2873 |
|
|
sregs.cwp <= sregsin.cwp;
|
2874 |
|
|
sregs.icc <= sregsin.icc;
|
2875 |
|
|
sregs.tt <= sregsin.tt;
|
2876 |
|
|
sregs.tba <= sregsin.tba;
|
2877 |
|
|
sregs.wim <= sregsin.wim;
|
2878 |
|
|
sregs.ec <= sregsin.ec;
|
2879 |
|
|
sregs.ef <= sregsin.ef;
|
2880 |
|
|
sregs.et <= sregsin.et;
|
2881 |
|
|
sregs.ps <= sregsin.ps;
|
2882 |
|
|
sregs.s <= sregsin.s;
|
2883 |
|
|
sregs.pil <= sregsin.pil;
|
2884 |
|
|
end if;
|
2885 |
|
|
|
2886 |
|
|
-- wathpoint registers
|
2887 |
|
|
for i in 0 to WATCHPOINTS-1 loop tr(i) <= trin(i); end loop;
|
2888 |
|
|
end if;
|
2889 |
|
|
|
2890 |
|
|
-- drive unused watchpoint signals to avoid tri-state buffers
|
2891 |
|
|
for i in WATCHPOINTS to 3 loop
|
2892 |
|
|
tr(i).addr <= (others => '0'); tr(i).mask <= (others => '0');
|
2893 |
|
|
tr(i).exec <= '0'; tr(i).load <= '0'; tr(i).store <= '0';
|
2894 |
|
|
end loop;
|
2895 |
|
|
end process;
|
2896 |
|
|
|
2897 |
|
|
-- DSU register
|
2898 |
|
|
|
2899 |
|
|
dsr0 : if DEBUG_UNIT generate
|
2900 |
|
|
dsuregs : process (clk)
|
2901 |
|
|
begin
|
2902 |
|
|
if rising_edge(clk) then
|
2903 |
|
|
if (holdn = '1') then
|
2904 |
|
|
dsur <= dsurin;
|
2905 |
|
|
wr.dsutrap <= wrin.dsutrap;
|
2906 |
|
|
de.step <= dein.step;
|
2907 |
|
|
end if;
|
2908 |
|
|
end if;
|
2909 |
|
|
end process;
|
2910 |
|
|
end generate;
|
2911 |
|
|
|
2912 |
|
|
-- MAC register
|
2913 |
|
|
|
2914 |
|
|
m0 : if MACEN generate
|
2915 |
|
|
mregs : process (clk)
|
2916 |
|
|
begin
|
2917 |
|
|
if rising_edge(clk) then
|
2918 |
|
|
if (holdn = '1') then
|
2919 |
|
|
wr.asr18 <= wrin.asr18;
|
2920 |
|
|
me.mulinsn <= ex.mulinsn;
|
2921 |
|
|
end if;
|
2922 |
|
|
end if;
|
2923 |
|
|
end process;
|
2924 |
|
|
end generate;
|
2925 |
|
|
|
2926 |
|
|
-- register for load bypass control if LDDELAY = 1
|
2927 |
|
|
|
2928 |
|
|
ldbpr0 : if LDDELAY = 1 generate
|
2929 |
|
|
lb : process(clk)
|
2930 |
|
|
begin
|
2931 |
|
|
if rising_edge(clk) then
|
2932 |
|
|
if (holdn = '1') then
|
2933 |
|
|
ex.ldbp1 <= exin.ldbp1; ex.ldbp2 <= exin.ldbp2;
|
2934 |
|
|
end if;
|
2935 |
|
|
end if;
|
2936 |
|
|
end process;
|
2937 |
|
|
end generate;
|
2938 |
|
|
|
2939 |
|
|
-- fpu support registers
|
2940 |
|
|
|
2941 |
|
|
fg3 : if ((FPIFTYPE = serial) and FPEN) generate
|
2942 |
|
|
fpureg : process (clk)
|
2943 |
|
|
begin
|
2944 |
|
|
if rising_edge(clk) then
|
2945 |
|
|
fpu_reg.fpld <= fpu_regin.fpld;
|
2946 |
|
|
fpu_reg.fpbusy <= fpu_regin.fpbusy;
|
2947 |
|
|
fpu_reg.rstdel <= fpu_regin.rstdel;
|
2948 |
|
|
if (holdn = '1') then
|
2949 |
|
|
fpu_reg.reset <= fpu_regin.reset;
|
2950 |
|
|
fpu_reg.fsr <= fpu_regin.fsr;
|
2951 |
|
|
fpu_reg.fpexc <= fpu_regin.fpexc;
|
2952 |
|
|
fpu_reg.op1h <= fpu_regin.op1h;
|
2953 |
|
|
fpu_reg.ex <= fpu_regin.ex;
|
2954 |
|
|
fpu_reg.me <= fpu_regin.me;
|
2955 |
|
|
fpu_reg.wr <= fpu_regin.wr;
|
2956 |
|
|
end if;
|
2957 |
|
|
end if;
|
2958 |
|
|
end process;
|
2959 |
|
|
end generate;
|
2960 |
|
|
|
2961 |
|
|
|
2962 |
|
|
fg4 : if ((FPIFTYPE = serial) and FPEN) generate
|
2963 |
|
|
fpu_regin.reset <= ((fpu_regin.fpop or fpu_reg.fpld or fpu_reg.fpbusy)
|
2964 |
|
|
and wr.annul_all) or not rst;
|
2965 |
|
|
fpu_regin.rstdel <= "11" when (fpu_reg.reset or fpu_regin.reset) = '1'
|
2966 |
|
|
else fpu_reg.rstdel - 1 when (fpu_reg.rstdel /= "00")
|
2967 |
|
|
-- pragma translate_off
|
2968 |
|
|
and not (is_x(fpu_reg.rstdel))
|
2969 |
|
|
-- pragma translate_on
|
2970 |
|
|
else fpu_reg.rstdel;
|
2971 |
|
|
fpui.fpop <= fpu_regin.fpop;
|
2972 |
|
|
fpu_regin.fpld <= fpu_regin.fpop or not rst;
|
2973 |
|
|
fpui.reset <= fpu_reg.reset or fpu_regin.reset or fpu_reg.rstdel(1)
|
2974 |
|
|
or fpu_reg.rstdel(0);
|
2975 |
|
|
fpu_regin.fpbusy <= fpuo.fpbusy;
|
2976 |
|
|
fpui.fpld <= fpu_reg.fpld;
|
2977 |
|
|
fpui.fpuholdn <= fpu_reg.reset or fpu_reg.rstdel(1) or fpu_reg.rstdel(0)
|
2978 |
|
|
or (not rst) or not (fpu_reg.fpbusy or fpu_reg.fpld);
|
2979 |
|
|
end generate;
|
2980 |
|
|
fg5 : if not ((FPIFTYPE = serial) and FPEN) generate
|
2981 |
|
|
fpui.fpuholdn <= '1';
|
2982 |
|
|
end generate;
|
2983 |
|
|
|
2984 |
|
|
|
2985 |
|
|
|
2986 |
|
|
|
2987 |
|
|
-- debugging support
|
2988 |
|
|
|
2989 |
|
|
debug0 : if DEBUGPORT generate
|
2990 |
|
|
|
2991 |
|
|
|
2992 |
|
|
iuo.debug.clk <= clk;
|
2993 |
|
|
|
2994 |
|
|
iuo.debug.rst <= rst;
|
2995 |
|
|
iuo.debug.holdn <= holdn;
|
2996 |
|
|
iuo.debug.ex <= ex.ctrl;
|
2997 |
|
|
iuo.debug.me <= me.ctrl;
|
2998 |
|
|
iuo.debug.mresult<= me.result;
|
2999 |
|
|
iuo.debug.diagrdy<= ico.diagrdy;
|
3000 |
|
|
iuo.debug.fpdbg <= fpo.debug;
|
3001 |
|
|
|
3002 |
|
|
end generate;
|
3003 |
|
|
|
3004 |
|
|
fadder : if FASTADD generate
|
3005 |
|
|
add0 : add32 port map (add32in1, add32in2, add32cin, sum32, open);
|
3006 |
|
|
end generate;
|
3007 |
|
|
|
3008 |
|
|
end;
|