3. MESI 缓存到缓存传输验证
任务目标
构造一个最小双核 MESI 模型:缓存 A 持有某地址的 S 状态副本,缓存 B 对该地址发起读请求。验证两点:
- B 的读请求由 A 通过缓存到缓存传输(Cache-to-Cache, C2C)提供数据,不访问内存;
- 传输完成后 A、B 均保持 S 状态,内存副本保持有效(未失效)。
状态与传输关系
最小实现
用 Python 模拟总线监听与状态转移。内存访问通过计数器 mem_reads 观测,C2C 传输通过 c2c_transfers 观测。
from enum import Enum
class State(Enum):
I = "Invalid"
S = "Shared"
E = "Exclusive"
M = "Modified"
class Cache:
def __init__(self, name):
self.name = name
self.state = State.I
self.data = None
class Bus:
def __init__(self):
self.mem_reads = 0
self.c2c_transfers = 0
def read(self, requester, caches, mem_data):
# 1. 总线广播读请求,其他缓存监听
supplier = None
for c in caches:
if c is requester:
continue
if c.state in (State.S, State.E, State.M):
supplier = c
break
if supplier is not None:
# 2. 缓存到缓存传输,不访问内存
self.c2c_transfers += 1
requester.data = supplier.data
requester.state = State.S
# 供应者若为 E/M 需降级为 S;S 保持 S
if supplier.state in (State.E, State.M):
supplier.state = State.S
# 内存副本仍有效,无需写回
else:
# 3. 无其他缓存持有,访问内存
self.mem_reads += 1
requester.data = mem_data
requester.state = State.E # 独占加载
def run():
mem_data = 0xAB
bus = Bus()
A = Cache("A")
B = Cache("B")
# 初始化:A 已处于 S 状态(例如之前被加载过)
A.state = State.S
A.data = mem_data
# B 发起读请求
bus.read(B, [A, B], mem_data)
print(f"A: state={A.state.value}, data={hex(A.data)}")
print(f"B: state={B.state.value}, data={hex(B.data)}")
print(f"mem_reads={bus.mem_reads}, c2c_transfers={bus.c2c_transfers}")
assert A.state == State.S, "A 应保持 S"
assert B.state == State.S, "B 应变为 S"
assert A.data == mem_data and B.data == mem_data
assert bus.mem_reads == 0, "不应访问内存"
assert bus.c2c_transfers == 1, "应发生一次 C2C 传输"
print("PASS: S 状态下读命中通过 C2C 完成,双方保持 S")
run()
运行与验证
直接执行:python mesi_c2c.py。预期输出(由代码逻辑唯一确定):
A: state=Shared, data=0xab
B: state=Shared, data=0xab
mem_reads=0, c2c_transfers=1
PASS: S 状态下读命中通过 C2C 完成,双方保持 S
判定通过条件:mem_reads == 0 且 c2c_transfers == 1,A、B 状态均为 Shared,数据一致。若把 A 初始状态改为 Invalid,则 mem_reads 变为 1、c2c_transfers 为 0,可作为反向对照验证。