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

Subversion Repositories core_arm

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 tarookumic
----------------------------------------------------------------------------
2
--  This file is a part of the LEON VHDL model
3
--  Copyright (C) 2003  Gaisler Research, all rights reserved
4
--
5
--  This library is free software; you can redistribute it and/or
6
--  modify it under the terms of the GNU Lesser General Public
7
--  License as published by the Free Software Foundation; either
8
--  version 2 of the License, or (at your option) any later version.
9
--
10
--  See the file COPYING.LGPL for the full details of the license.
11
----------------------------------------------------------------------------
12
 
13
-- Konrad Eisele<eiselekd@web.de> ,2002  
14
 
15
library ieee;
16
use ieee.std_logic_1164.all;
17
use IEEE.std_logic_arith.all;
18
use IEEE.std_logic_unsigned."+";
19
use work.leon_iface.all;
20
use work.mmuconfig.all;
21
use work.mmulib.all;
22
use work.tech_map.all;
23
use work.leon_config.all;
24
use work.macro.all;
25
use work.leon_target.all;
26
 
27
entity mmutlb is
28
  generic (
29
    entries : integer := 8
30
  );
31
  port (
32
    rst   : in  std_logic;
33
    clk   : in  clk_type;
34
    tlbi  : in  mmutlb_in_type;
35
    tlbo  : out mmutlb_out_type;
36
    two   : in  mmutw_out_type;
37
    twi   : out mmutw_in_type
38
    );
39
end mmutlb;
40
 
41
architecture rtl of mmutlb is
42
 
43
  constant entries_log : integer := log2(entries);
44
  constant entries_max : std_logic_vector(entries_log-1 downto 0) :=
45
        std_logic_vector(conv_unsigned(entries-1, entries_log));
46
 
47
  type states  is (idle, match, walk, pack, flush, sync, diag, dofault);
48
  type tlb_rtype is record
49
      s1_valid    : std_logic;
50
 
51
      s2_tlbstate : states;
52
      s2_valid    : std_logic;
53
      s2_entry    : std_logic_vector(entries_log-1 downto 0);
54
      s2_hm       : std_logic;
55
      s2_needsync : std_logic;
56
      s2_data     : std_logic_vector(31 downto 0);
57
      s2_isid     : mmu_idcache;
58
      s2_su       : std_logic;
59
      s2_read     : std_logic;
60
      s2_flush    : std_logic;
61
 
62
      walk_use       : std_logic;
63
      walk_transdata : mmuidc_data_out_type;
64
      walk_fault     : mmutlbfault_out_type;
65
 
66
      nrep        : std_logic_vector(entries_log-1 downto 0);
67
      tpos        : std_logic_vector(entries_log-1 downto 0);
68
      touch       : std_logic;
69
      sync_isw    : std_logic;
70
      hold        : std_logic;
71
  end record;
72
  signal c,r   : tlb_rtype;
73
 
74
  -- tlb cams
75
  component mmutlbcam
76
    port (
77
      rst     : in std_logic;
78
      clk     : in clk_type;
79
      tlbcami : in mmutlbcam_in_type;
80
      tlbcamo : out mmutlbcam_out_type
81
      );
82
  end component;
83
  signal tlbcami     : mmutlbcami_a (M_ENT_MAX-1 downto 0);
84
  signal tlbcamo     : mmutlbcamo_a (M_ENT_MAX-1 downto 0);
85
 
86
  -- least recently used
87
  component mmulru
88
    generic (
89
      entries  : integer := 8
90
    );
91
    port (
92
      clk   : in clk_type;
93
      rst   : in std_logic;
94
      lrui  : in mmulru_in_type;
95
      lruo  : out mmulru_out_type
96
    );
97
  end component;
98
  signal lrui  : mmulru_in_type;
99
  signal lruo  : mmulru_out_type;
100
 
101
  -- data-ram syncram signals
102
  signal dr1_addr         : std_logic_vector(entries_log-1 downto 0);
103
  signal dr1_datain       : std_logic_vector(29 downto 0);
104
  signal dr1_dataout      : std_logic_vector(29 downto 0);
105
  signal dr1_enable       : std_logic;
106
  signal dr1_write        : std_logic;
107
 
108
begin
109
 
110
 
111
 
112
  p0: process (clk, rst, r, c, tlbi, two, tlbcamo, dr1_dataout, lruo)
113
    variable v                    : tlb_rtype;
114
    variable finish, selstate      : std_logic;
115
 
116
    variable cam_hitaddr          : std_logic_vector(M_ENT_MAX_LOG -1 downto 0);
117
    variable cam_hit_all          : std_logic;
118
    variable mtag,ftag            : tlbcam_tfp;
119
 
120
    -- tlb cam input
121
    variable tlbcam_trans_op      : std_logic;
122
    variable tlbcam_write_op      : std_logic_vector(entries-1 downto 0);
123
    variable tlbcam_flush_op      : std_logic;
124
 
125
    -- tw inputs
126
    variable twi_walk_op_ur       : std_logic;
127
    variable twi_data             : std_logic_vector(31 downto 0);
128
    variable twi_areq_ur          : std_logic;
129
    variable twi_aaddr            : std_logic_vector(31 downto 0);
130
    variable twi_adata            : std_logic_vector(31 downto 0);
131
 
132
    variable two_error            : std_logic;
133
 
134
    -- lru inputs
135
    variable lrui_touch           : std_logic;
136
    variable lrui_touchmin        : std_logic;
137
    variable lrui_pos             : std_logic_vector(entries_log-1 downto 0);
138
 
139
    -- syncram inputs
140
    variable dr1write             : std_logic;
141
 
142
 
143
    -- hit tlbcam's output 
144
    variable ACC                  : std_logic_vector(2 downto 0);
145
    variable PTE                  : std_logic_vector(31 downto 0);
146
    variable LVL                  : std_logic_vector(1 downto 0);
147
    variable CAC                  : std_logic;
148
    variable NEEDSYNC             : std_logic;
149
 
150
    variable twACC                : std_logic_vector(2 downto 0);
151
    variable tWLVL                : std_logic_vector(1 downto 0);
152
    variable twPTE                : std_logic_vector(31 downto 0);
153
    variable twNEEDSYNC           : std_logic;
154
 
155
 
156
    variable tlbcam_tagin         : tlbcam_tfp;
157
    variable tlbcam_tagwrite      : tlbcam_reg;
158
 
159
    variable store                : std_logic;
160
 
161
    variable reppos               : std_logic_vector(entries_log-1 downto 0);
162
    variable i_entry              : integer range 0 to M_ENT_MAX-1;
163
    variable i_reppos             : integer range 0 to M_ENT_MAX-1;
164
 
165
    variable fault_pro, fault_pri  : std_logic;
166
    variable fault_mexc, fault_trans, fault_inv, fault_access  : std_logic;
167
 
168
    variable transdata : mmuidc_data_out_type;
169
    variable fault     : mmutlbfault_out_type;
170
    variable savewalk  : std_logic;
171
    variable tlbo_s1finished : std_logic;
172
 
173
  begin
174
 
175
    v := r;
176
 
177
 
178
 
179
    finish := '0';
180
    selstate := '0';
181
 
182
    cam_hitaddr := (others => '0');
183
    cam_hit_all := '0';
184
 
185
    mtag.TYP := (others => '0');
186
    mtag.I1 := (others => '0');
187
    mtag.I2 := (others => '0');
188
    mtag.I3 := (others => '0');
189
    mtag.CTX := (others => '0');
190
    mtag.M := '0';
191
    ftag.TYP := (others => '0');
192
    ftag.I1 := (others => '0');
193
    ftag.I2 := (others => '0');
194
    ftag.I3 := (others => '0');
195
    ftag.CTX := (others => '0');
196
    ftag.M := '0';
197
 
198
 
199
    tlbcam_trans_op := '0';
200
    tlbcam_write_op := (others => '0');
201
    tlbcam_flush_op := '0';
202
 
203
    twi_walk_op_ur := '0';
204
    twi_data := (others => '0');
205
    twi_areq_ur := '0';
206
    twi_aaddr := (others => '0');
207
    twi_adata := (others => '0');
208
 
209
    two_error := '0';
210
    lrui_touch:= '0';
211
    lrui_touchmin:= '0';
212
    lrui_pos := (others => '0');
213
 
214
    dr1write := '0';
215
 
216
    ACC := (others => '0');
217
    PTE := (others => '0');
218
    LVL := (others => '0');
219
    CAC := '0';
220
    NEEDSYNC := '0';
221
 
222
    twACC := (others => '0');
223
    tWLVL := (others => '0');
224
    twPTE := (others => '0');
225
    twNEEDSYNC := '0';
226
 
227
    tlbcam_tagin.TYP := (others => '0');
228
    tlbcam_tagin.I1 := (others => '0');
229
    tlbcam_tagin.I2 := (others => '0');
230
    tlbcam_tagin.I3 := (others => '0');
231
    tlbcam_tagin.CTX := (others => '0');
232
    tlbcam_tagin.M := '0';
233
 
234
    tlbcam_tagwrite.ET := (others => '0');
235
    tlbcam_tagwrite.ACC := (others => '0');
236
    tlbcam_tagwrite.M := '0';
237
    tlbcam_tagwrite.R := '0';
238
    tlbcam_tagwrite.SU := '0';
239
    tlbcam_tagwrite.VALID := '0';
240
    tlbcam_tagwrite.LVL := (others => '0');
241
    tlbcam_tagwrite.I1 := (others => '0');
242
    tlbcam_tagwrite.I2 := (others => '0');
243
    tlbcam_tagwrite.I3 := (others => '0');
244
    tlbcam_tagwrite.CTX := (others => '0');
245
    tlbcam_tagwrite.PPN := (others => '0');
246
    tlbcam_tagwrite.C := '0';
247
 
248
    store := '0';
249
    reppos := (others => '0');
250
    fault_pro := '0';
251
    fault_pri := '0';
252
    fault_mexc := '0';
253
    fault_trans := '0';
254
    fault_inv := '0';
255
    fault_access := '0';
256
 
257
    transdata.finish := '0';
258
    transdata.data := (others => '0');
259
    transdata.cache := '0';
260
    transdata.accexc := '0';
261
 
262
    fault.fault_pro := '0';
263
    fault.fault_pri := '0';
264
    fault.fault_access := '0';
265
    fault.fault_mexc := '0';
266
    fault.fault_trans := '0';
267
    fault.fault_inv := '0';
268
    fault.fault_lvl := (others => '0');
269
    fault.fault_su := '0';
270
    fault.fault_read := '0';
271
    fault.fault_isid := id_dcache;
272
    fault.fault_addr := (others => '0');
273
 
274
    savewalk := '0';
275
    tlbo_s1finished := '0';
276
 
277
 
278
 
279
 
280
 
281
 
282
 
283
 
284
 
285
 
286
 
287
 
288
 
289
    tlbcam_trans_op := '0'; tlbcam_write_op := (others => '0'); tlbcam_flush_op := '0';
290
    lrui_touch := '0'; lrui_touchmin := '0'; lrui_pos := (others => '0');
291
    dr1write := '0';
292
    fault_pro := '0'; fault_pri := '0'; fault_mexc := '0'; fault_trans := '0'; fault_inv := '0'; fault_access := '0';
293
    twi_walk_op_ur := '0'; twi_areq_ur := '0'; twi_aaddr := dr1_dataout&"00";
294
    finish := '0';
295
    store := '0'; v.hold := '0'; savewalk := '0'; tlbo_s1finished := '0';
296
    selstate := '0';
297
 
298
    cam_hitaddr := (others => '0');
299
    cam_hit_all := '0';
300
    NEEDSYNC := '0';
301
    for i in entries-1 downto 0 loop
302
      NEEDSYNC := NEEDSYNC or tlbcamo(i).NEEDSYNC;
303
      if (tlbcamo(i).hit) = '1' then
304
        cam_hitaddr(entries_log-1 downto 0) := cam_hitaddr(entries_log-1 downto 0) or std_logic_vector(conv_unsigned(i, entries_log));
305
        cam_hit_all := '1';
306
      end if;
307
    end loop;
308
 
309
    -- tlbcam write operation
310
    tlbcam_tagwrite := TLB_CreateCamWrite( two.data, r.s2_read, two.lvl, tlbi.mmctrl1.ctx, r.s2_data);
311
 
312
    -- replacement position
313
    reppos := (others => '0');
314
    if TLB_REP = replruarray then
315
      reppos := lruo.pos(entries_log-1 downto 0);
316
      v.touch := '0';
317
    elsif TLB_REP = repincrement then
318
      reppos := r.nrep;
319
    end if;
320
 
321
    -- pragma translate_off
322
    if not is_x(reppos) then
323
    -- pragma translate_on
324
      i_reppos := conv_integer(unsigned(reppos));
325
    -- pragma translate_off
326
    end if;
327
    -- pragma translate_on
328
 
329
    -- tw
330
    two_error := two.fault_mexc or two.fault_trans or two.fault_inv;
331
 
332
    twACC := two.data(PTE_ACC_U downto PTE_ACC_D);
333
    twLVL := two.lvl;
334
    twPTE := two.data;
335
    twNEEDSYNC := (not two.data(PTE_R)) or ((not r.s2_read) and (not two.data(PTE_M))); -- tw : writeback on next flush
336
 
337
 
338
    case r.s2_tlbstate is
339
 
340
      when idle =>
341
 
342
        if (tlbi.s2valid) = '1' then
343
          if r.s2_flush = '1' then
344
            v.s2_tlbstate := pack;
345
            v.s2_flush := '0';
346
          else
347
            v.walk_fault.fault_pri := '0';
348
            v.walk_fault.fault_pro := '0';
349
            v.walk_fault.fault_access := '0';
350
            v.walk_fault.fault_trans := '0';
351
            v.walk_fault.fault_inv := '0';
352
            v.walk_fault.fault_mexc := '0';
353
 
354
            if (r.s2_hm and not tlbi.mmctrl1.tlbdis )  = '1' then
355
              if r.s2_needsync = '1' then
356
                v.s2_tlbstate := sync;
357
              else
358
                finish := '1';
359
              end if;
360
 
361
              if TLB_REP = replruarray then
362
                v.tpos := r.s2_entry; v.touch := '1';  -- touch lru
363
              end if;
364
 
365
            else
366
              v.s2_tlbstate := walk;
367
              if TLB_REP = replruarray then
368
                lrui_touchmin := '1';             -- lru element consumed
369
              end if;
370
            end if;
371
          end if;
372
        end if;
373
 
374
      when walk =>
375
 
376
        if (two.finish = '1') then
377
          if ( two_error ) = '0' then
378
            tlbcam_write_op := decode(r.s2_entry);
379
            dr1write := '1';
380
            TLB_CheckFault( twACC, r.s2_isid, r.s2_su, r.s2_read, v.walk_fault.fault_pro, v.walk_fault.fault_pri );
381
          end if;
382
 
383
          TLB_MergeData( two.lvl , two.data, r.s2_data, v.walk_transdata.data );
384
          v.walk_transdata.cache := two.data(PTE_C);
385
          v.walk_fault.fault_lvl := two.fault_lvl;
386
          v.walk_fault.fault_access := '0';
387
          v.walk_fault.fault_mexc := two.fault_mexc;
388
          v.walk_fault.fault_trans := two.fault_trans;
389
          v.walk_fault.fault_inv := two.fault_inv;
390
          v.walk_use := '1';
391
 
392
          if ( twNEEDSYNC = '0' or two_error = '1') then
393
            v.s2_tlbstate := pack;
394
          else
395
            v.s2_tlbstate := sync;
396
            v.sync_isw := '1';
397
          end if;
398
 
399
          if TLB_REP = repincrement then
400
            if (r.nrep = entries_max) then v.nrep := (others => '0');
401
            else  v.nrep := r.nrep + 1;
402
            end if;
403
          end if;
404
        else
405
          twi_walk_op_ur := '1';
406
        end if;
407
 
408
      when pack =>
409
        v.walk_use := '0';
410
        finish := '1';
411
        v.s2_tlbstate := idle;
412
 
413
      when sync =>
414
 
415
        tlbcam_trans_op := '1';
416
        if ( v.sync_isw = '1') then
417
          -- pte address is currently written to syncram, wait one cycle before issuing twi_areq_ur
418
          v.sync_isw := '0';
419
        else
420
          if (two.finish = '1') then
421
            v.s2_tlbstate := pack;
422
            v.walk_fault.fault_mexc := two.fault_mexc;
423
            if (two.fault_mexc) = '1' then
424
              v.walk_use := '1';
425
            end if;
426
          else
427
            twi_areq_ur := '1';
428
          end if;
429
        end if;
430
 
431
 
432
      when others =>
433
        v .s2_tlbstate := idle;
434
    end case;
435
 
436
    if selstate = '1' then
437
      if tlbi.trans_op = '1' then
438
      elsif tlbi.flush_op = '1' then
439
      end if;
440
    end if;
441
 
442
    -- pragma translate_off
443
    if not is_x(r.s2_entry) then
444
    -- pragma translate_on
445
      i_entry := conv_integer(unsigned(r.s2_entry));
446
    -- pragma translate_off
447
    end if;
448
    -- pragma translate_on
449
 
450
    ACC := tlbcamo(i_entry).pteout(PTE_ACC_U downto PTE_ACC_D);
451
    PTE := tlbcamo(i_entry).pteout;
452
    LVL := tlbcamo(i_entry).LVL;
453
    CAC := tlbcamo(i_entry).pteout(PTE_C);
454
 
455
    transdata.cache := CAC;
456
 
457
    --# fault, todo: should we flush on a fault?
458
    TLB_CheckFault( ACC, r.s2_isid, r.s2_su, r.s2_read, fault_pro, fault_pri );
459
 
460
    fault.fault_pro    := '0';
461
    fault.fault_pri    := '0';
462
    fault.fault_access := '0';
463
    fault.fault_mexc   := '0';
464
    fault.fault_trans  := '0';
465
    fault.fault_inv    := '0';
466
    if finish = '1' then
467
      fault.fault_pro    := fault_pro;
468
      fault.fault_pri    := fault_pri;
469
      fault.fault_access := fault_access;
470
      fault.fault_mexc   := fault_mexc;
471
      fault.fault_trans  := fault_trans;
472
      fault.fault_inv    := fault_inv;
473
    end if;
474
 
475
    --# merge data
476
    TLB_MergeData( LVL, PTE, r.s2_data, transdata.data );
477
 
478
    --# reset
479
    if (rst = '0') then
480
      v.s2_tlbstate := idle;
481
      if TLB_REP = repincrement then
482
        v.nrep := (others => '0');
483
      end if;
484
      if TLB_REP = replruarray then
485
        v.touch := '0';
486
      end if;
487
    end if;
488
 
489
    if (finish = '1') or (tlbi.s2valid = '0') then
490
      tlbo_s1finished := '1';
491
      v.s2_hm := cam_hit_all;
492
      v.s2_entry := cam_hitaddr(entries_log-1 downto 0);
493
      v.s2_needsync := NEEDSYNC;
494
      v.s2_data := tlbi.transdata.data;
495
      v.s2_read := tlbi.transdata.read;
496
      v.s2_su := tlbi.transdata.su;
497
      v.s2_isid := tlbi.transdata.isid;
498
      v.s2_flush := tlbi.flush_op;
499
    end if;
500
 
501
    -- translation operation tag
502
    mtag := TLB_CreateCamTrans( tlbi.transdata.data, tlbi.transdata.read, tlbi.mmctrl1.ctx );
503
    tlbcam_tagin := mtag;
504
 
505
    -- flush/(probe) operation tag
506
    ftag := TLB_CreateCamFlush( r.s2_data, tlbi.mmctrl1.ctx );
507
    if (r.s2_flush = '1') then
508
      tlbcam_tagin := ftag;
509
    end if;
510
 
511
    if r.walk_use = '1' then
512
      transdata  := r.walk_transdata;
513
      fault      := r.walk_fault;
514
    end if;
515
    fault.fault_read   := r.s2_read;
516
    fault.fault_su     := r.s2_su;
517
    fault.fault_isid   := r.s2_isid;
518
    fault.fault_addr   := r.s2_data;
519
 
520
    transdata.finish := finish;
521
    transdata.accexc := '0';
522
 
523
 
524
    twi_adata := PTE;
525
 
526
    --# drive signals
527
    tlbo.transdata    <= transdata;
528
    tlbo.fault        <= fault;
529
    tlbo.nexttrans    <= store;
530
    tlbo.s1finished   <= tlbo_s1finished;
531
 
532
    twi.walk_op_ur    <= twi_walk_op_ur;
533
    twi.data          <= r.s2_data;
534
    twi.areq_ur       <= twi_areq_ur;
535
    twi.adata         <= twi_adata;
536
    twi.aaddr         <= twi_aaddr;
537
 
538
    if TLB_REP = replruarray then
539
      lrui.touch        <= r.touch;
540
      lrui.touchmin     <= lrui_touchmin;
541
      lrui.pos          <= (others => '0');
542
      lrui.pos(entries_log-1 downto 0)          <= r.tpos;
543
      lrui.mmctrl1      <= tlbi.mmctrl1;
544
    end if;
545
 
546
    dr1_addr          <= r.s2_entry;
547
    dr1_datain        <= two.addr(31 downto 2);
548
    dr1_enable        <= '1';
549
    dr1_write         <= dr1write;
550
 
551
    for i in entries-1 downto 0 loop
552
      tlbcami(i).tagin     <= tlbcam_tagin;
553
      tlbcami(i).trans_op  <= tlbi.trans_op; --tlbcam_trans_op;
554
      tlbcami(i).flush_op  <= r.s2_flush;
555
      tlbcami(i).mmuen     <= tlbi.mmctrl1.e;
556
      tlbcami(i).tagwrite  <= tlbcam_tagwrite;
557
      tlbcami(i).write_op  <= tlbcam_write_op(i);
558
    end loop;  -- i
559
 
560
    c <= v;
561
  end process p0;
562
 
563
 
564
  p1: process (clk)
565
  begin if rising_edge(clk) then r <= c;  end if;
566
  end process p1;
567
 
568
  -- tag-cam tlb entries
569
  tlbcam0: for i in entries-1 downto 0 generate
570
    tag0 : mmutlbcam port map (rst, clk, tlbcami(i), tlbcamo(i));
571
  end generate tlbcam0;
572
 
573
  -- data-ram syncram 
574
  dataram : syncram
575
    generic map ( dbits => 30, abits => entries_log)
576
    port map ( dr1_addr, clk, dr1_datain, dr1_dataout, dr1_enable, dr1_write);
577
 
578
  -- lru
579
  lru0: if TLB_REP = replruarray generate
580
    lru : mmulru
581
      generic map ( entries => entries)
582
      port map ( clk, rst, lrui, lruo );
583
  end generate lru0;
584
 
585
end rtl;

powered by: WebSVN 2.1.0

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