Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

cache.cpp

By: Ronin420 on Sep 25th, 2011  |  syntax: C++  |  size: 23.17 KB  |  views: 62  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include <cstdio>
  2. #include <cstdlib>
  3. #include <iostream>
  4. #include <cmath>
  5. #include <fstream>
  6. #include <iomanip>
  7. #include "cache.h"
  8.  
  9. using namespace std;
  10.  
  11.  
  12. // Defined in main.cpp
  13. extern ofstream fdbg;
  14. extern ofstream fdbg_ext;
  15.  
  16. #ifndef DEBUG
  17.     #define DEBUG 0
  18. #endif
  19.  
  20.  
  21. // Function to return the bits, from msb to lsb, of a number
  22. inline unsigned long getbits(unsigned long n,unsigned short msb=0,unsigned short lsb=0){return (n >> lsb) & ~(~0<<(msb-lsb+1));}
  23.  
  24.  
  25.  
  26.  
  27.  
  28. // Functions associated with main caches
  29. mem::mem(string name_in,class mem *next_in=NULL,unsigned short blocksize_in=0,unsigned long size_in=0,unsigned short assoc_in=1,unsigned short policy_rep_in=0,unsigned short policy_wr_in=0,unsigned long vc_blocks_in=0){
  30.  
  31.     read_access=0;
  32.     read_misses=0;
  33.     write_access=0;
  34.     write_misses=0;
  35.     writebacks=0;
  36.  
  37.     if(next_in==NULL){
  38.         sets=0;
  39.         meminfo(this,0);
  40.  
  41.     }else{
  42.        
  43.         size=size_in;
  44.         blocksize=blocksize_in;
  45.  
  46.         if(size==0 || blocksize==0){
  47.             cout<<"ERROR : Size and Blocksize should be non-zero"<<endl;
  48.             exit(1);
  49.         }
  50.  
  51.         assoc=assoc_in;
  52.         sets=size/(blocksize*assoc);
  53.  
  54.         next=next_in;
  55.         name=name_in;
  56.         vc_blocks=vc_blocks_in;
  57.         policy_rep=policy_rep_in;
  58.         policy_wr=policy_wr_in;
  59.  
  60.         if(name=="L1"){
  61.             hit_time=0.25+2.5*(float(size)/512/1024)+0.025*(float(blocksize)/16)+0.025*float(assoc);
  62.         }else if(name=="L2"){
  63.             hit_time=2.5+2.5*(float(size)/512/1024)+0.025*(float(blocksize)/16)+0.025*float(assoc);
  64.         }
  65.         miss_penalty=20+0.5*(float(blocksize)/16);
  66.  
  67.         arr_tag  = new unsigned long*[sets];
  68.         arr_tag_valid = new bool*[sets];
  69.         arr_block_dirty = new bool*[sets];
  70.  
  71.         if(assoc>1){
  72.             arr_block_count = new unsigned long*[sets];
  73.         }else{
  74.             arr_block_count = NULL;
  75.         }
  76.  
  77.         for(unsigned long i=0;i<sets;i++){
  78.             arr_tag[i]  = new unsigned long[assoc]();
  79.             arr_tag_valid[i] = new bool[assoc]();
  80.            
  81.             arr_block_dirty[i] = new bool[assoc]();
  82.  
  83.             if(assoc>1){
  84.                 arr_block_count[i] = new unsigned long[assoc]();
  85.             }
  86.         }
  87.        
  88.         if(vc_blocks==0){
  89.             vc=NULL;
  90.         }else{
  91.             vcache l1_vc(blocksize,vc_blocks);
  92.             vc=&l1_vc;
  93.         }
  94.  
  95.         meminfo(this,0);
  96.     }
  97. }
  98.  
  99.  
  100. bool mem::read(unsigned long addr){
  101.    
  102.     // Increment read counter and initialisation
  103.     read_access++;
  104.  
  105.     if(next==NULL){
  106.         // Check if this is Main Memory
  107.         return 1;
  108.     }
  109.  
  110.     unsigned long tag=addr;
  111.  
  112.     unsigned short offsetbits=lg(blocksize);
  113.     tag>>=offsetbits;
  114.  
  115.     unsigned short indexbits=lg(sets);
  116.     unsigned long index=getbits(tag,indexbits-1);
  117.     tag>>=indexbits;
  118.  
  119.     if(name=="L1"){
  120.         if(DEBUG >= 1){
  121.             fdbg<<"L1 Read : "<<hex<<addr<<" (tag "<<tag<<", index "<<dec<<index<<")"<<endl;
  122.         }
  123.         if(DEBUG >= 2){
  124.             fdbg_ext<<"Read 0x"<<hex<<addr<<"   Tag=0x"<<tag<<"  Index="<<dec<<index<<endl;
  125.         }
  126.     }
  127.  
  128.     bool flag_chk_next = ((vc == NULL) ? 1 : 0);
  129.         // 0 : Check VC before checking next level    1 : Check next level directly w/o checking VC
  130.    
  131.         // Print out the contents of the set (for debug)
  132.         if(DEBUG >= 2){
  133.             fdbg_ext<<"  "<<dec<<index<<"      : ";
  134.             for(unsigned short i=0; i<assoc; i++){
  135.                 if(arr_block_dirty[index][i]){
  136.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<" D\t";
  137.                 }else{
  138.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<"  \t";
  139.                 }
  140.             }
  141.             fdbg_ext<<endl;
  142.         }
  143.  
  144.     // Search the set for required addr
  145.     for(unsigned short i=0; i<assoc; i++){
  146.         if(arr_tag_valid[index][i]==0){
  147.             flag_chk_next=1;
  148.                 // Valid bit not set ==> Set not full ==> No need to check VC, check next level directly
  149.             break;
  150.  
  151.         }else if(arr_tag[index][i]==tag){
  152.            
  153.             if(DEBUG >= 1){
  154.                 fdbg<<name<<" hit"<<endl;
  155.             }
  156.             if(DEBUG >= 2){
  157.                 fdbg_ext<<"  "<<name<<" Hit  : "<<dec<<i<<endl;
  158.             }
  159.  
  160.             block_count_update(index,i);
  161.             return 1;
  162.         }
  163.     }
  164.  
  165.     // In case of a miss:
  166.  
  167.         // Increment read_miss count
  168.         read_misses++;
  169.         if(DEBUG >= 1){
  170.             fdbg<<name<<" miss"<<endl;
  171.         }
  172.         if(DEBUG >= 2){
  173.             fdbg_ext<<"  "<<name<<" Miss"<<endl;
  174.         }
  175.  
  176.         // Identify Victim Block
  177.         unsigned short vblock = block_replace(index);
  178.         unsigned long  vaddr  = arr_tag[index][vblock]<<(indexbits+offsetbits)+(index<<indexbits)+vblock;
  179.             // vaddr: Full address of the victim block
  180.  
  181.         // Find block in VC and swap if present
  182.         if(!flag_chk_next){
  183.             // Flag = 0 ==> Set is full ==> Check if block is present in VC and swap if it does
  184.            
  185.             int vc_block_rep = vc->find(addr);
  186.                 // vc_block_rep: location of block if present in VC, -1 otherwise
  187.  
  188.             // Swapping blocks if found
  189.             if(vc_block_rep != -1){
  190.                 unsigned long combo_rep = vc->swap(vaddr,arr_block_dirty[index][vblock],vc_block_rep);
  191.                 arr_block_dirty[index][vblock] = getbits(combo_rep);
  192.                 arr_tag[index][vblock] = combo_rep >> (indexbits + offsetbits + 1);
  193.  
  194.             }else{
  195.                 flag_chk_next = 1;
  196.                     // Data not found in VC ==> Search next level
  197.             }
  198.         }
  199.  
  200.         // Find block in next level and fetch if Set not full / Reqd block not found in VC
  201.         if(flag_chk_next){
  202.  
  203.             // Prepare for eviction (Swap with VC if reqd and writeback to next level if dirty)
  204.             if(arr_tag_valid[index][vblock] == 1){
  205.                 unsigned long combo_rep = vc->swap(vaddr,arr_block_dirty[index][vblock]);
  206.                 arr_block_dirty[index][vblock] = getbits(combo_rep);
  207.                 arr_tag[index][vblock] = combo_rep >> 1;
  208.          
  209.                 if(arr_block_dirty[index][vblock]==1){
  210.                     next->write(vaddr);
  211.                     writebacks++;
  212.                 }
  213.             }
  214.            
  215.             // Fetch data from next level (and reset dirty bit)
  216.             next->read(addr);
  217.             if(!policy_wr && arr_block_dirty[index][vblock]){
  218.                 fdbg<<name<<" Reset Dirty Bit"<<endl;
  219.                 arr_block_dirty[index][vblock]=0;
  220.             }
  221.  
  222.         }
  223.        
  224.         // Update Tag, status bits and counters
  225.         arr_tag[index][vblock]=tag;
  226.         arr_tag_valid[index][vblock]=1;
  227.         block_count_update(index,vblock);
  228.  
  229.     return 1;
  230. }
  231.  
  232.  
  233.  
  234. void mem::write(unsigned long addr){
  235.    
  236.     // Increment write counter and initialisation
  237.     write_access++;
  238.  
  239.     if(next==NULL){
  240.         // Check if this is Main Memory
  241.         return;
  242.     }
  243.  
  244.     unsigned long tag=addr;
  245.  
  246.     unsigned short offsetbits=lg(blocksize);
  247.     tag>>=offsetbits;
  248.  
  249.     unsigned short indexbits=lg(sets);
  250.     unsigned long index=getbits(tag,indexbits-1);
  251.     tag>>=indexbits;
  252.  
  253.     if(name=="L1"){
  254.         fdbg<<"L1 Write : "<<hex<<addr<<" (tag "<<tag<<", index "<<dec<<index<<")"<<endl;
  255.         if(DEBUG >= 2){
  256.             fdbg_ext<<"Writ 0x"<<hex<<addr<<"   Tag=0x"<<tag<<"  Index="<<dec<<index<<endl;
  257.         }
  258.     }
  259.  
  260.     bool flag_chk_next = ((vc == NULL) ? 1 : 0);
  261.         // 0 : Check VC before checking next level    1 : Check next level directly w/o checking VC
  262.      
  263.         // Print the contents of the set before the write (for debug)
  264.         if(DEBUG >= 2){
  265.             fdbg_ext<<"  "<<dec<<index<<"      : ";
  266.             for(unsigned short i=0; i<assoc; i++){
  267.                 if(!policy_wr && arr_block_dirty[index][i]){
  268.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<" D\t";
  269.                 }else{
  270.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<"  \t";
  271.                 }
  272.             }
  273.             fdbg_ext<<endl;
  274.         }
  275.  
  276.     // Search the set for the reqd block
  277.     for(unsigned short i=0; i<assoc; i++){
  278.  
  279.         if(arr_tag_valid[index][i]==0){
  280.             flag_chk_next = 1;
  281.                 // Valid bit not set ==> Set not full ==> No need to check VC, check next directly
  282.             break;
  283.  
  284.         }else if(arr_tag[index][i]==tag){
  285.  
  286.             if(DEBUG >= 1){
  287.                 fdbg<<name<<" hit"<<endl;
  288.             }
  289.             if(DEBUG >= 2){
  290.                 fdbg_ext<<"  "<<name<<" Hit  : "<<dec<<i<<endl;
  291.             }
  292.  
  293.             block_count_update(index,i);
  294.  
  295.             if(policy_wr){
  296.                 // WTNA
  297.                 next->write(addr);
  298.             }else{
  299.                 // WBWA
  300.                 if(DEBUG >= 1){
  301.                     fdbg<<name<<" Set Dirty Bit"<<endl;
  302.                 }
  303.                 arr_block_dirty[index][i]=1;
  304.             }
  305.  
  306.             // Print the contents of the set after the write (for debug)
  307.             if(DEBUG >= 2){
  308.                 fdbg_ext<<"          : ";
  309.                 for(unsigned short i=0; i<assoc; i++){
  310.                     if(!policy_wr && arr_block_dirty[index][i]){
  311.                         fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<" D\t";
  312.                     }else{
  313.                         fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<"  \t";
  314.                     }
  315.                 }
  316.                 fdbg_ext<<endl;
  317.             }
  318.  
  319.             return;
  320.         }
  321.     }
  322.    
  323.     // In case of a miss:
  324.  
  325.         // Increment write_miss count
  326.         fdbg<<name<<" miss"<<endl;
  327.         fdbg_ext<<"  "<<name<<" Miss"<<endl;
  328.         write_misses++;
  329.  
  330.         // Identify Victim Block
  331.         unsigned short vblock = block_replace(index);
  332.         unsigned long  vaddr  = arr_tag[index][vblock]<<(indexbits+offsetbits)+(index<<indexbits)+vblock;
  333.             // vaddr: Full address of the victim block
  334.  
  335.         // Search VC for block and swap if found
  336.         if(!flag_chk_next){
  337.             // Flag = 0 ==> Set is full ==> Check if block is present in VC and swap if it does
  338.  
  339.             int vc_block_rep = vc->find(addr);
  340.                 // vc_block_rep: location of block if present in VC, -1 otherwise
  341.  
  342.             // Swapping blocks if found
  343.             if(vc_block_rep != -1){
  344.                 vc->swap(vaddr,arr_block_dirty[index][vblock],vc_block_rep);
  345.                     // Return value is ignored as tag and dirty bits will be updated further on
  346.             }else{
  347.                 flag_chk_next = 1;
  348.                     // Data not found in VC ==> Search next level
  349.             }
  350.  
  351.             // Main cache at this point has fetched the data from VC (write is still pending) or has been set to fetch it from next level
  352.         }
  353.  
  354.         // Find block in next level if Set not full / Reqd block not found in VC. Fetch if WBWA
  355.         if(flag_chk_next){
  356.  
  357.             if(policy_wr){
  358.                 // WTNA
  359.                 next->write(addr);
  360.                 return;
  361.  
  362.             }else{
  363.                 // WBWA
  364.  
  365.                 // Prepare for eviction (Swap with VC if reqd and writeback to next level if dirty)
  366.                 if(arr_tag_valid[index][vblock] == 1){
  367.                     unsigned long combo_rep = vc->swap(vaddr,arr_block_dirty[index][vblock]);
  368.                     arr_block_dirty[index][vblock] = getbits(combo_rep);
  369.                     arr_tag[index][vblock] = combo_rep >> 1;
  370.          
  371.                     if(arr_block_dirty[index][vblock]){
  372.                         next->write(arr_tag[index][vblock]<<(indexbits+offsetbits)+(index<<indexbits)+vblock);
  373.                         writebacks++;
  374.                     }
  375.                 }
  376.  
  377.                 // Fetch required data from next level and reset dirty bit
  378.                 next->read(addr);
  379.                 if(!policy_wr && arr_block_dirty[index][vblock]){
  380.                     fdbg<<name<<" Reset Dirty Bit"<<endl;
  381.                     arr_block_dirty[index][vblock]=0;
  382.                 }
  383.             }
  384.             // Main cache at this point has fetched the data from next level but write needs to be done
  385.         }
  386.  
  387.         // Write: Update tag, status bits and counters
  388.         arr_tag[index][vblock]=tag;
  389.         arr_tag_valid[index][vblock]=1;
  390.         if(!policy_wr){
  391.             if(DEBUG >= 1){
  392.                 fdbg<<name<<" Set Dirty Bit"<<endl;
  393.             }
  394.             arr_block_dirty[index][vblock]=1;
  395.         }
  396.         block_count_update(index,vblock);
  397.  
  398.         // Print contents of the set after write (for debug)
  399.         if(DEBUG >= 2){
  400.             fdbg_ext<<"          : ";
  401.             for(unsigned short i=0; i<assoc; i++){
  402.                 if(!policy_wr && arr_block_dirty[index][i]){
  403.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<" D\t";
  404.                 }else{
  405.                     fdbg_ext<<"0x"<<hex<<arr_tag[index][i]<<"  \t";
  406.                 }
  407.             }
  408.             fdbg_ext<<endl;
  409.         }
  410.  
  411.     return;
  412. }
  413.  
  414.  
  415. void mem::block_count_update(unsigned long index,unsigned short block){
  416.    
  417.     if(assoc==1){
  418.         // Do nothing
  419.  
  420.     }else if(policy_rep){
  421.         // LFU
  422.         fdbg<<name<<" Update LFU"<<endl;
  423.         arr_block_count[index][block]++;
  424.  
  425.     }else{
  426.         // LRU : 1 is the least recently used block and 'assoc' is the most recently used
  427.         fdbg<<name<<" Update LRU"<<endl;
  428.  
  429.         for(unsigned short i=0; i<assoc; i++){
  430.             if(arr_block_count[index][i]>arr_block_count[index][block]){
  431.                 arr_block_count[index][i]--;
  432.             }
  433.         }
  434.         arr_block_count[index][block]=assoc;
  435.  
  436.         if(DEBUG >= 2){
  437.             fdbg_ext<<  "  Blocks  : ";
  438.             for(unsigned short i=0; i<assoc; i++){
  439.                 fdbg_ext<<dec<<arr_block_count[index][i]<<"   ";
  440.             }
  441.             fdbg_ext<<endl;
  442.         }
  443.  
  444.     }
  445.    
  446.     return;
  447. }
  448.  
  449.  
  450. unsigned short mem::block_replace(unsigned long index){
  451.    
  452.     unsigned short val=0;
  453.  
  454.     if(assoc==1){
  455.         return 0;
  456.  
  457.     }else if(policy_rep){
  458.         // LFU: Return invalid block if found, else return LFU block
  459.      
  460.         unsigned long min=arr_block_count[index][0];
  461.         for(unsigned short i=0; i<assoc; i++){
  462.             if(arr_tag_valid[index][i]==0){
  463.                 if(DEBUG >= 2){
  464.                     fdbg_ext<<  "  LFU     : Replacing Invalid Block "<<dec<<i<<endl;
  465.                 }
  466.                 return i;
  467.             }else if(arr_block_count[index][i]<min){
  468.                 min=arr_block_count[index][i];
  469.                 val=i;
  470.             }
  471.         }
  472.         if(DEBUG >= 2){
  473.             fdbg_ext<<  "  LFU     : Replacing Valid Block "<<dec<<val<<endl;
  474.         }
  475.         return val;
  476.  
  477.     }else{
  478.         // LRU: Return invalid block if found, else return LRU block
  479.      
  480.         if(DEBUG >= 2){
  481.             fdbg_ext<<  "  Blocks  : ";
  482.         }
  483.  
  484.         for(unsigned short i=0; i<assoc; i++){
  485.             if(arr_tag_valid[index][i]==0){
  486.                 if(DEBUG >= 2){
  487.                     fdbg_ext<<"NaN"<<endl;
  488.                 }
  489.                 return i;
  490.             }else if(arr_block_count[index][i]==1){
  491.                 val=i;
  492.             }
  493.  
  494.             if(DEBUG >= 2){
  495.                 fdbg_ext<<dec<<arr_block_count[index][i]<<"   ";
  496.             }
  497.         }
  498.  
  499.         if(DEBUG >= 2){
  500.             fdbg_ext<<endl<<  "  LRU     : Replacing Valid Block "<<dec<<val<<endl;
  501.         }
  502.  
  503.         return val;
  504.     }
  505. }
  506.  
  507.  
  508.  
  509.  
  510.  
  511. // Functions associated with victim caches
  512. vcache::vcache(unsigned short blocksize_in,unsigned assoc_in){
  513.  
  514.     assoc     = assoc_in;
  515.     blocksize = blocksize_in;
  516.  
  517.     read_access  = 0;
  518.     read_misses  = 0;
  519.     write_access = 0;
  520.     write_misses = 0;
  521.  
  522.     if(assoc==0 || blocksize==0){
  523.         cout<<"  ERROR : Associativity and Blocksize of "<<name<<"should be non-zero"<<endl;
  524.         exit(1);
  525.     }
  526.  
  527.     arr_tag = new unsigned long[assoc];
  528.     arr_tag_valid = new bool[assoc]();
  529.     arr_block_count = new unsigned[assoc]();
  530.     arr_block_dirty = new bool[assoc]();
  531. }
  532.  
  533.  
  534. int vcache::find(unsigned long addr){
  535.     // addr is the full address (at least tag << offsetbits) r/wr request which was a MISS in L1
  536.     // returns the location where the reqd addr has been found, -1 if not found
  537.  
  538.     read_access++;
  539.     unsigned short offsetbits = lg(blocksize);
  540.     unsigned long tag = addr>>offsetbits;
  541.  
  542.     for(unsigned i=0;i<assoc;i++){
  543.         if(arr_tag_valid[i]==0){
  544.             read_misses++;
  545.             return -1;
  546.         }else if(arr_tag[i]==tag){
  547.             return i;
  548.         }
  549.     }
  550.  
  551.     return -1;
  552. }
  553. unsigned vcache::find(){
  554.     // returns the victim block based on replacement policy
  555.  
  556.     unsigned val;
  557.     for(unsigned i=0;i<assoc;i++){
  558.         if(arr_tag_valid[i]==0){
  559.             return i;
  560.         }else if(arr_block_count[i]==1){
  561.             val = i;
  562.         }
  563.     }
  564.  
  565.     return val;
  566. }
  567.  
  568.  
  569. unsigned long vcache::swap(unsigned long addr,bool dirty,int vc_block_rep_in=-1){
  570.     // addr         : full address of the reqd block to be written/swapped
  571.     // dirty        : dirty bit corresponding to addr
  572.     // vc_block_rep : address of block to be swapped with addr/dirty. If not specified, will identify victim block based on replacement policy
  573.  
  574.     unsigned vc_block_rep;
  575.     if(vc_block_rep_in == -1){
  576.         vc_block_rep = find();
  577.     }else{
  578.         vc_block_rep = unsigned(vc_block_rep_in);
  579.     }
  580.  
  581.     unsigned short offsetbits = lg(blocksize);
  582.     unsigned long combo_rep = arr_tag[vc_block_rep]<<(offsetbits+1)+arr_block_dirty[vc_block_rep];
  583.  
  584.     arr_tag[vc_block_rep]=addr;
  585.     arr_tag_valid[vc_block_rep]=1;
  586.     arr_block_dirty[vc_block_rep]=dirty;
  587.  
  588.     block_count_update(vc_block_rep);
  589.  
  590.     return combo_rep;
  591. }
  592.  
  593.  
  594. void vcache::block_count_update(unsigned block){
  595.  
  596.     // LRU : 1 is the least recently used block and 'assoc' is the most recently used
  597.     if(DEBUG >= 1){
  598.         fdbg<<name<<" Update LRU"<<endl;
  599.     }
  600.  
  601.     for(unsigned i=0; i<assoc; i++){
  602.         if(arr_block_count[i]>arr_block_count[block]){
  603.             arr_block_count[i]--;
  604.         }
  605.     }
  606.     arr_block_count[block]=assoc;
  607.  
  608.     if(DEBUG >= 2){
  609.         fdbg_ext<<  "  Blocks  : ";
  610.         for(unsigned i=0; i<assoc; i++){
  611.             fdbg_ext<<dec<<arr_block_count[i]<<"   ";
  612.         }
  613.         fdbg_ext<<endl;
  614.     }
  615. }
  616.  
  617.  
  618. /*
  619.  *unsigned long vcache::fetch(unsigned long addr,bool dirty,unsigned long addr_rep=0){
  620.  *
  621.  *    if(addr_rep==0){
  622.  *        // Write
  623.  *
  624.  *    }else{
  625.  *        // Read/Swap
  626.  *
  627.  *        unsigned short offsetbits = lg(blocksize);
  628.  *        unsigned long tag = addr>>offsetbits;
  629.  *        unsigned vblock;
  630.  *        bool found=0;
  631.  *
  632.  *        for(unsigned i=0;i<assoc;i++){
  633.  *            if(arr_tag_valid[i]==0){
  634.  *                vblock=i;
  635.  *                break;
  636.  *            }else if(arr_tag[i]==tag){
  637.  *                vblock=i;
  638.  *                found=1;
  639.  *                break;
  640.  *            }
  641.  *        }
  642.  *
  643.  *        if(found==0){
  644.  *            for(unsigned i=0;i<assoc;i++){
  645.  *                if(arr_block_count[i]==1){
  646.  *                    vblock=i;
  647.  *                    break;
  648.  *                }
  649.  *            }
  650.  *        }
  651.  *
  652.  *        unsigned long combo_rep = arr_tag[vblock]<<2 + arr_block_dirty[vblock]<<1 + found;
  653.  *
  654.  *        arr_tag[vblock]=(addr_rep>>offsetbits);
  655.  *        arr_block_dirty[vblock]=dirty;
  656.  *
  657.  *        return combo_rep;
  658.  *    }
  659.  *}
  660.  */
  661.  
  662.  
  663.  
  664.  
  665.  
  666. // Memory Info
  667. float meminfo(class mem *mem,unsigned short var){
  668.  
  669.     if(var==0){
  670.         // Print Memory Configuration
  671.  
  672.         if(mem->next==NULL){
  673.             fdbg_ext<<endl<<"=== "<<mem->name<<" Parameters ========================="<<endl;
  674.             fdbg_ext<<"Main memory of infinite size"<<endl;
  675.  
  676.         }else{
  677.             fdbg_ext<<endl<<"=== "<<mem->name<<" Parameters ========================="<<endl;
  678.             fdbg_ext<<"Size           : "<<dec<<mem->size<<endl;
  679.             fdbg_ext<<"Blocksize      : "<<dec<<mem->blocksize<<endl;
  680.             fdbg_ext<<"Associativity  : "<<dec<<mem->assoc<<endl;
  681.             if(mem->policy_rep){
  682.                 fdbg_ext<<"Rep. Policy    : LFU"<<endl;
  683.             }else{
  684.                 fdbg_ext<<"Rep. Policy    : LRU"<<endl;
  685.             }
  686.             if(mem->policy_wr){
  687.                 fdbg_ext<<"Write Policy   : WTNA"<<endl;
  688.             }else{
  689.                 fdbg_ext<<"Write Policy   : WBWA"<<endl;
  690.             }
  691.             fdbg_ext<<"Next Level     : "<<mem->next->name<<endl;
  692.             fdbg_ext<<"Sets           : "<<dec<<mem->sets<<endl<<endl;
  693.  
  694.             cout<<"  ===== Simulator configuration ====="<<endl;
  695.             cout<<"  "<<mem->name<<"_BLOCKSIZE:"<<setw(23)<<setfill(' ')<<dec<<mem->blocksize<<endl;
  696.             cout<<"  "<<mem->name<<"_SIZE:"<<setw(28)<<setfill(' ')<<dec<<mem->size<<endl;
  697.             cout<<"  "<<mem->name<<"_ASSOC:"<<setw(27)<<setfill(' ')<<dec<<mem->assoc<<endl;
  698.             cout<<"  "<<mem->name<<"_REPLACEMENT_POLICY:"<<setw(14)<<setfill(' ')<<dec<<mem->policy_rep<<endl;
  699.             cout<<"  "<<mem->name<<"_WRITE_POLICY:"<<setw(20)<<setfill(' ')<<dec<<mem->policy_wr<<endl;
  700.         }
  701.  
  702.     }else if(var==1){
  703.         // Print Final Memory State
  704.  
  705.         if(mem->next==NULL){
  706.             cout<<"  g. total memory traffic:"<<setw(14)<<dec<<(mem->read_access+mem->write_access)<<endl;
  707.  
  708.         }else{
  709.             cout<<endl<<" ===== "<<mem->name<<" contents ====="<<endl;
  710.             for(unsigned long i=0; i<mem->sets; i++){
  711.                 cout<<"set"<<setfill(' ')<<setw(int(log(mem->sets))+3)<<dec<<i<<":";
  712.                 for(int j=0; j<mem->assoc; j++){
  713.                     if(mem->arr_tag_valid[i][j]){
  714.                         cout<<setw(8)<<hex<<mem->arr_tag[i][j];
  715.                     }else{
  716.                         cout<<setw(8)<<"-";
  717.                     }
  718.                     if(!mem->policy_wr and mem->arr_block_dirty[i][j]){
  719.                         cout<<" D";
  720.                     }else{
  721.                         cout<<"  ";
  722.                     }
  723.                 }
  724.                 cout<<endl;
  725.             }
  726.             cout<<endl;
  727.  
  728.             float miss_rate=float(mem->read_misses+mem->write_misses)/float(mem->read_access+mem->write_access);
  729.             mem->aat=mem->hit_time+miss_rate*mem->miss_penalty;
  730.             cout<<"  ====== Simulation results (raw) ======"<<endl;
  731.             cout<<"  a. number of "<<mem->name<<" reads:"<<setw(16)<<dec<<mem->read_access<<endl;
  732.             cout<<"  b. number of "<<mem->name<<" read misses:"<<setw(10)<<dec<<mem->read_misses<<endl;
  733.             cout<<"  c. number of "<<mem->name<<" writes:"<<setw(15)<<dec<<mem->write_access<<endl;
  734.             cout<<"  d. number of "<<mem->name<<" write misses:"<<setw(9)<<dec<<mem->write_misses<<endl;
  735.             cout<<"  e. "<<mem->name<<" miss rate:"<<setw(22)<<dec<<setiosflags(ios::fixed)<<setprecision(4)<<miss_rate<<endl;
  736.             cout<<"  f. number of writebacks from "<<mem->name<<":"<<setw(6)<<dec<<mem->writebacks<<endl;
  737.         }
  738.  
  739.     }else if(var==2){
  740.         // Return Average Access Time
  741.         return mem->aat;
  742.     }
  743.  
  744.     return 0;
  745. }
  746.  
  747.  
  748.  
  749.  
  750.  
  751. // Function to calculate log to the base 2
  752. unsigned lg(unsigned n){
  753.     float f=(log(n)/log(2));
  754.     return unsigned(f);
  755. }