ISA opcodes --- ¿De dónde vienen?

13

Cuando los ingenieros diseñan una arquitectura de conjunto de instrucciones, según qué procedimiento o protocolo, si corresponde, siguen al designar ciertos códigos binarios como instrucciones. Por ejemplo, si tengo un ISA que dice que 10110 es una instrucción de carga, ¿de dónde vino ese número binario? ¿Fue modelado a partir de una tabla de estados para una máquina de estados finitos que representa una operación de carga?

Editar: después de investigar más, creo que lo que estoy tratando de preguntar se refiere a cómo se asignan los códigos de operación para las diversas instrucciones de la CPU. ADD podría designarse con un código de operación de 10011; una instrucción de carga podría designarse como 10110. ¿Qué proceso de pensamiento entra para asignar estos códigos de operación binarios para el conjunto de instrucciones?

Steven
fuente
8
Monte Dalrymple, "Diseño de microprocesador con Verilog HDL", proporciona un enfoque de diseño muy detallado para la CPU Z80 y creo que aprendería mucho sobre su pregunta. Pero hay muchas consideraciones que intervienen en una elección específica, incluido el análisis estadístico de otros conjuntos de instrucciones, resultados del compilador, etc. Sin embargo, recomendaría comenzar con ese libro. Aunque comienza con un diseño conocido, él entra en detalles íntimos al respecto y creo que aprendería algunas cosas. Buen libro.
jonk
O, tal vez, está preguntando sobre el diseño del motor de ejecución y se pregunta cómo podrían jugar los bits en la instrucción. No estoy seguro de tu redacción.
jonk
2
Alguien más hace esta pregunta. Debe ser martes.
Ignacio Vazquez-Abrams
55
@ Steven Piénsalo bien. Si se tuviera que diseñar un ISA, lo que tendría que pensar? Si las instrucciones no todos son de la misma longitud, ¿cómo se escoge palabras de instrucción más cortos o más largos, por lo que las instrucciones? Si tuviera que diseñar una etapa de decodificación , ¿cómo desearía que se viera su ISA? Creo que la pregunta es innecesariamente amplia (y, por lo tanto, casi imposible de responder por completo), pero puede mejorarla mucho más pensando y haciendo una pregunta precisa que no requiera que escribamos un libro para responder. eso.
Marcus Müller
44
Las especificaciones RISC-V hablan sobre las decisiones de diseño que tomaron en todos los niveles, incluido un poco sobre la codificación de las instrucciones de la máquina. (Esto es inusual para un manual de procesador; RISC-V es un ejercicio académico primero y una arquitectura de CPU en segundo lugar, a diferencia de la mayoría.)
zwol

Respuestas:

6

En muchos casos, la elección es bastante arbitraria o se basa en "donde sea que se ajuste mejor" a medida que los ISA crecen con el tiempo. Sin embargo, el MOS 6502 es un maravilloso ejemplo de un chip donde el diseño de ISA fue fuertemente influenciado al tratar de exprimir lo más posible de los transistores limitados.

Echa un vistazo a este video que explica cómo se diseñó la ingeniería inversa del 6502 , especialmente a partir de las 34:20 en adelante.

El 6502 es un microprocesador de 8 bits introducido en 1975. Aunque tenía un 60% menos de puertas que el Z80, era dos veces más rápido, y aunque era más limitado (en términos de registros, etc.), lo compensaba con un Elegante conjunto de instrucciones.

Contiene solo 3510 transistores, que fueron extraídos a mano por un pequeño equipo de personas que se arrastra sobre unas grandes láminas de plástico que luego se redujeron ópticamente, formando las diversas capas del 6502.

Como puede ver a continuación, el 6502 pasa el código de operación de la instrucción y los datos de temporización a la ROM de decodificación, luego los pasa a un componente de "lógica de control aleatorio" cuyo propósito es probablemente anular la salida de la ROM en ciertas situaciones complejas.

Diagrama de bloques 6502

A las 37:00 en el video puede ver una tabla de la ROM de decodificación que muestra qué condiciones deben cumplir las entradas para obtener un "1" para una salida de control dada. También puedes encontrarlo en esta página .

Puede ver que la mayoría de las cosas en esta tabla tienen X en varias posiciones. Tomemos por ejemplo

011XXXXX 2 X RORRORA

Esto significa que los primeros 3 bits del código de operación deben ser 011 y G debe ser 2; Nada más importa. Si es así, la salida llamada RORRORA se hará realidad. Todos los códigos de operación ROR comienzan con 011; pero hay otras instrucciones que comienzan con 011 también. Probablemente, estos deben ser filtrados por la unidad de "lógica de control aleatorio".

Básicamente, se eligieron los códigos de operación de modo que las instrucciones que debían hacer lo mismo que el otro tenían algo en común en su patrón de bits. Puede ver esto mirando una tabla de código de operación ; todas las instrucciones OR comienzan con 000, todas las instrucciones de Store comienzan con 010, todas las instrucciones que usan direccionamiento de página cero tienen el formato xxxx01xx. Por supuesto, algunas instrucciones no parecen "encajar", porque el objetivo no es tener un formato de código de operación completamente regular, sino más bien proporcionar un poderoso conjunto de instrucciones. Y es por eso que la "lógica de control aleatorio" era necesaria.

La página que mencioné anteriormente dice que algunas de las líneas de salida en la ROM aparecen dos veces: "Suponemos que esto se ha hecho porque no tenían forma de enrutar la salida de alguna línea donde querían, por lo que pusieron la misma línea en una línea diferente ubicación de nuevo ". Me imagino a los ingenieros dibujando a mano esas puertas una por una y de repente se dan cuenta de una falla en el diseño e intentan encontrar una manera de evitar reiniciar todo el proceso.

Artelio
fuente
22

Depende de la antigüedad de la ISA.

En los primeros días del diseño manual, y aún más cuando las CPU se ensamblaron a partir de lógica discreta, el diseño lógico habría sido lo primero, y se habría minimizado ampliamente, y luego los patrones de bits ISA habrían sido los valores necesarios para hacer que ese mínimo trabajo de lógica

Por lo tanto, puede haber un patrón particular de señales de control que permita que algunos multiplexores conecten la salida de ALU a la entrada del archivo de registro GP, algunas señales de control más que indiquen a la ALU que sume, reste, AND, OR, etc., y algunas bits de dirección en el archivo de registro. Estos tres grupos de señales formarán campos dentro de la instrucción. Cada grupo se mantendrá unido, y su significado detallado surge del diseño de esa unidad (ALU, etc.), pero los grupos pueden estar en cualquier orden, hasta que diseñe el decodificador de instrucciones. (El x86 es lo suficientemente antiguo como para que pueda detectar algo de esto si mira en el lugar correcto; no era un diseño totalmente nuevo, sino que se inspiró en el antiguo 8080)

Los ISA posteriores pueden "limpiarse" y hacerse más regulares y fáciles de usar, con hardware para traducir entre ellos y las señales de control de nivel de hardware reales, a veces a través de "microcódigo". Estos se denominan "CISC" o "Codificación de conjunto de instrucciones complejas". El prefijo de instrucción x86 "Rep" es un ejemplo simple de esto: hace que la siguiente instrucción se repita varias veces, para evitar tener que escribir un bucle FOR.

Más tarde (en la década de 1980) llegó un movimiento hacia un estilo más simple de codificación directa (RISC - Codificación de conjunto de instrucciones reducido) que puede ver en los procesadores ARM. Esto fue impulsado por el pequeño tamaño de los ASIC en ese momento y el deseo de poner CPU de 32 bits en ellos, por lo tanto, no había capacidad disponible para decodificadores de conjuntos de instrucciones complejos, para reducir la CPU completa a aproximadamente 20,000 puertas. (También hubo un aumento temporal del rendimiento, porque la gente aún no había desarrollado técnicas para hacer que los decodificadores CISC fueran rápidos, eso ocurrió alrededor de 1995 con el Pentium Pro)

Y hoy en día no importa: las CPU leen varias instrucciones a la vez y dedican millones de transistores a decodificarlas, reordenarlas y ejecutar tantas como sea posible a la vez, para acelerar los programas que pueden haberse escrito para los más antiguos. estilo de ISA.

Brian Drummond
fuente
2
No estoy seguro de que realmente llamaría a CISC "más fácil de usar". Esa puede haber sido la intención original, pero 30 años después son la antítesis de "fácil de usar" (en comparación con los ISA RISC, al menos).
tonysdg
2
Hay aspectos en los que fueron más fáciles de usar ... ya sea la regularidad (la ortogonalidad era un gran tema) cuando los compiladores eran programas relativamente triviales, o mediante el apoyo a operaciones de nivel superior directamente, que requieren menos traducción del compilador. Pero eso fue hace mucho tiempo y cualquier CISC sobreviviente tiene muchas capas de revisiones además de su conjunto de instrucciones original. Los compiladores también han cambiado su reconocimiento: los miles de pases de optimización realizados por gcc habrían sido impensables en aquel entonces. Entonces, lo que era "fácil" entonces y ahora tiene muy poca relación.
Brian Drummond
44
La distinción ha sido erosionada (conjuntos "RISC" agregando más instrucciones) y reemplazada por arquitecturas nuevas, incluso más complejas, como VLIW; realmente el único consenso es que x86 (16 y 32 bits) es difícil de usar
pjc50
1
@tonysdg: Hay RISC difíciles de usar y CISC difíciles de usar. Una buena comparación de "amabilidad del programador" es comparar 68k vs ARM. El ARM fue diseñado para un compilador, por lo que tuvo que hacer mucho trabajo manual para obtener datos de la RAM y volver a escribir en la RAM. El 68k fue diseñado para programadores de ensamblaje y le permite operar directamente en datos en RAM. Si observa 68k ISA, verá que se parece mucho al RISC ISA moderno con una excepción: puede operar directamente en RAM, mientras que RISC solo le permite operar en registros.
slebetman
1
El microcódigo es principalmente un atributo CISC. Sin embargo, podría implementar CISC sin microcódigo: el decodificador de instrucciones sería más complicado. También verá algunos CISC desde Pentium-Pro en adelante descritos como RISC internamente; traducir cada instrucción CISC en una o más operaciones RISC internas: otro nombre para microcódigo (aunque las distinciones se vuelven borrosas en las unidades de ejecución superescalar)
Brian Drummond
9

Si agrupa instrucciones similares, surgirán patrones. Esto es muy obvio en ARM, donde el manual ISA realmente muestra qué bit de una palabra de instrucción corresponde a función, elección de registro, etc. Pero también se puede inferir para X86 .

En última instancia, la parte de "función" de los códigos de operación entra en un decodificador binario a un disparo que realmente activa una función o secuencia particular de operaciones canalizadas. Por lo general, no están relacionados con el contenido de ninguna máquina de estado, a menos que estemos considerando instrucciones de longitud variable que requieren una máquina de estado para decodificar.

pjc50
fuente
Básicamente estás diciendo que están buscando el menor recuento de transistores posible en el chip. Estoy totalmente de acuerdo en el contexto de la pregunta de OP, donde no pueden permitirse cientos de transistores adicionales para un conjunto de instrucciones más ordenado. Las CPU de un millón de transistores no tienen tantos motivos para preocuparse, pero, por supuesto, muchas lo conservan por compatibilidad con versiones anteriores.
Harper - Restablece a Monica el
@ Harper Todavía hay razones, porque aunque los transistores se hicieron más pequeños, todavía tienen un tamaño, y las frecuencias de reloj aumentaron mucho mientras tanto. Por lo que un decodificador de instrucciones que es demasiado grande todavía puede ser un cuello de botella para el rendimiento (una de las razones por las que muchos CPU optaron por pre instrucciones -decode, antes de tiempo). No se trata (solo) del recuento de transistores, sino más bien de la frecuencia del reloj en combinación con el área del dado. La información todavía demora en propagarse, y aunque las CPU modernas no funcionan a la velocidad de la luz, no están lo suficientemente lejos del límite de velocidad como para esperar mejoras significativas.
Luaan
@Luaan: En realidad, "qué hacemos con todos estos transistores" es una pregunta real hoy en día. Mira todos los cachés L2 / L3 que se lanzan hoy en día. Esa es una admisión silenciosa que no tenemos un mejor uso para todos esos millones de transistores. ¡El último Xeon dedica más de 2 mil millones de transistores al caché!
MSalters
6

Alguien en algún momento se sentó y los definió.

Un buen ISA hará que el decodificador sea lo más simple posible.

Por ejemplo, con una instrucción ALU, puede permitir que algunos bits del código de operación se envíen directamente a las líneas de control de la ALU.

monstruo de trinquete
fuente
Gracias a todos por las excelentes respuestas. Todos ustedes me ayudaron a entender esto mucho mejor.
Steven
44
En realidad, hay algunos factores distintos de la simplicidad del decodificador a tener en cuenta. Dependiendo de las circunstancias y el uso previsto, otros (por ejemplo, la densidad del código) pueden ser más importantes que la simplicidad del decodificador. En un procesador moderno, la densidad del código probablemente supera la simplicidad del decodificador en la mayoría de los casos.
Jerry Coffin
5

Por lo general, dividiría su ISA en grupos funcionales. Tiene sentido (ya sea para la optimización lógica o simplemente para ser ordenado) que los pares complementarios se diferencian por un solo cambio de bit (carga frente a almacenamiento), y que tiene alguna jerarquía de bits que afecta el árbol de decisión de decodificación.

Al final del día, una asignación arbitraria de bits para el bloque de funciones (en lugar de colocar los campos de 'datos' en la instrucción solo tendrá un pequeño impacto en la eficiencia general de su diseño, pero tiene muchas opciones sobre cómo 'optimizar' su codificación ISA dependiendo de lo que considere que es un parámetro importante.

Sean Houlihane
fuente
1

La codificación de instrucciones es un compromiso feo entre.

Simplificando la decodificación, para esto desea un conjunto simple de campos, cada uno de los cuales puede decodificarse por separado y enrutarse a una parte separada del motor de ejecución.

Empaquetar tanta funcionalidad como sea posible en un tamaño limitado de palabra de instrucción. Esto lleva a cosas como formatos constantes especiales que pueden codificar una variedad de números comunes.

Compatibilidad hacia adelante y hacia atrás. Si asigna funcionalidad a cada código de operación posible, no tendrá espacio para expandir la arquitectura más adelante. Si está agregando a una arquitectura existente, debe insertar sus nuevas instrucciones en los códigos de operación de reserva.

Peter Green
fuente
1

El excelente (aunque algo anticuado) de Randy Hyde The Art of Assembly entra en el conjunto de instrucciones x86 con cierto detalle en el capítulo 3.3.4 La unidad de control y los conjuntos de instrucciones y siguientes.

Los programas en los primeros sistemas informáticos (anteriores a Von Neumann) a menudo estaban "conectados" a los circuitos. Es decir, el cableado de la computadora determinó qué problema resolvería. Había que volver a cablear los circuitos para cambiar el programa. Una tarea muy difícil. El siguiente avance en el diseño de la computadora fue el sistema de computadora programable, uno que permitió que un programador de computadora "reconecte" fácilmente el sistema de computadora usando una secuencia de enchufes y enchufes. Un programa de computadora consistía en un conjunto de filas de agujeros (zócalos), cada fila representando una operación durante la ejecución del programa. El programador podría seleccionar una de varias instrucciones conectando un cable en el enchufe particular para la instrucción deseada.

Luego demuestra bastante pegadizo y, por fin, cómo los primeros enchufes representan la instrucción, los siguientes enchufes codifican el origen y el destino. Por supuesto, hoy ya nadie se "conecta", pero para los ISA realmente antiguos, los bits en el código de operación básicamente hacen el mismo trabajo que los enchufes anteriores.

Terminas con algo como esto:

ingrese la descripción de la imagen aquí

DevSolar
fuente
¡Gracias por el enlace de Hyde! Es muy informativo y parece tener un excelente estilo de enseñanza.
Steven