Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | /* |
2 | * ========== Copyright Header Begin ========================================== | |
3 | * | |
4 | * OpenSPARC T2 Processor File: rz3_lruhash.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 | /* rz3_lruhash.h | |
24 | * fully-associative cache with lru replacement | |
25 | */ | |
26 | ||
27 | #ifndef _rz3_lruhash_h_ | |
28 | #define _rz3_lruhash_h_ | |
29 | ||
30 | #include <stdio.h> | |
31 | #include <strings.h> | |
32 | #include <sys/types.h> | |
33 | ||
34 | struct rz3_lruhash_elem { | |
35 | uint64_t v; | |
36 | ||
37 | rz3_lruhash_elem * next; | |
38 | rz3_lruhash_elem * prev; | |
39 | ||
40 | ||
41 | rz3_lruhash_elem() { | |
42 | k = 0; | |
43 | prev = next = NULL; | |
44 | inited = false; | |
45 | } | |
46 | ||
47 | int GetKey() { | |
48 | if (!inited) { | |
49 | fprintf(stderr, "warning: rz3_lruhash: rz3_lruhash_elem key not set\n"); | |
50 | } | |
51 | return k; | |
52 | } | |
53 | ||
54 | bool SetKey(int key) { | |
55 | if (!inited) { | |
56 | k = key; | |
57 | inited = true; | |
58 | return true; | |
59 | } else { | |
60 | fprintf(stderr, "warning: rz3_lruhash: rz3_lruhash_elem key already set\n"); | |
61 | return false; | |
62 | } | |
63 | } | |
64 | private: | |
65 | // "k" is equivalent to a java "final" variable - write once | |
66 | int k; // "key", which is an index into a linear array in this implementation | |
67 | bool inited; | |
68 | }; // rz3_lruhash_elem | |
69 | ||
70 | ||
71 | struct rz3_lruhash { | |
72 | ||
73 | int nbits(uint64_t n) { | |
74 | int rv = 1; | |
75 | while(n>>rv) { | |
76 | rv++; | |
77 | } | |
78 | return rv; | |
79 | } | |
80 | ||
81 | // size must be a power of 2 | |
82 | rz3_lruhash(int arg_size) { | |
83 | size = arg_size; | |
84 | ||
85 | idxbits = nbits(size-1); | |
86 | arr = new rz3_lruhash_elem [size]; | |
87 | ||
88 | searchtbl = new rz3_lruhash_elem * [size]; | |
89 | ||
90 | Clear(); | |
91 | ||
92 | refs = misses = searchtbl_hits = 0; | |
93 | } | |
94 | ||
95 | void Clear() { | |
96 | newest = arr; | |
97 | oldest = arr+(size-1); | |
98 | ||
99 | bzero(searchtbl, size*sizeof(rz3_lruhash_elem *)); | |
100 | ||
101 | int i; | |
102 | for (i=0; i<size; i++) { | |
103 | rz3_lruhash_elem * elem = arr+i; | |
104 | elem->v = i; | |
105 | elem->SetKey(i); | |
106 | elem->prev = (elem == newest) ? NULL : arr+(i-1); | |
107 | elem->next = (elem == oldest) ? NULL : arr+(i+1); | |
108 | // insert into searchtbl | |
109 | searchtbl[search_idx_fn(elem->v)] = elem; | |
110 | } | |
111 | } // rz3_lruhash(int arg_size) | |
112 | ||
113 | ||
114 | ~rz3_lruhash() { | |
115 | delete [] arr; | |
116 | delete [] searchtbl; | |
117 | } // ~rz3_lruhash() | |
118 | ||
119 | // returns a "key" whose value is [0 .. size-1] | |
120 | // and whose size is CEIL(log2(arg_size)) bits | |
121 | bool Update(uint64_t v, int & k) { | |
122 | ||
123 | ||
124 | k = -1; | |
125 | refs++; | |
126 | ||
127 | // first search for elem | |
128 | int searchidx = search_idx_fn(v); | |
129 | if ((searchtbl[searchidx] != NULL) && (searchtbl[searchidx]->v == v)) { | |
130 | k = searchtbl[searchidx]->GetKey(); | |
131 | searchtbl_hits++; | |
132 | } else { | |
133 | int i; | |
134 | for (i=0; i<size; i++) { | |
135 | if (arr[i].v == v) { | |
136 | k = i; | |
137 | break; | |
138 | } | |
139 | } | |
140 | } | |
141 | ||
142 | bool hit; | |
143 | if (k != -1) { | |
144 | BringToFront(&(arr[k])); | |
145 | hit = true; | |
146 | } else { | |
147 | k = oldest->GetKey(); | |
148 | oldest->v = v; | |
149 | BringToFront(oldest); | |
150 | misses++; | |
151 | hit = false; | |
152 | } | |
153 | ||
154 | searchtbl[searchidx] = &(arr[k]); | |
155 | ||
156 | return hit; | |
157 | } // int Update(uint64_t v) | |
158 | ||
159 | // if key is good, stores corresponding value in v and returns true. also brings (key,v) to the front of the MRU list | |
160 | // returns false otherwise | |
161 | bool Get(int key, uint64_t & v) { | |
162 | if ((key < 0) || (key >= size)) return false; | |
163 | ||
164 | v = arr[key].v; | |
165 | ||
166 | BringToFront(&(arr[key])); | |
167 | int searchidx = search_idx_fn(v); | |
168 | searchtbl[searchidx] = &(arr[key]); | |
169 | return true; | |
170 | } // bool Get(int key, uint64_t & v) | |
171 | ||
172 | ||
173 | void BringToFront(rz3_lruhash_elem * elem) { | |
174 | if (elem == newest) return; | |
175 | ||
176 | elem->prev->next = elem->next; | |
177 | if (elem->next == NULL) { | |
178 | oldest = elem->prev; | |
179 | } else { | |
180 | elem->next->prev = elem->prev; | |
181 | } | |
182 | elem->prev = NULL; | |
183 | elem->next = newest; | |
184 | newest->prev = elem; | |
185 | newest = elem; | |
186 | } | |
187 | ||
188 | int search_idx_fn(uint64_t v) { | |
189 | return (v & (size-1)) ^ ((v >> idxbits) & (size-1)); | |
190 | } | |
191 | ||
192 | void Report(FILE * fp) { | |
193 | fprintf(fp, "refs %lld misses %lld (%0.4f%%/ref)\n", refs, misses, misses*100.0/refs); | |
194 | uint64_t hits = refs-misses; | |
195 | fprintf(fp, " fasthits %lld (%0.4f%%/hit, %0.4f%%/ref)\n", searchtbl_hits, searchtbl_hits*100.0/hits, searchtbl_hits*100.0/refs); | |
196 | } | |
197 | ||
198 | int size; | |
199 | ||
200 | int idxbits; | |
201 | ||
202 | rz3_lruhash_elem * newest; | |
203 | rz3_lruhash_elem * oldest; | |
204 | ||
205 | rz3_lruhash_elem * arr; | |
206 | ||
207 | rz3_lruhash_elem ** searchtbl; // search here first. if fails, search entire list | |
208 | ||
209 | uint64_t refs; | |
210 | uint64_t misses; | |
211 | uint64_t searchtbl_hits; | |
212 | }; // struct rz3_lruhash | |
213 | ||
214 | #endif // _rz3_lruhash_h_ | |
215 |