Descubrí que una instrucción ARM Branch parece tardar 6 ciclos en ejecutarse en un procesador ARM7TDMI. Parece que no debería estar sucediendo porque en todas las referencias que he encontrado, una instrucción de bifurcación ARM7TDMI debería tomar solo 3 ciclos. Pero:
La función C:
start_time = TC;
for (int i=0; i<120; i++) {
__asm("NOP");
}
end_time = TC;
El desmontaje muestra el bucle como: (Actualización: direcciones de instrucciones agregadas):
0x120 MOV R1, 0
0x124 B LOC0
start:
0x128 NOP
0x12C ADD R1, R1, 1
LOC0:
0x130 CMP R1, 120
0x134 BLT start
Ahora, el resultado muestra que el bucle tarda 1080 ciclos (convertidos de un contador de tiempo puesto en TC), es decir, 9 ciclos por núcleo de bucle. Dado que NOP
, ADD
, CMP
son todas instrucciones de un solo ciclo, BLT
tiene que ser de 6 ciclos.
Una vez sospeché si mi método de sincronización tiene fallas. Pero si agrego 1 NOP
en el kernel de bucle, el aumento de tiempo sería exactamente de 1 ciclo.
¿Qué pasa aquí?
(Actualización: corrección: el código de desmontaje original se escribió mal ADD R1, R1, 1
como ADD R1, R1
)
Gracias a todos por las útiles respuestas y comentarios, especialmente @supercat, @Dzarda, @DaveTweed, @IgorSkochinsky, @WoutervanOoijen. Estoy ejecutando código desde flash. La CPU es una LPC23xx. De acuerdo con el Manual del usuario, incluye un Módulo de aceleración de memoria (MAM) para el acceso flash almacenado en búfer. Y los ciclos de recuperación flash sugeridos bajo la velocidad de mi CPU son exactamente 3 ciclos.
El start
kernel de bucle penalizado anterior se está alineando con un límite de 8 bytes. Si cambio la alineación de start
un límite de 16 bytes, entonces desaparece la penalización de 3 ciclos adicionales. Esto puede explicarse por el tamaño del búfer de precarga flash de 128 bits (16 bytes) de mi CPU.
(@WoutervanOoijen) Tenga en cuenta que el tiempo de recuperación de flash MAM de 3 ciclos no lo realiza la CPU ARM, sino el módulo MAM que precarga los datos flash en paralelo con la CPU. Entonces, en mi código con start
alineación en el límite de 8 bytes, CMP
es la primera instrucción en el búfer de captación previa MAM de 128 bits (4 instrucciones). Cuando la CPU ARM se ejecuta BLT
, se necesita el primer ciclo para "comprender" la instrucción. Luego intenta recuperar NOP
la instrucción que no está en el búfer de captación previa de MAM. Ese debería ser el momento en que ocurren los 3 ciclos adicionales cuando el MAM accede al flash. Cuando la NOP
instrucción está en el búfer (junto con otras 3 instrucciones en la línea flash de 32 bytes), la CPU ARM puede volver a llenar la canalización recuperando NOP
(quinto ciclo) y decodificandoNOP
(6to ciclo). De ahí provienen los 6 ciclos totales.
Entonces, la respuesta a mi pregunta es Sí, es posible una instrucción de bifurcación de 6 ciclos si hay un bloqueo de acceso flash.
Como señala @WoutervanOoijen, el razonamiento anterior tiene un defecto. El módulo de aceleración de memoria de LPC23xx tiene un búfer de seguimiento de rama adicional que se supone que evita este tipo de bifurcaciones de bucle de recuperación repetidas. El Manual del usuario de LPC23XX establece:
El búfer de Branch Trail captura la línea en la que se produce dicha ruptura no secuencial. Si se vuelve a tomar la misma bifurcación, la siguiente instrucción se toma del búfer de Branch Trail
Esta declaración no parece ser muy clara acerca de qué se está colocando exactamente en el búfer de Branch Trail. Podría ser la última línea flash precargada o la última línea flash de destino de bifurcación. En cualquier caso, la penalización de acceso flash no debería haber ocurrido porque la línea flash (0x120 ~ 0x12F) que incluye la instrucción de destino de bifurcación ( ) ya NOP
debería estar en el búfer de Branch Trail cuando BLT
se está ejecutando (al menos desde la segunda vez en adelante) .
(Por cierto, verifiqué que el MAM está en modo totalmente habilitado, es decir, MAM_mode_control es 2).
Actualizaré esta pregunta después de encontrar más información sobre esto. Y te agradeceré si tienes algún comentario sobre lo que podría estar pasando aquí, o qué prueba se puede hacer para buscar pistas.
¿Estás ejecutando código desde RAM o desde flash? Los procesadores ARM que ejecutan código desde flash a menudo requieren estados de espera en al menos algunas circunstancias; dichos procesadores a menudo incluyen hardware que puede eliminar la mayoría de los estados de espera en el código común, pero dicho hardware puede ser tan simple como un búfer de una sola línea que permite el acceso a la misma línea de flash que el acceso anterior para evitar el estado de espera. Si el objetivo de bifurcación es la última palabra de una línea flash, el flash requerirá dos o tres ciclos para obtener esa palabra y dos o tres ciclos para obtener la siguiente palabra. Si uno de los ciclos se realiza simultáneamente con alguna otra operación de la CPU, eso dejaría una penalización de tres ciclos.
start
se alinea con el límite de 16 bytes. Anteriormente estaba en el límite de 8 bytes.Eche un vistazo al centro de información de ARM, figura 2 , teniendo en cuenta que está trabajando con la canalización ARM7 y no con la canalización de 3 etapas M3. El punto sigue siendo válido.
Puede haber ciclos entre la obtención y la ejecución. Es muy difícil contar los pulsos del reloj para los ciclos de instrucción en un núcleo canalizado moderno. No estoy seguro de que sea determinista
Me pregunto si la canalización debe comenzar de nuevo en cada sucursal. Podría considerar apilar un montón de estos NOP en lugar de bifurcarlos para ver si su comportamiento resultante es más determinista como un paso de depuración.
De hecho, me han advertido sobre el uso de NOP para retrasos precisos en plataformas ARM por este motivo.
NOP
en lugar de bucles. Usar NOP
el resultado sería correcto.
Dzarda
david tweed
add
y lascmp
instrucciones. Finalmente, 3 ciclos parablt
podría ser solo un valor mínimo; Es posible que se requieran relojes adicionales si es necesario vaciar partes de la canalización de decodificación cuando se toma la bifurcación.scott seidman
Igor Skochinsky
Wouter van Ooijen
Penghe Geng
Wouter van Ooijen
Penghe Geng
Wouter van Ooijen
Penghe Geng
Wouter van Ooijen
Penghe Geng