00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef SHTTL_LRU_H
00033 #define SHTTL_LRU_H
00034
00035 #include <limits>
00036 #include <cassert>
00037 #include <stdexcept>
00038 #include <vector>
00039 #include <algorithm>
00040
00041 #include "shttl_types.h"
00042 #include "bit.h"
00043 #include "replacement.h"
00044
00045
00046 namespace shttl
00047 {
00048
00049
00050
00051 template< typename key_type >
00052 class lru_time : public replacer< key_type >
00053 {
00054
00055 public:
00056 typedef typename replacer< key_type >::size_type size_type;
00057
00058 void construct( const size_type set_num , const size_type way_num )
00059 {
00060 m_lru.resize( set_num );
00061 for( size_t i = 0; i < m_lru.size(); i++ ){
00062 m_lru[i].construct( way_num );
00063 }
00064 }
00065
00066 size_type size()
00067 {
00068 return m_lru.size();
00069 }
00070
00071 void touch(
00072 const size_type index,
00073 const size_type way,
00074 const key_type key
00075 ){
00076 m_lru[ index ].touch( way );
00077 }
00078
00079 size_type target(
00080 const size_type index
00081 ){
00082 return m_lru[ index ].target();
00083 }
00084
00085 protected:
00086 class set
00087 {
00088 public:
00089
00090
00091 typedef u8 counter_type;
00092 typedef size_t size_type;
00093
00094 static const std::numeric_limits<counter_type> counter_info;
00095 static const std::numeric_limits<size_type> size_info;
00096
00097
00098 size_type size() const { return m_way_num; }
00099
00100
00101
00102 set( const size_type size ) :
00103 m_way_num(size),
00104 m_stamp( new counter_type[size] )
00105 {
00106 reset();
00107 }
00108
00109 set() :
00110 m_way_num(0),
00111 m_stamp(NULL)
00112 {
00113 m_mru = 0;
00114 m_tick = 0;
00115 }
00116
00117 void reset()
00118 {
00119 for (size_type w = 0; w < m_way_num; ++w)
00120 m_stamp[w] = (counter_type)w;
00121
00122 m_mru = m_way_num - 1;
00123 m_tick = (counter_type)m_way_num;
00124 }
00125
00126 ~set()
00127 {
00128 if(m_stamp)
00129 delete[] m_stamp;
00130 }
00131
00132 void construct( const size_type way_num )
00133 {
00134 if(m_stamp)
00135 delete[] m_stamp;
00136
00137 m_way_num = way_num;
00138 m_stamp = new counter_type[way_num];
00139 reset();
00140 }
00141
00142 void touch( const size_type i )
00143 {
00144 if(size() <= i)
00145 throw std::out_of_range("set::touch");
00146
00147 if (i == m_mru) return;
00148
00149 if (m_tick == counter_info.max())
00150 rewind();
00151
00152 m_stamp[i] = m_tick++;
00153 m_mru = i;
00154 }
00155
00156 size_type target()
00157 {
00158 size_type i = 0;
00159 size_type min = m_stamp[0];
00160 for (size_type j = 1; j < size(); ++j) {
00161 if (m_stamp[j] < min) {
00162 i = j;
00163 min = m_stamp[j];
00164 }
00165 }
00166 return i;
00167 }
00168
00169
00170 protected:
00171
00172
00173 size_type m_way_num;
00174
00175 counter_type* m_stamp;
00176 counter_type m_tick;
00177 size_type m_mru;
00178
00179 void rewind()
00180 {
00181 std::vector< std::pair<counter_type, size_type> > v(size());
00182
00183 for (size_type i = 0; i < size(); ++i)
00184 v[i] = std::pair<counter_type, size_type>(m_stamp[i], i);
00185
00186 sort(v.begin(), v.end());
00187
00188 for (size_type i = 0; i < size(); ++i)
00189 m_stamp[v[i].second] = (counter_type)i;
00190
00191 SHTTL_ASSERT(m_stamp[m_mru] == size() - 1);
00192 m_tick = (counter_type)size();
00193 }
00194
00195 };
00196
00197 typedef std::vector<set> lru_array;
00198 typedef typename lru_array::reference reference;
00199
00200 lru_array m_lru;
00201 };
00202
00203
00204
00205
00206
00207
00208
00209 template< typename key_type, typename order_type = u8 >
00210 class lru_order : public replacer< key_type >
00211 {
00212 public:
00213 typedef typename replacer< key_type >::size_type size_type;
00214 typedef typename std::vector<order_type> order_array_type;
00215 typedef typename order_array_type::iterator iterator;
00216
00217 lru_order()
00218 {
00219 m_way_num = 0;
00220 m_set_num = 0;
00221 }
00222
00223 void construct( const size_type set_num, const size_type way_num )
00224 {
00225 m_way_num = way_num;
00226 m_set_num = set_num;
00227
00228 size_t size = set_num * way_num;
00229
00230 if( std::numeric_limits<order_type>().max() <= way_num ){
00231 throw std::invalid_argument(
00232 "shttl::lru_order() \n THe specified way number is too large."
00233 );
00234 }
00235
00236 m_order.resize( size );
00237
00238 for( size_t i = 0; i < set_num; i++ ){
00239 reset_set( i );
00240 }
00241
00242 }
00243
00244 size_type size()
00245 {
00246 return m_set_num;
00247 }
00248
00249 size_type target( const size_type index )
00250 {
00251 return get_set( index )[0];
00252 }
00253
00254 void touch( const size_type index, const size_type way, const key_type key )
00255 {
00256 iterator set = get_set( index );
00257
00258
00259
00260
00261 bool sride = false;
00262 for( size_t w = 0; w < m_way_num; w++ ){
00263 if( sride ){
00264 set[ w-1 ] = set[ w ];
00265 }
00266 else{
00267 if( set[ w ] == way ){
00268 sride = true;
00269 }
00270 }
00271 }
00272 set[ m_way_num - 1 ] = (order_type)way;
00273
00274 }
00275
00276 protected:
00277
00278 size_t m_way_num;
00279 size_t m_set_num;
00280 order_array_type m_order;
00281
00282 iterator get_set( const size_type index )
00283 {
00284 size_t offset = index * m_way_num;
00285 return m_order.begin() + offset;
00286 }
00287
00288 void reset_set( size_type index )
00289 {
00290 iterator set = get_set( index );
00291 for( size_t i = 0; i < m_way_num; i++ ){
00292 set[i] = (order_type)i;
00293 }
00294 }
00295
00296
00297 };
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 template< typename key_type, typename pointer_type = u8 >
00316 class lru_list : public replacer< key_type >
00317 {
00318 public:
00319 typedef typename replacer< key_type >::size_type size_type;
00320
00321 struct element_type
00322 {
00323 pointer_type prev;
00324 pointer_type next;
00325 };
00326
00327 typedef typename std::vector<element_type> array_type;
00328 typedef typename array_type::iterator iterator;
00329
00330 lru_list()
00331 {
00332 m_way_num = 0;
00333 m_set_num = 0;
00334 m_pitch = 0;
00335 }
00336
00337 void construct( const size_type set_num, const size_type way_num )
00338 {
00339 m_way_num = way_num;
00340 m_set_num = set_num;
00341 m_pitch = way_num + 1;
00342 size_t size = set_num * m_pitch;
00343
00344 if( std::numeric_limits<pointer_type>().max() <= m_pitch ){
00345 throw std::invalid_argument(
00346 "shttl::lru_list() \n The specified way number is too large."
00347 );
00348 }
00349
00350 m_array.resize( size );
00351
00352 for( size_t i = 0; i < set_num; i++ ){
00353 reset_set( i );
00354 }
00355
00356 }
00357
00358 size_type size()
00359 {
00360 return m_set_num;
00361 }
00362
00363 size_type target( const size_type index )
00364 {
00365 return get_footer( index )->next;
00366 }
00367
00368 void touch( const size_type index, const size_type way, const key_type key )
00369 {
00370 iterator set = get_set( index );
00371 iterator cur = set + way;
00372
00373
00374 erase( set, cur );
00375
00376
00377 insert(
00378 set,
00379 set + m_way_num,
00380 cur
00381 );
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 }
00392
00393 protected:
00394
00395 size_t m_way_num;
00396 size_t m_pitch;
00397 size_t m_set_num;
00398 array_type m_array;
00399
00400 iterator get_set( const size_type index )
00401 {
00402 size_t offset = index * m_pitch;
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 return m_array.begin() + offset;
00414 }
00415
00416
00417 iterator get_footer( const size_type index )
00418 {
00419 return get_set( index ) + m_way_num;
00420 }
00421
00422
00423 void reset_set( size_type index )
00424 {
00425
00426
00427
00428
00429
00430
00431 iterator set = get_set( index );
00432
00433 for( size_t i = 0; i < m_way_num + 1; i++ ){
00434 ( set + i )->prev = (pointer_type)(i - 1);
00435 ( set + i )->next = (pointer_type)(i + 1);
00436 }
00437
00438 (set + 0)->prev = (pointer_type)m_way_num;
00439 (set + m_way_num)->next = (pointer_type)0;
00440 }
00441
00442
00443 void erase( iterator set, iterator cur )
00444 {
00445 iterator prev = set + cur->prev;
00446 iterator next = set + cur->next;
00447 prev->next = cur->next;
00448 next->prev = cur->prev;
00449 }
00450
00451
00452 void insert( iterator set, iterator pos, iterator cur )
00453 {
00454 iterator prev = set + pos->prev;
00455 cur->prev = pos->prev;
00456 cur->next = (pointer_type)(pos - set);
00457 prev->next = (pointer_type)(cur - set);
00458 pos->prev = (pointer_type)(cur - set);
00459 }
00460
00461 };
00462
00463
00464
00465
00466 template< typename key_type >
00467 class lru : public lru_list< key_type >
00468 {
00469 };
00470
00471 }
00472
00473 #endif // SHTTL_LRU_H