[2] | 1 | #ifndef CACHE_ONELEVEL_H |
---|
| 2 | #define CACHE_ONELEVEL_H |
---|
| 3 | |
---|
| 4 | #include <stdint.h> |
---|
| 5 | #include <math.h> |
---|
| 6 | #include <iostream> |
---|
| 7 | #include <iomanip> |
---|
| 8 | #include "../file/sort_file_dynamic.h" |
---|
| 9 | #include "type_req_cache.h" |
---|
| 10 | #include "tag.h" |
---|
| 11 | #include "address.h" |
---|
| 12 | #include "access_port.h" |
---|
| 13 | #include "write_buffer.h" |
---|
| 14 | |
---|
| 15 | using namespace std; |
---|
| 16 | using namespace hierarchy_memory::sort_file; |
---|
| 17 | using namespace hierarchy_memory::cache::cache_multilevel; |
---|
| 18 | |
---|
| 19 | namespace hierarchy_memory { |
---|
| 20 | namespace cache { |
---|
| 21 | namespace cache_multilevel { |
---|
| 22 | namespace cache_onelevel { |
---|
| 23 | |
---|
| 24 | class param_cache_t |
---|
| 25 | { |
---|
| 26 | public : const char * name ; |
---|
| 27 | public : uint32_t nb_line ; |
---|
| 28 | public : uint32_t size_line ; |
---|
| 29 | public : uint32_t size_word ; |
---|
| 30 | public : uint32_t associativity; |
---|
| 31 | public : uint32_t hit_latence ; |
---|
| 32 | public : uint32_t miss_penality; |
---|
| 33 | |
---|
| 34 | public : param_cache_t () {}; |
---|
| 35 | |
---|
| 36 | public : param_cache_t (const char * name , |
---|
| 37 | uint32_t nb_line , |
---|
| 38 | uint32_t size_line , |
---|
| 39 | uint32_t size_word , |
---|
| 40 | uint32_t associativity, |
---|
| 41 | uint32_t hit_latence , |
---|
| 42 | uint32_t miss_penality |
---|
| 43 | ) : |
---|
| 44 | name (name) |
---|
| 45 | { |
---|
| 46 | //this->name = name ; |
---|
| 47 | this->nb_line = nb_line ; |
---|
| 48 | this->size_line = size_line ; |
---|
| 49 | this->size_word = size_word ; |
---|
| 50 | this->associativity = associativity; |
---|
| 51 | this->hit_latence = hit_latence ; |
---|
| 52 | this->miss_penality = miss_penality; |
---|
| 53 | } |
---|
| 54 | |
---|
| 55 | friend ostream& operator<< (ostream& output_stream, const param_cache_t & x) |
---|
| 56 | { |
---|
| 57 | output_stream << "<" << x.name << "> " |
---|
| 58 | << x.nb_line << " " |
---|
| 59 | << x.size_line << " " |
---|
| 60 | << x.size_word << " " |
---|
| 61 | << x.associativity << " " |
---|
| 62 | << x.hit_latence << " " |
---|
| 63 | << x.miss_penality; |
---|
| 64 | |
---|
| 65 | return output_stream; |
---|
| 66 | } |
---|
| 67 | };//end param_cache_t |
---|
| 68 | |
---|
| 69 | class param_t |
---|
| 70 | { |
---|
| 71 | public : uint32_t nb_port ; |
---|
| 72 | public : param_cache_t param_cache; |
---|
| 73 | |
---|
| 74 | public : param_t (uint32_t nb_port , |
---|
| 75 | param_cache_t param_cache) |
---|
| 76 | { |
---|
| 77 | this->nb_port = nb_port ; |
---|
| 78 | this->param_cache = param_cache ; |
---|
| 79 | } |
---|
| 80 | |
---|
| 81 | friend ostream& operator<< (ostream& output_stream, const param_t & x) |
---|
| 82 | { |
---|
| 83 | output_stream << x.nb_port << " " |
---|
| 84 | << x.param_cache; |
---|
| 85 | return output_stream; |
---|
| 86 | } |
---|
| 87 | |
---|
| 88 | };//end param_t |
---|
| 89 | |
---|
| 90 | class Cache_OneLevel |
---|
| 91 | { |
---|
| 92 | protected : const uint32_t nb_port ; |
---|
| 93 | protected : const uint32_t nb_line ; |
---|
| 94 | protected : const uint32_t size_line ; |
---|
| 95 | protected : const uint32_t size_word ; |
---|
| 96 | protected : const uint32_t associativity ; |
---|
| 97 | protected : const uint32_t hit_latence ; |
---|
| 98 | protected : const uint32_t miss_penality ; |
---|
| 99 | |
---|
| 100 | private : char * name; |
---|
| 101 | private : tag_t ** tag; |
---|
| 102 | private : access_port_t * access_port; |
---|
| 103 | private : address_t size_address; |
---|
| 104 | private : Sort_File_Dynamic<write_buffer_t> * write_buffer; |
---|
| 105 | |
---|
| 106 | //*****[ constructor ]***** |
---|
| 107 | public : Cache_OneLevel (param_t param): |
---|
| 108 | nb_port (param.nb_port ), |
---|
| 109 | nb_line (param.param_cache.nb_line ), |
---|
| 110 | size_line (param.param_cache.size_line ), |
---|
| 111 | size_word (param.param_cache.size_word ), |
---|
| 112 | associativity (param.param_cache.associativity), |
---|
| 113 | hit_latence (param.param_cache.hit_latence ), |
---|
| 114 | miss_penality (param.param_cache.miss_penality) |
---|
| 115 | { |
---|
| 116 | uint32_t size_name = strlen(param.param_cache.name)+1; |
---|
| 117 | name = new char [size_name]; |
---|
| 118 | strncpy(name,param.param_cache.name,size_name); |
---|
| 119 | |
---|
| 120 | if ((nb_line * size_line * associativity) == 0) |
---|
| 121 | { |
---|
| 122 | cerr << "<" << name << ".{Cache_OneLevel}> all parameter must be greater that 0" << endl; |
---|
| 123 | cerr << " nb_line : " << nb_line << endl; |
---|
| 124 | cerr << " size_line : " << size_line << endl; |
---|
| 125 | cerr << " associativity : " << associativity << endl; |
---|
| 126 | exit(1); |
---|
| 127 | } |
---|
| 128 | if ((nb_line % associativity) != 0) |
---|
| 129 | { |
---|
| 130 | cerr << "<" << name << ".{Cache_OneLevel}> nb_line must be a mutiple of associativity" << endl; |
---|
| 131 | cerr << " * nb_line : " << nb_line << endl; |
---|
| 132 | cerr << " * associativity : " << associativity << endl; |
---|
| 133 | exit(1); |
---|
| 134 | } |
---|
| 135 | |
---|
| 136 | if ((double)nb_line != ::pow(2,::log2(nb_line))) |
---|
| 137 | { |
---|
| 138 | cerr << "<" << name << ".{Cache_OneLevel}> nb_line must be a mutiple of 2^n" << endl; |
---|
| 139 | cerr << " * nb_line : " << nb_line << endl; |
---|
| 140 | exit(1); |
---|
| 141 | } |
---|
| 142 | |
---|
| 143 | if ((double)size_line != ::pow(2,::log2(size_line))) |
---|
| 144 | { |
---|
| 145 | cerr << "<" << name << ".{Cache_OneLevel}> size_line must be a mutiple of 2^n" << endl; |
---|
| 146 | cerr << " * size_line : " << size_line << endl; |
---|
| 147 | exit(1); |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | if ((double)size_word != ::pow(2,::log2(size_word))) |
---|
| 151 | { |
---|
| 152 | cerr << "<" << name << ".{Cache_OneLevel}> size_word must be a mutiple of 2^n" << endl; |
---|
| 153 | cerr << " * size_word : " << size_word << endl; |
---|
| 154 | exit(1); |
---|
| 155 | } |
---|
| 156 | |
---|
| 157 | write_buffer= new Sort_File_Dynamic<write_buffer_t> (sort_file::param_t("write_buffer",5)); |
---|
| 158 | access_port = new access_port_t [nb_port]; |
---|
| 159 | tag = new tag_t * [nb_line/associativity]; |
---|
| 160 | for (uint32_t it = 0; it < nb_line/associativity; it ++) |
---|
| 161 | tag [it] = new tag_t [associativity]; |
---|
| 162 | |
---|
| 163 | size_address.offset = (uint32_t) log2(size_line * size_word); |
---|
| 164 | size_address.familly = (uint32_t) log2(nb_line/associativity); |
---|
| 165 | size_address.tag = 32 - size_address.familly - size_address.offset; |
---|
| 166 | } |
---|
| 167 | |
---|
| 168 | //*****[ destructor ]***** |
---|
| 169 | public : ~Cache_OneLevel () |
---|
| 170 | { |
---|
| 171 | // delete tag; |
---|
| 172 | // delete access_port; |
---|
| 173 | }; |
---|
| 174 | |
---|
| 175 | //*****[ reset ]***** |
---|
| 176 | public : void reset () |
---|
| 177 | { |
---|
| 178 | for (uint32_t x = 0; x < nb_port; x ++) |
---|
| 179 | access_port[x].valid = false; |
---|
| 180 | |
---|
| 181 | for (uint32_t x = 0; x < nb_line/associativity; x ++) |
---|
| 182 | for (uint32_t y = 0; y < associativity; y ++) |
---|
| 183 | { |
---|
| 184 | tag[x][y].valid = false; |
---|
| 185 | tag[x][y].index_lru = y; |
---|
| 186 | } |
---|
| 187 | write_buffer->reset(); |
---|
| 188 | } |
---|
| 189 | |
---|
| 190 | //*****[ transition ]***** |
---|
| 191 | public : void transition () |
---|
| 192 | { |
---|
| 193 | // scan all port - test if have a transaction |
---|
| 194 | for (int32_t x = nb_port-1; x >= 0; x --) |
---|
| 195 | { |
---|
| 196 | if (access_port[x].valid == true) |
---|
| 197 | { |
---|
| 198 | access_port[x].valid = false; |
---|
| 199 | |
---|
| 200 | // Update LRU |
---|
| 201 | // * hit : now |
---|
| 202 | // * miss : after the return of next cache |
---|
| 203 | |
---|
| 204 | if (access_port[x].hit == HIT_CACHE) |
---|
| 205 | {// Hit |
---|
| 206 | update_lru(access_port[x].address.familly,access_port[x].num_associativity); |
---|
| 207 | } |
---|
| 208 | |
---|
| 209 | if (access_port[x].hit == MISS) |
---|
| 210 | {// Miss |
---|
| 211 | // Write in write_buffer |
---|
| 212 | write_buffer->push(access_port[x].latence,write_buffer_t(access_port[x].address,access_port[x].trdid)); |
---|
| 213 | } |
---|
| 214 | } |
---|
| 215 | } |
---|
| 216 | |
---|
| 217 | // Test if a write_buffer have the result |
---|
| 218 | while ((write_buffer->empty() == false) && (write_buffer->read(0).delay == 0)) |
---|
| 219 | { |
---|
| 220 | // Save in the cache |
---|
| 221 | write_buffer_t val = write_buffer->pop(); |
---|
| 222 | |
---|
| 223 | uint32_t num_tag = val.address.tag; |
---|
| 224 | uint32_t num_familly = val.address.familly; |
---|
| 225 | uint32_t num_associativity = index_victim(num_familly); |
---|
| 226 | |
---|
| 227 | tag [num_familly][num_associativity].valid = true; |
---|
| 228 | tag [num_familly][num_associativity].address = num_tag; |
---|
| 229 | tag [num_familly][num_associativity].trdid = val.trdid; |
---|
| 230 | |
---|
| 231 | update_lru(num_familly,num_associativity); |
---|
| 232 | } |
---|
| 233 | |
---|
| 234 | write_buffer->transition(); |
---|
| 235 | } |
---|
| 236 | //*****[ update_lru ]***** |
---|
| 237 | private : void update_lru (uint32_t familly, uint32_t num_associativity) |
---|
| 238 | { |
---|
| 239 | uint32_t current_lru = tag [familly][num_associativity].index_lru; |
---|
| 240 | |
---|
| 241 | for (uint32_t k = 0; k < associativity; k ++) |
---|
| 242 | if (tag [familly][k].index_lru < current_lru) |
---|
| 243 | tag [familly][k].index_lru ++; |
---|
| 244 | tag [familly][num_associativity].index_lru = 0; |
---|
| 245 | } |
---|
| 246 | |
---|
| 247 | //*****[ index_victim ]***** |
---|
| 248 | // return the index of the nex victim |
---|
| 249 | public : uint32_t index_victim (uint32_t familly) |
---|
| 250 | { |
---|
| 251 | uint32_t victim = 0; |
---|
| 252 | while (tag [familly][victim].index_lru != (associativity-1)) |
---|
| 253 | { |
---|
| 254 | victim ++; |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | return victim; |
---|
| 258 | } |
---|
| 259 | |
---|
| 260 | //*****[ translate_address ]***** |
---|
| 261 | private : address_t translate_address (uint32_t address) |
---|
| 262 | { |
---|
| 263 | address_t address_translated; |
---|
| 264 | uint32_t shift; |
---|
| 265 | |
---|
| 266 | address_translated.offset = (address & ((uint32_t)-1 >> (32-(size_address.offset )))); |
---|
| 267 | address -= address_translated.offset; |
---|
| 268 | shift = size_address.offset; |
---|
| 269 | address_translated.familly = (address & ((uint32_t)-1 >> (32-(size_address.familly + shift))))>>shift; |
---|
| 270 | address -= address_translated.familly; |
---|
| 271 | shift += size_address.familly; |
---|
| 272 | address_translated.tag = (address & ((uint32_t)-1 >> (32-(size_address.tag + shift))))>>shift; |
---|
| 273 | |
---|
| 274 | return address_translated; |
---|
| 275 | } |
---|
| 276 | |
---|
| 277 | //******************** |
---|
| 278 | //******************** |
---|
| 279 | |
---|
| 280 | //*****[ access ]***** |
---|
| 281 | // Return hit (true) |
---|
| 282 | // uncache is to stocke the address on the cache |
---|
| 283 | public : type_rsp_cache_t access (uint32_t nb_port, uint32_t address, uint32_t trdid, type_req_cache_t type, direction_req_cache_t dir) |
---|
| 284 | { |
---|
| 285 | switch (type) |
---|
| 286 | { |
---|
| 287 | case UNCACHED : return access_uncached (nb_port,address,trdid ); break; |
---|
| 288 | case INVALIDATE : return access_invalidate (nb_port,address,trdid ); break; |
---|
| 289 | case FLUSH : return access_flush (nb_port,address,trdid ); break; |
---|
| 290 | case PREFETCH : // no difference with the simple read cached (have no add a prefetch cache) |
---|
| 291 | case CACHED : return access_cached (nb_port,address,trdid,dir); break; |
---|
| 292 | default : cout << "<Cache_Onelevel.access> unkonow type : " << endl; exit(1); break; |
---|
| 293 | } |
---|
| 294 | } |
---|
| 295 | |
---|
| 296 | // *****[ access_cached ]***** |
---|
| 297 | public : type_rsp_cache_t access_cached (uint32_t nb_port, uint32_t address, uint32_t trdid, direction_req_cache_t dir) |
---|
| 298 | { |
---|
| 299 | address_t address_translate = translate_address(address); |
---|
| 300 | uint32_t num_associativity = hit_cache (trdid, address_translate); |
---|
| 301 | uint32_t num_port = hit_access_port (trdid, address_translate); |
---|
| 302 | uint32_t num_write_buffer = hit_write_buffer (trdid, address_translate); |
---|
| 303 | |
---|
| 304 | if (num_port == this->nb_port) |
---|
| 305 | num_port = nb_port; |
---|
| 306 | |
---|
| 307 | uint32_t latence ; |
---|
| 308 | type_rsp_cache_t res = MISS; |
---|
| 309 | |
---|
| 310 | bool is_in_cache = (num_associativity != associativity); |
---|
| 311 | bool is_in_access_port = (num_port != nb_port); |
---|
| 312 | bool is_in_write_buffer = false; |
---|
| 313 | |
---|
| 314 | if (is_in_access_port == true) |
---|
| 315 | { |
---|
| 316 | res = HIT_BYPASS; |
---|
| 317 | latence = access_port[num_port].latence; //already compute |
---|
| 318 | } |
---|
| 319 | else |
---|
| 320 | if (is_in_cache == true) |
---|
| 321 | { |
---|
| 322 | res = HIT_CACHE; |
---|
| 323 | latence = 0; // Hit !!! |
---|
| 324 | } |
---|
| 325 | else |
---|
| 326 | { |
---|
| 327 | // Search in the write buffer, and test if have a miss |
---|
| 328 | if ( num_write_buffer == write_buffer->nb_slot_use()) |
---|
| 329 | { |
---|
| 330 | res = MISS; |
---|
| 331 | latence = miss_penality; // miss -> access at down of cache, + respons at the up of cache |
---|
| 332 | } |
---|
| 333 | else |
---|
| 334 | { |
---|
| 335 | res = HIT_WRITE_BUFFER; |
---|
| 336 | is_in_write_buffer = true; |
---|
| 337 | latence = write_buffer->read(num_write_buffer).delay; |
---|
| 338 | } |
---|
| 339 | } |
---|
| 340 | |
---|
| 341 | // access_port valid = there are a new request to update |
---|
| 342 | // -> no previous request in the same cycle (hit in a access port) |
---|
| 343 | // -> no previous request in the previous cycle (hit in the write buffer) |
---|
| 344 | |
---|
| 345 | access_port[nb_port].valid = ((is_in_access_port || is_in_write_buffer) == false); |
---|
| 346 | access_port[nb_port].address = address_translate; |
---|
| 347 | access_port[nb_port].trdid = trdid; |
---|
| 348 | access_port[nb_port].hit = res; |
---|
| 349 | access_port[nb_port].num_associativity = num_associativity; |
---|
| 350 | access_port[nb_port].latence = latence; |
---|
| 351 | |
---|
| 352 | return res; |
---|
| 353 | } |
---|
| 354 | |
---|
| 355 | // *****[ access_uncached ]***** |
---|
| 356 | public : type_rsp_cache_t access_uncached (uint32_t nb_port, uint32_t address, uint32_t trdid) |
---|
| 357 | { |
---|
| 358 | access_port[nb_port].valid = false; |
---|
| 359 | access_port[nb_port].trdid = trdid; |
---|
| 360 | access_port[nb_port].hit = MISS; |
---|
| 361 | access_port[nb_port].latence = miss_penality; |
---|
| 362 | |
---|
| 363 | return MISS; |
---|
| 364 | } |
---|
| 365 | // *****[ access_invalidate ]***** |
---|
| 366 | public : type_rsp_cache_t access_invalidate (uint32_t nb_port, uint32_t address, uint32_t trdid) |
---|
| 367 | { |
---|
| 368 | cerr << "<" << name << ".{Cache_OneLevel}.access_invalidate> Not implemented" << endl; |
---|
| 369 | exit (0); |
---|
| 370 | return MISS; |
---|
| 371 | } |
---|
| 372 | |
---|
| 373 | // *****[ access_flush ]***** |
---|
| 374 | public : type_rsp_cache_t access_flush (uint32_t nb_port, uint32_t address, uint32_t trdid) |
---|
| 375 | { |
---|
| 376 | cerr << "<" << name << ".{Cache_OneLevel}.access_flush> Not implemented" << endl; |
---|
| 377 | exit (0); |
---|
| 378 | return MISS; |
---|
| 379 | } |
---|
| 380 | |
---|
| 381 | //****************************** |
---|
| 382 | //****************************** |
---|
| 383 | |
---|
| 384 | //*****[ hit_write_buffer ]***** |
---|
| 385 | |
---|
| 386 | // If a instruction is in the write_buffer, return the position |
---|
| 387 | // else, return the number of elt in the write_buffer |
---|
| 388 | public : uint32_t hit_write_buffer (uint32_t trdid, address_t address) |
---|
| 389 | { |
---|
| 390 | uint32_t num_write_buffer = 0; |
---|
| 391 | // Scan the write_buffer |
---|
| 392 | for (num_write_buffer = 0; num_write_buffer < write_buffer->nb_slot_use(); num_write_buffer ++) |
---|
| 393 | { |
---|
| 394 | slot_t<write_buffer_t> val = write_buffer->read(num_write_buffer); |
---|
| 395 | |
---|
| 396 | if ( (val.data.trdid == trdid ) && |
---|
| 397 | (val.data.address.tag == address.tag ) && |
---|
| 398 | (val.data.address.familly == address.familly)) |
---|
| 399 | break; |
---|
| 400 | } |
---|
| 401 | |
---|
| 402 | return num_write_buffer; |
---|
| 403 | } |
---|
| 404 | |
---|
| 405 | //*****[ hit_access_port ]***** |
---|
| 406 | // return the number of associativity if hit |
---|
| 407 | // return nb_accosiativity if miss |
---|
| 408 | public : uint32_t hit_cache (uint32_t trdid, address_t address) |
---|
| 409 | { |
---|
| 410 | uint32_t num_associativity; |
---|
| 411 | for (num_associativity = 0; num_associativity < associativity; num_associativity ++) |
---|
| 412 | // Hit if : |
---|
| 413 | // * in the line |
---|
| 414 | // * in a way associative |
---|
| 415 | // -> there are the same tag |
---|
| 416 | // the same trdid |
---|
| 417 | // is valid |
---|
| 418 | if ( (tag [address.familly][num_associativity].address == address.tag) && |
---|
| 419 | (tag [address.familly][num_associativity].valid == true ) && |
---|
| 420 | (tag [address.familly][num_associativity].trdid == trdid ) ) |
---|
| 421 | break; |
---|
| 422 | |
---|
| 423 | return num_associativity; |
---|
| 424 | } |
---|
| 425 | |
---|
| 426 | //*****[ hit_access_port ]***** |
---|
| 427 | // Return the number of port if hit |
---|
| 428 | // Return nb_port if miss |
---|
| 429 | public : uint32_t hit_access_port (uint32_t trdid, address_t address) |
---|
| 430 | { |
---|
| 431 | uint32_t it_num_port = 0; |
---|
| 432 | |
---|
| 433 | // scan all port - test if have a transaction |
---|
| 434 | for (it_num_port = 0; it_num_port < nb_port; it_num_port ++) |
---|
| 435 | if ( (access_port[it_num_port].valid == true ) && |
---|
| 436 | (access_port[it_num_port].trdid == trdid ) && |
---|
| 437 | (access_port[it_num_port].address.tag == address.tag ) && |
---|
| 438 | (access_port[it_num_port].address.familly == address.familly)) |
---|
| 439 | break; |
---|
| 440 | |
---|
| 441 | return it_num_port; |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | //*****[ need_slot ]***** |
---|
| 445 | public : uint32_t need_slot () |
---|
| 446 | { |
---|
| 447 | uint32_t res = 0; |
---|
| 448 | // scan all port - test if have a transaction |
---|
| 449 | for (uint32_t x = 0; x < nb_port; x ++) |
---|
| 450 | if (access_port[x].valid == true) |
---|
| 451 | res ++; |
---|
| 452 | |
---|
| 453 | return res; |
---|
| 454 | } |
---|
| 455 | |
---|
| 456 | //*****[ latence ]***** |
---|
| 457 | // Return the time to have the data |
---|
| 458 | // uncache is to stocke the address on the cache |
---|
| 459 | public : uint32_t latence (uint32_t num_port) |
---|
| 460 | { |
---|
| 461 | uint32_t res = hit_latence + access_port[num_port].latence; |
---|
| 462 | |
---|
| 463 | return res; |
---|
| 464 | } |
---|
| 465 | |
---|
| 466 | //*****[ update_latence ]***** |
---|
| 467 | // Return the time to have the data |
---|
| 468 | // uncache is to stocke the address on the cache |
---|
| 469 | public : bool update_latence (uint32_t nb_port, uint32_t latence) |
---|
| 470 | { |
---|
| 471 | access_port[nb_port].latence = latence-hit_latence; |
---|
| 472 | return access_port[nb_port].valid; |
---|
| 473 | } |
---|
| 474 | |
---|
| 475 | //*****[ information ]***** |
---|
| 476 | public : void information (void) |
---|
| 477 | { |
---|
| 478 | cout << "<" << name << ">" << endl |
---|
| 479 | << " * Information" << endl |
---|
| 480 | << " * Capacity : " << nb_line * size_line * size_word << " bytes" << endl |
---|
| 481 | << " * Nb line : " << nb_line << endl |
---|
| 482 | << " * Size line : " << size_line << endl |
---|
| 483 | << " * Size word : " << size_word << endl |
---|
| 484 | << " * Associativity : " << associativity << endl |
---|
| 485 | << " * Timing : " << endl |
---|
| 486 | << " * Hit latence : " << hit_latence << endl |
---|
| 487 | << " * Miss penality : " << miss_penality << endl |
---|
| 488 | << " * Nb port : " << nb_port << endl |
---|
| 489 | << endl; |
---|
| 490 | } |
---|
| 491 | |
---|
| 492 | friend ostream& operator<< (ostream& output_stream, const Cache_OneLevel & x) |
---|
| 493 | { |
---|
| 494 | output_stream << "<" << x.name << ">" << endl |
---|
| 495 | << " * Capacity : " << x.nb_line * x.size_line * x.size_word << " bytes" << endl |
---|
| 496 | << " * Nb line : " << x.nb_line << endl |
---|
| 497 | << " * Size line : " << x.size_line << endl |
---|
| 498 | << " * Size word : " << x.size_word << endl |
---|
| 499 | << " * Associativity : " << x.associativity << endl |
---|
| 500 | << " * Timing : " << endl |
---|
| 501 | << " * Hit latence : " << x.hit_latence << endl |
---|
| 502 | << " * Miss penality : " << x.miss_penality << endl |
---|
| 503 | << " * Nb port : " << x.nb_port << endl |
---|
| 504 | << endl; |
---|
| 505 | |
---|
| 506 | output_stream << " * Tag" << endl; |
---|
| 507 | for (uint32_t i = 0; i < x.nb_line / x.associativity; i ++) |
---|
| 508 | { |
---|
| 509 | for (uint32_t j = 0; j < x.associativity; j ++) |
---|
| 510 | output_stream << x.tag [i][j] << " | "; |
---|
| 511 | output_stream << endl; |
---|
| 512 | } |
---|
| 513 | |
---|
| 514 | output_stream << endl; |
---|
| 515 | output_stream << *x.write_buffer << endl; |
---|
| 516 | |
---|
| 517 | return output_stream; |
---|
| 518 | } |
---|
| 519 | |
---|
| 520 | }; |
---|
| 521 | };};};}; |
---|
| 522 | #endif //!CACHE_ONELEVEL_H |
---|
| 523 | |
---|