Files
csapp2025/cachelab/Cache.c
2025-04-24 22:32:48 +08:00

615 lines
22 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///
// 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大小
每行存放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/DCACHE_LINE_PER_SET)
#define DCACHE_SET_ADDR_BITS GET_POWER_OF_2(DCACHE_SET) // 必须与上面设置一致即256行需要8位地址
// 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];
/*
DCache初始化代码一般需要把DCache的有效位Valid设置为0
模拟器启动时会调用此InitDataCache函数
*/
void InitDataCache()
{
UINT32 i, j;
printf("[%s] +-----------------------------------+\n", __func__);
printf("[%s] | derder的Data Cache初始化ing.... |\n", __func__);
printf("[%s] +-----------------------------------+\n", __func__);
for (i = 0; i < DCACHE_SET; i++)
{
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 set, UINT8 line)
{
// 一次性从Memory中将DCACHE_DATA_PER_LINE数据读入某个Data Cache行
// 提供了一个函数一次可以读入8个字节
// 地址对齐到缓存行边界
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 set,UINT8 line)
{
// 一次性将DCACHE_DATA_PER_LINE数据从某个Data Cache行写入Memory中
// 提供了一个函数一次可以写入8个字节
// 地址对齐到缓存行边界
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);
}
}
}
/*
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 Block;
UINT32 Set;
UINT64 Tag;
UINT8 MissFlag = 'M';
UINT64 ReadValue;
UINT8 HitLine;
*LoadResult = 0;
/*
* 组相联映射中Address被切分为 TagSetBlock
*/
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);
// 检查命中
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')
{
if (Operation == 'L') // 读操作
{
ReadValue = 0;
switch (DataSize)
{
case 1: // 1个字节
ReadValue = DCache[Set].Line[HitLine].Data[Block + 0];
break;
case 2: // 2个字节
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个字节
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个字节
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;
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[Set].Line[HitLine].Data[Block + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
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个字节
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个字节
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 if(MissFlag=='M')
{
if (DEBUG)
printf("[%s] Address=%016llX Operation=%c DataSize=%u StoreValue=%016llX\n", __func__, Address, Operation, DataSize, StoreValue);
UINT8 replace_Line = GetReplaceLineData(Set);
if (Operation == 'L') // 读操作
{
// 写回脏行
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[Set].Line[replace_Line].Data[Block + 0] = StoreValue & 0xFF;
break;
case 2: // 2个字节
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个字节
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个字节
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;
}
/*
组相联映射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)
{
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;
}
}
}
//LRU替换策略
UINT8 GetReplaceLineInst(UINT32 Set)
{
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)
{
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;
}