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

Subversion Repositories core_arm

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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