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

Subversion Repositories core_arm

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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