点击查看精选 CXL 系列文章
点击进入【芯片设计验证】社区,查看更多精彩内容
声明:
- 作者主页:【MangoPapa的CSDN主页】。
- ⚠️ 本文首发于CSDN,转载或引用请注明出处【https://mangopapa.blog.csdn.net/article/details/132129740】。
- ⚠️ 本文目的为 个人学习记录 及 知识分享。因个人能力受限,存在协议解读不正确的可能。若您参考本文进行产品设计或进行其他事项并造成了不良后果,本人不承担相关法律责任。
- ⚠️ 若本文所采用图片或相关引用侵犯了您的合法权益,请联系我进行删除。
- 欢迎大家指出文章错误,欢迎同行与我交流 ~
- 邮箱:[email protected]
- 直达博主:loveic_lovelife 。(搜索或点击扫码)
为便于表述,下述 Cacheline 均指 Device Cache 内归属于 Host Memory 的 Cacheline。
Bogus 是 CXL.cache D2H Data 中的一个字段,指示当前写的数据为伪数据,常用于 Host Snoop 与 Device Evict 相同 Cacheline 的场景,Host 收到该数据后应予以丢弃。
具体而言,在 Device 发出 Evict 请求之后、收到 GO_WritePull 响应之前收到了 Host 发来的针对该地址的 Snoop 请求,Device 先行对该 Snoop 进行响应并通过 D2H Data Channel 反馈该 Cacheline 的最新数据。紧接着,Device 收到 Host 发来的针对此前 Evict 请求的 GO_WritePull 响应,再次通过 D2H Data 反馈 Evict Cacheline 的数据,同时将 D2H Data Flit 中 Bogus 字段置一,提示 Host 当前数据此前已经发过一次,当前数据可能已经过期,Host 收到后直接丢弃数据。一次针对相同地址的 Evict+Snoop 的流程示意图如下图所示。
CXL 协议 Compliance 章节的算法 1b 中提到了 Bogus Write 的概念,笔者理解其并非 Bogus=1 的 Cache 写请求,而是常规的 Bogus=0 的写请求。
Bogus=1 仅适用于采用 Evict 原语进行写数据的场景。Device 可以采用 DirtyEvict、CleanEvict、CleanEvictNoData 等 D2H Evict 请求来释放 Device Cache 内归属于 Host Memory 的 Cacheline。发起 Evict 请求的前提是该 Cacheline 在 Device Cache 内的状态为 Modified 或 Shared/Exclusive,不能为 Invalid,这也意味着 Evict 请求在到达 Host 之前 Host Snoop Filter 仍然会 Track 该 Cacheline。
对于 WrInv、WoWrInv*、ItoMWr 及 WrCur 写数据,不存在需要 Bogus=1 的情况。笔者理解,有两大原因:
为了实现有效的 Bogus 传输,协议对 Host 和 Device 有如下要求:
我们抛开上边提到的约束,来探究下为什么要这么干——
我们知道,CXL 系统有两个场景会用到 D2H Data Channel:
假设允许在收齐 Rsp/Data 之前针对同一地址的 Cacheline 发送 GO_WritePull 和 Snoop 请求(协议不允许),我们分两种情况来讨论:
针对上述第二种情况,不管 Snoop 先到还是 GO_WritePull 先到,接下来针对这两笔请求,D2H 上会先后出现两笔 Data。至于哪个先到 Host,并不确定。更要命的是两笔数据并不一定相同。
此外,笔者认为,Snoop 和 GO_WritePull 先后脚到达 Device,Device 同时处理起来容易造成混乱。Device 收到 Snoop 后,DCOH 在 Device Cache 之间进行 Cache 一致性相关处理,此间具体耗时并不明确。处理 Snoop 或许会改变 Cacheline 状态,处理 GO_WritePull 后 Invalid 相关 Cacheline,显然一方对 Cacheline 状态的修改均会影响另一方,导致另一方处理出错。
再考虑一种情况,虽然 Device 不知道其是否能收到 Snoop,但其知道其已经发出了 Evict 且还没收到 GO_WritePull,等待 GO_WritePull 期间,收到的 Snoop 先 Pending 在 Device 不就好了么?——不行。一来,即便先处理 GO_WritePull 再处理 Snoop,也不确保其 Data 就比 Snoop 对应的 Data 先到达。二来,笔者认为 Go_WritePull Pending 比 Snoop Rsp Pending@Device 代价更小一些——从发起请求方的重要性来看,Snoop 由 Host 发起,可能涉及到的组件更多,或许其他组件正在等待 Snoop 的 Rsp 以进行下一步运算处理;Evict 由 Device 发起,Pending 的组件只有 Device 自己,Device 本身不打算用这条 Cacheline 了才 Evict,对 Device 性能影响较小。
综合下来,为了解决以上各种问题,较好的方案便是协议提到的——Host 等待收齐 Snoop 的 Rsp/Data 之后再反馈相同地址的 GO_WritePull。对 Device 而言,若其发出 Evict 请求后在等待 GO_WritePull 期间收到相同 Cacheline 的 Snoop 请求则进行响应。待收到 GO_WritePull 之后,若 Evict 和 GO_WritePull 期间曾经反馈该地址的 Data,则再次反馈 Data 时标注 Bogus=1。通过这种方式,能够保证 Snoop 的 Data 一定比 GO_WritePull 的 Data 先到。如果此前处理 Snoop 时未反馈 Data,笔者理解接下来处理 GO_WritePull 时 Bogus 不应置一。
此外,如果从 Snoop 到 GO_WritePull 相关 Cacheline 的数据并未发送变动,似乎 Bogus=0 也讲得过去,但这样 Host 会重复更新该地址,似无必要。
Host 端发出 Snoop 和 GO_WritePull 后,相关 Entry 已经创建并等待 Rsp/Data,如果不回复,Host 会报错。
Host 发出 Snoop 后又收到了 Evict,Host 直接忽略该 Evict 不就好了么?显然也不应该,因为 Device 中 Evict 相关 Entry 也已创建,需要回复 GO_WritePull 来清除 Entry。当然,Device 等待 GO_WritePull 期间收到相关 Snoop,用这个 Snoop 替代 GO_WritePull 来消除 Evict 创建的 Entry,理论上似乎也讲得过去,但总感觉是个歪路子,而且会增加 Device 的设计复杂度。
|
精选往期 CXL 协议系列文章,请查看【 CXL 专栏】
⬆️ 返回顶部 ⬆️