3. CCIX协议层(续)
3.3 一致性协议
3.3.1 缓存状态
CCIX协议规定的缓存状态如下:
I(Invalid):缓存行无效,即缓存行不存在于缓存中。
UC(Unique Clean):缓存行的状态是唯一且“干净”,即缓存行只存在当前缓存中,且缓存行没有被修改过。拥有该缓存行的处理器可以在不通知其它缓存的情况下修改此缓存行。当前缓存接收到监听消息时,如果DataRet(Data Return to Source)字段被置为1,可以(但不要求)返回该条缓存行数据;如果DataRet字段被置为0,不可以返回该条缓存行数据。
UCE(Unique Clean Empty):缓存行只在当前缓存中存在,缓存行处于唯一状态,但所有数据字节均无效。拥有该缓存行的处理器可以在不通知其它缓存的情况下修改缓存行。当前缓存接收到请求数据的监听消息时,不可以返回该条缓存行(因为所有数据无效)。
UD(Unique Dirty):缓存行的状态是唯一但为“脏“,即缓存行只在当前缓存中存在,但是缓存行数据被修改过,且没有更新到内存。当该缓存行被逐出(eviction)时,必须写回下一级缓存或内存。拥有该缓存行的处理器以在不通知其它缓存的情况下修改缓存行数据。当前缓存接收到请求数据的监听消息时,必须返回该缓存行数据。
UDP(Unique Dirty Partial):缓存行的状态是唯一但是部分为“脏“,即缓存行只在当前缓存中存在,缓存行是唯一的,但是缓存行的仅有一部分数据有效且“脏”。当该缓存行被逐出(eviction)时,必须将其与下一级缓存或内存中的数据合并,以形成完整的有效缓存行。拥有该缓存行的处理器以在不通知其它缓存的情况下修改缓存行数据。当前缓存接收到请求数据的监听时,必须返回该缓存行数据。仅当接口支持部分缓存状态(Partial Cache States)时,才支持此缓存行状态。
SC(Shared Clean):缓存行的状态是不唯一且“干净”,即在其它缓存中可能有该缓存行的副本,且缓存行数据可能被修改过,但是在当前缓存中是“干净“的。当该缓存行在当前缓存中被逐出(eviction)时,当前缓存不需要将此缓存行数据写回内存。当前缓存只有在无效(invalidate)此缓存行其它缓存中的副本,并取得此缓存行的唯一所有权后,才能修改此缓存行数据。当前缓存接收到请求数据的监听时,不可以返回缓存行数据。
SD(Shared Dirty):缓存行的状态是不唯一且“脏”。其它缓存中可能有该缓存行的副本,缓存行数据被修改过。当该缓存行被逐出(eviction)时,必须写回下一级缓存或内存。当前缓存只有在无效(invalidate)此缓存行其它缓存中的副本,并取得此缓存行的唯一所有权后,才能修改此缓存行数据。当前缓存接收到请求数据的监听时,必须返回缓存行数据。
3.3.2 请求类型(Request Type)
CCIX协议中的请求分为以下四类:
读请求:需要返回一个数据响应给请求者(requester)
写请求:请求者发出数据
无数据请求:不需要返回一个数据响应给请求者
原子请求:请求者发出数据,请求不可分割
1. 读事务(Read Transactions):
ReadNoSnp:对不可监听的(non-snoopable)地址区域的读取请求。数据包含在完成响应中;数据大小取决于请求中的数据尺寸属性(size attribute)值,最大是一条缓存行大小;接收到的数据不会被请求者缓存。
ReadOnce:对可监听的(snoopable)地址区域的读取请求,以获取一致性数据快照。数据大小是一条缓存行;接收到的数据不会被请求者缓存。
ReadOnceCleanInvalid:对可监听的地址区域的读取请求,以获取一致性数据快照。数据大小是一条缓存行;建议但不强制,缓存副本被置无效(invalidate);如果被置无效的缓存备份是“脏”的,必须把此缓存行写回到内存;接收到的数据不会被请求者缓存。
ReadOnceMakeInvlid:对可监听的地址区域的读取请求,以获取一致性数据快照。数据大小是一条缓存行;建议但不强制,所有缓存副本被置无效(invalidate);如果被置无效的缓存备份是“脏”的,无需把此缓存行写回到内存;接收到的数据不会被请求者缓存。使用ReadOnceMakeInvalid事务可能会导致“脏”缓存行丢失,因此ReadOnceMakeInvalid的使用必须严格限制在已知允许丢失“脏”缓存行的情况下。
ReadUnique:对可监听的地址区域的读取请求,以对缓存行进行存储。数据大小是一条缓存行;请求者将接收UC或UD状态的数据。
ReadClean:对可监听的地址区域的读取请求。数据大小是一条缓存行;数据必须以“干净”的状态(UC或SC)提供给请求者。
ReadNotSharedDirty:对可监听的地址区域的读取请求。数据大小是一条缓存行;数据必须以UC或UD或SC状态(不能是SD)提供给请求者。
ReadShared:对可监听的地址区域的读取请求。数据大小是一条缓存行;请求者将接收UC或UD或SC或SD状态的数据。
2. 无数据事务(Dataless Transactions): 顾名思义,这类事务不需要传输数据。
CleanUnique:请求可监听的地址区域将状态更改为Unique,以对缓存行执行存储。典型用法是当请求者拥有缓存行的共享副本,并希望获得存储到缓存行的权限时可以用此事务。数据不包括在完成响应中;任何“脏”副本都必须写回下一级缓存或内存。
MakeUnique:请求可监听的地址区域以获得缓存行的所有权,不需要数据响应。只有当请求者保证将对缓存行的所有字节进行存储时,才会使用此请求。任何“脏”副本都必须失效,而无需写回下一级缓存或内存。
Evict:用于指示缓存代理不再缓存“干净”的缓存行。此事务不发送数据;缓存行不得保留在缓存中。
缓存维护操作(Cache Maintenance Operation,CMO)有助于软件缓存管理。该协议包括以下支持CMO的无数据事务:
CleanShared:对CleanShared请求的完成响应可以确保所有缓存副本都更改为非“脏”状态,并且任何“脏”副本都会写回内存。完成响应中不用包含数据。
CleanSharedPersist:对CleanSharedPersist请求的完成响应可以确保所有缓存副本都更改为非“脏”状态,并且任何“脏”缓存副本都会写回PoP(Point of Persistence)。PoP是内存系统中的一个点,当系统电源断开时,会保持对内存的写入,当电源恢复时,会可靠的恢复对内存的写入。完成响应中不用包含数据。
CleanInvalid:对CleanInvalid的完成响应可以确保所有缓存的副本都无效,并且任何“脏”副本都会写入内存。完成响应中不用包含数据。
MakeInvalid:对MakeInvalid的完成响应可以确保所有缓存的副本都无效,并且必须丢弃任何“脏”副本。完成响应中不用包含数据。
SnpMe Variants:CleanShared、CleanSharedPersist、CleanInvalid和MakeInvalid事务都有一个SnpMe变体,后缀为[SnpMe]。SnpMe是请求者向主代理发出的指示,表明请求者尚未检查其缓存中是否存在该行的副本,请求者指示主代理在必要时向请求者发出监听。
3. 写事务(Write Transactions):
写事务将数据从请求者移动到下一级缓存、内存或外围设备。根据事务类型,传输的数据可以是一致的,也可以是非一致的。每个部分缓存行写入事务必须明确数据中的字节。事务名称中的Full或Ptl后缀指明了是整条缓存行还是部分缓存行。
WriteNoSnpPtl:写部分缓存行到不可监听(non-snoopable)的地址区域。数据最大是一条缓存行;必须明确写入的字节和不写入的字节。
WriteNoSnpFull:写完整缓存行到不可监听的地址区域。数据大小是一条缓存行;不需要指明写入的字节,因为默认写入全部字节。
WriteUniquePtl:写部分缓存行到可监听(snoopable)的地址区域。当缓存行在请求方无效(invalid)时,将数据的缓存行写入下一级缓存或内存。
WriteUniqueFull:写完整缓存行到可监听的地址区域。当缓存行在请求方无效(invalid)时,将数据的缓存行写入下一级缓存或内存。
CopyBack Transaction:回写事务是写事务的一个子类。回写事务将一致的数据从缓存移动到下一级缓存或内存。回写交易不需要snoop系统中的其它代理。
WriteBackPtl:将“脏”的部分缓存行写回下一级缓存或内存。仅当支持部分缓存状态时,才支持此事务。
WriteBackFull:将“脏”的完整缓存行写回下一级缓存或内存。WriteBackFull又可以分为两种,WriteBackFullUD和WriteBackFullSD。
WriteCleanFull:将“脏”的完整缓存行写回下一级缓存或内存,并在缓存中保留干净的副本。
WriteEvictFull:将唯一的“干净”数据写回下一级缓存。
4. 原子事务:
所谓的原子事务,指的是此事务就像原子一样是不可分割的,要么所有操作全部完成,要么全部不执行,不存在执行部分操作的情况。在单处理器系统中,能够在单条指令中完成的操作都可以认为是“原子操作“,因为中断只能发生于指令之间 。但是,在对称多处理器结构中就不同了,由于系统中有多个处理器在独立地运行,即使能在单条指令中完成的操作也有可能受到干扰。比如,一个典型的"读-改-写"过程,会涉及两次内存访问,先把数据读出,然后修改,最后写回。如果没有特殊限定,那么在这两次内存访问之间,有可能其它的处理器核发起内存访问 原子事务允许请求者向互连发送带有内存地址的事务,以及要在该内存位置上执行的操作。这种事务类型可以使操作更接近数据所在的位置。这样,对于以原子方式执行操作和以性能高效的方式更新内存位置非常有用。
AtomicStore:发送带有地址和要执行的原子操作的单个数据值。请求中包含数据;发出数据大小为1、2、4或8字节;目标对原子事务中提供的数据值指定的地址位置执行所需的操作;支持的操作数为8;目标返回一个没有数据的完成响应。
AtomicLoad:发送带有地址和要执行的原子操作的单个数据值。请求中包含数据;发出数据大小为1、2、4或8字节;目标对原子事务中提供的数据值指定的地址位置执行所需的操作;支持的操作数为8;完成响应中返回的数据大小要与请求中的数据大小一致。
AtomicSwap:发送数据值,交换值和执行地址。请求中包含数据;发出数据大小为1、2、4或8字节;目标对原子事务中提供的数据值指定的地址位置执行所需的操作;支持的操作数为1;完成响应中返回的数据大小要与请求中的数据大小一致。
AtomicCompare:发送两个数据值(比较值和交换值)执行地址。请求中包含数据;发出数据大小为2、4、8、16或32字节;目标将地址位置的值与比较值进行比较,如果值匹配,目标会将交换值写入寻址位置,如果值不匹配,则目标不会将交换值写入寻址位置。目标返回地址位置的原始值,完成响应的数据大小是请求中数据大小的一半。支持的操作数为1。
SnpMe Variants:上诉原子事务都有一个SnpMe变体,以后缀名[SnpMe]区分。
下面是不同请求的操作码(opcode):
对于AtomicLoad和AtomicStore,ReqOp[2:0]的编码含义为:
ReqOp[3]指示大小端。
3.3.3 请求响应
所有事务都需要有一个完成响应。它通常是结束请求事务所发送的最后一条消息。请求完成响应分为以下几类:
读完成:读完成响应包括数据响应;读完成响应还包括一个缓存状态,指示行缓存行的状态;读完成中不使用字节使能功能。
无数据完成:无数据完成响应不包括数据响应;无数据完成响应也不包括缓存状态,缓存行的状态由请求者决定。
写完成:写完成响应不包括数据响应;写完成响应也不包括缓存状态。
以下是内存请求的响应操作码编码:
3.3.4 监听请求
主代理会生成一个监听请求,以控制缓存代理(被监听者,也称为Snoopee)处的缓存行状态。监听请求有:
SnpToAny:用于获取缓存行副本,无需更改状态;在被监听端,不需要更改缓存行状态。
SnpToC:用于确保缓存行不处于“脏”状态,通常用于执行缓存清理操作;在被监听端,缓存行不可以是“脏”;缓存行(如果有效)预计将更改为“干净”状态,即UC或SC;缓存行可以(但不要求)转移为无效状态。
SnpToS:用于确保缓存行不处于唯一(unique)状态。可以确保在被监听端,在不通知系统中的其它代理的情况下,缓存行不会被更改。当主代理允许一个“脏”缓存行副本在被监听端是SD状态,通常使用SnpToS,而不是SnpToSC。在被监听端,缓存行不可以是唯一状态;缓存行(如果有效)预计将更改为共享状态,即SC或SD;缓存行可以(但不要求)转移为无效状态。
SnpToSC:用于确保缓存行不处于唯一或“脏”状态。当主代理不允许一个“脏”缓存行副本在被监听端,通常使用SnpToSC,而不是SnpToS。在被监听端,缓存行不可以是唯一或“脏”状态;缓存行(如果有效)预计将更改为SC状态;缓存行可以(但不要求)转移为无效状态。
SnpToI:用于将缓存行转移到无效状态。通常用于当另一个代理请求对缓存行执行存储时。
SnpMakeI:用于将缓存行转移到无效状态,而不会从被监听返回任何数据,即使缓存行处于“脏”状态。通常用于另一个代理请求对整个缓存行执行存储时。
SnpChain:将当前监听连接到同一数据包中较早的监听之后。
以下是每种监听请求的初始和最终状态:
SnpOp编码:
请求类型和相对应的监听请求如下表。其中,E表示期望的监听请求;E1表示当被监听端允许切换到SD(SharedDirty)状态时的期望监听请求;E2表示当被监听端不允许切换到SD状态时的期望监听请求;P表示允许的监听请求。
3.3.5 监听响应
监听响应可以带数据,也可以不带。 监听响应中的最终缓存状态必须精确。被监听者可以在发出监听响应后进行任何合法的静默缓存状态转换(Silent Cache State Transition)。 SnpRespOp编码:
3.3.6 MiscOp编码
下表列出了其它的杂项消息类型,包括两类:Credited和Uncredited。所谓的杂项消息就是指这些消息既不属于请求类型和请求响应,也不属于监听请求和监听响应。 NOP,CreditGrant,CreditReturn和ProtErrReport使用杂项信息通道。Generic消息可以使用Uncredited或Credited的杂项消息,其有效负载为2到32字节,其内容由具体实现所定义。
3.3.7 协议错误报告
CCIX组件(如请求代理、主代理、从代理、CCIX端口或CCIX链路)使用ProtErrReport(PER)消息向错误代理(EA)报告错误。该消息使用编码0011的MiscOp[3:0],有效负载为32字节。有关CCIX协议错误报告(PER)的详细信息,后面介绍。
3.3.8 请求缓存状态转移
请求者缓存处(读请求)的缓存状态转换:
上表第一列是发出的读请求类型,第二列是可以启动请求的缓存行的所有允许状态,第三列是事务完成后缓存行的允许状态,第四列是允许的响应。可以结合读请求类型那个章节看这个表。以ReadNoSnp为例,ReadNoSnp是对不可监听的地址区域的读取请求,且接收到的数据不会在请求端缓存。因此缓存行初始和最终状态都是Invalid。 无数据请求的缓存状态转换:
写请求的缓存状态转换:
原子请求的缓存状态转换:
3.3.9 被监听(Snoopee)端状态转移
被监听者在接收到监听请求后,必须根据监听类型的要求转换缓存行的状态。下表是有关每种监听类型的初始和最终状态的信息,以及相应的监听响应。可以结合监听请求那个章节看这张表。
3.3.10 静默缓存状态转移
静默缓存状态转换(Silent Cache State Transition)定义为缓存因内部事件而改变状态,而不通知系统其它部分。下表是合法的静默缓存状态转换。在某些情况下,可以(但不必需)发出一个事务来指示转换已经发生。如果发出这样的事务,则缓存状态转换对互连网络可见,因此也就不被归类为静默转换。
3.3.11 控制Evict和WriteEvictFull的使用
需要一种机制来控制请求代理和主代理之间的Evict(Dataless事务)和WriteEvictFull(写事务)的使用。 每个请求代理都有两个控制比特位,即RAEvictHintCntl和RAWriteEvictFullHintCntl,用于确定请求代理在Evict和WriteEvictFull事务方面的行为。 RAEvictHintCntl(默认值为0):
=0,出于最佳系统性能考虑,不建议从RA发送Evict事务。
=1,出于最佳系统性能考虑,建议从RA发送Evict事务。
RAWriteEvictFullHintCntl(默认值为0):
=0,出于最佳系统性能考虑,不建议从RA发送WriteEvictFull事务。
=1,出于最佳系统性能考虑,建议从RA发送WriteEvictFull事务。
每个主代理也有两个比特位,HAEvictHintCap和HAWriteEvictFullHintCap,用于指示有关使用Evict和WriteEvitFull事务的首选行为。 HAEvictHintCap:
=0,出于最佳系统性能考虑,不建议向HA发送Evict事务。
=1,出于最佳系统性能考虑,建议向HA发送Evict事务。
HAWriteEvictFullHintCap:
=0,出于最佳系统性能考虑,不建议向HA发送WriteEvictFull事务。
=1,出于最佳系统性能考虑,建议向HA发送WriteEvictFull事务。
3.3.12 同时超发请求
不支持同一请求代理对同一地址位置的请求超发(outstanding),除非它们仅包括ReadNoSnp、WriteNoSnp、ReadOnce或WriteUnique的任何组合。 不支持同时向同一请求代理发送到同一地址位置的多个Snoop事务。
3.3.13 对监听冒险的请求
当一个CopyBack请求发现对相同缓存行地址有未完成的监听,或者反过来,一个监听发现对相同缓存行地址有未完成的CopyBack,则会发生请求竞争。注意,如果监听目标代理ID和请求源代理ID不相同,则不视为请求竞争。
上图中,Chip 1中的HA向Chip 0中的RA发起了一个监听;同一时刻Chip 0的RA向Chip 1的HA发起了一个请求(对同一地址)。图中的带数据的请求,可以是CopyBack:WriteBackFullUD、WriteBackFullSD、WriteCleanFullSD或WriteEvickFull。在存在多个CCIX-R、CCIX-H端口的多跳(Muliti-hop)路由中,要求该路径中的每个端口必须包含竞争检测逻辑,以检测请求对监听的竞争。 【待续】
审核编辑 :李倩
-
处理器
+关注
关注
68文章
19273浏览量
229731 -
缓存
+关注
关注
1文章
239浏览量
26674
原文标题:技术分享 | CCIX(四)
文章出处:【微信号:Ithingedu,微信公众号:安芯教育科技】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论