assembly mips pipelining

assembly - ¿Cuál es el punto de las ranuras de retardo?



mips pipelining (5)

¿No esperaría que el código después de una rama no se ejecute en caso de que se tome la rama?

Pero ya es demasiado tarde. Todo el propósito de una tubería de CPU es que desee completar una instrucción en cada ciclo. La única forma de lograrlo es obteniendo una instrucción en cada ciclo. Por lo tanto, el código después de la instrucción de bifurcación ya se ha recuperado y está en vuelo antes de que la CPU advierta que se debe tomar la bifurcación.

¿Cual es el punto de esto?

No hay ningún punto. No es una característica, es simplemente un artefacto de este tipo de diseño de tuberías.

Por lo tanto, a mi entender de las ranuras de retardo, ocurren cuando se llama una instrucción de bifurcación y la siguiente instrucción que sigue a la bifurcación también se carga de la memoria. ¿Cual es el punto de esto? ¿No esperaría que el código después de una rama no se ejecute en caso de que se tome la rama? ¿Es para ahorrar tiempo en caso de que la rama no se toma?

Estoy mirando un diagrama de tubería y parece que la instrucción después de la bifurcación se está llevando a cabo de todos modos.


Aunque la instrucción aparece en el programa después de la bifurcación, en realidad se ejecuta antes de que se tome la bifurcación. Echa un vistazo a la página de wikipedia sobre la ranura de retardo y el riesgo de rama .


En el ejemplo de libro de texto de una implementación canalizada, una CPU busca , decodifica , ejecuta y vuelve a escribir . Todas estas etapas ocurren en diferentes ciclos de reloj, por lo tanto, cada instrucción se completa en 4 ciclos. Sin embargo, mientras el primer código de operación está a punto de decodificarse, el siguiente se carga desde la memoria. Cuando la CPU está completamente ocupada, hay partes de 4 instrucciones diferentes que se manejan simultáneamente y el rendimiento de la CPU es una instrucción por ciclo de reloj.

Cuando en el código de máquina hay una secuencia:

sub r0, #1 bne loop xxx

El procesador puede retroalimentar información de la etapa de escritura de sub r0, #1 para ejecutar la etapa de bne loop , pero al mismo tiempo, el xxx ya está en la captura de etapa. Para simplificar la necesidad de desenrollar la tubería, los diseñadores de la CPU optan por usar una ranura de demora en su lugar. Una vez que se obtiene la instrucción de la ranura de retardo, la unidad de recuperación tiene la dirección correcta del objetivo de bifurcación. Un compilador de optimización rara vez necesita poner un NOP en la ranura de retardo, pero inserta una instrucción que necesariamente es necesaria en ambos posibles objetivos de ramificación.


La idea de la arquitectura RISC es simplificar la decodificación y optimizar las tuberías para la velocidad. La CPU intenta superponer la ejecución de instrucciones mediante la canalización, por lo que se ejecutan varias instrucciones a la vez.

El punto de la ranura de retardo específicamente es ejecutar una instrucción que ya ha llegado a través de parte de la tubería y ahora se encuentra en una ranura que de lo contrario solo habría que tirar.

Un optimizador podría tomar la primera instrucción en el objetivo de bifurcación y moverlo a la ranura de retardo, ejecutándolo "gratis".

La característica no se generalizó, principalmente porque el mundo se estandarizó en los diseños existentes de ISA 1 , es decir, x86 y x86-64, pero también por otra razón.

La explosión cuadrática en los conteos de transistores hizo posible descodificadores muy sofisticados. Cuando la ISA visible desde el punto de vista arquitectónico se está convirtiendo en microoperaciones de todos modos, pequeños hacks como el slot de retardo ya no son importantes.

1. ISA: Arquitectura del conjunto de instrucciones

La mayoría de los procesadores en estos días utilizan tuberías. Las ideas y los problemas de los libros de H&P se utilizan en todas partes. En el momento de esos escritos originales, asumiría que el hardware real coincidía con la noción particular de una tubería. buscar, decodificar, ejecutar, escribir de nuevo.

Básicamente, una tubería es una línea de ensamblaje, con cuatro etapas principales en la línea, por lo que tiene que trabajar como máximo cuatro instrucciones a la vez. Lo que confunde la noción de cuántos relojes se necesitan para ejecutar una instrucción, bueno, toma más de un reloj, pero si tiene algunos / muchos ejecutándose en paralelo, el "promedio" puede acercarse o superar uno por reloj.

Cuando tomas una rama aunque la línea de montaje falla. Las instrucciones en la etapa de búsqueda y decodificación deben ser lanzadas, y usted debe comenzar a rellenar nuevamente, por lo que debe presionar algunos relojes para buscar, decodificar y luego volver a ejecutar. La idea de la sombra de ramificación o del intervalo de demora es recuperar uno de esos relojes. Si declara que la instrucción después de una bifurcación siempre se ejecuta, entonces, cuando se toma una bifurcación, también se ejecuta la instrucción en la ranura de decodificación, la instrucción en la ranura de extracción se descarta y usted tiene un agujero de tiempo no dos. Entonces, en lugar de ejecutar, vacíe, vacíe, ejecute, ejecute ahora, ejecute, ejecute, vacíe, ejecute, ejecute ... en la etapa de ejecución de la tubería. La rama es un 50% menos dolorosa, su velocidad de ejecución promedio general mejora, etc.

ARM no tiene una ranura de retardo, pero también da la ilusión de una tubería al declarar que el contador del programa tiene dos instrucciones por delante. Cualquier operación que se base en el contador del programa (direccionamiento relativo a la PC) debe calcular el desplazamiento utilizando una PC que tenga dos instrucciones por delante, para las instrucciones ARM esto es de 8 bytes para el pulgar original de 4 bytes y cuando agrega las instrucciones de thumb2, se ensucia.

Estas son ilusiones en este punto fuera de lo académico, las tuberías son más profundas, tienen muchos trucos, etc., para que el código heredado siga funcionando y / o no tenga que redefinir cómo funcionan las instrucciones para cada cambio de arquitectura (imagine mips rev x, 1 ranura de retardo, rev y 2 ranuras de retardo, rev z 3 ranuras si la condición ay 2 ranuras si la condición b y 1 ranura si la condición c) el procesador sigue adelante y ejecuta la primera instrucción después de una bifurcación, y descarta la otra parte o una docena después, ya que vuelve a llenar la tubería. La profundidad de las tuberías realmente no se comparte con el público.

Vi un comentario acerca de que esto es una cuestión de RISC, puede haber comenzado allí, pero los procesadores CISC usan los mismos trucos, simplemente dando la ilusión del conjunto de instrucciones heredado, a veces el procesador CISC no es más que un núcleo RISC o VLIW con una envoltura para emular el conjunto de instrucciones CISC heredado (microcodificado).

Mira cómo se hace. Visualice una línea de ensamblaje, cada paso en la línea tiene una tarea. ¿Qué pasa si un paso en la línea se queda sin el azul, y para que el producto azul y amarillo se necesite el azul? Y no puedes obtener lo que es azul nuevo por otra semana porque alguien cometió un error. Por lo tanto, debe detener la línea, cambiar los suministros a cada etapa y hacer el producto rojo y verde por un tiempo, lo que normalmente se podría haber introducido de manera adecuada sin descargar la línea. Eso es como lo que sucede con una rama, en algún lugar profundo de la línea de ensamblaje, algo hace que la línea tenga que cambiar, volcar la línea. la ranura de retardo es una forma de recuperar un producto al tener que ser descartado en la línea. En lugar de que salieran los productos de N antes de que la línea se detuviera, los productos de N + 1 salieron por ejecución de producción. La ejecución de código es como una ráfaga de ejecuciones de producción, a menudo se obtienen rutas de ejecución cortas, a veces largas, lineales, antes de ir a una rama para ir a otra ruta de ejecución corta, bifurcar otra ruta de ejecución corta ...