Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / common / regdef / include / pMap.h
/*
* ========== Copyright Header Begin ==========================================
*
* OpenSPARC T2 Processor File: pMap.h
* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
*
* The above named program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License version 2 as published by the Free Software Foundation.
*
* The above named program is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ========== Copyright Header End ============================================
*/
#ifndef __pMap_h
#define __pMap_h
#include <assert.h>
#include "Map.h"
#include "Math.h"
using namespace std;
/** @file pMap.h
* The file pMap.h contains "private" code for methods relating to the
* Map class.
* This file is considered private to the class implementation and not
* part of its interface. This code is in a header file just to
* allow the template class to be packaged up into a library.
*/
static const bool VERBOSE_MAP = false;
static const uint MAP_LEVEL4_SIZE = 1 << MAP_LEVEL4_BITS;
static const uint MAP_LEVEL4_SHIFT = 0;
static const Addr MAP_LEVEL4_MASK = MAP_LEVEL4_SIZE - 1;
static const uint MAP_LEVEL3_SIZE = 1 << MAP_LEVEL3_BITS;
static const uint MAP_LEVEL3_SHIFT = MAP_LEVEL4_SHIFT + MAP_LEVEL4_BITS;
static const Addr MAP_LEVEL3_MASK = MAP_LEVEL3_SIZE - 1;
static const uint MAP_LEVEL2_SIZE = 1 << MAP_LEVEL2_BITS;
static const uint MAP_LEVEL2_SHIFT = MAP_LEVEL3_SHIFT + MAP_LEVEL3_BITS;
static const Addr MAP_LEVEL2_MASK = MAP_LEVEL2_SIZE - 1;
static const uint MAP_LEVEL1_SIZE = 1 << MAP_LEVEL1_BITS;
static const uint MAP_LEVEL1_SHIFT = MAP_LEVEL2_SHIFT + MAP_LEVEL2_BITS;
static const Addr MAP_LEVEL1_MASK = MAP_LEVEL1_SIZE - 1;
static const uint MAP_LEVEL0_SIZE = 1 << MAP_LEVEL0_BITS;
static const uint MAP_LEVEL0_SHIFT = MAP_LEVEL1_SHIFT + MAP_LEVEL1_BITS;
static const Addr MAP_LEVEL0_MASK = MAP_LEVEL0_SIZE - 1;
// MapLevel4 is an instance of type T
template<class T> struct MapLevel3
{
T *level3[MAP_LEVEL3_SIZE];
};
template<class T> struct MapLevel2
{
MapLevel3<T> *level2[MAP_LEVEL2_SIZE];
};
template<class T> struct MapLevel1
{
MapLevel2<T> *level1[MAP_LEVEL1_SIZE];
};
template<class T> struct MapLevel0
{
MapLevel1<T> *level0[MAP_LEVEL0_SIZE];
};
template<class T> MapGeneric<T>::MapGeneric (string n, Addr s, Addr e, uint w)
{
assert(s >= MAP_MIN_ADDR && s <= e && e <= MAP_MAX_ADDR);
assert(ispow2(w));
name = n;
start = s;
end = e;
}
template<class T> Map<T>::Map (string n, Addr s, Addr e, uint w) :
MapGeneric<T>(n, s, e, w)
{
assert(w == MAP_LEVEL4_SIZE);
count_level0 = 0;
count_level1 = 0;
count_level2 = 0;
count_level3 = 0;
count_level4 = 0;
bytes = 0;
map = new MapLevel0<T>;
count_level0++;
bytes += sizeof(MapLevel0<T>);
for (uint l0=0; l0<MAP_LEVEL0_SIZE; l0++)
map->level0[l0] = NULL;
}
template<class T> Map<T>::~Map ()
{
if (VERBOSE_MAP) {
cout << "Map " << name << " has " << dec
<< "bytes = " << bytes
<< ", count_level0 = " << count_level0
<< ", count_level1 = " << count_level1
<< ", count_level2 = " << count_level2
<< ", count_level3 = " << count_level3
<< ", count_level4 = " << count_level4 << "\n";
}
for (uint l0=0; l0<MAP_LEVEL0_SIZE; l0++) {
if (map->level0[l0] != NULL) {
for (uint l1=0; l1<MAP_LEVEL1_SIZE; l1++) {
if (map->level0[l0]->level1[l1] != NULL) {
for (uint l2=0; l2<MAP_LEVEL2_SIZE; l2++) {
if (map->level0[l0]->level1[l1]->level2[l2] != NULL) {
delete map->level0[l0]->level1[l1]->level2[l2];
}
}
delete map->level0[l0]->level1[l1];
}
}
delete map->level0[l0];
}
}
delete map;
}
template<class T> bool Map<T>::insert (Addr addr, T *item)
{
assert(item != NULL);
if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0))
return false;
uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK);
uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK);
uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK);
uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK);
MapLevel1<T> *l;
if ((l = map->level0[level0_index]) == NULL) {
l = new MapLevel1<T>;
count_level1++;
bytes += sizeof(MapLevel1<T>);
for (uint l1=0; l1<MAP_LEVEL1_SIZE; l1++)
l->level1[l1] = NULL;
map->level0[level0_index] = l;
}
MapLevel2<T> *m;
if ((m = l->level1[level1_index]) == NULL) {
m = new MapLevel2<T>;
count_level2++;
bytes += sizeof(MapLevel2<T>);
for (uint l2=0; l2<MAP_LEVEL2_SIZE; l2++)
m->level2[l2] = NULL;
l->level1[level1_index] = m;
}
MapLevel3<T> *n;
if ((n = m->level2[level2_index]) == NULL) {
n = new MapLevel3<T>;
count_level3++;
bytes += sizeof(MapLevel3<T>);
for (uint l3=0; l3<MAP_LEVEL3_SIZE; l3++)
n->level3[l3] = NULL;
m->level2[level2_index] = n;
}
if (n->level3[level3_index] == NULL) {
n->level3[level3_index] = item;
count_level4++;
return true;
}
else
return false;
}
template<class T> T *Map<T>::remove (Addr addr)
{
if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0))
return NULL;
uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK);
uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK);
uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK);
uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK);
MapLevel1<T> *l;
if ((l = map->level0[level0_index]) == NULL)
return NULL;
MapLevel2<T> *m;
if ((m = l->level1[level1_index]) == NULL)
return NULL;
MapLevel3<T> *n;
if ((n = m->level2[level2_index]) == NULL)
return NULL;
T *result = n->level3[level3_index];
n->level3[level3_index] = NULL;
return result;
}
template<class T> T *Map<T>::lookup (Addr addr)
{
if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0))
return NULL;
uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK);
uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK);
uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK);
uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK);
MapLevel1<T> *l;
if ((l = map->level0[level0_index]) == NULL)
return NULL;
MapLevel2<T> *m;
if ((m = l->level1[level1_index]) == NULL)
return NULL;
MapLevel3<T> *n;
if ((n = m->level2[level2_index]) == NULL)
return NULL;
return n->level3[level3_index];
}
#endif