ARM11中的PMU计数器

时间:2016-07-07 16:17:25

标签: arm bare-metal

我正在编写raspbery pi model b ARM1176 bare metal(在程序集和c中)。我需要计算用于执行汇编代码的时钟周期。
我正在使用以下代码用于PMU计数器:

mov r0,#1 

MCR p15, 0, r0, c15, c12, 0 ; Write Performance Monitor Control Register 
  /* Reset Cycle Counter */ 

mov r0,#5 

MCR p15, 0, r0, c15, c12, 0 ; Write Performance Monitor Control Register 
  /* Meaure */ 

 MRC p15, 0, r0, c15, c12, 1 @ Read Cycle Counter Register 

<MY CODES> 

MRC p15, 0, r1, c15, c12, 1 @ Read Cycle Counter Register 

如果我有

add r3,#3

代替我的代码我得到r1=8r0=0,这似乎是正确的,因为arm11有8个流水线阶段,执行它需要8个时钟周期。

但是当我添加更多指令时,我会得到像

这样荒谬的结果
add r3,#3

add r4,#1

r0=0,r1=97/96/94 (the result of r1 should also be constant!!!)

我正在使用uart查看minicom上的寄存器结果。

1 个答案:

答案 0 :(得分:0)

好的,看到同样的事情,这很有趣。

    @ nop
.globl test
test:
    mov r0,#1 
    MCR p15, 0, r0, c15, c12, 0 
    mov r0,#5 
    MCR p15, 0, r0, c15, c12, 0 
    MRC p15, 0, r0, c15, c12, 1 

    add r3,#3
    add r2,#1

    MRC p15, 0, r1, c15, c12, 1
    sub r0,r1,r0
    bx lr

我从C中调用它,所以如果我在测试代码中使用r4进行捣乱,则必须将其保存在堆栈中,因此与r2混淆。如果没有添加r2行,则返回值为8,使用add r2行返回值为0x68然后为0x65。注意这是pi 0。所以有些时钟比你的快一点。

请记住,这是从dram和dram运行非常缓慢。所以你可能会看到其中的一些。

代码的初始对齐:

00008024 <test>:
    8024:   e3a00001    mov r0, #1
    8028:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    802c:   e3a00005    mov r0, #5
    8030:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    8034:   ee1f0f3c    mrc 15, 0, r0, cr15, cr12, {1}
    8038:   e2833003    add r3, r3, #3
    803c:   e2822001    add r2, r2, #1
    8040:   ee1f1f3c    mrc 15, 0, r1, cr15, cr12, {1}
    8044:   e0410000    sub r0, r1, r0
    8048:   e12fff1e    bx  lr

是的,如果我在.globl测试前取消注释nop,并且我注释掉了添加r2我只有添加r3作为测试中的代码,但是nop推动了整个代码块的对齐。添加r3并且没有nop我使用add r3得到8个计数而nop得到0x67计数。

所以我认为这只是一个测量获取的情况。我没有启用arm缓存,但可能有更深的缓存或mmu或其他,因为这个ram在arm和gpu之间共享。

如果我更进一步并取消注释nop同时添加r3和add r2则为0x69计数。或者基本上是平均值或者只是比一条指令长,所以我们强制在那里取一个。

所以我的情况如果我添加更多的nops,所以计数的初始读取在8字边界上对齐,并且我有两个指令被测量

00008030 <test>:
    8030:   e3a00001    mov r0, #1
    8034:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    8038:   e3a00005    mov r0, #5
    803c:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    8040:   ee1f0f3c    mrc 15, 0, r0, cr15, cr12, {1}
    8044:   e2833003    add r3, r3, #3
    8048:   e2822001    add r2, r2, #1
    804c:   ee1f1f3c    mrc 15, 0, r1, cr15, cr12, {1}
    8050:   e0410000    sub r0, r1, r0
    8054:   e12fff1e    bx  lr

我得到了8.我在那里添加了第三条指令,添加了r3和两条添加r2。仍然算是8。

如果我回到这里,其中至少有一部分位于不同的获取行中。

00008024 <test>:
    8024:   e3a00001    mov r0, #1
    8028:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    802c:   e3a00005    mov r0, #5
    8030:   ee0f0f1c    mcr 15, 0, r0, cr15, cr12, {0}
    8034:   ee1f0f3c    mrc 15, 0, r0, cr15, cr12, {1}
    8038:   e2833003    add r3, r3, #3
    803c:   e2822001    add r2, r2, #1
    8040:   ee1f1f3c    mrc 15, 0, r1, cr15, cr12, {1}
    8044:   e0410000    sub r0, r1, r0
    8048:   e12fff1e    bx  lr

我做了三次运行而没有改变任何东西,然后启用l1缓存(指令)并再做三次运行

00000068 
0000001D 
0000001D 
0000001F 
00000008 
00000008 

所以我认为你正在处理dram,这是缓慢的,获取行,缓存未命中和命中以及产生的缓存行提取。

如果您希望看到执行指令所花费的时钟数,那么除非您可以将整个代码保留在l1缓存中,否则您将没有零等待状态内存。

我不认为芯片sram你可以用于这种芯片/板的这种东西,你最终会击中dram并且dram与gpu共享。因此,基本上程序执行时间预计不会是确定性的,并且与您的计算机或电话或其他cpu不是瓶颈并不是很长一段时间,它坐在那里等待提供数据或指令。