L1P(direct mapped Cache)
C64x的L1P是直接映射cache(direct mapped),其为Read Allocate,即只在读操作时才进行cache处理(对于L1P,很好理解,因为不可能产生改变程序的代码)。
从上表可以看出,C64xDSP的一些基本参数。其line size为32字节,而L1P大小为16k字节,故L1P中包含512条32字节的line frame,每条line frame总是映射到内存中的固定地址。这就如下图所示(该图表示了miss 与hit的计算方法):
内存中的地址0000h到0019h总是映射到0 line frame,而3FE0h到3FFFh总是映射到511line frame,而由于cache用尽了,所以地址4000h到4019又必须映射到0 line frame。注意对于C64x来说,这样的L1P中的一条line frame也就正好包含了一个取址包。
上图中的V bit是一条line frame的有效态位,V=0表示Cache中相应的line frame无效,反之则表示有效。
下图为程序地址在Cache控制器内的结构:
如上图所示,当CPU要读某个地址处的指令时,该地址在Cache中被分为3个部分。其中5到13位表示了该地址所映射到的set(对于直接映射Cache,set=line frame号)。Cache控制器会检查有效位和Tag(14到31位)。所作的具体操作见Figure1-5。如果最后结果为0,则read miss。这时控制器会从内存中取出该指令包,并放入L1P相应line frame中,tag被设定,并且V=1,同时该指令包也会被送入CPU,此时该过程结束。
注意,利用Cache最重要的是保证只要一条line frame的内容还有用,就不要取代它。
解决Cache miss问题的一种方案就是建立包含多条line frame的set。这样内存中多条具有相同Set值的地址下的指令就可以同时存在于Cache中而不会发生冲突,从而使命中率提高。
L1D(2-way set-associative cache)
C64x的L1D是两路set相关的cache,下表为其基本参数:
2-way set-associative cache的每个set包含两条line frame,一条在way 0,另一条在way 1。内存中的每条line实际上还是映射到cache中的一个set中,但可以使way0的line frame,也可以使way1的line frame。
从上表中可以看出C64x的L1D每条line frame为64字节。并且是Read Allocate,Write-back的,这里对此先不做解释。上表还说明当write miss时,L1D通过4x64-bit的write buffer向下级存储器写入数据。
下图为set-associative cache的结构图,图中说明了其hit和miss的确定方法,这其实和direct mapped cache差不多,只是有两次tag比较,来确定需要的数据保存在那一路。
当两路中都不包含所需数据时,就要从内存中取了,而取到的数据应该放到哪一路呢?这就需要LRU(least-recently-used)位了。Cache中每一个set都有一个LRU位,当LRU=0,则数据被映射到way0的line frame中,如果LRU=1,则数据被映射到way1的line frame中。每次访问到某个set中的某路line frame时,如果hit,LRU都会改变一次,来保证most-recently-used位不被取代掉。而当每次某个set miss时LRU都被重新设置为新读入数据的way。而上述机制由程序的局部性决定。注意LRU只在miss发生时被参考,但是却在每次line way访问时(不论miss或hit)都要作相应调整。
前面说到过,L1D是Read Allocate cache,这的意思是cache中的一条line frame只在read miss发生时才会作相应的重新映射操作,而write miss时,只是将数据通过write buffer写入下一级内存中(L2 SDRAM或者外部存储器),这个write buffer包括4条64bit的通路。
同时,因为L1D是Write-back cache,所以当write hit发生时,数据只是写入cache,而不会立即写入对应的下级内存。这样,为了在以后能正确地将修改过的数据写回下级内存,就必须知道cache中的哪条line frame被CPU修改过。所以cache中每条line frame都有一个dirty bit(D)与其相关。Dirty bit的初始值为0,当CPU修改过其数据,则被置位1。当某一条line frame以为read miss而需要被替代时,则会检测其dirty bit,如果它是一条dirty line(D=1),则其内容会先写回下级内存,再被替代;否则(D=0),它的内容会被忽略。这种写回操作也能由程序向cache 控制器发送write back命令来实现。
L2 Cache
L1和L2 Cache像这样协同工作:当某个地址在L1中miss,则到L2中查找;L2使用相同的方法检测是否所需地址在L2中。反之,如果L1 hit,则接下来的操作直接在L1中进行,与L2无关。
上表给出了C6000 DSP的L2 Cache 属性,其L2 存储空间可以分为可寻址的片上空间(L2 SRAM)和cache(L2Cache)两部分。与L1 Cache的read-allocate不同,L2 Cache是Read and write allocate。L2 cache只用来cache外部存储地址,而L1 Cache用来cache L2 SRAM和外部存储地址。
下面以CPU要求读取一个可缓冲的外部存储地址为例,说明L2 Cache工作过程。
1、 在L1(L1P或L1D)中miss,并且在L2 Cache中miss。这时,外存中相应的line会被调入L2 cache,再由LRU bits决定被放置在哪条line frame。如果该line frame 包含dirty data,则在被新的line取代时,会将其数据写回外存中相应位置。(如果该line frame也在L1中,则在L2 cache写回外存前要先由L1写回L2 cache,这一操作叫保持 cache 一致性)接着,这一line在被写为L1的形式,并交至L1 cache。L1 cache在将其保存在其cache中,并交由CPU处理。注意,如果L1中放置该line的frame line 含有dirty data,同样要先写回L2 cache。
2、 如果该地址在L2 Cache 中hit。则相应line直接调入L1中。
前面说过,L2 Cache是Read and write allocate,这是指当CPU要向外存中写数据时,如果L1和L2 cache miss,则会像读时那样,把对应位置的line调入L2 cache的line frame中,而这时所作的操作也与读时类似,如果含有dirty data,则应先写回外存。但应注意,这一line是不会出现在L1中的,因为L1 Cache只是read-allocate。