2010-05-03 12 views
8

Ok questa è solo la mia seconda domanda, ed è abbastanza doozy. È per un incarico scolastico, ma nessuno (compresi gli AT) sembra essere in grado di aiutarmi. È un po 'troppo alto, ma non sono sicuro su quale altro girare.Cache Simulator in C

In sostanza l'incarico era di creare un simulatore di cache. Questa versione è una mappatura diretta ed è in realtà solo una piccola parte dell'intero progetto, ma se non riesco nemmeno a capirlo, non ho alcuna possibilità con altre associazioni. Sto postando il mio intero codice perché non voglio fare ipotesi su dove sia il problema.

Questo è il banco di prova:

e si esegue il seguente comando:
./sims 512 diretta 32 FIFO peso pinatrace.out

Si suppone di ottenere:

hits: 604037 
misses 138349 
writes: 239269 
reads: 138349 

ma ottengo:

Hits: 587148 
Misses: 155222 
Writes: 239261 
Reads: 155222 

Se qualcuno potesse almeno indicarmi la giusta direzione, sarebbe molto apprezzato. Sono rimasto bloccato su questo per circa 12 ore.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 


struct myCache 
{ 
    int valid; 
    char *tag; 
    char *block; 
}; 

/* 
sim [-h] <cache size> <associativity> <block size> <replace alg> <write policy> 
<trace file> 
*/ 

//God willing I come up with a better Hex to Bin convertion that maintains the beginning 0s... 
void hex2bin(char input[], char output[]) 
{ 
    int i; 
    int a = 0; 
    int b = 1; 
    int c = 2; 
    int d = 3; 
    int x = 4; 
    int size; 
    size = strlen(input); 

    for (i = 0; i < size; i++) 
    { 
     if (input[i] =='0') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '0'; 
     } 
     else if (input[i] =='1') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '1'; 
     }  
     else if (input[i] =='2') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '0'; 
     }  
     else if (input[i] =='3') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '1'; 
     }  
     else if (input[i] =='x') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '0'; 
     }  
     else if (input[i] =='5') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '1'; 
     }  
     else if (input[i] =='6') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '0'; 
     }  
     else if (input[i] =='7') 
     { 
      output[i*x +a] = '0'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '1'; 
     }  
     else if (input[i] =='8') 
     { 
      output[i*x +a] = '1'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '0'; 
     } 
     else if (input[i] =='9') 
     { 
      output[i*x +a] = '1'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '1'; 
     } 
     else if (input[i] =='a') 
     {  
      output[i*x +a] = '1'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '0'; 
     } 
     else if (input[i] =='b') 
     { 
      output[i*x +a] = '1'; 
      output[i*x +b] = '0'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '1'; 
     } 
     else if (input[i] =='c') 
     { 
      output[i*x +a] = '1'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '0'; 
     } 
     else if (input[i] =='d') 
     {  
      output[i*x +a] = '1'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '0'; 
      output[i*x +d] = '1'; 
     } 
     else if (input[i] =='e') 
     {  
      output[i*x +a] = '1'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '0'; 
     } 
     else if (input[i] =='f') 
     { 
      output[i*x +a] = '1'; 
      output[i*x +b] = '1'; 
      output[i*x +c] = '1'; 
      output[i*x +d] = '1'; 
     } 
    } 

    output[32] = '\0'; 
} 




int main(int argc, char* argv[]) 
{  
    FILE *tracefile; 
    char readwrite; 
    int trash; 
    int cachesize; 
    int blocksize; 
    int setnumber; 
    int blockbytes; 
    int setbits; 
    int blockbits; 
    int tagsize; 
    int m; 
    int count = 0; 
    int count2 = 0; 
    int count3 = 0; 
    int i; 
    int j; 
    int xindex; 
    int jindex; 
    int kindex; 
    int lindex;  
    int setadd; 
    int totalset; 
    int writeMiss = 0; 
    int writeHit = 0; 
    int cacheMiss = 0; 
    int cacheHit = 0; 
    int read = 0; 
    int write = 0; 
    int size; 
    int extra; 

    char bbits[100]; 
    char sbits[100]; 
    char tbits[100]; 
    char output[100]; 
    char input[100]; 
    char origtag[100]; 


    if (argc != 7) 
    { 
     if (strcmp(argv[0], "-h")) 
     { 
      printf("./sim2 <cache size> <associativity> <block size> <replace alg> <write policy> <trace file>\n"); 
      return 0; 
     } 
     else 
     { 
      fprintf(stderr, "Error: wrong number of parameters.\n"); 
      return -1; 
     } 
    } 

    tracefile = fopen(argv[6], "r"); 

    if(tracefile == NULL) 
    { 
     fprintf(stderr, "Error: File is NULL.\n"); 
     return -1; 
    } 

    //Determining size of sbits, bbits, and tag 
    cachesize = atoi(argv[1]); 
    blocksize = atoi(argv[3]); 
    setnumber = (cachesize/blocksize); 
    printf("setnumber: %d\n", setnumber); 
    setbits = (round((log(setnumber))/(log(2)))); 
    printf("sbits: %d\n", setbits); 
    blockbits = log(blocksize)/log(2); 
    printf("bbits: %d\n", blockbits); 
    tagsize = 32 - (blockbits + setbits); 
    printf("t: %d\n", tagsize); 

    struct myCache newCache[setnumber]; 

    //Allocating Space for Tag Bits, initiating tag and valid to 0s 
    for(i=0;i<setnumber;i++) 
    { 
     newCache[i].tag = (char *)malloc(sizeof(char)*(tagsize+1)); 
     for(j=0;j<tagsize;j++) 
     { 
      newCache[i].tag[j] = '0'; 
     } 
     newCache[i].valid = 0; 
    } 

    while(fgetc(tracefile)!='#') 
    {  
     setadd = 0; 
     totalset = 0; 
     //read in file 
     fseek(tracefile,-1,SEEK_CUR); 
     fscanf(tracefile, "%x: %c %s\n", &trash, &readwrite, origtag); 

     //shift input Hex 
     size = strlen(origtag); 
     extra = (10 - size); 
     for(i=0; i<extra; i++) 
      input[i] = '0'; 

     for(i=extra, j=0; i<(size-(2-extra)); j++, i++) 
      input[i]=origtag[j+2]; 

     input[8] = '\0'; 

     // Convert Hex to Binary 
     hex2bin(input, output); 

     //Resolving the Address into tbits, sbits, bbits 
     for (xindex=0, jindex=(32-blockbits); jindex<32; jindex++, xindex++) 
    { 
      bbits[xindex] = output[jindex]; 
     } 
    bbits[xindex]='\0'; 

    for (xindex=0, kindex=(32-(blockbits+setbits)); kindex<32-(blockbits); kindex++, xindex++){ 
     sbits[xindex] = output[kindex]; 
    } 
    sbits[xindex]='\0'; 

    for (xindex=0, lindex=0; lindex<(32-(blockbits+setbits)); lindex++, xindex++){ 
     tbits[xindex] = output[lindex]; 
    } 
    tbits[xindex]='\0'; 

    //Convert set bits from char array into ints 
    for(xindex = 0, kindex = (setbits -1); xindex < setbits; xindex ++, kindex--) 
     { 
      if (sbits[xindex] == '1') 
       setadd = 1; 
      if (sbits[xindex] == '0') 
       setadd = 0; 
      setadd = setadd * pow(2, kindex); 
      totalset += setadd; 
     } 

     //Calculating Hits and Misses 
     if (newCache[totalset].valid == 0) 
     { 
      newCache[totalset].valid = 1; 
      strcpy(newCache[totalset].tag, tbits); 
     } 

     else if (newCache[totalset].valid == 1) 
     { 
      if(strcmp(newCache[totalset].tag, tbits) == 0) 
      { 
       if (readwrite == 'W') 
       { 
        cacheHit++;   
        write++; 
       } 
       if (readwrite == 'R') 
        cacheHit++;  
      } 
      else 
      { 
       if (readwrite == 'R') 
       { 
        cacheMiss++; 
        read++; 
       } 
       if (readwrite == 'W') 
       { 
        cacheMiss++; 
        read++; 
        write++; 
       } 
       strcpy(newCache[totalset].tag, tbits); 
      } 
     }   
    } 
    printf("Hits: %d\n", cacheHit); 
    printf("Misses: %d\n", cacheMiss); 
    printf("Writes: %d\n", write); 
    printf("Reads: %d\n", read); 
} 
+0

PS: Ho provato così difficile fare questo leggibile secondo la formattazione qui. Scusa se continua a sanguinare gli occhi! – DuffDuff

+2

Non dovremmo 'else if (input [i] == 'x')' in 'hex2bin' essere' input [i] == '4''? –

+2

Solo perché il tuo TA non può capirlo non significa che la risposta è totalmente al di là delle tue capacità. Potrebbe conoscere meglio l'argomento, ma ** tu ** conosci il tuo codice meglio di lui, e ** tu ** devi imparare a capire cosa c'è che non va da solo. –

risposta

4

Hai due problemi. In primo luogo, Scott Wales ha ragione sulla tua funzione hex2bin() - hai uno 'x' dove intendi '4'.

In secondo luogo, non si conta correttamente un errore di cache quando si colpisce uno slot di cache non valido. Si può semplicemente gestire "non valido" con esattamente lo stesso percorso di codice utilizzato per una miss:

if ((newCache[totalset].valid == 1) && (strcmp(newCache[totalset].tag, tbits) == 0)) 
    { 
     /* Hit */ 
     if (readwrite == 'W') 
     { 
      cacheHit++; 
      write++; 
     } 
     if (readwrite == 'R') 
      cacheHit++; 
    } 
    else 
    { 
     /* Miss (cache entry invalid, or wrong tag) */ 
     if (readwrite == 'R') 
     { 
      cacheMiss++; 
      read++; 
     } 
     if (readwrite == 'W') 
     { 
      cacheMiss++; 
      read++; 
      write++; 
     } 
     newCache[totalset].valid = 1; 
     strcpy(newCache[totalset].tag, tbits); 
    } 
+0

Wow, grazie. Inizialmente avevo aggiunto le mie miss in questo modo, ma poiché erano troppo alte per iniziare, le ho ridotte rimuovendo quel codice. Non riesco a credere che questo fosse (quasi tutto) a causa di quella stupida "x". /vergognoso. – DuffDuff