Befehlsregister und die Dekodierphase
Wie eine Lehr-CPU einen Befehl erfasst, Opcode-, Register- und Immediate-Felder extrahiert und daraus validierte Steuersignale erzeugt – mit RISC-V- und x86-Kontext.
Kurz gesagt: In einer einfachen CPU erfasst ein Befehlsregister (IR) einen geholten Befehl, damit die Dekodierung stabile Bits sieht. Die Dekodierung erkennt das Befehlsformat, extrahiert Register- und Immediate-Felder, prüft, ob die Kodierung zulässig ist, und erzeugt Steuerinformationen für spätere Phasen. Ein moderner Prozessor kann diese Aufgabe auf Fetch-Puffer und Pipeline-Register verteilen, statt ein einzelnes architektonisches „IR“ zu besitzen.
Der Programmzähler beantwortet die Frage woher holen? Die Dekodierphase beantwortet was die geholten Bits bedeuten. Dazwischen platziert eine Lehr-CPU üblicherweise ein Befehlsregister: eine Bank aus Flipflops, die den aktuellen Befehl bewahrt, während die Steuerlogik ihn untersucht.
Dieses Modell ist nützlich, braucht aber eine klare Grenze. Das Befehlsregister ist in den meisten ISAs kein für Programmierende sichtbares Register, und eine leistungsstarke Implementierung kann viele Befehle gleichzeitig in Fetch-Blöcken, Warteschlangen, Pipeline-Registern oder Caches für dekodierte Operationen halten. „IR“ bezeichnet eine Rolle im Lehrdatenpfad, keine universelle physische Komponente.
Der Lehrdatenpfad
Eine kleine Mehrzyklus-CPU kann so dargestellt werden:
PC → instruction memory → instruction register → field extraction → control
Bei einem Ereignis zum Holen eines Befehls:
- liefert der PC eine Befehlsadresse;
- gibt der Befehlsspeicher ein Befehlswort zurück;
- erfasst das IR dieses Wort an der aktiven Taktflanke; und
- interpretiert kombinatorische Dekodierlogik die gespeicherten Bits.
Die Schreibfreigabe des IR wird nur aktiviert, wenn ein neuer Befehl angenommen werden soll. Während eines Stalls hält das IR seinen alten Wert. Bei einem Reset oder Pipeline-Flush markiert die Steuerung den gespeicherten Befehl entweder als ungültig oder ersetzt ihn durch eine harmlose Operation.
Manche Mehrzyklus-Datenpfade platzieren ein Speicher-Datenregister zwischen Speicher und IR. Andere erfassen die Speicherausgabe direkt. Keine der beiden Folgen ist universell; das Timing und der Handshake der gewählten Speicherschnittstelle bestimmen, welche Register erforderlich sind.
Eine kleine Beispielkodierung
Angenommen, eine Acht-Bit-Lehr-ISA definiert dieses Format:
7 5 4 2 1 0
┌──────────────┬───────────────┬───────────────┐
│ opcode [2:0] │ register [2:0]│ mode / small │
│ │ │ immediate │
└──────────────┴───────────────┴───────────────┘
Die genauen Felder sind eine ISA-Entscheidung. Acht Bits können nicht gleichzeitig einen großen Opcode-Raum, zwei unabhängige Registeroperanden und ein brauchbares Immediate kodieren; daher verwendet eine echte Lehr-ISA oft mehrere Formate. Zum Beispiel:
- eine Registeranweisung kann Bits für Quell- und Zieladressen vorsehen;
- eine Load-Immediate-Anweisung kann die meisten unteren Bits als Konstante verwenden; und
- eine Sprunganweisung kann dieselben Bits als Offset interpretieren.
Die Dekodierung muss zunächst das Format feststellen und anschließend die übrigen Bits entsprechend interpretieren. Jedem Bit eine dauerhafte einzelne Bezeichnung zu geben, ergibt die falsche Schaltung.
Felder mit fester Position: RISC-V-Beispiel
Die Basis-ISA RISC-V verwendet 32-Bit-Befehlsformate. Für einen Befehl des R-Typs:
31 25 24 20 19 15 14 12 11 7 6 0
┌────────────┬────────┬────────┬───────┬─────────┬──────────┐
│ funct7 │ rs2 │ rs1 │ funct3│ rd │ opcode │
└────────────┴────────┴────────┴───────┴─────────┴──────────┘
Die Registerfelder belegen in den Basisformaten konsistente Positionen:
opcode = IR[6:0]
rd = IR[11:7]
funct3 = IR[14:12]
rs1 = IR[19:15]
rs2 = IR[24:20]
funct7 = IR[31:25]
Diese Slices sind Verdrahtung, keine Arithmetik. rs1 und rs2 speisen die Leseadressen der Registerdatei; rd kennzeichnet ein mögliches Ziel; und Opcode plus Funktionsbits identifizieren die Operationsklasse und -variante.
Bei Immediates ist mehr Sorgfalt nötig. In mehreren RISC-V-Formaten sind die Immediate-Bits absichtlich über den Befehl verteilt. Die Hardware muss sie in der angegebenen Reihenfolge zusammenfügen und vom architektonisch festgelegten Vorzeichenbit aus vorzeichenerweitern. Das bleibt einfache kombinatorische Verdrahtung, ist aber nicht immer ein zusammenhängender Slice.
Dekodierung ist mehr als ein Opcode-Dekoder
Für eine Spielzeug-ISA mit acht vollständigen Operationen kann ein Drei-zu-Acht-Dekoder One-Hot-Signale erzeugen:
| Opcode | Lehr-Operation | One-Hot-Ergebnis |
|---|---|---|
000 | NOP | is_nop |
001 | LOAD | is_load |
010 | STORE | is_store |
011 | ADD | is_add |
100 | SUB | is_sub |
101 | JUMP | is_jump |
110 | BRANCH-Z | is_branch_z |
111 | HALT | is_halt |
Aus diesen Signalen lassen sich dann Steuergleichungen ableiten:
Das ist eine nützliche Einführung in Dekoder und Sum-of-Products-Logik, aber nicht die allgemeine Struktur eines echten Dekoders.
In einer größeren ISA:
- wählt der primäre Opcode oft ein Format oder eine Befehlsfamilie statt einer einzelnen Operation;
- unterscheiden sekundäre Funktionsfelder die Mitglieder der Familie;
- können Modus- oder Präfixzustand Operandenbreite und Interpretation verändern;
- sind einige Bitmuster reserviert oder unzulässig;
- können Privilegien und verfügbare Erweiterungen die Zulässigkeit beeinflussen; und
- sind Steuerausgänge üblicherweise kodiert statt eine eigene Leitung für jeden Befehl zu haben.
Ein korrekter Dekoder muss nicht unterstützte Kodierungen zurückweisen, statt sie versehentlich als einen ähnlichen zulässigen Befehl zu behandeln.
Was die Dekodierung erzeugt
Das Ergebnis sollte man eher als Steuerbündel denn als Dutzende unabhängiger Leitungen verstehen. Ein Lehrbündel könnte enthalten:
| Feld | Bedeutung |
|---|---|
alu_op | Addition, Subtraktion, logische Operation, Vergleich oder Durchleitung auswählen |
src_a / src_b | Register, PC, Immediate oder Konstante als Operanden wählen |
reg_write | Einen Schreibvorgang in die Registerdatei in der passenden späteren Phase erlauben |
mem_read / mem_write | Eine Daten-Speicheroperation anfordern |
result_source | ALU, Speicher, PC-relativen Wert oder eine andere Writeback-Quelle auswählen |
branch_kind | Keinen Sprung, bedingten Sprung, direkten Sprung oder indirekten Sprung auswählen |
immediate | Wieder zusammengesetzte und erweiterte Konstante |
legal | Anzeigen, ob die Kodierung im aktuellen Maschinenzustand unterstützt wird |
Diese Signale müssen durch Pipeline-Gültigkeit und das Timing der Phasen qualifiziert werden. Ein kombinatorisches reg_write = 1 bei der Dekodierung ist keine Erlaubnis, die Registerdatei sofort zu aktualisieren; geschrieben wird erst, wenn der Befehl die vorgesehene Phase erreicht, ohne verworfen worden zu sein oder einen Fehler ausgelöst zu haben.
Feste und variable Befehlslänge
Die Befehlslänge verändert den vorderen Teil des Dekodierproblems.
Beispiel mit fester Länge: Arm A64
Arm-A64-Befehle sind 32 Bit breit. Sobald Fetch ein ausgerichtetes Wort geliefert hat, können die Feldpositionen direkt untersucht werden. Die feste Länge vereinfacht das Erkennen von Befehlsgrenzen, macht aber nicht jede Operation oder Immediate-Kodierung trivial.
RISC-V mit komprimierten Befehlen
RISC-V-Basisbefehle sind 32 Bit breit. Die optionale komprimierte Erweiterung fügt 16-Bit-Befehle hinzu, und die Architektur reserviert ein Längenkodierungsschema für längere Kodierungen. Fetch muss feststellen, ob der nächste Befehl zwei, vier oder eine andere unterstützte Anzahl von Bytes belegt, bevor der PC weitergeschaltet und der nächste Befehl ausgerichtet wird.
Beispiel mit variabler Länge: x86
x86-Befehle sind ein bis 15 Byte lang und können historische oder moderne Präfixkodierungen, Opcode-Bytes, ModR/M- und SIB-Adressierungsbytes, Displacement und Immediate-Daten enthalten. Welche Teile vorhanden sind, hängt von den vorangehenden Bytes ab.
Ein modernes x86-Frontend benötigt daher eine Dekodierung von Befehlsgrenzen und -längen vor oder neben der semantischen Dekodierung. Implementierungen unterscheiden sich: Es ist unsicher zu behaupten, dass jeder Prozessor einen festen Blockumfang holt, dieselbe Warteschlangenstruktur verwendet oder jeden Befehl über denselben Pfad übersetzt. Die Architekturhandbücher von Intel definieren die softwareseitig sichtbare Kodierung; die genaue Pipeline ist mikroarchitekturspezifisch.
Feste und variable Länge sind keine Synonyme für RISC und CISC. Sie beschreiben eine Eigenschaft der Kodierung.
Festverdrahtete und sequenzierte Steuerung
Eine kleine CPU kann die Steuerung direkt aus Boolescher Logik erzeugen. Eine Mehrzyklussteuerung kann stattdessen eine Zustandsmaschine oder einen Steuerungsspeicher nutzen, dessen Einträge mehrere interne Schritte beschreiben. Reale Prozessoren können schnelle Dekodierpfade mit sequenzierter Behandlung komplexerer Operationen kombinieren.
Der hilfreiche Unterschied lautet:
- Kombinatorische Dekodierung bildet aktuelle Felder auf eine anfängliche Steuerdarstellung ab.
- Sequenzierte Steuerung gibt im Zeitverlauf mehrere interne Aktionen aus.
Keine Methode ist automatisch „RISC“ oder „CISC“, und eine mikrokodierte Implementierung ist nicht von Natur aus langsam. Die Leistung hängt von der vollständigen Implementierung und der Arbeitslast ab.
Pipelinesteuerung: Stall, Flush und Gültigkeit
Sobald mehrere Befehle überlappen, sind die Befehlsbits nur ein Teil des Zustands. Jedes Pipeline-Register benötigt außerdem Steuermetadaten.
Stall
Wenn die nächste Phase einen Befehl nicht annehmen kann, muss das aktuelle Fetch-/Dekodierregister seine Daten halten oder an einem Ready/Valid-Handshake teilnehmen. Wenn die Bits weiterrücken, während der Gültigkeitszustand angehalten ist, gehen Befehl und Steuerung auseinander.
Flush
Eine fehlvorhergesagte Verzweigung, eine Ausnahme oder ein Reset kann jüngere Befehle ungültig machen. Nur die Befehlsbits zu löschen ist weniger robust, als ein Gültigkeitsbit zu löschen, weil eine reine Null-Kodierung in manchen ISAs selbst zulässig sein kann.
Abhängigkeitsbehandlung
Die Dekodierung kann Quell- und Zielregister für Hazard-Prüfungen identifizieren. Die Reaktion kann ein Stall, eine Forwarding-Auswahl, Registerumbenennung oder eine andere implementierungsspezifische Aktion sein. Die Feldextraktion liefert die Kennungen; spätere Steuerung entscheidet, was damit geschieht.
Häufige Entwurfsfehler
- Annehmen, dass Speicher immer ein MDR benötigt. Fügen Sie Register anhand des tatsächlichen Speicherzeitverhaltens und der Schnittstelle hinzu, nicht aufgrund eines vermeintlich universellen Diagramms.
- Das IR verändern, während sein Befehl noch aktiv ist. Verwenden Sie eine Schreibfreigabe oder ein Handshake-Verfahren, damit der Decoder stabile Bits auswertet.
- Nur den primären Opcode dekodieren. Funktionsfelder, Modi, Erweiterungen und Zulässigkeitsprüfungen können nötig sein.
- Immediate-Bits in numerischer Zeichenreihenfolge zusammenfügen. Befolgen Sie exakt die Bitzuordnung der ISA und führen Sie anschließend die Vorzeichenerweiterung ausgehend vom festgelegten Vorzeichenbit durch.
- Seiteneffekte direkt aus unqualifizierter Dekodierung ansteuern. Gatter Schreibvorgänge mit Pipeline-Gültigkeit, Phasen-Timing und Ausnahme-/Flush-Zustand.
- Auf ein beliebiges Befehlsmuster zurücksetzen. Bevorzugen Sie ein Gültigkeitsbit oder einen definierten Reset-Zustand des Steuerwerks; setzen Sie nicht voraus, dass ein ausschließlich aus Nullen bestehendes Wort zwingend NOP bedeutet.
- Eine pädagogische Wellenform als Nachweis für physisches Timing behandeln. Das Modell kann logische Abfolgen zeigen, nicht die Einhaltung von Setup-/Hold-Zeiten in Silizium.
Einen Lehrdekoder bauen und überprüfen
Öffnen Sie den sequentiellen Befehlsausführer und identifizieren Sie:
- das Befehlsspeicherelement;
- die Leitungen, die jedes Feld bilden;
- die von jedem Feld beeinflussten Steuerausgänge; und
- den Punkt, an dem diese Ausgänge den Architekturzustand verändern dürfen.
Erstellen Sie anschließend eine kompakte Testtabelle:
| Testklasse | Was variieren | Erwartetes Ergebnis |
|---|---|---|
| Jeder zulässige Opcode | Primäre Opcode-Bits | Richtige Operationsfamilie und Freigaben für Seiteneffekte |
| Funktionsvarianten | Sekundäre Felder | Richtige ALU- oder Adressierungsvariante |
| Registeradressen | rs- / rd-Felder | Richtige Registerports, unveränderte Operation |
| Immediate-Grenzwerte | Null, größtes Positiv, kleinstes Negativ | Richtige Zusammensetzung und Erweiterung |
| Reservierte Kodierung | Nicht unterstütztes Bitmuster | Illegal-Instruction-Pfad, kein unbeabsichtigter Schreibvorgang |
| Stall | Dekodierung mehrere Takte halten | Befehl und Steuerung bleiben ausgerichtet |
| Flush | Einen Befehl in der Pipeline ungültig machen | Kein Seiteneffekt auf Register oder Speicher |
Ein Beispiel manuell umzuschalten ist eine Veranschaulichung, keine ausreichende Überprüfung. Decke jede zulässige Operationsklasse und repräsentative unzulässige Kodierungen ab.
Wo es in die CPU passt
Der Programmzähler liefert die Fetch-Adresse. Die Dekodierung identifiziert Operanden und Steuerabsicht. Das CPU-Flag-Register ist in flagbasierten ISAs eine mögliche Quelle von Sprungbedingungen; andere ISAs vergleichen Register direkt. Das Steuerwerk sequenziert den Lehrdatenpfad und qualifiziert Seiteneffekte.
Zusammen erklären diese Elemente den Steuerfluss eines kleinen Prozessors, doch keines von ihnen ist allein „die gesamte Steuerungsebene“. Caches, Vorhersage, Ausnahmen, Privilegien, Hazards und Pipelinezustand fügen in größeren Maschinen weitere Steuerung hinzu.
Primärquellen
- Bibliothek der unprivilegierten RISC-V-ISA-Spezifikation
- RISC-V-Basisbefehlsformate
- Erklärung von Arm zur A64-Kodierung fester Breite
- Softwareentwicklerhandbücher für Intel 64 und IA-32
Lesen Sie als Nächstes die ausführliche Betrachtung von Fetch–Decode–Execute und ändern Sie anschließend eine Kodierung in der Lehr-CPU. Aktualisieren Sie Decoder, Tests und Dokumentation gemeinsam.



