2016-07-07 25 views
0

我在编程raspbery pi model b ARM1176 bare metal(在汇编中和c)。我需要计算用于执行汇编代码的时钟周期。
我使用PMU柜台下面的代码:ARM11中的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看到小型机寄存器的结果。

回答

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零。所以有些时钟比你的快一点。

请记住,这是从德拉姆运行,德拉姆是痛苦缓慢。所以你可能会看到一些。

代码的初始对准:

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,我注释掉ADD R2我只有加R3作为被测试的代码,但nop推动整个代码块的对齐。与添加r3和没有nop我得到8个计数与添加r3和nop我得到0x67计数。

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

如果我更进一步并取消nop的注释,那么add r3和add r2都是0x69计数。或者基本上等于或只比一个指令长,所以我们在那里强制取回。

所以我在我的情况下,如果我增加更多的空指令因此计数的初始读取时的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和两个add r2s。仍然是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不是一个瓶颈已经很长时间了,它是坐在等待被馈送的数据或指令。