cachelab finished

This commit is contained in:
2025-04-24 22:32:48 +08:00
parent ace7a46fb9
commit 92300134d2
8 changed files with 2793 additions and 148 deletions

BIN
cachelab/Cache Executable file

Binary file not shown.

1930
cachelab/Cache.bak Normal file

File diff suppressed because it is too large Load Diff

403
cachelab/Cache.bak2 Normal file
View File

@ -0,0 +1,403 @@
///////////////////////////////////////////////////////////////////////
//// Copyright 2022 by mars. //
///////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#define DEBUG 0
#define GET_POWER_OF_2(X) (X == 0x00 ? 0 : \
X == 0x01 ? 0 : \
X == 0x02 ? 1 : \
X == 0x04 ? 2 : \
X == 0x08 ? 3 : \
X == 0x10 ? 4 : \
X == 0x20 ? 5 : \
X == 0x40 ? 6 : \
X == 0x80 ? 7 : \
X == 0x100 ? 8 : \
X == 0x200 ? 9 : \
X == 0x400 ? 10 : \
X == 0x800 ? 11 : \
X == 0x1000 ? 12 : \
X == 0x2000 ? 13 : \
X == 0x4000 ? 14 : \
X == 0x8000 ? 15 : \
X == 0x10000 ? 16 : \
X == 0x20000 ? 17 : \
X == 0x40000 ? 18 : \
X == 0x80000 ? 19 : \
X == 0x100000 ? 20 : \
X == 0x200000 ? 21 : \
X == 0x400000 ? 22 : \
X == 0x800000 ? 23 : \
X == 0x1000000 ? 24 : \
X == 0x2000000 ? 25 : \
X == 0x4000000 ? 26 : \
X == 0x8000000 ? 27 : \
X == 0x10000000 ? 28 : \
X == 0x20000000 ? 29 : \
X == 0x40000000 ? 30 : \
X == 0x80000000 ? 31 : \
X == 0x100000000 ? 32 : 0)
/*
全相联Data Cache16KB大小
每行存放64个字节
*/
#define DCACHE_SIZE 16384
#define DCACHE_DATA_PER_LINE 128 // 必须是8字节的倍数
#define DCACHE_DATA_PER_LINE_ADDR_BITS GET_POWER_OF_2(DCACHE_DATA_PER_LINE) // 必须与上面设置一致即64字节需要6位地址
#define DCACHE_LINES (DCACHE_SIZE/DCACHE_DATA_PER_LINE)
#define MAX_AGE (DCACHE_LINES-1) // 每行有一个唯一的Age
// Cache行的结构包括Valid、Age、Dirty、Tag和Data。你所有的状态信息只能记录在Cache行中
struct DCACHE_LineStruct
{
UINT8 Valid;
UINT16 Age;
UINT8 Dirty;
UINT64 Tag;
UINT8 Data[DCACHE_DATA_PER_LINE];
} DCache[DCACHE_LINES];
/*
DCache初始化代码一般需要把DCache的有效位Valid设置为0
模拟器启动时会调用此InitDataCache函数
*/
void InitDataCache()
{
UINT32 i;
printf("[%s] +-----------------------------------+\n", __func__);
printf("[%s] | 威震天的Data Cache初始化ing.... |\n", __func__);
printf("[%s] +-----------------------------------+\n", __func__);
for (i = 0; i < DCACHE_LINES; i++) {
DCache[i].Valid = 0;
DCache[i].Age = i;
DCache[i].Dirty = 0;
}
}
/*
从Memory中读入一行数据到Data Cache中
*/
void LoadDataCacheLineFromMemory(UINT64 Address, UINT32 CacheLineIndex)
{
// 一次性从Memory中将DCACHE_DATA_PER_LINE数据读入某个Data Cache行
// 提供了一个函数一次可以读入8个字节
UINT32 i;
UINT64 ReadData;
UINT64 AlignAddress;
UINT64* pp;
AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1); // 地址必须对齐到DCACHE_DATA_PER_LINE (64)字节边界
pp = (UINT64*)DCache[CacheLineIndex].Data;
for (i = 0; i < DCACHE_DATA_PER_LINE / 8; i++)
{
ReadData = ReadMemory(AlignAddress + 8LL * i);
if (DEBUG)
printf("[%s] Address=%016llX ReadData=%016llX\n", __func__, AlignAddress + 8LL * i, ReadData);
pp[i] = ReadData;
}
}
/*
将Data Cache中的一行数据写入存储器
*/
void StoreDataCacheLineToMemory(UINT64 Address, UINT32 CacheLineIndex)
{
// 一次性将DCACHE_DATA_PER_LINE数据从某个Data Cache行写入Memory中
// 提供了一个函数一次可以写入8个字节
UINT32 i;
UINT64 WriteData;
UINT64 AlignAddress;
UINT64* pp;
AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1); // 地址必须对齐到DCACHE_DATA_PER_LINE (64)字节边界
pp = (UINT64*)DCache[CacheLineIndex].Data;
WriteData = 0;
for (i = 0; i < DCACHE_DATA_PER_LINE / 8; i++)
{
WriteData = pp[i];
WriteMemory(AlignAddress + 8LL * i, WriteData);
if (DEBUG)
printf("[%s] Address=%016llX WriteData=%016llX\n", __func__, AlignAddress + 8LL * i, WriteData);
}
}
// 从所有行中找到需要替换的Cache行
// 如果有某行的Valid=0则返回该行行号
// 否则返回Age最大的行的行号
int GetReplaceLine()
{
int replace_line = -1;
UINT16 max_age = 0;
for (int i = 0; i < DCACHE_LINES; i++)
{
if (!DCache[i].Valid)
{
return i;
}
if (DCache[i].Age > max_age)
{
max_age = DCache[i].Age;
replace_line = i;
}
}
return replace_line;
}
// 更新Age将HitLine指定的Cache行的Age设置为0其他行的Age要相应调整
// 注意要确保所有行的Age分别为0~MAX_AGE且唯一
// void UpdateAge(int HitLine)
// {
// for (int i = 0; i < DCACHE_LINES; i++) {
// if (i != HitLine && DCache[i].Valid && DCache[i].Age < MAX_AGE) {
// DCache[i].Age++;
// }
// }
// DCache[HitLine].Age = 0;
// }
void UpdateAge(int HitLine)
{
UINT16 old_age = DCache[HitLine].Age;
DCache[HitLine].Age = 0;
for (int i = 0; i < DCACHE_LINES; i++)
{
if (i != HitLine && DCache[i].Valid)
{
if (DCache[i].Age < old_age)
{
DCache[i].Age++;
}
}
}
}
/*
Data Cache访问接口系统模拟器会调用此接口来实现对你的Data Cache访问
Address: 访存字节地址
Operation: 操作:读操作('L')、写操作('S')、读-修改-写操作('M'
DataSize: 数据大小1字节、2字节、4字节、8字节
StoreValue: 当执行写操作的时候,需要写入的数据
LoadResult: 当执行读操作的时候从Cache读出的数据
*/
UINT8 AccessDataCache(UINT64 Address, UINT8 Operation, UINT8 DataSize, UINT64 StoreValue, UINT64* LoadResult)
{
UINT8 BlockOffset;
UINT64 AddressTag;
UINT8 MissFlag = 'M';
UINT64 ReadValue;
int HitLine = -1;
*LoadResult = 0;
// 全相联中Address被切分为 AddressTag 和 BlockOffset
BlockOffset = Address % DCACHE_DATA_PER_LINE;
AddressTag = Address >> DCACHE_DATA_PER_LINE_ADDR_BITS;
// 查找是否命中
for (int i = 0; i < DCACHE_LINES; i++) {
if (DCache[i].Valid == 1 && DCache[i].Tag == AddressTag) {
MissFlag = 'H';
HitLine = i;
break;
}
}
if (MissFlag == 'H') // 命中!
{
if (Operation == 'L') // 读操作
{
ReadValue = 0;
switch (DataSize)
{
case 1: // 1个字节
ReadValue = DCache[HitLine].Data[BlockOffset + 0];
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
ReadValue = DCache[HitLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 0];
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
ReadValue = DCache[HitLine].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 0];
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
ReadValue = DCache[HitLine].Data[BlockOffset + 7]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 6]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 5]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 4]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[HitLine].Data[BlockOffset + 0];
break;
}
*LoadResult = ReadValue;
if (DEBUG)
printf("[%s] Address=%016llX Operation=%c DataSize=%u StoreValue=%016llX ReadValue=%016llX\n", __func__, Address, Operation, DataSize, StoreValue, ReadValue);
}
else if (Operation == 'S' || Operation == 'M') // 写操作(修改操作在此等价于写操作)
{
if (DEBUG)
printf("[%s] Address=%016llX Operation=%c DataSize=%u StoreValue=%016llX\n", __func__, Address, Operation, DataSize, StoreValue);
switch (DataSize)
{
case 1: // 1个字节
DCache[HitLine].Data[BlockOffset + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
DCache[HitLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 1] = StoreValue & 0xFF;
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
DCache[HitLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 3] = StoreValue & 0xFF;
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
DCache[HitLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[HitLine].Data[BlockOffset + 7] = StoreValue & 0xFF;
break;
}
// 写回策略数据只写入Cache并设置脏位
DCache[HitLine].Dirty = 1;
}
// 更新访问时间
UpdateAge(HitLine);
}
else
{
if (DEBUG)
printf("[%s] Address=%016llX Operation=%c DataSize=%u StoreValue=%016llX\n", __func__, Address, Operation, DataSize, StoreValue);
// 不命中, 获取要替换的行
int ReplaceLine = GetReplaceLine();
// 如果要替换的行有效且脏,则需要写回到内存
if (DCache[ReplaceLine].Valid == 1 && DCache[ReplaceLine].Dirty == 1)
{
UINT64 OldAddress = DCache[ReplaceLine].Tag << DCACHE_DATA_PER_LINE_ADDR_BITS;
StoreDataCacheLineToMemory(OldAddress, ReplaceLine);
}
// 需要从Memory中读入新的行
LoadDataCacheLineFromMemory(Address, ReplaceLine);
DCache[ReplaceLine].Valid = 1;
DCache[ReplaceLine].Tag = AddressTag;
DCache[ReplaceLine].Dirty = 0;
if (Operation == 'S' || Operation == 'M') // 写操作(修改操作在此等价于写操作)
{
// 写操作需要将新的StoreValue更新到CacheLine中
switch (DataSize)
{
case 1: // 1个字节
DCache[ReplaceLine].Data[BlockOffset + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
DCache[ReplaceLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 1] = StoreValue & 0xFF;
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
DCache[ReplaceLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 3] = StoreValue & 0xFF;
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
DCache[ReplaceLine].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[ReplaceLine].Data[BlockOffset + 7] = StoreValue & 0xFF;
break;
}
DCache[ReplaceLine].Dirty = 1;
}
// 更新访问时间
UpdateAge(ReplaceLine);
if (Operation == 'L') // 读操作需要返回读取的值
{
ReadValue = 0;
switch (DataSize)
{
case 1: // 1个字节
ReadValue = DCache[ReplaceLine].Data[BlockOffset + 0];
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
ReadValue = DCache[ReplaceLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 0];
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
ReadValue = DCache[ReplaceLine].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 0];
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
ReadValue = DCache[ReplaceLine].Data[BlockOffset + 7]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 6]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 5]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 4]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[ReplaceLine].Data[BlockOffset + 0];
break;
}
*LoadResult = ReadValue;
}
}
return MissFlag;
}
/* 指令Cache实现部分可选实现 */
void InitInstCache(void)
{
return;
}
void LoadInstCacheLineFromMemory(UINT64 Address, UINT32 CacheLineAddress)
{
return;
}
UINT8 AccessInstCache(UINT64 Address, UINT8 Operation, UINT8 InstSize, UINT64* InstResult)
{
// 返回值'M' = Miss'H'=Hit
return 'M';
}

View File

@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////
//// Copyright 2022 by mars. //
///////////////////////////////////////////////////////////////////////
///
// Copyright 2022 by mars. //
///
#include <stdio.h>
#include <stdlib.h>
@ -45,21 +45,29 @@
X == 0x100000000 ? 32 : 0)
/*
直接映射Data Cache16KB大小
每行存放64个字节,共256
组相联映射Data Cache16KB大小
每行存放16个字节1024
*/
#define DCACHE_LINE_PER_SET 256
#define DCACHE_SIZE 16384
#define DCACHE_DATA_PER_LINE 16 // 必须是8字节的倍数
#define DCACHE_DATA_PER_LINE_ADDR_BITS GET_POWER_OF_2(DCACHE_DATA_PER_LINE) // 必须与上面设置一致即64字节需要6位地址
#define DCACHE_SET (DCACHE_SIZE/DCACHE_DATA_PER_LINE)
#define DCACHE_SET (DCACHE_SIZE/DCACHE_DATA_PER_LINE/DCACHE_LINE_PER_SET)
#define DCACHE_SET_ADDR_BITS GET_POWER_OF_2(DCACHE_SET) // 必须与上面设置一致即256行需要8位地址
// Cache行的结构包括Valid、Tag和Data。你所有的状态信息只能记录在Cache行中
// DCache行的结构包括Valid、Tag、Age、Dirty和Data。你所有的状态信息只能记录在Cache行中
struct DCACHE_LineStruct
{
UINT8 Valid;
UINT8 Age;
UINT8 Dirty;
UINT64 Tag;
UINT8 Data[DCACHE_DATA_PER_LINE];
};
struct DCACHE_Set
{
struct DCACHE_LineStruct Line[DCACHE_LINE_PER_SET];
}DCache[DCACHE_SET];
/*
@ -68,60 +76,115 @@ struct DCACHE_LineStruct
*/
void InitDataCache()
{
UINT32 i;
UINT32 i, j;
printf("[%s] +-----------------------------------+\n", __func__);
printf("[%s] | 威震天的Data Cache初始化ing.... |\n", __func__);
printf("[%s] | derder的Data Cache初始化ing.... |\n", __func__);
printf("[%s] +-----------------------------------+\n", __func__);
for (i = 0; i < DCACHE_SET; i++)
DCache[i].Valid = 0;
{
for (j = 0; j < DCACHE_LINE_PER_SET; j++)
{
DCache[i].Line[j].Valid = 0;
DCache[i].Line[j].Dirty = 0;
DCache[i].Line[j].Tag = 0;
DCache[i].Line[j].Age = j;
}
}
}
// 在第Set组中从DCACHE_LINE_PER_SET路中找到需要替换的Cache行
// 如果DCACHE_LINE_PER_SET行中有某行的Valid=0则返回该行行号
// 否则返回Age最大的行的行号
UINT8 GetReplaceLineData(UINT32 Set)
{
int max_index = 0;
int max_age = -1;
for (int i = 0; i < DCACHE_LINE_PER_SET; i++)
{
if (DCache[Set].Line[i].Valid == 0)
return i;
if (DCache[Set].Line[i].Age > max_age)
{
max_index = i;
max_age = DCache[Set].Line[i].Age;
}
}
return max_index;
}
// 更新Age在第Set组中将HitLine指定的Cache行的Age设置为0其他行的Age要相应调整
// 注意要确保DCACHE_LINE_PER_SET行的Age分别为0~DCACHE_LINE_PER_SET-1且唯一
void UpdateAgeData(UINT32 Set, UINT8 HitLine)
{
int HitAge = DCache[Set].Line[HitLine].Age;
DCache[Set].Line[HitLine].Age = 0;
for (int i = 0; i < DCACHE_LINE_PER_SET; i++)
{
if (i != HitLine && DCache[Set].Line[i].Age < HitAge)
DCache[Set].Line[i].Age++;
}
}
/*
从Memory中读入一行数据到Data Cache中
*/
void LoadDataCacheLineFromMemory(UINT64 Address, UINT32 CacheLineAddress)
void LoadDataCacheLineFromMemory(UINT64 Address, UINT32 set, UINT8 line)
{
// 一次性从Memory中将DCACHE_DATA_PER_LINE数据读入某个Data Cache行
// 提供了一个函数一次可以读入8个字节
UINT32 i;
UINT64 ReadData;
UINT64 AlignAddress;
UINT64* pp;
AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1); // 地址必须对齐到DCACHE_DATA_PER_LINE (64)字节边界
pp = (UINT64*)DCache[CacheLineAddress].Data;
for (i = 0; i < DCACHE_DATA_PER_LINE / 8; i++)
{
ReadData = ReadMemory(AlignAddress + 8LL * i);
if (DEBUG)
printf("[%s] Address=%016llX ReadData=%016llX\n", __func__, AlignAddress + 8LL * i, ReadData);
pp[i] = ReadData;
}
// 地址对齐到缓存行边界
const UINT64 AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1);
UINT64* const cache_line_ptr = (UINT64*)DCache[set].Line[line].Data;
if (DEBUG) {
printf("[%s] Loading cache line (set=%u, line=%u) from memory %016llX\n",
__func__, set, line, AlignAddress);
}
// 分8字节块读取
for (UINT32 i = 0; i < DCACHE_DATA_PER_LINE / sizeof(UINT64); i++) {
const UINT64 read_addr = AlignAddress + i * sizeof(UINT64);
const UINT64 data = ReadMemory(read_addr);
cache_line_ptr[i] = data;
if (DEBUG) {
printf(" [LOAD] Address=%016llX -> Data=%016llX\n", read_addr, data);
}
}
}
/*
将Data Cache中的一行数据写入存储器
*/
void StoreDataCacheLineToMemory(UINT64 Address, UINT32 CacheLineAddress)
void StoreDataCacheLineToMemory(UINT64 Address, UINT32 set,UINT8 line)
{
// 一次性将DCACHE_DATA_PER_LINE数据从某个Data Cache行写入Memory中
// 提供了一个函数一次可以写入8个字节
UINT32 i;
UINT64 WriteData;
UINT64 AlignAddress;
UINT64* pp;
AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1); // 地址必须对齐到DCACHE_DATA_PER_LINE (64)字节边界
pp = (UINT64*)DCache[CacheLineAddress].Data;
WriteData = 0;
for (i = 0; i < DCACHE_DATA_PER_LINE / 8; i++)
{
WriteData = pp[i];
WriteMemory(AlignAddress + 8LL * i, WriteData);
if (DEBUG)
printf("[%s] Address=%016llX ReadData=%016llX\n", __func__, AlignAddress + 8LL * i, WriteData);
}
// 地址对齐到缓存行边界
const UINT64 AlignAddress = Address & ~(DCACHE_DATA_PER_LINE - 1);
UINT64* const cache_line_ptr = (UINT64*)DCache[set].Line[line].Data;
if (DEBUG) {
printf("[%s] Storing cache line (set=%u, line=%u) to memory %016llX\n",
__func__, set, line, AlignAddress);
}
// 分8字节块写入
for (UINT32 i = 0; i < DCACHE_DATA_PER_LINE / sizeof(UINT64); i++) {
const UINT64 write_addr = AlignAddress + i * sizeof(UINT64);
const UINT64 data = cache_line_ptr[i];
WriteMemory(write_addr, data);
if (DEBUG) {
printf(" [STORE] Address=%016llX <- Data=%016llX\n", write_addr, data);
}
}
}
/*
@ -134,57 +197,64 @@ void StoreDataCacheLineToMemory(UINT64 Address, UINT32 CacheLineAddress)
*/
UINT8 AccessDataCache(UINT64 Address, UINT8 Operation, UINT8 DataSize, UINT64 StoreValue, UINT64* LoadResult)
{
UINT32 CacheLineAddress;
UINT8 BlockOffset;
UINT64 AddressTag;
UINT8 Block;
UINT32 Set;
UINT64 Tag;
UINT8 MissFlag = 'M';
UINT64 ReadValue;
UINT8 HitLine;
*LoadResult = 0;
/*
* 直接映射中Address被切分为 AddressTagCacheLineAddressBlockOffset
* 组相联映射中Address被切分为 TagSetBlock
*/
// CacheLineAddress Cache的行号在直接映射中就是组号每组1行
CacheLineAddress = (Address >> DCACHE_DATA_PER_LINE_ADDR_BITS) % DCACHE_SET;
BlockOffset = Address % DCACHE_DATA_PER_LINE;
AddressTag = (Address >> DCACHE_DATA_PER_LINE_ADDR_BITS) >> DCACHE_SET_ADDR_BITS; // 地址去掉DCACHE_SET、DCACHE_DATA_PER_LINE剩下的作为Tag。警告不能将整个地址作为Tag
Set = (Address >> DCACHE_DATA_PER_LINE_ADDR_BITS) % DCACHE_SET;
Block = Address % DCACHE_DATA_PER_LINE;
Tag = Address >> (DCACHE_DATA_PER_LINE_ADDR_BITS + DCACHE_SET_ADDR_BITS);
if (DCache[CacheLineAddress].Valid == 1 && DCache[CacheLineAddress].Tag == AddressTag)
// 检查命中
for (int i = 0; i < DCACHE_LINE_PER_SET; i++) {
if (DCache[Set].Line[i].Valid && DCache[Set].Line[i].Tag == Tag) {
HitLine = i;
MissFlag = 'H';
break;
}
}
if(MissFlag=='H')
{
MissFlag = 'H'; // 命中!
if (Operation == 'L') // 读操作
{
ReadValue = 0;
switch (DataSize)
{
case 1: // 1个字节
ReadValue = DCache[CacheLineAddress].Data[BlockOffset + 0];
ReadValue = DCache[Set].Line[HitLine].Data[Block + 0];
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
ReadValue = DCache[CacheLineAddress].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 0];
Block = Block & 0xFE; // 需对齐到2字节边界
ReadValue = DCache[Set].Line[HitLine].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 0];
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
ReadValue = DCache[CacheLineAddress].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 0];
Block = Block & 0xFC; // 需对齐到4字节边界
ReadValue = DCache[Set].Line[HitLine].Data[Block + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 0];
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
ReadValue = DCache[CacheLineAddress].Data[BlockOffset + 7]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 6]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 5]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 4]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[CacheLineAddress].Data[BlockOffset + 0];
Block = Block & 0xF8; // 需对齐到8字节边界
ReadValue = DCache[Set].Line[HitLine].Data[Block + 7]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 6]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 5]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 4]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[HitLine].Data[Block + 0];
break;
}
*LoadResult = ReadValue;
@ -198,105 +268,347 @@ UINT8 AccessDataCache(UINT64 Address, UINT8 Operation, UINT8 DataSize, UINT64 St
switch (DataSize)
{
case 1: // 1个字节
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF;
DCache[Set].Line[HitLine].Data[Block + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF;
Block = Block & 0xFE; // 需对齐到2字节边界
DCache[Set].Line[HitLine].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 1] = StoreValue & 0xFF;
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 3] = StoreValue & 0xFF;
Block = Block & 0xFC; // 需对齐到4字节边界
DCache[Set].Line[HitLine].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 3] = StoreValue & 0xFF;
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 7] = StoreValue & 0xFF;
Block = Block & 0xF8; // 需对齐到8字节边界
DCache[Set].Line[HitLine].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[HitLine].Data[Block + 7] = StoreValue & 0xFF;
break;
}
DCache[Set].Line[HitLine].Dirty = 1;
}
UpdateAgeData(Set, HitLine);
}
else
else if(MissFlag=='M')
{
if (DEBUG)
printf("[%s] Address=%016llX Operation=%c DataSize=%u StoreValue=%016llX\n", __func__, Address, Operation, DataSize, StoreValue);
MissFlag = 'M'; // 不命中
if (DCache[CacheLineAddress].Valid == 1)
{
// 淘汰对应的Cache行如果对应的Cache行有数据需要写回到Memory中
UINT64 OldAddress;
// OldAddress = > (Tag,Set,0000)
OldAddress = ((DCache[CacheLineAddress].Tag << DCACHE_SET_ADDR_BITS) << DCACHE_DATA_PER_LINE_ADDR_BITS) | ((UINT64)CacheLineAddress << DCACHE_DATA_PER_LINE_ADDR_BITS); // 从Tag中恢复旧的地址
StoreDataCacheLineToMemory(OldAddress, CacheLineAddress);
}
// 需要从Memory中读入新的行真实情况下这个LoadCacheLineFromMemory需要很长时间的
LoadDataCacheLineFromMemory(Address, CacheLineAddress);
DCache[CacheLineAddress].Valid = 1;
DCache[CacheLineAddress].Tag = AddressTag;
UINT8 replace_Line = GetReplaceLineData(Set);
if (Operation == 'L') // 读操作
{
// 读操作不需要做事情因为已经MISS了
// 写回脏行
if (DCache[Set].Line[replace_Line].Valid && DCache[Set].Line[replace_Line].Dirty)
{
UINT64 victim_addr = (DCache[Set].Line[replace_Line].Tag <<(DCACHE_DATA_PER_LINE_ADDR_BITS + DCACHE_SET_ADDR_BITS)) |(Set << DCACHE_DATA_PER_LINE_ADDR_BITS);
StoreDataCacheLineToMemory(victim_addr,Set,replace_Line);
}
// 加载新数据
LoadDataCacheLineFromMemory(Address,Set,replace_Line);
DCache[Set].Line[replace_Line].Valid = 1;
DCache[Set].Line[replace_Line].Tag = Tag;
DCache[Set].Line[replace_Line].Dirty = 0;
ReadValue = 0;
switch (DataSize)
{
case 1: // 1个字节
ReadValue = DCache[Set].Line[replace_Line].Data[Block + 0];
break;
case 2: // 2个字节
Block = Block & 0xFE; // 需对齐到2字节边界
ReadValue = DCache[Set].Line[replace_Line].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 0];
break;
case 4: // 4个字节
Block = Block & 0xFC; // 需对齐到4字节边界
ReadValue = DCache[Set].Line[replace_Line].Data[Block + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 0];
break;
case 8: // 8个字节
Block = Block & 0xF8; // 需对齐到8字节边界
ReadValue = DCache[Set].Line[replace_Line].Data[Block + 7]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 6]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 5]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 4]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 3]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 2]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 1]; ReadValue = ReadValue << 8;
ReadValue |= DCache[Set].Line[replace_Line].Data[Block + 0];
break;
}
*LoadResult = ReadValue;
}
else if (Operation == 'S' || Operation == 'M') // 写操作(修改操作在此等价于写操作)
{
// 写回脏行
if (DCache[Set].Line[replace_Line].Valid && DCache[Set].Line[replace_Line].Dirty)
{
UINT64 victim_addr = (DCache[Set].Line[replace_Line].Tag << (DCACHE_DATA_PER_LINE_ADDR_BITS + DCACHE_SET_ADDR_BITS)) | (Set << DCACHE_DATA_PER_LINE_ADDR_BITS);
StoreDataCacheLineToMemory(victim_addr,Set,replace_Line);
}
// 加载新数据
LoadDataCacheLineFromMemory(Address, Set, replace_Line);
DCache[Set].Line[replace_Line].Valid = 1;
DCache[Set].Line[replace_Line].Tag = Tag;
DCache[Set].Line[replace_Line].Dirty = 0;
// 写操作需要将新的StoreValue更新到CacheLine中
switch (DataSize)
{
case 1: // 1个字节
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF;
DCache[Set].Line[replace_Line].Data[Block + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
BlockOffset = BlockOffset & 0xFE; // 需对齐到2字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF;
Block = Block & 0xFE; // 需对齐到2字节边界
DCache[Set].Line[replace_Line].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 1] = StoreValue & 0xFF;
break;
case 4: // 4个字节
BlockOffset = BlockOffset & 0xFC; // 需对齐到4字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 3] = StoreValue & 0xFF;
Block = Block & 0xFC; // 需对齐到4字节边界
DCache[Set].Line[replace_Line].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 3] = StoreValue & 0xFF;
break;
case 8: // 8个字节
BlockOffset = BlockOffset & 0xF8; // 需对齐到8字节边界
DCache[CacheLineAddress].Data[BlockOffset + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[CacheLineAddress].Data[BlockOffset + 7] = StoreValue & 0xFF;
Block = Block & 0xF8; // 需对齐到8字节边界
DCache[Set].Line[replace_Line].Data[Block + 0] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 1] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 2] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 3] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 4] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 5] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 6] = StoreValue & 0xFF; StoreValue = StoreValue >> 8;
DCache[Set].Line[replace_Line].Data[Block + 7] = StoreValue & 0xFF;
break;
}
DCache[Set].Line[replace_Line].Dirty = 1;
UpdateAgeData(Set, replace_Line);
}
UpdateAgeData(Set, replace_Line);
}
return MissFlag;
}
/* 指令Cache实现部分可选实现 */
/*
组相联映射Instruction Cache16KB大小
每行存放16个字节共1024行
*/
#define ICACHE_LINE_PER_SET 64
#define ICACHE_SIZE 16384
#define ICACHE_DATA_PER_LINE 16 // 必须是8字节的倍数
#define ICACHE_DATA_PER_LINE_ADDR_BITS GET_POWER_OF_2(ICACHE_DATA_PER_LINE)
#define ICACHE_SET (ICACHE_SIZE/ICACHE_DATA_PER_LINE/ICACHE_LINE_PER_SET)
#define ICACHE_SET_ADDR_BITS GET_POWER_OF_2(ICACHE_SET)
// ICache行的结构
struct ICACHE_LineStruct
{
UINT8 Valid;
UINT8 Age;
UINT64 Tag;
UINT8 Data[ICACHE_DATA_PER_LINE];
};
struct ICACHE_Set
{
struct ICACHE_LineStruct Line[ICACHE_LINE_PER_SET];
}ICache[ICACHE_SET];
void InitInstCache(void)
{
return;
UINT32 i, j;
printf("[%s] +-----------------------------------+\n", __func__);
printf("[%s] | derder的Inst Cache初始化ing.... |\n", __func__);
printf("[%s] +-----------------------------------+\n", __func__);
for (i = 0; i < ICACHE_SET; i++)
{
for (j = 0; j < ICACHE_LINE_PER_SET; j++)
{
ICache[i].Line[j].Valid = 0;
ICache[i].Line[j].Tag = 0;
ICache[i].Line[j].Age = j;
}
}
}
void LoadInstCacheLineFromMemory(UINT64 Address, UINT32 CacheLineAddress)
//LRU替换策略
UINT8 GetReplaceLineInst(UINT32 Set)
{
return;
int max_index = 0;
int max_age = -1;
for (int i = 0; i < ICACHE_LINE_PER_SET; i++)
{
if (ICache[Set].Line[i].Valid == 0)
return i;
if (ICache[Set].Line[i].Age > max_age)
{
max_index = i;
max_age = ICache[Set].Line[i].Age;
}
}
return max_index;
}
// 更新Age在第Set组中将HitLine指定的Cache行的Age设置为0其他行的Age要相应调整
// 注意要确保ICACHE_LINE_PER_SET行的Age分别为0~ICACHE_LINE_PER_SET-1且唯一
void UpdateAgeInst(UINT32 Set, UINT8 HitLine)
{
int HitAge = ICache[Set].Line[HitLine].Age;
ICache[Set].Line[HitLine].Age = 0;
for (int i = 0; i < ICACHE_LINE_PER_SET; i++)
{
if (i != HitLine && ICache[Set].Line[i].Age < HitAge)
ICache[Set].Line[i].Age++;
}
}
void LoadInstCacheLineFromMemory(UINT64 Address, UINT32 set, UINT8 line)
{
// 一次性从Memory中将ICACHE_DATA_PER_LINE数据读入某个Instruction Cache行
// 提供了一个函数一次可以读入8个字节
// 地址对齐到缓存行边界
const UINT64 AlignAddress = Address & ~(ICACHE_DATA_PER_LINE - 1);
UINT64* const cache_line_ptr = (UINT64*)ICache[set].Line[line].Data;
if (DEBUG) {
printf("[%s] Loading cache line (set=%u, line=%u) from memory %016llX\n",
__func__, set, line, AlignAddress);
}
// 分8字节块读取
for (UINT32 i = 0; i < ICACHE_DATA_PER_LINE / sizeof(UINT64); i++) {
const UINT64 read_addr = AlignAddress + i * sizeof(UINT64);
const UINT64 data = ReadMemory(read_addr);
cache_line_ptr[i] = data;
if (DEBUG) {
printf(" [LOAD] Address=%016llX -> Data=%016llX\n", read_addr, data);
}
}
}
UINT8 AccessInstCache(UINT64 Address, UINT8 Operation, UINT8 InstSize, UINT64* InstResult)
{
// 返回值'M' = Miss'H'=Hit
return 'M';
UINT32 set = (Address >> ICACHE_DATA_PER_LINE_ADDR_BITS) % ICACHE_SET;
UINT8 block = Address % ICACHE_DATA_PER_LINE;
UINT64 tag = Address >> (ICACHE_DATA_PER_LINE_ADDR_BITS + ICACHE_SET_ADDR_BITS);
UINT8 HitLine;
UINT8 MissFlag = 'M';
UINT64 ReadValue = 0;
*InstResult = 0;
// 检查命中
for (int i = 0; i < ICACHE_LINE_PER_SET; i++) {
if (ICache[set].Line[i].Valid && ICache[set].Line[i].Tag == tag) {
HitLine = i;
MissFlag = 'H';
break;
}
}
if (MissFlag == 'H') {
// 命中处理
switch (InstSize) {
case 1: // 8位指令
block = block & 0xFF; // 对齐到1字节边界
ReadValue = ICache[set].Line[HitLine].Data[block + 0];
break;
case 2: // 16位指令
block = block & 0xFE; // 对齐到2字节边界
ReadValue = ICache[set].Line[HitLine].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 0];
break;
case 4: // 32位指令
block = block & 0xFC; // 对齐到4字节边界
ReadValue = ICache[set].Line[HitLine].Data[block + 3]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 2]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 0];
break;
case 8: // 64位指令(如RISC-V的128位指令集扩展)
block = block & 0xF8; // 对齐到8字节边界
ReadValue = ICache[set].Line[HitLine].Data[block + 7]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 6]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 5]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 4]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 3]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 2]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[HitLine].Data[block + 0];
break;
default:
// 不支持的指令长度
return 'M';
}
*InstResult = ReadValue;
UpdateAgeInst(set, HitLine);
}
else
{
// 未命中处理
UINT8 replace_line = GetReplaceLineInst(set);
LoadInstCacheLineFromMemory(Address, set, replace_line);
// 重新读取指令
switch (InstSize) {
case 1:
block = block & 0xFF;
ReadValue = ICache[set].Line[replace_line].Data[block + 0];
break;
case 2:
block = block & 0xFE;
ReadValue = ICache[set].Line[replace_line].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 0];
break;
case 4:
block = block & 0xFC;
ReadValue = ICache[set].Line[replace_line].Data[block + 3]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 2]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 0];
break;
case 8:
block = block & 0xF8;
ReadValue = ICache[set].Line[replace_line].Data[block + 7]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 6]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 5]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 4]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 3]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 2]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 1]; ReadValue = ReadValue << 8;
ReadValue |= ICache[set].Line[replace_line].Data[block + 0];
break;
default:
// 不支持的指令长度
return 'M';
}
*InstResult = ReadValue;
ICache[set].Line[replace_line].Valid = 1;
ICache[set].Line[replace_line].Tag = tag;
UpdateAgeInst(set, replace_line);
}
return MissFlag;
}

View File

@ -8,7 +8,7 @@ LDFLAGS +=
LDLIBS += -lzstd
CPPFLAGS := -O3 -Wall -Wextra -Winline -Winit-self -Wno-sequence-point\
CPPFLAGS := -Ofast -Wall -Wextra -Winline -Winit-self -Wno-sequence-point\
-Wno-unused-function -Wno-inline -fPIC -W -Wcast-qual -Wpointer-arith -Icbsl/include
#CPPFLAGS := -g
@ -19,7 +19,7 @@ objects = Cache.o CacheHelper.o getopt.o cbsl/src/buffer.o cbsl/src/file.o cbsl/
all: $(PROGRAMS)
Cache : $(objects)
gcc $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
icx $(CPPFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
rm -f $(objects)
clean:

0
perflab/matrix/rowcol.c Normal file
View File

Binary file not shown.

0
perflab/poly/poly.c Normal file
View File