csim.c
实验一文件,根据存放程序对数据的访问记录的输入文件内容,模拟cache,获得模拟结果。变量与函数解析如下:
- 变量解析
verbosity
:是否输出每一行记录的命中、缺失、替换情况,一般用于bug测试s
:组索引组号位宽b
:cache每一行存放的数据位宽,即块内偏移位宽E
:关联度,即每组的行数,每组内是全相联trace_file
:数据访问追踪记录文件路径S
:组索引组数,由位宽计算得到cache
:模拟cache的一个二维数组,根据组号以及组内行号确定一行cacheset_index_mask
:用于获得组号的一个mask
- 函数解析
initCache
:根据S,E创建cache数据,并初始化set_index_maskfreeCache
:回收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;
}
来源:oschina
链接:https://my.oschina.net/u/4297414/blog/4288002