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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_61/] [or1ksim/] [mmu/] [dmmu.c] - Diff between revs 6 and 62

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 6 Rev 62
/* dmmu.c -- data mmu simulation
/* dmmu.c -- Data MMU simulation
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
   Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
 
 
This file is part of OpenRISC 1000 Architectural Simulator.
This file is part of OpenRISC 1000 Architectural Simulator.
 
 
This program is free software; you can redistribute it and/or modify
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
(at your option) any later version.
 
 
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
GNU General Public License for more details.
 
 
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
 
 
/* DMMU model (not functional yet, currently just copy of data cache). */
/* DMMU model (not functional yet, currently just copy of data cache). */
 
 
 
 
#include "dmmu.h"
#include "dmmu.h"
#include "abstract.h"
#include "abstract.h"
#include "stats.h"
#include "stats.h"
 
#include "sprs.h"
 
#include "except.h"
 
 
 
extern int cont_run;
 
 
/* Data MMU */
/* Data MMU */
 
 
unsigned long dmmu_translate(unsigned long virtaddr)
unsigned long dmmu_translate(unsigned long virtaddr)
{
{
        return virtaddr;
        unsigned long phyaddr = dmmu_simulate_tlb(virtaddr);
 
 
 
        printf("DMMU translate(%x) = %x\n", virtaddr, phyaddr);
 
        return phyaddr;
}
}
 
 
/* Number of DC sets (power of 2) */
/* Number of DTLB sets used (power of 2, max is 256) */
#define DC_SETS 256
#define DTLB_SETS 16
 
 
/* Block size in bytes (1, 2, 4, 8, 16, 32 etc.) */
/* Entry size in bytes (8 == two singlewords) */
#define DC_BLOCK_SIZE 4
#define DTLB_ENTRY_SIZE 8
 
 
/* Number of DC ways (1, 2, 3 etc.). */
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
#define DC_WAYS 1
#define DTLB_WAYS 2
 
 
/* Number of usage states (2, 3, 4 etc.). */
/* Number of usage states (2, 3, 4 etc., max is 4). */
#define DC_USTATES 2
#define DTLB_USTATES 2
 
 
struct dc_set {
 
        struct {
 
                unsigned long tagaddr;  /* tag address */
 
                int lru;                /* least recently used */
 
        } way[DC_WAYS];
 
} dc[DC_SETS];
 
 
 
void xdc_info()
/* Don't change. Defined by mask of PPN/VPN bits in TLB. */
 
#define MIN_PG_SIZE 1024
 
 
 
void dtlb_info()
{
{
        printf("Data cache %dKB: ", DC_SETS * DC_BLOCK_SIZE * DC_WAYS / 1024);
        printf("Data MMU %dKB: ", DTLB_SETS * DTLB_ENTRY_SIZE * DTLB_WAYS / 1024);
        printf("%d ways, %d sets, block size %d bytes\n", DC_WAYS, DC_SETS, DC_BLOCK_SIZE);
        printf("%d ways, %d sets, entry size %d bytes\n", DTLB_WAYS, DTLB_SETS, DTLB_ENTRY_SIZE);
}
}
 
 
/* First check if data is already in the cache and if it is:
/* First check if virtual address is covered by DTLB and if it is:
    - increment DC read hit stats,
    - increment DTLB read hit stats,
    - set 'lru' at this way to DC_USTATES - 1 and
    - set 'lru' at this way to DTLB_USTATES - 1 and
      decrement 'lru' of other ways unless they have reached 0,
      decrement 'lru' of other ways unless they have reached 0,
 
    - check page access attributes and invoke DMMU page fault exception
 
      handler if necessary
   and if not:
   and if not:
    - increment DC read miss stats
    - increment DTLB read miss stats
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
    - find lru way and entry and invoke DTLB miss exception handler
    - set 'lru' with DC_USTATES - 1 and decrement 'lru' of other
    - set 'lru' with DTLB_USTATES - 1 and decrement 'lru' of other
      ways unless they have reached 0
      ways unless they have reached 0
*/
*/
 
 
void xdc_simulate_read(unsigned long dataaddr)
unsigned long dtlb_status(int start_set)
{
{
        int set, way = -1;
        int set;
        int i;
        int way;
        unsigned long tagaddr;
        int end_set = DTLB_SETS;
 
 
        /* Which set to check out? */
        if ((start_set >= 0) && (start_set < end_set))
        set = (dataaddr / DC_BLOCK_SIZE) % DC_SETS;
                end_set = start_set + 1;
        tagaddr = (dataaddr / DC_BLOCK_SIZE) / DC_SETS;
        else
 
                start_set = 0;
        /* Scan all ways and try to find a matching way. */
 
        for (i = 0; i < DC_WAYS; i++)
        /* Scan set(s) and way(s). */
                if (dc[set].way[i].tagaddr == tagaddr)
        for (set = start_set; set < end_set; set++) {
                        way = i;
                printf("\nSet %x: ", set);
 
                for (way = 0; way < DTLB_WAYS; way++) {
        /* Did we find our cached data? */
                        printf("  way %d: ", way);
        if (way >= 0) { /* Yes, we did. */
                        printf("vpn %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBMR_VPN));
                dc_stats.readhit++;
                        printf("lru %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBMR_LRU));
 
                        printf("pl1 %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBMR_PL1));
                for (i = 0; i < DC_WAYS; i++)
                        printf("v %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBMR_V));
                        if (dc[set].way[i].lru)
                        printf("a %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_A));
                                dc[set].way[i].lru--;
                        printf("d %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_D));
                dc[set].way[way].lru = DC_USTATES - 1;
                        printf("ure %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_URE));
 
                        printf("uwe %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_UWE));
 
                        printf("sre %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_SRE));
 
                        printf("swe %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_SWE));
 
                        printf("ppn %x  ", getsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBTR_PPN));
 
                        if (way > 0)
 
                                printf("\n");
        }
        }
        else {  /* No, we didn't. */
 
                int minlru = DC_USTATES - 1;
 
                int minway = 0;
 
 
 
                dc_stats.readmiss++;
 
 
 
                for (i = 0; i < DC_WAYS; i++)
 
                        if (dc[set].way[i].lru < minlru)
 
                                minway = i;
 
 
 
                dc[set].way[minway].tagaddr = tagaddr;
 
                for (i = 0; i < DC_WAYS; i++)
 
                        if (dc[set].way[i].lru)
 
                                dc[set].way[i].lru--;
 
                dc[set].way[minway].lru = DC_USTATES - 1;
 
        }
        }
 
        printf("\n");
}
}
 
 
/* First check if data is already in the cache and if it is:
unsigned long dmmu_simulate_tlb(unsigned long virtaddr)
    - increment DC write hit stats,
 
    - set 'lru' at this way to DC_USTATES - 1 and
 
      decrement 'lru' of other ways unless they have reached 0,
 
   and if not:
 
    - increment DC write miss stats
 
    - find lru way and entry and replace old tag with tag of the 'dataaddr'
 
    - set 'lru' with DC_USTATES - 1 and decrement 'lru' of other
 
      ways unless they have reached 0
 
*/
 
 
 
void xdc_simulate_write(unsigned long dataaddr)
 
{
{
        int set, way = -1;
        int set, way = -1;
        int i;
        int i;
        unsigned long tagaddr;
        unsigned long tagaddr;
 
        unsigned long vpn;
 
 
 
        if (! (mfspr(SPR_SR) & SPR_SR_DME))
 
                return virtaddr;
 
 
        /* Which set to check out? */
        /* Which set to check out? */
        set = (dataaddr / DC_BLOCK_SIZE) % DC_SETS;
        set = (virtaddr / PAGE_SIZE) % DTLB_SETS;
        tagaddr = (dataaddr / DC_BLOCK_SIZE) / DC_SETS;
        tagaddr = (virtaddr / PAGE_SIZE) / DTLB_SETS;
 
        vpn = virtaddr / MIN_PG_SIZE;
 
 
        /* Scan all ways and try to find a matching way. */
        /* Scan all ways and try to find a matching way. */
        for (i = 0; i < DC_WAYS; i++)
        for (i = 0; i < DTLB_WAYS; i++)
                if (dc[set].way[i].tagaddr == tagaddr)
                if ((getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_VPN) == vpn) &&
 
                    getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_V))
                        way = i;
                        way = i;
 
 
        /* Did we find our cached data? */
        /* Did we find our tlb entry? */
        if (way >= 0) { /* Yes, we did. */
        if (way >= 0) { /* Yes, we did. */
                dc_stats.writehit++;
                dmmu_stats.loads_tlbhit++;
 
                debug("DTLB hit (virtaddr=%x).\n", virtaddr);
 
 
 
                /* Set LRUs */
 
                for (i = 0; i < DTLB_WAYS; i++)
 
                        if (getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU))
 
                                setsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU, getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU) - 1);
 
                setsprbits(SPR_DTLBMR_BASE(way) + set, SPR_DTLBMR_LRU, DTLB_USTATES - 1);
 
 
                for (i = 0; i < DC_WAYS; i++)
                return getsprbits(SPR_DTLBTR_BASE(way) + set, SPR_DTLBTR_PPN) * MIN_PG_SIZE + (virtaddr % PAGE_SIZE);
                        if (dc[set].way[i].lru)
 
                                dc[set].way[i].lru--;
 
                dc[set].way[way].lru = DC_USTATES - 1;
 
        }
        }
        else {  /* No, we didn't. */
        else {  /* No, we didn't. */
                int minlru = DC_USTATES - 1;
                int minlru = DTLB_USTATES - 1;
                int minway = 0;
                int minway = 0;
 
 
                dc_stats.writemiss++;
                dmmu_stats.loads_tlbmiss++;
 
#if 0
                for (i = 0; i < DC_WAYS; i++)
                for (i = 0; i < DTLB_WAYS; i++)
                        if (dc[set].way[i].lru < minlru)
                        if (getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU) < minlru)
                                minway = i;
                                minway = i;
 
 
                dc[set].way[minway].tagaddr = tagaddr;
                setsprbits(SPR_DTLBMR_BASE(minway) + set, SPR_DTLBMR_VPN, vpn);
                for (i = 0; i < DC_WAYS; i++)
                for (i = 0; i < DTLB_WAYS; i++)
                        if (dc[set].way[i].lru)
                        if (getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU))
                                dc[set].way[i].lru--;
                                setsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU, getsprbits(SPR_DTLBMR_BASE(i) + set, SPR_DTLBMR_LRU) - 1);
                dc[set].way[minway].lru = DC_USTATES - 1;
                setsprbits(SPR_DTLBMR_BASE(minway) + set, SPR_DTLBMR_LRU, DTLB_USTATES - 1);
 
                setsprbits(SPR_DTLBTR_BASE(minway) + set, SPR_DTLBTR_PPN, vpn); /* 1 to 1 */
 
                setsprbits(SPR_DTLBMR_BASE(minway) + set, SPR_DTLBMR_V, 1);
 
#endif
 
                except_handle(EXCEPT_DTLBMISS, virtaddr);
 
                /* if tlb refill implemented in HW */
 
                /* return getsprbits(SPR_DTLBTR_BASE(minway) + set, SPR_DTLBTR_PPN) * MIN_PG_SIZE + (virtaddr % PAGE_SIZE); */
 
                return 0;
        }
        }
}
}
 
 

powered by: WebSVN 2.1.0

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