csapp 實驗 Cache Lab: Understanding Cache Memories
阿新 • • 發佈:2019-01-02
實驗指導書
Part A: Writing a Cache Simulator
這裡的LRU和之前上課學的不一樣,首先會對地址進行雜湊運算再LRU。
如果E=1,那就不是LRU了。
不需要真的儲存資料,只需要計算hit, miss, eviction次數即可。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <memory.h>
#include "cachelab.h"
#include <limits.h>
int S, E, B;
int hit = 0, miss = 0, eviction = 0;//儲存結果
/*
* valid是表示當前cacheLine是否已被使用,addr存放地址,time存放時間,從1開始
*/
typedef struct {
int valid;
long addr;
int time;
} cacheLine;
cacheLine *cache;
/*
* 返回1表示hit,2表示miss,4表示eviction,所以6表示miss和eviction
* 讀入一條指令,可能為L,M,S。
* L與S的效果相同,首先對B取餘數找到對應區間(在這裡就是cache的第幾行),然後遍歷該行,
*(獲取地址是否存在資訊、存在的索引或最小索引、當前最大time)
* 看看地址是否存在,若存在則根據對應index更新time。
* 若不存在,則更新time最小的cacheLine。
*/
int readCacheLine(cacheLine *cache, char type, long addr);
void printHelp() {
printf("Usage: ./csim-wrc [-hv] -s <s> -E <E> -b <b> -t <tracefile>\n"
"• -h: Optional help flag that prints usage info\n"
"• -v: Optional verbose flag that displays trace info\n"
"• -s <s>: Number of set index bits (S = 2^s is the number of sets)\n"
"• -E <E>: Associativity (number of lines per set)\n"
"• -b <b>: Number of block bits (B = 2^b is the block size)\n"
"• -t <tracefile>: Name of the valgrind trace to replay\n");
}
/*
* 返回0代表成功
* 1是讀入引數錯誤
* 2是分配記憶體失敗
* 3是開啟檔案失敗
*/
int main(int argc, char *argv[]) {
opterr = 0;
int verboseFlag = 0;
int oc;
int error = 0;
int in = 0;
char *filePath = NULL;
while ((error == 0) && ((oc = getopt(argc, argv, "s:E:b:t:hv")) != -1)) {
in = 1;
switch (oc) {
case 's':
S = (int) pow(2, atoi(optarg));
break;
case 'E':
E = atoi(optarg);
break;
case 'b':
B = (int) pow(2, atoi(optarg));
break;
case 't':
filePath = optarg;
break;
case 'v':
verboseFlag = 1;
break;
case 'h':
case '?':
default:
error = 1;
printHelp();
break;
}
}
//輸入錯誤時輸出用法
if (in == 0 && oc == -1)
printHelp();
if (error == 0) {
FILE *file = fopen(filePath, "r");
if (file == NULL) {
printf("找不到檔案");
return 3;
}
cache = (cacheLine *) malloc(S * E * sizeof(cacheLine));
if (cache == NULL) {
printf("記憶體分配失敗");
return 2;
}
memset(cache, 0, S * E * sizeof(cacheLine));
char type;
int size;
long addr;
while (!feof(file)) {
int tr = fscanf(file, " %c %lx,%x", &type, &addr, &size);
if (tr != 3)
continue;
if (type != 'I') {
int rclResult = readCacheLine(cache, type, addr);
char *temp1 = NULL;
switch (rclResult) {
case 1:
hit++;
temp1 = "hit";
if (type == 'M')
hit++;
break;
case 2:
miss++;
temp1 = "miss";
break;
case 3:
miss++;
hit++;
temp1 = "miss";
break;
case 6:
miss++;
eviction++;
temp1 = "miss";
break;
case 7:
default:
miss++;
eviction++;
hit++;
temp1 = "miss";
break;
}
if (verboseFlag) {
printf("%c %lx,%x %s", type, addr, size, temp1);
if (rclResult == 6) {
printf(" eviction");
} else if (rclResult == 3) {
printf(" hit");
} else if (rclResult == 7) {
printf(" eviction hit");
} else if (rclResult == 1 && type == 'M') {
printf(" hit");
}
printf("\n");
}
}
}
free(cache);
cache = NULL;
printSummary(hit, miss, eviction);
}
// printSummary(0, 0, 0);
return error;
}
int readCacheLine(cacheLine *cache, char type, long addr) {
int result = 0;
int sIndex = (int) ((addr / B) % S);
int eIndex = 0, minTime = INT_MAX, maxTime = -1, exist = 0, insert = 0;
for (int i = 0; i < E; ++i) {
cacheLine *ptr = (cache + sIndex * E + i);
if (insert == 0 && result == 0) {
if (ptr->valid != 1) {
ptr->valid = 1;
ptr->addr = addr;
insert = 1;
exist = 0;
result = 2;
eIndex = i;
if (type == 'M')
result = 3;
//這裡還不能break,要找到最大時間
} else {
//如果addr已存在,則索引為當前索引,否則為time最小的索引
if ((ptr->addr / B) == (addr / B)) {
exist = 1;
eIndex = i;
result = 1;
}
if (minTime > ptr->time) {
minTime = ptr->time;
if (exist == 0)
eIndex = i;
}
}
}
if (ptr->time > maxTime)
maxTime = ptr->time;
}
cacheLine *ptr = (cache + sIndex * E + eIndex);
//更新而不是插入
if (insert == 0) {
if (exist == 0) {
ptr->addr = addr;
result = 6;
if (type == 'M')
result = 7;
}
}
ptr->time = maxTime + 1;
return result;
}
已通過traces目錄給出的用例測試