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,"%[^\n]%*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("\n");
    }

    fclose(trace_fp);
}

/*
 * printUsage - Print usage info
 */
void printUsage(char* argv[])
{
    printf("Usage: %s [-hv] -s <num> -E <num> -b <num> -t <file>\n", argv[0]);
    printf("Options:\n");
    printf("  -h         Print this help message.\n");
    printf("  -v         Optional verbose flag.\n");
    printf("  -s <num>   Number of set index bits.\n");
    printf("  -E <num>   Number of lines per set.\n");
    printf("  -b <num>   Number of block offset bits.\n");
    printf("  -t <file>  Trace file.\n");
    printf("\nExamples:\n");
    printf("  linux>  %s -s 4 -E 1 -b 4 -t traces/yi.trace\n", argv[0]);
    printf("  linux>  %s -v -s 8 -E 2 -b 4 -t traces/yi.trace\n", 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\n", 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\n", S, E, B, trace_file);
    printf("DEBUG: set_index_mask: %llu\n", 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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM