Tircore Cache
Cache 到底缓存什么
主要有两类 Cache:
例如:
uint32 value = table[100];
foo();如果 table 位于可缓存的数据区域,那么对 table[100]的读取可能经过 D-Cache。
如果函数 foo()位于可缓存的代码区域,那么 CPU 执行 foo()时的指令获取可能经过 P-Cache。
Cache 如何工作
假设执行:
value = (uint32_t )0x90001000;并假设 0x9... 是允许数据缓存的区域。
大致过程如下。
1. CPU 发出数据读取
CPU 计算出地址:
Text0x90001000
硬件根据地址的最高 4 位判断它属于段 9H。
2. 判断内存属性
硬件检查:
该地址是否属于 Peripheral Space
该段的数据访问是否允许缓存
D-Cache 是否存在并已启用
是否有其他硬件规则强制绕过 Cache
如果最终判断允许使用 D-Cache,就查询 D-Cache。
3. 查询 D-Cache
D-Cache 会判断目标地址所在的 Cache Line 是否已经保存。
如果存在,称为:
Cache Hit:缓存命中CPU 直接从 D-Cache 得到数据,速度较快。
如果不存在,称为:
Cache Miss:缓存未命中此时硬件会:
从实际存储器或总线读取对应 Cache Line。
将 Cache Line 放入 D-Cache。
把 CPU 需要的数据返回给 CPU。
后续对同一 Cache Line 的读取可能直接命中。
整个过程由硬件自动完成。
Cache类型
主要支持两类Cache——D-Cache(data cache)和P-Cache(program cache)
内存访问类型分为3类:
Cacheable Memory:可缓存内存
Non-cacheable Memory:不可缓存内存
Peripheral Space:外设空间
访问可缓存内存地址时,代码取指、数据读取都可以进入对应的Cache;同时CPU可以进行推测性取指、推测性读取;
访问不可缓存内存地址时,代码取值、数据读取不进入Cache;但仍允许预测性取指、读取,即CPU仍然可能提前读取某个地址;
对于一些外设寄存器来说,读取操作会造成寄存器复位,例如中断标志位;所以只把设备寄存器设置为“不可缓存”通常还不够,如果允许推测读取,就可能在程序真正执行读取指令前触发类似于“复位”的副作用,所以外设空间就单独设置了。
什么是推测访问
CPU 为了提高性能,可能提前访问它认为程序随后会用到的地址,这就是 speculative access。
文档把访问分为两类:
必要访问
程序正确执行必然需要发生的访问。
例如:
x = *ptr;当这条语句真正执行时,对 *ptr 的读取属于必要访问。
推测访问
CPU 为了提高性能而提前执行的访问。
例如:
提前取后续指令
分支结果还没确定时,提前取某条路径上的指令
提前读取可能马上使用的数据
如果分支预测错误,某些被读取的内容最终可能根本没有被程序使用(即没有命中)。
Cache 使用限制
即使 PMA 寄存器允许缓存,硬件仍然强制执行以下限制:
外设空间永远不能缓存。
当前 CPU 的本地 DSPR 内容不能进入当前 CPU 的数据 Cache。
当前 CPU 的本地 PSPR 内容不能进入当前 CPU 的程序 Cache。
原因是 PSPR/DSPR 本身就是靠近 CPU 的高速 SRAM,没有必要再复制到 Cache 中,而且这样也能避免同一内容存在多个副本所导致的一致性问题。
这些限制由硬件强制实施,不受 PMA0/PMA1 配置影响
默认内存属性

8H、9H:默认可缓存
EH、FH:默认外设空间
其他段:默认不可缓存
PMA 寄存器的整体关系
三个寄存器的职责是:
默认PMA0,PMA1为0x0300,对应位8、位9置1,对应8段、9段是缓存段
默认PMA2为0xC000,对应位14、位15置1,对应E, F段为外设空间
