CSAPP CacheLab PartA

5. CacheLab

Part A

code:

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <inttypes.h>

#include "cachelab.h"


void usage()
{
    puts("Usage: ./csim [-hv] -s <num> -E <num> -b <num> -t <file>\n"
         "Options:\n"
         "  -h         Print this help message.\n"
         "  -v         Optional verbose flag.\n"
         "  -s <num>   Number of set index bits.\n"
         "  -E <num>   Number of lines per set.\n"
         "  -b <num>   Number of block offset bits.\n"
         "  -t <file>  Trace file.\n"
         "\n"
         "Examples:\n"
         "  linux>  ./csim -s 4 -E 1 -b 4 -t traces/yi.trace\n"
         "  linux>  ./csim -v -s 8 -E 2 -b 4 -t traces/yi.trace");
}

#define STRING_LEN 256

int verbose = 0;            // verbose flag
int s = 0;                  // number of set index bits
int S = 0;                  // number of sets
int E = 0;                  // number of lines per set
int b = 0;                  // number of block offset bits
char traceFile[STRING_LEN] = {0};  // trace file name
char traceLine[STRING_LEN] = {0};  // line of trace file

int hits = 0;
int misses = 0;
int evictions = 0;
unsigned int cache_counter = 0;
unsigned int cnt = 0;


typedef struct {
    unsigned int valid;
    unsigned long long tag;
    uint8_t* data;
    unsigned int last_cc;       // last cache counter
} cacheLine_t;

typedef struct {
    cacheLine_t *lines;
} cacheSet_t;

typedef struct {
    cacheSet_t *sets;
} cache_t;


void verbose_log(char *str)
{
    if (verbose)
    {
        printf("%s", str);
    }
}


void handle_operation(cache_t cache, char op, unsigned int tag, unsigned int set_index, unsigned int offset)
{
    // initial
    int i;
    int flag;
    cacheLine_t* line;

    // get target set
    cacheSet_t set = cache.sets[set_index];

    // check tag in cache && valid
    flag = 0;
    for (i = 0; i < E; i++)
    {
        if (set.lines[i].valid && set.lines[i].tag == tag)
        {
            line = &set.lines[i];
            flag = 1;
            break;
        }
    }

    if (flag)
    {
        // hit
        hits++;
        verbose_log("hit ");
        line->last_cc = cache_counter++;
        return;
    }
    else
    {
        // miss
        misses++;
        verbose_log("miss ");

        // check is there any invalid line
        for (i = 0; i < E; i++)
        {
            if (0 == set.lines[i].valid)
            {
                line = &set.lines[i];
                line->valid = 1;                 // load line from memory
                line->tag = tag;
                line->last_cc = cache_counter++; // set last cache counter

                return;
            }
        }

        // no invalid line, evict a line whose last cache counter is the smallest
        line = &set.lines[0];
        for (i = 1; i < E; i++)
        {
            if (set.lines[i].valid)
            {
                line = (set.lines[i].last_cc < line->last_cc) ? &set.lines[i] : line;
                // break;
            }
        }

        evictions++;
        verbose_log("eviction ");
        line->tag = tag;
        line->last_cc = cache_counter++;

        return;
    }
}


void load_data(cache_t cache, unsigned int tag, unsigned int set_index, unsigned int offset)
{
    char op = 'L';
    handle_operation(cache, op, tag, set_index, offset);
#ifdef DEBUG
    cacheLine_t line;
    line = cache.sets[3].lines[0];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[1];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[2];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[3];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
#endif
}
void store_data(cache_t cache, unsigned int tag, unsigned int set_index, unsigned int offset)
{
    char op = 'S';
    handle_operation(cache, op, tag, set_index, offset);
#ifdef DEBUG
    cacheLine_t line;
    line = cache.sets[3].lines[0];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[1];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[2];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
    line = cache.sets[3].lines[3];
    printf("cc: %u, op: %c, valid: %u, tag: %llu, last_cc: %u\n",
           cache_counter, op, line.valid, line.tag, line.last_cc);
#endif
}


void simulate_cache()
{
    int i, j;

    // initial cache
    cache_counter = 0;
    cache_t cache;
    cache.sets = calloc(S, sizeof(cacheSet_t));
    for (i = 0; i < S; i++)
    {
        cache.sets[i].lines = calloc(E, sizeof(cacheLine_t));
        for (j = 0; j < E; j++)
        {
            cache.sets[i].lines[j].valid = 0;
            cache.sets[i].lines[j].data = calloc(1 << b, sizeof(uint8_t));
        }
    }

    // start simulation
    // read trace file
    FILE *fp = fopen(traceFile, "r");

    while (fgets(traceLine, STRING_LEN, fp) != NULL)
    {
        if ('I' == traceLine[0])
        {
            continue;
        }
        char op;
        unsigned long long addr;
        unsigned int size;
        sscanf(traceLine, " %c %llx,%x", &op, &addr, &size);
        if (verbose)
        {
            printf("%c %llx,%x ", op, addr, size);
        }
        if (0x7ff000370 == addr)
        {
            cnt++;
        }

        // handle address
        unsigned int tag;
        unsigned int set_index;
        unsigned int offset;

        offset = addr & ((1 << b) - 1);
        addr >>= b;
        set_index = addr & (S - 1);
        addr >>= s;
        tag = addr;

        // handle operation
        switch (op) {
            case 'L':
            {
                load_data(cache, tag, set_index, offset);
                break;
            }
            case 'S':
            {
                store_data(cache, tag, set_index, offset);
                break;
            }
            case 'M':
            {
                load_data(cache, tag, set_index, offset);
                store_data(cache, tag, set_index, offset);
                break;
            }
            default:
            {
               printf("error operation\n");
            }
        }
        verbose_log("\n");
    }

    // free cache
    for (i = 0; i < S; i++)
    {
        for (j = 0; j < E; j++)
        {
            free(cache.sets[i].lines[j].data);
        }
        free(cache.sets[i].lines);
    }
    free(cache.sets);
}


int main(int argc, char* argv[])
{
    int opt;

    while ((opt = getopt(argc, argv, "hvs:E:b:t:")) != -1)
    {
        switch (opt)
        {
            case 'h':
            {
                usage();
                break;
            }
            case 'v':
            {
                verbose = 1;
#ifdef DEBUG
                verbose = 0;
#endif
                break;
            }
            case 's':
            {
                s = (int) strtol(optarg, NULL, 10);
                S = 1 << s;
                break;
            }
            case 'E':
            {
                E = (int) strtol(optarg, NULL, 10);
                break;
            }
            case 'b':
            {
                b = (int) strtol(optarg, NULL, 10);
                break;
            }
            case 't':
            {
                sscanf(optarg, "%s", traceFile);
                break;
            }
            default:
            {
                usage();
                break;
            }
        }
    }

    if (s == 0 || E == 0 || b == 0)
    {
        puts("Missing required parameters!");
        return 0;
    }

    simulate_cache();

    printSummary(hits, misses, evictions);
    return 0;
}

Note:

在编写代码时,遇到了一些问题,这里记录下来

  • Modify operation指的是一次data load+一次data store,最开始是在handle_operation中用if判断如果为Modify operation则进行额外的操作,这样写的代码可读性很差,后来将操作封装成了load_data和store_data两个函数,在simulate_cache中,通过operation调用对应的接口,Modify则是调用一次load_data后再调用一次store_data

  • evict某个块时,忘了给新块设置last_cc,导致每次evict的都是该组数据块中第0个块,是通过在这俩个operation接口处理完操作后,打印某个组的所有块的last_cc和tag等属性才发现的这个bug(感觉还是测试的数据集太弱了)

  • evict某个块时,我的代码写成了

    // no invalid line, evict a line whose last cache counter is the smallest
            line = &set.lines[0];
            for (i = 1; i < E; i++)
            {
                if (set.lines[i].valid)
                {
                    line = (set.lines[i].last_cc < line->last_cc) ? &set.lines[i] : line;
                    break;
                }
            }
    

    明显的逻辑错误,由break语句引起的,注释掉break;就可以了

这三个问题下来,代码结构其实是有点乱了的,不过也是懒得再重构了(…

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值