一、配置cache
>配置L1 Cache:
CACHE_L1pSetSize(); CACHE_L1dSetSize();
>配置L2 cache:
启动时默认状态下L2 cache被disabled, 全部L2为SRAM。如果启用了DSP/BIOS,则L2 cache被自动使能;否则,可以通过调用CSL命令:CACHE_L2SetSize()来使能L2 cache。
>外部内存的cacheability
L1D 和 L2可以通过调用CSL命令CACHE_enableCaching(CACHE_MARi)修改对应MAR-bit来控制外部内存段的cacheability;而对L1P,外部内存总是cacheability的,跟MAR无关。
注意:配置成cache的地址段就不能再放入data and code,因为链接的时候,是不包含cache地址段的,如果要使用L1D SRAM或L1P SRAM,则应该相应减小cache段大小。
>example for C64x+ Linker Command File
MEMORY
{
L2SRAM : origin = 00800000h length = 001C0000h
CE0 : origin = 80000000h length = 01000000h (DDR第一个16M配置成可cache)
}
SECTIONS
{
.cinit > L2SRAM
.text > L2SRAM
.stack > L2SRAM
.bss > L2SRAM
.const > L2SRAM
.data > L2SRAM
.far > L2SRAM
.switch > L2SRAM
.sysmem > L2SRAM
.tables > L2SRAM
.cio > L2SRAM
.external > CE0
}
>example for C64x+ CSL Command Sequence to Enable Caching
[
#include <csl.h>
#include <csl_cache.h>
...
CACHE_enableCaching(CACHE_CE00);
CACHE_setL2Size(CACHE_256KCACHE);
]
二、cache一致性问题
如果内存是共享的,可以cache访问的,并且被修改了,那么这块内存就存在cache一致性维护的问题。对目前我们简单的编解码器移植来说,存在ARM与DSP的共享,但不存在同时修改的问题,故无需一致性维护。 对C64x+ DSPs来说,其cache控制器可以根据snoop command以硬件cache一致性协议来自动维护由CPU EDMA/IDMA所访问数据的一致性。当DMA发起读和写命令时就激活了一致性维护机制。当DMA读L2 SRAM cache内存时,数据直接从L1D cache提交给DMA,而不会在L2 SRAM更新;当DMA写时,数据直接提交到L1D cache,并且更新L2 SRAM。
>除了一致性操作,对于DMA buffer,最好将其按L2 cacheline对齐,并保证其为cachelines size的整数倍,可以通过以下方式保证:
#pragma DATA_ALIGN(InBuffA, CACHE_L2_LINESIZE)
#pragma DATA_ALIGN(InBuffB, CACHE_L2_LINESIZE)
#pragma DATA_ALIGN(OutBuffA,CACHE_L2_LINESIZE)
#pragma DATA_ALIGN(OutBuffB,CACHE_L2_LINESIZE)
unsigned char InBuffA [N*CACHE_L2_LINESIZE];
unsigned char OutBuffA[N*CACHE_L2_LINESIZE];
unsigned char InBuffB [N*CACHE_L2_LINESIZE];
unsigned char OutBuffB[N*CACHE_L2_LINESIZE];
我们也可以调用CSL宏CACHE_ROUND_TO_LINESIZE(cache, element count,element size)定义数组来完成上述功能,第一个参数是cache类型,可以为L1D,L1P,L2:
unsigned char InBuffA [CACHE_ROUND_TO_LINESIZE(L2, N, sizeof(unsigned char)];
unsigned char OutBuffA[CACHE_ROUND_TO_LINESIZE(L2, N, sizeof(unsigned char)];
unsigned char InBuffB [CACHE_ROUND_TO_LINESIZE(L2, N, sizeof(unsigned char)];
unsigned char OutBuffB[CACHE_ROUND_TO_LINESIZE(L2, N, sizeof(unsigned char)];
>一行在L1D/L1P中cache到不一定在L2中也能cache到;一行可能从L2中牺牲掉但L1P/L1D cache中仍然保存。
三、Run-time中改变Cache配置
>Disabling External Memory caching
通常不会出现这种需要。如果要做的时候应该考虑到以下问题:若MAR从1改为0,外部内存中原本被cached的地址仍然在cache中(cache的拷贝性),所以以cache方式访问这些外部地址仍然会hit。只有当L2 miss,或L2全SRAM时(这种状况也可理解为L2 miss),要访问外部内存时,更改的MAR比特才起作用.
>changing cache sizes during RUN-TIME
以L2的应用为例。有2个任务:A/B, 对A,64K L2 SRAM最好;对B,32K L2 cache/32K L2 SRAM最好。将64K L2分成两段32K,假定第二个32K放着A的程序、一些全局变量(B执行阶段需要保存下来),以及A的一些变量,这些变量在任务切换后不再需要。
用DMA将需要保存下来的代码和全局变量搬到外部内存某一区域,这样,就可以切换cache模式了。cache控制器会在对新尺寸的cache做初始化前将所有cache lines自动writeback-invalidate。注意:更改L2 cache大小不会造成L1P/L1D cache的任何evictions。尺寸修改可以调用CACHE_setL2Size()完成。
任务B执行完毕后,需要切换回A配置,B时的32K L2 cache 将需要切换回SRAM,之前必须将该32K line frames回写到外部内存并invalidated。当cache size切换时,这些工作由cache控制器自动完成。这样,可以从片外将A的代码和一些全局变量再拷贝回原来位置。
以上应用同样适用于L1P/L1D。对应的procedure、linker command file和C code example如下:
Procedure:
More Cache (SRAM转化成cache)
1. DMA or copy needed code/data out of SRAM addresses to be converted to cache.
2. Wait for completion of step 1.
3. Increase cache size using CACHE_setL1pSize(), CACHE_setL1dSize(),or CACHE_setL2Size()
Less Cache(cache转化成SRAM)
1. Decrease Cache size using CACHE_setL1pSize(),CACHE_setL1dSize(),or CACHE_setL2Size()
2. DMA or copy back any code/data needed.
3. Wait for completion of step 2.
linker command file:
MEMORY
{
L2_1: o = 00800000h l = 00008000h /*1st 32K segment: always SRAM */
L2_2: o = 00808000h l = 00008000h /*2nd 32K segment:Task A-SRAM,Task B-Cache */
CE0 : o = 80000000h l = 01000000h /*external memory */
}
SECTIONS
{
.cinit > L2_1
.text > L2_1
.stack > L2_1
.bss > L2_1
.const > L2_1
.data > L2_1
.far > L2_1
.switch > L2_1
.sysmem > L2_1
.tables > L2_1
.cio > L2_1
.sram_state_A > L2_2
.sram_process_A > L2_2
.sram_local_var_A > L2_2
.external > CE0
}
|