内存类型Normal Non-cacheable Non-bufferable详解
好的,我们来深入探讨 AXI 协议中一个非常特殊且重要的概念:Normal Non-cacheable Non-bufferable。
这个属性组合非常有趣,因为它看似与 Device Non-bufferable 完全相同(AxCACHE 值都是 4'b0000),但其内在含义和行为却有着本质的区别。理解这个区别是掌握 AXI 内存属性精妙之处的关键。
核心结论先行
- 是什么:
Normal Non-cacheable Non-bufferable是一种内存类型属性,它用于访问普通内存区域(如 DDR),但要求访问不能被缓存,并且写操作必须直达内存。 - 与 Device 的关键区别: 虽然
AxCACHE值相同(0000),但目标地址区域是 Normal 而不是 Device。这决定了系统互联(Interconnect)对访问的顺序要求和副作用处理完全不同。 - 核心价值: 它为共享的、对数据一致性有严格要求的普通内存区域提供了保障,确保读写操作能够及时地被系统其他参与者看到,同时避免了缓存带来的复杂性和开销。
详细解析
1. 属性定义:AxCACHE = 4‘b0000
- Non-cacheable (C=0): 禁止缓存。所有读写操作都必须直接针对主内存(DDR),不能与缓存发生任何关系。
- Non-bufferable (B=0): 禁止缓冲。对于写操作,必须在数据真正到达内存控制器并写入 DDR 之后,才能向发起者(如 CPU)返回完成信号。这确保了写操作完成的真实性。
- Non-allocate (RA=0, WA=0): 自然不会分配缓存行。
从信号上看,它和 Device Non-cacheable Non-bufferable 一模一样。奥秘在于另一个独立的信号:AxDOMAIN 或地址映射类型。
2. 内存类型:Normal vs. Device
这是理解两者区别的核心钥匙。AXI 协议中,一次访问的目标地址空间要么是 Normal,要么是 Device。这通常在系统设计时由地址解码器决定。
-
Normal Memory: 指的是像 DDR、SRAM 这样的普通内存。它们的特性是:
- 无副作用: 读一个地址 1000 次,得到的数据都一样,不会改变内存本身的状态。
- 支持重试: 如果访问暂时失败(例如 DDR 刷新),可以简单地重试该操作。
- 可预测的访问时间: 访问延迟相对稳定。
- 地址无关性: 访问地址 0x1000 和 0x1004 在行为上没有依赖关系。
-
Device Memory: 指的是映射到硬件设备寄存器的地址空间。它们的特性是:
- 有副作用: 读操作可能清除状态位,写操作可能触发动作。
- 不支持重试: 对寄存器的“读-修改-写”操作如果被重试,可能导致灾难性后果。
- 访问时间不可预测: 设备可能响应很慢,或者需要等待某些条件。
- 地址相关/顺序敏感: 写入寄存器 A 和 B 的顺序至关重要。
系统互联会根据目标地址是 Normal 还是 Device 来对拥有相同 AxCACHE 属性的事务采取不同的处理策略。
Normal Non-cacheable Non-bufferable 的行为与用途
由于目标区域是 Normal 内存,系统互联会以对待普通内存的方式来处理这些事务,但附加了“非缓存”和“非缓冲”的严格要求。
主要行为:
- 直达内存: 读写操作绕过所有缓存,直接与主内存交互。
- 写确认可靠: 写操作的完成信号(
BRESP)意味着数据已物理写入 DDR,而不是在某个中间缓冲区。 - 顺序性较弱: 虽然
Non-bufferable暗示了某种顺序,但对 Normal 区域的访问,互联仍然可能在一定程度上对访问进行重排序以优化性能,只要这不会破坏内存一致性模型(如 ARM 的弱内存模型)。这与对 Device 区域的严格强序要求形成对比。
典型用途:
-
高度共享的 DMA 缓冲区:
- 场景: 一个处理器核心(CPU)和另一个总线主设备(如 DSP、另一个 CPU 集群、硬件加速器)需要通过一片共享内存来传递数据。
- 为什么用它: 如果 CPU 缓存了这片内存,它看到的数据可能不是最新的(DMA 可能已经更新了 DDR 中的数据)。反之,CPU 写入缓存的数据也可能迟迟不写回 DDR,DMA 设备就读不到新数据。将其设置为
Non-cacheable确保了所有访问者都直接读写 DDR,数据视图天然一致。Non-bufferable确保了 CPU 在收到写完成信号时,数据肯定已被 DMA 设备可见,CPU 可以安全地通知 DMA 设备“数据已就绪”。
-
对时间敏感的数据结构:
- 场景: 一个用于任务队列或信号量的共享内存区。当一个核心释放一个信号量(写入内存)时,其他核心必须能立刻看到这个变化,而不是等到缓存行被写回。
- 为什么用它:
Non-bufferable保证了写入能及时到达内存。Non-cacheable保证了其他核心在读取时能直接从内存获取最新值,而不是自己缓存里的旧值。这实现了类似“存储-释放”内存序的效果。
-
避免缓存抖动的场景:
- 场景: 处理器需要访问一个非常大的缓冲区(例如处理一帧图像数据),但只会访问一次。如果这些数据被缓存,会污染缓存,将可能更有用的指令或数据挤出去,反而降低整体性能。
- 为什么用它: 标记为
Non-cacheable,可以避免无用的缓存填充,节省宝贵的缓存空间给更需要的代码和数据。
与相似属性的对比
| 属性 | AxCACHE | 目标区域 | 核心行为与用途 |
|---|---|---|---|
| Device Non-cacheable Non-bufferable | 4‘b0000 | Device | 安全访问设备寄存器。强制严格顺序,保护副作用。用于控制、状态寄存器。 |
| Normal Non-cacheable Non-bufferable | 4‘b0000 | Normal | 保障一致性的共享内存。数据直达内存,写操作确认可靠。用于多主设备间共享的 DMA 缓冲区、信号量等。 |
| Normal Non-cacheable Bufferable | 4‘b0001 | Normal | 高效的普通内存访问。写操作可缓冲,CPU 无需等待。用于无严格顺序要求的 DMA 缓冲区,提升性能。 |
| Normal Write-Back Cacheable | 4‘b1111 | Normal | 高性能私有内存。充分利用缓存,性能最佳。用于处理器内部的私有数据和代码。 |
总结
Normal Non-cacheable Non-bufferable 是一种专门为多主设备系统中需要强数据一致性的普通内存区域而设计的属性。
- 它做了什么: 它通过牺牲缓存带来的性能优势,换取了最简单、最直接的数据一致性。所有读写都直达最终的内存,并且写操作得到的是真实的完成确认。
- 何时使用: 当你有一块内存需要被多个总线主设备(CPU, GPU, DMA, Accelerator)共享,并且你对数据更新的及时性和一致性有严格要求时,就应使用此属性。
- 核心区别: 记住,
AxCACHE=0000的含义取决于目标地址是 Device 还是 Normal。前者是为了保护设备副作用和顺序,后者是为了保障共享数据的一致性和可见性。
浙公网安备 33010602011771号