Wir extrahieren Konstanten aus dem Kristall des mathematischen Coprozessors 8087

1980 führte Intel den 8087-Chip ein, um die Verarbeitung von Gleitkommazahlen auf 8086-Prozessoren zu beschleunigen. Er wurde im ursprünglichen IBM-PC verwendet. Da die ersten Mikroprozessoren nur mit ganzen Zahlen arbeiteten, war die Arithmetik mit Gleitkommazahlen langsam, und mit transzendentalen Funktionen wie Arkustangens oder Logarithmen war es noch schlimmer. Durch Hinzufügen des 8087-Coprozessorchips zum System konnten Operationen mit Gleitkommazahlen bis zu hundertmal beschleunigt werden.

Ich öffnete den 8087-Chip und machte ein paar Fotos davon unter einem Mikroskop. Das Foto unten zeigt einen winzigen Siliziumchipkristall. An seinen Seiten verbinden winzige Leiter es mit 40 äußeren Beinen. Das Markup der Hauptfunktionsblöcke im Bild wurde von mir dank Reverse Engineering erstellt. Wenn Sie den Chip sorgfältig untersuchen, können Sie verschiedene Konstanten aus seinen ROM-Zahlen extrahieren, z. B. π, die vom Chip in den Berechnungen verwendet werden. Intel 8087 Chip Chip für Gleitkommabetrieb mit markierten Hauptfunktionsblöcken. ROM mit Konstanten ist grün markiert. Klickbar.




In der oberen Hälfte des Chips befinden sich Steuerkreise. Es können bis zu 1000 Schritte erforderlich sein, um einen Gleitkommabefehl auszuführen. 8087 verwendete Mikrocode, um diese Schritte zu beschreiben. Auf dem Foto des Kristalls sehen Sie den "Mechanismus", der das Programm über den Mikrocode gestartet hat. Tatsächlich ist es eine einfache CPU. Daneben befindet sich ein großes ROM, in dem der Mikrocode gespeichert ist.

Am unteren Rand des Chips befinden sich Schaltungen, die Gleitkommazahlen verarbeiten. Eine Gleitkommazahl besteht aus einem Bruchteil (auch als wesentlicher Teil einer Zahl oder Mantisse bekannt), einem Exponenten und einem Vorzeichenbit. In Dezimalschreibweise die Zahl 6.02 × 10 236.02 wird die Mantisse sein und 23 wird der Exponent sein. Separate Chipschaltungen verarbeiten gleichzeitig die Mantisse und den Exponenten. Das Mantissenverarbeitungsschema unterstützt 67-Bit-Werte - eine 64-Bit-Mantisse und drei zusätzliche Bits für die Genauigkeit. Von links nach rechts bestehen die Mantissenoperationsschemata aus ROMs mit Konstanten, einem Schieberegister, einem Addierer / Subtrahierer und einem Registerstapel. Das Thema dieses Artikels ist ROM mit Konstanten, auf dem Foto ist es grün hervorgehoben.

8087 arbeitete als Coprozessor für den 8086-Prozessor. Als der 8086-Prozessor auf eine spezielle Anweisung für Gleitkommazahlen stieß, ignorierte er diese und gab dem 8087 die Möglichkeit, sie parallel auszuführen. Das Zusammenspiel von 8086 und 8087 war ziemlich gerissen angeordnet. Zur Vereinfachung betrachtet 8087 dann den Befehlsstrom 8086 und führt alle Befehle aus, die sich auf 8087 beziehen. Die Schwierigkeit besteht darin, dass 8086 einen Puffer zum Vorabrufen von Befehlen hat, so dass der Befehl, den 8086 derzeit empfängt, nicht mit dem Befehl übereinstimmt er tritt auf. Daher duplizierte 8087 den Puffer des Vorwärtsabtastwerts der Befehle 8086 (oder einen kleineren Puffer des Vorwärtsabtastwerts des Befehls 8088), um zu wissen, womit der 8086 beschäftigt ist ( weitere Einzelheiten werden hier beschrieben) Eine weitere Schwierigkeit ist mit komplexen 8086-Adressierungsmodi verbunden, die Register in 8086 verwenden. 8087 kann diese Adressierungsmodi nicht ausführen, da es keinen Zugriff auf 8086-Register hat. Wenn 8086 den Befehl für 8087 sieht, fordert es stattdessen Daten von einem bestimmten Speicherort an und ignoriert das Ergebnis. In der Zwischenzeit nimmt 8087 die Adresse aus dem Bus, falls er sie benötigt. Es scheint Ihnen, dass sich an dieser Stelle eine Falle bildet, wenn 8087 nicht installiert ist - aber dies wird nicht passieren. Auf einem System ohne 8087 schreibt der Linker die 8087-Anweisungen neu und ersetzt sie durch Unterprogrammaufrufe aus der Emulationsbibliothek.

Ich werde die internen Abläufe von 8087 nicht im Detail erläutern, aber im Allgemeinen werden Gleitkommaoperationen durch Additionen, Subtraktionen und Verschiebungen von ganzen Zahlen implementiert. Um zwei Gleitkommazahlen zu addieren oder zu subtrahieren, verschiebt 8087 die Zahlen, bis die Binärkommas ausgerichtet sind (wie Dezimalstellen nur im Binärsystem), und addiert oder subtrahiert dann die Mantisse. Multiplikation, Division und Quadratwurzelbildung werden durch aufeinanderfolgende Verschiebungen und Additionen / Subtraktionen durchgeführt. Transzendentale Funktionen (Tangens, Arkustangens, Logarithmus, Grad) verwenden CORDIC-Algorithmen , die Verschiebungen und Additionen spezieller Konstanten verwenden, um die Effizienz von Berechnungen zu erhöhen.

ROM-Implementierung


Dieser Artikel beschreibt das ROM, in dem die Konstanten gespeichert sind. Verwechseln Sie es nicht mit einem größeren ROM mit vier Ebenen, in dem der Mikrocode gespeichert ist. Letzteres wird mithilfe einer ungewöhnlichen Technologie implementiert, die zwei Bits pro Transistor speichert. Dies erfolgt unter Verwendung von Transistoren mit drei verschiedenen Größen oder ohne einen Transistor an jeder Position. Diese vier Optionen geben zwei Bits an. Diese hoch entwickelte Technologie wurde benötigt, um ein großes ROM auf einen 8087-Chip zu passen.

ROM für Konstanten verwendet Standardtechnologien zum Speichern von Konstanten (wie π, ln (2) und √2), die 8087 für Berechnungen benötigt. Das Foto unten zeigt einen Teil des ROM mit Konstanten. Um den Kristall selbst zu sehen, wurde eine Metallschicht von ihm entfernt. Rosa Bereiche sind Silizium mit Verunreinigungen, die ihm unterschiedliche Eigenschaften verleihen, und rötliche und grünliche Linien sind Polysilizium , eine spezielle Art von Siliziumverdrahtung, die oben liegt. Achten Sie auf die Struktur des ROM, ähnlich dem richtigen Gitter. Der ROM besteht aus zwei Spalten von Transistoren, in denen Bits gespeichert sind. Um das Schema seiner Funktionsweise zu erklären, beginne ich mit dem Schema des Transistors.


Teil des ROM mit Konstanten, mit einer entfernten Metallschicht. Drei Spalten größerer Transistoren werden zur Auswahl von Zeilen verwendet.

Integrierte Schaltungen mit hoher Dichte (ICs) wurden in den 1970er Jahren üblicherweise aus N-MOS- Transistoren hergestellt. (Moderne Computer bestehen aus CMOS, bestehend aus N-MOS- und P-MOS-Verpolung). Das folgende Diagramm zeigt den Aufbau eines N-MOS-Transistors. Der IC ist aus einem Siliziumsubstrat zusammengesetzt, auf dem Transistoren erzeugt werden. Den Siliziumstellen werden Verunreinigungen zugesetzt, wodurch "diffuse" Bereiche mit den gewünschten elektrischen Eigenschaften erzeugt werden. Ein Transistor kann als Schalter betrachtet werden, der den Stromfluss zwischen zwei Diffusionsabschnitten ermöglicht, die als Source und Drain bezeichnet werden. Der Transistor wird von einem Gate gesteuert, das aus einer speziellen Art von Silizium - Polysilizium besteht. Durch Anlegen einer Spannung an das Gate kann Strom zwischen Source und Drain fließen. Andernfalls fließt kein Strom. Der 8087 ist mit etwa 40.000 Transistoren recht komplex.

Verschiedene Quellen geben eine unterschiedliche Anzahl von Transistoren für 8087 an: Intel sagt ungefähr 40.000, Wikipedia sagt ungefähr 45.000. Vielleicht ist das Ganze in verschiedenen Berechnungsmethoden. Da die Anzahl der Transistoren in einem ROM, PLA oder einer anderen ähnlichen Struktur von den gespeicherten Daten abhängt, geben Quellen häufig die Anzahl der "potenziellen" Transistoren anstelle der realen an. Sie können auch Pull-up-Transistoren in Betracht ziehen oder nicht oder Hochstromtreiber als einen oder mehrere parallele Transistoren betrachten.


In IP implementierte MOS-Struktur

Durch Vergrößern können einzelne ROM-Transistoren berücksichtigt werden. Rosa Bereiche sind Silizium mit Verunreinigungen, die Quellen und Abflüsse bilden. Vertikale Polysilicium-Auswahlbusleitungen bilden Transistorgatter. Die markierten Bereiche aus Silizium sind mit Masse verbunden und ziehen eine Seite jedes Transistors nach unten. Die Kreise sind VIA , eine Zwischenschicht zwischen Silikon- und Metallreifen oben. Bei Fotos werden Metallreifen entfernt. Die Position eines von ihnen wird durch die orange Linie angezeigt.


Teil des ROM mit Konstanten. Jeder Abtastbus wählt eine bestimmte Konstante aus. Transistoren sind gelb dargestellt. X markiert den fehlenden Transistor entsprechend Bit 0. Die orange Linie zeigt die Position des Metallleiters an.

Ein wichtiges Merkmal des ROM ist das Fehlen einiger Transistoren - es gibt keine erste in der oberen Reihe und zwei mit X gekennzeichnete in der unteren Reihe. Bits werden im ROM programmiert, indem die Schaltung zum Hinzufügen von Verunreinigungen zu Silizium geändert wird, wodurch Transistoren erzeugt werden oder isolierende Bereiche zurückbleiben. Jeder verfügbare oder fehlende Transistor repräsentiert ein Bit. Wenn der Abtastbus aktiviert ist, öffnen sich alle Transistoren in dieser Spalte und ziehen die entsprechenden Ausgangsbusse herunter. Befindet sich jedoch kein Transistor in der ausgewählten Position, bleibt der entsprechende Ausgang hoch. Somit wird der Wert aus dem ROM gelesen, indem der Abtastbus aktiviert wird, der diesen Wert vom ROM an die Ausgangsbusse ausgibt.

ROM-Inhalt


ROM mit Konstanten besteht aus 143 Zeilen und 21 Spalten. Es enthält 134 Zeilen mit 21 Bits, mit Ausnahme eines Stücks 6 × 6-Transistoren oben links. Daher beträgt die physikalische Größe des ROM mit Konstanten 2946 Bit.



Basierend auf dem ROM-Schema bedeutet der fehlende Abschnitt, dass die ersten 12 Konstanten 64-Bit und nicht 67-Bit sind. Dies sind Konstanten, die nicht mit CORDIC zusammenhängen, und sie erfordern anscheinend keine zusätzliche Genauigkeit.

Unter dem Mikroskop ist das ROM-Bitmuster sichtbar, sodass es von dort entfernt werden kann. Es ist jedoch überhaupt nicht offensichtlich, wie diese Bits später interpretiert werden sollen. Die erste Frage ist, ob das Vorhandensein eines Transistors 0 oder 1 anzeigt (später stellte sich heraus, dass das Vorhandensein eines Transistors 1 ist). Das zweite Problem besteht darin, wie das 134 × 21-Bit-Gitter in Werte übersetzt wird.

Die Bitcodierung kann auf zwei Arten definiert werden. Die erste besteht darin, die Schaltung zu verfolgen, die die Daten aus dem ROM liest, und zu sehen, wie sie verwendet werden. Die zweite besteht darin, nach Mustern in Rohdaten zu suchen und diese zu verstehen. Da 8087 sehr komplex ist, wollte ich beim Studium von Konstanten ein vollständiges Reverse Engineering vermeiden, deshalb habe ich den zweiten Ansatz verwendet.

Der Datenpfad des Chips besteht aus 67 horizontalen Zeilen, so dass klar war, dass die 134 Zeilen im ROM zwei Sätzen von 67-Bit-Konstanten entsprechen. Ich habe einen Satz von Konstanten aus der ungeraden Reihe und den anderen aus der geraden Reihe extrahiert, aber die erhaltenen Werte waren nicht sinnvoll. Als ich etwas mehr nachdachte, stellte ich fest, dass sich die Reihen nicht abwechselten, sondern die ABBA-Reihenfolge wiederholten.

Die Zeilen gingen in der Reihenfolge ABBAABBAABBA ..., wobei die Zeilen A Bits für einen Satz von Konstanten und die Zeilen B Bits für einen anderen enthielten. Eine solche Schaltung wurde verwendet, anstatt einfach ABAW zu wechseln, möglicherweise weil ein Kontakt zwei benachbarte Transistoren steuern kann. Das heißt, ein Dirigent kann jede der Gruppen AA und BB auswählen.

Als ich die ABBA-Reihenfolge berücksichtigte, erhielt ich eine Reihe bekannter Konstanten, einschließlich π und 1. Das folgende Diagramm zeigt die Bits dieser Konstanten. Auf dem Foto ist Bit 1 ein grüner Streifen, Bit 0 ist rot. Im binären System ist π 11.001001 ... und dieser Wert ist in der oberen Reihe der markierten Bits sichtbar. Der untere Wert ist konstant 1. Die


obere Bitreihe ist die Zahl π, die untere ist 1. Dieses Diagramm ist im Vergleich zu den anderen um 90 ° gedreht.

Die nächste Schwierigkeit bei der Interpretation besteht darin, dass nur die Mantisse im ROM gespeichert ist, nicht jedoch der Exponent (bisher habe ich kein separates ROM mit den Exponenten gefunden). Und ich habe mit verschiedenen Ausstellern experimentiert, bis ich aussagekräftige Werte erhalten habe. Einige waren sofort klar: Beispielsweise ergibt die Konstante 1.204120 log 10 (2) unter Verwendung des Exponenten 2 -2 . Andere waren schwieriger zu verstehen, zum Beispiel 1.734723. Am Ende wurde mir klar, dass 1,734723 × 2 59 = 10 18 . Warum gibt es in 8087 eine solche Konstante? Vielleicht, weil der 8087 18-stelligen gepackten binären Dezimalcode unterstützt .

Einige Exponenten waren sehr schwer zu finden, und ich verwendete die Brute-Force-Methode, um festzustellen, ob das Ergebnis einen Logarithmus oder einen Grad einer bestimmten Zahl ergeben würde. Am schwierigsten war es, die Konstante für ln (2) / 3 zu bestimmen. Die Bedeutung dieser Nummer ist mir nicht klar.

Hier ist die vollständige Liste der Konstanten aus dem ROM. Die Spalte "Bedeutung" ist meine Beschreibung der Bedeutung.

KonstantenDezimalwertBedeutung
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)


Ich bin mir nicht sicher, warum 10 18 wiederholt wird - vielleicht ist der Unterschied exponentiell.

Physikalisch liegen die Konstanten in drei Gruppen. Die erste Gruppe sind die Werte, die der Benutzer laden kann (1, π, log 2 10, log 2 e, log 10 2 und ln), sowie Werte für den internen Gebrauch (10 18 , ln (2) / 3, 3 *) log 2 (e), log 2 (e) und √2). Die zweite Gruppe besteht aus 16 Arkustangens-Konstanten und die dritte aus 14 log 2- Konstanten .

In 8087 gibt es sieben Anweisungen zum direkten Laden von Konstanten. Die Anweisungen FDLZ, FLD1, FLDPI, FLD2T, FLD2E, FLDLG2 und FLDLN2 laden die Konstanten 0, 1, π, log 2 10, log 2 auf den Stapele, log 10 2 bzw. ln 2. Alle diese Konstanten außer 0 werden im ROM gespeichert.

Die letzten beiden Konstantengruppen werden verwendet, um transzendentale Funktionen unter Verwendung von CORDIC-Algorithmen zu berechnen.

CORDIC-Algorithmen


Anhand von Konstanten aus dem ROM können Sie einige Details zur Funktionsweise der 8087-Algorithmen herausfinden. Das ROM enthält 16 Werte für den Arkustangens, Arkustangens von 2 -n . Außerdem sind 14 Logarithmen auf der Basis 2 von (1 + 2 -n ) gespeichert . Solche Werte mögen ungewöhnlich erscheinen, werden jedoch in dem 1958 erfundenen effizienten CORDIC-Algorithmus verwendet.

Die Idee von CORDIC ist, dass Tangens und Arkustangens berechnet werden können, indem der Winkel mit der Drehung des Vektors um diese Winkel in kleinere geteilt wird. Der Trick ist, dass, wenn Sie die richtigen kleineren Winkel wählen, jede Drehung durch die effektiven Verschiebungen und Additionen anstelle von trigonometrischen Funktionen berechnet werden kann. Angenommen, wir müssen tan (z) finden. Wir können z in die Summe kleiner Winkel teilen: z ≈ {atan (2 -1 ) oder 0} + {atan (2 -2)) oder 0} + {atan (2 -3 ) oder 0} + ... + {atan (2 -16 oder 0}. Sie können den Vektor beispielsweise um atan (2 -2 ) drehen, indem Sie mit 2 -2 multiplizieren und addieren. Die Quintessenz ist, dass das Multiplizieren mit 2 -2 durch eine schnelle bitweise Verschiebung erfolgt. Unter Berücksichtigung all dessen können Sie tan (z) berechnen, indem Sie z mit atan-Konstanten vergleichen und dann nach 16 Additions- und Verschiebungszyklen, die schnell mit Eisen durchgeführt werden. für atan werden vorberechnet und im ROM gespeichert. Die Bogentangente wird auf ähnliche Weise berechnet, aber umgekehrt - beim Rotationsprozess werden die Winkel (vom ROM mit Konstanten) summiert und ergeben den endgültigen.

Bei der Berechnung des Logarithmus und des Exponenten werden auch CORDIC-Algorithmen und ihre entsprechenden logarithmischen Konstanten verwendet. Die Hauptsache hier ist, dass die Multiplikation mit (1 + 2 -n ) mit Hilfe von Verschiebungen und Additionen schnell erfolgen kann. Der Logarithmus und der Exponent können berechnet werden, indem eine Seite der Gleichung mit einer Folge von Werten multipliziert und die entsprechenden logarithmischen Konstanten zur anderen addiert werden. Nach den Algorithmen zur Berechnung des Logarithmus und des Exponenten der Dokumentation für 8087 habe ich ihn nicht gefunden. Ich denke, dass sie den im nächsten Artikel beschriebenen ähnlich sind , nur 8087 verwendet Basis 2 anstelle von e. Ich verstehe nicht, warum 8087 nicht die für diesen Algorithmus erforderliche log 2- Konstante (1 + 2 -1 ) hat.

Die Unterstützung für transzendentale Funktionen in 8087 ist nicht so umfangreich wie erwartet. Es unterstützt nur Tangenten und Bogen-Tangenten ohne Sinus und Cosinus. Um letzteres zu berechnen, müssen trigonometrische Identitäten angewendet werden. Logarithmen und Exponenten unterstützen nur Basis 2 - für Basis 10 oder e muss der Benutzer einen Skalierungsfaktor anwenden. Zu einer Zeit erweiterte 8087 die Kapazitätsgrenzen der Chips, so dass die Anzahl der Anweisungen minimiert wurde.

Fazit


Der 8087 ist ein komplexer Chip, und auf den ersten Blick sieht er aus wie ein hoffnungslos verwickeltes Labyrinth. Zum größten Teil kann es jedoch nach sorgfältiger Untersuchung verstanden werden. In seinem ROM sind 42 Konstanten gespeichert, und ihre Werte können unter Verwendung eines Mikroskops extrahiert werden. Einige Konstanten (z. B. π) wurden erwartet, während andere (z. B. in (2) / 3) mehr Fragen aufwerfen. Viele der Konstanten werden verwendet, um Tangenten, Arkustangens, Logarithmen und Grade mithilfe von CORDIC-Algorithmen zu berechnen. Foto eines Kristalls 8087 ohne Metallschicht. Klickbar.




Obwohl Intel 8087 für den Gleitkomma-Betrieb vor 40 Jahren eingeführt wurde, sind seine Auswirkungen immer noch zu spüren. Er brachte den IEEE 754-Standard für Gleitkommazahlen hervor, der in den meisten arithmetischen Berechnungen verwendet wird, und die 8087-Anweisungen bleiben Teil der x86-Prozessoren, die auf den meisten Computern verwendet werden.

All Articles