CSCI 2330 Spring 2017 Instructor: Sean Barker |
This project may be completed either individually or in groups of 2. If you work in a group, you should be coding at the same time in front of one machine (this is sometimes called 'pair programming'). Take turns driving.
This project will help you understand the different types of caches designs and the impact that cache memories can have on the performance of your programs. To do so, you will write a C program simulating the behavior of a cache memory on real-world memory usage traces.
Start by reading through the entire project description!
Assigned | Wednesday, April 19. |
Due | Thursday, April 27. |
Your cache simulator will simulate an arbitrary cache memory, as defined by the usual three values S (the number of sets), E (the number of lines per set), and B (the size of a data block). Your program will simulate the behavior of the specified cache on a trace file, which consists of a series of memory accesses that you will replay in simulation. The output of your simulator will be three values: the number of cache hits, the number of cache misses, and the number of block evictions performed.
To help you test your program, you have been provided with a reference implementation, as well as a driver program that will automatically test your simulator by comparing its results against the reference simulator. Details on the trace files and the reference simulator are provided below.
The traces subdirectory of your project directory contains a collection of reference trace files that will be used to evaluate the correctness of your cache simulator. These trace files describe a series of memory accesses and are generated by valgrind. The traces have the following format:
I 0400d7d4,8 M 0421c7f0,4 L 04f6b868,8 S 7ff0005c8,8
Each line denotes one or two memory accesses. The general format of each line is
[space]operation address,size
The operation field denotes the type of memory access: "I" denotes an instruction load, "L" a data load, "S" a data store, and "M" a data modify (i.e., a data load followed by a data store). There is never a space before each "I", while there is always a space before each "M", "L", or "S". The address field specifies a 64-bit hex memory address. The size field specifies the number of bytes accessed by the operation.
In addition to the included traces, you can use valgrind to generate your own memory traces in this format, like so:
$ valgrind --log-fd=1 --tool=lackey -v --trace-mem=yes ls -l
The above example will run the program ls -l and dump a trace of its memory accesses to stdout. To save the output in a file, just redirect to a file by appending something like > ls.trace to the end of the valgrind command as we've seen in the past.
You have been provided with the compiled executable of a reference cache simulator called cachesim-ref to help you in testing your program. Just like the simulator you will write, the reference simulator outputs the total number of hits, misses, and evictions when running a given valgrind trace through the specified cache.
The reference simulator takes the following command-line arguments:
For example, here is an example run of the reference simulator:
$ ./cachesim-ref -s 4 -E 1 -b 4 -t traces/t2.trace hits:4 misses:5 evictions:3
Running the same with the addition of the -v flag will print information about each memory access in the trace:
$ ./cachesim-ref -v -s 4 -E 1 -b 4 -t traces/t2.trace L 10,1 miss M 20,1 miss hit L 22,1 hit S 18,1 hit L 110,1 miss eviction L 210,1 miss eviction M 12,1 miss eviction hit hits:4 misses:5 evictions:3
Your job is to complete your own cache simulator such that it takes the same command-line arguments as the reference simulator and produces identical output. You should write your simulator in cachesim.c. Note that this file is almost completely empty -- you'll need to write your simulator from scratch.
In addition to following the reference implementation output format, you must adhere to the following specifications while designing your cache simulator. Read each of these points carefully, as each one of them has the potential to completely change your cache's behavior if ignored.
Your project files contained in proj5 consist of the following:
To test your cache simulator against all of the included trace files and output an autograded correctness score, just execute the test-cachesim program:
$ ./test-cachesim Your simulator Reference simulator Points (s,E,b) Hits Misses Evicts Hits Misses Evicts 3 (1,1,1) 9 8 6 9 8 6 traces/t1.trace 3 (4,2,4) 4 5 2 4 5 2 traces/t2.trace 3 (2,1,4) 2 3 1 2 3 1 traces/t3.trace 3 (2,1,3) 167 71 67 167 71 67 traces/t4.trace 3 (2,2,3) 201 37 29 201 37 29 traces/t4.trace 3 (2,4,3) 212 26 10 212 26 10 traces/t4.trace 3 (5,1,5) 231 7 0 231 7 0 traces/t4.trace 6 (5,1,5) 265189 21775 21743 265189 21775 21743 traces/t5.trace 27 Simulator summary: scored 27 of 27 points
Here are some general tips for working on the cache simulator:
You will want to make use of the C standard library while working on your simulator. Here are some particular functions that you may wish to use (but feel free to expand beyond this list):
./myprog -b 25 -cHere is idiomatic code using getopt that supports parsing these arguments:
int flag_a_set = 0; int flag_b_value = -1; int flag_c_set = 0; char c; while ((c = getopt(argc, argv, "ab:c")) != -1) { // : indicates flag with an argument switch (c) { case 'a': flag_a_set = 1; break; case 'b': // optarg is a global variable set by getopt flag_b_value = atoi(optarg); // atoi converts a string to an int break; case 'c': flag_c_set = 1; break; default: // we got an unexpected flag (not a, b, or c) printUsageMsg(argv); // print a message saying what args are expected exit(1); } }Note that you'll need to include a few header lines to use getopt:
#include <getopt.h> #include <stdlib.h> #include <unistd.h>
You are responsible for completing the contents of the cachesim.c file. You should not modify any other file (e.g., you should not add any code to cache.c or cache.h).
As usual, your final submission will consist of your committed cachesim.c file at the time of the due date.
You will be evaluated both on the correctness of your cache simulator (as determined by test-cachesim) as well as the style and overall quality of your program (as determined by me).
Note: for full credit, your program must compile without any warnings on the class server!
You should follow all standard and sensible style guidelines, such as using good variable names, commenting, using consistent indentation, breaking up functionality into small, well-defined functions, etc. While you do not have to adhere to any particular set of conventions (e.g., where to put parentheses), you SHOULD be consistent with whatever conventions you choose.
Please ask if you have any questions about what contitutes good style or what is expected!