Extraemos constantes del cristal del coprocesador matemático 8087

En 1980, Intel introdujo el chip 8087 para acelerar el procesamiento de números de coma flotante en los procesadores 8086, y se utilizó en la PC original de IBM. Como los primeros microprocesadores solo funcionaban con números enteros, la aritmética con números de coma flotante era lenta y con funciones trascendentales como el arcotangente o los logaritmos, las cosas eran aún peores. Agregar el chip coprocesador 8087 al sistema fue capaz de acelerar las operaciones con números de coma flotante hasta cien veces.

Abrí el chip 8087 y tomé algunas fotos con un microscopio. La foto a continuación muestra un pequeño cristal de chip de silicio. A sus lados, pequeños conductores lo conectan con 40 patas externas. El marcado de los principales bloques funcionales en la imagen lo hice yo gracias a la ingeniería inversa. Si estudia cuidadosamente el chip, puede extraer varias constantes de su ROM, números como π utilizado por el chip en los cálculos. Chip chip Intel 8087 para operación en coma flotante con bloques de funciones principales marcados. ROM con constantes está marcado en verde. Clickable




En la mitad superior del chip hay circuitos de control. Se pueden requerir hasta 1000 pasos para ejecutar una instrucción de punto flotante; 8087 usó microcódigo para describir estos pasos. En la foto del cristal puede ver el "mecanismo" que lanzó el programa desde el microcódigo; de hecho, es una CPU simple. Al lado hay una gran ROM, donde se almacena el microcódigo.

En la parte inferior del chip hay circuitos que procesan números de coma flotante. Un número de coma flotante consiste en una parte fraccionaria (también conocida como una parte significativa de un número o mantisa), un exponente y un bit de signo. En notación decimal, el número 6.02 × 10 236.02 será la mantisa y 23 será el exponente. Circuitos de chips separados procesan simultáneamente la mantisa y el exponente. El esquema de procesamiento de mantisa admite valores de 67 bits: una mantisa de 64 bits y tres bits adicionales para mayor precisión. De izquierda a derecha, los esquemas de operación de mantisa consisten en ROM con constantes, un registro de desplazamiento, un sumador / sustractor y una pila de registros. El tema de este artículo es ROM con constantes; en la foto se resalta en verde.

El 8087 funcionó como coprocesador del procesador 8086. Cuando el procesador 8086 encontró una instrucción especial relacionada con números de coma flotante, lo ignoró y le dio al 8087 la oportunidad de ejecutarlo en paralelo. La interacción de 8086 y 8087 se organizó de una manera bastante astuta. Para simplificar, 8087 mira la secuencia de instrucciones 8086 y ejecuta cualquier instrucción relacionada con 8087. La dificultad es que 8086 tiene un búfer de instrucciones de captación previa, por lo que la instrucción que está recibiendo actualmente 8086 no coincide con la instrucción él realiza. Por lo tanto, 8087 duplicó el búfer de la muestra directa de instrucciones 8086 (o un búfer más pequeño de la muestra directa de instrucciones 8088) para saber con qué está ocupado el 8086 ( aquí se describen más detalles) Otra dificultad está asociada con los complejos modos de direccionamiento 8086 que usan registros dentro de 8086. 8087 no puede ejecutar estos modos de direccionamiento porque no tiene acceso a los registros 8086. En cambio, cuando 8086 ve la instrucción para 8087, solicita datos de una ubicación específica en la memoria e ignora el resultado. Mientras tanto, 8087 toma la dirección del autobús, en caso de que la necesite. Puede parecerle que se formará una trampa en este lugar si 8087 no está instalado, pero esto no sucederá. En un sistema sin 8087, el enlazador reescribe las instrucciones 8087, reemplazándolas con llamadas de subrutina desde la biblioteca de emulación.

No contaré en detalle el funcionamiento interno de 8087, pero en general, las operaciones de coma flotante se implementan mediante sumas, restas y desplazamientos de enteros. Para sumar o restar dos números de punto flotante, 8087 desplaza los números hasta que las comas binarias estén alineadas (como los puntos decimales, solo en el sistema binario), y luego suma o resta la mantisa. La multiplicación, división y sacar la raíz cuadrada se realizan mediante cambios sucesivos y sumas / restas. Las funciones trascendentales (tangente, arcotangente, logaritmo, grado) usan algoritmos CORDIC , que usan desplazamientos y adiciones de constantes especiales para aumentar la eficiencia de los cálculos.

Implementación de ROM


Este artículo describe la ROM donde se almacenan las constantes. No lo confunda con una ROM de cuatro niveles más grande donde se almacena el microcódigo; este último se implementa utilizando una tecnología inusual que almacena dos bits por transistor. Esto se hace usando transistores de tres tamaños diferentes o la ausencia de un transistor en cada posición. Estas cuatro opciones indican dos bits. Esta sofisticada tecnología era necesaria para instalar una ROM grande en un chip 8087.

ROM para constantes utiliza tecnologías estándar para almacenar constantes (como π, ln (2) y √2) requeridas por 8087 para los cálculos. La foto a continuación muestra parte de la ROM con constantes. Para ver el cristal en sí, se ha eliminado una capa de metal. Las áreas rosadas son de silicio con impurezas que le otorgan diferentes propiedades, y las líneas rojizas y verdosas son de polisilicio , un tipo especial de cableado de silicio que se encuentra en la parte superior. Presta atención a la estructura de la ROM, similar a la red correcta. ROM consta de dos columnas de transistores que almacenan bits. Para explicar el esquema de su operación, comenzaré con el esquema del transistor.


Parte de ROM con constantes, con una capa de metal eliminada. Se utilizan tres columnas de transistores más grandes para seleccionar filas.

Los circuitos integrados de alta densidad (IC) en la década de 1970 generalmente estaban hechos de transistores N-MOS. (Las computadoras modernas están hechas de CMOS, que consiste en polaridad inversa N-MOS y P-MOS). El siguiente diagrama muestra la estructura de un transistor N-MOS. El IC se ensambla a partir de un sustrato de silicio en el que se crean los transistores. Se agregan impurezas a los sitios de silicio, creando regiones "difusas" con las propiedades eléctricas deseadas. Un transistor puede considerarse como un interruptor que permite que la corriente fluya entre dos secciones de difusión, que se denominan fuente y drenaje. El transistor está controlado por una puerta hecha de un tipo especial de silicio: polisilicio. La aplicación de voltaje a la puerta permite que la corriente fluya entre la fuente y el drenaje; de lo contrario, no fluye corriente. El 8087 es bastante complejo, con aproximadamente 40,000 transistores.

Diferentes fuentes dan un número diferente de transistores para 8087: Intel dice aproximadamente 40,000, Wikipedia dice aproximadamente 45,000. Quizás todo se deba a diferentes métodos de cálculo. Dado que el número de transistores en una ROM, PLA u otra estructura similar depende de los datos almacenados, las fuentes a menudo indican el número de transistores "potenciales" en lugar de los reales. También puede considerar o no considerar los transistores pull-up, o considerar los controladores de alta corriente como un transistor o varios paralelos.


Estructura MOS implementada en IP

Al hacer zoom, se pueden considerar los transistores ROM individuales. Las áreas rosadas son de silicio con impurezas que forman fuentes y drenajes. Las líneas de bus de selección vertical de polisilicio forman compuertas de transistor. Las áreas marcadas de silicio están conectadas al suelo y tiran hacia abajo un lado de cada transistor. Los círculos son VIA , una vias entre capas entre los neumáticos de silicio y metal de arriba. Para fotos, se quitan los neumáticos de metal; La ubicación de uno de ellos se muestra mediante la línea naranja.


Parte de ROM con constantes. Cada bus de muestreo selecciona una constante específica. Los transistores se muestran en amarillo. X marca el transistor faltante correspondiente al bit 0. La línea naranja indica la ubicación del conductor de metal.

Una característica importante de la ROM es la ausencia de algunos transistores: no hay primero en la fila superior y dos marcados con una X en la fila inferior. Los bits se programan en ROM cambiando el circuito para agregar impurezas al silicio, que crea transistores o deja áreas aislantes. Cada transistor disponible o faltante representa un bit. Cuando se activa el bus de muestreo, todos los transistores en esta columna se abren, tirando hacia abajo de los buses de salida correspondientes. Pero si no hay transistor en la posición seleccionada, la salida correspondiente permanecerá alta. Por lo tanto, el valor se lee desde la ROM activando el bus de muestra, que envía este valor desde la ROM a los buses de salida.

Contenidos ROM


ROM con constantes consta de 143 filas y 21 columnas. Contiene 134 filas de 21 bits, a excepción de una pieza de transistores 6 × 6 en la esquina superior izquierda. Por lo tanto, el tamaño físico de la ROM con constantes es de 2946 bits.



Según el esquema ROM, la sección que falta significa que las primeras 12 constantes son de 64 bits, no de 67 bits. Estas son constantes no relacionadas con CORDIC, y aparentemente no requieren precisión adicional.

Bajo el microscopio, el patrón de bits de ROM es visible, por lo que puede eliminarse desde allí. Sin embargo, no es del todo obvio cómo interpretar estos bits más adelante. La primera pregunta es si la presencia de un transistor indica 0 o 1 (más tarde resultó que la presencia de un transistor es 1). El segundo problema es cómo traducir la cuadrícula de 134 × 21 bits en valores.

La codificación de bits se puede definir de dos maneras. El primero es rastrear el circuito leyendo los datos de la ROM y ver cómo se usa. El segundo es buscar patrones en los datos sin procesar e intentar comprenderlos. Como 8087 es muy complejo, quería evitar la ingeniería inversa completa al estudiar constantes, por lo que utilicé el segundo enfoque.

La ruta de datos del chip consta de 67 filas horizontales, por lo que estaba claro que las 134 filas en la ROM corresponden a dos conjuntos de constantes de 67 bits. Extraje un conjunto de constantes de la serie impar y el otro de la serie par, sin embargo, los valores obtenidos no tenían sentido. Pensando un poco más, me di cuenta de que las filas no se alternaban, sino que caminé repitiendo el orden ABBA.

Las filas iban en el orden ABBAABBAABBA ..., donde las filas A contenían bits para un conjunto de constantes, y las filas B contenían bits para otro. Tal circuito se usó en lugar de simplemente alternar ABAW, posiblemente porque un contacto puede controlar dos transistores adyacentes. Es decir, un conductor puede seleccionar cada uno de los grupos AA y BB.

Cuando tomé en cuenta el orden de ABBA, obtuve un montón de constantes familiares, incluyendo π y 1. El siguiente diagrama muestra los bits de estas constantes. En la foto, el bit 1 es una franja verde, el bit 0 es rojo. En el sistema binario, π es 11.001001 ..., y este valor es visible en la fila superior de bits marcados. El valor inferior es constante 1. La


fila superior de bits es el número π, la inferior es 1. Este diagrama se gira 90 ° en comparación con los demás.

La siguiente dificultad con la interpretación es que solo la mantisa se almacena en la ROM, pero no el exponente (hasta ahora no he encontrado una ROM separada con los exponentes). Y experimenté con varios expositores hasta que obtuve valores significativos. Algunos quedaron inmediatamente claros: por ejemplo, la constante 1.204120 da el log 10 (2) usando el exponente 2 -2 . Otros fueron más difíciles de entender, por ejemplo, 1,734723. Al final, me di cuenta de que 1.734723 × 2 59 = 10 18 . ¿Por qué hay tanta constante en 8087? Quizás porque el 8087 admite código decimal binario empaquetado de 18 caracteres.

Algunos exponentes fueron muy difíciles de encontrar, y utilicé el método de fuerza bruta para ver si el resultado produciría algún logaritmo o grado de algún número. Lo más difícil fue determinar la constante para ln (2) / 3. La importancia de este número no me queda clara.

Aquí está la lista completa de constantes de ROM. La columna de "significado" es mi descripción del significado.

ConstantesValor decimalSentido
1.204120 × 2 -20.3010300log 10 (2)
1.386294 × 2 -10.6931472ln (2)
1.442695 × 2 01.426950log 2 (e)
1.570796 × 2 13.1415927π
1.000000 × 2 01.0000001
1.660964 × 2 13.219281log 2 (10)
1.734723 × 2 591.00e + 1810 18
1.734723 × 2 591.00e + 1810 18
1.848392×2-30.2310491ln(2)/3
1.082021×224.2808513*log2(e)
1.442695×201.426950log2 (e)
1.414214×201.4142136√2
1.570796×2-10.7853982atan(20)
1.854590×2-20.4636476atan(2-1)
2.000000×2-150.0000610atan(2-14)
2.000000×2-160.0000305atan(2-15)
1.959829×2-30.2449787atan(2-2)
1.989680×2-40.1243550atan(2-3)
2.000000×2-130.0002441atan(2-12)
2.000000×2-140.0001221atan(2-13)
1.997402×2-50.0624188atan(2-4)
1.999349×2-60.0312398atan(2-5)
1.999999×2-110.0009766atan(2-10)
2.000000×2-120.0004883atan(2-11)
1.999837×2-70.0156237atan(2-6)
1.999959×2-80.0078123atan(2-7)
1.999990×2-90.0039062atan(2-8)
1.999997×2-100.0019531atan(2-9)
1.441288×2-90.0028150log2(1+2-9)
1.439885×2-80.0056245log2(1+2-8)
1.437089×2-70.0112273log2(1+2-7)
1.431540×2-60.0223678log2(1+2-6)
1.442343×2-110.0007043log2(1+2-11)
1.441991×2-100.0014082log2(1+2-10)
1.420612×2-50.0443941log2(1+2-5)
1.399405×2-40.0874628log2(1+2-4)
1.442607×2-130.0001761log2(1+2-13)
1.442519×2-120.0003522log2(1+2-12)
1.359400×2-30.1699250log2(1+2-3)
1.287712×2-20.3219281log2(1+2-2)
1.442673×2-150.0000440log2(1+2-15)
1.442651×2-140.0000881log2(1+2-14)


No estoy seguro de por qué se repite 10 18 , tal vez la diferencia es exponencial.

Físicamente, las constantes se encuentran en tres grupos. El primer grupo son los valores que el usuario puede cargar (1, π, log 2 10, log 2 e, log 10 2 y ln), así como los valores para uso interno (10 18 , ln (2) / 3, 3 * log 2 (e), log 2 (e) y √2). El segundo grupo consta de 16 constantes arcotangentes, y el tercero consta de 14 constantes log 2 .

En 8087, hay siete instrucciones para cargar constantes directamente. Las instrucciones FDLZ, FLD1, FLDPI, FLD2T, FLD2E, FLDLG2 y FLDLN2 cargan las constantes 0, 1, π, log 2 10, log 2 en la pilae, log 10 2 e ln 2, respectivamente. Todas estas constantes excepto 0 se almacenan en ROM.

Los dos últimos grupos de constantes se utilizan para calcular funciones trascendentales utilizando algoritmos CORDIC.

Algoritmos CORDICOS


Mediante las constantes de la ROM, puede encontrar algunos detalles del funcionamiento de los algoritmos 8087. La ROM contiene 16 valores para el arcotangente, arcotangentes de 2 -n . También hay 14 logaritmos almacenados en la base 2 de (1 + 2 -n ). Tales valores pueden parecer inusuales, pero se usan en el algoritmo eficiente CORDIC, inventado en 1958.

La idea de CORDIC es que la tangente y el arcotangente pueden calcularse dividiendo el ángulo en ángulos más pequeños con la rotación del vector por estos ángulos. El truco es que si elige los ángulos más pequeños correctos, cada rotación se puede calcular a través de los cambios efectivos y las adiciones en lugar de las funciones trigonométricas. Supongamos que necesitamos encontrar tan (z). Podemos dividir z en la suma de ángulos pequeños: z ≈ {atan (2 -1 ) o 0} + {atan (2 -2) o 0} + {atan (2 -3 ) o 0} + ... + {atan (2 -16 o 0}. Puede rotar el vector por, digamos, atan (2 -2 ) multiplicando por 2 -2 y sumando. La conclusión es que la multiplicación por 2-2 se lleva a cabo a través de un rápido cambio bit a bit. Teniendo en cuenta todo esto, puede calcular tan (z) comparando z con constantes atan, y luego después de pasar por 16 ciclos de adiciones y cambios, que se realiza rápidamente en hierro. para atan se calculan previamente y se almacenan en ROM. La tangente de arco se calcula de manera similar, pero viceversa: en el proceso de rotación, los ángulos (desde ROM con constantes) se resumen y dan el último.

Al calcular el logaritmo y el exponente, también se utilizan algoritmos CORDIC y sus correspondientes constantes logarítmicas. Lo principal aquí es que la multiplicación por (1 + 2 -n ) se puede hacer rápidamente con la ayuda de cambios y adiciones. El logaritmo y el exponente se pueden calcular multiplicando un lado de la ecuación por una secuencia de valores y sumando las constantes logarítmicas correspondientes al otro. De acuerdo con los algoritmos para calcular el logaritmo y el exponente de la documentación para 8087, no lo encontré. Creo que son similares a los que se describen en el siguiente artículo , solo 8087 usa la base 2 en lugar de E. No entiendo por qué 8087 no tiene la constante log 2 (1 + 2 -1 ) necesaria para ese algoritmo.

El soporte para funciones trascendentales en 8087 no es tan extenso como cabría esperar. Solo admite tangente y arco tangente, sin senos ni cosenos. Para calcular esto último, es necesario aplicar identidades trigonométricas. Los logaritmos y los exponentes solo admiten la base 2: para las bases 10 o e, el usuario tendrá que aplicar un factor de escala. En un momento, 8087 amplió los límites de la capacidad de los chips, por lo que se minimizó el número de instrucciones.

Conclusión


El 8087 es un chip complejo, y a primera vista parece un laberinto irremediablemente enredado. Sin embargo, en su mayor parte, se puede entender después de un estudio cuidadoso. En su ROM, se almacenan 42 constantes y sus valores se pueden extraer con un microscopio. Se esperaban algunas constantes (por ejemplo, π), mientras que otras (por ejemplo, ln (2) / 3) plantean más preguntas. Muchas de las constantes se usan para calcular tangentes, arcotangentes, logaritmos y grados usando algoritmos CORDIC. Foto de un cristal 8087 sin capa metálica. Clickable




Aunque Intel 8087 para la operación de punto flotante se introdujo hace 40 años, su impacto aún se siente. Engendró el estándar IEEE 754 para números de coma flotante, utilizado en la mayoría de los cálculos aritméticos, y las instrucciones 8087 siguen siendo parte de los procesadores x86 utilizados en la mayoría de las computadoras.

All Articles