首页 文章

如何编写具有回写策略的缓存模拟器,该策略来自通过写入实现的? [重复]

提问于
浏览
1

这个问题与以下内容完全相同:

我已经为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 回答

  • 0

    您需要跟踪缓存中每行的三种状态:

    • 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的读写顺序应该在缓存行分配和受害者写回方面变成什么样 . 一旦你手工完成它,你可能会更清楚如何在软件中实现状态转换 .

    如果您在制作翻译时遇到困难,那么您应该能够在此处提供更简洁的问题 .

    祝好运 .

相关问题