OpenCores
URL https://opencores.org/ocsvn/core_arm/core_arm/trunk

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [iu.vhd] - Blame information for rev 5

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
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;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.