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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [fp1eu.vhd] - Blame information for rev 4

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:      fp
19
-- File:        fp.vhd
20
-- Author:      Jiri Gaisler - ESA/ESTEC
21
-- Description: Parallel floating-point and co-processor interface
22
-- The interface allows one execution unit
23
------------------------------------------------------------------------------
24
 
25
library IEEE;
26
use IEEE.std_logic_1164.all;
27
use work.leon_config.all;
28
use work.leon_iface.all;
29
use work.sparcv8.all;
30
use work.tech_map.all;
31
use work.fpulib.all;
32
 
33
-- pragma translate_off
34
use STD.TEXTIO.all;
35
use work.debug.all;
36
-- pragma translate_on
37
 
38
entity fp1eu is
39
port (
40
    rst    : in  std_logic;                     -- Reset
41
    clk    : in  clk_type;
42
    holdn  : in  std_logic;                     -- pipeline hold
43
    xholdn : in  std_logic;                     -- pipeline hold
44
    cpi    : in  cp_in_type;
45
    cpo    : out cp_out_type
46
  );
47
end;
48
 
49
architecture rtl of fp1eu is
50
 
51
type cpins_type is (none, cpop, load, store);
52
 
53
type pl_ctrl is record          -- pipeline control record
54
  cpins    : cpins_type;        -- CP instruction
55
  rreg1    : std_logic;         -- using rs1
56
  rreg2    : std_logic;         -- using rs1
57
  rs1d     : std_logic;         -- rs1 is double (64-bit)
58
  rs2d     : std_logic;         -- rs2 is double (64-bit)
59
  wreg     : std_logic;         -- write CP regfile
60
  rdd      : std_logic;         -- rd is double (64-bit)
61
  wrcc     : std_logic;         -- write CP condition codes
62
  acsr     : std_logic;         -- access CP control register
63
end record;
64
 
65
type unit_status_type is (free, started, ready);
66
type unit_ctrl is record        -- execution unit control record
67
  status   : unit_status_type;              -- unit status
68
  rs1      : std_logic_vector (4 downto 0); -- destination register
69
  rs2      : std_logic_vector (4 downto 0); -- destination register
70
  rd       : std_logic_vector (4 downto 0); -- destination register
71
  rreg1    : std_logic;         -- using rs1
72
  rreg2    : std_logic;         -- using rs1
73
  rs1d     : std_logic;         -- rs1 is double (64-bit)
74
  rs2d     : std_logic;         -- rs2 is double (64-bit)
75
  wreg     : std_logic;         -- will write CP regfile
76
  rdd      : std_logic;         -- rd is double (64-bit)
77
  wbok     : std_logic;         -- ok to write result
78
  wrcc     : std_logic;         -- will write CP condition codes
79
  rst      : std_logic;         -- reset register
80
  pc       : std_logic_vector (31 downto PCLOW); -- program counter
81
  inst     : std_logic_vector (31 downto 0); -- instruction
82
end record;
83
 
84
type csr_type is record -- CP status register
85
  cc       : std_logic_vector (1 downto 0); -- condition codes
86
  aexc     : std_logic_vector (4 downto 0); -- exception codes
87
  cexc     : std_logic_vector (4 downto 0); -- exception codes
88
  tem      : std_logic_vector (4 downto 0); -- trap enable mask
89
  rd       : std_logic_vector (1 downto 0); -- rounding mode
90
  tt       : std_logic_vector (2 downto 0); -- trap type
91
end record;
92
 
93
type execstate is (nominal, excpend, exception);
94
type reg_type is record -- registers clocked with pipeline
95
  start    : std_logic;         -- start EU
96
end record;
97
 
98
type regx_type is record        -- registers clocked continuously
99
  res      : std_logic_vector (63 downto 0); -- write stage result
100
  waddr    : std_logic_vector (3 downto 0); -- write stage dest
101
  wren     : std_logic_vector (1 downto 0); -- write stage regfile write enable
102
  csr      : csr_type;                       -- co-processor status register
103
  start    : std_logic;         -- start EU
104
  starty   : std_logic;         -- start EU
105
  startx   : std_logic;         -- start EU
106
  holdn    : std_logic;
107
  wbok     : std_logic;         -- ok to write result
108
  state    : execstate;         -- FP/CP state
109
end record;
110
 
111
signal vcc, gnd, wb, snnotdb, fp_ctl_scan_out : std_logic;
112
signal rfi1, rfi2 : rf_cp_in_type;
113
signal rfo1, rfo2 : rf_cp_out_type;
114
signal ex, exin, me, mein, wr, wrin : pl_ctrl;
115
signal r, rin  : reg_type;
116
signal rx, rxin  : regx_type;
117
signal eui : cp_unit_in_type;
118
signal euo : cp_unit_out_type;
119
signal eu, euin : unit_ctrl;
120
 
121
function ldcheck (rdin : std_logic_vector; ldd : std_logic; eu : unit_ctrl)
122
  return std_logic is
123
variable lock : std_logic;
124
variable rd : std_logic_vector(4 downto 0);
125
begin
126
  lock := '0'; rd := rdin;
127
  if (eu.status > free) then
128
    if (eu.rdd = '0') then
129
      if ((eu.wreg = '1') and (rd = eu.rd)) or
130
         ((eu.rreg1 = '1') and (rd = eu.rs1)) or
131
         ((eu.rreg2 = '1') and (rd = eu.rs2))
132
      then lock := '1'; end if;
133
      if (ldd = '1') then
134
        if ((eu.wreg = '1')  and ((rd(4 downto 1) & '1') = eu.rd)) or
135
           ((eu.rreg1 = '1') and ((rd(4 downto 1) & '1') = eu.rs1)) or
136
           ((eu.rreg2 = '1') and ((rd(4 downto 1) & '1') = eu.rs2))
137
        then lock := '1'; end if;
138
      end if;
139
    else
140
      if ((eu.wreg = '1')  and (rd(4 downto 1) = eu.rd(4 downto 1))) or
141
         ((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
142
         ((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
143
      then lock := '1'; end if;
144
    end if;
145
  end if;
146
  return(lock);
147
end;
148
function stcheck (rdin : std_logic_vector; std : std_logic; eu : unit_ctrl)
149
  return std_logic is
150
variable lock : std_logic;
151
variable rd : std_logic_vector(4 downto 0);
152
begin
153
  lock := '0'; rd := rdin;
154
  if (eu.status > free) then
155
    if (eu.rdd = '0') then
156
      if ((eu.wreg = '1') and (rd = eu.rd)) then lock := '1'; end if;
157
      if (std = '1') then
158
        if ((eu.wreg = '1')  and ((rd(4 downto 1) & '1') = eu.rd))
159
        then lock := '1'; end if;
160
      end if;
161
    else
162
      if ((eu.wreg = '1')  and (rd(4 downto 1) = eu.rd(4 downto 1))) or
163
         ((eu.rreg1 = '1') and (rd(4 downto 1) = eu.rs1(4 downto 1))) or
164
         ((eu.rreg2 = '1') and (rd(4 downto 1) = eu.rs2(4 downto 1)))
165
      then lock := '1'; end if;
166
    end if;
167
  end if;
168
  return(lock);
169
end;
170
 
171
function srccheck (rsin : std_logic_vector; dbl : std_logic; eu : unit_ctrl)
172
  return std_logic is
173
variable lock : std_logic;
174
variable rs : std_logic_vector(4 downto 0);
175
begin
176
  lock := '0'; rs := rsin;
177
  if (eu.wreg = '1')  and (rs(4 downto 1) = eu.rd(4 downto 1)) then
178
    if ((dbl or eu.rdd) = '1') or (rs(0) = eu.rd(0)) then lock := '1'; end if;
179
  end if;
180
  return(lock);
181
end;
182
 
183
begin
184
 
185
  vcc <= '1'; gnd <= '1';
186
 
187
-- instruction decoding
188
 
189
  pipeline : process(cpi, ex, me, wr, eu, euin, r, rx, rfi1, rfi2, rfo1, rfo2,
190
                     holdn, xholdn,
191
                        euo, rst, wb)
192
  variable op     : std_logic_vector(1 downto 0);
193
  variable op3    : std_logic_vector(5 downto 0);
194
  variable opc    : std_logic_vector(8 downto 0);
195
  variable stdata : std_logic_vector(31 downto 0);
196
  variable rs1, rs2, rd : std_logic_vector(4 downto 0);
197
  variable ctrl   : pl_ctrl;
198
  variable ldlock : std_logic;
199
  variable wren   : std_logic_vector(1 downto 0);
200
  variable waddr  : std_logic_vector(3 downto 0);
201
  variable rtaddr : std_logic_vector(3 downto 0);
202
  variable wrdata : std_logic_vector(63 downto 0);
203
  variable rtdata : std_logic_vector(63 downto 0);
204
  variable rv : reg_type;
205
  variable rxv : regx_type;
206
  variable euv : unit_ctrl;
207
  variable euiv : cp_unit_in_type;
208
  variable ddep     : std_logic;
209
  variable cpexc    : std_logic;
210
  variable fpill    : std_logic;
211
  variable ccv      : std_logic;
212
  variable qne      : std_logic;
213
  variable wbv      : std_logic;
214
  variable op1      : std_logic_vector (63 downto 0); -- operand1
215
  variable op2      : std_logic_vector (63 downto 0); -- operand2
216
  variable opcode   : std_logic_vector (9 downto 0); -- FP opcode
217
  begin
218
 
219
-------------------------------------------------------------
220
-- decode stage
221
-------------------------------------------------------------
222
    op    := cpi.dinst(31 downto 30);
223
    op3   := cpi.dinst(24 downto 19);
224
    opc   := cpi.dinst(13 downto 5);
225
    rs1   := cpi.dinst(18 downto 14);
226
    rs2   := cpi.dinst(4 downto 0);
227
    rd    := cpi.dinst(29 downto 25);
228
 
229
    rv := r; rxv := rx;
230
    ctrl.cpins := none; ctrl.wreg := '0'; ctrl.rdd := '0';
231
    ctrl.wrcc := '0'; ctrl.acsr := '0'; ldlock := '0';
232
    ctrl.rreg1 := '0'; ctrl.rreg2 := '0';
233
    ctrl.rs1d := '0'; ctrl.rs2d := '0'; fpill := '0';
234
    stdata := (others => '-'); wren := "00"; cpexc := '0';
235
    ccv := '0'; rv.start := '0'; rxv.wbok := '0';
236
    rxv.start := '0';
237
    euv := eu;
238
    if eu.status /= free then qne := '1'; else qne := '0'; end if;
239
 
240
    euiv.opcode := cpi.ex.inst(19) & cpi.ex.inst(13 downto 5);
241
    euiv.start := '0'; euiv.load := '0';
242
    euiv.flush := eu.rst or euin.rst;
243
    wbv := '0';
244
    euv.rst := not rst;
245
    if (eu.status = started) and (euo.busy = '0') then
246
      euv.status := ready;
247
    end if;
248
    if (eu.status > free) then ccv := ccv or eu.wrcc; end if;
249
 
250
    -- decode CP instructions
251
      case op is
252
      when FMT3 =>
253
        case op3 is
254
        when FPOP1 =>
255
          if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
256
          elsif rx.state = nominal then
257
            ctrl.cpins := cpop; ctrl.wreg := '1';
258
            case opc is
259
            when FMOVS | FABSS | FNEGS => ctrl.rreg2 := '1';
260
            when FITOS | FSTOI => ctrl.rreg2 := '1';
261
            when FITOD | FSTOD => ctrl.rreg2 := '1'; ctrl.rdd := '1';
262
            when FDTOI | FDTOS => ctrl.rreg2 := '1'; ctrl.rs2d  := '1';
263
            when FSQRTS => ctrl.rreg2 := '1';
264
            when FSQRTD => ctrl.rreg2 := '1'; ctrl.rs2d  := '1'; ctrl.rdd := '1';
265
            when FADDS | FSUBS | FMULS | FDIVS =>
266
              ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
267
            when FADDD | FSUBD | FMULD | FDIVD =>
268
              ctrl.rreg1 := '1'; ctrl.rreg2 := '1'; ctrl.rs1d  := '1';
269
              ctrl.rs2d  := '1'; ctrl.rdd := '1';
270
            when others => fpill := '1'; -- illegal instuction
271
            end case;
272
          end if;
273
        when FPOP2 =>
274
          if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
275
          elsif rx.state = nominal then
276
            ctrl.cpins := cpop; ctrl.wrcc := '1';
277
            ctrl.rreg1 := '1'; ctrl.rreg2 := '1';
278
            case opc is
279
            when FCMPD | FCMPED =>
280
              ctrl.rs1d := '1'; ctrl.rs2d := '1';
281
            when others => fpill := '1'; -- illegal instuction
282
            end case;
283
          end if;
284
        when others => null;
285
        end case;
286
        if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
287
          (ex.wreg = '1')
288
        then
289
          if (ctrl.rreg1 = '1') and
290
           (rs1(4 downto 1) = cpi.ex.inst(29 downto 26)) and
291
           (((ctrl.rs1d or ex.rdd) = '1') or (rs1(0) = cpi.ex.inst(25)))
292
          then ldlock := '1'; end if;
293
          if (ctrl.rreg2 = '1') and
294
           (rs2(4 downto 1) = cpi.ex.inst(29 downto 26)) and
295
           (((ctrl.rs2d or ex.rdd) = '1') or (rs2(0) = cpi.ex.inst(25)))
296
          then ldlock := '1'; end if;
297
        end if;
298
      when LDST =>
299
        case op3 is
300
        when LDF | LDDF =>
301
          if rx.state = exception then rxv.state := excpend; rxv.csr.tt := "100";
302
          elsif rx.state = nominal then
303
            ctrl.rdd := op3(1) and op3(0);
304
            ctrl.cpins := load; ctrl.wreg := '1';
305
            -- dst interlock
306
            ldlock := ldlock or ldcheck(rd, ctrl.rdd, euin);
307
          end if;
308
        when STF | STDF =>
309
          -- check for CP register dependencies
310
          if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
311
             (cpi.ex.cnt = "00") and
312
               ((rd = cpi.ex.inst(29 downto 25)) or
313
               ((rd(4 downto 1) = cpi.ex.inst(29 downto 26)) and
314
                  (ex.rdd = '1')))
315
          then ldlock := '1'; end if;
316
          if rx.state = nominal then
317
            ldlock := ldlock or stcheck(rd, (op3(1) and op3(0)), euin);
318
          end if;
319
          if (ldlock = '0') then ctrl.cpins := store; end if;
320
        when STFSR | LDFSR =>
321
          if (rx.state = exception) and (op3 = LDFSR) then
322
            rxv.state := excpend;  rxv.csr.tt := "100";
323
          else
324
            if (ex.cpins = load) and ((cpi.ex.annul or cpi.ex.trap) = '0') and
325
             (cpi.ex.cnt = "00") and (op3 = STFSR) and (ex.acsr = '1')
326
            then ldlock := '1'; end if;
327
            if (rx.state = nominal) then
328
              if (((cpi.ex.annul or cpi.ex.trap) = '0') and (ex.cpins = cpop))
329
                or (eu.status > free)
330
              then ldlock := '1'; end if;
331
            end if;
332
          end if;
333
          if (ldlock = '0') then
334
            ctrl.acsr := '1';
335
            if op3 = STFSR then ctrl.cpins := store;
336
            else ctrl.cpins := load; end if;
337
          end if;
338
        when STDFQ =>
339
          if (rx.state = nominal) then
340
            rxv.state := excpend; rxv.csr.tt := "100";
341
          else ctrl.cpins := store; end if;
342
        when others => null;
343
        end case;
344
      when others => null;
345
      end case;
346
    if ((cpi.flush or cpi.dtrap or cpi.dannul or ldlock) = '1') then
347
      ctrl.cpins := none; ctrl.acsr := '0';
348
      rxv.state := rx.state; rxv.csr.tt := rx.csr.tt;
349
    end if;
350
    if ((cpi.flush or cpi.dtrap or cpi.dannul) = '1') then
351
      ldlock := '0';
352
    end if;
353
 
354
-------------------------------------------------------------
355
-- execute stage
356
-------------------------------------------------------------
357
 
358
    -- generate regfile addresses
359
    if holdn = '0' then
360
      op  := cpi.me.inst(31 downto 30);
361
      rd  := cpi.me.inst(29 downto 25);
362
      op3 := cpi.me.inst(24 downto 19);
363
      rs1 := cpi.me.inst(18 downto 14);
364
      rs2 := cpi.me.inst(4 downto 0);
365
    else
366
      op  := cpi.ex.inst(31 downto 30);
367
      rd  := cpi.ex.inst(29 downto 25);
368
      op3 := cpi.ex.inst(24 downto 19);
369
      rs1 := cpi.ex.inst(18 downto 14);
370
      rs2 := cpi.ex.inst(4 downto 0);
371
    end if;
372
 
373
    if (op = LDST) and (op3(2) = '1') then rs1 := rd; end if;
374
 
375
    rfi1.rd1addr(3 downto 0) <= rs1(4 downto 1); rfi1.rd2addr(3 downto 0) <= rs2(4 downto 1);
376
    rfi2.rd1addr(3 downto 0) <= rs1(4 downto 1); rfi2.rd2addr(3 downto 0) <= rs2(4 downto 1);
377
    rfi1.ren1 <= '1'; rfi1.ren2 <= '1'; rfi2.ren1 <= '1'; rfi2.ren2 <= '1';
378
    cpo.ldlock <= ldlock;
379
 
380
    op1 := rfo1.data1(31 downto 0) & rfo2.data1(31 downto 0);
381
    op2 := rfo1.data2(31 downto 0) & rfo2.data2(31 downto 0);
382
 
383
    -- generate store data
384
    if  (cpi.ex.inst(20 downto 19) = "10") then  -- STDFQ
385
      if (cpi.ex.cnt /= "10") then stdata := eu.pc(31 downto 2) & "00";
386
      else stdata := eu.inst; end if;
387
    elsif  ((cpi.ex.inst(25) = '0') and (cpi.ex.cnt /= "10")) then  -- STF/STDF
388
      stdata := op1(63 downto 32);
389
    else stdata := op1(31 downto 0); end if;
390
    if (ex.cpins = store) and (ex.acsr = '1') then              -- STFSR
391
      stdata :=  rx.csr.rd & "00" & rx.csr.tem & "000" &
392
        std_logic_vector(FPUVER) & rx.csr.tt & qne & '0' & rx.csr.cc &
393
        rx.csr.aexc & rx.csr.cexc;
394
    end if;
395
    cpo.data <= stdata;
396
 
397
    -- check if an execution unit is available
398
    if (ex.cpins = cpop) and (holdn = '1') and (cpi.ex.annul = '0') then
399
      ccv := ccv or ex.wrcc;
400
      if (eu.status = free) or ((eu.status = ready) and (wb = '1')) then
401
        rxv.start := '1';
402
        euiv.start := '1';
403
        if cpi.flush = '0' then euv.status := started; end if;
404
        euv.rd := cpi.ex.inst(29 downto 25);
405
        euv.rs1 := cpi.ex.inst(18 downto 14);
406
        euv.rs2 := cpi.ex.inst(4 downto 0);
407
        euv.wreg := ex.wreg;
408
        euv.rreg1 := ex.rreg1;
409
        euv.rreg2 := ex.rreg2;
410
        euv.rs1d := ex.rs1d;
411
        euv.rs2d := ex.rs2d;
412
        euv.rdd := ex.rdd;
413
        euv.wrcc := ex.wrcc;
414
      else rxv.holdn := '0'; rv.start := '1'; end if;
415
    end if;
416
    if cpi.flush = '1' then
417
      rxv.start := '0'; euiv.start := '0';
418
    end if;
419
 
420
-------------------------------------------------------------
421
-- memory stage
422
-------------------------------------------------------------
423
 
424
    euiv.load := rx.start or rx.starty;
425
    if (rx.holdn = '0') and  (xholdn = '1') and (cpi.flush = '0') and
426
        (euo.busy = '0')
427
    then
428
      euiv.start := not rx.startx;
429
      euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
430
    end if;
431
    if (rx.holdn = '0') and ((eu.status <= free) or (wb = '1'))
432
    then
433
      euiv.load := rx.starty;
434
      euiv.start := not (rx.starty or rx.startx);
435
      euv.status := started;
436
      euv.rs1 := cpi.me.inst(18 downto 14);
437
      euv.rs2 := cpi.me.inst(4 downto 0);
438
      euv.rd := cpi.me.inst(29 downto 25);
439
      euv.wreg := me.wreg;
440
      euv.rreg1 := me.rreg1;
441
      euv.rreg2 := me.rreg2;
442
      euv.rs1d := me.rs1d;
443
      euv.rs2d := me.rs2d;
444
      euv.rdd := me.rdd;
445
      euv.wrcc := me.wrcc;
446
      euiv.opcode := cpi.me.inst(19) & cpi.me.inst(13 downto 5);
447
      rxv.holdn := '1';
448
    end if;
449
    euiv.start := euiv.start and not cpi.flush;
450
    rxv.starty := euiv.start;
451
    rxv.startx := (rx.startx or euiv.start) and (not holdn) and not cpi.flush;
452
    ccv := ccv or me.wrcc;
453
    if (cpi.flush = '1') or (rx.state /= nominal) then rxv.holdn := '1'; end if;
454
    if holdn = '0' then rxv.wbok := rx.wbok; end if;
455
    if (me.cpins = cpop) and (holdn = '1') then
456
      if ((cpi.flush and not eu.wbok) = '1') then euv.rst := '1';
457
      else rxv.wbok := not cpi.me.annul; end if;
458
    end if;
459
 
460
    -- regfile bypass
461
    if (rx.waddr = cpi.me.inst(18 downto 15)) then
462
      if (rx.wren(0) = '1') then op1(63 downto 32) := rx.res(63 downto 32); end if;
463
      if (rx.wren(1) = '1') then op1(31 downto 0) := rx.res(31 downto 0); end if;
464
    end if;
465
    if (rx.waddr = cpi.me.inst(4 downto 1)) then
466
      if (rx.wren(0) = '1') then op2(63 downto 32) := rx.res(63 downto 32); end if;
467
      if (rx.wren(1) = '1') then op2(31 downto 0) := rx.res(31 downto 0); end if;
468
    end if;
469
 
470
    -- optionally forward data from write stage
471
    if rfi1.wren = '1' then
472
      if cpi.me.inst(18 downto 15) = rfi1.wraddr(3 downto 0) then
473
        op1(63 downto 32) := rfi1.wrdata(31 downto 0);
474
      end if;
475
      if cpi.me.inst(4 downto 1) = rfi1.wraddr(3 downto 0) then
476
        op2(63 downto 32) := rfi1.wrdata(31 downto 0);
477
      end if;
478
    end if;
479
    if rfi2.wren = '1' then
480
      if cpi.me.inst(18 downto 15) = rfi2.wraddr(3 downto 0) then
481
        op1(31 downto 0) := rfi2.wrdata(31 downto 0);
482
      end if;
483
      if cpi.me.inst(4 downto 1) = rfi2.wraddr(3 downto 0) then
484
        op2(31 downto 0) := rfi2.wrdata(31 downto 0);
485
      end if;
486
    end if;
487
 
488
 
489
    -- align single operands
490
    if me.rs1d = '0' then
491
      if cpi.me.inst(14) = '0' then op1 := op1(63 downto 32) & op1(63 downto 32);
492
      else op1 := op1(31 downto 0) & op1(31 downto 0); end if;
493
    end if;
494
    if me.rs2d = '0' then
495
      if cpi.me.inst(0) = '0' then op2 := op2(63 downto 32) & op2(63 downto 32);
496
      else op2 := op2(31 downto 0) & op2(31 downto 0); end if;
497
    end if;
498
 
499
    -- drive EU operand inputs
500
    euiv.op1 := op1; euiv.op2 := op2;
501
 
502
    cpo.holdn <= rx.holdn;
503
 
504
-------------------------------------------------------------
505
-- write stage
506
-------------------------------------------------------------
507
 
508
    wrdata := cpi.lddata & cpi.lddata;
509
    if (cpi.wr.annul or cpi.flush) = '0' then
510
      case wr.cpins is
511
      when load =>
512
        if (wr.wreg = '1') then
513
          if cpi.wr.cnt = "00" then
514
            wren(0) := not cpi.wr.inst(25);
515
            wren(1) := cpi.wr.inst(25);
516
          else wren(1) := '1'; end if;
517
        end if;
518
        if (wr.acsr and holdn) = '1' then
519
          rxv.csr.cexc := cpi.lddata(4 downto 0);
520
          rxv.csr.aexc := cpi.lddata(9 downto 5);
521
          rxv.csr.cc  := cpi.lddata(11 downto 10);
522
          rxv.csr.tem  := cpi.lddata(27 downto 23);
523
          rxv.csr.rd   := cpi.lddata(31 downto 30);
524
        end if;
525
      when store =>
526
        if wr.acsr = '1' then rxv.csr.tt := (others => '0'); end if;
527
        if (cpi.wr.inst(20 downto 19) = "10") then  -- STDFQ
528
          if qne = '1'then
529
            euv.status := free; euv.rst := '1'; euv.wbok := '0';
530
          else
531
            rxv.state := nominal;
532
          end if;
533
        end if;
534
      when cpop =>
535
        -- dont assign PC and inst until here in case previous cpop trapped
536
        if holdn = '1' then euv.wbok := rx.wbok; end if;
537
          euv.inst := cpi.wr.inst;
538
          euv.pc := cpi.wr.pc;
539
      when others => null;
540
      end case;
541
    end if;
542
    if (wr.cpins = cpop) and (holdn = '1') and (eu.wbok = '0') and
543
       ((cpi.flush or cpi.wr.annul) = '1')
544
    then
545
      if rx.state = nominal then euv.status := free; end if;
546
      euv.rst := '1'; euv.wbok := '0';
547
    end if;
548
 
549
    waddr := cpi.wr.inst(29 downto 26);
550
 
551
-------------------------------------------------------------
552
-- retire stage
553
-------------------------------------------------------------
554
 
555
    rtaddr := eu.rd(4 downto 1);
556
    if eu.rdd = '1' then rtdata := euo.res;
557
    else
558
      rtdata(63 downto 32) := euo.res(63) &
559
          euo.res(59 downto 29);
560
      rtdata(31 downto 0) := rtdata(63 downto 32);
561
    end if;
562
 
563
    wren := wren and (holdn & holdn);
564
 
565
    if ((euo.exc(4 downto 0) and rx.csr.tem) /= "00000") or
566
       (euo.exc(5) = '1')
567
    then
568
      cpexc := '1';
569
    end if;
570
    if (wren = "00") and (eu.status = ready) and (rx.state = nominal) and
571
    ((eu.wbok = '1') or ((cpi.flush = '0') and (rx.wbok = '1')))
572
    then
573
      waddr := rtaddr; wrdata := rtdata;
574
      euv.wbok := '0';
575
      if (holdn = '0') then rxv.wbok := '0'; end if;
576
      if cpexc = '0' then
577
        if (eu.wreg) = '1' then
578
          if (eu.rdd) = '1' then wren := "11";
579
          else
580
            wren(0) := not eu.rd(0);
581
            wren(1) := eu.rd(0);
582
          end if;
583
        end if;
584
        if eu.wrcc = '1' then
585
          rxv.csr.cc := euo.cc;
586
        end if;
587
        rxv.csr.aexc := rx.csr.aexc or euo.exc(4 downto 0);
588
        if euv.status = ready then
589
          euv.status := free;
590
        end if;
591
        wbv := '1';
592
        rxv.csr.cexc := euo.exc(4 downto 0);
593
      else
594
        rxv.state := excpend;
595
        if (euo.exc(5) = '1') then rxv.csr.tt := "011";
596
        else rxv.csr.tt := "001"; end if;
597
      end if;
598
    end if;
599
 
600
    if cpi.exack = '1' then rxv.state := exception; end if;
601
    if rxv.state = excpend then cpo.exc <= '1'; else cpo.exc <= '0'; end if;
602
    cpo.ccv   <= not ccv;
603
    cpo.cc    <= rx.csr.cc;
604
 
605
    rxv.res := wrdata;
606
    rxv.waddr := waddr;
607
    rxv.wren := wren;
608
    rfi1.wraddr(3 downto 0) <= waddr;
609
    rfi2.wraddr(3 downto 0) <= waddr;
610
    rfi1.wren <= wren(0);
611
    rfi2.wren <= wren(1);
612
    rfi1.wrdata(31 downto 0) <= wrdata(63 downto 32);
613
    rfi2.wrdata(31 downto 0) <= wrdata(31 downto 0);
614
 
615
 
616
-- reset
617
    if rst = '0' then
618
      rxv.holdn := '1'; rv.start := '0';
619
      rxv.state := nominal; rxv.csr.tt := (others => '0');
620
      rxv.startx := '0'; euv.status := free; euv.wbok := '0';
621
    end if;
622
 
623
    euin <= euv;
624
    eui <= euiv;
625
    exin <= ctrl;
626
    rin <= rv;
627
    rxin <= rxv;
628
    wb <= wbv;
629
 
630
  end process;
631
 
632
-- registers
633
 
634
  regs : process(clk)
635
  variable pc : std_logic_vector(31 downto 0);
636
  begin
637
 
638
    if rising_edge(clk) then
639
 
640
      if holdn = '1' then
641
        ex <= exin; me <= ex; wr <= me; r <= rin;
642
      end if;
643
      rx <= rxin; eu <= euin;
644
-- pragma translate_off
645
        if DEBUGFPU then
646
          if (rfi1.wren = '1') then
647
            print("0x" & tosth(cpi.wr.pc(31 downto 2) & "00") & ": %f" &
648
                tostd(rfi1.wraddr(3 downto 0) & '0') &
649
                " = " & tosth(rfi1.wrdata(31 downto 0)));
650
          end if;
651
          if (rfi2.wren = '1') then
652
            print("0x" & tosth(cpi.wr.pc(31 downto 2) & "00") & ": %f" &
653
                tostd(rfi1.wraddr(3 downto 0) & '1') &
654
                " = " & tosth(rfi2.wrdata(31 downto 0)));
655
          end if;
656
        end if;
657
-- pragma translate_on
658
    end if;
659
  end process;
660
 
661
 
662
-- regfile
663
 
664
  rf0: regfile_cp generic map (4, 32, 16)
665
       port map (rst, clk, rfi1, rfo1);
666
 
667
  rf1: regfile_cp generic map (4, 32, 16)
668
       port map (rst, clk, rfi2, rfo2);
669
 
670
  fpu0 : fpu_core port map (
671
      clk   => clk,
672
      fpui.FpInst     => eui.opcode,
673
      fpui.FpOp       => eui.start,
674
      fpui.FpLd       => eui.load,
675
      fpui.Reset      => eui.flush,
676
      fpui.fprf_dout1 => eui.op1,
677
      fpui.fprf_dout2 => eui.op2,
678
      fpui.RoundingMode => rx.csr.rd,
679
      fpui.ss_scan_mode => gnd,
680
      fpui.fp_ctl_scan_in => gnd,
681
      fpui.fpuholdn => gnd,
682
      fpuo.FpBusy    => euo.busy,
683
      fpuo.FracResult => euo.res(51 downto 0),
684
      fpuo.ExpResult  => euo.res(62 downto 52),
685
      fpuo.SignResult => euo.res(63),
686
      fpuo.SNnotDB    => snnotdb,
687
      fpuo.Excep      => euo.exc,
688
      fpuo.ConditionCodes => euo.cc,
689
      fpuo.fp_ctl_scan_out => fp_ctl_scan_out);
690
 
691
end;
692
 
693
 

powered by: WebSVN 2.1.0

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