内存类型device bufferable详解
好的,我们来深入解析 AXI 协议中一个相对微妙且容易混淆的概念:Device Bufferable。
这个概念的关键在于理解它与 Device Non-bufferable 的对比,以及为什么在“设备”区域这个本应严格的地方,会允许“缓冲”这种优化存在。
核心结论先行
- Device Bufferable 是一种混合属性。它保持了 Device 类型的关键特性(主要是非缓存和对副作用的保护),但允许写操作进行缓冲。
- 目标:在基本保证设备访问正确性的前提下,适度提升系统性能。
- 风险:如果使用不当,可能会破坏设备操作的严格顺序,因此必须谨慎用于特定的设备。
详细解析
在 AXI 协议中,内存属性由 AxCACHE[3:0] 信号定义。Device Bufferable 通常对应于 AxCACHE = 4'b0010(即 Bufferable=1, Cacheable=0, Read-Allocate=0, Write-Allocate=0)。
让我们分解这个配置:
-
Device Type (C=0, RA=0, WA=0):
Non-cacheable: 这是核心。访问绝不能通过缓存来完成。每次读操作都必须从终点设备获取数据,绝不能从缓存返回旧值。这保护了设备读操作的副作用(例如,读状态寄存器会清零标志位)。Non-allocate: 访问绝不会导致缓存行分配。- 这保证了它仍然属于“设备”范畴,而不是“内存”范畴。
-
Bufferable (B=1):
- 这是与
Device Non-bufferable的唯一区别,也是所有奥秘所在。 - 它允许写操作被放入写缓冲区中。发起写操作的主机(如 CPU)可以立即得到完成响应,而无需等待写操作真正到达最终的设备。
- 写缓冲区会异步地将数据最终写入设备。
- 这是与
为什么需要 Device Bufferable?—— 性能权衡
Device Non-bufferable 虽然安全,但性能差。因为每次写操作,CPU 都必须停滞等待,直到数据穿过整个系统互联,被设备接收并返回响应。这对于慢速设备来说尤其痛苦。
Device Bufferable 就是为了缓解这个性能瓶颈。它允许 CPU 将要写入设备的数据快速放入一个本地的或系统的写缓冲区,然后就可以继续执行后续指令,无需等待。这隐藏了写延迟,大大提升了 CPU 的执行效率。
潜在风险与适用场景
允许缓冲带来了性能收益,但也引入了风险。关键在于:什么样的设备能够容忍这种“写操作可能延迟或稍后重排”的行为?
适用场景(能容忍缓冲的设备):
-
单次写操作无关顺序: 对设备的多次写操作之间没有严格的先后顺序要求。
- 例子: 向一个帧缓冲区(Frame Buffer)写入像素数据。先写左上角的像素还是先写右下角的像素,通常不会影响最终显示一帧完整的画面。允许这些写操作被缓冲和重新排序可以极大地提高数据填充速率。
-
写入后无需立即检查状态: 写入设备后,程序不会马上读取该设备的状态来依赖写入的结果。
- 例子: 配置一个 DMA 引擎的源地址、目标地址和长度。通常,在启动 DMA 之前,会配置好几个寄存器。只要在启动(通常是一个
Device Non-bufferable的写操作)之前,所有这些配置写入都已完成即可。这些配置写入的顺序可能并不重要。
- 例子: 配置一个 DMA 引擎的源地址、目标地址和长度。通常,在启动 DMA 之前,会配置好几个寄存器。只要在启动(通常是一个
-
大量数据写入: 设备有一个大的数据端口(如 FIFO),CPU 需要连续写入大量数据。使用缓冲可以显著提高吞吐量。
不适用场景(绝对不能用的设备):
-
控制/命令寄存器: 写入操作有严格的顺序。
- 例子: 必须先写“模式寄存器”再写“启动命令寄存器”。如果“启动命令”因为被缓冲而先于“模式配置”到达设备,设备会以错误的配置启动,导致错误。
-
有严格时序要求的寄存器:
- 例子: 一个中断应答寄存器。写入它来清除中断必须在ISR(中断服务例程)中立即完成,绝不能延迟,否则可能导致中断重复触发。
-
写入后立即读状态: 如果写入后程序立刻读取设备状态来检查写入是否生效,使用
Device Bufferable会出问题。因为读操作(非缓存,必须直达设备)可能会在写操作(还在缓冲区)之前到达设备,从而读到旧的、未更新的状态。
对比总结:Device Bufferable vs. Device Non-bufferable
| 特性 | Device Non-bufferable (AxCACHE=0000) | Device Bufferable (AxCACHE=0010) |
|---|---|---|
| 核心特性 | 严格、保守、安全 | 性能优化、有风险 |
| 读操作 | 直达设备,保护副作用 | 直达设备,保护副作用 |
| 写操作 | 直达设备,CPU等待完成确认 | 可进入写缓冲区,CPU立即继续执行 |
| 写顺序 | 严格保持程序顺序 | 可能被重排(相对于其他缓冲写) |
| 性能 | 差(CPU 停滞等待) | 好(隐藏写延迟) |
| 适用场景 | 所有关键控制寄存器、命令寄存器、状态寄存器 | 大数据量 FIFO、帧缓冲区、顺序无关的配置寄存器 |
软件/系统设计视角
在设置系统内存映射时,软件工程师(或系统架构师)必须非常小心地划分地址空间。
- 关键设备寄存器(控制、状态、命令)必须映射为 Device Non-bufferable。这是最安全的选择。
- 设备的数据缓冲区(如网卡的数据包缓冲区、显卡的显存)可以评估后映射为 Device Bufferable,以提升性能。
- Modern Terminology: 在 ARMv8 架构中,这些概念通常被映射到内存属性:
- Device Non-bufferable ->
MT_DEVICE_nGnRnE(最严格的设备类型) - Device Bufferable ->
MT_DEVICE_nGnRE(稍宽松的设备类型, ‘E’ 代表 Early Write Acknowledgement,即允许缓冲确认)
- Device Non-bufferable ->
总结
Device Bufferable 是 AXI 协议在设备访问的正确性和系统性能之间所做的一种权衡。它放宽了“缓冲”限制以换取更高的写吞吐量,但仍坚持“非缓存”以保护设备操作的副作用。
使用它的黄金法则是: 只有当你能百分之百确定对目标设备的多次写操作顺序无关,或者延迟写入不会影响程序逻辑时,才可以使用 Device Bufferable。否则,请始终使用更安全的 Device Non-bufferable。
浙公网安备 33010602011771号