Klassische RISC-Pipeline - Classic RISC pipeline

In der Geschichte der Computerhardware verwendeten einige frühe Computer- Zentraleinheiten mit reduziertem Befehlssatz (RISC-CPUs) eine sehr ähnliche Architekturlösung, die heute als klassische RISC-Pipeline bezeichnet wird . Diese CPUs waren: MIPS , SPARC , Motorola 88000 und später die fiktive CPU DLX , die für den Bildungsbereich erfunden wurde.

Jedes dieser klassischen skalaren RISC-Designs ruft einen Befehl pro Zyklus ab und versucht ihn auszuführen . Das Haupt gemeinsame Konzept für jedes Design ist eine fünfstufige Ausführungsbefehlspipeline . Während des Betriebs arbeitet jede Pipeline-Stufe jeweils an einem Befehl. Jede dieser Stufen besteht aus einem Satz von Flip-Flops zum Halten des Zustands und einer kombinatorischen Logik , die an den Ausgängen dieser Flip-Flops arbeitet.

Die klassische fünfstufige RISC-Pipeline

Grundlegende fünfstufige Pipeline in einer RISC- Maschine (IF = Instruction Fetch , ID = Instruction Decode, EX = Execute, MEM = Memory Access, WB = Register Writeback). Die vertikale Achse sind aufeinanderfolgende Anweisungen; die horizontale Achse ist die Zeit. In der grünen Spalte befindet sich also der früheste Befehl in der WB-Stufe, und der neueste Befehl wird einem Befehlsabruf unterzogen.

Anweisung abrufen

Die Anweisungen befinden sich im Speicher, der einen Zyklus zum Lesen benötigt. Dieser Speicher kann ein dedizierter SRAM oder ein Befehls- Cache sein . Der Begriff "Latenz" wird in der Informatik häufig verwendet und bezeichnet die Zeit vom Beginn eines Vorgangs bis zum Abschluss. Somit hat der Befehlsabruf eine Latenzzeit von einem Taktzyklus (wenn ein SRAM mit einem einzigen Zyklus verwendet wird oder wenn der Befehl im Cache war). Somit wird während der Instruction Fetch Stufe ein 32-Bit - Befehl abgerufen aus dem Befehlsspeicher.

Der Programmzähler oder PC ist ein Register, das die Adresse enthält, die dem Befehlsspeicher präsentiert wird. Zu Beginn eines Zyklus wird die Adresse dem Befehlsspeicher präsentiert. Während des Zyklus wird dann der Befehl aus dem Befehlsspeicher gelesen und gleichzeitig wird eine Berechnung durchgeführt, um den nächsten PC zu bestimmen. Die Berechnung des nächsten PCs erfolgt, indem der PC um 4 erhöht wird und ob dieser als nächster PC oder alternativ das Ergebnis einer Verzweigungs- / Sprungberechnung als nächster PC genommen werden soll. Beachten Sie, dass im klassischen RISC alle Anweisungen die gleiche Länge haben. (Dies ist eine Sache, die RISC von CISC unterscheidet). In den ursprünglichen RISC-Designs beträgt die Größe eines Befehls 4 Byte, fügen Sie also immer 4 zur Befehlsadresse hinzu, verwenden Sie jedoch nicht PC + 4 für den Fall einer genommenen Verzweigung, eines Sprungs oder einer Ausnahme (siehe verzögerte Verzweigungen unten). ). (Beachten Sie, dass einige moderne Maschinen kompliziertere Algorithmen verwenden ( Verzweigungsvorhersage und Verzweigungszielvorhersage ), um die nächste Befehlsadresse zu erraten.)

Anweisungsdecodierung

Eine andere Sache, die die ersten RISC-Maschinen von früheren CISC-Maschinen unterscheidet, ist, dass RISC keinen Mikrocode hat . Bei mikrocodierten CISC-Befehlen werden die Befehlsbits, sobald sie aus dem Befehls-Cache geholt wurden, die Pipeline nach unten verschoben, wobei einfache kombinatorische Logik in jeder Pipeline-Stufe Steuersignale für den Datenpfad direkt aus den Befehlsbits erzeugt. Bei diesen CISC-Entwürfen wird in der traditionell als Decodierungsstufe bezeichneten Stufe nur sehr wenig Decodierung durchgeführt. Eine Folge dieses Fehlens von Decodierung ist, dass mehr Befehlsbits verwendet werden müssen, um anzugeben, was der Befehl tut. Dadurch bleiben weniger Bits für Dinge wie Registerindizes übrig.

Alle MIPS-, SPARC- und DLX-Befehle haben höchstens zwei Registereingänge. Während der Dekodierungsstufe werden die Indizes dieser beiden Register innerhalb des Befehls identifiziert und die Indizes werden dem Registerspeicher als Adresse präsentiert. Damit werden die beiden genannten Register aus der Registerdatei gelesen . Im MIPS-Design hatte die Registerdatei 32 Einträge.

Gleichzeitig mit dem Lesen der Registerdatei bestimmt die Befehlsausgabelogik in dieser Stufe, ob die Pipeline bereit ist, den Befehl in dieser Stufe auszuführen. Wenn nicht, bewirkt die Ausgabelogik, dass sowohl die Instruction Fetch-Phase als auch die Decode-Phase angehalten werden. In einem Blockierungszyklus akzeptieren die Eingangs-Flipflops keine neuen Bits, daher finden während dieses Zyklus keine neuen Berechnungen statt.

Wenn der decodierte Befehl eine Verzweigung oder ein Sprung ist, wird die Zieladresse der Verzweigung oder des Sprungs parallel zum Lesen der Registerdatei berechnet. Die Verzweigungsbedingung wird im folgenden Zyklus berechnet (nachdem die Registerdatei gelesen wurde), und wenn die Verzweigung ausgeführt wird oder die Anweisung ein Sprung ist, wird dem PC in der ersten Stufe das Verzweigungsziel zugewiesen und nicht der inkrementierte PC, der berechnet wurde. Einige Architekturen verwendeten die Arithmetic Logic Unit (ALU) in der Ausführungsstufe auf Kosten eines leicht verringerten Befehlsdurchsatzes.

Die Dekodierungsstufe endete mit ziemlich viel Hardware: MIPS hat die Möglichkeit, zu verzweigen, wenn zwei Register gleich sind, so dass ein 32 Bit breiter UND-Baum nach dem Lesen der Registerdatei in Reihe läuft, was einen sehr langen kritischen Weg durch diese macht Stufe (was weniger Zyklen pro Sekunde bedeutet). Außerdem erforderte die Verzweigungszielberechnung im Allgemeinen eine 16-Bit-Addition und einen 14-Bit-Inkrementierer. Das Auflösen der Verzweigung in der Dekodierungsstufe machte es möglich, nur eine Ein-Zyklus-Verzweigungs-Fehlvorhersagestrafe zu haben. Da Verzweigungen sehr oft genommen (und damit falsch vorhergesagt) wurden, war es sehr wichtig, diese Strafe gering zu halten.

Ausführen

In der Ausführungsphase findet die eigentliche Berechnung statt. Typischerweise besteht diese Stufe aus einer ALU und auch einem Bitschieber. Es kann auch einen Multiplizierer und Dividierer mit mehreren Zyklen umfassen.

Die ALU ist verantwortlich für die Durchführung von Booleschen Operationen (und, oder, nicht, nand, nor, xor, xnor) und auch für die Durchführung einer ganzzahligen Addition und Subtraktion. Neben dem Ergebnis liefert die ALU typischerweise Statusbits, wie zum Beispiel ob das Ergebnis 0 war oder nicht oder ob ein Überlauf aufgetreten ist.

Der Bitschieber ist für Verschiebung und Drehungen verantwortlich.

Anweisungen auf diesen einfachen RISC-Maschinen können je nach Art der Operation in drei Latenzklassen unterteilt werden:

  • Register-Register-Operation (Einzelzyklus-Latenz): Addieren, Subtrahieren, Vergleichen und logische Operationen. Während der Ausführungsphase wurden die beiden Argumente einer einfachen ALU zugeführt, die am Ende der Ausführungsphase das Ergebnis generierte.
  • Speicherreferenz (Latenz in zwei Zyklen). Alle Ladevorgänge aus dem Speicher. Während der Ausführungsphase fügte die ALU die beiden Argumente (ein Register und einen konstanten Offset) hinzu, um am Ende des Zyklus eine virtuelle Adresse zu erzeugen.
  • Anweisungen für mehrere Zyklen (Latenz mit vielen Zyklen). Integer multiplizieren und dividieren und alle Gleitkommaoperationen . Während der Ausführungsstufe wurden die Operanden dieser Operationen der Multi-Cycle-Multiply/Divide-Einheit zugeführt. Der Rest der Pipeline konnte die Ausführung fortsetzen, während die Multiplikations-/Divisionseinheit ihre Arbeit verrichtete. Um eine Verkomplizierung der Rückschreibstufe und der Ausgabelogik zu vermeiden, schrieben die Mehrzyklusbefehle ihre Ergebnisse in einen separaten Satz von Registern.

Speicherzugriff

Wenn auf Datenspeicher zugegriffen werden muss, erfolgt dies in dieser Phase.

Während dieser Stufe werden die Ergebnisse von Einzelzyklus-Latenzbefehlen einfach an die nächste Stufe weitergeleitet. Diese Weiterleitung stellt sicher, dass sowohl Ein- als auch Zwei-Zyklus-Befehle ihre Ergebnisse immer in dieselbe Stufe der Pipeline schreiben, so dass nur ein Schreibport in die Registerdatei verwendet werden kann und immer verfügbar ist.

Für das direkt abgebildete und virtuell gekennzeichnete Daten-Caching, die bei weitem einfachste der zahlreichen Daten-Cache-Organisationen , werden zwei SRAMs verwendet, von denen einer Daten und der andere Tags speichert.

Schreib zurück

Während dieser Stufe schreiben sowohl Einzelzyklus- als auch Zweizyklusbefehle ihre Ergebnisse in die Registerdatei. Beachten Sie, dass zwei verschiedene Stufen gleichzeitig auf die Registerdatei zugreifen – die Decodierstufe liest zwei Quellregister, während die Rückschreibstufe gleichzeitig das Zielregister eines vorherigen Befehls schreibt. Bei echtem Silizium kann dies eine Gefahr darstellen (weitere Informationen zu den Gefahren finden Sie weiter unten). Das liegt daran, dass eines der Quellregister, das beim Decodieren gelesen wird, das gleiche sein kann wie das beim Zurückschreiben geschriebene Zielregister. Wenn dies geschieht, werden dieselben Speicherzellen in der Registerdatei gleichzeitig gelesen und geschrieben. Auf Silizium funktionieren viele Implementierungen von Speicherzellen nicht richtig, wenn sie gleichzeitig gelesen und geschrieben werden.

Gefahren

Hennessy und Patterson prägten den Begriff Hazard für Situationen, in denen Anweisungen in einer Pipeline falsche Antworten liefern würden.

Strukturelle Gefahren

Strukturelle Gefahren treten auf, wenn zwei Anweisungen versuchen könnten, gleichzeitig dieselben Ressourcen zu verwenden. Klassische RISC-Pipelines haben diese Gefahren durch die Replikation von Hardware vermieden. Insbesondere könnten Verzweigungsbefehle die ALU verwendet haben, um die Zieladresse der Verzweigung zu berechnen. Wenn die ALU zu diesem Zweck in der Decodierungsstufe verwendet worden wäre, hätten bei einem ALU-Befehl gefolgt von einer Verzweigung beide Befehle versucht, die ALU gleichzeitig zu verwenden. Es ist einfach, diesen Konflikt zu lösen, indem ein spezialisierter Verzweigungsziel-Addierer in der Decodierungsstufe entworfen wird.

Datengefahren

Datengefahren treten auf, wenn ein blind geplanter Befehl versuchen würde, Daten zu verwenden, bevor die Daten in der Registerdatei verfügbar sind.

In der klassischen RISC-Pipeline werden Datengefahren auf zwei Arten vermieden:

Lösung A. Umgehen

Das Umgehen wird auch als Operandenweiterleitung bezeichnet .

Angenommen, die CPU führt den folgenden Code aus:

SUB r3,r4 -> r10     ; Writes r3 - r4 to r10
AND r10,r3 -> r11    ; Writes r10 & r3 to r11

Die Befehlshol- und -decodierungsstufen senden den zweiten Befehl einen Zyklus nach dem ersten. Sie fließen die Pipeline entlang, wie in diesem Diagramm gezeigt:

Pipeline-Daten Hazard.svg

In einer naiven Pipeline schreitet das Datenrisiko ohne Gefährdungsabwägung wie folgt fort:

Im Zyklus 3 SUBberechnet die Anweisung den neuen Wert für r10. Im gleichen Zyklus wird die ANDOperation dekodiert und der Wert von r10wird aus der Registerdatei geholt. Die SUBAnweisung hat ihr Ergebnis jedoch noch nicht in geschrieben r10. Das Zurückschreiben erfolgt normalerweise im Zyklus 5 (grüner Kasten). Daher ist der aus der Registerdatei gelesene und an die ALU übergebene Wert (in der Ausführungsphase der ANDOperation, rotes Kästchen) falsch.

Stattdessen müssen wir die berechneten Daten SUBan die Execute-Stufe (dh an den roten Kreis im Diagramm) der ANDOperation zurückgeben, bevor sie normalerweise zurückgeschrieben werden. Die Lösung für dieses Problem ist ein Paar Bypass-Multiplexer. Diese Multiplexer sitzen am Ende der Dekodierungsstufe, und ihre gefloppten Ausgänge sind die Eingänge zur ALU. Jeder Multiplexer wählt zwischen:

  1. Ein Port zum Lesen einer Registerdatei (dh die Ausgabe der Dekodierungsstufe, wie in der naiven Pipeline): roter Pfeil
  2. Die aktuelle Registerpipeline der ALU (um eine Stufe zu umgehen): blauer Pfeil
  3. Die aktuelle Registerpipeline der Zugriffsstufe (die entweder ein geladener Wert oder ein weitergeleitetes ALU-Ergebnis ist, dies ermöglicht das Umgehen von zwei Stufen): lila Pfeil. Beachten Sie, dass dies erfordert, dass die Daten zeitlich um einen Zyklus rückwärts übergeben werden. In diesem Fall muss eine Blase eingefügt werden, um den ANDVorgang anzuhalten, bis die Daten bereit sind.

Die Logik der Decodierungsstufe vergleicht die durch Befehle in den Ausführungs- und Zugriffsstufen der Pipeline geschriebenen Register mit den durch den Befehl in der Decodierungsstufe gelesenen Registern und veranlasst die Multiplexer, die neuesten Daten auszuwählen. Diese Bypass-Multiplexer ermöglichen es der Pipeline, einfache Befehle mit nur der Latenzzeit der ALU, des Multiplexers und eines Flip-Flops auszuführen. Ohne die Multiplexer müsste die Latenzzeit des Schreibens und anschließenden Lesens der Registerdatei in die Latenzzeit dieser Befehle einfließen.

Beachten Sie, dass die Daten nur rechtzeitig weitergegeben werden können - die Daten können nicht in eine frühere Phase zurückgeführt werden, wenn sie noch nicht verarbeitet wurden. Im obigen Fall werden die Daten weitergereicht (bis die ANDfür das Register in der ALU bereit ist, SUBhat sie sie bereits berechnet).

Datenweiterleitung (eine Stufe).svg

Lösung B. Pipeline-Verriegelung

Beachten Sie jedoch die folgenden Anweisungen:

LD  adr    -> r10
AND r10,r3 -> r11

Die von der Adresse gelesenen adrDaten sind im Datencache erst nach der Speicherzugriffsstufe des LDBefehls vorhanden. Zu diesem Zeitpunkt ist die ANDAnweisung bereits durch die ALU. Um dies zu lösen, müssten die Daten aus dem Speicher zeitlich rückwärts an den Eingang der ALU übergeben werden. Das ist nicht möglich. Die Lösung besteht darin, den ANDBefehl um einen Zyklus zu verzögern . Die Datengefahr wird in der Dekodierungsstufe erkannt, und die Hol- und Dekodierungsstufen werden angehalten - sie werden daran gehindert, ihre Eingänge zu floppen und bleiben so für einen Zyklus im gleichen Zustand. Die stromabwärtigen Ausführungs-, Zugriffs- und Rückschreibstufen sehen eine zusätzliche No-Operation-Instruktion (NOP), die zwischen den LDund- ANDInstruktionen eingefügt ist .

Dieses NOP wird als Pipelineblase bezeichnet , da es in der Pipeline schwimmt, wie eine Luftblase in einer Wasserleitung, Ressourcen beansprucht, aber keine brauchbaren Ergebnisse liefert. Die Hardware zum Erkennen einer Datengefahr und zum Blockieren der Pipeline, bis die Gefahr beseitigt ist, wird als Pipeline-Verriegelung bezeichnet .

Zeitlich rückwärts umgehen Problem mit einer Blase gelöst
Datenweiterleitung (zweistufig, Fehler).svg Datenweiterleitung (zweistufig).svg

Ein Pipeline-Interlock muss jedoch bei keiner Datenweiterleitung verwendet werden. Das erste Beispiel für SUBgefolgt von ANDund das zweite Beispiel für LDgefolgt von ANDkönnen gelöst werden, indem die erste Stufe um drei Zyklen angehalten wird, bis das Zurückschreiben erreicht ist und die Daten in der Registerdatei korrekt sind, wodurch der korrekte Registerwert abgerufen wird durch die ANDDecodierungsphase von . Dies führt zu einem ziemlichen Leistungseinbruch, da der Prozessor viel Zeit damit verbringt, nichts zu verarbeiten, aber die Taktraten können erhöht werden, da weniger Weiterleitungslogik zu warten ist.

Diese Datengefahr lässt sich recht leicht erkennen, wenn der Maschinencode des Programms vom Compiler geschrieben wird. Die Stanford-MIPS- Maschine verließ sich in diesem Fall auf den Compiler, um die NOP-Anweisungen hinzuzufügen, anstatt über die Schaltung zu verfügen, um die ersten beiden Pipeline-Stufen zu erkennen und (noch anstrengender) zu blockieren. Daher der Name MIPS: Mikroprozessor ohne Interlocked Pipeline Stages. Es stellte sich heraus, dass die vom Compiler hinzugefügten zusätzlichen NOP-Befehle die Programmbinärdateien so weit erweiterten, dass die Trefferrate des Befehls-Cache reduziert wurde. Die Stall-Hardware, obwohl teuer, wurde in spätere Designs wieder eingebaut, um die Trefferrate des Befehls-Cache zu verbessern, woraufhin das Akronym keinen Sinn mehr machte.

Gefahren kontrollieren

Steuerungsgefahren werden durch bedingte und unbedingte Verzweigungen verursacht. Die klassische RISC-Pipeline löst Verzweigungen in der Dekodierungsstufe auf, was bedeutet, dass die Wiederholung der Verzweigungsauflösung zwei Zyklen lang ist. Es gibt drei Implikationen:

  • Die Wiederholung der Verzweigungsauflösung durchläuft eine ganze Reihe von Schaltungen: das Lesen des Befehlscache, das Lesen der Registerdatei, das Berechnen der Verzweigungsbedingung (was einen 32-Bit-Vergleich auf den MIPS-CPUs beinhaltet) und den nächsten Befehlsadreßmultiplexer.
  • Da Verzweigungs- und Sprungziele parallel zum Registerlesen berechnet werden, haben RISC-ISAs typischerweise keine Befehle, die zu einer Register- + Offset-Adresse verzweigen. Zur Registrierung springen wird unterstützt.
  • Bei jeder ausgeführten Verzweigung wird der Befehl unmittelbar nach der Verzweigung immer aus dem Befehlscache geholt. Wenn dieser Befehl ignoriert wird, gibt es eine IPC- Strafe von einem Zyklus pro genommener Verzweigung , die angemessen groß ist.

Es gibt vier Schemata, um dieses Leistungsproblem mit Verzweigungen zu lösen:

  • Predict Not Taken: Hole den Befehl immer nach der Verzweigung aus dem Befehlscache, aber führe ihn nur aus, wenn der Sprung nicht genommen wird. Wird die Verzweigung nicht genommen, bleibt die Pipeline voll. Wenn die Verzweigung genommen wird, wird der Befehl geleert (als ob er ein NOP wäre), und die Gelegenheit eines Zyklus zum Beenden eines Befehls geht verloren.
  • Verzweigungswahrscheinlich: Holen Sie die Anweisung immer nach der Verzweigung aus dem Anweisungs-Cache, führen Sie sie jedoch nur aus, wenn die Verzweigung ausgeführt wurde. Der Compiler kann immer den Verzweigungsverzögerungsschlitz einer solchen Verzweigung füllen, und da Verzweigungen häufiger genommen werden als nicht, haben solche Verzweigungen einen geringeren IPC-Einbußen als die vorherige Art.
  • Verzweigungsverzögerungsschlitz : Hole immer den Befehl nach der Verzweigung aus dem Befehlscache und führe ihn immer aus, selbst wenn die Verzweigung genommen wird. Anstatt einen IPC-Nachteil für einen Teil der Verzweigungen zu nehmen, die entweder genommen (vielleicht 60%) oder nicht genommen (vielleicht 40%) sind, nehmen Verzweigungsverzögerungsschlitze einen IPC-Nachteil für diejenigen Verzweigungen, in die der Compiler den Verzweigungsverzögerungsschlitz nicht einplanen konnte. Die Designer von SPARC, MIPS und MC88K haben einen Branch Delay Slot in ihre ISAs entworfen.
  • Verzweigungsvorhersage : Schätzen Sie parallel zum Abrufen jeder Anweisung, ob die Anweisung eine Verzweigung oder ein Sprung ist, und wenn ja, erraten Sie das Ziel. Rufen Sie im Zyklus nach einer Verzweigung oder einem Sprung den Befehl am geschätzten Ziel ab. Wenn die Vermutung falsch ist, spülen Sie das falsch abgerufene Ziel.

Verzögerte Verzweigungen waren erstens umstritten, weil ihre Semantik kompliziert ist. Eine verzögerte Verzweigung gibt an, dass der Sprung zu einer neuen Stelle nach dem nächsten Befehl erfolgt. Dieser nächste Befehl ist derjenige, der nach der Verzweigung unvermeidlich vom Befehlscache geladen wird.

Verzögerte Verzweigungen wurden als schlechte kurzfristige Wahl im ISA-Design kritisiert:

  • Compiler haben typischerweise einige Schwierigkeiten, logisch unabhängige Befehle zu finden, die nach der Verzweigung platziert werden sollen (der Befehl nach der Verzweigung wird als Verzögerungsschlitz bezeichnet), so dass sie NOPs in die Verzögerungsschlitze einfügen müssen.
  • Superskalare Prozessoren, die mehrere Befehle pro Zyklus abrufen und irgendeine Form von Verzweigungsvorhersage haben müssen, profitieren nicht von verzögerten Verzweigungen. Der Alpha ISA ließ verzögerte Verzweigungen aus, da er für superskalare Prozessoren gedacht war.
  • Der gravierendste Nachteil verzögerter Verzweigungen ist die zusätzliche Steuerungskomplexität, die sie mit sich bringen. Wenn der Verzögerungsschlitzbefehl eine Ausnahme annimmt, muss der Prozessor in der Verzweigung neu gestartet werden, anstatt in diesem nächsten Befehl. Ausnahmen haben dann im Wesentlichen zwei Adressen, die Ausnahmeadresse und die Neustartadresse, und das korrekte Generieren und Unterscheiden zwischen den beiden in allen Fällen war eine Quelle von Fehlern für spätere Designs.

Ausnahmen

Angenommen, ein 32-Bit-RISC verarbeitet einen ADD-Befehl, der zwei große Zahlen addiert, und das Ergebnis passt nicht in 32 Bits.

Die einfachste Lösung, die von den meisten Architekturen bereitgestellt wird, ist die Wrapping-Arithmetik. Bei Zahlen, die größer als der maximal mögliche codierte Wert sind, werden ihre höchstwertigen Bits abgeschnitten, bis sie passen. Im üblichen Ganzzahlsystem ist 3000000000+3000000000=6000000000. Mit vorzeichenloser 32-Bit-Wrap-Arithmetik, 3000000000+3000000000=1705032704 (6000000000 mod 2^32). Dies mag nicht besonders nützlich erscheinen. Der größte Vorteil der Wrapping-Arithmetik besteht darin, dass jede Operation ein genau definiertes Ergebnis hat.

Aber der Programmierer, insbesondere wenn er in einer Sprache programmiert, die große Ganzzahlen unterstützt (zB Lisp oder Scheme ), möchte möglicherweise keine Wrapping-Arithmetik. Einige Architekturen (zB MIPS) definieren spezielle Additionsoperationen, die bei Überlauf zu speziellen Stellen verzweigen, anstatt das Ergebnis zu umhüllen. Software am Zielort ist für die Behebung des Problems verantwortlich. Dieser spezielle Zweig wird als Ausnahme bezeichnet. Ausnahmen unterscheiden sich von regulären Verzweigungen dadurch, dass die Zieladresse nicht durch den Befehl selbst angegeben wird und die Verzweigungsentscheidung vom Ergebnis des Befehls abhängt.

Die häufigste Art von Software-sichtbarer Ausnahme auf einem der klassischen RISC-Computer ist ein TLB-Miss .

Ausnahmen unterscheiden sich von Verzweigungen und Sprüngen, da diese anderen Kontrollflussänderungen in der Dekodierungsstufe aufgelöst werden. Ausnahmen werden in der Rückschreibphase aufgelöst. Wenn eine Ausnahme erkannt wird, werden die folgenden Anweisungen (früher in der Pipeline) als ungültig markiert, und wenn sie zum Ende der Pipeline fließen, werden ihre Ergebnisse verworfen. Der Programmzähler wird auf die Adresse eines speziellen Ausnahmehandlers gesetzt, und spezielle Register werden mit der Ausnahmeposition und -ursache geschrieben.

Damit die Software das Problem einfach (und schnell) beheben und das Programm neu starten kann, muss die CPU eine genaue Ausnahme machen. Eine genaue Ausnahme bedeutet, dass alle Anweisungen bis auf die Ausnahmeanweisung ausgeführt wurden und die Ausnahmeanweisung und alles danach nicht ausgeführt wurde.

Zu nehmen präzise Ausnahmen muss die CPU verpflichten Änderungen an der Software sichtbaren Zustand in der Programmreihenfolge. Dieses Commit in der richtigen Reihenfolge geschieht in der klassischen RISC-Pipeline ganz natürlich. Die meisten Befehle schreiben ihre Ergebnisse in der Rückschreibphase in die Registerdatei, und so erfolgen diese Schreibvorgänge automatisch in der Programmreihenfolge. Speicheranweisungen schreiben ihre Ergebnisse jedoch in der Zugriffsphase in die Speicherdatenwarteschlange. Wenn der Speicherbefehl eine Ausnahme annimmt, wird der Eintrag der Speicherdatenwarteschlange ungültig gemacht, so dass er später nicht in den Cache-Daten-SRAM geschrieben wird.

Cache-Miss-Behandlung

Gelegentlich enthält entweder der Daten- oder der Befehlscache keine erforderlichen Daten oder Befehle. In diesen Fällen muss die CPU den Betrieb unterbrechen, bis der Cache mit den erforderlichen Daten gefüllt werden kann, und muss dann die Ausführung wieder aufnehmen. Das Problem des Füllens des Caches mit den erforderlichen Daten (und möglicherweise des Zurückschreibens der entfernten Cache-Zeile in den Speicher) ist nicht spezifisch für die Pipeline-Organisation und wird hier nicht erörtert.

Es gibt zwei Strategien, um das Suspend/Resume-Problem zu lösen. Das erste ist ein globales Stall-Signal. Dieses Signal, wenn es aktiviert ist, verhindert, dass Befehle in der Pipeline nach unten vorrücken, im Allgemeinen durch Aussteuern des Takts zu den Flip-Flops zu Beginn jeder Stufe. Der Nachteil dieser Strategie besteht darin, dass es eine große Anzahl von Flip-Flops gibt, so dass das globale Stall-Signal lange braucht, um sich auszubreiten. Da die Maschine im Allgemeinen in dem gleichen Zyklus abwürgen muss, in dem sie die Bedingung erkennt, die das Abwürgen erfordert, wird das Abwürgesignal zu einem geschwindigkeitsbegrenzenden kritischen Pfad.

Eine andere Strategie zur Handhabung von Suspend/Resume besteht darin, die Ausnahmelogik wiederzuverwenden. Die Maschine nimmt eine Ausnahme bei der beanstandeten Anweisung vor, und alle weiteren Anweisungen werden ungültig. Wenn der Cache mit den erforderlichen Daten gefüllt ist, wird die Anweisung, die den Cache-Fehltreffer verursacht hat, neu gestartet. Um die Fehlerbehandlung des Datencachespeichers zu beschleunigen, kann der Befehl neu gestartet werden, so dass sein Zugriffszyklus einen Zyklus nach dem Füllen des Datencachespeichers stattfindet.

Siehe auch

Verweise

  • Hennessy, John L.; Patterson, David A. (2011). Computerarchitektur, ein quantitativer Ansatz (5. Aufl.). Morgan Kaufmann. ISBN 978-0123838728.
  1. ^ Patterson, David. "RISC I: Ein VLSI-Computer mit reduziertem Befehlssatz" . Cite Journal erfordert |journal=( Hilfe )
  2. ^ Patterson, David. "RISC I: Ein VLSI-Computer mit reduziertem Befehlssatz" . Cite Journal erfordert |journal=( Hilfe )