ARM-V8学习-cache的结构设计

Cache的结构设计(VIVT-PIPT-VIPT)

发现一篇讲cache特别好的文章,在看uboot代码时看到cache的开关总是和mmu有一些联系,直到看到这篇文章,明白了其中的一些联系。文中深入的对cache的工作机制进行分析,首先明确在CPU是如何使用Cache的,Cache和主存到底是如何通过虚拟地址和物理地址进行映射的,映射的过程中是否存在问题等等。没有特殊说明,Cache中的数据包括指令和被指令操作的数据。

1、Cache的工作方式

从处理器的角度分析一下Cache在PE工作中的作用。处理器工作的时候,访问主存使用的是虚拟地址的编码方式。前文中也已经讲过,cache中的数据其实就是主存中数据的副本。主存中的数据编码方式是以字节为单位,而Cache中的数据编址是以Cache Line(一般为64字节)为单位,这样Cache和内存中的数据进行映射就需要一个过程,又因为作为数据的访问者CPU使用虚拟地址进行数据的访问,那么自然这个过程的参与者就变成了PE、MMU、Cache、主存,如何通过虚拟地址进行串联的过程,这里通过一个经典的Cache架构加以说明,如下图所示。

对上面这个架构做一下拆解,其实就是一个寻找TAG、Index、Offset之旅:

  • S-1 任何时候,CPU在访问主存的时候永远是使用虚拟地址的。内存管理是个很复杂的课题,后续单独进行讨论。而支持通过虚拟地址方式访问是现代处理器的基本能力。可以这么理解虚拟地址给软件用的,物理地址是给硬件用的,虚拟地址和物理地址之间有一个映射的关系,不过这个映射是以页或者块为单位的,最少小映射颗粒度是4k空间。
  • 处理器在访问存储器时,会把虚拟地址同时传递给 TLB (S-2)和Cache高速缓存(S-6)。TLB (Translation Lookaside Buffer)是一个用于存储虚拟地址到物理地址转换的小缓存,处理器先使用有效页帧号(Effective Page Number, EPN)在 TLB 中查找最终的实际页帧号(Real Page Number, RPN)。假设发生 TLB 命中(TLB hit)(S-3),就会很快获得合适的 RPN ,并得到相应的物理地址(Physical Address , PA)。到这里简单回顾下寻址一个cache line的3要素:TAG、Index、Offset。既然,我们已经锁定了物理地址,那么至少TAG到这里我们是可以确定了的。
  • 同时,处理器通过高速缓存编码地址的索引(index )域可以很快找到相应的高速缓存行对应的组Set(S-3)。但是这里的高速缓存行的数据不一定是处理器所需要的,因此有必要进行一些检查,将高速缓存行中存放的标记域TAG和通过MMU 转换得到的物理地址的标记域进行比较。如果相同并且状态位匹配,就会发生高速缓存命中(cache hit)(S-8),处理器通过字节选择与对齐(byte select and align)部件,就可以获取所需要的数据。这个过程就是把S-6过来的Index分发给所有的Way的Set然后比较TAG,再比较TAG的有效位,如果都匹配说明数据在cache且有效。就可以把cache line上的数据整体取出来了。
  • 此时通过TAG和Index已经取出了Cache Line的数据,但是CPU其实想要的也许就是其中的几个字节的数据,那么就通过S-9传过来的Offset做更精细化的自己寻址就可以了。到这里,就顺利地给CPU返回它想要的数据了。

例外的情况:

  • 如果发生高速缓存未命中(cache miss),处理器需要用物理地址进一步访问主存储器来获得最终数据,数据也会填充到相应的高速缓存行中。也就是经过TAG和Index进行比较判断出,想要的数据没有在Cache中,因为此时系统已经了主存数据所在的物理地址,直接按照既定的替换策略,将数据经过L3-Cache->L2-Cache->L1 Cache(S-7)加载到Cache,然后重复过程上述(3)(4)也达到了CPU的目的。
  • 如果其间发生 TLB 未命中(TLB miss)(S-4),将会带来一系列严重的系统惩罚,处理器需要查询页表。那么此时,MMU就要做虚拟地址和物理地址映射,其实就是到页表中找到对应分配好的页中数据的物理地址(之前没有分配的话,说明想要的数据主存中也有没有就要抛出异常先将数据从系统外部加载到主存),然后将这个物理地址和数据经过S-5和(5)中的过程,然后就让CPU得到它想要的数据。

上面这个过程,大家先关注总结2个点:

  • TAG 在这里是是通过物理地址算出来的。
  • Index是通过虚拟地址算出来的。
  • 通过虚拟Index和物理TAG的形式我们寻址到了Cache Line。这就是缓存实际的组织形式之一VIPT,实际上Cache还有其他的组织形式,一个CPU中不同level的cache可以支持不同的组织形式。本文下面的章节,就来介绍Cache的类型。

2、Cache类型

这里结合一款具体的ARM处理器架构来介绍一下Cache的分类,如下图所示。

通过Cortex-A710的block图,可以清晰看到,ARM设计了两级Cache结构,其中L1层还对Cache做了细分(指令和数据分离)。下面看一下这两级Cache的具体特征,如下图所示。

Cortex-A710的Cache的Feature可以简单总结一下:

  • Cache Size 为 32KB、64KB、256KB、512KB;
  • Cache Line length都为64bytes;
  • 都是组多路组关联的方式(4 or 8 ways set associative);
  • Index和Tag的类型分别是VIPT和PIPT;
  • 替换策略为LRU 或者 动态地调整替换策略。

Cache的详细结构

Feature中的前三点在前面的文章已经充分讨论过了,替换的策略后续讨论一下,这里会重点讨论一下Index和Tag的类型,借此也讨论清楚Cache的结构。前面讲述VIPT类型的Cache的工作流程,这里们看到ARM-Core中的cache还有另外一种组织形式PIPT,要讨论讲清楚这两种Cache类型,还是要结合的具体结构,如下图所示。

这是ARM手册中一个比较经典的例子(手册中的例子貌似有点错误,这里也希望大家一起思考指正),64KB-L1 data cache,分成4路,采用组关联的方式,每行的cache line的长度或者size为64字节。

  • 高速缓存的总大小为 64KB ,并且是 4 路的,所以每一路的大小为 16KB(way_size = 64KB/ 4 = 16KB) 。
  • 高速缓存行的大小为 64 字节,所以每一路包含的高速缓存行数量如下num_cache_line = 16KB/64B = 256。

Offset

这里offset为地址编码的Bit[0:5]总计6位,其中Bit[2:5]共计4位可以用来寻址0~15共计16个字,Bit[0:1]可以对字中的字节进行寻址,最终实现的效果就是可以实现Cache Line中的64字节寻址。

Index

Bit[6:13] 共8位用于在索引域中选择每一路上的高速缓存行,也就是Index可以实现在一路cache中进行256行的寻址。因为cache采用的是组关联的方式,也就是说这里Index可以实现这4路256组的寻址。

TAG

Bit[14:43]共30位用作标记域。

V & D

当通过主存的地址编码确认了Offset、Index、TAG之后就可以在cache中锁定了CPU想要的数据了,但是此时还不是胜利的时候,还需要检查数据所在的Cache Line的两个标志位:V,D。这两个标志位的作用,我们直接引用手册的描述:

  • Valid bits to indicate whether the line exists in the cache, that is whether the tag is valid. Valid bits can also be state bits for the MESI state if the cache is coherent across multiple cores.
  • Dirty data bits to indicate whether the data in the cache line is not coherent with external memory.

上图虽然详细的描述了cache的结构,但是还是有一个点没有表达清楚,就是CPU使用的虚拟地址采用什么样的方式和cache中的TAG、Index做映射,比如例子中使用的是VIPT(使用虚拟地址的索引域和物理地址的标记域)的方式,下面继续讨论其他的方式。不同的映射方式对应的CPU-Core内部硬件电路(CPU的架构)也是不同的。以ARM为例,从早期到现在共使用了三种映射技术:虚拟高速缓存(VIVT)、物理标记的虚拟高速缓存(VIPT)、物理高速缓存(PIPT)。

VIVT

VIVT(Virtual Index Virtual Tag) 使⽤虚拟地址的索引域和虚拟地址的标记域,相当于虚拟⾼速缓存,早期的处理器采用的就是这种方式。这种方式就是把PE传递过来的虚拟地址直接切成三段分别代表TAG、Index、Offset(如下图),然后对Cache进行寻址,命中则直接返回数据,失败则需要将虚拟地址转换成物理地址,然后寻址主存储器然后将数据加载到Cache再返回给PE。

一个VA的地址可以映射任意的物理地址,VIVT的cache不需要经过译码,直接被拆分成TAG(V)和Index(V),以页为4K为例,无论怎么切分就是上述三种场景,这样设计的好处是架构简单,会引入两个问题:歧义和别名。

(1)歧义(ambiguity)

当不同的数据在高速缓存中有相同的index、tag

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

嵌入式学习专栏 文章被收录于专栏

7年嵌入式软、硬件开发经验,分享嵌入式软件开发相关资料,简历、工作、技术支持!!!

全部评论

相关推荐

3 4 评论
分享
牛客网
牛客企业服务