关于我转生为MMU,和我的傲娇Cache搭档一起实现双重加速这件事✨

B站播客
![[d297a5d22d9d43418719d6f8648de2e1.mp3]]
引言:CPU的“快”从何而来?

当CPU发出一个内存访问请求时,它需要经过MMU(内存管理单元)将虚拟地址翻译成物理地址,然后才能去Cache或主存中查找数据。这听起来是一个串行的、耗时的过程。但为什么现代计算机给人的感觉如此流畅?难道MMU的地址翻译是瞬时完成的吗?

虚地址索引、实地址标记(Virtually Indexed, Physically Tagged, VIPT) Cache,看看它如何实现MMU与Cache查找的“瞒天过海”式并行。


一、传统模式:访存的“龟速”瓶颈

在深入VIPT之前,我们先回顾一下最直观的访存方式。如果MMU和Cache完全串行工作,流程是这样的:

  1. CPU发出虚拟地址(VA)

  2. MMU/TLB:用VA的高位(虚拟页号)去查页表,将VA翻译成物理地址(PA)。

  3. Cache控制器:拿到完整的PA后,将其拆解成标记、索引和偏移量,开始在Cache中查找。

  4. 数据返回:如果命中,则从Cache中返回数据。

这个过程,我们称之为实地址索引、实地址标记(PIPT)。它的缺点显而易见:MMU的地址翻译是Cache查找的前提。如果页表查询或TLB未命中,就需要访问主存,这个巨大的延迟会严重拖慢整个系统的性能。


二、:一次精妙的“偷步”

虚拟地址的页内偏移量与物理地址的页内偏移量是完全相同的!这个偏移量在地址翻译过程中是恒定不变的。

利用这一点,VIPT Cache的设计思想应运而生:既然Cache的**组索引(Index)块内偏移(Offset)都在地址的低位,那么我们能否让它们完全落入页内偏移的范围内呢?如果能,我们就可以在MMU翻译高位(页号)的同时,用虚拟地址的低位(页内偏移)**去同步完成Cache的组查找!

这就是VIPT的核心:虚地址索引——用虚拟地址的低位部分作为索引,来确定Cache的组号;而实地址标记——在完成翻译后,用物理地址的页号来与Cache中的标记进行比对,以最终确定是否命中。


三、VIPT的完美配合:工作流程详解

假设:

首先,我们来计算Cache的索引和偏移位数:

索引位数(6位) + 偏移位数(6位) = 12位,这正好等于页内偏移的位数!这说明我们可以完美地采用VIPT设计。

VIPT工作步骤:

  1. CPU发出一个虚拟地址(VA)

  2. 并行启动!

    • MMU/TLB:用VA的**高20位(虚拟页号)**去查表,获取物理页号。

    • Cache控制器:同时,用VA的低12位,将其中的6位作为索引6位作为偏移,立即定位到Cache的一个特定组,并把该组中的所有行(4路)都读出来。

  3. 最终验证

    • 当MMU翻译完成,得到物理页号

    • Cache控制器将物理页号和VA的高位组合成完整的物理地址标记

    • 与第2步中读出的Cache行中的标记进行比对。如果匹配,则命中!


四、避坑

1. 地址重叠陷阱

VIPT并非万能。如果Cache的索引位和偏移位之和大于页内偏移的位数,VIPT就会失效。

反例:如果页面大小仍是4KB,但Cache变成了64KB,块大小64B,4路组相联。