2012-03-15 164 views
0

我正在寻找在cache.c文件LRU代码,但是这是唯一的代码,我可以找到:SimpleScalar的缓存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算法。所以如果我错过了一些东西,你能指点我的方向还是给我一些提示?

非常感谢。

+0

我了解情况:您正在阅读某些代码,其中一些代码似乎已丢失。但我不明白这个问题是什么。你为什么不问代码的作者呢? – 2012-03-15 22:20:12

回答

1

我碰巧在使用Simplescalar之前。实际上,Simplescalar已经实现了真正的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插入策略)的行为。

2

很难说没有看到代码的其余部分,但我看到两个明显的可能性在这里。其中之一是,正如你所建议的那样,LRU管理代码缺失,可能是因为编辑错误。

然而,我认为可能性更大的可能性是,对于代码的这个特定部分,LRU和FIFO管理做同样的事情,所以它们取决于C开关的“通过”声明在这种情况下为两者执行相同的代码(但其他代码可能会为其他策略执行)。

+0

这更像是第二种情况,我应该检查其余的代码。非常感谢你。 – astr627 2012-03-16 02:16:12

+0

有一个约定(我认为很好)在空'case'标签(本例中为'LRU')之后放置'/ * fall-through * /'注释。它使意图清楚,即作者没有忘记一个'break'声明。 – gcbenison 2012-05-07 15:01:07

0

看起来代码的其他部分按照FIFO或LRU顺序排列cp->sets中的条目,使得无论替换策略如何,要替换的集合始终为cp->sets[set].way_tail。这两个替换策略仅在使用或添加行时有所不同,而不是在替换行时使用。