我使用了 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->CYCCNT读取)
"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>
两个ldr指令正在读取DWT->CYCCNT寄存器,此外,奇怪的是为什么这需要10个周期,我的估计是2(来自ldr)+4 = 6。顺便说一下,该板没有任何缓存,我将代码存储在sramx中,堆栈在sram2中。我是否遗漏了什么,并且有没有办法找出每个周期如何消耗?此外,我也对cortex-m4的数据依赖性感到困惑。
DWT->CYCCNT
的两个LDR指令中的一个,而不是两个都包括。假设它们在执行这两个指令的相对点上同时读取循环计数(例如,在开始时)。如果要包括两个指令,则循环计数必须在第一个LDR指令的开头和第二个LDR指令的结尾处。 - Ross Ridge