1. CHI 协议 Cache Line 状态

当组件访问 cache line 时,协议会定义 cache 状态以确定是否需要执行操作。每个 cache 状态都基于以下 cache line 特征:

  • Valid、Invalid
    • 当 Valid 时,cache line 存在于 cache 中。
    • 当 Invalid 时,cache line 不存在于 cache 中。
  • Unique、Shared
    • 当 Unique 时,cache line 仅存在于唯一 cache 中。
    • 当 Shared 时,cache line 可以存在于多个 cache 中。cache line 不保证存在于多个 cache 中。
  • Clean、Dirty
    • 当 Clean 时,cache 不负责更新主内存。
    • 当 Dirty 时,cache line 已相对于主内存进行了修改。Dirty cache 必须确保主内存最终得到更新。
  • Full、Partial、Empty
    • Full cache line 的所有字节都有效。
    • Half cache line 可以有一些字节有效,而有些字节包括零字节或所有字节。
    • Empty cache line 没有有效字节。

Cache state model

CHI 协议节点访问 cache line 时所需的操作由 cache line 状态决定。CHI 协议定义了以下 cache line 状态:

  • I: Invalid

    • Cache line 不存在于 cache 中。
  • UC: Unique Clean

    • Cache line 仅存在于此 cache 中。
    • Cache line 尚未针对内存进行修改。
    • 可以在不通知其他 cache 的情况下修改 cache line。
    • 响应请求数据的 snoop,允许但不要求 cache line:
      • 被请求时返回到 Home。
      • 被 snoop 指示时直接转发给 Requester。
  • UC: Unique Clean Empty

    • Cache line 仅存在于此 cache 中。
    • Cache line 处于唯一状态,但数据所有的字节均无效。
    • 可以在不通知其他 cache 的情况下修改 cache line。
    • 响应请求数据的监听,cache line 不得:
      • 返回到 Home,即使被请求。
      • 直接转发给 Requester,即使被 snoop 指示。
  • UD: Unique Dirty

    • Cache line 仅存在于此 cache 中。
    • Cache line 已根据内存进行了修改。
    • Cache line 必须在被驱逐时写回到下一级 cache 或内存。
    • Cache line 可以在不通知其他 cache 的情况下进行修改。
    • 响应请求数据的监听,cache line:
      • 必须在请求时返回到 Home。
      • 被 snoop 指示时,期望直接转发给 Requester。
  • UDP: Unique Dirty Partial

    • Cache line 仅存在于此 cache 中。
    • Cache line 是唯一的。cache line 可能有些字节有效、有些为零字节或者有些全部字节有效。
    • Cache line 已根据内存进行了修改。
    • 当 cache line 被逐出时,下一级 cache 或内存中的数据必须与被逐出的 cache line 合并,以形成完整的有效 cache line。
    • 可以在不通知其他 cache 的情况下修改 cache line。
    • 响应请求数据的 snoop,cache line 必须:
      • 返回到 HOME。
      • 即使受到 snoop 指示,也不要直接转发给请 Requester。
  • SC: Shared Clean

    • 其他 cache 可能拥有 cache line 的共享副本。
    • Cache line 可能已相对内存进行了修改。
    • 在驱逐时,Cache 不负责将 cache line 写回内存。
    • 如果不使任何共享副本无效并获得某 cache line 的唯一所有权,则无法修改该 cache line。
    • 响应请求数据的 snoop,cache line:
      • 如果未设置 RetToSrc 位,则被期望不返回数据。
      • 如果设置了 RetToSrc 位,则被期望返回数据。
      • 在 snoop 指示时,则被期望直接转发给 Requester。
  • SD: Shared Dirty

    • 其他 cache 可能拥有 cache line 的共享副本。
    • Cache line 已针对内存进行了修改。
    • 驱逐时必须将 cache line 写回下一级 cache 或内存。
    • 如果不使任何共享副本无效并获得某 cache line 的唯一所有权,则无法修改该 cache line。
      • 响应请求数据的 snoop,cache line:
        • 收到请求时必须返回到 Home。
        • 收到 snoop 指示时,应直接转发给 Requester。

2. CHI 协议 Cache Line 状态 vs MOESI Cache Line 状态

下表显示了 MOESI cache line 状态到 CHI cache line 状态的映射:

MOESI CHI Description
M = Modified UD =  Unique Dirty Cache line 仅存在于该 cache 中,并且已相对内存进行了修改。
O = Owned SD = Shared Dirty Cache line 可能存在于其他 cache 中,并且已相对内存进行了修改,该 cache 负责更新内存。
E = Exclusive UC = Unique Clean Cache line 仅存在于该 cache 中,并且相对内存尚未进行修改。
S = Shared SC =  Shared Clean Cache line 可能存在于其他 cache 中,并且可能已经相对内存进行了修改。
I = Invalid I = Invalid Cache line 不存在于 cache 中。

2.1. MOESI 中的 O(Owned)状态映射到 CHI 中的 Shared Dirty 状态?

Shared Dirty (SD) 的名称听起来不像“Owned”。虽然名字听起来可能不太直观,但仍然有意义,因为 Owned 状态是指 cache line 可能存在于多个 cache 中,但只有一个 cache 负责将其写入内存,并且该 cache 是此 cache line 的所有者,即使此 cache line 在多个 cache 之间共享。

2.2. Shared Clean 是否真的 Clean?

另一个因 CHI 协议名称而引起混淆的状态是 Shared Clean (SC)。Shared Clean 状态可能不是真正意义上“Clean”,它可能与主内存的数据不一致。

2.3. Cache line 如何最终处于 Shared Clean (SC) 状态或 Shared Dirty (SD) 状态?共享“Dirty”数据是什么意思。MOESI 协议如何支持共享“Dirty”数据?

考虑 2 个 Request Node RN0 和 RN1, 两者都有一个处于“I”的 cache line 状态即 Invalid 状态。

RN0 发出 ReadUnique 请求。假设 RN0 处的 cache line 未命中,换句话说该 cache line 不存在于任何其他 cache 中,那么请求数据来自主内存,数据被放在 RN0 的 cache line 中,标记为“UC”。

RN0 (I) -> ReadUnique -> RN0 (UC)

现在,RN1 同一 cache line 发出 ReadShared 命令。由于这 cache line 存在于 RN0 中,RN0 被 HOME 节点 SnpSharedFwd,并且向 RN1 提供数据。 RN1 通过 RN0 的数据响应 CompData_SC 获取该 cache line 数据。现在 RN0 和 RN1 都有该 cache line 数据,两个 Request Node 最终都进入了“SC”状态,并且他们的数据与主内存相同。

但是,如果在 RN1 发出 ReadShared 命令之前,RN0 修改了该行, 那么 RN0 的 cache line 状态 将从“UC”变为“UD”。注意 RN0 的 cache line 数据相对主内存已被修改,它是“Dirty”的。

现在 RN1 同一 cache line 发出 ReadShared,该 cache line 仍然存在于 RN0,因此 RN0 会被 snoop。当 RN0 收到 SnpSharedFwd 命令后,向 RN1 提供 “Dirty” 数据。现在 RN0 cache line 状态从 Unique Dirty (UD) 变为 Shared Clean (SC)。另一方面,RN1 接收到 RN0 的数据响应 CompData_SD_PD,表示将 RN1 的 cache line 状态变为 Shared Dirty (SD) 状态,并将 “Dirty” 的责任传递给 RN1。

RN0 最终处于 Shared Clean (SC) 状态,RN1 最终处于 Shared Dirty (SD) 状态,两者具有相同的数据,相对主内存是不同的,它是“Dirty”而不是“Clean”。这就是任何节点的 cache line 状态“SC”可能有“Clean”和“Dirty”数据(尽管在不同时间)的情况,也是将“SC”状态定义为“cache line 可能已被修改”的含义,也是 MOESI 的 Owned 状态允许共享“Dirty”数据的方式。

现在 RN0 和 RN1 中存在“Dirty”数据,两者都有责任将“Dirty”数据写回,但有且只有 1 个 RN 有责任写它写回到主存储器,目前这个责任在 RN1 上。如果另一个 cache line 状态为“I”的 Request Node RN2 发出 ReadShared,那么 RN2 的 cache line 状态将最转换为“SD”,而 RN0 和 RN1 cache line 状态转换为“SC”。现在 RN0、RN1 和 RN2 都共享“Dirty”数据,但 RN2 有责任更新主缓存。

如果 RN2 决定将数据写入主内存,它可能使用 WriteBackFull 或 WriteCleanFull。如果使用 WriteBackFull,RN2 的 cache line 状态将转“I”,如果使用 WriteCleanFull,RN2 的 cache line 将保留一个副本,RN0、RN1、RN2 的 cache line 状态将转为“SC”。

假设 RN2 确实发出了 WriteCleanFull,所以它仍然有 cache line 状态为“SC”的副本。如果 RN3 发出 ReadUnique 到同一个 cache line,那么它可以从 RN0、RN1 或 RN2 获取数据,因为现在 RN0、RN1、RN2 的 cache line 处于“SC”状态,HOME 响应为 CompData_UD_PD。RN3 的 cache line 将从“I”转到“UD”,RN0、RN1 和 RN2 的 cache line 将转为“I”。 某个 RN 将收到 SnpUniqueFwd,而其他的 RN 将收到 SnpMakeInvalid 命令来使它们的 cache line 数据无效。

协议流程:

Protocol Flows Part1

Protocol Flows Part2

3. 参考文献