• Cache模拟器的设计与实现


    csim.c

      实验一文件,根据存放程序对数据的访问记录的输入文件内容,模拟cache,获得模拟结果。变量与函数解析如下:

    • 变量解析
      • verbosity:是否输出每一行记录的命中、缺失、替换情况,一般用于bug测试
      • s:组索引组号位宽
      • b:cache每一行存放的数据位宽,即块内偏移位宽
      • E:关联度,即每组的行数,每组内是全相联
      • trace_file:数据访问追踪记录文件路径
      • S:组索引组数,由位宽计算得到
      • cache:模拟cache的一个二维数组,根据组号以及组内行号确定一行cache
      • set_index_mask:用于获得组号的一个mask
    • 函数解析
      • initCache:根据S,E创建cache数据,并初始化set_index_mask
      • freeCache:回收cache模拟数组空间
      • accessData:根据传入地址,模拟访问一次数据,更新模拟结果
      • replayTrace:根据trace文件模拟整个数据访问,有的记录需要两次访问数据
      • printUsage:打印帮助信息
      • main:处理传入的参数,将参数传入函数,依次调用initCache、replayCache、freeCache、printSummary模拟Cache


    csim.c编程要求: .模拟器必须在输入参数s、E、b设置为任意值时均能正确工作——即:


    /*
     * csim.c - A cache simulator that can replay traces from Valgrind
     *     and output statistics such as number of hits, misses, and
     *     evictions.  The replacement policy is LRU.
     *
     * Implementation and assumptions:
     *  1. Each load/store can cause at most one cache miss. (I examined the trace,
     *  the largest request I saw was for 8 bytes).
     *  2. Instruction loads (I) are ignored, since we are interested in evaluating
     *  trans.c in terms of its data cache performance.
     *  3. data modify (M) is treated as a load followed by a store to the same
     *  address. Hence, an M operation can result in two cache hits, or a miss and a
     *  hit plus an possible eviction.
     *
     * The function printSummary() is given to print output.
     * Please use this function to print the number of hits, misses and evictions.
     * This is crucial for the driver to evaluate your work.
     */
    #include <getopt.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <assert.h>
    #include <math.h>
    #include <limits.h>
    #include <string.h>
    #include <errno.h>
    #include "cachelab.h"
    
    //#define DEBUG_ON
    #define ADDRESS_LENGTH 64
    
    /* Type: Memory address */
    typedef unsigned long long int mem_addr_t;
    
    /* Type: Cache line
       LRU is a counter used to implement LRU replacement policy  */
    typedef struct cache_line {
        char valid;
        mem_addr_t tag;
        unsigned long long int lru;
    } cache_line_t;
    
    typedef cache_line_t* cache_set_t;
    typedef cache_set_t* cache_t;
    
    /* Globals set by command line args */
    int verbosity = 0; /* print trace if set */
    int s = 0; /* set index bits */
    int b = 0; /* block offset bits */
    int E = 0; /* associativity */
    char* trace_file = NULL;
    
    /* Derived from command line args */
    int S; /* number of sets */
    int B; /* block size (bytes) */
    
    /* Counters used to record cache statistics */
    int miss_count = 0;
    int hit_count = 0;
    int eviction_count = 0;
    unsigned long long int lru_counter = 1;
    
    /* The cache we are simulating */
    cache_t cache;
    mem_addr_t set_index_mask;
    
    /*
     * initCache - Allocate memory, write 0's for valid and tag and LRU
     * also computes the set_index_mask
     */
    void initCache()
    {
        int i,j;
        cache = (cache_set_t*) malloc(sizeof(cache_set_t) * S);
        for (i=0; i<S; i++){
            cache[i]=(cache_line_t*) malloc(sizeof(cache_line_t) * E);
            for (j=0; j<E; j++){
                cache[i][j].valid = 0;
                cache[i][j].tag = 0;
                cache[i][j].lru = 0;
            }
        }
    
        /* Computes set index mask */
        set_index_mask = (mem_addr_t) (pow(2, s) - 1);
    }
    
    
    /*
     * freeCache - free allocated memory
     */
    void freeCache()
    {
        for (int i=0;i<S;i++)
            free(cache[i]);
    
        free(cache);
    }
    
    
    /*
     * accessData - Access data at memory address addr.
     *   If it is already in cache, increast hit_count
     *   If it is not in cache, bring it in cache, increase miss count.
     *   Also increase eviction_count if a line is evicted.
     */
    void accessData(mem_addr_t addr)
    {
        int i;
        char hit_flag = 0;
        unsigned long long int eviction_lru = ULONG_MAX;
        unsigned int eviction_line = 0;
        mem_addr_t set_index = (addr >> b) & set_index_mask;
        mem_addr_t tag = addr >> (s+b);
    
        cache_set_t cache_set = cache[set_index];
    
        for (i=0;i<E;i++)
        {
            if (cache_set[i].valid)
            {
                if (cache_set[i].tag == tag)
                {
                    ++hit_count;
                    cache_set[i].lru = ULONG_MAX;
                    hit_flag = 1;
                    if (verbosity)
                        printf(" hit");
                    continue;
                }
                if (cache_set[i].lru<eviction_lru)
                {
                    eviction_line = i;
                    eviction_lru = cache_set[i].lru;
                }
                --cache_set[i].lru;
            }
            else
            {
                if (cache_set[i].lru<eviction_lru)
                {
                    eviction_line = i;
                    eviction_lru = 0;
                }
            }
        }
        if (!hit_flag)
        {
            if (verbosity)
            {
                printf(" miss");
                if (cache_set[eviction_line].tag)S
                    printf(" eviction");
            }
    
            ++miss_count;
            eviction_count += cache_set[eviction_line].valid;
            cache_set[eviction_line].valid = 1;
            cache_set[eviction_line].tag = tag;
            cache_set[eviction_line].lru = ULONG_MAX;
        }
    }
    
    
    /*
     * replayTrace - replays the given trace file against the cache
     */
    void replayTrace(char* trace_fn)
    {
        char buf[1000];
        mem_addr_t addr=0;
        unsigned int len=0;
        FILE* trace_fp = fopen(trace_fn, "r");
        while (fscanf(trace_fp,"%[^
    ]%*c",buf)!=EOF)
        {
    
            char op;
            if (buf[0]==' ')
                sscanf(buf," %c%llx,%d",&op,&addr,&len);
            else
    
                sscanf(buf,"%c%llx,%d",&op,&addr,&len);
    
            if (verbosity)
                printf("%s",buf);
    
            switch (op) {
                case 'I':
                    break;
                case 'L':
                    accessData(addr);
                    break;
                case 'S':
                    accessData(addr);
                    break;
                case 'M':
                    accessData(addr);
                    accessData(addr);
                    break;
                default:
                    break;
            }
    
            if (verbosity)
                printf("
    ");
        }
    
        fclose(trace_fp);
    }
    
    /*
     * printUsage - Print usage info
     */
    void printUsage(char* argv[])
    {
        printf("Usage: %s [-hv] -s <num> -E <num> -b <num> -t <file>
    ", argv[0]);
        printf("Options:
    ");
        printf("  -h         Print this help message.
    ");
        printf("  -v         Optional verbose flag.
    ");
        printf("  -s <num>   Number of set index bits.
    ");
        printf("  -E <num>   Number of lines per set.
    ");
        printf("  -b <num>   Number of block offset bits.
    ");
        printf("  -t <file>  Trace file.
    ");
        printf("
    Examples:
    ");
        printf("  linux>  %s -s 4 -E 1 -b 4 -t traces/yi.trace
    ", argv[0]);
        printf("  linux>  %s -v -s 8 -E 2 -b 4 -t traces/yi.trace
    ", argv[0]);
        exit(0);
    }
    
    /*
     * main - Main routine
     */
    int main(int argc, char* argv[])
    {
        char c;
    
        while( (c=getopt(argc,argv,"s:E:b:t:vh")) != -1){
            switch(c){
            case 's':
                s = atoi(optarg);
                break;
            case 'E':
                E = atoi(optarg);
                break;
            case 'b':
                b = atoi(optarg);
                break;
            case 't':
                trace_file = optarg;
                break;
            case 'v':
                verbosity = 1;
                break;
            case 'h':
                printUsage(argv);
                exit(0);
            default:
                printUsage(argv);
                exit(1);
            }
        }
    
        /* Make sure that all required command line args were specified */
        if (s == 0 || E == 0 || b == 0 || trace_file == NULL) {
            printf("%s: Missing required command line argument
    ", argv[0]);
            printUsage(argv);
            exit(1);
        }
    
        /* Compute S, E and B from command line args */
        S = (unsigned int) pow(2, s);
        B = (unsigned int) pow(2, b);
    
        /* Initialize cache */
        initCache();
    
    #ifdef DEBUG_ON
        printf("DEBUG: S:%u E:%u B:%u trace:%s
    ", S, E, B, trace_file);
        printf("DEBUG: set_index_mask: %llu
    ", set_index_mask);
    #endif
    
        replayTrace(trace_file);
    
        /* Free allocated memory */
        freeCache();
    
        /* Output the hit and miss statistics for the autograder */
        printSummary(hit_count, miss_count, eviction_count);
    
    
        return 0;
    }
  • 相关阅读:
    2955 ACM 杭电 抢银行 01背包 乘法
    杭店 ACM 1864 最大报销额 01背包
    【ACM】 1231 最大连续子序列
    如何保证消息队列的幂等性
    Kafka如何保证消息的高可用
    消息队列的优点和缺点
    架构学习和经验积累的方法
    如何撰写总体设计与详细设计文档
    如何做合格的面试官
    如何设计好的接口
  • 原文地址:https://www.cnblogs.com/dgwblog/p/12938825.html
Copyright © 2020-2023  润新知