我正在cache.c文件中查找LRU代码,但这是我能找到的唯一代码:

switch (cp->policy) {

  case LRU:

  case FIFO:

    repl = cp->sets[set].way_tail;
    update_way_list(&cp->sets[set], repl, Head);
    break;

对我来说,这看起来像是丢失了LRU代码,我想应该把LRU算法放在冒号后面。所以如果我漏掉了什么,你能告诉我正确的方向还是给我一些提示?
非常感谢你。

最佳答案

我以前碰巧用过SimpleScar。实际上,simplescaler已经实现了真正的LRU算法。
下面的注释清楚地描述了函数update_way_list。

/* insert BLK into the order way chain in SET at location WHERE */
static void
update_way_list(struct cache_set_t *set,        /* set contained way chain */
                struct cache_blk_t *blk,        /* block to insert */
                enum list_loc_t where)          /* insert location */

您引用的代码来自访问缓存时的“缓存未命中”情况:
  switch (cp->policy) {
  case LRU:
  case FIFO:
    repl = cp->sets[set].way_tail;
    update_way_list(&cp->sets[set], repl, Head);
    break;
  }

在这里,选择最后一种方式作为牺牲品,并将其移动到集的头部。
稍后,被替换的块数据被写回,然后受害者被新的数据块替换。
区分LRU和FIFO最重要的部分来自“缓存命中”情况:
  /* if LRU replacement and this is not the first element of list, reorder */
  if (blk->way_prev && cp->policy == LRU)
    {
      /* move this block to head of the way (MRU) list */
      update_way_list(&cp->sets[set], blk, Head);
    }

因此,集合中的方法遵循年龄的递减顺序:集合的头部是MRU(最近使用的)块,而尾部是LRU块。
这正是真正的LRU算法:当缓存命中时,命中块被提升为MRU方式,同时保持其他块的顺序。当缓存未命中时,将LRU块选为牺牲品,并以MRU方式放置新块。如果我们删除之前的“缓存命中”代码,则不会记录访问历史,并且集合中的方式遵循访问顺序,从而提供FIFO行为。如果我们把线移走
    update_way_list(&cp->sets[set], repl, Head);

在前面的“缓存未命中”代码中,新块将以LRU方式放置,从而提供LIP(LRU插入策略)行为。

关于c - Simplescalar缓存LRU实现,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9728907/

10-11 19:39