ACE事务类型体系:从信号到语义的映射
引言
在AXI协议中,事务类型相对简单:读事务和写事务,加上一些属性信号来区分不同的内存类型和访问特性。但在ACE协议中,事务类型体系变得复杂而丰富。这种复杂性不是无意义的堆砌,而是为了精确表达一致性操作的语义。
ACE协议通过扩展AXI的信号定义,引入了一套完整的事务类型体系。这套体系不仅包括传统的读写操作,还包括专门用于一致性管理的事务类型,如Clean、Make、Evict等。理解这套事务类型体系,关键在于理解每个事务类型背后的语义,以及这些语义如何通过信号编码来表达。
本文将从信号编码出发,深入解析ACE的事务类型体系,探讨事务类型与缓存状态模型的关系,揭示从信号到语义的映射机制。
信号扩展:从AXI到ACE的演进
ACE协议在AXI的基础上添加了多个新信号,这些信号共同构成了事务类型表达的基础。理解这些信号的含义和作用,是理解ACE事务类型体系的前提。
最重要的信号扩展是ARSNOOP和AWSNOOP。ARSNOOP[3:0]是读地址通道上的4位信号,用于指定读事务的一致性类型。AWSNOOP[2:0]是写地址通道上的3位信号,用于指定写事务的一致性类型。这两个信号是ACE协议的核心,它们将简单的AXI读写操作扩展为丰富的一致性操作集合。
ARDOMAIN[1:0]和AWDOMAIN[1:0]是域(Domain)信号,用于指定事务的一致性域。ACE协议定义了四个域级别:Non-shareable(非共享)、Inner Shareable(内部共享)、Outer Shareable(外部共享)和System(系统级)。域的概念允许系统设计者灵活控制一致性的范围,例如,可以将某些Master排除在一致性协议之外以降低开销。
ARBAR[1:0]和AWBAR[1:0]是Barrier信号,用于指定Barrier事务。Barrier事务用于建立事务之间的顺序关系,这在多核系统中对于保证内存一致性至关重要。
RRESP[3:2]是读数据通道上的扩展响应位,用于传递一致性相关的信息。其中,RRESP[3]是IsShared位,表示返回的数据是否可能被其他缓存共享;RRESP[2]是PassDirty位,表示返回的数据是否是脏的(相对于主存已修改)。
这些信号的组合使用,使得ACE可以在AXI的框架内表达丰富的一致性语义。例如,一个ReadUnique事务通过ARSNOOP=0b0111、ARDOMAIN=0b10(Outer Shareable)来编码,表示这是一个需要获取独占读取权限的一致性读操作。
事务类型分类:六组事务的语义
ACE协议将事务类型分为六个主要组:Read事务组、Clean事务组、Make事务组、Write事务组、Evict事务组,以及特殊的Barrier和Cache Maintenance事务。每个事务组都有其特定的语义和用途。
Read事务组包括ReadNoSnoop、ReadOnce、ReadClean、ReadNotSharedDirty、ReadShared和ReadUnique。这些事务的共同特点是它们都通过读地址通道发出,通过读数据通道返回数据。但它们的一致性语义各不相同。
ReadNoSnoop是最简单的读事务,它不对其他缓存进行Snoop操作。这个事务类型用于非共享内存区域,或者用于不需要一致性保证的访问。从一致性协议的角度看,ReadNoSnoop等同于AXI的普通读事务。
ReadOnce是一个基本的一致性读事务。它允许Interconnect决定是否进行Snoop操作,以及返回的数据是否可能被共享。ReadOnce提供了最大的灵活性,Interconnect可以根据系统状态和优化策略来决定具体的处理方式。
ReadClean是一个更具体的一致性读事务。它要求返回的数据必须是Clean的,即如果数据来自其他缓存,该缓存必须先将脏数据写回主存。这个事务类型适用于需要确保数据与主存一致的场景。
ReadNotSharedDirty是ReadClean的一个变体。它要求返回的数据不能是SharedDirty状态,但可以是UniqueDirty状态。这个事务类型允许在独占的情况下延迟写回,但在共享的情况下必须写回。
ReadShared是一个共享读事务。它明确表示Master希望以共享方式获取数据,即使数据当前是独占的,也应该转换为共享状态。这个事务类型适用于预期会有多个Master同时读取的场景。
ReadUnique是一个独占读事务。它要求获取数据的独占访问权限,所有其他缓存中的副本必须被无效化。这个事务类型通常用于准备执行写操作的场景,因为只有独占状态的缓存行才能直接写入。
Clean事务组包括CleanUnique、CleanShared和CleanInvalid。这些事务的共同特点是它们不返回数据,只执行一致性状态转换操作。
CleanUnique用于将其他缓存中的副本无效化,同时确保当前缓存获得独占权限。如果其他缓存持有脏数据,必须先写回主存。这个事务类型通常用于准备执行写操作,但不需要读取当前数据的场景。
CleanShared用于确保所有缓存中的副本都是Clean的。这个事务类型是缓存维护操作的一部分,用于在软件需要时确保数据已经写回主存。
CleanInvalid用于清理并无效化所有缓存中的副本。这个事务类型也是缓存维护操作的一部分,用于在软件需要时确保所有缓存都不再持有该数据的副本。
Make事务组包括MakeUnique和MakeInvalid。这些事务也不返回数据,只执行状态转换操作。
MakeUnique用于将其他缓存中的副本无效化,使当前缓存获得独占权限。与CleanUnique不同,MakeUnique不要求脏数据写回主存,脏数据可以直接丢弃。这个事务类型适用于准备写入整个缓存行的场景,因为不需要保留旧数据。
MakeInvalid用于无效化所有缓存中的副本,但不要求写回脏数据。这个事务类型是缓存维护操作的一部分,用于在软件需要时快速无效化缓存。
Write事务组包括WriteNoSnoop、WriteUnique、WriteLineUnique、WriteBack、WriteClean和WriteEvict。这些事务的共同特点是它们都通过写地址通道发出,通过写数据通道传输数据,通过写响应通道返回响应。
WriteNoSnoop是最简单的写事务,它不对其他缓存进行Snoop操作。这个事务类型用于非共享内存区域,或者用于不需要一致性保证的写入。
WriteUnique是一个一致性写事务,它要求获取独占写入权限,同时将数据写入主存。这个事务类型适用于部分缓存行的写入,需要先获取当前数据,然后修改部分字节,最后写回。
WriteLineUnique是一个完整缓存行的写入事务。它要求获取独占权限,但不需要先读取数据,因为整个缓存行都会被覆盖。这个事务类型适用于写入整个缓存行的场景。
WriteBack用于将脏数据写回主存。这个事务类型是缓存管理的一部分,用于在缓存行被驱逐前将脏数据写回。
WriteClean也用于将数据写回主存,但它不要求数据是脏的。这个事务类型可以用于确保数据已经写回主存,即使数据实际上是Clean的。
WriteEvict用于在驱逐UniqueClean状态的缓存行时通知系统。这个事务类型允许系统优化缓存层次结构,常用于缓存层级之间的数据迁移。例如,可以将缓存行从L2缓存中逐出,但迁移到L3缓存。
Evict事务组只有一个事务类型:Evict。这个事务用于通知系统某个缓存行已经被驱逐,不需要传输数据。Evict事务是缓存管理的一部分,用于支持外部Snoop Filter等优化机制。
信号编码:从位模式到语义
理解ACE事务类型的关键在于理解信号编码如何映射到语义。这种映射不是随意的,而是经过精心设计的,使得相似的语义使用相似的编码模式。
对于读事务,ARSNOOP[3:0]的编码遵循一定的规律。最低位(bit 0)通常用于区分是否需要Snoop操作。例如,ReadNoSnoop的编码是0b0000,表示不需要Snoop;而其他读事务的编码都设置了某些位,表示需要Snoop操作。
中间位(bit 1和bit 2)用于表达更细粒度的语义。例如,ReadClean的编码是0b0010,其中的bit 1表示要求Clean数据;ReadShared的编码是0b0001,其中的bit 0可能表示共享意图;ReadUnique的编码是0b0111,多个位的组合表达了独占的语义。
最高位(bit 3)通常用于区分特殊的事务类型。例如,CleanShared的编码是0b1000,CleanInvalid的编码是0b1001,MakeUnique的编码是0b1100,MakeInvalid的编码是0b1101,这些缓存维护相关的事务都设置了bit 3。
对于写事务,AWSNOOP[2:0]的编码相对简单,因为写事务的类型较少。WriteNoSnoop的编码是0b000,WriteUnique的编码是0b000或0b001(取决于是否写入整个缓存行),WriteBack的编码是0b011,WriteClean的编码是0b010,Evict的编码是0b100,WriteEvict的编码是0b101。
这种编码设计使得硬件实现可以高效地解码事务类型。例如,可以通过简单的位检查来判断是否需要Snoop操作,或者判断事务的特定属性。这种设计权衡了编码的灵活性和解码的效率。
Domain概念:一致性范围的精确控制
Domain(域)概念是ACE协议的一个重要创新。它允许系统设计者精确控制一致性的范围,这对于复杂系统设计至关重要。
Non-shareable域表示事务只涉及单个Master,不需要与其他Master协调。这个域用于私有内存区域,或者用于不需要一致性保证的访问。在Non-shareable域中,事务的行为类似于AXI的普通事务,不会触发Snoop操作。
Inner Shareable域表示事务涉及一组相关的Master,这些Master通常属于同一个处理器集群或子系统。Inner Shareable域允许在这些Master之间维护一致性,而不影响其他Master。这个域的设计考虑了多级缓存层次结构,例如,一个处理器集群可能有共享的L2缓存,集群内的Master通过Inner Shareable域协调。
Outer Shareable域表示事务涉及更大范围的Master,包括所有Inner Shareable域的Master,以及可能存在的其他Master。Outer Shareable域用于系统级的一致性协调,例如,多个处理器集群之间的数据共享。
System域表示事务涉及系统中的所有Master。System域主要用于设备内存(Device memory),这种内存类型不允许缓存,因此不需要缓存一致性协议。
Domain的选择不仅影响Snoop操作的范围,还影响事务的语义。例如,一个ReadUnique事务在Inner Shareable域中只会Snoop同一域内的Master,而在Outer Shareable域中会Snoop更大范围的Master。这种设计允许系统在保证正确性的同时,最小化Snoop操作的开销。
在实际系统设计中,Domain的选择需要仔细考虑。过于宽泛的Domain会增加Snoop操作的开销,而过于狭窄的Domain可能导致一致性保证不足。ACE协议通过提供多个Domain级别,为系统设计者提供了灵活的权衡空间。
事务类型与状态模型:语义的精确映射
ACE事务类型体系的设计与五状态缓存模型紧密相关。每个事务类型都对应特定的状态转换语义,理解这种映射关系对于正确使用ACE协议至关重要。
ReadOnce事务可以导致多种状态转换,具体取决于系统的当前状态和Interconnect的决策。如果数据不在任何缓存中,ReadOnce可以将缓存行转换为UniqueClean状态;如果数据在其他缓存中且是Clean的,ReadOnce可以将缓存行转换为SharedClean状态;如果数据在其他缓存中且是Dirty的,ReadOnce可以将缓存行转换为SharedDirty状态。
ReadClean事务要求返回Clean数据,因此它不能导致UniqueDirty或SharedDirty状态。如果数据在其他缓存中且是Dirty的,必须先写回主存,然后才能返回给请求者。ReadClean通常导致UniqueClean或SharedClean状态。
ReadShared事务明确要求共享访问,因此它通常导致SharedClean或SharedDirty状态。即使数据当前是独占的,ReadShared也会将其转换为共享状态。
ReadUnique事务要求独占访问,因此它通常导致UniqueClean或UniqueDirty状态。所有其他缓存中的副本必须被无效化,确保请求者获得独占权限。
CleanUnique事务用于获取独占权限而不读取数据。它会导致其他缓存中的副本被无效化,如果副本是Dirty的,必须先写回主存。CleanUnique通常用于准备执行写操作但不需要读取当前数据的场景。
MakeUnique事务也用于获取独占权限,但它不要求脏数据写回。MakeUnique通常用于准备写入整个缓存行的场景,因为不需要保留旧数据。
WriteUnique事务同时执行写入和一致性操作。它要求获取独占权限,用于在发出写事务前,清除该缓存行的所有拷贝。该事务可以用来保证在写事务前,所有的dirty数据写回到主存。WriteUnique通常用于缓存行中一部分的修改(Read,Modify,Write)。
WriteLineUnique事务用于写入整个缓存行。它要求获取独占权限,但不需要先读取数据。WriteLineUnique通常用于写入整个缓存行的场景,可以避免不必要的数据传输。
WriteBack和WriteClean事务用于将数据写回主存。WriteBack(写回并释放): Master 将一个处于 Dirty 状态(UniqueDirty 或 SharedDirty)的缓存行写回到内存或下级缓存,并且不再保留该缓存行的副本。这个过程通常发生在驱逐(Eviction)时,即缓存空间不足,需要腾位子给新数据。WriteClean(写回并保留): Master 将 Dirty 数据写回,但继续保留该缓存行的副本。写回后,该缓存行的状态会从 Dirty 变为 Clean(因为数据已经与内存一致了)。这通常用于同步(Sync)操作,确保内存得到更新,但 Master 预计不久后还会用到这些数据。
这种精确的映射关系使得ACE协议可以表达丰富的一致性语义,同时保持协议的严谨性。每个事务类型都有明确的状态转换语义,这使得系统行为可以预测和验证。
事务约束:协议正确性的保证
ACE协议为不同的事务类型定义了各种约束,这些约束确保了协议的正确性和一致性。理解这些约束对于正确实现和使用ACE协议至关重要。
缓存行大小约束是最基本的约束之一。某些事务类型必须精确匹配缓存行大小,例如ReadClean、ReadShared、ReadUnique、CleanUnique、MakeUnique等。这些事务类型的一致性语义要求它们操作整个缓存行,因此不能是部分缓存行操作。
对于缓存行大小事务,地址必须对齐到缓存行边界,突发长度必须是1、2、4、8或16个传输,突发类型必须是INCR或WRAP(不支持FIXED)。这些约束确保了事务可以高效地处理,同时保持了协议的一致性。
ReadOnce和WriteUnique事务不受缓存行大小约束,这使得它们可以用于任意大小的访问。这种设计允许传统的不关心缓存行大小的组件在一致性环境中工作,只需要添加适当的Domain属性。
Domain约束限制了哪些Domain可以用于哪些事务类型。例如,缓存维护事务(CleanShared、CleanInvalid、MakeInvalid)可以使用Non-shareable、Inner Shareable或Outer Shareable域,但不能使用System域。这种约束确保了缓存维护操作的正确范围。
内存类型约束限制了哪些内存类型可以用于哪些Domain。例如,Device内存(AxCACHE[1]=0)只能使用System域,而Cacheable内存(AxCACHE[3:2]≠0)不能使用System域。这种约束确保了不同类型内存的正确处理。
这些约束虽然增加了协议的复杂性,但它们是确保协议正确性的必要条件。违反这些约束可能导致系统行为未定义,或者一致性保证失效。
实际应用:事务类型的选择策略
在实际系统设计中,选择合适的事务类型是一个重要的设计决策。不同的选择会导致不同的性能特征和一致性保证。
对于读操作,选择ReadOnce、ReadClean、ReadShared还是ReadUnique,取决于具体的应用场景。如果只是简单地读取数据,ReadOnce提供了最大的灵活性,允许Interconnect根据系统状态优化处理。如果需要确保数据是Clean的(例如,在DMA操作前),应该使用ReadClean。如果预期会有多个Master同时读取,应该使用ReadShared以优化共享访问。如果准备执行写操作,应该使用ReadUnique以获取独占权限。
对于写操作,选择WriteUnique还是WriteLineUnique,取决于写入的范围。如果是部分缓存行写入,必须使用WriteUnique,因为它需要先读取当前数据。如果是整个缓存行写入,应该使用WriteLineUnique,因为它可以避免不必要的数据读取。
对于缓存管理,选择CleanUnique还是MakeUnique,取决于是否需要保留旧数据。如果需要保留旧数据(例如,部分写入),应该使用CleanUnique。如果不需要保留旧数据(例如,整个缓存行写入),应该使用MakeUnique。
这些选择策略反映了ACE协议设计的灵活性。通过提供多种事务类型,ACE允许系统设计者根据具体需求选择最合适的操作,从而在保证正确性的同时优化性能。
总结:从信号到语义的完整映射
ACE事务类型体系通过精心设计的信号编码,实现了从底层信号到高层语义的完整映射。这种映射不是简单的枚举,而是基于一致性协议理论的系统化设计。
理解ACE事务类型体系,不仅要记住每个事务类型的名称和编码,更要理解它们背后的语义和设计动机。每个事务类型都是为了解决特定的问题而设计的,理解这些问题有助于正确选择和使用事务类型。
从信号编码的角度看,ACE通过扩展AXI的信号定义,在保持AXI基本架构的同时,添加了丰富的一致性语义。这种扩展设计体现了ACE协议的设计哲学:在AXI的基础上添加一致性功能,而不是重新设计整个协议。
从语义映射的角度看,ACE事务类型与缓存状态模型紧密相关。每个事务类型都对应特定的状态转换语义,这种精确的映射关系确保了协议的正确性和一致性。
在实际应用中,选择合适的事务类型需要综合考虑性能、一致性和实现复杂度。ACE协议通过提供多种事务类型,为系统设计者提供了灵活的权衡空间,使得可以在保证正确性的同时优化系统性能。
在后续的文章中,我们将深入探讨Snoop机制,看看这些事务类型如何通过Snoop操作来实现一致性协调,以及Interconnect如何根据事务类型生成相应的Snoop操作。
本文是ACE协议学习系列的第三篇,下一篇将深入探讨Snoop机制,揭示ACE一致性的核心引擎如何工作。