基于C 语⾔的Cache 模拟器实验
1.1实验⽬的
· 理解cache⼯作原理;
· 如何实现⼀个⾼效的模拟器
1.2实验环境
Linux 64-bit ,C语⾔
1.3实验思路
1.3.1 cache 模拟
建⽴cache的数据结构,包括有效位valid、标签位tag和使⽤记录器lru。实现代码如下:
定义cache组:⽤数组模拟cache组,即建⽴关于cache组的⼀个指针,然后动态开辟所需要cache的数量。实现代码如下:定义cache:⽤cache_set数组模拟cache,即⼀个cache包含多个cache组,同样先创建⼀个cache指针,然后根据所需要cache组的⼤⼩动态开辟cache的实际⼤⼩。实现代码如下:
1.3.2输⼊输出参数
verbosity:显⽰轨迹信息,输⼊指令中含-v则verbosity置1,表⽰要进⾏轨迹信息输出,否则verbosity置0。
s:组索引位数,输⼊指令中-s后⾯的数据为组索引位数,⽤S=2s表⽰所需要的cache组数。
b:内存块内地址位数,输⼊指令-b后⾯的数据为块内存地址组数,⽤B=2b表⽰所需要划分cache的内存块⼤⼩。
E:关联度(每组包含的缓存⾏数),输⼊指令后⾯的数据为关联度,即每⼀组有多少个块。
miss_count:⽤于记录未命中的次数。
hit_count:⽤于记录命中的次数。
eviction_count:⽤于记录淘汰的次数。
1.3.3函数initCache()
功能:初始化cache。
实现⽅法:对于给定的参数S、B、E利⽤malloc函数动态开辟cache所需要的内存⼤⼩。实现代码如下:
typedef  struct  cache_line {    char  valid ;    mem_addr_t tag ;    unsigned  long  long  int  lru ;} cache_line_t ;
1
2
3
4
5
6typedef  cache_line_t * cache_set_t ;
1typedef  cache_set_t * cache_t ;
1
1.3.4函数freeCache()
功能:释放cache所占⽤的内存。
实现⽅法:⽤循环遍历cache所申请的指针数组内存块,以此free掉各个内存块。实现代码如下:
1.3.5函数accessData()
功能:模拟cache进⾏的访问,给出所访问内存地址对应的是否命中或者是否淘汰。
实现⽅法:将输⼊地址和set_index_mask求与后得到⼀个索引,然后输⼊地址的前s+b位作为标签。依次查询每个块,并对⽐所需要的索引和标签,如果到了相应数据,则hit_count加1,否则miss_count加1。并且在未命中时,先查询块中是否有空位置,有的话直接占⽤此空位置,否则需要到lru最⼩的⾏(即最近访问时间间隔最长的⾏),然后进⾏数据的替换,eviction_count加1。实现代码如下:
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;        }    }    set_index_mask = (mem_addr_t ) (pow (2, s ) - 1);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14void  freeCache (){    int  i ;    for (i =0;i <S ;i ++){    free (cache [i ]);    }    free (cache );}
1
2
3
4
5
6
7
8
1.3.7函数printUsage()
功能:当有输⼊格式错误或者输⼊-h指令时,输出相应的信息。
实现⽅法:⽤printf函数输出相关信息。实现代码如下:
1.4实验结果和分析
修改完成csim.c⽂件后,进⾏make编译,并运⾏test-csim,得到的测试结果如下:
图 1-1 test-csim结果
由运⾏结果可知,cache模拟正确。
2.总结和体会
对cache进⾏的实验模拟算是⽐较简单的实验,仅仅只是模拟⼀个建议的cache然后对指令访问的命中和淘汰进⾏记录。需要考虑的函数实现⼤概就是accessData和replayTrace,前者要进⾏cache内数据的查和替换,后者是对⽂件的读取和指令类型判断。总体上来说,完成cache模拟实验加深了对cache运⾏模式的认知,也很好的理解了LRU淘汰策略的⼯作机制。
正确。
2.总结和体会
void  replayTrace (char * trace_fn ){    mem_addr_t addr =0;    unsigned  int  len =0;    char  operation ;    FILE * trace_fp = fopen (trace_fn , "r");    while (fscanf (trace_fp ,"%c %llx,%d",&operation ,&addr ,&len )!=EOF ){        if (operation =='I'&&verbosity )            printf ("%c %llx,%u ",operation ,addr ,len );        else  if (operation =='L'||operation =='S'||operation =='M'){            if (verbosity ) printf ("%c %llx,%u ",operation ,addr ,len );      accessData (addr );            if (operation =='M') accessData (addr );        if (verbosity ) printf ("\n");    }    }    fclose (trace_fp );}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
access被淘汰了吗18void  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 ace\n", argv [0]);    printf ("  linux>  %s -v -s 8 -E 2 -b 4 -t ace\n", argv [0]);    exit (0);}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。