我只是想澄清一下这个概念,并且可以找到足够详细的答案,这些答案可以说明一切在硬件中的实际效果。请提供任何相关细节。
对于VIPT缓存,内存请求将并行发送到TLB和缓存。
从TLB我们得到了经过翻译的物理地址。 从缓存索引中我们得到一个标签列表(例如,来自属于一个集合的所有缓存行)。
然后将翻译的TLB地址与标签列表匹配以找到候选者。
有人可以说“实际上”如何实现这一点以及Cache模块和之间的连接。 TLB(MMU)模块?
我知道这依赖于特定的架构和实现。 但是,当有VIPT缓存时,您知道的实现是什么?
感谢。
答案 0 :(得分:5)
在这个详细程度,您必须打破"缓存"和" TLB"到他们的组成部分。它们在设计中非常紧密地互连,该设计使用与标签获取并行转换的VIPT速度黑客(即利用索引位全部低于页面偏移并因此被翻译"免费&#34 ;相关:Why is the size of L1 cache smaller than that of the L2 cache in most of the processors?)
L1dTLB本身是一个小/快Content addressable memory,具有(例如)64个条目和4路组关联(Intel Skylake)。通常使用并行检查的第二(和第三)阵列来处理重复数据,例如, 32页4路,适用于2M页面和1G页面:4项完全(4路)关联。
但是现在,简化你的心理模型,忘记大片。 L1dTLB是单个CAM,并且检查它是单个查找操作。
"缓存" 至少由以下部分组成:
L1dTLB与L1D缓存并不是真正分开的。我实际上并没有设计硬件,但我认为现代高性能设计中的负载执行单元是这样的:
AGU从寄存器+偏移量生成地址。
(有趣的事实:Sandybridge家族乐观地将此过程简化为简单寻址模式:[reg + 0-2047]
的负载使用延迟比其他寻址模式低1c,如果reg值与{{1}相同的4k页面}}。Is there a penalty when base+offset is in a different page than the base?)
索引位来自地址的页内偏移部分,因此它们不需要从虚拟转换为物理。或翻译是无操作。具有PIPT高速缓存的非别名的此VIPT速度与reg+disp
一样长。例如32kiB / 8-way = 4k页。
索引位选择一组。对于该集合的所有方式,并行获取标签+数据。 (这需要节省延迟的能力,并且可能只对L1有价值。更高的关联性(每组更多的方式)L3缓存绝对不是)
如果标签匹配,则高速缓存从数据中提取匹配方式的正确字节(使用地址的偏移行低位和操作数大小)。
或者不是取出完整的64字节行,而是可以使用先前的偏移位从每个方向获取一个(对齐的)字。没有高效未对齐负载的CPU肯定是这样设计的。我不知道在支持未对齐负载的CPU上为简单对齐的负载节省电量是否值得。
但现代英特尔CPU(P6及更高版本)对未对齐的负载微控制没有任何损失,即使对于32字节向量,只要它们不跨越缓存线边界即可。并行8种方式的字节粒度索引可能不仅仅需要获取整个8 x 64字节,并且在fetch + TLB发生时设置输出的复用,基于行内偏移,操作数大小,以及特殊属性,如零或符号扩展或广播加载。因此,一旦标记比较完成,来自所选方式的64字节数据可能只进入已经配置的多路复用网络,该网络抓取正确的字节并进行广播或符号扩展。
AVX512 CPU甚至可以进行64字节的全线负载。
如果L1dTLB CAM中没有匹配,则整个缓存提取操作不能继续。我不确定CPU是否/如何管理这个,以便其他负载可以在解决TLB-miss时继续执行。这个过程包括检查L2TLB(Skylake:统一的1536条目12路4k和2M,16条1G),如果失败则进行页面漫步。
我假设TLB未命中导致标记+数据提取被丢弃。一旦找到所需的翻译,就可以重新获取它们。在其他负载运行时,无处可以保留它们。
最简单的是,它可以在转换准备就绪时重新运行整个操作(包括从L1dTLB获取转换),但它可以通过缩短进程并直接使用转换来降低L2TLB命中的延迟而不是将其放入L1dTLB并再次将其取回。
显然,这要求dTLB和L1D真正设计在一起并紧密集成。由于他们只需要相互交谈,这是有道理的。硬件页面遍历通过L1D缓存获取数据。 (页面表总是有已知的物理地址,以避免捕获22 /鸡蛋问题)。
是否有从TLB到Cache的边带连接?
我不会称之为边带连接。 L1D缓存是使用L1dTLB的唯一事物。同样,L1iTL仅由L1I缓存使用。
如果有第二级TLB,它通常是统一的,所以L1iTLB和L1dTLB都会检查它们是否错过。就像拆分L1I和L1D缓存一样,如果它们错过了,通常会检查统一的L2缓存。
外部缓存(L2,L3)非常普遍的PIPT。在L1检查期间发生转换,因此可以将物理地址发送到其他缓存。