如何编写具有回写策略的缓存模拟器,该模式使用直写实现?

时间:2013-12-11 00:35:55

标签: c++ qt caching

我为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 :(得分:0)

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

  • 无效:此行中没有缓存数据。
  • 有效,干净,又名独家:此行缓存的数据;自上次回写后未被处理器修改
  • 有效,脏,又名修改:此行缓存的数据;自上次回写后由处理器修改

就常见的MESI protocol而言,这些对应于“I - 无效”,“E - 独有”和“M - 修改”状态。在这个模拟中没有共享状态,因为你只考虑一个处理器,所以这真的是一个“MEI”协议。

分配一行时,您需要选择在缓存中分配的位置。如果要替换的行处于M状态(已修改/有效,脏),则需要为该行发送受害者写回,以便您可以安全地分配新行。如果它处于E状态,你可以在不派遣受害者的情况下丢弃该线路。

如果为响应CPU读取而分配新行,则新行将进入E状态(Exclusive / Valid,clean)。如果为响应CPU写入而分配一行,则新行将进入M状态(已修改/有效,脏)。

因此,在您的代码中,您需要跟踪每一行的M / E / I状态,并处理在重新分配一行以响应错过缓存的CPU请求时发生的转换。此外,根据您的替换策略(LRU,随机,FIFO),您可能需要跟踪每个集合的一些额外状态,假设有一个组关联结构。

你有相当多的代码 - 真的有点太多了。但是,考虑到缓存协议以及您需要跟踪的状态,您应该能够使用铅笔和纸张计算来自CPU的读取和写入序列在缓存行方面应该变成什么分配和受害者回写。一旦你手工完成它,你可能会更清楚如何在软件中实现状态转换。

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

祝你好运。