这个问题与以下内容完全相同:
我已经为2路组关联缓存模拟器编写了代码 . 模拟器从文本文件中获取输入,如下所示:
输入文件:
read 0x04000000
write 0x02000000
read 0x04000008
从这里有一个方法,它给它缓存大小和块大小 . 当前实现的方式是使用直写缓存策略 . 我想用回写策略代替它 .
这是我的头文件的相关部分:
class Cache
{
private:
QStringList m_Instructions;
QList<QString> m_Output;
public:
Cache(QString);
~Cache();
void TwoWaySA(int, int);
void print(QString);
};
以下是该方法的代码:
void Cache::TwoWaySA(int cacheSize, int blockSize)
{
// Determine Properties
int blockCount = cacheSize/blockSize;
int numWays = 2;
int numSets = blockCount/numWays;
int cacheMemory[numSets][numWays+1];
// Reset Cache_Memory for New Cache Specs
for(int i = 0; i < numSets; i++)
{
cacheMemory[i][0] = i;
for(int j = 0; j <= numWays; j++)
{
cacheMemory[i][1] = 0;
cacheMemory[i][2] = 0;
}
}
float hit = 0;
int bytesMtoC = 0;
int bytesCtoM = 0;
for(int i = 0; i < m_Instructions.length(); i++)
{
QString instruction = m_Instructions[i];
QString memAddress_Text = instruction.split(" ")[1];
bool ok;
int memAddress_Num = memAddress_Text.toInt(&ok, 16);
int set = (memAddress_Num/blockSize)%numSets;
int tag = memAddress_Num/blockSize/numSets;
if(m_Instructions[i].contains("read"))
{
int flag = 0;
for(int i = 1; i <= numWays; i++)
{
if(cacheMemory[set][i] == tag)
{
hit++;
flag = 1;
}
}
if(flag != 1)
{
// LRU?
bytesMtoC += blockSize;
cacheMemory[set][1] = tag;
}
}
if(m_Instructions[i].contains("write"))
{
int flag = 0;
for(int i = 1; i <= numWays; i++)
{
if(cacheMemory[set][i] == tag)
{
hit++;
flag = 1;
bytesCtoM += blockSize;
}
}
if(flag != 1)
{
// LRU?
cacheMemory[set][2] = tag;
bytesMtoC += blockSize;
bytesCtoM += blockSize;
}
}
}
float hitRatio = hit/m_Instructions.length();
QString output;
QString cache_size = QString::number(cacheSize);
QString block_size = QString::number(blockSize);
QString cache_type = "2W";
QString hit_ratio = QString::number(hitRatio, 'g', 2);
QString memTOcache = QString::number(bytesMtoC);
QString cacheTOmem = QString::number(bytesCtoM);
QString comparisons = "2";
output.append(cache_size).append(" ").append(block_size).append(" ")
.append(cache_type).append(" ").append(hit_ratio).append(" ")
.append(memTOcache).append(" ").append(cacheTOmem).append(" ")
.append(comparisons);
m_Output.append(output);
}
我知道回写策略和写入策略之间的区别 . 写回内容然后写入缓存然后写入内存 . 通过内容写入同时写入缓存和内存 .
但是,我不知道如何实现这一点 . 感谢您的帮助,我真的很感激 .
1 回答
您需要跟踪缓存中每行的三种状态:
Invalid :此行没有缓存数据 .
Valid, clean ,又名独家:此行缓存的数据;自上次回写后未被处理器修改
Valid, dirty ,又名修改:此行缓存的数据;自上次回写以来由处理器修改
就常见的MESI protocol而言,这些对应于"I - Invalid","E - Exclusive"和"M - Modified"状态 . 此模拟中没有共享状态,因为您只考虑单个处理器,所以实际上这是一个"MEI"协议 .
分配行时,需要选择在缓存中分配行的位置 . 如果要替换的行处于M状态(已修改/有效,脏),则需要为该行发送受害者写回,以便您可以安全地分配新行 . 如果它处于E状态,您可以在不发送受害者的情况下丢弃该线路 .
如果为响应CPU读取而分配新行,则新行将进入E状态(Exclusive / Valid,clean) . 如果为响应CPU写入而分配一行,则新行将进入M状态(已修改/有效,脏) .
因此,在您的代码中,您需要跟踪每一行的M / E / I状态,并处理在重新分配一行以响应错过高速缓存的CPU请求时发生的转换 . 此外,根据您的替换策略(LRU,随机,FIFO),您可能需要跟踪每个集合的一些附加状态,假设有一个组关联结构 .
你有相当多的代码 - 真的需要花费很多 . 但是,考虑到缓存协议以及您需要跟踪的状态,您应该能够使用铅笔和纸来解决CPU的读写顺序应该在缓存行分配和受害者写回方面变成什么样 . 一旦你手工完成它,你可能会更清楚如何在软件中实现状态转换 .
如果您在制作翻译时遇到困难,那么您应该能够在此处提供更简洁的问题 .
祝好运 .