В настоящее время я пытаюсь использовать счетчики событий на ARM Cortex-a9 (на Xilinx zynq EPP) для подсчета циклов. Для этой цели я адаптировал некоторый код примера ARM из ARM. Я программирую этот голой металл с помощью компилятора GNU ARM EABI.ARM Cortex-a9 счетчики событий возвращаются 0
Как я понимаю, использование PMU заключается в том, что вы сначала должны включить PMU.
void enable_pmu (void){
asm volatile( "MRC p15, 0, r0, c9, c12, 0\n\t"
"ORR r0, r0, #0x01\n\t"
"MCR p15, 0, r0, c9, c12, 0\n\t"
);
}
затем настроить счетчик производительности рассчитывать определенный тип события (0x11
для циклов в данном случае)
void config_pmn(unsigned counter,int event){
asm volatile( "AND %[counter], %[counter], #0x1F\n\t" :: [counter] "r" (counter)); //Mask to leave only bits 4:0
asm volatile( "MCR p15, 0, %[counter], c9, c12, 5\n\t" :: [counter] "r" (counter)); //Write PMSELR Register
asm volatile( "ISB\n\t"); //Synchronize context
asm volatile( "MCR p15, 0, %[event], c9, c13, 1\n\t" :: [event] "r" (counter)); //Write PMXEVTYPER Register
}
После включения счетчика событий
void enable_pmn(int counter){
asm volatile( "MOV r1, #0x1\n\t");
asm volatile( "MOV r1, r1, LSL %[counter]\n\t" :: [counter] "r" (counter));
asm volatile( "MCR p15, 0, r1, c9, c12, 1\n\t"); //Write PMCNTENSET Register
}
после этого вы немедленно сбросите счетчик событий
void reset_pmn(void){
asm volatile( "MRC p15, 0, r0, c9, c12, 0\n\t"); //Read PMCR
asm volatile( "ORR r0, r0, #0x2\n\t"); //Set P bit (Event counter reset)
asm volatile( "MCR p15, 0, r0, c9, c12, 0\n\t"); //Write PMCR
}
вы позволяете ваше приложение работало и читать счетчик событий
int read_pmn(int counter){
int value;
asm volatile( "AND %0,%0, #0x1F\n\t" :: "r" (counter)); //Mask to leave only bits 4:0
asm volatile( "MCR p15, 0, %[counter], c9, c12, 5\n\t" ::[counter] "r" (counter)); //Write PMSELR Register
asm volatile( "ISB\n\t"); //Synchronize context
asm volatile( "MRC p15, 0,%[value] , c9, c13, 2\n\t" : [value] "=r" (value)); //Read current PMNx Register
return value;
}
, а затем отключить счетчик событий
void disable_pmn(int counter){
asm volatile( "MOV r1, #0x1\n\t");
asm volatile( "MOV r1, r1, LSL %[counter] \n\t":: [counter] "r" (counter));
asm volatile( "MCR p15, 0, r1, c9, c12, 2\n\t"); //Write PMCNTENCLR Register
}
и ЦУП.
void disable_pmu (void){
asm volatile( "MRC p15, 0, r0, c9, c12, 0\n\t"
"BIC r0, r0, #0x01\n\t"
"MCR p15, 0, r0, c9, c12, 0\n\t"
);
}
Однако, когда я пытаюсь прочитать значение, хранящееся в счетчике событий я получаю 0. Я знаю, что мой PMU настроен правильно, потому что я в состоянии прочитать счетчик цикла (PMCCNTR
) без проблем. Вероятно, есть проблема с тем, как я настраиваю счетчик или как его читаю. Этот встроенный сборник для меня совсем новый, поэтому, если кто-то может указать мне в правильном направлении, я буду навсегда благодарен.
См [Cortex-A8 pmnc] (http://stackoverflow.com/questions/15492120/arm-cortex-a8-pmnc-read-дает-0-after-enable-also-any-idea-предложения) и [Cortex-a8 profiling] (http://stackoverflow.com/questions/15524138/profling-on-arm-cortex-a8), они могут быть полезны. И Linux [perf_event_v7.c] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/kernel/perf_event_v7.c), который предположительно будет для процессоров Cortex afaik. Это может быть что-то простое; У меня всегда возникают проблемы с параметрами 'MCR' /' MRC'. –
У вас также есть некоторые проблемы с * встроенным ассемблером *. Во многих случаях вы изменяете 'counter', но не комментируете это. Кроме того, вы используете жестко закодированные 'r0',' r1', но не указали это. Вы можете сгруппировать несколько * opm-кодов * asm в том же самом выражении 'asm'. Просто используйте '\ n'; вам не нужно указывать параметры столько раз, сколько нужно, но получите их право. Также [A8] (http://stackoverflow.com/questions/3247373/how-to-measure-program-execution-time-in-arm-cortex-a8-processor) [A8-2] (http: // stackoverflow .com/вопросы/9795132/мера времени выполнение-на-руки-Cortex-A8-помощи-аппаратно-счетчик) –