The goal of this assignment is to provide you a better understanding of caches.
ID: 3812833 • Letter: T
Question
The goal of this assignment is to provide you a better understanding of caches. You are required to write a cache simulator using the C programming languages. The programs have to run on iLab machines and should be tested with the autograder. We are providing real program memory traces as input to your cache simulator. The format and structure of the memory traces are described below. Memory Access Traces The input to the cache simulator is a memory access trace, which we have generated by executing real programs. The trace contains memory addresses accessed during program execution. Your cache simulator will have to use these addresses to determine if the access is a hit, miss, and the actions to perform. The memory trace file consists of multiple lines. Each line of the trace file corresponds to a memory accesses performed by the program. Each line consists of multiple columns, which are space- separated.The first column reports the PC (program counter) when this particular memory access occurred. Second column lists whether the memory access is a read (R) or a write operation. And the last column reports the actual 48-bit memory address that has been accessed by the program. In this assignment, you only need to consider the second and the third columns (i e. you don't really need to know the PCs). Cache Simulator You will implement a cache simulator to evaluate different configurations of caches. It should be able to run with different traces files. The followings are the requirements for your cache simulator: 1. Simulate only one level cache L1 2. The cache size, associativity, and block size are input parameters. Cache size and block size are specified in bytes.Explanation / Answer
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(" %s -s 4 -E 1 -b 4 -t traces/yi.trace ", argv[0]);
printf(" %s -v -s 8 -E 2 -b 4 -t traces/yi.trace ", argv[0]);
exit(0);
}
int main(int argc, char **argv)
{
cache_param_t par; bzero(&par, sizeof(par));
char *trace_file;
char c;
while( (c=getopt(argc,argv,"s:E:b:t:vh")) != -1)
{
switch(c)
{
case 's': par.s = atoi(optarg);
break;
case 'E': par.E = atoi(optarg);
break;
case 'b': par.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);
}
}
if (par.s == 0 || par.E == 0 || par.b == 0 || trace_file == NULL)
{
printf("%s: Missing required command line argument ", argv[0]);
printUsage(argv);
exit(1);
}
/* TODO: Compute S and B based on information passed in */
//Compute S and B, 2^s and 2^b respectively
par.S = (1 << par.s);
par.B = (1 << par.b);
/* TODO: Initialize a cache */
//Structure for a line
typedef struct
{
int valid;
mem_addr_t tag;
int timestamp;
}
line_st;
//Structure for a set; a pointer to an array of lines
typedef struct { line_st *lines;
}
cache_set;
//Structure for a cache; a pointer to an array of sets
typedef struct
{
cache_set *sets;
}
cache_t;
//allocate space for sets and for lines
cache_t cache;
cache.sets = malloc(par.S * sizeof(cache_set));
for (int i = 0; i < par.S; i++)
{
cache.sets[i].lines = malloc(sizeof(line_st) * par.E);
}
//counters
int hit_count = 0;
int miss_count = 0;
int eviction_count = 0;
/* TODO: Run the trace simulation */
char act;
//L,S,M
int size;
//size read in from file
int TSTAMP = 0;
//value for LRU
int empty = -1;
//index of empty space
int H = 0;
//is there a hit
int E = 0;
//is there an eviction
int toEvict = 0;
//keeps track of what to
evict mem_addr_t addr;
//open the file and read it in
FILE * traceFile = fopen(trace_file, "r");
if (traceFile != NULL)
{
//keep going while we have additional lines //
while(feof(traceFile) == 0)
{
while(fscanf(traceFile, " %c %llx,%d", &act, &addr, &size) == 3)
{
if (act != 'I')
{
//read the next line and look for string formated as " %c %llx,%d" //
sscanf(traceFile, " %c %llx,%d", &act, &addr, &size);
//fscanf(traceFile, " %c %llx,%d", &act, &addr, &size);
//calculate address tag and set index
mem_addr_t addr_tag = addr >> (par.s + par.b);
int tag_size = (64 - (par.s + par.b));
unsigned long long temp = addr << (tag_size);
unsigned long long setid = temp >> (tag_size + par.b);
//unsigned long
long setid = ((addr >> par.b) & (par.S - 1));
cache_set set = cache.sets[setid];
int low = par.E + 1;
for(int e = 0; e < par.E; e++)
{
if (set.lines[e].valid == 0)
{
empty = e;
}
else if (set.lines[e].valid == 1)
{
if (TSTAMP < low)
{
low = TSTAMP;
toEvict = e;
}
if (set.lines[e].tag == addr_tag)
{
hit_count++;
H = 1;
set.lines[e].timestamp = TSTAMP;
TSTAMP++;
}
}
}
//if we have a miss
if (H != 1)
{
miss_count++;
//if we have an empty line
if (empty > -1)
{
set.lines[empty].valid = 1;
set.lines[empty].tag = addr_tag;
set.lines[empty].timestamp = TSTAMP;
TSTAMP++;
}
//if the set is full we need to evict
else if (empty < 0)
{
E = 1;
set.lines[toEvict].tag = addr_tag;
set.lines[toEvict].timestamp = TSTAMP;
eviction_count++;
}
}
//if the instruction is M, we will always get a hit
if (act == 'M')
{
hit_count++;
}
//if the -v flag is set print out all debug information
if (verbosity == 1)
{
printf("%c ", act);
//printf("%llx,%d ", addr_tag, setid);
printf("%llx,%d ", addr, size);
if (H == 1)
{
printf("Hit ");
}
else if (H != 1)
{
printf("Miss ");
}
if (E == 1)
{
printf("Eviction ");
}
if (act == 'M')
{
printf("Hit ");
}
printf(" ");
}
empty = -1;
H = 0;
E = 0;
}
}
}
/* TODO: Clean up cache resources */
/* TODO: Print out real results */
printSummary(hit_count, miss_count, eviction_count);
return 0;
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.