Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: pMap.h | |
5 | * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES. | |
7 | * | |
8 | * The above named program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public | |
10 | * License version 2 as published by the Free Software Foundation. | |
11 | * | |
12 | * The above named program is distributed in the hope that it will be | |
13 | * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public | |
18 | * License along with this work; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. | |
20 | * | |
21 | * ========== Copyright Header End ============================================ | |
22 | */ | |
23 | #ifndef __pMap_h | |
24 | #define __pMap_h | |
25 | ||
26 | #include <assert.h> | |
27 | #include "Map.h" | |
28 | #include "Math.h" | |
29 | using namespace std; | |
30 | ||
31 | /** @file pMap.h | |
32 | * The file pMap.h contains "private" code for methods relating to the | |
33 | * Map class. | |
34 | * This file is considered private to the class implementation and not | |
35 | * part of its interface. This code is in a header file just to | |
36 | * allow the template class to be packaged up into a library. | |
37 | */ | |
38 | ||
39 | static const bool VERBOSE_MAP = false; | |
40 | ||
41 | static const uint MAP_LEVEL4_SIZE = 1 << MAP_LEVEL4_BITS; | |
42 | static const uint MAP_LEVEL4_SHIFT = 0; | |
43 | static const Addr MAP_LEVEL4_MASK = MAP_LEVEL4_SIZE - 1; | |
44 | ||
45 | static const uint MAP_LEVEL3_SIZE = 1 << MAP_LEVEL3_BITS; | |
46 | static const uint MAP_LEVEL3_SHIFT = MAP_LEVEL4_SHIFT + MAP_LEVEL4_BITS; | |
47 | static const Addr MAP_LEVEL3_MASK = MAP_LEVEL3_SIZE - 1; | |
48 | ||
49 | static const uint MAP_LEVEL2_SIZE = 1 << MAP_LEVEL2_BITS; | |
50 | static const uint MAP_LEVEL2_SHIFT = MAP_LEVEL3_SHIFT + MAP_LEVEL3_BITS; | |
51 | static const Addr MAP_LEVEL2_MASK = MAP_LEVEL2_SIZE - 1; | |
52 | ||
53 | static const uint MAP_LEVEL1_SIZE = 1 << MAP_LEVEL1_BITS; | |
54 | static const uint MAP_LEVEL1_SHIFT = MAP_LEVEL2_SHIFT + MAP_LEVEL2_BITS; | |
55 | static const Addr MAP_LEVEL1_MASK = MAP_LEVEL1_SIZE - 1; | |
56 | ||
57 | static const uint MAP_LEVEL0_SIZE = 1 << MAP_LEVEL0_BITS; | |
58 | static const uint MAP_LEVEL0_SHIFT = MAP_LEVEL1_SHIFT + MAP_LEVEL1_BITS; | |
59 | static const Addr MAP_LEVEL0_MASK = MAP_LEVEL0_SIZE - 1; | |
60 | ||
61 | // MapLevel4 is an instance of type T | |
62 | ||
63 | template<class T> struct MapLevel3 | |
64 | { | |
65 | T *level3[MAP_LEVEL3_SIZE]; | |
66 | }; | |
67 | ||
68 | template<class T> struct MapLevel2 | |
69 | { | |
70 | MapLevel3<T> *level2[MAP_LEVEL2_SIZE]; | |
71 | }; | |
72 | ||
73 | template<class T> struct MapLevel1 | |
74 | { | |
75 | MapLevel2<T> *level1[MAP_LEVEL1_SIZE]; | |
76 | }; | |
77 | ||
78 | template<class T> struct MapLevel0 | |
79 | { | |
80 | MapLevel1<T> *level0[MAP_LEVEL0_SIZE]; | |
81 | }; | |
82 | ||
83 | template<class T> MapGeneric<T>::MapGeneric (string n, Addr s, Addr e, uint w) | |
84 | { | |
85 | assert(s >= MAP_MIN_ADDR && s <= e && e <= MAP_MAX_ADDR); | |
86 | assert(ispow2(w)); | |
87 | name = n; | |
88 | start = s; | |
89 | end = e; | |
90 | } | |
91 | ||
92 | template<class T> Map<T>::Map (string n, Addr s, Addr e, uint w) : | |
93 | MapGeneric<T>(n, s, e, w) | |
94 | { | |
95 | assert(w == MAP_LEVEL4_SIZE); | |
96 | count_level0 = 0; | |
97 | count_level1 = 0; | |
98 | count_level2 = 0; | |
99 | count_level3 = 0; | |
100 | count_level4 = 0; | |
101 | bytes = 0; | |
102 | map = new MapLevel0<T>; | |
103 | count_level0++; | |
104 | bytes += sizeof(MapLevel0<T>); | |
105 | for (uint l0=0; l0<MAP_LEVEL0_SIZE; l0++) | |
106 | map->level0[l0] = NULL; | |
107 | } | |
108 | ||
109 | template<class T> Map<T>::~Map () | |
110 | { | |
111 | if (VERBOSE_MAP) { | |
112 | cout << "Map " << name << " has " << dec | |
113 | << "bytes = " << bytes | |
114 | << ", count_level0 = " << count_level0 | |
115 | << ", count_level1 = " << count_level1 | |
116 | << ", count_level2 = " << count_level2 | |
117 | << ", count_level3 = " << count_level3 | |
118 | << ", count_level4 = " << count_level4 << "\n"; | |
119 | } | |
120 | ||
121 | for (uint l0=0; l0<MAP_LEVEL0_SIZE; l0++) { | |
122 | if (map->level0[l0] != NULL) { | |
123 | for (uint l1=0; l1<MAP_LEVEL1_SIZE; l1++) { | |
124 | if (map->level0[l0]->level1[l1] != NULL) { | |
125 | for (uint l2=0; l2<MAP_LEVEL2_SIZE; l2++) { | |
126 | if (map->level0[l0]->level1[l1]->level2[l2] != NULL) { | |
127 | delete map->level0[l0]->level1[l1]->level2[l2]; | |
128 | } | |
129 | } | |
130 | delete map->level0[l0]->level1[l1]; | |
131 | } | |
132 | } | |
133 | delete map->level0[l0]; | |
134 | } | |
135 | } | |
136 | delete map; | |
137 | } | |
138 | ||
139 | ||
140 | template<class T> bool Map<T>::insert (Addr addr, T *item) | |
141 | { | |
142 | assert(item != NULL); | |
143 | ||
144 | if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0)) | |
145 | return false; | |
146 | ||
147 | uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK); | |
148 | uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK); | |
149 | uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK); | |
150 | uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK); | |
151 | ||
152 | MapLevel1<T> *l; | |
153 | if ((l = map->level0[level0_index]) == NULL) { | |
154 | l = new MapLevel1<T>; | |
155 | count_level1++; | |
156 | bytes += sizeof(MapLevel1<T>); | |
157 | for (uint l1=0; l1<MAP_LEVEL1_SIZE; l1++) | |
158 | l->level1[l1] = NULL; | |
159 | map->level0[level0_index] = l; | |
160 | } | |
161 | ||
162 | MapLevel2<T> *m; | |
163 | if ((m = l->level1[level1_index]) == NULL) { | |
164 | m = new MapLevel2<T>; | |
165 | count_level2++; | |
166 | bytes += sizeof(MapLevel2<T>); | |
167 | for (uint l2=0; l2<MAP_LEVEL2_SIZE; l2++) | |
168 | m->level2[l2] = NULL; | |
169 | l->level1[level1_index] = m; | |
170 | } | |
171 | ||
172 | MapLevel3<T> *n; | |
173 | if ((n = m->level2[level2_index]) == NULL) { | |
174 | n = new MapLevel3<T>; | |
175 | count_level3++; | |
176 | bytes += sizeof(MapLevel3<T>); | |
177 | for (uint l3=0; l3<MAP_LEVEL3_SIZE; l3++) | |
178 | n->level3[l3] = NULL; | |
179 | m->level2[level2_index] = n; | |
180 | } | |
181 | ||
182 | if (n->level3[level3_index] == NULL) { | |
183 | n->level3[level3_index] = item; | |
184 | count_level4++; | |
185 | return true; | |
186 | } | |
187 | else | |
188 | return false; | |
189 | } | |
190 | ||
191 | template<class T> T *Map<T>::remove (Addr addr) | |
192 | { | |
193 | if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0)) | |
194 | return NULL; | |
195 | ||
196 | uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK); | |
197 | uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK); | |
198 | uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK); | |
199 | uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK); | |
200 | ||
201 | MapLevel1<T> *l; | |
202 | if ((l = map->level0[level0_index]) == NULL) | |
203 | return NULL; | |
204 | ||
205 | MapLevel2<T> *m; | |
206 | if ((m = l->level1[level1_index]) == NULL) | |
207 | return NULL; | |
208 | ||
209 | MapLevel3<T> *n; | |
210 | if ((n = m->level2[level2_index]) == NULL) | |
211 | return NULL; | |
212 | ||
213 | T *result = n->level3[level3_index]; | |
214 | n->level3[level3_index] = NULL; | |
215 | return result; | |
216 | } | |
217 | ||
218 | template<class T> T *Map<T>::lookup (Addr addr) | |
219 | { | |
220 | if (addr < start || addr > end || ((addr & MAP_LEVEL4_MASK) != 0)) | |
221 | return NULL; | |
222 | ||
223 | uint level0_index = uint((addr >> MAP_LEVEL0_SHIFT) & MAP_LEVEL0_MASK); | |
224 | uint level1_index = uint((addr >> MAP_LEVEL1_SHIFT) & MAP_LEVEL1_MASK); | |
225 | uint level2_index = uint((addr >> MAP_LEVEL2_SHIFT) & MAP_LEVEL2_MASK); | |
226 | uint level3_index = uint((addr >> MAP_LEVEL3_SHIFT) & MAP_LEVEL3_MASK); | |
227 | ||
228 | MapLevel1<T> *l; | |
229 | if ((l = map->level0[level0_index]) == NULL) | |
230 | return NULL; | |
231 | ||
232 | MapLevel2<T> *m; | |
233 | if ((m = l->level1[level1_index]) == NULL) | |
234 | return NULL; | |
235 | ||
236 | MapLevel3<T> *n; | |
237 | if ((n = m->level2[level2_index]) == NULL) | |
238 | return NULL; | |
239 | ||
240 | return n->level3[level3_index]; | |
241 | } | |
242 | ||
243 | #endif |