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/] [mmu_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, Konrad Eisele - Gaisler Research
22
-- Description: This unit implements the data cache controller.
23
------------------------------------------------------------------------------  
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
library techmap;
28
use techmap.gencomp.all;
29
library grlib;
30
use grlib.amba.all;
31
use grlib.sparc.all;
32
use grlib.stdlib.all;
33
library gaisler;
34
use gaisler.libiu.all;
35
use gaisler.libcache.all;
36
use gaisler.mmuconfig.all;
37
use gaisler.mmuiface.all;
38
 
39
entity mmu_dcache is
40
  generic (
41
    dsu       : 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
    itlbnum   : integer range 2 to 64 := 8;
49
    dtlbnum   : integer range 2 to 64 := 8;
50
    tlb_type  : integer range 0 to 3 := 1;
51
    memtech   : integer range 0 to NTECH := 0;
52
    cached    : integer := 0);
53
  port (
54
    rst : in  std_logic;
55
    clk : in  std_logic;
56
    dci : in  dcache_in_type;
57
    dco : out dcache_out_type;
58
    ico : in  icache_out_type;
59
    mcdi : out memory_dc_in_type;
60
    mcdo : in  memory_dc_out_type;
61
    ahbsi : in  ahb_slv_in_type;
62
    dcrami : out dcram_in_type;
63
    dcramo : in  dcram_out_type;
64
    fpuholdn : in  std_logic;
65
    mmudci : out mmudc_in_type;
66
    mmudco : in mmudc_out_type;
67
    sclk : in std_ulogic
68
);
69
end;
70
 
71
architecture rtl of mmu_dcache is
72
 
73
constant DSNOOP2        : integer := conv_integer(conv_std_logic_vector(dsnoop,3) and conv_std_logic_vector(3,3));
74
constant DSNOOP4        : integer := conv_integer(conv_std_logic_vector(dsnoop,3) and conv_std_logic_vector(4,3));
75
 
76
constant M_TLB_TYPE     : integer range 0 to 1 := conv_integer(conv_std_logic_vector(tlb_type,2) and conv_std_logic_vector(1,2));  -- eather split or combined
77
constant M_TLB_FASTWRITE : integer range 0 to 3 := conv_integer(conv_std_logic_vector(tlb_type,2) and conv_std_logic_vector(2,2));   -- fast writebuffer
78
 
79
constant M_ENT_I        : integer range 2 to 64 := itlbnum;   -- icache tlb entries: number
80
constant M_ENT_ILOG     : integer := log2(M_ENT_I);     -- icache tlb entries: address bits
81
 
82
constant M_ENT_D        : integer range 2 to 64 := dtlbnum;   -- dcache tlb entries: number
83
constant M_ENT_DLOG     : integer := log2(M_ENT_D);     -- dcache tlb entries: address bits
84
 
85
constant M_ENT_C        : integer range 2 to 64 := M_ENT_I;   -- i/dcache tlb entries: number
86
constant M_ENT_CLOG     : integer := M_ENT_ILOG;     -- i/dcache tlb entries: address bits
87
 
88
constant DLINE_BITS   : integer := log2(dlinesize);
89
constant DOFFSET_BITS : integer := 8 +log2(dsetsize) - DLINE_BITS;
90
constant LRR_BIT      : integer := TAG_HIGH + 1;
91
constant TAG_LOW    : integer := DOFFSET_BITS + DLINE_BITS + 2;
92
 
93
constant OFFSET_HIGH: integer := TAG_LOW - 1;
94
constant OFFSET_LOW : integer := DLINE_BITS + 2;
95
constant LINE_HIGH  : integer := OFFSET_LOW - 1;
96
constant LINE_LOW   : integer := 2;
97
constant LINE_ZERO  : std_logic_vector(DLINE_BITS-1 downto 0) := (others => '0');
98
constant SETBITS : integer := log2x(DSETS);
99
constant DLRUBITS  : integer := lru_table(DSETS);
100
 
101
constant lram      : integer range 0 to 1 := 0;
102
constant lramsize  : integer range 1 to 64 := 1;
103
constant lramstart : integer range 0 to 255 := 16#00#;
104
 
105
constant LOCAL_RAM_START : std_logic_vector(7 downto 0) := conv_std_logic_vector(lramstart, 8);
106
constant DREAD_FAST  : boolean := false;
107
constant DWRITE_FAST  : boolean := false;
108
constant DCLOCK_BIT : integer := dsetlock;
109
constant M_EN : boolean := true;
110
constant DCREPLACE  : integer range 0 to 2  :=    drepl;
111
 
112
constant DLINE_SIZE : integer := dlinesize;
113
constant DEST_RW      : boolean := (syncram_dp_dest_rw_collision(memtech) = 1);
114
 
115
type rdatatype is (dtag, ddata, dddata, dctx, icache, memory, sysr , misc, mmusnoop_dtag);  -- sources during cache read
116
type vmasktype is (clearone, clearall, merge, tnew);    -- valid bits operation
117
 
118
type valid_type is array (0 to DSETS-1) of std_logic_vector(dlinesize - 1 downto 0);
119
 
120
type write_buffer_type is record                        -- write buffer 
121
  addr, data1, data2 : std_logic_vector(31 downto 0);
122
  size : std_logic_vector(1 downto 0);
123
  asi  : std_logic_vector(3 downto 0);
124
  read : std_logic;
125
  lock : std_logic;
126
end record;
127
 
128
type dstatetype is (idle, wread, rtrans, wwrite, wtrans, wflush,
129
                    asi_idtag,dblwrite, loadpend);
130
type dcache_control_type is record                      -- all registers
131
  read : std_logic;                                     -- access direction
132
  size : std_logic_vector(1 downto 0);                   -- access size
133
  req, burst, holdn, nomds, stpend  : std_logic;
134
  xaddress : std_logic_vector(31 downto 0);              -- common address buffer
135
  paddress : std_logic_vector(31 downto 0);              -- physical address buffer
136
  faddr : std_logic_vector(DOFFSET_BITS - 1 downto 0);   -- flush address
137
  valid : valid_type; --std_logic_vector(DLINE_SIZE - 1 downto 0);      -- registered valid bits
138
  dstate : dstatetype;                                  -- FSM
139
  hit : std_logic;
140
  flush         : std_logic;                            -- flush in progress
141
  flush2        : std_logic;                            -- flush in progress
142
  mexc          : std_logic;                            -- latched mexc
143
  wb            : write_buffer_type;                    -- write buffer
144
  asi           : std_logic_vector(4 downto 0);
145
  icenable      : std_logic;                            -- icache diag access
146
  rndcnt        : std_logic_vector(log2x(DSETS)-1 downto 0); -- replace counter
147
  setrepl       : std_logic_vector(log2x(DSETS)-1 downto 0); -- set to replace
148
  lrr           : std_logic;
149
  dsuset        : std_logic_vector(log2x(DSETS)-1 downto 0);
150
  lock          : std_logic;
151
  lramrd : std_ulogic;
152
  cctrl            : cctrltype;
153
  cctrlwr       : std_ulogic;
154
 
155
  mmctrl1       : mmctrl_type1;
156
  mmctrl1wr       : std_ulogic;
157
 
158
  pflush        : std_logic;
159
  pflushr       : std_logic;
160
  pflushaddr    : std_logic_vector(VA_I_U downto VA_I_D);
161
  pflushtyp     : std_logic;
162
  vaddr         : std_logic_vector(31 downto 0);
163
  ready         : std_logic;
164
  wbinit        : std_logic;
165
  cache         : std_logic;
166
  su            : std_logic;
167
  dblwdata      : std_logic;
168
 
169
  trans_op      : std_logic;
170
  flush_op      : std_logic;
171
  diag_op       : std_logic;
172
 
173
end record;
174
 
175
type snoop_reg_type is record                   -- snoop control registers
176
  snoop   : std_logic;                          -- snoop access to tags
177
  writebp : std_logic_vector(0 to DSETS-1);              -- snoop write bypass
178
  addr    : std_logic_vector(TAG_HIGH downto OFFSET_LOW);-- snoop tag
179
  readbpx  : std_logic_vector(0 to DSETS-1);  -- possible write/read contention
180
end record;
181
 
182
type snoop_hit_bits_type is array (0 to 2**DOFFSET_BITS-1) of std_logic_vector(0 to DSETS-1);
183
 
184
type snoop_hit_reg_type is record
185
  hit     : snoop_hit_bits_type;                              -- snoop hit bits  
186
  taddr   : std_logic_vector(OFFSET_HIGH downto OFFSET_LOW);  -- saved tag address
187
  set     : std_logic_vector(log2x(DSETS)-1 downto 0);        -- saved set
188
end record;
189
 
190
subtype lru_type is std_logic_vector(DLRUBITS-1 downto 0);
191
type lru_array  is array (0 to 2**DOFFSET_BITS-1) of lru_type;  -- lru registers
192
type par_type is array (0 to DSETS-1) of std_logic_vector(1 downto 0);
193
 
194
type lru_reg_type is record
195
  write : std_logic;
196
  waddr : std_logic_vector(DOFFSET_BITS-1 downto 0);
197
  set   :  std_logic_vector(SETBITS-1 downto 0); --integer range 0 to DSETS-1;
198
  lru   : lru_array;
199
end record;
200
 
201
 
202
subtype lock_type is std_logic_vector(0 to DSETS-1);
203
 
204
function lru_set (lru : lru_type; lock : lock_type) return std_logic_vector is
205
variable xlru : std_logic_vector(4 downto 0);
206
variable set  : std_logic_vector(SETBITS-1 downto 0);
207
variable xset : std_logic_vector(1 downto 0);
208
variable unlocked : integer range 0 to DSETS-1;
209
begin
210
  set := (others => '0'); xlru := (others => '0'); xset := (others => '0');
211
  xlru(DLRUBITS-1 downto 0) := lru;
212
 
213
  if dsetlock = 1 then
214
    unlocked := DSETS-1;
215
    for i in DSETS-1 downto 0 loop
216
      if lock(i) = '0' then unlocked := i; end if;
217
    end loop;
218
  end if;
219
 
220
  case DSETS is
221
  when 2 =>
222
    if dsetlock = 1 then
223
      if lock(0) = '1' then xset(0) := '1'; else xset(0) := xlru(0); end if;
224
    else xset(0) := xlru(0); end if;
225
  when 3 =>
226
    if dsetlock = 1 then
227
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (unlocked), 2);
228
    else
229
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (0), 2);
230
    end if;
231
  when 4 =>
232
    if dsetlock = 1 then
233
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (unlocked), 2);
234
    else
235
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (0), 2);
236
    end if;
237
  when others =>
238
  end case;
239
  set := xset(SETBITS-1 downto 0);
240
  return(set);
241
end;
242
 
243
function lru_calc (lru : lru_type; set : integer) return lru_type is
244
variable new_lru : lru_type;
245
variable xnew_lru: std_logic_vector(4 downto 0);
246
variable xlru : std_logic_vector(4 downto 0);
247
begin
248
  new_lru := (others => '0'); xnew_lru := (others => '0');
249
  xlru := (others => '0'); xlru(DLRUBITS-1 downto 0) := lru;
250
  case DSETS is
251
  when 2 =>
252
    if set = 0 then xnew_lru(0) := '1'; else xnew_lru(0) := '0'; end if;
253
  when 3 =>
254
    xnew_lru(2 downto 0) := lru_3set_table(conv_integer(lru))(set);
255
  when 4 =>
256
    xnew_lru(4 downto 0) := lru_4set_table(conv_integer(lru))(set);
257
  when others =>
258
  end case;
259
  new_lru := xnew_lru(DLRUBITS-1 downto 0);
260
  return(new_lru);
261
end;
262
 
263
subtype word is std_logic_vector(31 downto 0);
264
 
265
signal r, c : dcache_control_type;      -- r is registers, c is combinational
266
signal rs, cs : snoop_reg_type;         -- rs is registers, cs is combinational
267
signal rh, ch : snoop_hit_reg_type;     -- rs is registers, cs is combinational
268
signal rl, cl : lru_reg_type;           -- rl is registers, cl is combinational
269
 
270
constant ctbl : std_logic_vector(15 downto 0) :=  conv_std_logic_vector(cached, 16);
271
 
272
begin
273
 
274
  dctrl : process(rst, r, rs, rh, rl, dci, mcdo, ico, dcramo, ahbsi, fpuholdn, mmudco)
275
  variable dcramov : dcram_out_type;
276
  variable rdatasel : rdatatype;
277
  variable maddress : std_logic_vector(31 downto 0);
278
  variable maddrlow : std_logic_vector(1 downto 0);
279
  variable edata : std_logic_vector(31 downto 0);
280
  variable size : std_logic_vector(1 downto 0);
281
  variable read : std_logic;
282
  variable twrite, tpwrite, tdiagwrite, ddiagwrite, dwrite : std_logic;
283
  variable taddr : std_logic_vector(OFFSET_HIGH  downto LINE_LOW); -- tag address
284
  variable newtag : std_logic_vector(TAG_HIGH  downto TAG_LOW); -- new tag
285
  variable newptag : std_logic_vector(TAG_HIGH  downto TAG_LOW); -- new tag
286
  variable align_data : std_logic_vector(31 downto 0); -- aligned data
287
  variable ddatainv, rdatav, align_datav : cdatatype;
288
  variable rdata : std_logic_vector(31 downto 0);
289
 
290
  variable vmaskraw : std_logic_vector((dlinesize -1) downto 0);
291
  variable vmask : valid_type; --std_logic_vector((dlinesize -1) downto 0);
292
  variable ivalid : std_logic_vector((dlinesize -1) downto 0);
293
  variable vmaskdbl : std_logic_vector((dlinesize/2 -1) downto 0);
294
  variable enable, senable, scanen : std_logic_vector(0 to 3);
295
  variable mds : std_logic;
296
  variable mexc : std_logic;
297
  variable hit, valid, validraw, forcemiss : std_logic;
298
  variable flush    : std_logic;
299
  variable iflush   : std_logic;
300
  variable v : dcache_control_type;
301
  variable eholdn : std_logic;                          -- external hold
302
  variable tparerr, dparerr  : std_logic_vector(0 to DSETS-1);
303
  variable snoopwe : std_logic;
304
  variable hcache   : std_logic;
305
  variable snoopaddr: std_logic_vector(OFFSET_HIGH downto OFFSET_LOW);
306
  variable vs : snoop_reg_type;
307
  variable vh : snoop_hit_reg_type;
308
  variable dsudata   : std_logic_vector(31 downto 0);
309
  variable set : integer range 0 to DSETS-1;
310
  variable ddset : integer range 0 to MAXSETS-1;
311
  variable snoopset : integer range 0 to DSETS-1;
312
  variable validv, hitv, validrawv : std_logic_vector(0 to MAXSETS-1);
313
  variable csnoopwe : std_logic_vector(0 to MAXSETS-1);
314
  variable ctwrite, ctpwrite, cdwrite : std_logic_vector(0 to MAXSETS-1);
315
  variable vset, setrepl  : std_logic_vector(log2x(DSETS)-1 downto 0);
316
  variable wlrr : std_logic_vector(0 to MAXSETS-1);
317
  variable vl : lru_reg_type;
318
  variable diagset : std_logic_vector(TAG_LOW + SETBITS -1 downto TAG_LOW);
319
  variable lock : std_logic_vector(0 to DSETS-1);
320
  variable wlock : std_logic_vector(0 to MAXSETS-1);
321
  variable snoopset2, rdsuset : integer range 0 to DSETS-1;
322
  variable snoophit : std_logic_vector(0 to DSETS-1);
323
  variable snoopval : std_logic;
324
  variable tag : cdatatype; --std_logic_vector(31  downto 0);
325
  variable ptag : cdatatype; --std_logic_vector(31  downto 0);
326
  variable ctx : ctxdatatype;
327
 
328
  variable miscdata  : std_logic_vector(31 downto 0);
329
  variable mmudiagaddr  : std_logic_vector(2 downto 0);
330
  variable pflush : std_logic;
331
  variable pflushaddr : std_logic_vector(VA_I_U downto VA_I_D);
332
  variable pflushtyp : std_logic;
333
  variable pftag : std_logic_vector(31 downto 2);
334
  variable mmuwdata : std_logic_vector(31 downto 0);
335
 
336
  variable mmudci_fsread, tagclear : std_logic;
337
  variable mmudci_trans_op : std_logic;
338
  variable mmudci_flush_op : std_logic;
339
  variable mmudci_wb_op : std_logic;
340
  variable mmudci_diag_op : std_logic;
341
  variable mmudci_su : std_logic;
342
  variable mmudci_read : std_logic;
343
  variable mmuregw, su : std_logic;
344
  variable mmuisdis : std_logic;
345
  variable readbp : std_logic_vector(0 to DSETS-1);
346
  variable rbphit, sidle : std_logic;
347
 
348
  variable mmudci_transdata_data : std_logic_vector(31 downto 0);
349
  variable paddress : std_logic_vector(31 downto 0);             -- physical address buffer
350
 
351
  begin
352
 
353
-- init local variables
354
 
355
    v := r; vs := rs; vh := rh; dcramov := dcramo; vl := rl;
356
    vl.write := '0'; v.cctrlwr := '0'; v.mmctrl1wr := '0';
357
    v.flush2 := r.flush; sidle := '0';
358
 
359
    if ((dci.eenaddr or dci.enaddr) = '1') or (r.dstate /= idle) or
360
       ((dsu = 1) and (dci.dsuen = '1')) or (r.flush = '1')  or
361
        (is_fpga(memtech) = 1)
362
    then
363
      enable := (others => '1');
364
    else enable := (others => '0'); end if;
365
 
366
    tagclear := '0'; mmuisdis := '0';
367
    if (not M_EN) or ((r.asi(4 downto 0) = ASI_MMU_BP) or (r.mmctrl1.e = '0')) then
368
      mmuisdis := '1';
369
    end if;
370
 
371
    if (mmuisdis = '1') then paddress := r.xaddress;
372
    else paddress := r.paddress; end if;
373
 
374
    mds := '1'; dwrite := '0'; twrite := '0'; tpwrite := '0';
375
    ddiagwrite := '0'; tdiagwrite := '0'; v.holdn := '1'; mexc := '0';
376
    flush := '0'; v.icenable := '0'; iflush := '0';
377
    eholdn := ico.hold and fpuholdn; ddset := 0; vset := (others => '0');
378
    tparerr  := (others => '0'); dparerr  := (others => '0');
379
    vs.snoop := '0'; vs.writebp := (others => '0'); snoopwe := '0';
380
    snoopaddr := ahbsi.haddr(OFFSET_HIGH downto OFFSET_LOW);
381
    hcache := '0'; rdsuset := 0;
382
    validv := (others => '0'); validrawv := (others => '0');
383
    hitv := (others => '0'); ivalid := (others => '0');
384
    miscdata := (others => '0'); pflush := '0';
385
    pflushaddr := dci.maddress(VA_I_U downto VA_I_D); pflushtyp := PFLUSH_PAGE;
386
    pftag := (others => '0');
387
    mmudiagaddr := (others => '0'); mmuregw := '0'; mmuwdata := (others => '0');
388
    mmudci_fsread := '0';
389
    ddatainv := (others => (others => '0')); tag := (others => (others => '0')); ptag := (others => (others => '0'));
390
    ctx := (others => (others => '0')); vs.readbpx := (others => '0'); rbphit := '0';
391
    newptag(TAG_HIGH downto TAG_LOW) := (others => '0');
392
 
393
    v.trans_op := r.trans_op and (not mmudco.grant);
394
    v.flush_op := r.flush_op and (not mmudco.grant);
395
    v.diag_op := r.diag_op and (not mmudco.grant);
396
    mmudci_trans_op := r.trans_op;
397
    mmudci_flush_op := r.flush_op;
398
    mmudci_diag_op := r.diag_op;
399
    mmudci_wb_op := '0';
400
    mmudci_transdata_data := r.vaddr;
401
 
402
    mmudci_su := '0'; mmudci_read := '0'; su := '0';
403
    if (not M_EN) or (r.mmctrl1.e = '0') then v.cache := '1'; end if;
404
 
405
    rdatasel := ddata;  -- read data from cache as default
406
    senable := (others => '0'); scanen := (others => mcdo.scanen);
407
 
408
    set := 0; snoopset := 0;  csnoopwe := (others => '0');
409
    ctwrite := (others => '0'); ctpwrite := (others => '0'); cdwrite := (others => '0');
410
    wlock := (others => '0');
411
    for i in 0 to DSETS-1 loop wlock(i) := dcramov.tag(i)(CTAG_LOCKPOS); end loop;
412
    wlrr := (others => '0');
413
    for i in 0 to 3 loop wlrr(i) := dcramov.tag(i)(CTAG_LRRPOS); end loop;
414
 
415
    if (DSETS > 1) then setrepl := r.setrepl; else setrepl := (others => '0'); end if;
416
 
417
-- random replacement counter
418
    if DSETS > 1 then
419
      if conv_integer(r.rndcnt) = (DSETS - 1) then v.rndcnt := (others => '0');
420
      else v.rndcnt := r.rndcnt + 1; end if;
421
    end if;
422
 
423
-- generate lock bits
424
    lock := (others => '0');
425
    if DCLOCK_BIT = 1 then
426
      for i in 0 to DSETS-1 loop lock(i) := dcramov.tag(i)(CTAG_LOCKPOS); end loop;
427
    end if;
428
 
429
-- AHB snoop handling
430
 
431
    if DSNOOP2 /= 0 then
432
      -- snoop on NONSEQ or SEQ and first word in cache line
433
      -- do not snoop during own transfers or during cache flush
434
      if (ahbsi.hready and ahbsi.hwrite and not mcdo.bg) = '1' and
435
         ((ahbsi.htrans = HTRANS_NONSEQ) or
436
            ((ahbsi.htrans = HTRANS_SEQ) and
437
             (ahbsi.haddr(LINE_HIGH downto LINE_LOW) = LINE_ZERO)))
438
      then
439
        vs.snoop := r.cctrl.dsnoop;-- and not r.mmctrl1.e;
440
        vs.addr := ahbsi.haddr(TAG_HIGH downto OFFSET_LOW);
441
      end if;
442
 
443
      for i in 0 to DSETS-1 loop senable(i) := vs.snoop or rs.snoop; end loop;
444
 
445
      readbp := (others => '0');
446
      if (paddress(TAG_HIGH downto OFFSET_LOW) = rs.addr(TAG_HIGH downto OFFSET_LOW)) then rbphit := '1'; end if;
447
      for i in 0 to DSETS-1 loop
448
        if (rs.readbpx(i) and rbphit) = '1' then readbp(i) := '1'; end if;
449
      end loop;
450
 
451
      -- clear valid bits on snoop hit (or set hit bits)
452
      for i in DSETS-1 downto 0 loop
453
        if ((rs.snoop and (not mcdo.ba) and not r.flush) = '1')
454
          and ((dcramov.stag(i)(TAG_HIGH downto TAG_LOW) = rs.addr(TAG_HIGH downto TAG_LOW)) or (readbp(i) = '1'))
455
        then
456
          if DSNOOP2 = 2 then
457
            vh.hit(conv_integer(rs.addr(OFFSET_HIGH downto OFFSET_LOW)))(i) := '1';
458
          else
459
            snoopaddr := rs.addr(OFFSET_HIGH downto OFFSET_LOW);
460
            snoopwe := '1'; snoopset := i;
461
          end if;
462
        end if;
463
      -- bypass tag data on read/write contention
464
        if (DSNOOP2 /= 2) and (rs.writebp(i) = '1') then
465
          dcramov.tag(i)(TAG_HIGH downto TAG_LOW) := rs.addr(TAG_HIGH downto TAG_LOW);
466
          dcramov.tag(i)(dlinesize-1 downto 0) := zero32(dlinesize-1 downto 0);
467
        end if;
468
      end loop;
469
    end if;
470
 
471
-- generate access parameters during pipeline stall
472
 
473
    if ((r.holdn) = '0') or ((dsu = 1) and (dci.dsuen = '1')) then
474
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
475
    elsif ((dci.enaddr and not dci.read) = '1') or (eholdn = '0')
476
    then
477
      taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW);
478
    else
479
      taddr := dci.eaddress(OFFSET_HIGH downto LINE_LOW);
480
    end if;
481
 
482
    if (dci.write or not r.holdn) = '1' then
483
      maddress := r.xaddress(31 downto 0); --signed := r.signed; 
484
      read := r.read; size := r.size; edata := dci.maddress;
485
      mmudci_su := r.su; mmudci_read := r.read;
486
    else
487
      maddress := dci.maddress(31 downto 0); --signed := dci.signed; 
488
      read := dci.read; size := dci.size; edata := dci.edata;
489
      mmudci_su := dci.msu; mmudci_read := dci.read;
490
    end if;
491
 
492
    newtag := dci.maddress(TAG_HIGH downto TAG_LOW);
493
    newptag := dci.maddress(TAG_HIGH downto TAG_LOW);
494
    vl.waddr := maddress(OFFSET_HIGH downto OFFSET_LOW);  -- lru write address
495
 
496
-- generate cache hit and valid bits
497
 
498
    if cached /= 0 then hcache := ctbl(conv_integer(dci.maddress(31 downto 28)));
499
    else hcache := '1'; end if;
500
 
501
    forcemiss := not dci.asi(3); hit := '0'; set := 0;
502
    snoophit := (others => '0'); snoopval := '1';
503
    for i in DSETS-1 downto 0 loop
504
      if DSNOOP2 = 2 then
505
        snoophit(i) := rh.hit(conv_integer(rh.taddr))(i);
506
      end if;
507
      if (dcramov.tag(i)(TAG_HIGH downto TAG_LOW) = dci.maddress(TAG_HIGH downto TAG_LOW))
508
        and ((dcramov.ctx(i) = r.mmctrl1.ctx) or (r.mmctrl1.e = '0'))
509
      then hitv(i) := hcache; end if;
510
      validrawv(i) := hitv(i) and (not r.flush) and (not r.flush2) and (not snoophit(i)) and
511
        genmux(dci.maddress(LINE_HIGH downto LINE_LOW), dcramov.tag(i)(dlinesize-1 downto 0));
512
      validv(i) :=  validrawv(i);
513
      snoopval := snoopval and not snoophit(i);
514
    end loop;
515
 
516
    hit := orv(hitv) and not r.flush and (not r.flush2);
517
 
518
    -- cache hit disabled if mmu-enabled but off or BYPASS
519
    if (M_EN) and (dci.asi(4 downto 0) = ASI_MMU_BP) then  -- or (r.mmctrl1.e = '0')
520
      hit := '0';
521
    end if;
522
 
523
    validraw := orv(validrawv);
524
    valid := orv(validv);
525
    if DSETS > 1 then
526
      for i in DSETS-1 downto 0 loop
527
        if hitv(i) = '1' then
528
          vset := conv_std_logic_vector(i, SETBITS);
529
        end if;
530
      end loop;
531
      set := conv_integer(vset);
532
    else set := 0; end if;
533
 
534
    if (dci.dsuen = '1') then diagset := r.xaddress(TAG_LOW+SETBITS-1 downto TAG_LOW);
535
    else diagset := maddress(TAG_LOW + SETBITS - 1 downto TAG_LOW); end if;
536
    case DSETS is
537
    when 1 => ddset := 0;
538
    when 3 => if conv_integer(diagset) < 3 then ddset := conv_integer(diagset); end if;
539
    when others => ddset := conv_integer(diagset);
540
    end case;
541
 
542
    if ((r.holdn and dci.enaddr) = '1')  and (r.dstate = idle) then
543
        v.hit := hit; v.xaddress := dci.maddress;
544
        v.read := dci.read; v.size := dci.size;
545
        v.asi := dci.asi(4 downto 0);
546
        --v.signed := dci.signed;
547
        v.su := dci.msu;
548
    end if;
549
 
550
-- Store buffer
551
 
552
    if mcdo.ready = '1' then
553
      v.wb.addr(2) := r.wb.addr(2) or (r.wb.size(0) and r.wb.size(1));
554
      if r.stpend = '1' then
555
        v.stpend := r.req; v.wb.data1 := r.wb.data2;
556
        v.wb.lock := r.wb.lock and r.req;
557
      end if;
558
    end if;
559
    if mcdo.grant = '1' then v.req := r.burst; v.burst := '0'; end if;
560
    if (mcdo.grant and not r.wb.read and r.req) = '1' then v.wb.lock := '0'; end if;
561
 
562
    -- cache freeze operation
563
    if (r.cctrl.ifrz and dci.intack and r.cctrl.ics(0)) = '1' then
564
      v.cctrl.ics := "01";
565
    end if;
566
    if (r.cctrl.dfrz and dci.intack and r.cctrl.dcs(0)) = '1' then
567
      v.cctrl.dcs := "01";
568
    end if;
569
 
570
    if r.cctrlwr = '1' then
571
    if (r.xaddress(7 downto 2) = "000000") and (dci.read = '0') then
572
      v.cctrl.dsnoop := dci.maddress(23);
573
      flush        := dci.maddress(22);
574
      iflush       := dci.maddress(21);
575
      v.cctrl.burst:= dci.maddress(16);
576
      v.cctrl.dfrz := dci.maddress(5);
577
      v.cctrl.ifrz := dci.maddress(4);
578
      v.cctrl.dcs  := dci.maddress(3 downto 2);
579
      v.cctrl.ics  := dci.maddress(1 downto 0);
580
    end if;
581
    end if;
582
 
583
    if (dsu = 1) and (dci.dsuen = '1') then
584
      mmuwdata := dci.maddress;
585
    else
586
      mmuwdata := dci.edata;
587
    end if;
588
 
589
    mmudiagaddr := dci.maddress(CNR_U downto CNR_D);
590
    if r.mmctrl1wr = '1' then
591
      mmudiagaddr := r.xaddress(CNR_U downto CNR_D);  -- defer match sram out
592
      if (dci.read = '0') then
593
        mmuwdata := dci.maddress;
594
        mmuregw := '1';
595
      end if;
596
    end if;
597
 
598
-- main Dcache state machine
599
 
600
    case r.dstate is
601
    when idle =>                        -- Idle state
602
      if (M_TLB_FASTWRITE /= 0) then
603
        mmudci_transdata_data := dci.maddress;
604
      end if;
605
      sidle := '1';
606
      if (snoopval = '1') then
607
        for i in 0 to DSETS-1 loop
608
          v.valid(i) := dcramov.tag(i)(dlinesize-1 downto 0);
609
        end loop;
610
      else v.valid := (others => (others => '0')); end if;
611
      v.nomds := r.nomds and not eholdn; --v.valid := dcramov.dtramout(set).valid;
612
      if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1') then -- wait for store queue
613
        v.wb.addr := dci.maddress; v.wb.size := dci.size;
614
        v.wb.read := dci.read; v.wb.data1 := dci.edata; v.wb.lock := dci.lock;
615
        v.wb.asi := dci.asi(3 downto 0);
616
        if ((M_EN) and (dci.asi(4 downto 0) /= ASI_MMU_BP) and (r.mmctrl1.e = '1') and (M_TLB_FASTWRITE /= 0) ) then
617
          v.wb.addr := mmudco.wbtransdata.data;
618
          newptag := mmudco.wbtransdata.data(TAG_HIGH downto TAG_LOW);
619
        end if;
620
      end if;
621
      if (eholdn and (not r.nomds)) = '1' then -- avoid false path through nullify
622
        case dci.asi(4 downto 0) is
623
        when ASI_SYSR => rdatasel := sysr;
624
        when ASI_DTAG => rdatasel := dtag;
625
        when ASI_DDATA => rdatasel := dddata;
626
        when ASI_DCTX => rdatasel := dctx;
627
        when ASI_MMUREGS => rdatasel := misc;
628
        when ASI_MMUSNOOP_DTAG => rdatasel := mmusnoop_dtag;
629
        when others =>
630
        end case;
631
      end if;
632
      if (dci.enaddr and eholdn and (not r.nomds) and not dci.nullify) = '1' then
633
        case dci.asi(4 downto 0) is
634
        when ASI_SYSR =>                -- system registers
635
          if (dsu = 0) or (dci.dsuen = '0') then
636
            if (dci.maddress(7 downto 2) = "000000") and (dci.read = '0') then
637
              v.cctrl.dsnoop := dci.edata(23);
638
              flush        := dci.edata(22);
639
              iflush       := dci.edata(21);
640
              v.cctrl.burst:= dci.edata(16);
641
              v.cctrl.dfrz := dci.edata(5);
642
              v.cctrl.ifrz := dci.edata(4);
643
              v.cctrl.dcs  := dci.edata(3 downto 2);
644
              v.cctrl.ics  := dci.edata(1 downto 0);
645
            end if;
646
          else
647
            v.cctrlwr := not dci.read;
648
          end if;
649
        when ASI_MMUREGS =>
650
          if (dsu = 0) or dci.dsuen = '0' then
651
            if M_EN then
652
--              rdatasel := misc; 
653
              -- clean fault valid bit
654
              if dci.read = '1' then
655
                case dci.maddress(CNR_U downto CNR_D) is
656
                  when CNR_F =>
657
                    mmudci_fsread := '1';
658
                  when others => null;
659
                end case;
660
              else
661
                mmuregw := '1';
662
              end if;
663
            end if;
664
          else
665
            v.mmctrl1wr := not dci.read and not (r.mmctrl1wr and dci.dsuen);
666
          end if;
667
        when ASI_ITAG | ASI_IDATA | ASI_ICTX =>         -- Read/write Icache tags
668
          -- CTX write has to be done through ctxnr & ASI_ITAG
669
          if (ico.flush = '1') or (dci.asi(4) = '1') then mexc := '1';
670
         else v.dstate := asi_idtag; v.holdn := '0'; end if;
671
        when ASI_DFLUSH =>              -- flush data cache
672
          if dci.read = '0' then flush := '1'; end if;
673
        when ASI_DDATA =>               -- Read/write Dcache data
674
          if (dci.size /= "10") or (r.flush = '1') then -- only word access is allowed
675
            mexc := '1';
676
          elsif (dci.read = '0') then
677
            dwrite := '1'; ddiagwrite := '1';
678
          end if;
679
        when ASI_DTAG =>                -- Read/write Dcache tags
680
          if (dci.size /= "10") or (r.flush = '1') then -- allow only word access
681
            mexc := '1';
682
          elsif (dci.read = '0') then
683
            twrite := '1'; tdiagwrite := '1';
684
          end if;
685
        when ASI_MMUSNOOP_DTAG =>       -- Read/write MMU physical snoop tags
686
          if M_EN then
687
          snoopaddr := taddr(OFFSET_HIGH downto OFFSET_LOW);
688
          if (dci.size /= "10") or (r.flush = '1') then -- allow only word access
689
            mexc := '1';
690
          elsif (dci.read = '0') then
691
            tpwrite := '1'; tdiagwrite := '1';
692
          end if;
693
          end if;
694
        when ASI_DCTX =>
695
          -- write has to be done through ctxnr & ASI_DTAG
696
          if (dci.size /= "10") or (r.flush = '1') or (dci.read = '0') then -- allow only word access
697
            mexc := '1';
698
          end if;
699
        when ASI_FLUSH_PAGE => -- i/dcache flush page
700
          if M_EN then
701
            if dci.read = '0' then
702
              flush := '1'; iflush := '1'; --pflush := '1'; pflushtyp := PFLUSH_PAGE;
703
            end if;
704
          end if;
705
        when ASI_FLUSH_CTX => -- i/dcache flush ctx
706
          if M_EN then
707
            if dci.read = '0' then
708
              flush := '1'; iflush := '1'; --pflush := '1'; pflushtyp := PFLUSH_CTX;
709
            end if;
710
          end if;
711
        when ASI_MMUFLUSHPROBE =>
712
          if M_EN then
713
            if dci.read = '0' then      -- flush
714
              mmudci_flush_op := '1';
715
              v.flush_op := not mmudco.grant;
716
              v.dstate := wflush;
717
              v.vaddr := dci.maddress; v.holdn := '0'; flush := '1'; iflush := '1';
718
            end if;
719
          end if;
720
        when ASI_MMU_DIAG =>
721
          if dci.read = '0' then      -- diag access
722
            mmudci_diag_op := '1';
723
            v.diag_op := not mmudco.grant;
724
            v.vaddr := dci.maddress;
725
          end if;
726
        when others =>
727
          if dci.read = '1' then        -- read access
728
            --if (not ((mcdo.dcs(0) = '1') 
729
            if (not ((r.cctrl.dcs(0) = '1')
730
               and ((hit and valid and not forcemiss) = '1')))
731
 
732
            then        -- read miss
733
              v.holdn := '0'; v.dstate := wread; v.ready := '0'; v.cache := '1';
734
              if (not M_EN) or
735
                ((dci.asi(4 downto 0) = ASI_MMU_BP) or (r.mmctrl1.e = '0'))
736
              then
737
                -- cache disabled if mmu-enabled but off or BYPASS
738
                if (M_EN) then v.cache := '0'; end if;
739
 
740
                if ((r.stpend  = '0') or ((mcdo.ready and not r.req) = '1'))
741
                then    -- wait for store queue
742
 
743
                  v.req := '1';
744
                  v.burst := dci.size(1) and dci.size(0) and not dci.maddress(2);
745
                end if;
746
              else
747
                -- ## mmu case >
748
                if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1')
749
                then
750
                  v.wbinit := '1';     -- wb init in idle
751
                  v.burst := dci.size(1) and dci.size(0) and not dci.maddress(2);
752
                else
753
                  v.wbinit := '0';
754
                end if;
755
 
756
                mmudci_trans_op := '1';  -- start translation
757
                v.trans_op := not mmudco.grant;
758
                v.vaddr := dci.maddress;
759
                v.dstate := rtrans;
760
                -- ## < mmu case 
761
              end if;
762
 
763
            else       -- read hit
764
              if (DSETS > 1) and (DCREPLACE = lru) then vl.write := '1'; end if;
765
            end if;
766
 
767
          else                  -- write access
768
            v.ready := '0';
769
            if (not M_EN) or
770
 
771
              ((dci.asi(4 downto 0) = ASI_MMU_BP) or (r.mmctrl1.e = '0')) then
772
 
773
              if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1') then
774
 
775
                v.req := '1'; v.stpend := '1';
776
                v.burst := dci.size(1) and dci.size(0);
777
 
778
                if (dci.size = "11") then v.dstate := dblwrite; end if; -- double store       
779
              else              -- wait for store queue
780
                v.dstate := wwrite; v.holdn := '0';
781
              end if;
782
            else
783
              -- ## mmu case >  false and
784
              --if  ((r.stpend  = '0') or ((mcdo.ready and not r.req)= '1')) and ( mmudco.wbtransdata.accexc = '0' ) and (dci.size /= "11") and (M_TLB_FASTWRITE /= 0) 
785
              if  ((r.stpend  = '0') or ((mcdo.ready and not r.req)= '1')) and ( mmudco.wbtransdata.accexc = '0' ) and (M_TLB_FASTWRITE /= 0)
786
              then
787
                v.req := '1'; v.stpend := '1';
788
                v.burst := dci.size(1) and dci.size(0);
789
                if (dci.size = "11") then v.dstate := dblwrite; end if; -- double store       
790
              else
791
              if (r.stpend  = '0') or ((mcdo.ready and not r.req)= '1')
792
              then
793
                v.wbinit := '1';     -- wb init in idle
794
                v.burst := dci.size(1) and dci.size(0);
795
              else
796
                v.wbinit := '0';
797
              end if;
798
              mmudci_trans_op := '1';  -- start translation
799
              v.trans_op := not mmudco.grant;
800
              v.vaddr := dci.maddress; v.holdn := '0';
801
              v.dstate := wtrans;
802
              v.dblwdata := dci.size(0) or dci.size(1);  -- "11"
803
              -- ## < mmu case 
804
              end if;
805
            end if;
806
 
807
            -- note: cache hit disabled if BYPASS
808
            if (r.cctrl.dcs(0) = '1') and ((hit and (dci.size(1) or validraw)) = '1')
809
            then  -- write hit
810
              twrite := '1'; dwrite := '1';
811
              if (DSETS > 1) and (DCREPLACE = lru) then vl.write := '1'; end if;
812
              setrepl := conv_std_logic_vector(set, SETBITS);
813
              if DSNOOP2 /= 0 then
814
                if ((dci.enaddr and not dci.read) = '1') or (eholdn = '0')
815
                then v.xaddress := dci.maddress; else v.xaddress := dci.eaddress; end if;
816
                vs.readbpx(set) := '1';
817
              end if;
818
            end if;
819
            if (dci.size = "11") then v.xaddress(2) := '1'; end if;
820
          end if;
821
 
822
          if (DSETS > 1) then
823
            vl.set := conv_std_logic_vector(set, SETBITS);
824
            v.setrepl := conv_std_logic_vector(set, SETBITS);
825
            if ((not hit) and (not dparerr(set)) and (not r.flush)) = '1' then
826
              case DCREPLACE is
827
              when rnd =>
828
                if DCLOCK_BIT = 1 then
829
                  if lock(conv_integer(r.rndcnt)) = '0' then v.setrepl := r.rndcnt;
830
                  else
831
                    v.setrepl := conv_std_logic_vector(DSETS-1, SETBITS);
832
                    for i in DSETS-1 downto 0 loop
833
                      if (lock(i) = '0') and (i>conv_integer(r.rndcnt)) then
834
                        v.setrepl := conv_std_logic_vector(i, SETBITS);
835
                      end if;
836
                    end loop;
837
                  end if;
838
                else
839
                  v.setrepl := r.rndcnt;
840
                end if;
841
              when lru =>
842
                v.setrepl := lru_set(rl.lru(conv_integer(dci.maddress(OFFSET_HIGH downto OFFSET_LOW))), lock(0 to DSETS-1));
843
              when lrr =>
844
                v.setrepl := (others => '0');
845
                if DCLOCK_BIT = 1 then
846
                  if lock(0) = '1' then v.setrepl(0) := '1';
847
                  else
848
                    v.setrepl(0) := dcramov.tag(0)(CTAG_LRRPOS) xor dcramov.tag(1)(CTAG_LRRPOS);
849
                  end if;
850
                else
851
                  v.setrepl(0) := dcramov.tag(0)(CTAG_LRRPOS) xor dcramov.tag(1)(CTAG_LRRPOS);
852
                end if;
853
                if v.setrepl(0) = '0' then
854
                  v.lrr := not dcramov.tag(0)(CTAG_LRRPOS);
855
                else
856
                  v.lrr := dcramov.tag(0)(CTAG_LRRPOS);
857
                end if;
858
              end case;
859
            end if;
860
 
861
            if (DCLOCK_BIT = 1) then
862
              if (hit and (not dparerr(set)) and lock(set)) = '1' then v.lock := '1';
863
              else v.lock := '0'; end if;
864
            end if;
865
 
866
          end if;
867
 
868
        end case;
869
      end if;
870
    when rtrans =>
871
      if M_EN then
872
        if r.stpend = '1' then
873
          if ((mcdo.ready and not r.req) = '1') then
874
            v.ready := '1';       -- buffer store finish
875
          end if;
876
        end if;
877
 
878
        v.holdn := '0';
879
        if mmudco.transdata.finish = '1' then
880
          -- translation error, i.e. page fault
881
          if (mmudco.transdata.accexc) = '1' then
882
            v.holdn := '1'; v.dstate := idle;
883
            mds := '0'; mexc := not r.mmctrl1.nf;
884
          else
885
            v.dstate := wread;
886
            v.cache := r.cache and mmudco.transdata.cache;
887
            --v.xaddress := mmudco.data;
888
            v.paddress := mmudco.transdata.data;
889
            if v.wbinit = '1' then
890
              v.wb.addr := mmudco.transdata.data;
891
              v.req := '1';
892
            end if;
893
          end if;
894
        end if;
895
      end if;
896
 
897
    when wread =>               -- read miss, wait for memory data
898
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
899
      newtag := r.xaddress(TAG_HIGH downto TAG_LOW);
900
      newptag := paddress(TAG_HIGH downto TAG_LOW);
901
      v.nomds := r.nomds and not eholdn;
902
      v.holdn := v.nomds; rdatasel := memory;
903
      for i in 0 to DSETS-1 loop wlock(i) := r.lock; end loop;
904
      for i in 0 to 1 loop wlrr(i) := r.lrr; end loop;
905
      if (r.stpend = '0') and (r.ready = '0') then
906
 
907
        if mcdo.ready = '1' then
908
          mds := r.holdn or r.nomds; v.xaddress(2) := '1'; v.holdn := '1';
909
          if (r.cctrl.dcs = "01") then
910
            v.hit := mcdo.cache and r.hit and r.cache; twrite := v.hit;
911
          elsif (r.cctrl.dcs(1) = '1') then
912
            v.hit := mcdo.cache and (r.hit or (r.asi(3) and not r.asi(2))) and r.cache; twrite := v.hit;
913
          end if;
914
          dwrite := twrite; rdatasel := memory;
915
          mexc := mcdo.mexc;
916
          tpwrite := twrite;
917
 
918
          if r.req = '0' then
919
 
920
            if (((dci.enaddr and not mds) = '1') or
921
              ((dci.eenaddr and mds and eholdn) = '1')) and (r.cctrl.dcs(0) = '1') then
922
              v.dstate := loadpend; v.holdn := '0';
923
            else v.dstate := idle; end if;
924
          else v.nomds := '1'; end if;
925
        end if;
926
        v.mexc := mcdo.mexc; v.wb.data2 := mcdo.data;
927
      else
928
        if (r.ready or (mcdo.ready and not r.req)) = '1' then   -- wait for store queue
929
          v.burst := r.size(1) and r.size(0) and not r.xaddress(2);
930
          v.wb.addr := paddress;
931
          v.wb.size := r.size;
932
          v.wb.read := r.read; v.wb.data1 := dci.maddress; v.req := '1';
933
          v.wb.lock := dci.lock; v.wb.asi := r.asi(3 downto 0); v.ready := '0';
934
        end if;
935
      end if;
936
      if DSNOOP2 /= 0 then vs.readbpx(conv_integer(setrepl)) := '1'; end if;
937
    when loadpend =>            -- return from read miss with load pending
938
      taddr := dci.maddress(OFFSET_HIGH downto LINE_LOW);
939
      v.dstate := idle;
940
    when dblwrite =>            -- second part of double store cycle
941
      v.dstate := idle; v.wb.data2 := dci.edata;
942
      edata := dci.edata;  -- needed for STD store hit
943
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
944
        if (r.cctrl.dcs(0) = '1') and (r.hit = '1') then dwrite := '1'; end if;
945
 
946
    when asi_idtag =>           -- icache diag access
947
      rdatasel := icache; v.icenable := '1'; v.holdn := dci.dsuen;
948
      if  ico.diagrdy = '1' then
949
        v.dstate := loadpend; v.icenable := '0'; mds := not r.read;
950
      end if;
951
 
952
    when wtrans =>
953
      edata := dci.edata;  -- needed for STD store hit
954
      taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW);
955
      newtag := r.xaddress(TAG_HIGH downto TAG_LOW);
956
 
957
      if M_EN then
958
        if r.stpend = '1' then
959
          if ((mcdo.ready and not r.req) = '1') then
960
            v.ready := '1';       -- buffer store finish
961
          end if;
962
        end if;
963
 
964
        -- fetch dblwrite data 2, does the same as state dblwrite,
965
        -- except that init of data2 is omitted to end of translation or in wwrite
966
        if ((r.dblwdata) = '1') and ((r.size) = "11") then
967
          v.dblwdata := '0';
968
        end if;
969
 
970
        v.holdn := '0';
971
        if mmudco.transdata.finish = '1' then
972
          if (mmudco.transdata.accexc) = '1' then
973
            v.holdn := '1'; v.dstate := idle;
974
            mds := '0'; mexc := not r.mmctrl1.nf;
975
 
976
              tagclear := r.cctrl.dcs(0) and r.hit;
977
 
978
            twrite := tagclear;
979
 
980
            if (twrite = '1') and (((dci.enaddr and not mds) = '1') or
981
                ((dci.eenaddr and mds and eholdn) = '1')) and (r.cctrl.dcs(0) = '1') then
982
              v.dstate := loadpend; v.holdn := '0';
983
            end if;
984
 
985
          else
986
            v.dstate := wwrite;
987
            v.cache := mmudco.transdata.cache;
988
            v.paddress := mmudco.transdata.data;
989
 
990
            if (r.wbinit) = '1' then
991
              v.wb.data2 := dci.edata;
992
              v.wb.addr := mmudco.transdata.data;
993
              v.dstate := idle;  v.holdn := '1';
994
              v.req := '1'; v.stpend := '1';
995
              v.burst := r.size(1) and r.size(0) and not v.wb.addr(2);
996
 
997
              --if (mcdo.dcs(0) = '1') and (r.hit = '1') and (r.size = "11")  then  -- write hit
998
              if (r.cctrl.dcs(0) = '1') and (r.hit = '1') and (r.size = "11")  then  -- write hit
999
                dwrite := '1';
1000
              end if;
1001
            end if;
1002
          end if;
1003
        else
1004
          -- mmudci_trans_op := '1';  -- start translation
1005
        end if;
1006
 
1007
      end if;
1008
 
1009
    when wwrite =>              -- wait for store buffer to empty (store access)
1010
      edata := dci.edata;  -- needed for STD store hit
1011
 
1012
      if (v.ready or (mcdo.ready and not r.req)) = '1' then     -- store queue emptied
1013
 
1014
          if (r.cctrl.dcs(0) = '1') and (r.hit = '1') and (r.size = "11")  then  -- write hit
1015
            taddr := r.xaddress(OFFSET_HIGH downto LINE_LOW); dwrite := '1';
1016
          end if;
1017
        v.dstate := idle;
1018
 
1019
        v.req := '1'; v.burst := r.size(1) and r.size(0); v.stpend := '1';
1020
 
1021
        v.wb.addr := paddress;
1022
        v.wb.size := r.size;
1023
        v.wb.read := r.read; v.wb.data1 := dci.maddress;
1024
        v.wb.lock := dci.lock; v.wb.data2 := dci.edata;
1025
        v.wb.asi := r.asi(3 downto 0);
1026
        if r.size = "11" then v.wb.addr(2) := '0'; end if;
1027
      else  -- hold cpu until buffer empty
1028
        v.holdn := '0';
1029
      end if;
1030
 
1031
    when wflush =>
1032
      v.holdn := '0';
1033
      if mmudco.transdata.finish = '1' then
1034
        v.dstate := idle; v.holdn := '1';
1035
      end if;
1036
 
1037
    when others => v.dstate := idle;
1038
    end case;
1039
 
1040
-- select data to return on read access
1041
-- align if byte/half word read from cache or memory.
1042
 
1043
    --mmudiagaddr := dci.maddress(CNR_U downto CNR_D); mmuwdata := dci.edata;
1044
    if (dsu = 1) and (dci.dsuen = '1') then
1045
      v.dsuset := conv_std_logic_vector(ddset, SETBITS);
1046
      case dci.asi(4 downto 0) is
1047
      when ASI_ITAG | ASI_IDATA =>
1048
        v.icenable := not ico.diagrdy;
1049
        rdatasel := icache;
1050
      when ASI_DTAG =>
1051
        tdiagwrite := not dci.eenaddr and dci.enaddr and dci.write;
1052
        twrite := not dci.eenaddr and dci.enaddr and dci.write;
1053
        rdatasel := dtag;
1054
      when ASI_MMUSNOOP_DTAG =>
1055
        if M_EN then
1056
        tdiagwrite := not dci.eenaddr and dci.enaddr and dci.write;
1057
        tpwrite := not dci.eenaddr and dci.enaddr and dci.write;
1058
        rdatasel := mmusnoop_dtag;
1059
        end if;
1060
      when ASI_DDATA =>
1061
        ddiagwrite := not dci.eenaddr and dci.enaddr and dci.write;
1062
        dwrite := not dci.eenaddr and dci.enaddr and dci.write;
1063
        rdatasel := dddata;
1064
      when ASI_MMUREGS =>
1065
        mmuregw := not dci.eenaddr and dci.enaddr and dci.write;
1066
        rdatasel := misc;
1067
      when others =>
1068
      end case;
1069
    end if;
1070
 
1071
    -- note: mmudiagaddr is (10 downto 8) (000,001, ...)
1072
    -- read
1073
    case mmudiagaddr is
1074
      when CNR_CTRL =>
1075
        miscdata(MMCTRL_E) := r.mmctrl1.e;
1076
        miscdata(MMCTRL_NF) := r.mmctrl1.nf;
1077
        miscdata(MMCTRL_PSO) := r.mmctrl1.pso;
1078
        miscdata(MMCTRL_VER_U downto MMCTRL_VER_D) := "0000";
1079
        miscdata(MMCTRL_IMPL_U downto MMCTRL_IMPL_D) := "0000";
1080
        miscdata(23 downto 21) := conv_std_logic_vector(M_ENT_ILOG,3);
1081
        miscdata(20 downto 18) := conv_std_logic_vector(M_ENT_DLOG,3);
1082
        if M_TLB_TYPE = 0 then miscdata(17) := '1'; else
1083
          miscdata(23 downto 21) := conv_std_logic_vector(M_ENT_CLOG,3);
1084
          miscdata(20 downto 18) := (others => '0');
1085
        end if;
1086
        miscdata(MMCTRL_TLBDIS) := r.mmctrl1.tlbdis;
1087
        --custom 
1088
      when CNR_CTXP =>
1089
        miscdata(MMCTXP_U downto MMCTXP_D) := r.mmctrl1.ctxp;
1090
      when CNR_CTX =>
1091
        miscdata(MMCTXNR_U downto MMCTXNR_D) := r.mmctrl1.ctx;
1092
      when CNR_F =>
1093
        miscdata(FS_OW) := mmudco.mmctrl2.fs.ow;
1094
        miscdata(FS_FAV) := mmudco.mmctrl2.fs.fav;
1095
        miscdata(FS_FT_U downto FS_FT_D) := mmudco.mmctrl2.fs.ft;
1096
        miscdata(FS_AT_LS) := mmudco.mmctrl2.fs.at_ls;
1097
        miscdata(FS_AT_ID) := mmudco.mmctrl2.fs.at_id;
1098
        miscdata(FS_AT_SU) := mmudco.mmctrl2.fs.at_su;
1099
        miscdata(FS_L_U downto FS_L_D) := mmudco.mmctrl2.fs.l;
1100
        miscdata(FS_EBE_U downto FS_EBE_D) := mmudco.mmctrl2.fs.ebe;
1101
      when CNR_FADDR =>
1102
        miscdata(VA_I_U downto VA_I_D) := mmudco.mmctrl2.fa;
1103
      when others => null;
1104
    end case;
1105
 
1106
 
1107
 
1108
    rdata := (others => '0'); rdatav := (others => (others => '0'));
1109
    align_data := (others => '0'); align_datav := (others => (others => '0'));
1110
    maddrlow := maddress(1 downto 0); -- stupid Synopsys VSS bug ...
1111
 
1112
    case rdatasel is
1113
    when misc =>
1114
      set := 0;
1115
      rdatav(0) := miscdata;
1116
    when dddata =>
1117
      rdatav := dcramov.data;
1118
      if dci.dsuen = '1' then set := conv_integer(r.dsuset);
1119
      else set := ddset; end if;
1120
    when dtag =>
1121
      rdatav := dcramov.tag;
1122
      if dci.dsuen = '1' then set := conv_integer(r.dsuset);
1123
      else set := ddset; end if;
1124
    when mmusnoop_dtag =>
1125
      rdatav := dcramov.stag;
1126
      if dci.dsuen = '1' then set := conv_integer(r.dsuset);
1127
      else set := ddset; end if;
1128
    when dctx =>
1129
      --rdata(M_CTX_SZ-1 downto 0) := dcramov.dtramout(ddset).ctx;
1130
    when icache =>
1131
      rdatav(0) := ico.diagdata; set := 0;
1132
    when ddata | memory =>
1133
        if rdatasel = memory then
1134
          rdatav(0) := mcdo.data; set := 0; --FIXME
1135
        else
1136
          for i in 0 to DSETS-1 loop rdatav(i) := dcramov.data(i); end loop;
1137
        end if;
1138
    when sysr =>
1139
      set := 0;
1140
      case dci.maddress(3 downto 2) is
1141
      when "00" | "01" =>
1142
        rdatav(0)(23) := r.cctrl.dsnoop;
1143
        rdatav(0)(16 downto 14) := r.cctrl.burst & ico.flush & r.flush;
1144
        rdatav(0)(5 downto 0) :=
1145
            r.cctrl.dfrz & r.cctrl.ifrz & r.cctrl.dcs & r.cctrl.ics;
1146
      when "10" =>
1147
        rdatav(0) := ico.cfg;
1148
      when others =>
1149
        rdatav(0) := cache_cfg(drepl, dsets, dlinesize, dsetsize, dsetlock,
1150
                dsnoop, lram, lramsize, lramstart, 1);
1151
      end case;
1152
    end case;
1153
 
1154
-- select which data to update the data cache with
1155
 
1156
       for i in 0 to DSETS-1 loop
1157
        case size is            -- merge data during partial write
1158
        when "00" =>
1159
          case maddrlow is
1160
          when "00" =>
1161
            ddatainv(i) := edata(7 downto 0) & dcramov.data(i)(23 downto 0);
1162
          when "01" =>
1163
            ddatainv(i) := dcramov.data(i)(31 downto 24) & edata(7 downto 0) &
1164
                     dcramov.data(i)(15 downto 0);
1165
          when "10" =>
1166
            ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(7 downto 0) &
1167
                     dcramov.data(i)(7 downto 0);
1168
          when others =>
1169
            ddatainv(i) := dcramov.data(i)(31 downto 8) & edata(7 downto 0);
1170
          end case;
1171
        when "01" =>
1172
          if maddress(1) = '0' then
1173
            ddatainv(i) := edata(15 downto 0) & dcramov.data(i)(15 downto 0);
1174
          else
1175
            ddatainv(i) := dcramov.data(i)(31 downto 16) & edata(15 downto 0);
1176
          end if;
1177
        when others =>
1178
          ddatainv(i) := edata;
1179
        end case;
1180
 
1181
      end loop;
1182
 
1183
-- handle double load with pipeline hold
1184
 
1185
    if (r.dstate = idle) and (r.nomds = '1') then
1186
      rdatav(0) := r.wb.data2; mexc := r.mexc; set := 0; --FIXME
1187
    end if;
1188
 
1189
-- Handle AHB retry. Re-generate bus request and burst
1190
 
1191
    if mcdo.retry = '1' then
1192
      v.req := '1';
1193
      v.burst := r.wb.size(0) and r.wb.size(1) and not r.wb.addr(2);
1194
    end if;
1195
 
1196
-- Generate new valid bits
1197
 
1198
    vmaskdbl := decode(maddress(LINE_HIGH downto LINE_LOW+1));
1199
    if (size = "11") and (read = '0') then
1200
      for i in 0 to (DLINE_SIZE - 1) loop vmaskraw(i) := vmaskdbl(i/2); end loop;
1201
    else
1202
      vmaskraw := decode(maddress(LINE_HIGH downto LINE_LOW));
1203
    end if;
1204
 
1205
    vmask := (others => vmaskraw);
1206
    if r.hit = '1' then
1207
      for i in 0 to DSETS-1 loop vmask(i) := r.valid(i) or vmaskraw; end loop;
1208
    end if;
1209
    if r.dstate = idle then
1210
      for i in 0 to DSETS-1 loop
1211
        vmask(i) := dcramov.tag(i)(dlinesize-1 downto 0) or vmaskraw;
1212
      end loop;
1213
 
1214
    end if;
1215
 
1216
    if (mcdo.mexc or r.flush) = '1' then twrite := '0'; dwrite := '0'; end if;
1217
    if twrite = '1' then
1218
      if tagclear = '1' then vmask := (others => (others => '0')); end if;
1219
      v.valid := vmask;
1220
      if (DSETS>1) and (DCREPLACE = lru) and (tdiagwrite = '0') then
1221
        vl.write := '1'; vl.set := setrepl;
1222
      end if;
1223
    end if;
1224
 
1225
    if (DSETS>1) and (DCREPLACE = lru) and (rl.write = '1') then
1226
      vl.lru(conv_integer(rl.waddr)) :=
1227
        lru_calc(rl.lru(conv_integer(rl.waddr)), conv_integer(rl.set));
1228
    end if;
1229
 
1230
    if tdiagwrite = '1' then -- diagnostic tag write
1231
      if (dsu = 1) and (dci.dsuen = '1') then
1232
        vmask := (others => dci.maddress(dlinesize - 1 downto 0));
1233
      else
1234
         vmask := (others => dci.edata(dlinesize - 1 downto 0));
1235
        newtag(TAG_HIGH downto TAG_LOW) := dci.edata(TAG_HIGH downto TAG_LOW);
1236
        newptag(TAG_HIGH downto TAG_LOW) := dci.edata(TAG_HIGH downto TAG_LOW);
1237
        for i in 0 to 3 loop wlrr(i)  := dci.edata(CTAG_LRRPOS); end loop;
1238
        for i in 0 to DSETS-1 loop wlock(i) := dci.edata(CTAG_LOCKPOS); end loop;
1239
      end if;
1240
    end if;
1241
 
1242
    -- mmureg write
1243
    if mmuregw = '1' then
1244
      case mmudiagaddr is
1245
        when CNR_CTRL =>
1246
          v.mmctrl1.e      := mmuwdata(MMCTRL_E);
1247
          v.mmctrl1.nf     := mmuwdata(MMCTRL_NF);
1248
          v.mmctrl1.pso    := mmuwdata(MMCTRL_PSO);
1249
          v.mmctrl1.tlbdis := mmuwdata(MMCTRL_TLBDIS);
1250
          --custom 
1251
          -- Note: before tlb disable tlb flush is required !!!  
1252
        when CNR_CTXP =>
1253
          v.mmctrl1.ctxp := mmuwdata(MMCTXP_U downto MMCTXP_D);
1254
        when CNR_CTX =>
1255
          v.mmctrl1.ctx  := mmuwdata(MMCTXNR_U downto MMCTXNR_D);
1256
        when CNR_F => null;
1257
        when CNR_FADDR => null;
1258
        when others => null;
1259
      end case;
1260
    end if;
1261
 
1262
 
1263
 
1264
 
1265
-- cache flush
1266
 
1267
    --if (dci.flush or flush or mcdo.dflush) = '1' then
1268
    if (dci.flush or flush ) = '1' then
1269
      v.flush := '1'; v.faddr := (others => '0'); v.pflush := pflush;
1270
      v.pflushr := '1';
1271
      v.pflushaddr := pflushaddr;
1272
      v.pflushtyp := pflushtyp;
1273
    end if;
1274
 
1275
    if r.flush = '1' then
1276
      twrite := '1'; vmask := (others=>(others => '0')); v.faddr := r.faddr +1;
1277
      newtag(TAG_HIGH downto TAG_LOW) := (others => '0');
1278
      newptag(TAG_HIGH downto TAG_LOW) := (others => '0');
1279
      taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;
1280
      wlrr := (others => '0'); v.lrr := '0';
1281
      if (r.faddr(DOFFSET_BITS -1) and not v.faddr(DOFFSET_BITS -1)) = '1' then
1282
        v.flush := '0';
1283
      end if;
1284
      if DSNOOP2 = 2 then
1285
        vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW))) := (others => '0');
1286
      end if;
1287
    end if;
1288
 
1289
-- AHB snoop handling (2), bypass write data on read/write contention
1290
 
1291
    if DSNOOP2 /= 0 then
1292
      if tdiagwrite = '1' then snoopset2 := ddset;
1293
      else snoopset2 := conv_integer(setrepl); end if;
1294
      if DSNOOP2 = 2 then
1295
        vh.taddr := taddr(OFFSET_HIGH downto OFFSET_LOW);
1296
        vh.set := conv_std_logic_vector(set, SETBITS);
1297
        if (twrite = '1') and (r.dstate /= idle) then
1298
          vh.hit(conv_integer(taddr(OFFSET_HIGH downto OFFSET_LOW)))(snoopset2) := '0';
1299
        end if;
1300
      else
1301
        if rs.addr(OFFSET_HIGH  downto OFFSET_LOW) =
1302
          taddr(OFFSET_HIGH  downto OFFSET_LOW)
1303
        then
1304
          if twrite = '0' then
1305
            if snoopwe = '1' then
1306
              vs.writebp(snoopset) := '1';
1307
              if DEST_RW then enable(snoopset) := '0'; end if;
1308
            end if;
1309
          else
1310
            if (snoopwe = '1') and (conv_integer(setrepl) = snoopset) then -- avoid write/write contention
1311
              twrite := '0';
1312
              if DEST_RW then enable(snoopset) := '0'; end if;
1313
            end if;
1314
          end if;
1315
        end if;
1316
      end if;
1317
      if (r.dstate = wread) and ((rbphit and rs.snoop) = '1') then v.hit := '0'; end if;
1318
      if DEST_RW then
1319
        -- disable snoop read enable on write/read contention
1320
        if taddr(OFFSET_HIGH downto OFFSET_LOW) = ahbsi.haddr(OFFSET_HIGH  downto OFFSET_LOW) then
1321
          for i in 0 to DSETS-1 loop
1322
            if (twrite and senable(i)) = '1' then senable(i) := '0'; end if;
1323
          end loop;
1324
        end if;
1325
      end if;
1326
    end if;
1327
 
1328
-- update cache with memory data during read miss
1329
 
1330
    if read = '1' then
1331
      for i in 0 to DSETS-1 loop ddatainv(i) := mcdo.data; end loop;
1332
    end if;
1333
 
1334
-- cache write signals
1335
 
1336
    if twrite = '1' then
1337
      if tdiagwrite = '1' then ctwrite(ddset) := '1';
1338
      else ctwrite(conv_integer(setrepl)) := '1'; end if;
1339
    end if;
1340
    if M_EN then
1341
    if tpwrite = '1' then
1342
      if tdiagwrite = '1' then ctpwrite(ddset) := '1';
1343
      else ctpwrite(conv_integer(setrepl)) := '1'; end if;
1344
    end if;
1345
    end if;
1346
    if dwrite = '1' then
1347
      if ddiagwrite = '1' then cdwrite(ddset) := '1';
1348
      else cdwrite(conv_integer(setrepl)) := '1'; end if;
1349
    end if;
1350
 
1351
    csnoopwe := (others => '0');
1352
    if ((snoopwe and not mcdo.scanen) = '1') then csnoopwe(snoopset) := '1'; end if;
1353
 
1354
     if (r.flush and twrite) = '1' then   -- flush 
1355
       ctwrite := (others => '1'); wlrr := (others => '0'); wlock := (others => '0');
1356
       if M_EN then
1357
         ctpwrite := (others => '1');
1358
       end if;
1359
 
1360
       -- precise flush, ASI_FLUSH_PAGE & ASI_FLUSH_CTX
1361
       if false then                    -- 
1362
      if M_EN then
1363
        if r.pflush = '1' then
1364
          twrite := '0'; ctwrite := (others => '0');
1365
          for i in DSETS-1 downto 0 loop
1366
            wlrr(i) := dcramov.tag(i)(CTAG_LRRPOS);
1367
            wlock(i) := dcramov.tag(i)(CTAG_LOCKPOS);
1368
          end loop;
1369
          if r.pflushr = '0' then
1370
            for i in DSETS-1 downto 0 loop
1371
              pftag(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;
1372
              pftag(TAG_HIGH downto TAG_LOW) := dcramov.tag(i)(TAG_HIGH downto TAG_LOW);
1373
              if ((pftag(VA_I_U downto VA_I_D) = r.pflushaddr(VA_I_U downto VA_I_D)) or
1374
                  (r.pflushtyp = '1')) then
1375
                ctwrite(i) := '1';
1376
                wlrr(i) := '0';
1377
                wlock(i) := '0';
1378
              end if;
1379
            end loop;
1380
          else
1381
            v.faddr := r.faddr;
1382
          end if;
1383
          v.pflushr := not r.pflushr;
1384
        end if;
1385
      end if;
1386
       end if;
1387
 
1388
     end if;
1389
 
1390
     if r.flush2 = '1' then
1391
      vl.lru := (others => (others => '0'));
1392
    end if;
1393
 
1394
 
1395
-- reset
1396
 
1397
    if rst = '0' then
1398
      v.dstate := idle; v.stpend  := '0'; v.req := '0'; v.burst := '0';
1399
      v.read := '0'; v.flush := '0'; v.nomds := '0'; v.holdn := '1';
1400
      v.rndcnt := (others => '0'); v.setrepl := (others => '0');
1401
      v.dsuset := (others => '0');
1402
      v.lrr := '0'; v.lock := '0'; v.flush2 := '1';
1403
      v.cctrl.dcs := "00"; v.cctrl.ics := "00";
1404
      v.cctrl.burst := '0'; v.cctrl.dsnoop := '0';
1405
      v.mmctrl1.e := '0'; v.mmctrl1.nf := '0'; v.mmctrl1.ctx := (others => '0');
1406
      v.mmctrl1.tlbdis := '0';
1407
      v.mmctrl1.pso := '0';
1408
      v.trans_op := '0';
1409
      v.flush_op := '0';
1410
      v.diag_op := '0';
1411
      v.pflush := '0';
1412
      v.pflushr := '0';
1413
      v.mmctrl1.bar := (others => '0');
1414
    end if;
1415
 
1416
    if dsnoop = 0 then v.cctrl.dsnoop := '0'; end if;
1417
 
1418
-- Drive signals
1419
 
1420
    c <= v; cs <= vs;   ch <= vh; -- register inputs
1421
    cl <= vl;
1422
 
1423
    -- tag ram inputs
1424
    senable := senable and not scanen; enable := enable and not scanen;
1425
    if mcdo.scanen = '1' then ctpwrite := (others => '0'); end if;
1426
 
1427
    for i in 0 to DSETS-1 loop
1428
      tag(i)(dlinesize-1 downto 0) := vmask(i);
1429
      tag(i)(TAG_HIGH downto TAG_LOW) := newtag(TAG_HIGH downto TAG_LOW);
1430
      tag(i)(CTAG_LRRPOS) := wlrr(i);
1431
      tag(i)(CTAG_LOCKPOS) := wlock(i);
1432
      ctx(i) := r.mmctrl1.ctx;
1433
      ptag(i)(TAG_HIGH downto TAG_LOW) := newptag(TAG_HIGH downto TAG_LOW);
1434
    end loop;
1435
    dcrami.tag <= tag;
1436
    dcrami.ptag <= ptag;
1437
    dcrami.ctx <= ctx;
1438
    dcrami.tenable   <= enable;
1439
    dcrami.twrite    <= ctwrite;
1440
    dcrami.tpwrite   <= ctpwrite;
1441
    dcrami.flush    <= r.flush;
1442
    dcrami.senable <= senable; --vs.snoop or rs.snoop;
1443
    dcrami.swrite  <= csnoopwe;
1444
    dcrami.saddress(19 downto (OFFSET_HIGH - OFFSET_LOW +1)) <=
1445
        zero32(19 downto (OFFSET_HIGH - OFFSET_LOW +1));
1446
    dcrami.saddress(OFFSET_HIGH - OFFSET_LOW downto 0) <= snoopaddr;
1447
    dcrami.stag(31 downto (TAG_HIGH - TAG_LOW +1)) <=
1448
        zero32(31 downto (TAG_HIGH - TAG_LOW +1));
1449
    dcrami.stag(TAG_HIGH - TAG_LOW downto 0) <= rs.addr(TAG_HIGH downto TAG_LOW);
1450
    dcrami.tdiag <= mcdo.testen & "000";
1451
    dcrami.ddiag <= mcdo.testen & "000";
1452
 
1453
    -- data ram inputs
1454
    dcrami.denable   <= enable;
1455
    dcrami.address(19 downto (OFFSET_HIGH - LINE_LOW + 1)) <= zero32(19 downto (OFFSET_HIGH - LINE_LOW + 1));
1456
    dcrami.address(OFFSET_HIGH - LINE_LOW downto 0) <= taddr;
1457
    dcrami.data <= ddatainv;
1458
    dcrami.dwrite    <= cdwrite;
1459
 
1460
    -- memory controller inputs
1461
    mcdi.address  <= r.wb.addr;
1462
    mcdi.data     <= r.wb.data1;
1463
    mcdi.burst    <= r.burst;
1464
    mcdi.size     <= r.wb.size;
1465
    mcdi.read     <= r.wb.read;
1466
    mcdi.asi      <= r.wb.asi;
1467
    mcdi.lock     <= r.wb.lock;
1468
    mcdi.req      <= r.req;
1469
    mcdi.cache    <= orv(r.cctrl.dcs);
1470
 
1471
    --mcdi.flush    <= r.flush;
1472
 
1473
    -- diagnostic instruction cache access
1474
    dco.icdiag.flush  <= iflush;-- or mcdo.iflush;
1475
    dco.icdiag.pflush <= pflush;
1476
    dco.icdiag.pflushaddr <= pflushaddr;
1477
    dco.icdiag.pflushtyp <= pflushtyp;
1478
    dco.icdiag.read   <= read;
1479
    dco.icdiag.tag    <= (not r.asi(0));-- and (not r.asi(4));
1480
    dco.icdiag.ctx    <= r.asi(4); --ASI_ICTX "10101"
1481
    dco.icdiag.addr   <= r.xaddress;
1482
    dco.icdiag.enable <= r.icenable;
1483
    dco.icdiag.cctrl <= r.cctrl;
1484
    dco.icdiag.scanen  <= mcdo.scanen;
1485
 
1486
    -- IU data cache inputs
1487
    dco.data  <= rdatav;
1488
    dco.mexc  <= mexc;
1489
    dco.set   <= conv_std_logic_vector(set, 2);
1490
    dco.hold  <= r.holdn;
1491
    dco.mds   <= mds;
1492
    dco.werr  <= mcdo.werr;
1493
    dco.idle  <= sidle and not r.stpend;
1494
    dco.scanen  <= mcdo.scanen;
1495
    dco.testen  <= mcdo.testen;
1496
 
1497
    -- MMU
1498
    mmudci.trans_op <= mmudci_trans_op;
1499
    mmudci.transdata.data <= mmudci_transdata_data; --r.vaddr;
1500
    mmudci.transdata.su <= mmudci_su;
1501
    mmudci.transdata.read <= mmudci_read;
1502
    mmudci.transdata.isid <= id_dcache;
1503
    mmudci.transdata.wb_data <= dci.maddress;
1504
 
1505
    mmudci.flush_op <= mmudci_flush_op;
1506
    mmudci.wb_op <= mmudci_wb_op;
1507
    mmudci.diag_op <= mmudci_diag_op;
1508
    mmudci.fsread <= mmudci_fsread;
1509
    mmudci.mmctrl1 <= r.mmctrl1;
1510
 
1511
  end process;
1512
 
1513
-- Local registers
1514
 
1515
    reg1 : process(clk)
1516
    begin if rising_edge(clk ) then r <= c; end if; end process;
1517
 
1518
    sn2 : if DSNOOP2 /= 0 generate
1519
      reg2 : process(sclk)
1520
      begin if rising_edge(sclk ) then rs <= cs; end if; end process;
1521
    end generate;
1522
 
1523
    nosn2 : if DSNOOP2 = 0 generate
1524
      rs.snoop <= '0'; rs.writebp <= (others => '0');
1525
      rs.addr <= (others => '0'); rs.readbpx <= (others => '0');
1526
    end generate;
1527
 
1528
    sn3 : if DSNOOP2 = 2 generate
1529
      reg3 : process(sclk)
1530
      begin if rising_edge(sclk ) then rh <= ch; end if; end process;
1531
    end generate;
1532
    sn3no : if DSNOOP2 /= 2 generate
1533
      rh.hit <= (others => (others => '0'));
1534
      rh.taddr <= (others => '0');
1535
      rh.set <= (others => '0');
1536
    end generate;
1537
 
1538
    reg2 : if (DSETS>1) and (DCREPLACE = lru) generate
1539
      reg2 : process(clk)
1540
      begin if rising_edge(clk ) then rl <= cl; end if; end process;
1541
    end generate;
1542
 
1543
    noreg2 : if (DSETS = 1) or (drepl /= lru) generate
1544
      rl.write <= '0'; rl.waddr <= (others => '0');
1545
      rl.set <= (others => '0'); rl.lru <= (others => (others => '0'));
1546
    end generate;
1547
 
1548
-- pragma translate_off
1549
  chk : process
1550
  begin
1551
    assert not ((DSETS > 2) and (DCREPLACE = lrr)) report
1552
        "Wrong data cache configuration detected: LRR replacement requires 2 sets"
1553
    severity failure;
1554
    wait;
1555
  end process;
1556
-- pragma translate_on
1557
 
1558
end ;
1559
 

powered by: WebSVN 2.1.0

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