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_icache.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:      icache
20
-- File:        icache.vhd
21
-- Author:      Jiri Gaisler, Konrad Eisele - Gaisler Research
22
-- Description: This unit implements the instruction cache controller.
23
------------------------------------------------------------------------------  
24
 
25
library ieee;
26
use ieee.std_logic_1164.all;
27
library grlib;
28
use grlib.amba.all;
29
use grlib.stdlib.all;
30
library gaisler;
31
use gaisler.libiu.all;
32
use gaisler.libcache.all;
33
use gaisler.mmuconfig.all;
34
use gaisler.mmuiface.all;
35
 
36
entity mmu_icache is
37
  generic (
38
    irepl     : integer range 0 to 2  := 0;
39
    isets     : integer range 1 to 4  := 1;
40
    ilinesize : integer range 4 to 8  := 4;
41
    isetsize  : integer range 1 to 256 := 1;
42
    isetlock  : integer range 0 to 1  := 0
43
  );
44
  port (
45
    rst : in  std_logic;
46
    clk : in  std_logic;
47
    ici : in  icache_in_type;
48
    ico : out icache_out_type;
49
    dci : in  dcache_in_type;
50
    dco : in  dcache_out_type;
51
    mcii : out memory_ic_in_type;
52
    mcio : in  memory_ic_out_type;
53
    icrami : out icram_in_type;
54
    icramo : in  icram_out_type;
55
    fpuholdn : in  std_logic;
56
    mmudci : in  mmudc_in_type;
57
    mmuici : out mmuic_in_type;
58
    mmuico : in mmuic_out_type
59
);
60
end;
61
 
62
architecture rtl of mmu_icache is
63
 
64
constant ILINE_BITS   : integer := log2(ilinesize);
65
constant IOFFSET_BITS : integer := 8 +log2(isetsize) - ILINE_BITS;
66
constant TAG_LOW    : integer := IOFFSET_BITS + ILINE_BITS + 2;
67
constant OFFSET_HIGH: integer := TAG_LOW - 1;
68
constant OFFSET_LOW : integer := ILINE_BITS + 2;
69
constant LINE_HIGH  : integer := OFFSET_LOW - 1;
70
constant LINE_LOW   : integer := 2;
71
constant LRR_BIT    : integer := TAG_HIGH + 1;
72
constant PCLOW : integer  := 2;
73
constant ILINE_SIZE : integer := ilinesize;
74
constant ICLOCK_BIT : integer := isetlock;
75
constant ICREPLACE : integer range 0 to 2  := irepl;
76
 
77
constant lline : std_logic_vector((ILINE_BITS -1) downto 0) := (others=>'1');
78
 
79
constant SETBITS : integer := log2x(ISETS);
80
constant ILRUBITS  : integer := lru_table(ISETS);
81
subtype lru_type is std_logic_vector(ILRUBITS-1 downto 0);
82
type lru_array  is array (0 to 2**IOFFSET_BITS-1) of lru_type;  -- lru registers
83
type rdatatype is (itag, idata, memory);        -- sources during cache read
84
 
85
type lru_table_vector_type is array(0 to 3) of std_logic_vector(4 downto 0);
86
type lru_table_type is array (0 to 2**IOFFSET_BITS-1) of lru_table_vector_type;
87
 
88
subtype lock_type is std_logic_vector(0 to ISETS-1);
89
type par_type is array (0 to ISETS-1) of std_logic_vector(1 downto 0);
90
 
91
function lru_set (lru : lru_type; lock : lock_type) return std_logic_vector is
92
variable xlru : std_logic_vector(4 downto 0);
93
variable set  : std_logic_vector(SETBITS-1 downto 0);
94
variable xset : std_logic_vector(1 downto 0);
95
variable unlocked : integer range 0 to ISETS-1;
96
begin
97
 
98
  set := (others => '0'); xlru := (others => '0'); xset := (others => '0');
99
  xlru(ILRUBITS-1 downto 0) := lru;
100
 
101
  if isetlock = 1 then
102
    unlocked := ISETS-1;
103
    for i in ISETS-1 downto 0 loop
104
      if lock(i) = '0' then unlocked := i; end if;
105
    end loop;
106
  end if;
107
 
108
  case ISETS is
109
  when 2 =>
110
    if isetlock = 1 then
111
      if lock(0) = '1' then xset(0) := '1'; else xset(0) := xlru(0); end if;
112
    else xset(0) := xlru(0); end if;
113
  when 3 =>
114
    if isetlock = 1 then
115
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (unlocked), 2);
116
    else
117
      xset := conv_std_logic_vector(lru3_repl_table(conv_integer(xlru)) (0), 2);
118
    end if;
119
  when 4 =>
120
    if isetlock = 1 then
121
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (unlocked), 2);
122
    else
123
      xset := conv_std_logic_vector(lru4_repl_table(conv_integer(xlru)) (0), 2);
124
    end if;
125
  when others =>
126
  end case;
127
  set := xset(SETBITS-1 downto 0);
128
  return(set);
129
end;
130
 
131
function lru_calc (lru : lru_type; set : integer) return lru_type is
132
variable new_lru : lru_type;
133
variable xnew_lru: std_logic_vector(4 downto 0);
134
variable xlru : std_logic_vector(4 downto 0);
135
begin
136
  new_lru := (others => '0'); xnew_lru := (others => '0');
137
  xlru := (others => '0'); xlru(ILRUBITS-1 downto 0) := lru;
138
  case ISETS is
139
  when 2 =>
140
    if set = 0 then xnew_lru(0) := '1'; else xnew_lru(0) := '0'; end if;
141
  when 3 =>
142
    xnew_lru(2 downto 0) := lru_3set_table(conv_integer(lru))(set);
143
  when 4 =>
144
    xnew_lru(4 downto 0) := lru_4set_table(conv_integer(lru))(set);
145
  when others =>
146
  end case;
147
  new_lru := xnew_lru(ILRUBITS-1 downto 0);
148
  return(new_lru);
149
end;
150
 
151
type istatetype is (idle, trans, streaming, stop);
152
type icache_control_type is record                      -- all registers
153
  req, burst, holdn : std_logic;
154
  overrun       : std_logic;                    -- 
155
  underrun      : std_logic;                    -- 
156
  istate        : istatetype;                   -- FSM
157
  waddress      : std_logic_vector(31 downto PCLOW); -- write address buffer
158
  vaddress      : std_logic_vector(31 downto PCLOW); -- virtual address buffer
159
  valid         : std_logic_vector(ILINE_SIZE-1 downto 0); -- valid bits
160
  hit           : std_logic;
161
  su            : std_logic;
162
  flush         : std_logic;                            -- flush in progress
163
  flush2        : std_logic;                            -- flush in progress
164
  flush3        : std_logic;                            -- flush in progress
165
  faddr         : std_logic_vector(IOFFSET_BITS - 1 downto 0);   -- flush address
166
  diagrdy       : std_logic;
167
  rndcnt        : std_logic_vector(log2x(ISETS)-1 downto 0); -- replace counter
168
  lrr           : std_logic;
169
  setrepl       : std_logic_vector(log2x(ISETS)-1 downto 0); -- set to replace
170
  diagset       : std_logic_vector(log2x(ISETS)-1 downto 0);
171
  lock          : std_logic;
172
 
173
  pflush        : std_logic;
174
  pflushr       : std_logic;
175
  pflushaddr    : std_logic_vector(VA_I_U downto VA_I_D);
176
  pflushtyp     : std_logic;
177
  cache         : std_logic;
178
  trans_op      : std_logic;
179
end record;
180
 
181
type lru_reg_type is record
182
  write : std_logic;
183
  waddr : std_logic_vector(IOFFSET_BITS-1 downto 0);
184
  set   : std_logic_vector(SETBITS-1 downto 0); --integer range 0 to ISETS-1;
185
  lru   : lru_array;
186
end record;
187
 
188
signal r, c : icache_control_type;      -- r is registers, c is combinational
189
signal rl, cl : lru_reg_type;           -- rl is registers, cl is combinational
190
 
191
constant icfg : std_logic_vector(31 downto 0) :=
192
        cache_cfg(irepl, isets, ilinesize, isetsize, isetlock, 0, 0, 1, 0, 1);
193
 
194
 
195
begin
196
 
197
  ictrl : process(rst, r, rl, mcio, ici, dci, dco, icramo, fpuholdn, mmuico, mmudci)
198
  variable rdatasel : rdatatype;
199
  variable twrite, diagen, dwrite : std_logic;
200
  variable taddr : std_logic_vector(TAG_HIGH  downto LINE_LOW); -- tag address
201
  variable wtag : std_logic_vector(TAG_HIGH downto TAG_LOW); -- write tag value
202
  variable ddatain : std_logic_vector(31 downto 0);
203
  variable rdata : cdatatype;
204
  variable diagdata : std_logic_vector(31 downto 0);
205
  variable vmaskraw, vmask : std_logic_vector((ILINE_SIZE -1) downto 0);
206
  variable xaddr_inc : std_logic_vector((ILINE_BITS -1) downto 0);
207
  variable lastline, nlastline, nnlastline : std_logic;
208
  variable enable : std_logic;
209
  variable error : std_logic;
210
  variable whit, hit, valid : std_logic;
211
  variable cacheon  : std_logic;
212
  variable v : icache_control_type;
213
  variable branch  : std_logic;
214
  variable eholdn  : std_logic;
215
  variable mds, write  : std_logic;
216
  variable tparerr, dparerr  : std_logic_vector(0 to ISETS-1);
217
  variable set     : integer range 0 to MAXSETS-1;
218
  variable setrepl : std_logic_vector(log2x(ISETS)-1 downto 0); -- set to replace
219
  variable ctwrite, cdwrite, validv : std_logic_vector(0 to MAXSETS-1);
220
  variable wlrr : std_logic;
221
  variable vl : lru_reg_type;
222
  variable vdiagset, rdiagset : integer range 0 to ISETS-1;
223
  variable lock : std_logic_vector(0 to ISETS-1);
224
  variable wlock, sidle : std_logic;
225
  variable tag : cdatatype;
226
 
227
  variable pftag : std_logic_vector(31 downto 2);
228
  variable mmuici_trans_op : std_logic;
229
  variable mmuici_su : std_logic;
230
  begin
231
 
232
-- init local variables
233
 
234
    v := r; vl := rl; vl.write := '0'; vl.set := r.setrepl;
235
    vl.waddr := r.waddress(OFFSET_HIGH downto OFFSET_LOW);
236
 
237
    mds := '1'; dwrite := '0'; twrite := '0'; diagen := '0'; error := '0';
238
    write := mcio.ready; v.diagrdy := '0'; v.holdn := '1';
239
    v.flush3 := r.flush2; sidle := '0';
240
 
241
    cacheon := dco.icdiag.cctrl.ics(0) and not r.flush;
242
    enable := '1'; branch := '0';
243
    eholdn := dco.hold and fpuholdn;
244
 
245
    rdatasel := idata;  -- read data from cache as default
246
    ddatain := mcio.data;       -- load full word from memory
247
    --if M_EN and (mmudci.mmctrl1.e = '1') then wtag := r.vaddress(TAG_HIGH downto TAG_LOW);
248
    --else wtag := r.waddress(TAG_HIGH downto TAG_LOW); end if;
249
    wtag := r.vaddress(TAG_HIGH downto TAG_LOW);
250
    wlrr := r.lrr; wlock := r.lock;
251
 
252
    tparerr := (others => '0'); dparerr := (others => '0');
253
 
254
    set := 0; ctwrite := (others => '0'); cdwrite := (others => '0');
255
    vdiagset := 0; rdiagset := 0; lock := (others => '0');
256
    pftag := (others => '0');
257
 
258
    v.trans_op := r.trans_op and (not mmuico.grant);
259
    mmuici_trans_op := r.trans_op;
260
 
261
 
262
    mmuici_su := ici.su;
263
 
264
-- random replacement counter
265
    if ISETS > 1 then
266
      if conv_integer(r.rndcnt) = (ISETS - 1) then v.rndcnt := (others => '0');
267
      else v.rndcnt := r.rndcnt + 1; end if;
268
    end if;
269
 
270
 
271
-- generate lock bits
272
    if ICLOCK_BIT = 1 then
273
      for i in 0 to ISETS-1 loop lock(i) := icramo.tag(i)(CTAG_LOCKPOS); end loop;
274
    end if;
275
 
276
-- generate cache hit and valid bits    
277
    hit := '0';
278
    for i in ISETS-1 downto 0 loop
279
      if (icramo.tag(i)(TAG_HIGH downto TAG_LOW) = ici.fpc(TAG_HIGH downto TAG_LOW))
280
        and ((icramo.ctx(i) = mmudci.mmctrl1.ctx) or (mmudci.mmctrl1.e = '0'))
281
      then hit := not r.flush; set := i; end if;
282
      validv(i) := genmux(ici.fpc(LINE_HIGH downto LINE_LOW),
283
                          icramo.tag(i)(ilinesize -1 downto 0));
284
    end loop;
285
 
286
    if ici.fpc(LINE_HIGH downto LINE_LOW) = lline then lastline := '1';
287
    else lastline := '0'; end if;
288
 
289
    if r.waddress(LINE_HIGH downto LINE_LOW) = lline((ILINE_BITS -1) downto 0) then
290
      nlastline := '1';
291
    else nlastline := '0'; end if;
292
 
293
    if r.waddress(LINE_HIGH downto LINE_LOW+1) = lline((ILINE_BITS -1) downto 1) then
294
      nnlastline := '1';
295
    else nnlastline := '0'; end if;
296
 
297
    valid := validv(set);
298
 
299
    xaddr_inc := r.waddress(LINE_HIGH downto LINE_LOW) + 1;
300
 
301
    if mcio.ready = '1' then
302
      v.waddress(LINE_HIGH downto LINE_LOW) := xaddr_inc;
303
    end if;
304
 
305
 
306
    xaddr_inc := r.vaddress(LINE_HIGH downto LINE_LOW) + 1;
307
 
308
    if mcio.ready = '1' then
309
      v.vaddress(LINE_HIGH downto LINE_LOW) := xaddr_inc;
310
    end if;
311
 
312
 
313
    taddr := ici.rpc(TAG_HIGH downto LINE_LOW);
314
 
315
-- main Icache state machine
316
 
317
    case r.istate is
318
    when idle =>        -- main state and cache hit
319
      v.valid := icramo.tag(set)(ilinesize-1 downto 0);
320
      v.hit := hit; v.su := ici.su; sidle := '1';
321
 
322
      if eholdn  = '0' then
323
        taddr := ici.fpc(TAG_HIGH downto LINE_LOW);
324
      else taddr := ici.rpc(TAG_HIGH downto LINE_LOW); end if;
325
      v.burst := dco.icdiag.cctrl.burst and not lastline;
326
      if (eholdn and not ici.inull ) = '1' then
327
        if not (cacheon and hit and valid) = '1' then
328
          v.istate := streaming;
329
          v.holdn := '0'; v.overrun := '1';
330
 
331
          if ((mmudci.mmctrl1.e) = '1') then
332
            v.istate := trans;
333
            mmuici_trans_op := '1';
334
            v.trans_op := not mmuico.grant;
335
            v.cache := '0';
336
            --v.req := '0';
337
          else
338
            v.req := '1';
339
            v.cache := '1';
340
          end if;
341
 
342
        else
343
          if (ISETS > 1) and (ICREPLACE = lru) then vl.write := '1'; end if;
344
        end if;
345
        v.waddress := ici.fpc(31 downto PCLOW);
346
        v.vaddress := ici.fpc(31 downto PCLOW);
347
 
348
      end if;
349
      if dco.icdiag.enable = '1' then
350
        diagen := '1';
351
      end if;
352
      ddatain := dci.maddress;
353
      if (ISETS > 1) then
354
        if (ICREPLACE = lru) then
355
          vl.set := conv_std_logic_vector(set, SETBITS);
356
          vl.waddr := ici.fpc(OFFSET_HIGH downto OFFSET_LOW);
357
        end if;
358
        v.setrepl := conv_std_logic_vector(set, SETBITS);
359
        if (((not hit) and (not dparerr(set)) and (not r.flush)) = '1') then
360
          case ICREPLACE is
361
          when rnd =>
362
            if ICLOCK_BIT = 1 then
363
              if lock(conv_integer(r.rndcnt)) = '0' then v.setrepl := r.rndcnt;
364
              else
365
                v.setrepl := conv_std_logic_vector(ISETS-1, SETBITS);
366
                for i in ISETS-1 downto 0 loop
367
                  if (lock(i) = '0') and (i>conv_integer(r.rndcnt)) then
368
                    v.setrepl := conv_std_logic_vector(i, SETBITS);
369
                  end if;
370
                end loop;
371
              end if;
372
            else
373
              v.setrepl := r.rndcnt;
374
            end if;
375
          when lru =>
376
             v.setrepl :=  lru_set(rl.lru(conv_integer(ici.fpc(OFFSET_HIGH downto OFFSET_LOW))), lock(0 to ISETS-1));
377
          when lrr =>
378
            v.setrepl := (others => '0');
379
            if isetlock = 1 then
380
              if lock(0) = '1' then v.setrepl(0) := '1';
381
              else
382
                v.setrepl(0) := icramo.tag(0)(CTAG_LRRPOS) xor icramo.tag(1)(CTAG_LRRPOS);
383
              end if;
384
            else
385
              v.setrepl(0) := icramo.tag(0)(CTAG_LRRPOS) xor icramo.tag(1)(CTAG_LRRPOS);
386
            end if;
387
            if v.setrepl(0) = '0' then v.lrr := not icramo.tag(0)(CTAG_LRRPOS);
388
            else v.lrr := icramo.tag(0)(CTAG_LRRPOS); end if;
389
          end case;
390
        end if;
391
        if (ICLOCK_BIT = 1) then
392
          if (hit and lock(set)) = '1' then v.lock := '1';
393
          else v.lock := '0'; end if;
394
        end if;
395
      end if;
396
    when trans =>
397
 
398
        v.holdn := '0';
399
 
400
        if (mmuico.transdata.finish = '1') then
401
          if (mmuico.transdata.accexc) = '1' and ((mmudci.mmctrl1.nf) /= '1' or (r.su) = '1') then
402
            -- if su then always do mexc
403
            error := '1'; mds := '0';
404
            v.holdn := '1'; v.istate := idle; v.burst := '0';
405
          else
406
            v.cache := mmuico.transdata.cache;
407
            v.waddress := mmuico.transdata.data(31 downto PCLOW);
408
            v.istate := streaming; v.req := '1';
409
          end if;
410
      end if;
411
 
412
    when streaming =>           -- streaming: update cache and send data to IU
413
      rdatasel := memory;
414
      taddr(TAG_HIGH downto LINE_LOW) := r.vaddress(TAG_HIGH downto LINE_LOW);
415
      branch := (ici.fbranch and r.overrun) or
416
                      (ici.rbranch and (not r.overrun));
417
      v.underrun := r.underrun or
418
        (write and ((ici.inull or not eholdn) and (mcio.ready and not (r.overrun and not r.underrun))));
419
      v.overrun := (r.overrun or (eholdn and not ici.inull)) and
420
                    not (write or r.underrun);
421
      if mcio.ready = '1' then
422
        mds := not (r.overrun and not r.underrun);
423
        v.burst := v.req and not (nnlastline and mcio.ready);
424
      end if;
425
      if mcio.grant = '1' then
426
        v.req := dco.icdiag.cctrl.burst and r.burst and
427
                 (not (nnlastline and mcio.ready)) and (dco.icdiag.cctrl.burst or (not branch)) and
428
                 not (v.underrun and not cacheon);
429
        v.burst := v.req and not (nnlastline and mcio.ready);
430
      end if;
431
      v.underrun := (v.underrun or branch) and not v.overrun;
432
      v.holdn := not (v.overrun or v.underrun);
433
      if (mcio.ready = '1') and (r.req = '0') then --(v.burst = '0') then
434
        v.underrun := '0'; v.overrun := '0';
435
        if (dco.icdiag.cctrl.ics(0) and not r.flush2) = '1' then
436
          v.istate := stop; v.holdn := '0';
437
        else
438
          v.istate := idle; v.flush := r.flush2; v.holdn := '1';
439
          if r.overrun = '1' then taddr := ici.fpc(TAG_HIGH downto LINE_LOW);
440
          else taddr := ici.rpc(TAG_HIGH downto LINE_LOW); end if;
441
        end if;
442
      end if;
443
    when stop =>                -- return to main
444
      taddr := ici.fpc(TAG_HIGH downto LINE_LOW);
445
      v.istate := idle; v.flush := r.flush2;
446
    when others => v.istate := idle;
447
    end case;
448
 
449
    if mcio.retry = '1' then v.req := '1'; end if;
450
 
451
-- Generate new valid bits write strobe
452
 
453
    vmaskraw := decode(r.waddress(LINE_HIGH downto LINE_LOW));
454
    twrite := write;
455
    if cacheon = '0' then
456
      twrite := '0'; vmask := (others => '0');
457
    elsif (dco.icdiag.cctrl.ics = "01") then
458
      twrite := twrite and r.hit;
459
      vmask := icramo.tag(set)(ilinesize-1 downto 0) or vmaskraw;
460
    else
461
      if r.hit = '1' then vmask := r.valid or vmaskraw;
462
      else vmask := vmaskraw; end if;
463
    end if;
464
    if (mcio.mexc or (not mcio.cache) or (not r.cache)) = '1' then
465
      twrite := '0'; dwrite := '0';
466
    else dwrite := twrite; end if;
467
    if twrite = '1' then
468
      v.valid := vmask; v.hit := '1';
469
      if (ISETS > 1) and (ICREPLACE = lru) then vl.write := '1'; end if;
470
    end if;
471
 
472
    if (ISETS > 1) and (ICREPLACE = lru) and (rl.write = '1') then
473
      vl.lru(conv_integer(rl.waddr)) :=
474
          lru_calc(rl.lru(conv_integer(rl.waddr)), conv_integer(rl.set));
475
    end if;
476
 
477
-- cache write signals
478
 
479
    if ISETS > 1 then setrepl := r.setrepl; else setrepl := (others => '0'); end if;
480
    if twrite = '1' then ctwrite(conv_integer(setrepl)) := '1'; end if;
481
    if dwrite = '1' then cdwrite(conv_integer(setrepl)) := '1'; end if;
482
 
483
-- diagnostic cache access
484
 
485
    if diagen = '1' then
486
     if (ISETS /= 1) then
487
       v.diagset := dco.icdiag.addr(SETBITS -1 + TAG_LOW downto TAG_LOW);
488
     end if;
489
   end if;
490
 
491
    if (ISETS /= 1) then
492
      rdiagset := conv_integer(r.diagset);
493
      vdiagset := conv_integer(v.diagset);
494
    end if;
495
 
496
    diagdata := icramo.data(rdiagset);
497
    if diagen = '1' then -- diagnostic access
498
      taddr(OFFSET_HIGH downto LINE_LOW) := dco.icdiag.addr(OFFSET_HIGH downto LINE_LOW);
499
      wtag(TAG_HIGH downto TAG_LOW) := dci.maddress(TAG_HIGH downto TAG_LOW);
500
      wlrr := dci.maddress(CTAG_LRRPOS);
501
      wlock := dci.maddress(CTAG_LOCKPOS);
502
      if dco.icdiag.tag = '1' then
503
        twrite := not dco.icdiag.read; dwrite := '0';
504
        ctwrite := (others => '0'); cdwrite := (others => '0');
505
        ctwrite(vdiagset) := not dco.icdiag.read;
506
        diagdata := icramo.tag(rdiagset);
507
      else
508
        dwrite := not dco.icdiag.read; twrite := '0';
509
        cdwrite := (others => '0'); cdwrite(vdiagset) := not dco.icdiag.read;
510
        ctwrite := (others => '0');
511
      end if;
512
      vmask := dci.maddress(ilinesize -1 downto 0);
513
      v.diagrdy := '1';
514
    end if;
515
 
516
-- select data to return on read access
517
 
518
    rdata := icramo.data;
519
    case rdatasel is
520
    when memory => rdata(0) := mcio.data; set := 0;
521
    when others =>
522
    end case;
523
 
524
-- cache flush
525
 
526
    if (ici.flush or dco.icdiag.flush) = '1' then
527
      v.flush := '1'; v.flush2 := '1'; v.faddr := (others => '0');
528
      v.pflush := dco.icdiag.pflush; wtag := (others => '0');
529
      v.pflushr := '1';
530
      v.pflushaddr := dco.icdiag.pflushaddr;
531
      v.pflushtyp := dco.icdiag.pflushtyp;
532
    end if;
533
 
534
    if r.flush2 = '1' then
535
      twrite := '1'; ctwrite := (others => '1'); vmask := (others => '0'); v.faddr := r.faddr +1;
536
      taddr(OFFSET_HIGH downto OFFSET_LOW) := r.faddr; wlrr := '0'; wlock := '0';
537
      if (r.faddr(IOFFSET_BITS -1) and not v.faddr(IOFFSET_BITS -1)) = '1' then
538
        v.flush2 := '0';
539
      end if;
540
      v.lrr := '0';
541
 
542
      -- precise flush, ASI_FLUSH_PAGE & ASI_FLUSH_CTX
543
      --if M_EN then
544
        if r.pflush = '1' then
545
          twrite := '0'; ctwrite := (others => '0');
546
          v.pflushr := not r.pflushr;
547
          if r.pflushr = '0' then
548
            for i in ISETS-1 downto 0 loop
549
              pftag(OFFSET_HIGH downto OFFSET_LOW) := r.faddr;
550
              pftag(TAG_HIGH downto TAG_LOW) := icramo.tag(i)(TAG_HIGH downto TAG_LOW); --icramo.itramout(i).tag;
551
              --if (icramo.itramout(i).ctx = mmudci.mmctrl1.ctx) and
552
              --   ((pftag(VA_I_U downto VA_I_D) = r.pflushaddr(VA_I_U downto VA_I_D)) or
553
              --    (r.pflushtyp = '1')) then
554
                ctwrite(i) := '1';
555
              --end if;
556
            end loop;
557
          end if;
558
        end if;
559
      --end if;
560
    end if;
561
 
562
-- reset
563
 
564
    if rst = '0' then
565
      v.istate := idle; v.req := '0'; v.burst := '0'; v.holdn := '1';
566
      v.flush := '0'; v.flush2 := '0'; v.overrun := '0'; v.underrun := '0';
567
      v.rndcnt := (others => '0'); v.lrr := '0'; v.setrepl := (others => '0');
568
      v.diagset := (others => '0'); v.lock := '0'; v.trans_op := '0';
569
      v.flush3 := '1';
570
    end if;
571
 
572
    if r.flush3 = '1' then
573
      vl.lru := (others => (others => '0'));
574
    end if;
575
 
576
-- Drive signals
577
 
578
    c  <= v;       -- register inputs
579
    cl <= vl;  -- lru register inputs
580
 
581
    -- tag ram inputs
582
    enable := enable and not dco.icdiag.scanen;
583
    for i in 0 to ISETS-1 loop
584
      tag(i) := (others => '0');
585
      tag(i)(ilinesize-1 downto 0) := vmask;
586
      tag(i)(TAG_HIGH downto TAG_LOW) := wtag;
587
      tag(i)(CTAG_LRRPOS) := wlrr;
588
      tag(i)(CTAG_LOCKPOS) := wlock;
589
    end loop;
590
    icrami.tag <= tag;
591
    icrami.tenable   <= enable;
592
    icrami.twrite    <= ctwrite;
593
    icrami.flush    <= r.flush2;
594
    icrami.ctx      <= mmudci.mmctrl1.ctx;
595
 
596
    -- data ram inputs
597
    icrami.denable   <= enable;
598
    icrami.address(19 downto (OFFSET_HIGH - LINE_LOW +1)) <=
599
        zero32(19 downto (OFFSET_HIGH - LINE_LOW +1));
600
    icrami.address(OFFSET_HIGH - LINE_LOW downto 0) <= taddr(OFFSET_HIGH downto LINE_LOW);
601
    icrami.data     <= ddatain;
602
    icrami.dwrite    <= cdwrite;
603
 
604
    -- memory controller inputs
605
    mcii.address(31 downto 2)  <= r.waddress(31 downto 2);
606
    mcii.address(1 downto 0)  <= "00";
607
    mcii.su       <= r.su;
608
    mcii.burst    <= r.burst;
609
    mcii.req      <= r.req;
610
    mcii.flush    <= r.flush;
611
 
612
    -- mmu <-> icache
613
    mmuici.trans_op <= mmuici_trans_op;
614
    mmuici.transdata.data <= r.waddress(31 downto 2) & "00";
615
    mmuici.transdata.su   <= r.su;
616
    mmuici.transdata.isid <= id_icache;
617
    mmuici.transdata.read <= '1';
618
    mmuici.transdata.wb_data <= (others => '0');
619
 
620
    -- IU data cache inputs
621
    ico.data      <= rdata;
622
    ico.mexc      <= mcio.mexc or error;
623
    ico.hold      <= r.holdn;
624
    ico.mds       <= mds;
625
    ico.flush     <= r.flush;
626
    ico.diagdata  <= diagdata;
627
    ico.diagrdy   <= r.diagrdy;
628
    ico.set       <= conv_std_logic_vector(set, 2);
629
    ico.cfg       <= icfg;
630
    ico.idle      <= sidle;
631
 
632
  end process;
633
 
634
-- Local registers
635
 
636
 
637
  regs1 : process(clk)
638
  begin if rising_edge(clk) then r <= c; end if; end process;
639
 
640
  regs2gen : if (ISETS > 1) and (ICREPLACE = lru) generate
641
    regs2 : process(clk)
642
    begin if rising_edge(clk) then rl <= cl; end if; end process;
643
  end generate;
644
 
645
  nolru : if (ISETS = 1) or (irepl /= lru) generate
646
    rl.write <= '0'; rl.waddr <= (others => '0');
647
    rl.set <= (others => '0'); rl.lru <= (others => (others => '0'));
648
  end generate;
649
 
650
-- pragma translate_off
651
  chk : process
652
  begin
653
    assert not ((ISETS > 2) and (ICREPLACE = lrr)) report
654
        "Wrong instruction cache configuration detected: LRR replacement requires 2 sets"
655
    severity failure;
656
    wait;
657
  end process;
658
-- pragma translate_on
659
 
660
end ;
661
 

powered by: WebSVN 2.1.0

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