C语言中的缓存模拟器

9

好的,这是我第二个问题,而且它非常棘手。这是一个学校作业,但是没有人(包括助教)似乎能够帮助我。这是一个有点高难度的任务,但我不确定还能向哪里求助。

本质上,这个任务是制作一个缓存模拟器。这个版本是直接映射,实际上只是整个项目的一小部分,但如果我连这个都做不好,我在其他关联性方面就没有机会了。我发布我的整个代码,因为我不想对问题的位置做任何假设。

这是测试用例:http://www.mediafire.com/?ty5dnihydnw

然后你运行以下命令:
./sims 512 direct 32 fifo wt pinatrace.out

你应该得到:

hits: 604037
misses 138349
writes: 239269
reads: 138349

但我得到的是:
Hits: 587148
Misses: 155222
Writes: 239261
Reads: 155222

如果有人能够至少指点我正确的方向,那将不胜感激。我已经困在这个问题上大约12个小时了。

#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);
}

PS:我尽力使这个格式符合阅读要求。如果还是让你眼花,请见谅! - DuffDuff
2
hex2bin 中的 else if (input[i] =='x') 应该改为 input[i] =='4' 吗? - Scott Wales
3
即使你的助教无法解决问题,也并不意味着答案完全超出了你的能力范围。他可能比你更熟悉这个主题,但是你比他更了解自己的代码,并且需要学会自己找出问题所在。 - Ken Bloom
这绝对是迄今为止在SO上出现的最好的作业问题。 - Tim Post
@Tim Post 哈哈,我不确定自己应该感到高兴还是羞愧。 - DuffDuff
显示剩余2条评论
1个回答

5

您有两个问题。首先,Scott Wales对于您的hex2bin()函数是正确的 - 您在想要'4'的地方有一个'x'

其次,当您命中无效的缓存槽时,您没有正确地计算缓存未命中。您可以使用与未命中相同的代码路径来简单地处理“无效”:

    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);
    }

哇,谢谢。我最初就是这样添加我的漏洞的,但由于它们一开始就太高了,所以我通过删除那段代码来减少它们。我简直不敢相信这几乎全部都是因为那个愚蠢的“x”。/感到惭愧。 - DuffDuff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接