mortbopet / Ripes

A graphical processor simulator and assembly editor for the RISC-V ISA
https://ripes.me/
MIT License
2.49k stars 270 forks source link

Add Cache Replacement Policy #335

Open tinhanho opened 8 months ago

tinhanho commented 8 months ago

About Issue #334.

I think that we could add a FIFO mechanism to the cache policy.

A new replacement policy, FIFO (First In, First Out), has been added to the existing enumeration. Additionally, a new counter has been introduced in the cachesim.h file. This counter plays a crucial role in cyclically determining which cache entry should be evicted.

// line 19 in cachesim.h
enum ReplPolicy { Random, LRU, FIFO}; 

The code below handles the eviction process based on the FIFO replacement policy.

//line 124 in cachesim.cpp
else if (m_replPolicy == ReplPolicy::FIFO){
    ew.first = CacheSim::counter;
    ew.second = &cacheLine[ew.first];
    CacheSim::counter += 1;
CacheSim::counter %= getWays();
}
mortbopet commented 7 months ago

Thank you for looking into adding a new cache replacement policy!

A few comments:

tinhanho commented 7 months ago

Hi, @mortbopet.

Thanks for the reply. I had already renamed the counter and tried my best to follow the coding style. If there are any problem still, please let me know.

As for third comments, I rework all the framework to implement visualizing the FIFO bit. Now, there is no need about fifoIndexCounter. Instead, boolean fifoflag is presented. This flag is set under two circumstances,

  1. When an invalid entry is selected, we set the fifoflag.
  2. When all the entries are full and cache miss occurs, we need to choose a entry to evicted and we set the fifoflag.

When this flag is set, we shall add 1 to fifo bits if entry is valid. In this way, we'll find that when fifo bits equal to the way of the cache, that entry should be evicted.

//Line 167 in cachesim.cpp
if (it != cacheLine.end()) {
  ew.first = it->first;
  ew.second = &it->second;
  m_fifoflag = true;
}
if (ew.second == nullptr) {
  for (auto &way : cacheLine) {
    if (static_cast<long>(way.second.fifo) == getWays()){
      ew.first = way.first;
      ew.second = &way.second;
      m_fifoflag = true;
      break;
    }
  }
}

Furthermore, the undo part needs to be taken into consideration as well. Under the circumstance of doing undo, if miss occurs and the policy is FIFO, we set the fifoflag again and we need to restore the oldway.

//Line 442 in cachesim.cpp
if (!trace.transaction.isHit && getReplacementPolicy() == ReplPolicy::FIFO) {
  m_fifoflag = true;
  way = oldWay;
}
//Line 82 in cachesim.cpp
if (getReplacementPolicy() == ReplPolicy::FIFO) {
  for(auto &set : line){
    if(set.second.valid && m_fifoflag) set.second.fifo--;
  }
  m_fifoflag = false;
  line[wayIdx].fifo = oldWay.fifo;
}

Demo video here, https://github.com/mortbopet/Ripes/assets/67796326/b67aab30-17ee-4b3c-8fa7-ba56f905a282

Demo video demostrates the assembly code below,

lw a1 0(x0)
lw a1 512(x0)
lw a1 0(x0)
lw a1 512(x0)
lw a1 512(x0)
lw a1 1024(x0)
lw a1 1024(x0)
lw a1 1024(x0)
lw a1 1024(x0)
lw a1 0(x0)
lw a1 0(x0)
lw a1 0(x0)
lw a1 1536(x0)
lw a1 1536(x0)
lw a1 1536(x0)
addi a0 x0 1024
addi a0 a0 1024
lw a1 0(a0)

Full code is in the branch FIFO of my fork, https://github.com/tinhanho/Ripes/commit/6772d1abec6a6bff5e0e40374fd5922c67e3a427

Let me know if there are any problems of my think and implement.

mortbopet commented 7 months ago

@tinhanho thank you for the further work - if you update the branch of this PR, it'll be a bit easier for me to review your code.

tinhanho commented 7 months ago

@mortbopet I have already updated the branch 😉