决不可存苟且心,决不可做偷薄事,
决不可学轻狂态,决不可做惫赖人。
-- 曾国藩
提起AMBA(Advanced Microcontroller Bus Architecture),估计做前端逻辑设计的朋友们都知道,尤其是称霸业内多年的AHB,AXI这些。
所以咱们花点时间,来好好研究一下这些总线协议都是什么。开始之前,先说一下,ACE是AXI Coherency Extensions的缩写。顾名思义,ACE就是AXI加上支持一致性的扩展。如果有人对AXI不熟悉,可以去网上找找介绍的文章,或者看看spec。这个系列尽量讲扩展的部分。关于cache和一致性的基础知识,可以参考以前的系列文章,《CPU设计之Cache -- 一致性初探》及其它。
AMBA发展到现在,已经到了第5代。命名规则简单粗暴,直接是协议名加上第几代的数字。像我们熟悉的AXI,从AXI3发展到AXI4,再发展到AXI5。ACE协议是在AMBA4中才引入的,在AMBA5中叫做ACE5。因为在发展过程中,协议特性/内容肯定会有一些增减,为了不引起歧义,这一系列文章尽量保证同ARM的命名规则相同。但是,难免会有手滑笔误,请大家多担待,欢迎随时指出错误。
在AMBA4中,ACE协议有两个变体:ACE和ACE-Lite。在AMBA5中,ACE有四个变体,分别是:ACE5,ACE5-Lite,ACE5-LiteDVM,ACE5-LiteACP。不管怎么变,其主体都是ACE,其它变体是围绕ACE做的一些改进和删减。
开始之前,先看几个基本概念:
Caching master:指的是具有硬件一致性缓存的处理器单元。这个处理器有一个snoop地址通道和一个snoop响应通道,还可以选择带一个snoop数据通道。这里插一句,这三个通道是ACE协议比AXI协议多出来的,后面会讲。
Initiating master:发起主机,指的是可以发出一个事务以启动后续一系列事件的处理器单元。
Snooped master:被监听主机,指的是可以接收snoop事务的处理器单元。
暂时看不懂也不要着急,其实这里想说的是,一个有着硬件一致性缓存的处理器,既可以主动发起(initiating)一系列的一致性事务,也必须监听其它处理器发出的一致性事务。区分这几个概念,是为了后面能更好的描述。
缓存一致性(cache coherency)要解决的是空间上的问题,也就是说,如果多个处理器同时缓存了主存(main memory)的同一段数据,那么这些处理器之间必须要保证数据的一致,如果某个处理器改动了数据,就要通知其它处理器知晓,否则会引起应用程序运行不一致。对此,ACE协议要求,如果cache中的一个缓存行(cache line)是整个系统中的唯一拷贝,那么拥有这个缓存行的处理器单元可以修改数据,同时不必通知其它主机;如果这个缓存行数据在整个系统中存在其它拷贝(副本),则拥有这个缓存行的处理器在修改数据的同时,必须通知其它处理器知晓这个改动。所以,对于缓存行来说,记录其当前状态至关重要。为此,在ACE里面提出了一个五种状态的缓存模型(cache state model)。
图1 ACE缓存状态模型
Invalid:简称I,表示该缓存行无效
UniqueClean:简称UC,表示缓存行是唯一的,并且数据未被修改
UniqueDirty:简称UD,表示缓存行是唯一的,但是数据被修改过,拥有该缓存行的主机必须保证修改后的数据要写回到主存
SharedClean:简称SC,缓存行可能存在其它拷贝,但该缓存行数据没有被修改过
SharedDirty:简称SD,缓存行可能存在其它拷贝,但该缓存行数据被修改过
这里要注意的是,对于状态为SC或者SD的缓存行来说,当前时刻可能,但不一定在其它cache中存在拷贝。想一下,为什么?试想一种简单的场景,处理器A,B和C都在自己的cache中缓存了相同地址的数据,且没有改动数据,那么都会标记为SC状态。随时各自运行程序,core B的这条缓存行被替换掉(replacement)了。这时,由于缓存行是clean的,处理器B就没必要这个行为放到总线上通知处理器A和C,这会导致白白浪费系统带宽。而且对于处理器A和C来说,也不需要知道。
ACE的事务分为几大类:
Non-snooping,用于访问不在其它处理器单元的cache中的内存位置,因此不需要snoop事务,主要用于non-shareable和device memory(还记得device memory是啥不?)。
ReadNoSnoop
WriteNoSnoop
Coherent,此类事务用来访问shareable的内存位置,因为其它核也能访问到这些区域,因此需要维护一致性。
ReadClean:该事务表示请求读取的处理器只能接受clean的缓存行,不能接受dirty的。该事务用于不能接受dirty缓存行,或者是写通(write through)缓存的处理器。
ReadNotSharedDirty:该事务表示请求读的处理器可以接受除SharedDirty状态外的缓存行
ReadShared:该事务表示请求读的处理器可以接受任何状态的缓存行
ReadUnique:该事务用于存储(store)部分缓存行,且此处理器没有缓存拷贝的情况下。ReadUnique事务获得数据拷贝,并确保没有其它拷贝在别的处理器。
CleanUnique:该事务用于存储(store)部分缓存行,且此处理器拥有拷贝的情况下。CleanUnique清除其它的拷贝,如果其它拷备是dirty的,要保证dirty的缓存行写回到主存
MakeUnique:该事务用于存储整条缓存行,其它的拷贝会被无效(invalidate)
ReadOnce:用于获得不需要复制到缓存的数据快照
WriteUnique:用于在发出写事务前,清除该缓存行的所有拷贝。该事务可以用来保证在写事务前,所有的dirty数据写回到主存
WriteLineUnique:与WriteUnique不同的是,仅用于全缓存行
Memory update,此类事务更新内存,但是不需要监听其它处理器
WriteBack:把dirty的缓存行写回到主存,并释放这条缓存行
WriteClean:
把dirty的缓存行写回到主存,但是保持这条缓存行
WriteEvict:
逐出一条clean的缓存行,可以用来把缓存行写到下层的cache中,比如L3。
WriteEvict并不需要更新主存
Evict:
用来指示一条缓存行的地址被逐出,可以用来构建snoop filter。
该事务没有数据传输
Cache maintenance
CleanShared:一个处理器可以通过这个事务对其它处理器的缓存进行clean操作。有dirty缓存行的snooped cache接收到CleanShared,必须写回到主存,该snooped cache可以保存本地的副本
CleanInvalid:
一个处理器可以通过这个事务对其它处理器的缓存进行clean和invalidate操作。
如果snooped cache拥有该条缓存行,并且是clean状态,那么要移除本地拷贝;
如果是dirty状态,要提供该条缓存行以写回到主存,并移除本地拷贝
MakeInvalid:
一个处理器可以通过这个事务对其它处理器的缓存进行invalidate操作。
Snooped cache需要移除本地拷贝,但不需要提供数据,即使这条缓存行是dirty的。
Snoop
Barrier
DVM(distributed virtual memory)
在spec中给出了几种应用场景。先看对于可共享区域的load操作:
发起处理器通过读地址通道发出一个读请求事务;
互连网络接收到读请求事务,判断在哪些处理器中有此地址的缓存备份,并发送事务给用有拷贝的处理器,也就是前面说的snooped master;
被监听主机通过snoop响应通道发送确认,如果有需要的话,通过snoop数据通道发送数据;
如果被监听主机发出数据,互连网络通过读数据通道把数据发送给发起主机;
如果被监听主机不需要发出数据,那么互连网络需要发送事务给主存,得到数据后通过读数据通道送给发起主机;
发起主机通过RACK指示此次读请求完成
如果是store操作,除了发起方,其它的缓存拷贝必须被无效掉,这样才能保证发起方的缓存数据是唯一的。如果其它处理器还需要这段数据,可以发出读请求,把更新后的数据再次放入缓存。对于store部分缓存行还是整条缓存行,发出的具体事务略有不同。
祝大家周末愉快!
领取专属 10元无门槛券
私享最新 技术干货