我最近使用了一个板(LPCXpresso 5411x)做一些计算,我们试图减少周期,只要我们能够节省我们的特定需求的运行时间,所以我需要对cortex-m4指令的成本周期进行一些研究。我发现很多奇怪的东西(不能用我在互联网上找到的东西解释)用手臂皮质m4周期计数奇怪的东西
我用DWT-> CYCCNT来计算我想测试的函数所消耗的周期数。
int start_cycle, end_cycle;
__asm volatile (
"LDR %[s1], [%[a]], #0\n\t"
:[s1] "=&r"(start_cycle): [a] "r"(&(DWT->CYCCNT)):);
AddrSumTest();
__asm volatile (
"LDR %[s1], [%[a]], #0\n\t"
:[s1] "=&r"(end_cycle): [a] "r"(&(DWT->CYCCNT)):);
printf("inside the func() cycles: %d\n",end_cycle - start_cycle);
这里是我的功能是如何定义的:
__attribute__((always_inline)) static inline void AddrSumTest(){
uint32_t x, y, i, q;
__asm volatile (
"nop\n\t"
:[x] "=r" (x), [y] "=r" (y), [i] "=r" (i), [q] "=r" (q):);
}
}
- 据Arm Infocenter,指令MOV应该花费一个周期,但我发现,
以下指令需要8个周期(不是3个,因为需要额外的周期来读取DWT-> CYCC NT)
"nop\n\t"
"MOV %[x], #2\n\t"
"nop\n\t"
添加另一MOV指令之后,需要10个循环以下循环(为什么不9个周期)
"nop\n\t"
"MOV %[x], #2\n\t"
"MOV %[y], #3\n\t"
"nop\n\t"
和组装编码后一种情况是
4000578: f853 4b00 ldr.w r4, [r3], #0
400057c: bf00 nop
400057e: f04f 0502 mov.w r5, #2
4000582: f04f 0603 mov.w r6, #3
4000586: bf00 nop
4000588: f853 1b00 ldr.w r1, [r3], #0
400058c: 4805 ldr r0, [pc, #20] ;(40005a4<test_AddrSum+0x30>)
400058e: 1b09 subs r1, r1, r4
4000590: f000 f80e bl 40005b0 <__printf_veneer>
这两个ldrs正在从DWT-> CYCCNT读取,另外,为什么这会花费10个周期,我估计是2(来自ldr)+ 4 = 6
顺便说一句,板没有任何缓存,并且我将代码存储在sramx中,并且堆栈在sram2中。
我错过了什么,它有什么办法可以弄清楚每个周期如何消耗?此外,我也对cortex-m4的数据依赖性感到困惑。
如果没有任何缓存,您可能不得不为循环获取指令提取额外的费用。另请注意,您计算的周期时间只包含读取DWT-> CYCCNT的两条LDR指令之一,而不是两条指令。推测它们在执行两条指令时(例如在开始时)在相同的相对点处读取循环计数。要包含这两者,循环次数必须在第一个LDR指令开始时和第二个LDR指令结束时。 –
我同意你的意见,但你的意思是每个指令fetche的周期额外成本 –
每个指令获取,但我不知道如何Cortex-M4指令提取。例如,它可能会在每个提取中获取32位字,因此并非每条指令都会支付它。 –