原创
SimpleScalar中cache分析
2008-7-19 17:09
3311
2
3
分类:
消费电子
SimpleScalar中cache分析 (2008-06-16 13:37:49)
cache的介绍
首先介绍cache.h文件的内容。
1)cache的替换策略,包括三种LRU,RAMDOM和FIFO
2)整个cache结构的组织:
表示整个cache的是struct cache_t
接下来的次一级的是struct cache_set_t
再接下来次一级的是 struct cache_blk_t
也即:首先由cache块组成cache组,然后由cache组形成整个cache结构
先看cache_t中的定义:
首先是给出了cache中的一些常用参数,这些参数虽然可以通过其他方法获取,不过这儿体现了所谓的面向对象的概念,因为在cache_t的定义中,就使用了函数指针;
而在cache_set中,不难发现,每个组其中就是有若干个块组成的;
3)接下来的就是其他函数了,具体碰到再看。
再介绍cache.c文件的实现
1)先看cache_create函数
1-1)首先是对传入参数的判断,组数不能小于0,而(nsets & (nsets-1)) != 0的作用且是判断nsets必须是2的幂次;
1-2)给cache分配空间,注意,这儿的分配是(nsets-1)个cache_set,这主要是因为在cache_t的定义中已经包含了一个struct cache_set_t sets[1],这也就是SS的高明之处
1-3)开始给cache_t中的一些变量赋值,其中的 CACHE_HIGHLY_ASSOC宏判断构造的cache是不是相联度很大的cache,因为如果相连度大了,那么为了效率考虑,需要采用不同的搜索方法
1-4)给cache中的数据分配空间,其中的(cp->balloc ? (bsize*sizeof(byte_t)) : 0)根据传入的参数,决定是不是要给cache分配存放数据的空间。
现在看其中初始化cache部分的一段代码:
cache_dl1 = cache_create(name, nsets, bsize, FALSE,0, assoc, cache_char2policy(c),dl1_access_fn, 1); //在sim-cache.c文件中
对照参数,可以知道,其中的balloc给出的结果是FALSE,也就是说,SS并不会直接给cache分配存放数据的空间。而在我们一般的理解中,在存储器中会存放数据,在cache中也会存放一部分数据,从而提高数据存取效率,但是SS并没有给cache分配空间,cache拥有的只是一些tag而已,从而也就造成SS的cache行为模型不精确,现在被称之为玩具。
1-5)接下来是按照每个组针对组内的块进行处理,即:for (bindex=0,i=0; i<nsets; i++)
1-5-1)针对其中的三个语句:
cp->sets.way_head = NULL;
cp->sets.way_tail = NULL;
cp->sets.blks = CACHE_BINDEX(cp, cp->data, bindex);
而在cache_t的定义中,我们只能看到有关组的这个定义 struct cache_set_t sets[1];这主要是因为在之前给cache分配空间的时候,采用了这个方式:
cp = …… + (nsets-1)*sizeof(struct cache_set_t));
即把(nsets-1)*sizeof(struct cache_set_t)个空间放在了整个cache空间的结尾,从而在内存空间中,前一部分是一个cache结构,其中有一个cache_set,接下来就是
(nsets-1)个cache_set了,从而可以使用cp->sets,这也就是SS的高明之处。
1-5-2)宏CACHE_BINDEX的作用是去确定每个组内的块的位置.这儿觉得SS弄得有点神秘了,完全可以老实点按层次实现cache,有空看看RSIM和M5怎么实现的。不过我就是很老实实现了cache,理解起来也方便,运行结果也蛮好……
1-5-3)然后就是针对组内的块进行处理: for (j=0; j<assoc; j++) 这儿看blk->user_data = ……calloc(usize, sizeof(byte_t)) : NULL);这句话,看其中的参数usize,也是0!
1-6)好了,cache构造结束了。
2)cache.c文件中最重要的函数应该就是cache_access函数了,现在看这个函数的实现
2-1)首先利用宏得到要访问addr的一些tag和set
然后会进行判断,由于访问的字节是1个、2个、4个、8个,
所以要(nbytes & (nbytes-1)) != 0
而系统在存放数据的时候,是对其存放的地址是对齐的,所以 (addr & (nbytes-1)) != 0
2-2)在cache访问中,有时候为了节约cache访问时间,可以假设本次访问的cache块与上一次访问的cache块是同一个块,所以有if (CACHE_TAGSET(cp, addr) == cp->last_tagset),从而避免更多的查找时间,如果不是的话,会带来一定的开销。如果条件不成立,就接下去寻找cache块。
2-3)先看如果在cache中没有找到的情况,即 cp->misses++那么,根据选择的替换策略,要选择一个被替换出去的cache块,这儿 case LRU:case FIFO:可以看出,把LRU和FIFO的替换看成是一样的,其实不是,而且LRU处理起来还要10多条语句。
好,到此为止,找到了需要被替换出去的块。
用户182952 2009-2-2 23:24