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
00028
00032
00033
00034
00035 #include "ac_cache.H"
00036 #include "ac_resources.H"
00037
00039 void ac_cache::tracing(unsigned address, unsigned type)
00040 {
00041 #ifdef AC_TRACE
00042 access_type = type;
00043 size_ref = 1;
00044 char * buffer;
00045 buffer = new char [8];
00046 for (int b = 0; b < 8; b++)
00047 buffer[b]=0;
00048 buffer[0] = address;
00049 buffer[4] = size_ref;
00050 buffer[6] = access_type;
00051 buffer[7] = padding;
00052
00053 trace << address << endl;
00054 delete[] buffer;
00055 #endif
00056 }
00057
00059 void ac_cache::addressing(unsigned address)
00060 {
00062 unsigned offset_field = (AC_WORDSIZE/8) * this->block_size;
00063 unsigned index_field = this->num_sets;
00064 unsigned tag_field = offset_field*index_field;
00065 this->offset = address % offset_field;
00066 this->set = (address/offset_field) % index_field;
00067 this->address_tag = address/tag_field;
00068
00070 slot_tag = (unsigned *)(this->tag + (this->set * this->set_size));
00071 slot_valid = (bool *)(this->valid + (this->set * this->set_size));
00072 hit = -1;
00073 unsigned *test_tag;
00074 bool *test_valid;
00075
00076
00077 for(this->element = 0; this->element < this->set_size ; this->element++)
00078 {
00079 test_tag = (unsigned *)(slot_tag + element);
00080 test_valid = (bool *)(slot_valid + element);
00081
00082 if((*test_tag == address_tag)&&(*test_valid))
00083 {
00084 hit = element;
00085
00086 }
00087 }
00088
00089 if(hit!=-1)
00090 {
00091 slot_data = (char *)(this->Data + (hit + this->set * this->set_size) *this->block_size * AC_WORDSIZE/8);
00092 slot_tag = (unsigned *)(this->tag + (hit + this->set * this->set_size));
00093 slot_valid = (bool *)(this->valid + (hit + this->set * this->set_size));
00094 slot_dirty = (bool *)(this->dirty + (hit + this->set * this->set_size));
00095 }
00096 else
00097 {
00098 this->element = get_chosen(set);
00099 slot_data = (char *)(this->Data + (this->element + set * this->set_size) *this->block_size * AC_WORDSIZE/8);
00100 slot_tag = (unsigned *)(this->tag + (this->element + set * this->set_size));
00101 slot_valid = (bool *)(this->valid + (this->element + set * this->set_size));
00102 slot_dirty = (bool *)(this->dirty + (this->element + set * this->set_size));
00103 }
00104 }
00105
00106
00108 void ac_cache::replaceBlockWrite()
00109 {
00110
00111 unsigned base_address, f;
00112 switch(replace_status)
00113 {
00114 case 0:
00115
00116 if((isWriteBack())&&(isWriteAllocate())&&(this->next_level != NULL)&&(*slot_valid==true)&&(*slot_dirty==true))
00117 {
00118
00119 this->writingBack();
00120 break;
00121 }
00122 else
00123 {
00124
00125 replace_status++;
00126 }
00127
00128
00129
00130 case 1:
00131
00132
00133 if(isWriteAllocate())
00134 {
00135 f = ~(0);
00136 f = (unsigned) (f * block_size * AC_WORDSIZE/8);
00137 base_address = requested_address & f;
00138
00139 if(this->next_level != NULL)
00140 {
00141
00142 this->next_level->request_block(this, base_address, block_size*AC_WORDSIZE/8);
00143 break;
00144 }
00145 }
00146 else
00147 {
00148 replace_status++;
00149 }
00150
00151 case 2:
00152
00153
00154
00155 if(isWriteAllocate())
00156 {
00157 if(write_size == W_WORD)
00158 this->ac_storage::write(slot_data + offset - Data, *(ac_word*)datum_ref);
00159 else if(write_size == W_HALF)
00160 this->ac_storage::write_half(slot_data + offset - Data, *(unsigned short*)datum_ref);
00161 else if(write_size == W_BYTE)
00162 this->ac_storage::write_byte(slot_data + offset - Data, *(char*)datum_ref);
00163
00164 if(isWriteBack())
00165 {
00166 *(slot_dirty) = true;
00167 this->ready();
00168
00169 break;
00170 }
00171 else
00172 {
00173 replace_status++;
00174 }
00175 }
00176 else
00177 {
00178 replace_status++;
00179 }
00180
00181 case 3:
00182
00183
00184 if(this->next_level != NULL)
00185 {
00186 if(write_size == W_WORD)
00187 {
00188 this->next_level->request_write(this, requested_address, *(ac_word*)datum_ref);
00189 break;
00190 }
00191 else if(write_size == W_HALF)
00192 {
00193 this->next_level->request_write_half(this, requested_address, *(unsigned short*)datum_ref);
00194 break;
00195 }
00196 else if(write_size == W_BYTE)
00197 {
00198 this->next_level->request_write_byte(this, requested_address, *(char*)datum_ref);
00199 break;
00200 }
00201 }
00202
00203 }
00204 }
00205
00207 void ac_cache::replaceBlockRead(unsigned address)
00208 {
00209
00210 unsigned base_address, f;
00211 switch(replace_status)
00212 {
00213 case 0:
00214 if((isWriteBack())&&(this->next_level != NULL)&&(*slot_valid==true)&&(*slot_dirty==true))
00215 {
00216
00217 this->writingBack();
00218
00219 break;
00220 }
00221 else
00222 {
00223 replace_status++;
00224 }
00225
00226 case 1:
00227
00228 f = ~(0);
00229 f = (unsigned) (f * block_size * AC_WORDSIZE/8);
00230
00231
00232 base_address = requested_address & f;
00233 if(this->next_level != NULL)
00234 {
00235
00236
00237 this->next_level->request_block(this, base_address, block_size*AC_WORDSIZE/8);
00238 break;
00239 }
00240
00241 case 2:
00242 this->ready();
00243 }
00244 }
00245
00247 void ac_cache::writingBack()
00248 {
00249
00250 unsigned index_shift = ((AC_WORDSIZE/8) * this->block_size);
00251 unsigned tag_shift = index_shift*this->num_sets;
00252 unsigned base_address = (*slot_tag)*tag_shift + set*index_shift;
00253
00254
00255 this->next_level->request_write_block(this, base_address, this->slot_data, this->block_size*AC_WORDSIZE/8);
00256
00257 *slot_dirty = false;
00258
00259 }
00260
00261
00262 bool ac_cache::isWriteThrough()
00263 {
00264 if(write_policy & 0x01)
00265 return true;
00266 else
00267 return false;
00268 }
00269
00270 bool ac_cache::isWriteBack()
00271 {
00272 if(write_policy & 0x02)
00273 return true;
00274 else
00275 return false;
00276 }
00277
00278 bool ac_cache::isWriteAllocate()
00279 {
00280 if(write_policy & 0x10)
00281 return true;
00282 else
00283 return false;
00284 }
00285
00286 bool ac_cache::isWriteAround()
00287 {
00288 if(write_policy & 0x20)
00289 return true;
00290 else
00291 return false;
00292 }
00293
00294
00296 ac_word ac_cache::read( unsigned address )
00297 {
00298 read_access_type = true;
00299 ac_word data_out;
00300 this->ac_cache::addressing(address);
00301 #ifdef AC_TRACE
00302 this->ac_cache::tracing(address, 0); //access trace file registering a read operation
00303 #endif
00304
00305 if(hit != -1){
00306
00307 }
00308
00309 else if (this->next_level != NULL)
00310 {
00311 #ifdef AC_STATS
00312 ac_resources::ac_sim_stats.add_miss(name);
00313 #endif
00314 this->stall();
00315
00316 requested_address = address;
00317 this->replaceBlockRead(requested_address);
00318 }
00319 data_out = ac_storage::read(slot_data + offset - Data);
00320
00321 this->update(set, element);
00322 return (data_out);
00323 }
00324
00326 unsigned char ac_cache::read_byte( unsigned address )
00327 {
00328 read_access_type = true;
00329 unsigned char data_out;
00330 this->ac_cache::addressing(address);
00331 #ifdef AC_TRACE
00332 this->ac_cache::tracing(address, 0); //access trace file registering a read operation
00333 #endif
00334
00335 if(hit != -1){
00336 }
00337
00338 else if (this->next_level != NULL)
00339 {
00340 #ifdef AC_STATS
00341 ac_resources::ac_sim_stats.add_miss(name);
00342 #endif
00343 this->stall();
00344
00345 requested_address = address;
00346 this->replaceBlockRead(requested_address);
00347 }
00348 data_out = ac_storage::read_byte(slot_data + offset - Data);
00349
00350 this->update(set, element);
00351 return (data_out);
00352 }
00353
00355 ac_Hword ac_cache::read_half( unsigned address )
00356 {
00357 read_access_type = true;
00358 ac_Hword data_out;
00359 this->ac_cache::addressing(address);
00360 #ifdef AC_TRACE
00361 this->ac_cache::tracing(address, 0); //access trace file registering a read operation
00362 #endif
00363
00364 if(hit != -1){
00365 }
00366
00367 else if (this->next_level != NULL)
00368 {
00369 #ifdef AC_STATS
00370 ac_resources::ac_sim_stats.add_miss(name);
00371 #endif
00372 this->stall();
00373
00374 requested_address = address;
00375 this->replaceBlockRead(requested_address);
00376 }
00377 data_out = ac_storage::read_half(slot_data + offset - Data);
00378
00379 this->update(set, element);
00380 return (data_out);
00381 }
00382
00383
00385 void ac_cache::write( unsigned address, ac_word datum )
00386 {
00387 read_access_type = false;
00388 this->ac_cache::addressing(address);
00389 #ifdef AC_TRACE
00390 this->ac_cache::tracing(address, 1); //access trace file registering a write operation
00391 #endif
00392
00393 if(hit != -1){
00394
00395 if(isWriteBack())
00396 {
00397 *(slot_dirty) = true;
00398 }
00399 else if(isWriteThrough())
00400 {
00401 if(this->next_level != NULL)
00402 {
00403
00404 this->stall();
00405
00406
00407 if(datum != *(ac_word*)(slot_data + offset))
00408 this->next_level->request_write(this, address, datum);
00409 else
00410 this->ready();
00411 }
00412
00413
00414 }
00415
00416 this->ac_storage::write(slot_data + offset - Data, datum);
00417
00418 }
00419
00420 else
00421 {
00422
00423 #ifdef AC_STATS
00424 ac_resources::ac_sim_stats.add_miss(name);
00425 #endif
00426 if(this->next_level != NULL)
00427 {
00428
00429 if(!isWriteAround())
00430 this->stall();
00431
00432
00433 write_size = W_WORD;
00434 *(ac_word*)datum_ref = datum;
00435 requested_address = address;
00436
00437 this->replaceBlockWrite();
00438 }
00439 else
00440 {
00441 *(slot_tag) = address_tag;
00442 *(slot_valid) = true;
00443 *(slot_dirty) = true;
00444 this->ac_storage::write(slot_data + offset - Data, datum);
00445
00446 }
00447 }
00448 this->update(set, element);
00449 }
00450
00451
00453 void ac_cache::write_byte( unsigned address, unsigned char datum )
00454 {
00455 read_access_type = false;
00456 this->ac_cache::addressing(address);
00457 #ifdef AC_TRACE
00458 this->ac_cache::tracing(address, 1); //access trace file registering a write operation
00459 #endif
00460
00461 if(hit != -1){
00462
00463 if(isWriteBack())
00464 {
00465 *(slot_dirty) = true;
00466 }
00467 else if(isWriteThrough())
00468 {
00469 if(this->next_level != NULL)
00470 {
00471
00472 this->stall();
00473
00474 unsigned char tmp= ac_storage::read_byte(slot_data + offset - Data);
00475 if(datum != tmp)
00476 this->next_level->request_write_byte(this, address, datum);
00477 else
00478 this->ready();
00479 }
00480 }
00481
00482 this->ac_storage::write_byte(slot_data + offset - Data, datum);
00483 }
00484
00485 else
00486 {
00487 #ifdef AC_STATS
00488 ac_resources::ac_sim_stats.add_miss(name);
00489 #endif
00490 if(this->next_level != NULL)
00491 {
00492
00493 if(!isWriteAround())
00494 this->stall();
00495
00496
00497 write_size = W_BYTE;
00498 *(unsigned char*)datum_ref = datum;
00499 requested_address = address;
00500 this->replaceBlockWrite();
00501 }
00502 else
00503 {
00504 *(slot_tag) = address_tag;
00505 *(slot_valid) = true;
00506 *(slot_dirty) = true;
00507 this->ac_storage::write_byte(slot_data + offset - Data, datum);
00508 }
00509 }
00510 this->update(set, element);
00511 }
00512
00513
00515 void ac_cache::write_half( unsigned address, unsigned short datum )
00516 {
00517 read_access_type = false;
00518 this->ac_cache::addressing(address);
00519 #ifdef AC_TRACE
00520 this->ac_cache::tracing(address, 1); //access trace file registering a write operation
00521 #endif
00522
00523 if(hit != -1){
00524
00525 if(isWriteBack())
00526 {
00527 *(slot_dirty) = true;
00528 }
00529 else if(isWriteThrough())
00530 {
00531 if(this->next_level != NULL)
00532 {
00533
00534 this->stall();
00535
00536 unsigned short tmp= ac_storage::read_half(slot_data + offset - Data);
00537 if(datum != tmp)
00538 this->next_level->request_write_half(this, address, datum);
00539 else
00540 this->ready();
00541 }
00542
00543
00544 }
00545
00546 this->ac_storage::write_half(slot_data + offset - Data, datum);
00547 }
00548
00549 else
00550 {
00551 #ifdef AC_STATS
00552 ac_resources::ac_sim_stats.add_miss(name);
00553 #endif
00554 if(this->next_level != NULL)
00555 {
00556
00557 if(!isWriteAround())
00558 this->stall();
00559
00560
00561 write_size = W_HALF;
00562 *(unsigned short*)datum_ref = datum;
00563 requested_address = address;
00564 this->replaceBlockWrite();
00565 }
00566 else
00567 {
00568 *(slot_tag) = address_tag;
00569 *(slot_valid) = true;
00570 *(slot_dirty) = true;
00571 this->ac_storage::write_half(slot_data + offset - Data, datum);
00572 }
00573 }
00574 this->update(set, element);
00575 }
00576
00582 ac_cache::ac_cache( char *n, unsigned bs, unsigned nb, unsigned ss, unsigned st, unsigned char wp) :
00583 ac_storage(n, bs*nb*(AC_WORDSIZE/8)),
00584 block_size(bs),
00585 num_blocks (nb),
00586 set_size (ss),
00587 num_sets (nb/ss),
00588 strategy (st),
00589 write_policy (wp)
00590 {
00591 request_block_event = false;
00592 request_write_block_event = false;
00593 request_write_event = false;
00594
00595
00596
00597 next_level = NULL;
00598 previous_level = NULL;
00599 tag = new unsigned[this->num_blocks];
00600 valid = new bool[this->num_blocks];
00601 dirty = new bool[this->num_blocks];
00602 chosen = new unsigned[this->num_sets];
00603
00604 tracker = new unsigned[this->num_blocks];
00605
00606
00607
00608 *valid = false;
00609
00610 *dirty = false;
00611
00612 datum_ref = new char[4];
00613 #ifdef AC_TRACE
00614 ac_cache::trace.open(n, ofstream::out);
00615
00616 #endif
00617 }
00618
00619
00620
00621
00623 ac_cache::~ac_cache(){
00624
00625
00626
00627
00628
00629
00630 delete[] tag;
00631
00632 delete[] valid;
00633
00634 delete[] dirty;
00635
00636 delete[] chosen;
00637
00638 delete[] tracker;
00639 #ifdef AC_TRACE
00640
00641 ac_cache::trace.close();
00642 #endif
00643
00644
00645 delete[] datum_ref;
00646
00647 }
00648
00649 void ac_cache::bindTo(ac_cache& lower){
00650 this->next_level = &lower;
00651
00652 }
00653
00654
00655 void ac_cache::set_codeSize( unsigned s){
00656 codeSize = s;
00657 }
00658
00659 unsigned ac_cache::get_chosen(unsigned s){
00660 unsigned maximum = 0;
00661 long double norm;
00662 switch(this->strategy)
00663 {
00664 case LRU:
00665 for (unsigned t = 0 ; t < (unsigned)this->set_size ; t = t + sizeof(unsigned))
00666 {
00667 if( *(tracker + s*this->set_size + t) > maximum )
00668 {
00669 maximum = *(tracker + s*this->set_size + t);
00670 *(chosen + s) = t;
00671 }
00672 if(*(chosen + s) > this->set_size)
00673 *(chosen + s) = 0;
00674 }
00675 break;
00676
00677 case RANDOM:
00678 srand((int)(chosen + s));
00679 norm = rand();
00680 norm = norm * (this->set_size - 1);
00681 *(chosen + s) = (unsigned)((set_size-1)*(rand()/(double)RAND_MAX));
00682 break;
00683
00684 default:
00685 *(chosen + s) += 1;
00686 if((*(chosen + s))>=set_size)
00687 *(chosen + s) = 0;
00688 }
00689 #ifdef AC_DETAIL
00690 printf("Strategia %d: escolhido o %d \n",this->strategy, *(chosen + s));
00691 #endif
00692 return *(chosen + s);
00693 }
00694
00696 void ac_cache::update(unsigned s, unsigned e)
00697 {
00698 for (unsigned t = 0 ; t < (unsigned)this->set_size ; t++)
00699 {
00700 *(tracker + s*this->set_size + t) += 1;
00701 }
00702 *(tracker + s*this->set_size + e) = 0;
00703 }
00704
00705 unsigned ac_cache::get_codeSize(){
00706 return codeSize;
00707 }
00708
00709
00710
00711
00712
00713 void ac_cache::stall(){
00714 ac_resources::ac_wait();
00715
00716 }
00717
00718
00719 void ac_cache::ready(){
00720 ac_resources::ac_release();
00721 this->replace_status = 0;
00722
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732 void ac_cache::request_block(ac_cache_if* client, unsigned address, unsigned size_bytes)
00733 {
00734
00735
00736 client_global = client;
00737 request_buffer = new char[size_bytes*(AC_WORDSIZE/8)];
00738 for (unsigned offset_word = 0; offset_word < size_bytes; offset_word+=AC_WORDSIZE/8)
00739 {
00740 *(ac_word *)(request_buffer + offset_word) = this->read(address + offset_word);
00741
00742 }
00743 request_block_event = true;
00744
00745
00746 }
00747
00748 void ac_cache::process_request() {
00749 if (request_write_block_event) {
00750 request_write_block_event = false;
00751 client_global->response_write_block();
00752 }else if (request_block_event) {
00753 request_block_event = false;
00754 client_global->response_block(request_buffer);
00755 }else if (request_write_event) {
00756 request_write_event = false;
00757 client_global->response_write();
00758 }
00759
00760
00761
00762
00763
00764 }
00765
00766 void ac_cache::request_write_byte(ac_cache_if* client, unsigned address, unsigned char datum)
00767 {
00768 client_global = client;
00769 ac_cache::write_byte(address, datum);
00770 request_write_event = true;
00771
00772
00773 }
00774
00775 void ac_cache::request_write_half(ac_cache_if* client, unsigned address, unsigned short datum)
00776 {
00777 client_global = client;
00778 ac_cache::write_half(address, datum);
00779 request_write_event = true;
00780
00781
00782 }
00783
00784 void ac_cache::request_write(ac_cache_if* client, unsigned address, ac_word datum)
00785 {
00786 client_global = client;
00787 ac_cache::write(address, datum);
00788 request_write_event = true;
00789
00790 }
00791
00792 void ac_cache::request_write_block(ac_cache_if* client, unsigned address, char* datum, unsigned size_bytes)
00793 {
00794 client_global = client;
00795 for (unsigned offset_word = 0; offset_word < size_bytes; offset_word+=AC_WORDSIZE/8)
00796 {
00797 write(address + offset_word, *(ac_word*)(datum + offset_word));
00798
00799 }
00800
00801 request_write_block_event = true;
00802
00803 }
00804
00805 void ac_cache::response_block(char* block)
00806 {
00807 *(slot_tag) = address_tag;
00808
00809 *(slot_valid) = true;
00810 *(slot_dirty) = false;
00811 for (unsigned offset_word = 0; offset_word < block_size; offset_word++)
00812 {
00813 *(ac_word *)(slot_data + offset_word*AC_WORDSIZE/8) = *(ac_word *)(block + offset_word*(AC_WORDSIZE/8));
00814
00815 }
00816 replace_status++;
00817 if(read_access_type)
00818 {
00819 this->replaceBlockRead(requested_address);
00820 }
00821 else
00822 {
00823 this->replaceBlockWrite();
00824 }
00825 delete[] block;
00826 }
00827
00828
00829 void ac_cache::response_write_byte()
00830 {
00831
00832 }
00833
00834 void ac_cache::response_write_half()
00835 {
00836
00837 }
00838
00839 void ac_cache::response_write()
00840 {
00841 this->ready();
00842 }
00843
00844 void ac_cache::response_write_block()
00845 {
00846 replace_status++;
00847 if(read_access_type)
00848 this->replaceBlockRead(requested_address);
00849 else
00850 this->replaceBlockWrite();
00851 }
00852
00853
00854
00855
00856
00857 void ac_cache::bindToNext(ac_cache_if& next)
00858 {
00859 this->next_level = &next;
00860 }
00861
00862 void ac_cache::bindToPrevious(ac_cache_if& previous)
00863 {
00864
00865 }
00866
00867
00868