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

Subversion Repositories core_arm

[/] [core_arm/] [trunk/] [vhdl/] [sparc/] [mmu.vhd] - Blame information for rev 5

Go to most recent revision | 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
-- $#author : Konrad Eisele,2002 {eiselekd@web.de}; 
14
library ieee;
15
use ieee.std_logic_1164.all;
16
use work.leon_iface.all;
17
use work.mmuconfig.all;
18
use work.leon_target.all;
19
 
20
entity mmu is
21
  port (
22
    rst  : in std_logic;
23
    clk  : in clk_type;
24
 
25
    mmudci : in  mmudc_in_type;
26
    mmudco : out mmudc_out_type;
27
 
28
    mmuici : in  mmuic_in_type;
29
    mmuico : out mmuic_out_type;
30
 
31
    mcmmo  : in  memory_mm_out_type;
32
    mcmmi  : out memory_mm_in_type
33
    );
34
end mmu;
35
 
36
architecture rtl of mmu is
37
 
38
  type mmu_op is record
39
    trans_op  : std_logic;
40
    flush_op  : std_logic;
41
    diag_op   : std_logic;
42
  end record;
43
 
44
  type mmu_cmbpctrl is record
45
    tlbowner     : mmu_idcache;
46
    tlbactive    : std_logic;
47
    op           : mmu_op;
48
  end record;
49
 
50
 
51
  type mmu_rtype is record
52
      cmb_s1          : mmu_cmbpctrl;
53
      cmb_s2          : mmu_cmbpctrl;
54
 
55
      splt_is1          : mmu_cmbpctrl;
56
      splt_is2          : mmu_cmbpctrl;
57
      splt_ds1          : mmu_cmbpctrl;
58
      splt_ds2          : mmu_cmbpctrl;
59
 
60
      twactive     : std_logic;        -- split tlb
61
      twowner      : mmu_idcache;        -- split tlb
62
 
63
      flush         : std_logic;
64
      mmctrl2       : mmctrl_type2;
65
      --#dump
66
      -- pragma translate_off
67
      -- pragma translate_on      
68
  end record;
69
  signal r, c   : mmu_rtype;
70
 
71
  -- tlb
72
  component mmutlb
73
    generic (
74
      entries : integer := 8
75
      );
76
    port (
77
      rst   : in std_logic;
78
      clk   : in clk_type;
79
      tlbi  : in mmutlb_in_type;
80
      tlbo  : out mmutlb_out_type;
81
      two  : in mmutw_out_type;
82
      twi  : out mmutw_in_type
83
      );
84
  end component;
85
  signal tlbi_a : mmutlbi_a(1 downto 0);
86
  signal tlbo_a : mmutlbo_a(1 downto 0);
87
  signal twi_a : mmutwi_a(1 downto 0);
88
  signal two_a : mmutwo_a(1 downto 0);
89
 
90
  -- table walk
91
  component mmutw
92
  port (
93
    rst     : in  std_logic;
94
    clk     : in  std_logic;
95
    mmctrl1 : in  mmctrl_type1;
96
    twi     : in  mmutw_in_type;
97
    two     : out mmutw_out_type;
98
    mcmmo   : in  memory_mm_out_type;
99
    mcmmi   : out memory_mm_in_type
100
    );
101
  end component;
102
  signal twi     : mmutw_in_type;
103
  signal two     : mmutw_out_type;
104
  signal mmctrl1 : mmctrl_type1;
105
 
106
begin
107
 
108
  p1: process (clk)
109
  begin if rising_edge(clk) then r <= c; end if;
110
  end process p1;
111
 
112
 
113
  p0: process (clk, rst, r, c, mmudci, mmuici, mcmmo, tlbo_a(0), tlbo_a(1), tlbi_a(0), tlbi_a(1), two_a(0), two_a(1), twi_a(0), twi_a(1), two)
114
    variable cmbtlbin     : mmuidc_data_in_type;
115
    variable cmbtlbout    : mmutlb_out_type;
116
 
117
    variable spltitlbin     : mmuidc_data_in_type;
118
    variable spltdtlbin     : mmuidc_data_in_type;
119
    variable spltitlbout    : mmutlb_out_type;
120
    variable spltdtlbout    : mmutlb_out_type;
121
 
122
 
123
 
124
    variable mmuico_transdata : mmuidc_data_out_type;
125
    variable mmudco_transdata : mmuidc_data_out_type;
126
    variable mmuico_grant : std_logic;
127
    variable mmudco_grant : std_logic;
128
    variable v            : mmu_rtype;
129
    variable twiv         : mmutw_in_type;
130
    variable twod, twoi   : mmutw_out_type;
131
    variable fault       : mmutlbfault_out_type;
132
 
133
 
134
    variable fs : mmctrl_fs_type;
135
    variable fa : std_logic_vector(VA_I_SZ-1 downto 0);
136
  begin
137
 
138
    v := r;
139
 
140
    cmbtlbin.data := (others => '0');
141
    cmbtlbin.su := '0';
142
    cmbtlbin.read := '0';
143
    cmbtlbin.isid := id_dcache;
144
 
145
    cmbtlbout.transdata.finish := '0';
146
    cmbtlbout.transdata.data := (others => '0');
147
    cmbtlbout.transdata.cache := '0';
148
    cmbtlbout.transdata.accexc := '0';
149
 
150
    cmbtlbout.fault.fault_pro := '0';
151
    cmbtlbout.fault.fault_pri := '0';
152
    cmbtlbout.fault.fault_access := '0';
153
    cmbtlbout.fault.fault_mexc := '0';
154
    cmbtlbout.fault.fault_trans := '0';
155
    cmbtlbout.fault.fault_inv := '0';
156
    cmbtlbout.fault.fault_lvl := (others => '0');
157
    cmbtlbout.fault.fault_su  := '0';
158
    cmbtlbout.fault.fault_read := '0';
159
    cmbtlbout.fault.fault_isid  := id_dcache;
160
    cmbtlbout.fault.fault_addr := (others => '0');
161
 
162
    cmbtlbout.nexttrans := '0';
163
    cmbtlbout.s1finished := '0';
164
 
165
    mmuico_transdata.finish := '0';
166
    mmuico_transdata.data := (others => '0');
167
    mmuico_transdata.cache := '0';
168
    mmuico_transdata.accexc := '0';
169
 
170
    mmudco_transdata.finish := '0';
171
    mmudco_transdata.data := (others => '0');
172
    mmudco_transdata.cache := '0';
173
    mmudco_transdata.accexc := '0';
174
 
175
    mmuico_grant := '0';
176
    mmudco_grant := '0';
177
 
178
    twiv.walk_op_ur := '0';
179
    twiv.areq_ur := '0';
180
 
181
    twiv.data := (others => '0');
182
    twiv.adata := (others => '0');
183
    twiv.aaddr := (others => '0');
184
 
185
    twod.finish := '0';
186
    twod.data := (others => '0');
187
    twod.addr := (others => '0');
188
    twod.lvl := (others => '0');
189
    twod.fault_mexc := '0';
190
    twod.fault_trans := '0';
191
    twod.fault_inv := '0';
192
    twod.fault_lvl := (others => '0');
193
 
194
    twoi.finish := '0';
195
    twoi.data := (others => '0');
196
    twoi.addr := (others => '0');
197
    twoi.lvl := (others => '0');
198
    twoi.fault_mexc := '0';
199
    twoi.fault_trans := '0';
200
    twoi.fault_inv := '0';
201
    twoi.fault_lvl := (others => '0');
202
 
203
    fault.fault_pro := '0';
204
    fault.fault_pri := '0';
205
    fault.fault_access := '0';
206
    fault.fault_mexc := '0';
207
    fault.fault_trans := '0';
208
    fault.fault_inv := '0';
209
    fault.fault_lvl := (others => '0');
210
    fault.fault_su := '0';
211
    fault.fault_read := '0';
212
    fault.fault_isid := id_dcache;
213
    fault.fault_addr := (others => '0');
214
 
215
 
216
    fs.ow := '0';
217
    fs.fav := '0';
218
    fs.ft := (others => '0');
219
    fs.at_ls := '0';
220
    fs.at_id := '0';
221
    fs.at_su := '0';
222
    fs.l := (others => '0');
223
    fs.ebe := (others => '0');
224
 
225
    fa := (others => '0');
226
 
227
 
228
 
229
 
230
 
231
 
232
 
233
    if M_TLB_TYPE = splittlb then
234
 
235
      spltitlbout := tlbo_a(0);
236
      spltdtlbout := tlbo_a(1);
237
      twod := two; twoi := two;
238
      twod.finish := '0'; twoi.finish := '0';
239
      spltdtlbin := mmudci.transdata;
240
      spltitlbin := mmuici.transdata;
241
      mmudco_transdata := spltdtlbout.transdata;
242
      mmuico_transdata := spltitlbout.transdata;
243
 
244
      -- d-tlb
245
      if ((not v.splt_ds1.tlbactive) or spltdtlbout.s1finished) = '1'  then
246
        v.splt_ds1.tlbactive := '0';
247
        v.splt_ds1.op.trans_op := '0';
248
        v.splt_ds1.op.flush_op := '0';
249
        if mmudci.trans_op = '1' then
250
          mmudco_grant := '1';
251
          v.splt_ds1.tlbactive := '1';
252
          v.splt_ds1.op.trans_op := '1';
253
        elsif mmudci.flush_op = '1' then
254
          v.flush := '1';
255
          mmudco_grant := '1';
256
          v.splt_ds1.tlbactive := '1';
257
          v.splt_ds1.op.flush_op := '1';
258
        end if;
259
      end if;
260
 
261
      -- i-tlb
262
      if ((not v.splt_is1.tlbactive) or spltitlbout.s1finished) = '1'  then
263
        v.splt_is1.tlbactive := '0';
264
        v.splt_is1.op.trans_op := '0';
265
        v.splt_is1.op.flush_op := '0';
266
        if v.flush = '1' then
267
          v.flush := '0';
268
          v.splt_is1.tlbactive := '1';
269
          v.splt_is1.op.flush_op := '1';
270
        elsif mmuici.trans_op = '1' then
271
          mmuico_grant := '1';
272
          v.splt_is1.tlbactive := '1';
273
          v.splt_is1.op.trans_op := '1';
274
        end if;
275
      end if;
276
 
277
      if spltitlbout.transdata.finish = '1' then
278
        fault := spltitlbout.fault;
279
      end if;
280
      if spltdtlbout.transdata.finish = '1' then
281
        fault := spltdtlbout.fault;     -- overwrite icache fault
282
      end if;
283
 
284
      if spltitlbout.s1finished = '1' then
285
        v.splt_is2 := r.splt_is1;
286
      end if;
287
      if spltdtlbout.s1finished = '1' then
288
        v.splt_ds2 := r.splt_ds1;
289
      end if;
290
 
291
      if ( r.splt_is2.op.flush_op ) = '1' then
292
        mmuico_transdata.finish := '0';
293
      end if;
294
 
295
      -- share tw
296
      if two.finish = '1' then
297
        v.twactive := '0';
298
      end if;
299
 
300
      if r.twowner = id_icache then
301
        twiv := twi_a(0);
302
        twoi.finish := two.finish;
303
      else
304
        twiv := twi_a(1);
305
        twod.finish := two.finish;
306
      end if;
307
 
308
      if (v.twactive) = '0'  then
309
        if (twi_a(1).areq_ur or twi_a(1).walk_op_ur) = '1' then
310
          v.twactive := '1';
311
          v.twowner := id_dcache;
312
        elsif (twi_a(0).areq_ur or twi_a(0).walk_op_ur) = '1' then
313
          v.twactive := '1';
314
          v.twowner := id_icache;
315
        end if;
316
      end if;
317
 
318
    else
319
 
320
      --# combined i/d cache: 1 tlb, 1 tw
321
      -- share one tlb among i and d cache
322
      cmbtlbout := tlbo_a(0);
323
      fault := cmbtlbout.fault;
324
      mmuico_grant := '0'; mmudco_grant := '0';
325
      mmuico_transdata.finish := '0'; mmudco_transdata.finish := '0';
326
      twiv := twi_a(0);
327
      twod := two; twoi := two;
328
      twod.finish := '0'; twoi.finish := '0';
329
      twod.finish := two.finish;
330
 
331
      if ((not v.cmb_s1.tlbactive) or cmbtlbout.s1finished) = '1'  then
332
        v.cmb_s1.tlbactive := '0';
333
        v.cmb_s1.op.trans_op := '0';
334
        v.cmb_s1.op.flush_op := '0';
335
        if (mmudci.trans_op or mmudci.flush_op or mmuici.trans_op) = '1' then
336
          v.cmb_s1.tlbactive := '1';
337
        end if;
338
        if mmudci.trans_op = '1' then
339
          mmudco_grant := '1';
340
          v.cmb_s1.tlbowner := id_dcache;
341
          v.cmb_s1.op.trans_op := '1';
342
        elsif mmudci.flush_op = '1' then
343
          mmudco_grant := '1';
344
          v.cmb_s1.tlbowner := id_dcache;
345
          v.cmb_s1.op.flush_op := '1';
346
        elsif mmuici.trans_op = '1' then
347
          mmuico_grant := '1';
348
          v.cmb_s1.tlbowner := id_icache;
349
          v.cmb_s1.op.trans_op := '1';
350
        end if;
351
      end if;
352
 
353
      if (r.cmb_s1.tlbactive and not r.cmb_s2.tlbactive)  = '1'  then
354
 
355
      end if;
356
 
357
      if cmbtlbout.s1finished = '1' then
358
        v.cmb_s2 := r.cmb_s1;
359
      end if;
360
 
361
      if r.cmb_s1.tlbowner = id_dcache then
362
        cmbtlbin := mmudci.transdata;
363
      else
364
        cmbtlbin := mmuici.transdata;
365
      end if;
366
 
367
      if r.cmb_s2.tlbowner = id_dcache then
368
        mmudco_transdata := cmbtlbout.transdata;
369
      else
370
        mmuico_transdata := cmbtlbout.transdata;
371
      end if;
372
 
373
    end if;
374
 
375
 
376
 
377
 
378
    -- # fault status register
379
    if (mmudci.fsread) = '1' then
380
      v.mmctrl2.valid := '0'; v.mmctrl2.fs.fav := '0';
381
    end if;
382
 
383
    if (fault.fault_mexc) = '1' then
384
      fs.ft := FS_FT_TRANS;
385
    elsif (fault.fault_trans) = '1' then
386
      fs.ft := FS_FT_INV;
387
    elsif (fault.fault_inv) = '1' then
388
      fs.ft := FS_FT_INV;
389
    elsif (fault.fault_pri) = '1' then
390
      fs.ft := FS_FT_PRI;
391
    elsif (fault.fault_pro) = '1' then
392
      fs.ft := FS_FT_PRO;
393
    elsif (fault.fault_access) = '1' then
394
      fs.ft := FS_FT_BUS;
395
    else
396
      fs.ft := FS_FT_NONE;
397
    end if;
398
 
399
    fs.ow := '0';
400
    fs.l := fault.fault_lvl;
401
    if fault.fault_isid = id_dcache then
402
      fs.at_id := '0';
403
    else
404
      fs.at_id := '1';
405
    end if;
406
    fs.at_su := fault.fault_su;
407
    fs.at_ls := not fault.fault_read;
408
    fs.fav := '1';
409
    fs.ebe := (others => '0');
410
 
411
    fa := fault.fault_addr(VA_I_U downto VA_I_D);
412
 
413
    if (fault.fault_mexc or
414
        fault.fault_trans or
415
        fault.fault_inv or
416
        fault.fault_pro or
417
        fault.fault_pri or
418
        fault.fault_access) = '1' then
419
 
420
      --# priority
421
      if v.mmctrl2.valid = '1'then
422
        if (fault.fault_mexc) = '1' then
423
          v.mmctrl2.fs := fs;
424
          v.mmctrl2.fa := fa;
425
        else
426
          if (r.mmctrl2.fs.ft /= FS_FT_INV) then
427
            if fault.fault_isid = id_dcache then
428
            -- dcache
429
              v.mmctrl2.fs := fs;
430
              v.mmctrl2.fa := fa;
431
            else
432
            -- icache
433
              if (not r.mmctrl2.fs.at_id) = '0' then
434
                fs.ow := '1';
435
                v.mmctrl2.fs := fs;
436
                v.mmctrl2.fa := fa;
437
              end if;
438
            end if;
439
          end if;
440
 
441
        end if;
442
      else
443
        v.mmctrl2.fs := fs;
444
        v.mmctrl2.fa := fa;
445
        v.mmctrl2.valid := '1';
446
      end if;
447
 
448
      if (fault.fault_isid) = id_dcache then
449
        mmudco_transdata.accexc := '1';
450
      else
451
        mmuico_transdata.accexc := '1';
452
      end if;
453
 
454
    end if;
455
 
456
    -- # reset
457
    if ( rst = '0' ) then
458
      if M_TLB_TYPE = splittlb then
459
        v.splt_is1.tlbactive := '0';
460
        v.splt_is2.tlbactive := '0';
461
        v.splt_ds1.tlbactive := '0';
462
        v.splt_ds2.tlbactive := '0';
463
        v.splt_is1.op.trans_op := '0';
464
        v.splt_is2.op.trans_op := '0';
465
        v.splt_ds1.op.trans_op := '0';
466
        v.splt_ds2.op.trans_op := '0';
467
        v.splt_is1.op.flush_op := '0';
468
        v.splt_is2.op.flush_op := '0';
469
        v.splt_ds1.op.flush_op := '0';
470
        v.splt_ds2.op.flush_op := '0';
471
      else
472
        v.cmb_s1.tlbactive := '0';
473
        v.cmb_s2.tlbactive := '0';
474
        v.cmb_s1.op.trans_op := '0';
475
        v.cmb_s2.op.trans_op := '0';
476
        v.cmb_s1.op.flush_op := '0';
477
        v.cmb_s2.op.flush_op := '0';
478
      end if;
479
      v.flush := '0';
480
      v.mmctrl2.valid := '0';
481
      v.twactive := '0';
482
    end if;
483
 
484
    -- drive signals
485
    if M_TLB_TYPE = splittlb then
486
      tlbi_a(0).trans_op  <= r.splt_is1.op.trans_op;
487
      tlbi_a(0).flush_op  <= r.splt_is1.op.flush_op;
488
      tlbi_a(0).transdata <= spltitlbin;
489
      tlbi_a(0).s2valid   <= r.splt_is2.tlbactive;
490
      tlbi_a(0).mmctrl1   <= mmudci.mmctrl1;
491
      tlbi_a(1).trans_op  <= r.splt_ds1.op.trans_op;
492
      tlbi_a(1).flush_op  <= r.splt_ds1.op.flush_op;
493
      tlbi_a(1).transdata <= spltdtlbin;
494
      tlbi_a(1).s2valid   <= r.splt_ds2.tlbactive;
495
      tlbi_a(1).mmctrl1   <= mmudci.mmctrl1;
496
    else
497
      tlbi_a(0).trans_op  <= r.cmb_s1.op.trans_op;
498
      tlbi_a(0).flush_op  <= r.cmb_s1.op.flush_op;
499
      tlbi_a(0).transdata <= cmbtlbin;
500
      tlbi_a(0).s2valid   <= r.cmb_s2.tlbactive;
501
      tlbi_a(0).mmctrl1   <= mmudci.mmctrl1;
502
    end if;
503
 
504
    mmudco.transdata <= mmudco_transdata;
505
    mmuico.transdata <= mmuico_transdata;
506
    mmudco.grant     <= mmudco_grant;
507
    mmuico.grant     <= mmuico_grant;
508
    mmudco.mmctrl2   <= r.mmctrl2;
509
 
510
    twi      <= twiv;
511
    two_a(0) <= twoi;
512
    two_a(1) <= twod;
513
    mmctrl1 <= mmudci.mmctrl1;
514
 
515
    c <= v;
516
 
517
  end process p0;
518
 
519
  tlbcomb0: if M_TLB_TYPE = combinedtlb generate
520
    -- i/d tlb
521
    ctlb0 : mmutlb
522
      generic map ( entries => M_ENT_C )
523
      port map (rst, clk, tlbi_a(0), tlbo_a(0), two_a(0), twi_a(0));
524
  end generate tlbcomb0;
525
 
526
  tlbsplit0: if M_TLB_TYPE = splittlb generate
527
    -- i tlb
528
    itlb0 : mmutlb
529
      generic map ( entries => M_ENT_I )
530
      port map (rst, clk, tlbi_a(0), tlbo_a(0), two_a(0), twi_a(0));
531
    -- d tlb
532
    dtlb0 : mmutlb
533
      generic map ( entries => M_ENT_D )
534
      port map (rst, clk, tlbi_a(1), tlbo_a(1), two_a(1), twi_a(1));
535
  end generate tlbsplit0;
536
 
537
  -- table walk component
538
  tw0 : mmutw
539
    port map (rst, clk, mmctrl1, twi, two, mcmmo, mcmmi);
540
 
541
end rtl;

powered by: WebSVN 2.1.0

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