cachelab started

This commit is contained in:
2025-04-21 23:52:27 +08:00
parent cc99d9b5d9
commit ace7a46fb9
58 changed files with 10071 additions and 0 deletions

792
cachelab/CacheHelper.c Normal file
View File

@@ -0,0 +1,792 @@
///////////////////////////////////////////////////////////////////////
//// Copyright 2022 by mars. //
///////////////////////////////////////////////////////////////////////
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#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 <trace>.zst\n", __func__, argv[0]);
printf("[%s] 例如: %s ./traces/dave.trace.zst\n", __func__, argv[0]);
printf("[%s] 将文本格式的Trace转换到bin格式:\t%s -w <trace>.zst\n", __func__, argv[0]);
printf("[%s] 从bin格式文件中读取Trace:\t\t%s -r <trace>.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;
}