Equipo conjunto de instrucciones complejas

Ajustar Compartir Imprimir Citar

Una computadora con conjunto de instrucciones complejo (CISC) es una arquitectura de computadora en la que las instrucciones individuales pueden ejecutar varias operaciones de bajo nivel (como una carga desde la memoria, una operación aritmética operación y un almacenamiento de memoria) o son capaces de operaciones de varios pasos o modos de direccionamiento dentro de instrucciones individuales. El término se acuñó retroactivamente en contraste con la computadora con conjunto de instrucciones reducido (RISC) y, por lo tanto, se ha convertido en una especie de término general para todo lo que no es RISC, donde la característica típica de diferenciación es que la mayoría de los diseños RISC usan una longitud de instrucción uniforme para casi todas las instrucciones, y emplear instrucciones de carga y almacenamiento estrictamente separadas.

Ejemplos de arquitecturas CISC incluyen computadoras centrales complejas a microcontroladores simples donde las operaciones de almacenamiento y carga de memoria no están separadas de las instrucciones aritméticas. Las arquitecturas de conjunto de instrucciones específicas que se han etiquetado retroactivamente como CISC son System/360 a z/Architecture, las arquitecturas PDP-11 y VAX, y muchas otras. Los microprocesadores y microcontroladores bien conocidos que también han sido etiquetados como CISC en muchas publicaciones académicas incluyen las familias Motorola 6800, 6809 y 68000; la familia Intel 8080, iAPX432 y x86; las familias Zilog Z80, Z8 y Z8000; la línea National Semiconductor 32016 y NS320xx; la familia MOS Technology 6502; la familia Intel 8051; y otros.

Algunos escritores han considerado algunos diseños como casos límite. Por ejemplo, el PIC de Microchip Technology ha sido etiquetado como RISC en algunos círculos y CISC en otros. Tanto el 6502 como el 6809 se han descrito como similares a RISC, aunque tienen modos de direccionamiento complejos e instrucciones aritméticas que operan en la memoria, en contra de los principios de RISC.

Incitaciones y beneficios

Antes de que la filosofía RISC se volviera prominente, muchos arquitectos informáticos intentaron cerrar la llamada brecha semántica, es decir, diseñar conjuntos de instrucciones que admitieran directamente construcciones de programación de alto nivel, como llamadas a procedimientos, control de bucle y modos de direccionamiento complejos. permitiendo que la estructura de datos y los accesos a matrices se combinen en instrucciones únicas. Las instrucciones también suelen estar altamente codificadas para mejorar aún más la densidad del código. La naturaleza compacta de tales conjuntos de instrucciones da como resultado programas más pequeños y menos accesos a la memoria principal (que a menudo eran lentos), lo que en ese momento (principios de la década de 1960 en adelante) resultó en un enorme ahorro en el costo de la memoria de la computadora y el almacenamiento en disco, como así como una ejecución más rápida. También significó una buena productividad de programación incluso en lenguaje ensamblador, ya que los lenguajes de alto nivel como Fortran o Algol no siempre estaban disponibles o eran apropiados. De hecho, los microprocesadores de esta categoría a veces todavía se programan en lenguaje ensamblador para ciertos tipos de aplicaciones críticas.

Nuevas instrucciones

En la década de 1970, el análisis de lenguajes de alto nivel indicó que los compiladores producían un lenguaje de máquina correspondiente complejo. Se determinó que las nuevas instrucciones podrían mejorar el rendimiento. Se agregaron algunas instrucciones que nunca fueron pensadas para usarse en lenguaje ensamblador pero que encajan bien con lenguajes compilados de alto nivel. Los compiladores se actualizaron para aprovechar estas instrucciones. Los beneficios de las instrucciones semánticamente ricas con codificaciones compactas también se pueden ver en los procesadores modernos, particularmente en el segmento de alto rendimiento donde los cachés son un componente central (a diferencia de la mayoría de los sistemas integrados). Esto se debe a que estas memorias rápidas, pero complejas y costosas, tienen un tamaño inherentemente limitado, lo que hace que el código compacto sea beneficioso. Por supuesto, la razón fundamental por la que se necesitan es que las memorias principales (es decir, la RAM dinámica actual) siguen siendo lentas en comparación con un núcleo de CPU (de alto rendimiento).

Problemas de diseño

Si bien muchos diseños lograron el objetivo de mayor rendimiento a menor costo y también permitieron que las construcciones de lenguaje de alto nivel se expresaran con menos instrucciones, se observó que este no era siempre el caso. Por ejemplo, las versiones de gama baja de arquitecturas complejas (es decir, que usan menos hardware) podrían dar lugar a situaciones en las que era posible mejorar el rendimiento al no usar una instrucción compleja (como una llamada a un procedimiento o una instrucción de entrada) pero en su lugar usando una secuencia de instrucciones más simples.

Una de las razones de esto fue que los arquitectos (escritores de microcódigos) a veces "diseñaron en exceso" instrucciones en lenguaje ensamblador, incluidas funciones que no se pueden implementar de manera eficiente en el hardware básico disponible. Podría haber, por ejemplo, "efectos secundarios" (por encima de las banderas convencionales), como la configuración de un registro o ubicación de memoria que quizás rara vez se usaba; si esto se hiciera a través de buses internos ordinarios (no duplicados), o incluso el bus externo, exigiría ciclos adicionales cada vez y, por lo tanto, sería bastante ineficiente.

Incluso en diseños equilibrados de alto rendimiento, las instrucciones altamente codificadas y (relativamente) de alto nivel podrían ser complicadas de decodificar y ejecutar de manera eficiente dentro de un presupuesto de transistores limitado. Tales arquitecturas, por lo tanto, requerían una gran cantidad de trabajo por parte del diseñador del procesador en los casos en que una solución más simple, pero (típicamente) más lenta, basada en tablas de decodificación y/o secuenciación de microcódigos no es apropiada. En un momento en que los transistores y otros componentes eran un recurso limitado, esto también dejó menos componentes y menos oportunidades para otros tipos de optimizaciones de rendimiento.

La idea RISC

El circuito que realiza las acciones definidas por el microcódigo en muchos (pero no en todos) los procesadores CISC es, en sí mismo, un procesador que en muchos sentidos recuerda en estructura a los primeros diseños de CPU. A principios de la década de 1970, esto dio lugar a la idea de volver a diseños de procesadores más simples para que fuera más factible hacer frente sin (entonces relativamente grandes y costosas) tablas ROM y/o estructuras PLA para secuenciar y /o decodificación.

Un procesador temprano (retroactivamente) RISC-etiquetado (IBM 801 - IBM's Watson Research Center, mediados de la década de 1970) era una máquina simple estrechamente interconectada originalmente pensada para ser utilizada como un procesador interno kernel o motor de microcódigo en los diseños de CISC, pero también se convirtió en el procesador que introdujo la idea de RISC a una audiencia algo mayor. La simplicidad y la regularidad también en el conjunto de instrucciones visible facilitarían la implementación de etapas de procesador superpuestas (canalización) a nivel de código de máquina (es decir, el nivel visto por los compiladores). Sin embargo, la segmentación a ese nivel ya se utilizaba en algunos "superordenadores" CISC de alto rendimiento. para reducir el tiempo del ciclo de instrucción (a pesar de las complicaciones de implementar dentro del conteo limitado de componentes y la complejidad del cableado factible en ese momento). La ejecución del microcódigo interno en los procesadores CISC, por otro lado, podría canalizarse más o menos según el diseño particular y, por lo tanto, sería más o menos similar a la estructura básica de los procesadores RISC.

La supercomputadora CDC 6600, entregada por primera vez en 1965, también se describió retroactivamente como RISC. Tenía una arquitectura de almacenamiento de carga que permitía que hasta cinco cargas y dos almacenamientos estuvieran en progreso simultáneamente bajo el control del programador. También tenía unidades de múltiples funciones que podían operar al mismo tiempo.

Superescalar

En un contexto más moderno, la compleja codificación de longitud variable utilizada por algunas de las arquitecturas CISC típicas hace que sea complicado, pero factible, construir una implementación superescalar de un modelo de programación CISC directamente; el Pentium original superescalar en orden y el Cyrix 6x86 superescalar fuera de orden son ejemplos bien conocidos de esto. Los frecuentes accesos a la memoria para los operandos de una máquina CISC típica pueden limitar el paralelismo a nivel de instrucción que se puede extraer del código, aunque esto está fuertemente mediado por las estructuras de caché rápida utilizadas en los diseños modernos, así como por otras medidas. Debido a las instrucciones inherentemente compactas y semánticamente ricas, la cantidad promedio de trabajo realizado por unidad de código de máquina (es decir, por byte o bit) es mayor para un procesador CISC que para un procesador RISC, lo que puede brindarle una ventaja significativa en una implementación moderna basada en caché..

Los transistores para lógica, PLA y microcódigo ya no son recursos escasos; solo las memorias caché grandes de alta velocidad están limitadas por la cantidad máxima de transistores en la actualidad. Aunque es complejo, el recuento de transistores de los decodificadores CISC no crece exponencialmente como el número total de transistores por procesador (la mayoría se usa típicamente para cachés). Junto con mejores herramientas y tecnologías mejoradas, esto ha llevado a nuevas implementaciones de diseños altamente codificados y de longitud variable sin limitaciones de almacenamiento de carga (es decir, sin RISC). Esto rige las reimplementaciones de arquitecturas más antiguas, como la omnipresente x86 (ver más abajo), así como los nuevos diseños de microcontroladores para sistemas integrados y usos similares. La complejidad superescalar en el caso del x86 moderno se resolvió convirtiendo las instrucciones en una o más microoperaciones y emitiendo dinámicamente esas microoperaciones, es decir, ejecución superescalar indirecta y dinámica; el Pentium Pro y AMD K5 son ejemplos tempranos de esto. Permite ubicar un diseño superescalar bastante simple después de los decodificadores (y búferes) (bastante complejos), brindando, por así decirlo, lo mejor de ambos mundos en muchos aspectos. Esta técnica también se utiliza en microprocesadores IBM z196 y posteriores z/Architecture.

Términos CISC y RISC

Los términos CISC y RISC se han vuelto menos significativos con la continua evolución de los diseños e implementaciones de CISC y RISC. Las primeras implementaciones de x86 altamente (o estrictamente) canalizadas, los diseños 486 de Intel, AMD, Cyrix e IBM, admitieron todas las instrucciones que hicieron sus predecesores, pero lograron la máxima eficiencia solo en un subconjunto x86 bastante simple. eso fue solo un poco más que un conjunto de instrucciones RISC típico (es decir, sin los límites típicos de carga-almacenamiento de RISC). La generación Intel P5 Pentium fue una versión superescalar de estos principios. Sin embargo, los procesadores x86 modernos también (por lo general) decodifican y dividen las instrucciones en secuencias dinámicas de microoperaciones almacenadas en búfer internas, lo que ayuda a ejecutar un subconjunto más grande de instrucciones de forma canalizada (superpuesta) y facilita una extracción más avanzada del paralelismo del código. corriente, para un rendimiento aún mayor.

Al contrario de las simplificaciones populares (presentes también en algunos textos académicos), no todos los CISC están microcodificados o tienen "complejos" instrucciones. Como CISC se convirtió en un término general que significa cualquier cosa que no sea una arquitectura de almacenamiento de carga (RISC), no es la cantidad de instrucciones, ni la complejidad de la implementación o de las instrucciones, lo que define a CISC., pero que las instrucciones aritméticas también realizan accesos a la memoria. En comparación con un pequeño procesador CISC de 8 bits, una instrucción de punto flotante RISC es compleja. CISC ni siquiera necesita tener modos de direccionamiento complejos; Los procesadores RISC de 32 o 64 bits pueden tener modos de direccionamiento más complejos que los pequeños procesadores CISC de 8 bits.

Un PDP-10, un PDP-8, un Intel 80386, un Intel 4004, un Motorola 68000, un mainframe System z, un Burroughs B5000, un VAX, un Zilog Z80000 y un MOS Technology 6502 varían ampliamente en el número, tamaños y formatos de instrucciones, el número, tipos y tamaños de registros y los tipos de datos disponibles. Algunos tienen soporte de hardware para operaciones como escanear una subcadena, aritmética BCD de precisión arbitraria o funciones trascendentales, mientras que otros solo tienen sumas y restas de 8 bits. Pero todos están en la categoría CISC porque tienen "cargar-operar" instrucciones que cargan y/o almacenan contenidos de memoria dentro de las mismas instrucciones que realizan los cálculos reales. Por ejemplo, el PDP-8, que tiene solo 8 instrucciones de longitud fija y ningún microcódigo, es un CISC debido a cómo funcionan las instrucciones, PowerPC, que tiene más de 230 instrucciones (más que algunos VAX), y elementos internos complejos como el cambio de nombre de registros y un búfer de reordenación, es un RISC, mientras que Minimal CISC tiene 8 instrucciones, pero es claramente un CISC porque combina el acceso a la memoria y el cálculo en las mismas instrucciones.