2013-12-11 36 views
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); 
} 

我知道寫回政策之間的差異,通過政策寫。回寫內容寫入緩存然後寫入內存。通過內容寫入同時寫入緩存和內存。

但是,我不知道如何實現這一點。感謝你們的幫助,我真的很感激。

回答

0

你需要跟蹤三種狀態中緩存的每一行:

  • 無效:在這一行緩存沒有數據。
  • 有效,清潔,又名獨家:數據緩存在這一行;自上次寫回以來未由處理器修改
  • 有效,髒,又名修改:數據緩存在此行;處理器自上次回寫以來修改了

根據經常遇到的MESI protocol,這些對應於「I - 無效」,「E - 獨佔」和「M-修改」狀態。在這個模擬中沒有共享狀態,因爲你只考慮單個處理器,所以這真是一個「MEI」協議。

當您分配一行時,您需要選擇將其分配到緩存中的位置。如果您要更換的線路處於M狀態(已修改/有效,髒),則需要爲該線路發送受害者寫回,以便您可以安全地分配新線路。如果它處於E狀態,則可以放棄該線路而不發送受害者。

如果您爲CPU讀取分配新行,則新行進入E狀態(獨佔/有效,清除)。如果您分配一條線來響應CPU寫入,則新行將轉到M狀態(修改/有效,髒)。

因此,在您的代碼中,您需要跟蹤每行的M/E/I狀態,並處理在重新分配線路以響應未命中緩存的CPU請求時發生的轉換。另外,根據您的替換策略(LRU,隨機,FIFO),您可能需要爲每個集合追蹤一些額外的狀態,假設集合關聯結構。

你有相當多的代碼在那裏 - 真的有很多東西需要通過。但是,鑑於緩存協議以及需要跟蹤的狀態,您應該能夠使用鉛筆和紙張來編寫,從CPU中讀取和寫入的順序應該變成緩存行分配和受害者回寫。一旦你手動完成了它,你可能會更清楚地知道如何在軟件中實現狀態轉換。

如果您在製作該翻譯時遇到問題,那麼您應該可以在此處提供更簡潔的問題。

祝你好運。

+0

我會讀這個。非常感謝!好像我的工作爲我剪掉了。嘆。我一定會在這裏回答更多/更好的問題。 – user3084848

+0

我認爲,如果你把它固定在一些問題紙和鉛筆上,那麼編碼過程確實不是那麼糟糕。 「檢查命中:在讀命中時,只更新LRU,在寫命中更新LRU和標記行Modified時,首先驅逐某物(如果被驅逐者被修改,則發送受害者),然後分配新行發送讀取請求,如果CPU請求是讀取請求,則標記爲E;如果是寫入,請標記爲M.這是該計劃的精髓所在。 –