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

Subversion Repositories core_arm

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

powered by: WebSVN 2.1.0

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