这篇从一致性问题讲到MESI协议,再到ACE的5种Cache行状态和Snoop嗅探机制。资料来源:ARM AMBA4 AXI and ACE协议规范(328页)。
一、一致性问题:为什么需要硬件维护?
问题场景
想象双核SoC,CPU0和CPU1各有自己的L1 Cache,共享L2和主存:
CPU0从内存读变量X=5,存入自己的L1 Cache
CPU1也从内存读变量X=5,存入自己的L1 Cache
CPU0把X改成10,写入自己的L1 Cache
问题来了:CPU1读X,从自己Cache拿到旧值5,而不是CPU0改后的10
如果靠软件维护(每次读写都刷Cache),性能灾难。所以多核SoC需要硬件自动维护Cache一致性——这就是MESI和ACE要做的事。
MESI协议:四种状态
MESI是经典的一致性协议,用4种状态标记每个Cache行的状态:
M,Modified,已修改(脏)
E,Exclusive,独占(干净)
S,Shared,共享(干净)
I,Invalid,无效
| 状态 | 本地是否有效 | 其他Cache有副本? | 与内存一致? |
|---|---|---|---|
| M(Modified) | 是 | 否(唯一) | 否(已修改,需写回) |
| E(Exclusive) | 是 | 否(唯一) | 是 |
| S(Shared) | 是 | 可能 | 是 |
| I(Invalid) | 否 | — | — |
MOESI扩展:多了个O
MOESI在MESI基础上加了O(Owned,拥有)状态,解决"共享脏数据"的写回责任问题:
当一个Cache持有修改后的数据,另一个Cache来读时,数据可以从Cache间直接传(不绕道内存),此时原Cache进入O状态——它负责最终写回内存
没有O状态的话,共享脏数据时谁该写回内存就模糊了
总线嗅探(Bus Snooping):每个Cache监听总线上的事务,发现有人写自己Cache里有的行就做出反应。简单,但核数多了总线流量爆炸。ACE用的就是这种。
目录(Directory):用一个集中目录记录每个Cache行被哪些核缓存。写的时候只通知目录里记的核,不用全网广播。CHI用的就是这种,下一篇讲。
二、ACE:5种Cache行状态
ACE(AXI Coherency Extensions)是AMBA4引入的AXI一致性扩展。它在MESI基础上把状态细化成5种,核心是新增了SD(Shared Dirty)状态:
I,Invalid,无效
UC,Unique Clean,唯一干净
UD,Unique Dirty,唯一脏
SC,Shared Clean,共享干净
SD,Shared Dirty,共享脏(新增)
| 状态 | 本地有效? | 唯一? | 干净? | 说明 |
|---|---|---|---|---|
| I | 否 | — | — | 数据不在本地Cache |
| UC | 是 | 是 | 是 | 只有我有,且与内存一致 |
| UD | 是 | 是 | 否 | 只有我有,但改过了,需写回 |
| SC | 是 | 否 | 是 | 多处缓存,都与内存一致 |
| SD | 是 | 否 | 否 | 多处缓存,我这边改过,需负责写回 |
SC(Shared Clean):共享且干净,数据可能多处缓存,但都和内存一致,谁都不用负责写回。
SD(Shared Dirty):共享且脏,数据多处缓存,但其中一方改过了。SD状态的Cache行负责把脏数据写回内存。这就是MOESI里O状态在ACE中的对应。
三、Snoop嗅探机制:三个通道
ACE在AXI原有的5个通道(AW/W/B/AR/R)基础上,新增了3个Snoop通道,专门做一致性嗅探:
| 通道 | 方向 | 作用 |
|---|---|---|
| AC(Snoop Address) | 互连器 → Master | 发嗅探请求,问"你Cache里有没有这个地址?" |
| CR(Snoop Response) | Master → 互连器 | 返回响应:有没有、什么状态 |
| CD(Snoop Data) | Master → 互连器 | 返回数据(如果被请求交出) |
关键事务类型
| 事务 | 作用 |
|---|---|
| WriteBack | 把脏数据写回内存(Cache行从UD变UC或I) |
| WriteUnique | 写唯一化:先让其他Cache副本无效,再写 |
| CleanInvalid | 使其他Cache中的副本无效化(干净副本直接丢) |
| MakeInvalid | 强制使其他副本无效(不管脏不脏) |
四、读事务Snoop流程实例
CPU0要读地址A,但自己Cache没有(miss)
1、CPU0通过AR通道向互连器发读请求
2、互连器通过AC通道向其他所有Master发Snoop请求:"你们Cache里有没有地址A?"
3、其他Master通过CR通道响应:有的报状态(SC/SD),没有的报I
4、如果某个Master持有SD(脏数据),通过CD通道把数据返回给互连器
5、互连器把数据通过R通道返回CPU0,同时可能更新内存
6、CPU0的Cache行进入SC状态(共享干净)
五、写事务Snoop流程实例
CPU0要写地址A,但Cache里是SC状态(共享,不能直接写)
1、CPU0发WriteUnique事务,通过AW通道告诉互连器"我要写这个地址"
2、互连器通过AC通道向其他Master发Snoop,要求它们无效化地址A的副本
3、其他Master通过CR响应"已无效",副本变成I状态
4、现在CPU0是唯一持有者,Cache行变成UD状态,开始写数据
5、后续CPU0可以自由读写,直到别的核又要访问触发新一轮Snoop
ACE-Lite:IO一致性
不是所有设备都需要全一致性。GPU、DMA这些非Cache设备可以通过ACE-Lite参与部分一致性——它们不需要被Snoop(因为没有Cache),但可以发起一致性事务,确保写到内存的数据对CPU Cache可见。典型场景:DMA把数据搬进内存后,CPU不用手动刷Cache就能读到最新数据。
AXI是个"傻"总线——它只管搬数据,不管数据语义。一致性需要知道"这个地址在哪些Cache里有副本""谁改过",这超出了AXI的职责范围。ACE就是在AXI基础上加了一层"Cache感知"的能力。
ACE用总线嗅探实现一致性,但核数多了就扛不住——8核16核时每次写都要snoop所有核,总线流量爆炸。CHI用目录式架构解决这个问题。再加上AXI4-Stream和低功耗接口,覆盖AMBA的三个进阶主题。
94