/////////////////////////////////////////////////////////////////////// //// Copyright 2022 by mars. // /////////////////////////////////////////////////////////////////////// #include #include #include #include #include #include "getopt.h" #include "cbsl.h" #define CBSL_ERROR_CHECK(X) {if ((X) == cbsl_error) { fprintf(stderr, "error: %s\n", (#X)); }} /* fcn ideal% #items #buckets dup% fl add_usec find_usec del-all usec --- ------ ---------- ---------- ----- -- ---------- ---------- ------------ OAT 89.1% 597731 524288 0% ok 317292 179676 59726 FNV 88.6% 597731 262144 0% ok 226650 220626 61619 JEN 87.8% 597731 524288 0% ok 321989 175945 59956 BER 86.4% 597731 262144 0% ok 198477 179332 60901 SAX 70.4% 597731 524288 0% ok 270281 196427 64064 SFH 69.2% 597731 524288 0% ok 289843 165105 61860 FNV1A_Pippip_Yurii 更快?? */ // 使用OAT hash算法,以获得最高性能 #include "uthash.h" #undef HASH_FUNCTION //#define HASH_FUNCTION HASH_OAT #define HASH_FUNCTION(keyptr,keylen,hashv) (hashv) = FNV1A_Pippip_Yurii((UINT64 *)keyptr) #define VERBOSE_MSG 0 #ifdef _WIN32 #define ZLIB_WINAPI #endif #include "common.h" #ifdef _WIN64 #pragma comment(lib,"..\\zstd\\libzstd_static-win64.lib") #elif _WIN32 #pragma comment(lib,"..\\zstd\\libzstd_static-win32.lib") #endif /* 构建一个用Hash表访问的Memory,以便能够紧凑存放稀疏、随机的Memory数据 */ struct MemoryDataStruct { UINT64 Address; // 地址(默认是64位字地址) UINT64 Data; // 数据(默认保存64位字数据) UT_hash_handle memory; // makes this structure hashable } *MemoryHash = NULL; static void WriteMemoryHash(UINT64 Address, UINT64 WriteValue, UINT8 WriteSize); static UINT64 ReadMemoryHash(UINT64 Address, UINT8 ReadSize); #define MEMORY_TRACE_CHUNK (1<<20) // MemoryTrace结构,每次增长1M条记录 struct MemoryTraceStruct { UINT8 Operation; UINT64 Address; UINT8 Size; } *MemoryTrace; UINT64 MemoryTraceCounter, MemoryTraceCapacity; /* * 统计计数器 */ UINT64 GlobalMemoryModifyCounter; UINT64 GlobalMemoryInstCounter; UINT64 GlobalMemoryWriteCounter; UINT64 GlobalCacheWriteHitCounter; UINT64 GlobalMemoryReadCounter; UINT64 GlobalCacheReadHitCounter; UINT64 GlobalCacheModifyHitCounter; UINT64 GlobalSimReadMemoryCounter; UINT64 GlobalSimWriteMemoryCounter; UINT64 GlobalCacheInstHitCounter; #define CHUNK 16384 static void Trim(char* src) { char* begin = src; char* end = src + strlen(src); if (begin == end) return; while (*begin == ' ' || *begin == '\t') ++begin; while ((*end) == '\0' || *end == ' ' || *end == '\t' || *end == '\n' || *end == '\r') --end; if (begin > end) { *src = '\0'; return; } while (begin != end) { *src++ = *begin++; } *src++ = *end; *src = '\0'; return; } typedef struct { const char* start; size_t len; } token; // https://stackoverflow.com/a/39286524 static char** split_space(const char* str, int* field_count) { char** array; unsigned int start = 0, stop, toks = 0, t; token* tokens = malloc((strlen(str) + 1) * sizeof(token)); for (stop = 0; str[stop]; stop++) { if (str[stop] == ' ' || str[stop] == '\t' || str[stop] == ',') { tokens[toks].start = str + start; tokens[toks].len = stop - start; toks++; start = stop + 1; } } /* Mop up the last token */ tokens[toks].start = str + start; tokens[toks].len = stop - start; toks++; array = malloc(toks * sizeof(char*)); for (t = 0; t < toks; t++) { /* Calloc makes it nul-terminated */ char* token = calloc(tokens[t].len + 1, 1); memcpy(token, tokens[t].start, tokens[t].len); array[t] = token; } free(tokens); *field_count = toks; return array; } #define SR_A ((UINT64)1103515245) #define SR_C ((UINT64)12345) #define SR_M ((UINT64)1<<32) UINT64 Xn; static void SyncRand(UINT64 Seed) { Xn = Seed; } static UINT8 GetRand8() { Xn = ((SR_A * Xn + SR_C) % SR_M); return (UINT8)Xn; } static UINT16 GetRand16() { Xn = ((SR_A * Xn + SR_C) % SR_M); return (UINT16)Xn; } static UINT32 GetRand32() { Xn = ((SR_A * Xn + SR_C) % SR_M); return (UINT32)Xn; } static UINT64 GetRand64() { UINT32 Hi, Lo; Hi = GetRand32(); Lo = GetRand32(); return ((UINT64)Hi << 32 | Lo); } //https://www.codeproject.com/articles/716530/fastest-hash-function-for-table-lookups-in-c static inline UINT32 FNV1A_Pippip_Yurii(UINT64* Address) { const UINT32 PRIME = 591798841; UINT32 hash32; UINT64 hash64 = 14695981039346656037ULL; hash64 = (hash64 ^ *Address) * PRIME; hash32 = (uint32_t)(hash64 ^ (hash64 >> 32)); return hash32 ^ (hash32 >> 16); } static void InitMemoryHash() { } static void FreeMemoryHash() { struct MemoryDataStruct* p, * tmp; HASH_ITER(memory, MemoryHash, p, tmp) { HASH_DELETE(memory, MemoryHash, p); free(p); } } static void UpdateMemoryData(UINT64* Location, UINT8 Offset, UINT64 WriteValue, UINT8 WriteSize) { UINT64 OriginValue; OriginValue = *Location; switch (WriteSize) { case 1: // 1个字节 Offset = Offset << 3; // 从字节换算成位 OriginValue = (OriginValue & ~((UINT64)0xFF << Offset)) | ((WriteValue & (UINT64)0xFF) << Offset); break; case 2: // 2个字节 Offset = Offset & 0xFE; // 对齐到2字节边界 Offset = Offset << 3; // 从字节换算成位 OriginValue = (OriginValue & ~((UINT64)0xFFFF << Offset)) | ((WriteValue & (UINT64)0xFFFF) << Offset); break; case 4: // 4个字节 Offset = Offset & 0xFC; // 对齐到4字节边界 Offset = Offset << 3; // 从字节换算成位 OriginValue = (OriginValue & ~((UINT64)0xFFFFFFFF << Offset)) | ((WriteValue & (UINT64)0xFFFFFFFF) << Offset); break; case 8: // 8个字节 OriginValue = WriteValue; break; } *Location = OriginValue; } static void WriteMemoryHash(UINT64 Address, UINT64 WriteValue, UINT8 WriteSize) { UINT64 AlignAddress; UINT8 Offset; struct MemoryDataStruct* s; AlignAddress = Address & 0xFFFFFFFFFFFFFFF8; Offset = Address & 0x7; HASH_FIND(memory, MemoryHash, &AlignAddress, sizeof(AlignAddress), s); if (s == NULL) { // 没有在MemoryData中命中 s = (struct MemoryDataStruct*)malloc(sizeof(struct MemoryDataStruct)); s->Address = AlignAddress; s->Data = 0xDEADBEEFDEADC0DE; HASH_ADD(memory, MemoryHash, Address, sizeof(AlignAddress), s); } UpdateMemoryData(&(s->Data), Offset, WriteValue, WriteSize); } static UINT64 ReadMemoryHash(UINT64 Address, UINT8 ReadSize) { UINT64 AlignAddress; UINT8 Offset; struct MemoryDataStruct* s; UINT64 OriginValue, ReadValue; AlignAddress = Address & 0xFFFFFFFFFFFFFFF8; Offset = Address & 0x7; HASH_FIND(memory, MemoryHash, &AlignAddress, sizeof(AlignAddress), s); if (s == NULL) { // 没有在MemoryData中命中,出错了! if (VERBOSE_MSG) printf("[%s] 试图从一个未初始化的内存读取数据Address=%016llX!\n", __func__, Address); OriginValue = 0xDEADBEEFDEADC0DE; } else { OriginValue = s->Data; } /* * 根据Offset和Size,对读出的数据进行修正,对齐到小端 */ ReadValue = OriginValue; switch (ReadSize) { case 1: // 1个字节 Offset = Offset << 3; // 从字节换算成位 ReadValue = (OriginValue >> Offset) & 0xFF; break; case 2: // 2个字节 Offset = Offset & 0xFE; // 对齐到2字节边界 Offset = Offset << 3; // 从字节换算成位 ReadValue = (OriginValue >> Offset) & 0xFFFF; break; case 4: // 4个字节 Offset = Offset & 0xFC; // 对齐到4字节边界 Offset = Offset << 3; // 从字节换算成位 ReadValue = (OriginValue >> Offset) & 0xFFFFFFFF; break; case 8: // 8个字节 ReadValue = OriginValue; break; } return ReadValue; } UINT64 ReadMemory(UINT64 Address) { GlobalSimReadMemoryCounter++; return ReadMemoryHash(Address, 8); } void WriteMemory(UINT64 Address, UINT64 WriteData) { GlobalSimWriteMemoryCounter++; WriteMemoryHash(Address, WriteData, 8); } static void MemoryTraceStat() { UINT64 i; GlobalMemoryInstCounter = 0; GlobalMemoryReadCounter = 0; GlobalMemoryWriteCounter = 0; GlobalMemoryModifyCounter = 0; for (i = 0; i < MemoryTraceCounter; i++) { if (MemoryTrace[i].Operation == 'I') GlobalMemoryInstCounter++; else if (MemoryTrace[i].Operation == 'L') GlobalMemoryReadCounter++; else if (MemoryTrace[i].Operation == 'S') GlobalMemoryWriteCounter++; else if (MemoryTrace[i].Operation == 'M') GlobalMemoryModifyCounter++; } } static int process_TRACE_line(char* linebuf, UINT64 lineno) { int i; int ret = 0; UINT8 Operation; UINT64 Address; UINT8 Size; UINT64 RandValue64; // 删除行首、行尾空白回车等 Trim(linebuf); int linelen = (int)strlen(linebuf); // 跳过空行 if (linelen == 0) return 0; // 跳过超长的行 if (linelen >= 100) return 0; // 跳过注释行 if (linebuf[0] == '#' || linebuf[0] == '/' || linebuf[0] == '=' || linebuf[0] == '-') return 0; //printf("lineno=%llu\n", lineno); char** pt; int field_count; pt = split_space(linebuf, &field_count); if (field_count == 3 || field_count == 4) { // 格式: Operation Address,Size Operation = pt[0][0]; if (field_count == 3) { Address = strtoull(pt[1], NULL, 16); Size = atoi(pt[2]); } else { Address = strtoull(pt[2], NULL, 16); Size = atoi(pt[3]); } if (Operation != 'I' && Operation != 'L' && Operation != 'S' && Operation != 'M') { if (VERBOSE_MSG) printf("[%s] line %lld 操作类型错误,不是I、L、S、M! %s\n", __func__, lineno, linebuf); ret = -1; } else if (Size != 1 && Size != 2 && Size != 4 && Size != 8) { if (VERBOSE_MSG) printf("[%s] line %lld 数据大小错误,不是1、2、4、8! %s\n", __func__, lineno, linebuf); ret = -1; } else { RandValue64 = GetRand64(); // 初始化阶段,需要将所有地址的数据,设置为随机值 WriteMemoryHash(Address, RandValue64, Size); if (MemoryTraceCounter >= MemoryTraceCapacity) { if (VERBOSE_MSG) printf("[%s] line %lld 扩展内存到%llu!\n", __func__, lineno, MemoryTraceCapacity + MEMORY_TRACE_CHUNK); MemoryTrace = (struct MemoryTraceStruct*)realloc(MemoryTrace, (MemoryTraceCapacity + MEMORY_TRACE_CHUNK) * sizeof(struct MemoryTraceStruct)); if (MemoryTrace == NULL) { printf("[%s] line %lld 分配内存失败!\n", __func__, lineno); ret = -1; } else MemoryTraceCapacity += MEMORY_TRACE_CHUNK; } if (MemoryTrace) { MemoryTrace[MemoryTraceCounter].Operation = Operation; MemoryTrace[MemoryTraceCounter].Address = Address; MemoryTrace[MemoryTraceCounter].Size = Size; MemoryTraceCounter++; ret = 0; } } } else { printf("[%s] line %lld 格式错误![fields=%d] %s\n", __func__, lineno, field_count, linebuf); ret = -1; } for (i = 0; i < field_count; i++) free(pt[i]); free(pt); return ret; } static int parse_TRACE_file(char* filename) { UINT64 lineno; int ret_parse_line = 0; clock_t tick1, tick2; cbsl_errors cbsl_ret = cbsl_error; char linebuf[CHUNK]; tick1 = clock(); cbsl_ctx* ctx = cbsl_open(cbsl_load_mode, filename); if (ctx == NULL) { printf("[%s] 不能以读方式打开Trace文件 %s\n", __func__, filename); return -1; } lineno = 0; do { lineno++; cbsl_ret = cbsl_readline(ctx, linebuf, sizeof(linebuf)); CBSL_ERROR_CHECK(cbsl_ret); // 从文件中读取1行 ret_parse_line = process_TRACE_line(linebuf, lineno); // 分析处理1行 if (ret_parse_line == 1 || cbsl_ret == cbsl_end) break; if (lineno % 10000 == 0) { printf("\33[?25l[%s] ====已处理%llu行====\r", __func__, lineno); // 隐藏光标,显示进度 } } while (1); printf("\n\33[?25h"); // 显示光标 CBSL_ERROR_CHECK(cbsl_close(ctx)); tick2 = clock(); MemoryTraceStat(); printf("[%s] +-----------------------------------------------------+\n", __func__); printf("[%s] | Memory Trace数量 \t : %10llu |\n", __func__, MemoryTraceCounter); printf("[%s] | Instruction操作数量 \t : %10llu |\n", __func__, GlobalMemoryInstCounter); printf("[%s] | Data Load操作数量 \t : %10llu |\n", __func__, GlobalMemoryReadCounter); printf("[%s] | Data Store操作数量 \t : %10llu |\n", __func__, GlobalMemoryWriteCounter); printf("[%s] | Data Modify操作数量 \t : %10llu |\n", __func__, GlobalMemoryModifyCounter); printf("[%s] | 时间耗费(ms) \t : %10.0f |\n", __func__, ((float)(tick2 - tick1) / CLOCKS_PER_SEC) * 1000.0); printf("[%s] +-----------------------------------------------------+\n", __func__); if (MemoryTraceCounter == 0) return -1; return 0; } int SimTrace() { int ret = 0; UINT32 i; UINT8 Operation; UINT64 Address; UINT8 Size; UINT64 RandValue64; UINT64 DataFromCache; UINT64 DataFromMemory; UINT8 MissFlag; clock_t tick1, tick2; tick1 = clock(); GlobalMemoryInstCounter = 0; GlobalMemoryReadCounter = 0; GlobalMemoryWriteCounter = 0; GlobalMemoryModifyCounter = 0; GlobalCacheInstHitCounter = 0; GlobalCacheReadHitCounter = 0; GlobalCacheWriteHitCounter = 0; GlobalCacheModifyHitCounter = 0; GlobalSimReadMemoryCounter = 0; GlobalSimWriteMemoryCounter = 0; for (i = 0; i < MemoryTraceCounter; i++) { Operation = MemoryTrace[i].Operation; Address = MemoryTrace[i].Address; Size = MemoryTrace[i].Size; if (Operation == 'L' || Operation == 'S' || Operation == 'M') { RandValue64 = GetRand64(); MissFlag = AccessDataCache(Address, Operation, Size, RandValue64, &DataFromCache); if (Operation == 'S' || Operation == 'M') { WriteMemoryHash(Address, RandValue64, Size); if (Operation == 'S') { GlobalMemoryWriteCounter++; if (MissFlag == 'H') { GlobalCacheWriteHitCounter++; } } else if (Operation == 'M') { GlobalMemoryModifyCounter++; if (MissFlag == 'H') { GlobalCacheModifyHitCounter++; } } } else if (Operation == 'L') { GlobalMemoryReadCounter++; if (MissFlag == 'H') { DataFromMemory = ReadMemoryHash(Address, Size); if (DataFromMemory == DataFromCache) GlobalCacheReadHitCounter++; else { printf("[%s] 关键错误!数据Cache读错误,内存地址=%016llX 内存数据=%016llX Cache读数据=%016llX 大小%d字节\n", __func__, Address, DataFromMemory, DataFromCache, Size); ret = -1; break; } } } } else if (Operation == 'I') { MissFlag = AccessInstCache(Address, Operation, Size, &DataFromCache); GlobalMemoryInstCounter++; if (MissFlag == 'H') { DataFromMemory = ReadMemoryHash(Address, Size); if (DataFromMemory == DataFromCache) GlobalCacheInstHitCounter++; else { printf("[%s] 关键错误!指令Cache读错误,内存地址=%016llX 内存数据=%016llX Cache读数据=%016llX 大小%d字节\n", __func__, Address, DataFromMemory, DataFromCache, Size); ret = -1; break; } } } } tick2 = clock(); printf("[%s] +-----------------------------------------------------+\n", __func__); printf("[%s] | Memory Trace数量 \t : %10llu |\n", __func__, MemoryTraceCounter); printf("[%s] | Instruction操作数量 \t : %10llu |\n", __func__, GlobalMemoryInstCounter); printf("[%s] | Data Load操作数量 \t : %10llu |\n", __func__, GlobalMemoryReadCounter); printf("[%s] | Data Store操作数量 \t : %10llu |\n", __func__, GlobalMemoryWriteCounter); printf("[%s] | Data Modify操作数量 \t : %10llu |\n", __func__, GlobalMemoryModifyCounter); printf("[%s] | Instruction操作Cache命中数量 \t : %10llu |\n", __func__, GlobalCacheInstHitCounter); printf("[%s] | Data Load操作Cache命中数量 \t : %10llu |\n", __func__, GlobalCacheReadHitCounter); printf("[%s] | Data Store操作Cache命中数量 \t : %10llu |\n", __func__, GlobalCacheWriteHitCounter); printf("[%s] | Data Modify操作Cache命中数量 \t : %10llu |\n", __func__, GlobalCacheModifyHitCounter); printf("[%s] | Cache访存数量 \t : %10llu |\n", __func__, GlobalSimReadMemoryCounter + GlobalSimWriteMemoryCounter); printf("[%s] | Cache读存储器数量 \t : %10llu |\n", __func__, GlobalSimReadMemoryCounter); printf("[%s] | Cache写存储器数量 \t : %10llu |\n", __func__, GlobalSimWriteMemoryCounter); printf("[%s] | Data Cache命中率 \t : %9.2f%% |\n", __func__, (double)((GlobalCacheReadHitCounter + GlobalCacheWriteHitCounter + GlobalCacheModifyHitCounter) * 100) / (double)(GlobalMemoryReadCounter + GlobalMemoryWriteCounter + GlobalMemoryModifyCounter)); printf("[%s] | Inst Cache命中率 \t : %9.2f%% |\n", __func__, (GlobalMemoryInstCounter == 0) ? 0 : (double)(GlobalCacheInstHitCounter * 100) / (double)GlobalMemoryInstCounter); printf("[%s] | 时间耗费(ms) \t : %10.0f |\n", __func__, ((float)(tick2 - tick1) / CLOCKS_PER_SEC) * 1000.0); printf("[%s] +-----------------------------------------------------+\n", __func__); return ret; } void DisplayHelp(char* argv[]) { printf("[%s] 请在Cache.c中,实现你自己的Cache,然后编译项目,执行。\n", __func__); printf("[%s] 从文本格式压缩文件中读取Trace:\t%s .zst\n", __func__, argv[0]); printf("[%s] 例如: %s ./traces/dave.trace.zst\n", __func__, argv[0]); printf("[%s] 将文本格式的Trace转换到bin格式:\t%s -w .zst\n", __func__, argv[0]); printf("[%s] 从bin格式文件中读取Trace:\t\t%s -r .bin.zst\n", __func__, argv[0]); printf("[%s] 提示:从bin中读取Trace速度要远远快于从文本格式中读取。\n", __func__); } int main(int argc, char* argv[]) { int ret_val = -1; UINT8 ReadBinFileFlag, WriteBinFileFlag, ReadTxtFileFlag; char* pfilename; char pfilename_bin[CHUNK]; clock_t tick1, tick2; UINT64 i; printf("[%s] Cache模拟器框架 v3.0 by mars, 2022\n", __func__); pfilename = NULL; ReadBinFileFlag = 0; WriteBinFileFlag = 0; ReadTxtFileFlag = 1; /* check arguments */ while (1) { int c = getopt(argc, argv, "-hrw"); if (c == -1) break; switch (c) { case 'h': DisplayHelp(argv); return 1; case 'r': ReadBinFileFlag = 1; ReadTxtFileFlag = 0; break; case 'w': WriteBinFileFlag = 1; ReadTxtFileFlag = 0; break; case 1: pfilename = optarg; break; } } if ((ReadBinFileFlag == 1 || WriteBinFileFlag == 1 || ReadTxtFileFlag == 1) && pfilename == NULL) { DisplayHelp(argv); return 1; } InitMemoryHash(); printf("[%s] 初始化存储器,读入Trace文件[%s],请稍后...\n", __func__, pfilename); if (ReadTxtFileFlag || WriteBinFileFlag) { MemoryTrace = (struct MemoryTraceStruct*)malloc(MEMORY_TRACE_CHUNK * sizeof(struct MemoryTraceStruct)); MemoryTraceCounter = 0; MemoryTraceCapacity = MEMORY_TRACE_CHUNK; ret_val = parse_TRACE_file(pfilename); if (ret_val != 0) { FreeMemoryHash(); if (MemoryTrace) free(MemoryTrace); printf("[%s] 解压缩文件失败 %s\n", __func__, argv[1]); return -1; } if (WriteBinFileFlag) { // 将内存中的MemoryTrace保存到bin文件中 int filenamelen = (int)strlen(pfilename); memcpy(pfilename_bin, pfilename, filenamelen); pfilename_bin[filenamelen] = '\0'; if (filenamelen > 5) { if ((pfilename_bin[filenamelen - 4] == '.' && pfilename_bin[filenamelen - 3] == 'z' && pfilename_bin[filenamelen - 2] == 's' && pfilename_bin[filenamelen - 1] == 't') || (pfilename_bin[filenamelen - 4] == '.' && pfilename_bin[filenamelen - 3] == 'Z' && pfilename_bin[filenamelen - 2] == 'S' && pfilename_bin[filenamelen - 1] == 'T')) { pfilename_bin[filenamelen - 3] = 'b'; pfilename_bin[filenamelen - 2] = 'i'; pfilename_bin[filenamelen - 1] = 'n'; pfilename_bin[filenamelen - 0] = '.'; pfilename_bin[filenamelen + 1] = 'z'; pfilename_bin[filenamelen + 2] = 's'; pfilename_bin[filenamelen + 3] = 't'; pfilename_bin[filenamelen + 4] = '\0'; cbsl_ctx* ctx = cbsl_open(cbsl_store_mode, pfilename_bin); if (ctx == NULL) { printf("[%s] 不能以写方式打开文件 %s\n", __func__, pfilename_bin); ret_val = -1; } else { CBSL_ERROR_CHECK(cbsl_write(ctx, &MemoryTraceCounter, sizeof(MemoryTraceCounter))); CBSL_ERROR_CHECK(cbsl_write(ctx, MemoryTrace, MemoryTraceCounter * sizeof(struct MemoryTraceStruct))); CBSL_ERROR_CHECK(cbsl_close(ctx)); printf("[%s] 已经将Trace保存到文件中 %s\n", __func__, pfilename_bin); ret_val = 0; } } else { printf("[%s] 文件扩展名不是.zst或者.ZST!不能转换!\n", __func__); ret_val = -1; } } else { printf("[%s] 文件名长度不足5字符!不能转换!\n", __func__); ret_val = -1; } FreeMemoryHash(); if (MemoryTrace) free(MemoryTrace); return ret_val; } } else if (ReadBinFileFlag) { cbsl_ctx* ctx = cbsl_open(cbsl_load_mode, pfilename); if (ctx == NULL) { printf("[%s] 不能以读方式打开文件 %s\n", __func__, pfilename); ret_val = -1; } else { tick1 = clock(); CBSL_ERROR_CHECK(cbsl_read(ctx, &MemoryTraceCounter, sizeof(MemoryTraceCounter))); { MemoryTrace = (struct MemoryTraceStruct*)malloc(MemoryTraceCounter * sizeof(struct MemoryTraceStruct)); MemoryTraceCapacity = MemoryTraceCounter; CBSL_ERROR_CHECK(cbsl_read(ctx, MemoryTrace, MemoryTraceCounter * sizeof(struct MemoryTraceStruct))); CBSL_ERROR_CHECK(cbsl_close(ctx)); { // 初始化阶段,需要将所有地址的数据,设置为随机值 UINT64 RandValue64; for (i = 0; i < MemoryTraceCounter; i++) { RandValue64 = GetRand64(); WriteMemoryHash(MemoryTrace[i].Address, RandValue64, MemoryTrace[i].Size); } MemoryTraceStat(); tick2 = clock(); printf("[%s] +-----------------------------------------------------+\n", __func__); printf("[%s] | Memory Trace数量 \t : %10llu |\n", __func__, MemoryTraceCounter); printf("[%s] | Instruction操作数量 \t : %10llu |\n", __func__, GlobalMemoryInstCounter); printf("[%s] | Data Load操作数量 \t : %10llu |\n", __func__, GlobalMemoryReadCounter); printf("[%s] | Data Store操作数量 \t : %10llu |\n", __func__, GlobalMemoryWriteCounter); printf("[%s] | Data Modify操作数量 \t : %10llu |\n", __func__, GlobalMemoryModifyCounter); printf("[%s] | 时间耗费(ms) \t : %10.0f |\n", __func__, ((float)(tick2 - tick1) / CLOCKS_PER_SEC) * 1000.0); printf("[%s] +-----------------------------------------------------+\n", __func__); printf("[%s] 已经将Trace从文件中读取 %s\n", __func__, pfilename); ret_val = 0; } } } if (ret_val == -1) { if (MemoryTrace) free(MemoryTrace); FreeMemoryHash(); return ret_val; } } printf("[%s] 处理Trace文件完毕\n", __func__); InitDataCache(); InitInstCache(); printf("[%s] 开始Cache模拟,请稍后...\n", __func__); ret_val = SimTrace(); if (ret_val != 0) { FreeMemoryHash(); if (MemoryTrace) free(MemoryTrace); printf("[%s] Cache模拟失败\n", __func__); return -1; } else printf("[%s] Cache模拟成功完成\n", __func__); if (MemoryTrace) free(MemoryTrace); FreeMemoryHash(); return 0; }