1. 程式人生 > >csapp 實驗 Cache Lab: Understanding Cache Memories

csapp 實驗 Cache Lab: Understanding Cache Memories

實驗指導書

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目錄給出的用例測試