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

Subversion Repositories mips_enhanced

[/] [mips_enhanced/] [trunk/] [grlib-gpl-1.0.19-b3188/] [lib/] [gaisler/] [leon3/] [dcache.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dimamali
------------------------------------------------------------------------------
2
--  This file is a part of the GRLIB VHDL IP LIBRARY
3
--  Copyright (C) 2003, Gaisler Research
4
--
5
--  This program is free software; you can redistribute it and/or modify
6
--  it under the terms of the GNU General Public License as published by
7
--  the Free Software Foundation; either version 2 of the License, or
8
--  (at your option) any later version.
9
--
10
--  This program is distributed in the hope that it will be useful,
11
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
--  GNU General Public License for more details.
14
--
15
--  You should have received a copy of the GNU General Public License
16
--  along with this program; if not, write to the Free Software
17
--  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
18
-----------------------------------------------------------------------------   
19
-- Entity:      dcache
20
-- File:        dcache.vhd
21
-- Author:      Jiri Gaisler - Gaisler Research
22
-- Modified:    Edvin Catovic - Gaisler Research
23
-- Description: This unit implements the data cache controller.
24
------------------------------------------------------------------------------  
25
 
26
library ieee;
27
use ieee.std_logic_1164.all;
28
library techmap;
29
use techmap.gencomp.all;
30
library grlib;
31
use grlib.amba.all;
32
use grlib.sparc.all;
33
use grlib.stdlib.all;
34
library gaisler;
35
use gaisler.libiu.all;
36
use gaisler.libcache.all;
37
 
38
entity dcache is
39
  generic (
40
    dsu       : integer range 0 to 1  := 0;
41
    dcen      : integer range 0 to 1  := 0;
42
    drepl     : integer range 0 to 2  := 0;
43
    dsets     : integer range 1 to 4  := 1;
44
    dlinesize : integer range 4 to 8  := 4;
45
    dsetsize  : integer range 1 to 256 := 1;
46
    dsetlock  : integer range 0 to 1  := 0;
47
    dsnoop    : integer range 0 to 6 := 0;
48
    dlram      : integer range 0 to 1 := 0;
49
    dlramsize  : integer range 1 to 512 := 1;
50
    dlramstart : integer range 0 to 255 := 16#8f#;
51
    ilram      : integer range 0 to 1 := 0;
52
    ilramstart : integer range 0 to 255 := 16#8e#;
53
    memtech    : integer range 0 to NTECH := 0;
54
    cached     : integer := 0);
55
  port (
56
    rst : in  std_ulogic;
57
    clk : in  std_ulogic;
58
    dci : in  dcache_in_type;
59
    dco : out dcache_out_type;
60
    ico : in  icache_out_type;
61
    mcdi : out memory_dc_in_type;
62
    mcdo : in  memory_dc_out_type;
63
    ahbsi : in  ahb_slv_in_type;
64
    dcrami : out dcram_in_type;
65
    dcramo : in  dcram_out_type;
66
    fpuholdn : in  std_ulogic;
67
    sclk : in std_ulogic
68
);
69
end;
70
 
71
architecture rtl of dcache is
72
 
73
 
74
constant DLINE_BITS   : integer := log2(dlinesize);
75
constant DOFFSET_BITS : integer := 8 +log2(dsetsize) - DLINE_BITS;
76
constant LRR_BIT      : integer := TAG_HIGH + 1;
77
constant TAG_LOW    : integer := DOFFSET_BITS + DLINE_BITS + 2;
78
 
79
constant OFFSET_HIGH: integer := TAG_LOW - 1;
80
constant OFFSET_LOW : integer := DLINE_BITS + 2;
81
constant LINE_HIGH  : integer := OFFSET_LOW - 1;
82
constant LINE_LOW   : integer := 2;
83
constant LINE_ZERO  : std_logic_vector(DLINE_BITS-1 downto 0) := (others => '0');
84
constant SETBITS : integer := log2x(DSETS);
85
constant DLRUBITS  : integer := lru_table(DSETS);
86
constant LOCAL_RAM_START : std_logic_vector(7 downto 0) := conv_std_logic_vector(dlramstart, 8);
87
constant ILRAM_START : std_logic_vector(7 downto 0) := conv_std_logic_vector(ilramstart, 8);
88
constant DREAD_FAST  : boolean := false;
89
constant DWRITE_FAST  : boolean := false;
90
constant DEST_RW      : boolean := (syncram_dp_dest_rw_collision(memtech) = 1);
91
 
92
type rdatatype is (dtag, ddata, dddata, icache, memory, sysr);  -- sources during cache read
93
type vmasktype is (clearone, clearall, merge, tnew);    -- valid bits operation
94
 
95
type valid_type is array (0 to DSETS-1) of std_logic_vector(dlinesize - 1 downto 0);
96
 
97
type write_buffer_type is record                        -- write buffer 
98
  addr, data1, data2 : std_logic_vector(31 downto 0);
99
  size : std_logic_vector(1 downto 0);
100
  asi  : std_logic_vector(3 downto 0);
101
  read : std_ulogic;
102
  lock : std_ulogic;
103
end record;
104
 
105
type dcache_control_type is record                      -- all registers
106
  read : std_ulogic;                                    -- access direction
107
  size : std_logic_vector(1 downto 0);                   -- access size
108
  req, burst, holdn, nomds, stpend  : std_ulogic;
109
  xaddress : std_logic_vector(31 downto 0);              -- common address buffer
110
  faddr : std_logic_vector(DOFFSET_BITS - 1 downto 0);   -- flush address
111
  valid : valid_type; --std_logic_vector(dlinesize - 1 downto 0);       -- registered valid bits
112
  dstate : std_logic_vector(2 downto 0);                 -- FSM vector
113
  hit : std_ulogic;
114
  flush         : std_ulogic;                           -- flush in progress
115
  flush2        : std_ulogic;                           -- flush in progress
116
  mexc          : std_ulogic;                           -- latched mexc
117
  wb            : write_buffer_type;                    -- write buffer
118
  asi           : std_logic_vector(3 downto 0);
119
  icenable      : std_ulogic;                           -- icache diag access
120
  rndcnt        : std_logic_vector(log2x(DSETS)-1 downto 0); -- replace counter
121
  setrepl       : std_logic_vector(log2x(DSETS)-1 downto 0); -- set to replace
122
  lrr           : std_ulogic;
123
  dsuset        : std_logic_vector(log2x(DSETS)-1 downto 0);
124
  lock          : std_ulogic;
125
  lramrd : std_ulogic;
126
  ilramen : std_ulogic;
127
  cctrl         : cctrltype;
128
  cctrlwr       : std_ulogic;
129
  forcemiss     : std_ulogic;
130
end record;
131
 
132
type snoop_reg_type is record                   -- snoop control registers
133
  snoop   : std_ulogic;                         -- snoop access to tags
134
  writebp : std_logic_vector(0 to DSETS-1);              -- snoop write bypass
135
  addr    : std_logic_vector(TAG_HIGH downto OFFSET_LOW);-- snoop tag
136
  readbpx  : std_logic_vector(0 to DSETS-1);  -- possible write/read contention    
137
end record;
138
 
139
type snoop_hit_bits_type is array (0 to 2**DOFFSET_BITS-1) of std_logic_vector(0 to DSETS-1);
140
 
141
type snoop_hit_reg_type is record
142
  hit     : snoop_hit_bits_type;                              -- snoop hit bits  
143
  taddr   : std_logic_vector(OFFSET_HIGH downto OFFSET_LOW);  -- saved tag address
144
  set     : std_logic_vector(log2x(DSETS)-1 downto 0);        -- saved set
145
end record;
146
 
147
 
148
subtype lru_type is std_logic_vector(DLRUBITS-1 downto 0);
149
type lru_array  is array (0 to 2**DOFFSET_BITS-1) of lru_type;  -- lru registers
150
type par_type is array (0 to DSETS-1) of std_logic_vector(1 downto 0);
151
 
152
type lru_reg_type is record
153
  write : std_ulogic;
154
  waddr : std_logic_vector(DOFFSET_BITS-1 downto 0);
155
  set   :  std_logic_vector(SETBITS-1 downto 0); --integer range 0 to DSETS-1;
156
  lru   : lru_array;
157
end record;
158
 
159
 
160
subtype lock_type is std_logic_vector(0 to DSETS-1);
161
 
162
function lru_set (lru : lru_type; lock : lock_type) return std_logic_vector is
163
variable xlru : std_logic_vector(4 downto 0);
164
variable set  : std_logic_vector(SETBITS-1 downto 0);
165
variable xset : std_logic_vector(1 downto 0);
166
variable unlocked : integer range 0 to DSETS-1;
167
begin
168
  set := (others => '0'); xlru := (others => '0'); xset := (others => '0');
169
  xlru(DLRUBITS-1 downto 0) := lru;
170
 
171
  if dsetlock = 1 then
172
    unlocked := DSETS-1;
173
    for i in DSETS-1 downto 0 loop
174
      if lock(i) = '0' then unlocked := i; end if;
175
    end loop;
176
  end if;
177
 
178
  case DSETS is
179
  when 2 =>
180
    if dsetlock = 1 then
181
      if lock(0) = '1' then xset(0) := '1'; else xset(0) := xlru(0); end if;
182
    else xset(0) := xlru(0); end if;
183
  when 3 =>
184
    if dsetlock = 1 then
185
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (unlocked), 2);
186
    else
187
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (0), 2);
188
    end if;
189
  when 4 =>
190
    if dsetlock = 1 then
191
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (unlocked), 2);
192
    else
193
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (0), 2);
194
    end if;
195
  when others =>
196
  end case;
197
  set := xset(SETBITS-1 downto 0);
198
  return(set);
199
end;
200
 
201
function lru_calc (lru : lru_type; set : integer) return lru_type is
202
variable new_lru : lru_type;
203
variable xnew_lru: std_logic_vector(4 downto 0);
204
variable xlru : std_logic_vector(4 downto 0);
205
begin
206
  new_lru := (others => '0'); xnew_lru := (others => '0');
207
  xlru := (others => '0'); xlru(DLRUBITS-1 downto 0) := lru;
208
  case DSETS is
209
  when 2 =>
210
    if set = 0 then xnew_lru(0) := '1'; else xnew_lru(0) := '0'; end if;
211
  when 3 =>
212
    xnew_lru(2 downto 0) := lru_3set_table(conv_integer(lru))(set);
213
  when 4 =>
214
    xnew_lru(4 downto 0) := lru_4set_table(conv_integer(lru))(set);
215
  when others =>
216
  end case;
217
  new_lru := xnew_lru(DLRUBITS-1 downto 0);
218
  return(new_lru);
219
end;
220
 
221
subtype word is std_logic_vector(31 downto 0);
222
 
223
signal r, c : dcache_control_type;      -- r is registers, c is combinational
224
signal rs, cs : snoop_reg_type;         -- rs is registers, cs is combinational
225
signal rh, ch : snoop_hit_reg_type;     -- rs is registers, cs is combinational
226
signal rl, cl : lru_reg_type;           -- rl is registers, cl is combinational
227
 
228
constant ctbl : std_logic_vector(15 downto 0) :=  conv_std_logic_vector(cached, 16);
229
 
230
begin
231
 
232
  dctrl : process(rst, r, rs, rh, rl, dci, mcdo, ico, dcramo, ahbsi, fpuholdn)
233
  variable dcramov : dcram_out_type;
234
  variable rdatasel : rdatatype;
235
  variable maddress : std_logic_vector(31 downto 0);
236
  variable maddrlow : std_logic_vector(1 downto 0);
237
  variable edata : std_logic_vector(31 downto 0);
238
  variable size : std_logic_vector(1 downto 0);
239
  variable read : std_ulogic;
240
  variable twrite, tdiagwrite, ddiagwrite, dwrite : std_ulogic;
241
  variable taddr : std_logic_vector(OFFSET_HIGH  downto LINE_LOW); -- tag address
242
  variable newtag : std_logic_vector(TAG_HIGH  downto TAG_LOW); -- new tag
243
  variable align_data : std_logic_vector(31 downto 0); -- aligned data
244
--  variable ddatain : std_logic_vector(31 downto 0);
245
  variable ddatainv, rdatav, align_datav : cdatatype;
246
 
247
  variable vmaskraw : std_logic_vector((dlinesize -1) downto 0);
248
  variable vmask : valid_type; --std_logic_vector((dlinesize -1) downto 0);
249
  variable ivalid : std_logic_vector((dlinesize -1) downto 0);
250
  variable vmaskdbl : std_logic_vector((dlinesize/2 -1) downto 0);
251
  variable enable, senable, scanen : std_logic_vector(0 to 3);
252
  variable mds : std_ulogic;
253
  variable mexc : std_ulogic;
254
  variable hit, valid, validraw, forcemiss : std_ulogic;
255
  variable flush    : std_ulogic;
256
  variable iflush   : std_ulogic;
257
  variable v : dcache_control_type;
258
  variable eholdn : std_ulogic;                         -- external hold
259
  variable snoopwe  : std_ulogic;
260
  variable hcache   : std_ulogic;
261
  variable lramcs, lramen, lramrd, lramwr, ilramen  : std_ulogic;
262
  variable snoopaddr: std_logic_vector(OFFSET_HIGH downto OFFSET_LOW);
263
  variable vs : snoop_reg_type;
264
  variable vh : snoop_hit_reg_type;
265
  variable dsudata   : std_logic_vector(31 downto 0);
266
  variable set : integer range 0 to DSETS-1;
267
  variable ddset : integer range 0 to MAXSETS-1;
268
  variable snoopset : integer range 0 to DSETS-1;
269
  variable validv, hitv, validrawv : std_logic_vector(0 to MAXSETS-1);
270
  variable csnoopwe : std_logic_vector(0 to MAXSETS-1);
271
  variable ctwrite, cdwrite : std_logic_vector(0 to MAXSETS-1);
272
  variable vset, setrepl  : std_logic_vector(log2x(DSETS)-1 downto 0);
273
  variable wlrr : std_logic_vector(0 to 3);
274
  variable vl : lru_reg_type;
275
  variable diagset : std_logic_vector(TAG_LOW + SETBITS -1 downto TAG_LOW);
276
  variable lock : std_logic_vector(0 to DSETS-1);
277
  variable wlock : std_logic_vector(0 to MAXSETS-1);
278
  variable snoophit : std_logic_vector(0 to DSETS-1);
279
  variable snoopval : std_ulogic;
280
  variable snoopset2 : integer range 0 to DSETS-1;
281
  variable laddr : std_logic_vector(31  downto 0); -- local ram addr
282
  variable tag : cdatatype; --std_logic_vector(31  downto 0);
283
  variable rlramrd : std_ulogic;
284
  variable readbp : std_logic_vector(0 to DSETS-1);
285
  variable rbphit, sidle : std_logic;
286
 
287
  begin
288
 
289
-- init local variables
290
 
291
    v := r; vs := rs; vh := rh; dcramov := dcramo; vl := rl;
292
    vl.write := '0'; lramen := '0'; lramrd := '0'; lramwr := '0';
293
    lramcs := '0'; laddr := (others => '0'); v.cctrlwr := '0';
294
    ilramen := '0'; sidle := '0';
295
 
296
    if ((dci.eenaddr or dci.enaddr) = '1') or (r.dstate /= "000") or
297
       ((dsu = 1) and (dci.dsuen = '1')) or (r.flush = '1') or
298
        (is_fpga(memtech) = 1)
299
    then
300
      enable := (others => '1');
301
    else enable := (others => '0'); end if;
302
 
303
    mds := '1'; dwrite := '0'; twrite := '0';
304
    ddiagwrite := '0'; tdiagwrite := '0'; v.holdn := '1'; mexc := '0';
305
    flush := '0'; v.icenable := '0'; iflush := '0';
306
    eholdn := ico.hold and fpuholdn; ddset := 0; vset := (others => '0');
307
    vs.snoop := '0'; vs.writebp := (others => '0'); snoopwe := '0';
308
    snoopaddr := ahbsi.haddr(OFFSET_HIGH downto OFFSET_LOW);
309
    hcache := '0';
310
    validv := (others => '0'); validrawv := (others => '0');
311
    hitv := (others => '0'); ivalid := (others => '0');
312
    if (dlram = 1) then rlramrd := r.lramrd; else rlramrd := '0'; end if;
313
    ddatainv := (others => (others => '0')); tag := (others => (others => '0'));
314
    v.flush2 := r.flush;
315
    rdatasel := ddata;  -- read data from cache as default
316
    vs.readbpx := (others => '0'); rbphit := '0';
317
    senable := (others => '0'); scanen := (others => mcdo.scanen);
318
 
319
    set := 0; snoopset := 0;  csnoopwe := (others => '0');
320
    ctwrite := (others => '0'); cdwrite := (others => '0');
321
    wlock := (others => '0');
322
    for i in 0 to DSETS-1 loop wlock(i) := dcramov.tag(i)(CTAG_LOCKPOS); end loop;
323
    wlrr := (others => '0');
324
    for i in 0 to 3 loop wlrr(i) := dcramov.tag(i)(CTAG_LRRPOS); end loop;
325
 
326
    if (DSETS > 1) then setrepl := r.setrepl; else setrepl := (others => '0'); end if;
327
 
328
-- random replacement counter
329
    if DSETS > 1 then
330
      if conv_integer(r.rndcnt) = (DSETS - 1) then v.rndcnt := (others => '0');
331
      else v.rndcnt := r.rndcnt + 1; end if;
332
    end if;
333
 
334
-- generate lock bits
335
    lock := (others => '0');
336
    if dsetlock = 1 then
337
      for i in 0 to DSETS-1 loop lock(i) := dcramov.tag(i)(CTAG_LOCKPOS); end loop;
338
    end if;
339
 
340
-- AHB snoop handling
341
 
342
    if (DSNOOP /= 0) then
343
 
344
      -- snoop on NONSEQ or SEQ and first word in cache line
345
      -- do not snoop during own transfers or during cache flush
346
      if (ahbsi.hready and ahbsi.hwrite and not mcdo.bg) = '1' and
347
         ((ahbsi.htrans = HTRANS_NONSEQ) or
348
            ((ahbsi.htrans = HTRANS_SEQ) and
349
             (ahbsi.haddr(LINE_HIGH downto LINE_LOW) = LINE_ZERO)))
350
      then
351
        vs.snoop := r.cctrl.dsnoop; -- and hcache;
352
        vs.addr := ahbsi.haddr(TAG_HIGH downto OFFSET_LOW);
353
      end if;
354
 
355
      for i in 0 to DSETS-1 loop senable(i) := vs.snoop or rs.snoop; end loop;
356
 
357
      readbp := (others => '0');
358
      if (r.xaddress(TAG_HIGH downto OFFSET_LOW) = rs.addr(TAG_HIGH downto OFFSET_LOW)) then rbphit := '1'; end if;
359
      for i in 0 to DSETS-1 loop
360
        if (rs.readbpx(i) and rbphit) = '1' then readbp(i) := '1'; end if;
361
      end loop;
362
 
363
      -- clear valid bits on snoop hit (or set hit bits)
364
      for i in DSETS-1 downto 0 loop
365
        if ((rs.snoop and (not mcdo.ba) and not r.flush) = '1')
366
          and ((dcramov.stag(i)(TAG_HIGH downto TAG_LOW) = rs.addr(TAG_HIGH downto TAG_LOW)) or (readbp(i) = '1'))
367
        then
368
          if DSNOOP = 2 then
369
            vh.hit(conv_integer(rs.addr(OFFSET_HIGH downto OFFSET_LOW)))(i) := '1';
370
--             vh.set := std_logic_vector(conv_unsigned(i, SETBITS));
371
          else
372
            snoopaddr := rs.addr(OFFSET_HIGH downto OFFSET_LOW);
373
            snoopwe := '1'; snoopset := i;
374
          end if;
375
        end if;
376
      -- bypass tag data on read/write contention
377
        if (DSNOOP /= 2) and (rs.writebp(i) = '1') then
378
          dcramov.tag(i)(TAG_HIGH downto TAG_LOW) := rs.addr(TAG_HIGH downto TAG_LOW);
379
          dcramov.tag(i)(dlinesize-1 downto 0) := zero32(dlinesize-1 downto 0);
380
        end if;
381
      end loop;
382
    end if;
383
 
384
-- generate access parameters during pipeline stall
385
 
386
    if ((r.holdn) = '0') or ((dsu = 1) and (dci.dsuen = '1')) then
387
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
388
    elsif ((dci.enaddr and not dci.read) = '1') or (eholdn = '0')
389
    then
390
      taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW);
391
    else
392
      taddr := dci.eaddress(OFFSET_HIGH downto LINE_LOW);
393
    end if;
394
 
395
    if (dci.write or not r.holdn) = '1' then
396
      maddress := r.xaddress(31 downto 0);
397
      read := r.read; size := r.size; edata := dci.maddress;
398
    else
399
      maddress := dci.maddress(31 downto 0);
400
      read := dci.read; size := dci.size; edata := dci.edata;
401
    end if;
402
 
403
    newtag := dci.maddress(TAG_HIGH downto TAG_LOW);
404
    vl.waddr := maddress(OFFSET_HIGH downto OFFSET_LOW);  -- lru write address
405
 
406
-- generate cache hit and valid bits
407
 
408
    if cached /= 0 then hcache := ctbl(conv_integer(dci.maddress(31 downto 28)));
409
    else hcache := '1'; end if;
410
 
411
    forcemiss := not dci.asi(3); hit := '0'; set := 0; snoophit := (others => '0');
412
    snoopval := '1';
413
    for i in DSETS-1 downto 0 loop
414
      if DSNOOP = 2 then
415
        snoophit(i) := rh.hit(conv_integer(rh.taddr))(i);
416
      end if;
417
      if (dcramov.tag(i)(TAG_HIGH downto TAG_LOW) = dci.maddress(TAG_HIGH downto TAG_LOW))
418
      then hitv(i) := hcache; end if;
419
      validrawv(i) := hitv(i) and (not r.flush) and (not r.flush2) and (not snoophit(i)) and
420
        genmux(dci.maddress(LINE_HIGH downto LINE_LOW), dcramov.tag(i)(dlinesize-1 downto 0));
421
      validv(i) :=  validrawv(i);
422
      snoopval := snoopval and not snoophit(i);
423
    end loop;
424
 
425
    hit := orv(hitv) and not r.flush and not r.flush2; validraw := orv(validrawv);
426
    valid := orv(validv);
427
    if DSETS > 1 then
428
      for i in DSETS-1 downto 0 loop
429
        if (hitv(i) = '1') then
430
          vset := conv_std_logic_vector(i, SETBITS);
431
        end if;
432
      end loop;
433
      set := conv_integer(vset);
434
      if rlramrd = '1' then set := 1; end if;
435
    else set := 0; end if;
436
 
437
    if (dci.dsuen = '1') then diagset := r.xaddress(TAG_LOW+SETBITS-1 downto TAG_LOW);
438
    else diagset := maddress(TAG_LOW + SETBITS - 1 downto TAG_LOW); end if;
439
    case DSETS is
440
    when 1 => ddset := 0;
441
    when 3 => if conv_integer(diagset) < 3 then ddset := conv_integer(diagset); end if;
442
    when others => ddset := conv_integer(diagset);
443
    end case;
444
 
445
    if ((r.holdn and dci.enaddr) = '1')  and (r.dstate = "000") then
446
        v.hit := hit; v.xaddress := dci.maddress;
447
        v.read := dci.read; v.size := dci.size;
448
        v.asi := dci.asi(3 downto 0);
449
    end if;
450
 
451
-- Store buffer
452
 
453
--    wdata := r.wb.data1;
454
    if mcdo.ready = '1' then
455
      v.wb.addr(2) := r.wb.addr(2) or (r.wb.size(0) and r.wb.size(1));
456
      if r.stpend = '1' then
457
        v.stpend := r.req; v.wb.data1 := r.wb.data2;
458
        v.wb.lock := r.wb.lock and r.req;
459
      end if;
460
    end if;
461
    if mcdo.grant = '1' then v.req := r.burst; v.burst := '0'; end if;
462
    if (mcdo.grant and not r.wb.read and r.req) = '1' then v.wb.lock := '0'; end if;
463
 
464
    if (dlram = 1) then
465
      if ((r.holdn) = '0') or ((dsu = 1) and (dci.dsuen = '1')) then
466
        laddr := r.xaddress;
467
      elsif ((dci.enaddr and not dci.read) = '1') or (eholdn = '0') then
468
        laddr := dci.maddress;
469
      else laddr := dci.eaddress; end if;
470
      if  (dci.enaddr = '1') and (dci.maddress(31 downto 24) = LOCAL_RAM_START)
471
      then lramen := '1'; end if;
472
      if  ((laddr(31 downto 24) = LOCAL_RAM_START)) or ((dci.dsuen = '1') and (dci.asi(4 downto 1) = "0101"))
473
      then lramcs := '1'; end if;
474
    end if;
475
 
476
    if (ilram = 1) then
477
      if  (dci.enaddr = '1') and (dci.maddress(31 downto 24) = ILRAM_START)  then ilramen := '1'; end if;
478
    end if;
479
 
480
    -- cache freeze operation
481
    if (r.cctrl.ifrz and dci.intack and r.cctrl.ics(0)) = '1' then
482
      v.cctrl.ics := "01";
483
    end if;
484
    if (r.cctrl.dfrz and dci.intack and r.cctrl.dcs(0)) = '1' then
485
      v.cctrl.dcs := "01";
486
    end if;
487
 
488
    if r.cctrlwr = '1' then
489
    if (r.xaddress(7 downto 2) = "000000") and (dci.read = '0') then
490
      v.cctrl.dsnoop := dci.maddress(23);
491
      flush        := dci.maddress(22);
492
      iflush       := dci.maddress(21);
493
      v.cctrl.burst:= dci.maddress(16);
494
      v.cctrl.dfrz := dci.maddress(5);
495
      v.cctrl.ifrz := dci.maddress(4);
496
      v.cctrl.dcs  := dci.maddress(3 downto 2);
497
      v.cctrl.ics  := dci.maddress(1 downto 0);
498
    end if;
499
    end if;
500
 
501
-- main Dcache state machine
502
 
503
    case r.dstate is
504
    when "000" =>                       -- Idle state
505
      v.nomds := r.nomds and not eholdn;
506
      v.forcemiss := forcemiss; sidle := '1';
507
      if (snoopval = '1') then
508
        for i in 0 to DSETS-1 loop
509
          v.valid(i) := dcramov.tag(i)(dlinesize-1 downto 0);
510
        end loop;
511
      else v.valid := (others => (others => '0')); end if;
512
      if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1') then -- wait for store queue
513
        v.wb.addr := dci.maddress; v.wb.size := dci.size;
514
        v.wb.read := dci.read; v.wb.data1 := dci.edata; v.wb.lock := dci.lock;
515
        v.wb.asi := dci.asi(3 downto 0);
516
      end if;
517
      if (eholdn and (not r.nomds)) = '1' then -- avoid false path through nullify
518
        case dci.asi(4 downto 0) is
519
        when ASI_SYSR => rdatasel := sysr;
520
        when ASI_DTAG => rdatasel := dtag;
521
        when ASI_DDATA => rdatasel := dddata;
522
        when others =>
523
        end case;
524
      end if;
525
      if (dci.enaddr and eholdn and (not r.nomds) and not dci.nullify) = '1' then
526
        case dci.asi(4 downto 0) is
527
        when ASI_SYSR =>                -- system registers
528
          if (dsu = 0) or (dci.dsuen = '0') then
529
            if (dci.maddress(7 downto 2) = "000000") and (dci.read = '0') then
530
              v.cctrl.dsnoop := dci.edata(23);
531
              flush        := dci.edata(22);
532
              iflush       := dci.edata(21);
533
              v.cctrl.burst:= dci.edata(16);
534
              v.cctrl.dfrz := dci.edata(5);
535
              v.cctrl.ifrz := dci.edata(4);
536
              v.cctrl.dcs  := dci.edata(3 downto 2);
537
              v.cctrl.ics  := dci.edata(1 downto 0);
538
            end if;
539
          else
540
            v.cctrlwr := not dci.read;
541
          end if;
542
        when ASI_ITAG | ASI_IDATA =>            -- Read/write Icache tags
543
          if ico.flush = '1' then mexc := '1';
544
          else v.dstate := "101"; v.holdn := dci.dsuen; end if;
545
        when ASI_UINST | ASI_SINST =>
546
          if (ilram = 1) then v.dstate := "101"; v.ilramen := '1'; end if;
547
        when ASI_IFLUSH =>              -- flush instruction cache
548
          if dci.read = '0' then iflush := '1'; end if;
549
        when ASI_DFLUSH =>              -- flush data cache
550
          if dci.read = '0' then flush := '1'; end if;
551
        when ASI_DDATA =>               -- Read/write Dcache data
552
          if (dci.size /= "10") or (r.flush = '1') then -- only word access is allowed
553
            mexc := '1';
554
          elsif (dci.read = '0') then
555
            dwrite := '1'; ddiagwrite := '1';
556
          end if;
557
        when ASI_DTAG =>                -- Read/write Dcache tags
558
          if (dci.size /= "10") or (r.flush = '1') then -- allow only word access
559
            mexc := '1';
560
          elsif (dci.read = '0') then
561
            twrite := '1'; tdiagwrite := '1';
562
          end if;
563
        when others =>
564
--          setrepl := std_logic_vector(conv_unsigned(set, SETBITS));
565
          if dci.read = '1' then        -- read access
566
            if (dlram = 1) and (lramen = '1') then
567
              lramrd := '1';
568
            elsif (ilram = 1) and (ilramen = '1') then
569
              if (ico.flush = '1') or (dci.size /= "10") then mexc := '1';
570
              else v.dstate := "101"; v.holdn := dci.dsuen; v.ilramen := '1'; end if;
571
            elsif dci.dsuen = '0' then
572
              if (not ((r.cctrl.dcs(0) = '1') and ((hit and valid and not forcemiss) = '1')))
573
              then      -- read miss
574
                v.holdn := '0'; v.dstate := "001";
575
                if ((r.stpend  = '0') or ((mcdo.ready and not r.req) = '1'))
576
                then    -- wait for store queue
577
                  v.req := '1';
578
                  v.burst := dci.size(1) and dci.size(0) and not dci.maddress(2);
579
                end if;
580
              else       -- read hit
581
                if (DSETS > 1) and (drepl = lru) then vl.write := '1'; end if;
582
              end if;
583
            end if;
584
 
585
          else                  -- write access
586
            if (dlram = 1) and (lramen = '1') then
587
              lramwr := '1';
588
              if (dci.size = "11") then -- double store
589
                v.dstate := "100"; v.xaddress(2) := '1';
590
              end if;
591
            elsif (ilram = 1) and (ilramen = '1') then
592
              if (ico.flush = '1') or (dci.size /= "10") then mexc := '1';
593
              else v.dstate := "101"; v.holdn := dci.dsuen; v.ilramen := '1'; end if;
594
            elsif dci.dsuen = '0' then
595
              if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1') then     -- wait for store queue
596
                v.req := '1'; v.stpend := '1';
597
                v.burst := dci.size(1) and dci.size(0);
598
                if (dci.size = "11") then v.dstate := "100"; end if; -- double store
599
              else              -- wait for store queue
600
                v.dstate := "110"; v.holdn := '0';
601
              end if;
602
--          if (r.cctrl.dcs(0) = '1') and ((hit and (dci.size(1) or validraw)) = '1') 
603
              if (r.cctrl.dcs(0) = '1') and (((hit and dci.size(1)) or validraw) = '1')
604
              then  -- write hit
605
 
606
                twrite := '1'; dwrite := '1';
607
                if (DSETS > 1) and (drepl = lru) then vl.write := '1'; end if;
608
                setrepl := conv_std_logic_vector(set, SETBITS);
609
                if DSNOOP /= 0 then
610
                  if ((dci.enaddr and not dci.read) = '1') or (eholdn = '0')
611
                  then v.xaddress := dci.maddress; else v.xaddress := dci.eaddress; end if;
612
                  vs.readbpx(set) := '1';
613
                end if;
614
              end if;
615
              if (dci.size = "11") then v.xaddress(2) := '1'; end if;
616
            end if;
617
          end if;
618
 
619
          if (DSETS > 1) then
620
            vl.set := conv_std_logic_vector(set, SETBITS);
621
            v.setrepl := conv_std_logic_vector(set, SETBITS);
622
            if ((not hit) and (not r.flush)) = '1' then
623
              case drepl is
624
              when rnd =>
625
                if dsetlock = 1 then
626
                  if lock(conv_integer(r.rndcnt)) = '0' then v.setrepl := r.rndcnt;
627
                  else
628
                    v.setrepl := conv_std_logic_vector(DSETS-1, SETBITS);
629
                    for i in DSETS-1 downto 0 loop
630
                      if (lock(i) = '0') and (i>conv_integer(r.rndcnt)) then
631
                        v.setrepl := conv_std_logic_vector(i, SETBITS);
632
                      end if;
633
                    end loop;
634
                  end if;
635
                else
636
                  v.setrepl := r.rndcnt;
637
                end if;
638
              when lru =>
639
                v.setrepl := lru_set(rl.lru(conv_integer(dci.maddress(OFFSET_HIGH downto OFFSET_LOW))), lock(0 to DSETS-1));
640
              when lrr =>
641
                v.setrepl := (others => '0');
642
                if dsetlock = 1 then
643
                  if lock(0) = '1' then v.setrepl(0) := '1';
644
                  else
645
                    v.setrepl(0) := dcramov.tag(0)(CTAG_LRRPOS) xor dcramov.tag(1)(CTAG_LRRPOS);
646
                  end if;
647
                else
648
                  v.setrepl(0) := dcramov.tag(0)(CTAG_LRRPOS) xor dcramov.tag(1)(CTAG_LRRPOS);
649
                end if;
650
                if v.setrepl(0) = '0' then
651
                  v.lrr := not dcramov.tag(0)(CTAG_LRRPOS);
652
                else
653
                  v.lrr := dcramov.tag(0)(CTAG_LRRPOS);
654
                end if;
655
              end case;
656
            end if;
657
 
658
            if (dsetlock = 1) then
659
              if (hit and lock(set)) = '1' then v.lock := '1';
660
              else v.lock := '0'; end if;
661
            end if;
662
 
663
          end if;
664
 
665
        end case;
666
      end if;
667
    when "001" =>               -- read miss, wait for memory data
668
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
669
      newtag := r.xaddress(TAG_HIGH downto TAG_LOW);
670
      v.nomds := r.nomds and not eholdn;
671
      v.holdn := v.nomds; rdatasel := memory;
672
      for i in 0 to DSETS-1 loop wlock(i) := r.lock; end loop;
673
      for i in 0 to 3 loop wlrr(i) := r.lrr; end loop;
674
      if r.stpend = '0' then
675
 
676
        if mcdo.ready = '1' then
677
          mds := r.holdn or r.nomds; v.xaddress(2) := '1'; v.holdn := '1';
678
          if (r.cctrl.dcs = "01") then
679
            v.hit := mcdo.cache and r.hit; twrite := v.hit;
680
          elsif (r.cctrl.dcs(1) = '1') then
681
            v.hit := mcdo.cache and (r.hit or (r.asi(3) and not r.asi(2))); twrite := v.hit;
682
          end if;
683
          dwrite := twrite; rdatasel := memory;
684
          mexc := mcdo.mexc;
685
 
686
          if r.req = '0' then
687
 
688
            if (((dci.enaddr and not mds) = '1') or
689
              ((dci.eenaddr and mds and eholdn) = '1')) and ((r.cctrl.dcs(0) = '1') or (dlram = 1)) then
690
              v.dstate := "011"; v.holdn := '0';
691
            else v.dstate := "000"; end if;
692
          else v.nomds := '1'; end if;
693
        end if;
694
        v.mexc := mcdo.mexc; v.wb.data2 := mcdo.data;
695
      else
696
        if ((mcdo.ready and not r.req) = '1') then      -- wait for store queue
697
          v.burst := r.size(1) and r.size(0) and not r.xaddress(2);
698
          v.wb.addr := r.xaddress; v.wb.size := r.size;
699
          v.wb.read := r.read; v.wb.data1 := dci.maddress; v.req := '1';
700
          v.wb.lock := dci.lock; v.wb.asi := r.asi;
701
        end if;
702
      end if;
703
      if DSNOOP /= 0 then vs.readbpx(conv_integer(setrepl)) := '1'; end if;
704
    when "011" =>               -- return from read miss with load pending
705
      taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW);
706
      if (dlram = 1) then
707
        laddr := dci.maddress;
708
        if laddr(31 downto 24) = LOCAL_RAM_START then lramcs := '1'; end if;
709
      end if;
710
      v.dstate := "000";
711
    when "100" =>               -- second part of double store cycle
712
      v.dstate := "000";
713
      edata := dci.edata;  -- needed for STD store hit
714
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
715
      if (dlram = 1) and (rlramrd = '1') then
716
        laddr := r.xaddress; lramwr := '1';
717
      else
718
        if (r.cctrl.dcs(0) = '1') and (r.hit = '1') then dwrite := '1'; end if;
719
        v.wb.data2 := dci.edata;
720
      end if;
721
 
722
    when "101" =>               -- icache diag and inst local ram access 
723
      rdatasel := icache; v.icenable := '1'; v.holdn := dci.dsuen;
724
      if  ico.diagrdy = '1' then
725
        v.dstate := "011"; v.icenable := '0'; mds := not r.read; v.ilramen := '0';
726
      end if;
727
 
728
    when "110" =>               -- wait for store buffer to empty (store access)
729
      edata := dci.edata;  -- needed for STD store hit
730
 
731
      if ((mcdo.ready and not r.req) = '1') then        -- store queue emptied
732
 
733
        if (r.cctrl.dcs(0) = '1') and (r.hit = '1') and (r.size = "11") then  -- write hit
734
          taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); dwrite := '1';
735
        end if;
736
        v.dstate := "000";
737
 
738
        v.req := '1'; v.burst := r.size(1) and r.size(0); v.stpend := '1';
739
 
740
        v.wb.addr := r.xaddress; v.wb.size := r.size;
741
        v.wb.read := r.read; v.wb.data1 := dci.maddress;
742
        v.wb.lock := dci.lock; v.wb.data2 := dci.edata;
743
        v.wb.asi := r.asi;
744
        if r.size = "11" then v.wb.addr(2) := '0'; end if;
745
      else  -- hold cpu until buffer empty
746
        v.holdn := '0';
747
      end if;
748
    when others => v.dstate := "000";
749
    end case;
750
 
751
    if (dlram = 1) then v.lramrd := lramcs; end if; -- read local ram data 
752
 
753
-- select data to return on read access
754
-- align if byte/half word read from cache or memory.
755
 
756
    if (dsu = 1) and (dci.dsuen = '1') then
757
      v.dsuset := conv_std_logic_vector(ddset, SETBITS);
758
      case dci.asi(4 downto 0) is
759
      when ASI_ITAG | ASI_IDATA =>
760
        v.icenable := not ico.diagrdy;
761
        rdatasel := icache;
762
      when ASI_DTAG =>
763
        tdiagwrite := not dci.eenaddr and dci.enaddr and dci.write;
764
        twrite := not dci.eenaddr and dci.enaddr and dci.write;
765
        rdatasel := dtag;
766
      when ASI_DDATA =>
767
        ddiagwrite := not dci.eenaddr and dci.enaddr and dci.write;
768
        dwrite := not dci.eenaddr and dci.enaddr and dci.write;
769
        rdatasel := dddata;
770
       when ASI_UDATA | ASI_SDATA  =>
771
         lramwr := not dci.eenaddr and dci.enaddr and dci.write;
772
--       when ASI_UINST | ASI_SINST =>        
773
      when others =>
774
      end case;
775
    end if;
776
 
777
    rdatav := (others => (others => '0'));
778
    align_data := (others => '0'); align_datav := (others => (others => '0'));
779
    maddrlow := maddress(1 downto 0); -- stupid Synopsys VSS bug ...
780
 
781
    case rdatasel is
782
    when dddata =>
783
      rdatav := dcramov.data;
784
      if dci.dsuen = '1' then set := conv_integer(r.dsuset);
785
      else set := ddset; end if;
786
    when dtag =>
787
      rdatav := dcramov.tag;
788
      if dci.dsuen = '1' then set := conv_integer(r.dsuset);
789
      else set := ddset; end if;
790
    when icache =>
791
      rdatav(0) := ico.diagdata; set := 0;
792
    when ddata | memory =>
793
        if rdatasel = memory then
794
          rdatav(0) := mcdo.data; set := 0; --FIXME
795
        else
796
          for i in 0 to DSETS-1 loop rdatav(i) := dcramov.data(i); end loop;
797
        end if;
798
    when sysr =>
799
      set := 0;
800
      case dci.maddress(3 downto 2) is
801
      when "00" | "01" =>
802
        rdatav(0)(23) := r.cctrl.dsnoop;
803
        rdatav(0)(16 downto 14) := r.cctrl.burst & ico.flush & r.flush;
804
        rdatav(0)(5 downto 0) :=
805
            r.cctrl.dfrz & r.cctrl.ifrz & r.cctrl.dcs & r.cctrl.ics;
806
      when "10" =>
807
        rdatav(0) := ico.cfg;
808
      when others =>
809
        rdatav(0) := cache_cfg(drepl, dsets, dlinesize, dsetsize, dsetlock,
810
                dsnoop, dlram, dlramsize, dlramstart, 0);
811
      end case;
812
    end case;
813
 
814
-- select which data to update the data cache with
815
 
816
      for i in 0 to DSETS-1 loop
817
        case size is            -- merge data during partial write
818
        when "00" =>
819
          case maddrlow is
820
          when "00" =>
821
            ddatainv(i) := edata(7 downto 0) & dcramov.data(i)(23 downto 0);
822
          when "01" =>
823
            ddatainv(i) := dcramov.data(i)(31 downto 24) & edata(7 downto 0) &
824
                     dcramov.data(i)(15 downto 0);
825
          when "10" =>
826
            ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(7 downto 0) &
827
                     dcramov.data(i)(7 downto 0);
828
          when others =>
829
            ddatainv(i) := dcramov.data(i)(31 downto 8) & edata(7 downto 0);
830
          end case;
831
        when "01" =>
832
          if maddress(1) = '0' then
833
            ddatainv(i) := edata(15 downto 0) & dcramov.data(i)(15 downto 0);
834
          else
835
            ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(15 downto 0);
836
          end if;
837
        when others =>
838
          ddatainv(i) := edata;
839
        end case;
840
 
841
      end loop;
842
--      ddatain := ddatainv(set);
843
 
844
-- handle double load with pipeline hold
845
 
846
    if (r.dstate = "000") and (r.nomds = '1') then
847
      rdatav(0) := r.wb.data2; mexc := r.mexc; set := 0; --FIXME
848
    end if;
849
 
850
-- Handle AHB retry. Re-generate bus request and burst
851
 
852
    if mcdo.retry = '1' then
853
      v.req := '1';
854
      v.burst := r.wb.size(0) and r.wb.size(1) and not r.wb.addr(2);
855
    end if;
856
 
857
-- Generate new valid bits
858
 
859
    vmaskdbl := decode(maddress(LINE_HIGH downto LINE_LOW+1));
860
    if (size = "11") and (read = '0') then
861
      for i in 0 to (dlinesize - 1) loop vmaskraw(i) := vmaskdbl(i/2); end loop;
862
    else
863
      vmaskraw := decode(maddress(LINE_HIGH downto LINE_LOW));
864
    end if;
865
 
866
    vmask := (others => vmaskraw);
867
    if r.hit = '1' then
868
      for i in 0 to DSETS-1 loop vmask(i) := r.valid(i) or vmaskraw; end loop;
869
    end if;
870
    if r.dstate = "000" then
871
--      vmask := dcramov.dtramout(set).valid or vmaskraw;
872
      for i in 0 to DSETS-1 loop
873
        vmask(i) := dcramov.tag(i)(dlinesize-1 downto 0) or vmaskraw;
874
      end loop;
875
    else
876
      for i in 0 to DSETS-1 loop tag(i)(dlinesize-1 downto 0) := vmask(i); end loop;
877
    end if;
878
 
879
    if (mcdo.mexc or r.flush) = '1' then twrite := '0'; dwrite := '0'; end if;
880
    if twrite = '1' then
881
      v.valid := vmask;
882
      if (DSETS>1) and (drepl = lru) and (tdiagwrite = '0') then
883
        vl.write := '1'; vl.set := setrepl;
884
      end if;
885
    end if;
886
 
887
    if (DSETS>1) and (drepl = lru) and (rl.write = '1') then
888
      vl.lru(conv_integer(rl.waddr)) :=
889
        lru_calc(rl.lru(conv_integer(rl.waddr)), conv_integer(rl.set));
890
    end if;
891
 
892
    if tdiagwrite = '1' then -- diagnostic tag write
893
      if (dsu = 1) and (dci.dsuen = '1') then
894
        vmask := (others => dci.maddress(dlinesize - 1 downto 0));
895
      else
896
        vmask := (others => dci.edata(dlinesize - 1 downto 0));
897
        newtag(TAG_HIGH downto TAG_LOW) := dci.edata(TAG_HIGH downto TAG_LOW);
898
        for i in 0 to 3 loop wlrr(i)  := dci.edata(CTAG_LRRPOS); end loop;
899
        for i in 0 to DSETS-1 loop wlock(i) := dci.edata(CTAG_LOCKPOS); end loop;
900
      end if;
901
    end if;
902
 
903
-- cache flush
904
 
905
    if ((dci.flush or flush) = '1') and (dcen /= 0) then
906
      v.flush := '1'; v.faddr := (others => '0');
907
    end if;
908
 
909
    if (r.flush = '1') and (dcen /= 0) then
910
      twrite := '1'; vmask := (others => (others => '0'));
911
      v.faddr := r.faddr +1; newtag(TAG_HIGH downto TAG_LOW) := (others => '0');
912
      taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;
913
      wlrr := (others => '0');
914
      if (r.faddr(DOFFSET_BITS -1) and not v.faddr(DOFFSET_BITS -1)) = '1' then
915
        v.flush := '0';
916
      end if;
917
      if DSNOOP = 2 then
918
        vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW))) := (others => '0');
919
      end if;
920
    end if;
921
 
922
-- AHB snoop handling (2), bypass write data on read/write contention
923
 
924
    if DSNOOP /= 0 then
925
      if tdiagwrite = '1' then snoopset2 := ddset;
926
      else snoopset2 := conv_integer(setrepl); end if;
927
      if DSNOOP = 2 then
928
        vh.taddr := taddr(OFFSET_HIGH downto OFFSET_LOW);
929
        vh.set := conv_std_logic_vector(set, SETBITS);
930
        if (twrite = '1') and (r.dstate /= "000") then
931
          vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW)))(snoopset2) := '0';
932
        end if;
933
      else
934
        if rs.addr(OFFSET_HIGH  downto OFFSET_LOW) =
935
          taddr(OFFSET_HIGH  downto OFFSET_LOW)
936
        then
937
          if twrite = '0' then
938
            if snoopwe = '1' then
939
              vs.writebp(snoopset) := '1';
940
              if DEST_RW then enable(snoopset) := '0'; end if;
941
            end if;
942
          else
943
            if (snoopwe = '1') and (conv_integer(setrepl) = snoopset) then  -- avoid write/write contention
944
              twrite := '0';
945
              if DEST_RW then enable(snoopset) := '0'; end if;
946
            end if;
947
          end if;
948
        end if;
949
      end if;
950
      if (r.dstate = "001") and ((rbphit and rs.snoop) = '1') then v.hit := '0'; end if;
951
      if DEST_RW then
952
        -- disable snoop read enable on write/read contention
953
        if taddr(OFFSET_HIGH downto OFFSET_LOW) = ahbsi.haddr(OFFSET_HIGH  downto OFFSET_LOW) then
954
          for i in 0 to DSETS-1 loop
955
            if (twrite and senable(i)) = '1' then senable(i) := '0'; end if;
956
          end loop;
957
        end if;
958
      end if;
959
    end if;
960
 
961
-- update cache with memory data during read miss
962
 
963
    if read = '1' then
964
      for i in 0 to DSETS-1 loop ddatainv(i) := mcdo.data; end loop;
965
    end if;
966
 
967
-- cache write signals
968
 
969
    if twrite = '1' then
970
      if tdiagwrite = '1' then ctwrite(ddset) := '1';
971
      else ctwrite(conv_integer(setrepl)) := '1'; end if;
972
    end if;
973
    if dwrite = '1' then
974
      if ddiagwrite = '1' then cdwrite(ddset) := '1';
975
      else cdwrite(conv_integer(setrepl)) := '1'; end if;
976
    end if;
977
 
978
    csnoopwe := (others => '0');
979
    if ((snoopwe and not mcdo.scanen) = '1') then csnoopwe(snoopset) := '1'; end if;
980
 
981
     if (r.flush and twrite) = '1' then   -- flush 
982
       ctwrite := (others => '1'); wlrr := (others => '0'); wlock := (others => '0');
983
     end if;
984
 
985
     if r.flush2 = '1' then
986
      vl.lru := (others => (others => '0'));
987
    end if;
988
 
989
 
990
-- reset
991
 
992
    if rst = '0' then
993
      v.dstate := "000"; v.stpend  := '0'; v.req := '0'; v.burst := '0';
994
      v.read := '0'; v.flush := '0'; v.nomds := '0'; v.holdn := '1';
995
      v.rndcnt := (others => '0'); v.setrepl := (others => '0');
996
      v.dsuset := (others => '0'); v.flush2 := '1';
997
      v.lrr := '0'; v.lock := '0'; v.ilramen := '0';
998
      v.cctrl.dcs := "00"; v.cctrl.ics := "00";
999
      v.cctrl.burst := '0'; v.cctrl.dsnoop := '0';
1000
    end if;
1001
 
1002
    if dsnoop = 0 then v.cctrl.dsnoop := '0'; end if;
1003
 
1004
-- Drive signals
1005
 
1006
    c <= v; cs <= vs;   ch <= vh; -- register inputs
1007
    cl <= vl;
1008
 
1009
 
1010
    -- tag ram inputs
1011
    senable := senable and not scanen; enable := enable and not scanen;
1012
    if mcdo.scanen = '1' then ctwrite := (others => '0'); end if;
1013
 
1014
    for i in 0 to DSETS-1 loop
1015
      tag(i)(dlinesize-1 downto 0) := vmask(i);
1016
      tag(i)(TAG_HIGH downto TAG_LOW) := newtag(TAG_HIGH downto TAG_LOW);
1017
      tag(i)(CTAG_LRRPOS) := wlrr(i);
1018
      tag(i)(CTAG_LOCKPOS) := wlock(i);
1019
    end loop;
1020
    dcrami.tag <= tag;
1021
    dcrami.tenable   <= enable;
1022
    dcrami.twrite    <= ctwrite;
1023
    dcrami.flush    <= r.flush;
1024
    dcrami.senable <= senable;--vs.snoop or rs.snoop;
1025
    dcrami.swrite  <= csnoopwe;
1026
    dcrami.saddress(19 downto (OFFSET_HIGH - OFFSET_LOW +1)) <=
1027
        zero32(19 downto (OFFSET_HIGH - OFFSET_LOW +1));
1028
    dcrami.saddress(OFFSET_HIGH - OFFSET_LOW downto 0) <= snoopaddr;
1029
    dcrami.stag(31 downto (TAG_HIGH - TAG_LOW +1)) <=
1030
        zero32(31 downto (TAG_HIGH - TAG_LOW +1));
1031
    dcrami.stag(TAG_HIGH - TAG_LOW downto 0) <= rs.addr(TAG_HIGH downto TAG_LOW);
1032
    dcrami.tdiag <= mcdo.testen & "000";
1033
    dcrami.ddiag <= mcdo.testen & "000";
1034
 
1035
    -- data ram inputs
1036
    dcrami.denable   <= enable;
1037
    dcrami.address(19 downto (OFFSET_HIGH - LINE_LOW + 1)) <= zero32(19 downto (OFFSET_HIGH - LINE_LOW + 1));
1038
    dcrami.address(OFFSET_HIGH - LINE_LOW downto 0) <= taddr;
1039
    dcrami.data <= ddatainv;
1040
    dcrami.dwrite    <= cdwrite;
1041
    dcrami.ldramin.address(23 downto 2) <= laddr(23 downto 2);
1042
    dcrami.ldramin.enable <= (lramcs or lramwr) and not mcdo.scanen;
1043
    dcrami.ldramin.read   <= rlramrd;
1044
    dcrami.ldramin.write  <= lramwr;
1045
    dcrami.dpar <= (others => (others => '0'));
1046
    dcrami.tpar <= (others => (others => '0'));
1047
    dcrami.ctx <= (others => (others => '0'));
1048
    dcrami.ptag <= (others => (others => '0'));
1049
    dcrami.tpwrite <= (others => '0');
1050
 
1051
    -- memory controller inputs
1052
    mcdi.address  <= r.wb.addr;
1053
    mcdi.data     <= r.wb.data1;
1054
    mcdi.burst    <= r.burst;
1055
    mcdi.size     <= r.wb.size;
1056
    mcdi.read     <= r.wb.read;
1057
    mcdi.asi      <= r.wb.asi;
1058
    mcdi.lock     <= r.wb.lock;
1059
    mcdi.req      <= r.req;
1060
    mcdi.cache    <= orv(r.cctrl.dcs);
1061
 
1062
    -- diagnostic instruction cache access
1063
    dco.icdiag.flush  <= iflush;
1064
    dco.icdiag.read   <= read;
1065
    dco.icdiag.tag    <= not r.asi(0);
1066
    dco.icdiag.addr   <= r.xaddress;
1067
    dco.icdiag.enable <= r.icenable;
1068
    dco.icdiag.ilramen <= r.ilramen;
1069
    dco.icdiag.cctrl <= r.cctrl;
1070
    dco.icdiag.scanen  <= mcdo.scanen;
1071
    dco.icdiag.pflush <= '0';
1072
    dco.icdiag.ctx <= '0';
1073
    dco.icdiag.ilock <= (others => '0');
1074
    dco.icdiag.pflushaddr <= (others => '0');
1075
 
1076
    -- IU data cache inputs
1077
    dco.data <= rdatav;
1078
    dco.mexc <= mexc;
1079
    dco.set  <= conv_std_logic_vector(set, 2);
1080
    dco.hold <= r.holdn;
1081
    dco.mds  <= mds;
1082
    dco.werr <= mcdo.werr;
1083
    dco.idle <= sidle and not r.stpend;
1084
    dco.scanen <= mcdo.scanen;
1085
    dco.testen <= mcdo.testen;
1086
 
1087
  end process;
1088
 
1089
-- Local registers
1090
 
1091
    reg1 : process(clk)
1092
    begin
1093
      if rising_edge(clk) then
1094
        r <= c;
1095
        if rst = '0' then r.wb.lock <= '0'; end if;
1096
        --sync reset for wb.lock  must be generated here to make
1097
        --gate level simulations possible with some synthesis tools
1098
      end if;
1099
    end process;
1100
 
1101
    sn2 : if DSNOOP /= 0 generate
1102
      reg2 : process(sclk)
1103
      begin if rising_edge(sclk ) then rs <= cs; end if; end process;
1104
    end generate;
1105
 
1106
    nosn2 : if DSNOOP = 0 generate
1107
      rs.snoop <= '0'; rs.writebp <= (others => '0');
1108
      rs.addr <= (others => '0'); rs.readbpx <= (others => '0');
1109
    end generate;
1110
 
1111
    sn3 : if DSNOOP = 2 generate
1112
      reg3 : process(sclk)
1113
      begin if rising_edge(sclk ) then rh <= ch; end if; end process;
1114
    end generate;
1115
 
1116
    nosn3 : if DSNOOP /= 2 generate
1117
      rh.hit <=  (others => (others => '0')); rh.taddr <=  (others => '0');
1118
      rh.set <=  (others => '0');
1119
    end generate;
1120
 
1121
    reg2 : if (DSETS>1) and (drepl = lru) generate
1122
      reg2 : process(clk)
1123
      begin if rising_edge(clk ) then rl <= cl; end if; end process;
1124
    end generate;
1125
 
1126
    noreg2 : if (DSETS = 1) or (drepl /= lru) generate
1127
      rl.write <= '0'; rl.waddr <= (others => '0');
1128
      rl.set <= (others => '0'); rl.lru <= (others => (others => '0'));
1129
    end generate;
1130
 
1131
-- pragma translate_off
1132
  chk : process
1133
  begin
1134
    assert not ((DSETS > 2) and (drepl = lrr)) report
1135
        "Wrong data cache configuration detected: LRR replacement requires 2 sets"
1136
    severity failure;
1137
    wait;
1138
  end process;
1139
-- pragma translate_on
1140
 
1141
end ;
1142
 

powered by: WebSVN 2.1.0

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