375 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ---
 | ||
| title: Rechnerarchitekturen 2
 | ||
| date: Wintersemester 20/21
 | ||
| author: Robert Jeutter
 | ||
| ---
 | ||
| 
 | ||
| # Einführung
 | ||
| > Rechnerarchitektur = Programmierschnittstelle + Interner Aufbau\\
 | ||
| > Einheit von Struktur und Funktion
 | ||
| 
 | ||
| - Programmierschnittstelle
 | ||
|     - Schnittstelle zwischen Rechner und Benutzer bzw. der Hardware und der untersten Softwareschicht
 | ||
|     - Befehlssatzarchitektur (Instruction Set Architecture)
 | ||
| - Interner Aufbau
 | ||
|     - Hardware-Aufbau von Komponenten, die die Rechnerarchitektur realisieren
 | ||
|     - Speichereinheiten, Recheneinheiten, Verbindungssysteme,
 | ||
| 
 | ||
| Abstraktionsebenen eines Rechnersystems
 | ||
| | Anwendungsprogramm | Java, C,... |
 | ||
| | Assemblerprogramm | Betriebssystem-Ebene |
 | ||
| | Maschinenprogramm | Betriebssystem-Ebene |
 | ||
| | Register Transfer Verhaltensebene | Reg[2]:=Reg[3] |
 | ||
| | Register Transfer Strukturebene | Addierer, Multiplexer, Register |
 | ||
| | Gatterebene | $f=a\vee bc$ |
 | ||
| | Transistorebene |  |
 | ||
| 
 | ||
| Grundarchitekturen:
 | ||
| - Harvard (Zugriff direkt durch Prozessor)
 | ||
| - Princton/von-Neumann (Zugriff über Systembus)
 | ||
| 
 | ||
| | Speicher | Daten und Instruktionen speichern |
 | ||
| | Steuerwerk | beinhaltet Programmzähler um Ausführung zu steuern |
 | ||
| | Rechenwerk | auch ALU (Arithmetic and Logic Unit) um Berechnung durchzuführen
 | ||
| Üblicherweise besitzt eine Recheneinheit (CPU) Daten- oder Rechenregister (Registermaschine). Berechnungen werden ausschließlich mit den Registern vorgenommen.
 | ||
| - Daten aus Hauptspeicher in Register laden
 | ||
| - Berechnungsaufgaben durchführen
 | ||
| - Ergebnisse in Hauptspeicher ablegen
 | ||
| 
 | ||
| Klassifikation von Befehlssatzarchitekturen
 | ||
| - 0-Operand (Stack): Add
 | ||
| - 1-Operand (Akkumulator): Add R1
 | ||
| - 2-Operand: Add R1, R3
 | ||
| - 3-Operand: Add R1, R2, R3
 | ||
| 
 | ||
| 
 | ||
| # Prozessorarchitektur
 | ||
| Programmiermodelle, Instruction Set Architectures (ISAs): 
 | ||
| Klassifikation von Befehlssätzen nach der Gestaltung/Ausprägung der vorhandenen Maschinenbefehle
 | ||
| 
 | ||
| | CISC | RISC | MIPS |
 | ||
| | -- | -- | -- |
 | ||
| | Complex Instruction Set Computing | Reduced Instruction Set Computing | Microprocessor without interlocked pipeline stages |
 | ||
| | Einfache und komplexe Befehle | Nur einfache Befehle | |
 | ||
| | Heterogener Befehlssatz | Orthogonaler Befehlssatz | |
 | ||
| | Verschiedene Taktzahl pro Befehl | Meist 1 Takt pro Befehl | |
 | ||
| | Viele Befehlscode-Formate mit unterschiedlicher Länge | Wenige Befehlscode-Formate mit einheitlicher Länge | |
 | ||
| | Mikroprogrammwerk | Direktverdrahtung | |
 | ||
| | Vermischung von Verarbeitungs- und Speicherbefehlen | Trennung von Verarbeitungs- und Speicherbefehlen | |
 | ||
| | schwierig, unter CPI = 2 zu kommen | CPI möglichst nicht über 1 | |
 | ||
| 
 | ||
| > Unter dem CPI (cycles per instruction) -Wert einer Menge von Maschinenbefehlen versteht man die mittlere Anszahl der Taktzyklen pro Maschinenbefehl
 | ||
| 
 | ||
| 
 | ||
| ## Einzelzyklusmaschine
 | ||
| - Programmzähler (32 bit, PZ, engl. Program Counter, PC)
 | ||
|   - Speichert und liefert die aktuelle auszuführende Instruktionsadresse
 | ||
|   - an den Instruktionsspeicher (b) und das Addierwerk (a)
 | ||
|   - übernimmt die Adresse der Folgeinstruktion (c)
 | ||
| - Addierwerk
 | ||
|   - Fortlaufende Addition mit 4, da 4-Byte Instruktionen
 | ||
|   - Der neue Wert für PZ wird im Register gespeichert (c)
 | ||
|   - Die hintersten 2 Bit im PZ sind immer Null
 | ||
| - Instruktionsspeicher
 | ||
|   - Liefert die auszuführende Maschineninstruktion
 | ||
| - Instruktionswort (32 bit)
 | ||
|   - Gelesener Wert erscheint am Ausgang des Speichers
 | ||
|   - Instruktionsformat bestimmt den weiteren Ablauf
 | ||
| - Master-Slave Flip-Flops
 | ||
|   - Master übernimmt Wert bei steigender Taktflanke
 | ||
|   - Slave übernimmt Wert bei fallender Taktflanke
 | ||
|   - Instruktionszyklus beginnt bei fallender Taktflanke
 | ||
| - Ansteuerung des Registersatzes
 | ||
|   - Register immer auslesen (kein Takt) und Transport zur ALU
 | ||
|   - Schreiben des Zielregisters Register[rd] am Ende der Taktperiode
 | ||
|   - Zeit für Speicherzugriff und für die primäre ALU muss eingeplant werden
 | ||
|   - Ausgabe des Instruktionsspeichers wird über die ganze Dauer gehalten
 | ||
| - Vorzeichenerweiterung des Direktoperanden von 16 auf 32 Bit
 | ||
|   - Erleichtert die Unterbringung kleiner Konstanten im Befehlswort
 | ||
|   - Vom Steuerwerk aus abschaltbar für „unsigned“ Befehle
 | ||
| 
 | ||
| ### Ausführungsphase
 | ||
| - ALU-Registeroperationen
 | ||
|   - Operanden im Register oder als
 | ||
| - Direktoperand
 | ||
|   - Üblicher Satz an ALU-Operationen
 | ||
|   - Register $0 liefert Wert 0
 | ||
| - Adressierung von Variablen im Speicher
 | ||
|   - Adressrechnung in der primären ALU
 | ||
|   - Basisregister plus Direktoperand
 | ||
|   - Registerinhalt lesen/schreiben
 | ||
| - Load/Store-Architektur
 | ||
|   - Speicheroperationen können keine Arithmetik
 | ||
|   - also z.B. kein inc 0xaff0($7),0x0004
 | ||
|   - ALU schon zur Adressberechnung benötigt
 | ||
| - Separater Addierer zur Sprungzielberechnung
 | ||
|   - Prüfschaltung auf Gleichheit zweier Register in der primären ALU („eql“) 
 | ||
|   - Bedingte Sprünge mit einem 16-bit Direktoperanden (beq $7,$8,loop)
 | ||
|   - Maximal möglicher Offset von ±17 Bit nach einer 2-bit Verschiebung
 | ||
|   - Unbedingte Sprünge mit 28-bit Adresse später
 | ||
| 
 | ||
| ### Speicherzugriff
 | ||
| - Getrennte Speicher für Code & Daten
 | ||
|   - Aktuelle Instruktion wird bis zum Ende des Gesamtzyklus gehalten
 | ||
|   - Kein zweiter Zugriff im gleichen Taktzyklus möglich 
 | ||
| - Quellregister speichern, falls Store
 | ||
|   - Speichersteuerung durch besonderes Schreibsignal
 | ||
| - Zielregister laden
 | ||
|   - Falls Ladebefehl aus dem Speicher
 | ||
|   - Falls Rücksprungadresse (PC-magic)
 | ||
|   - Falls Resultat aus ALU
 | ||
| - ALU-Resultat nutzen
 | ||
|   - Für „Register Write-Back“
 | ||
|   - Als Datenspeicheradresse
 | ||
|   - Nicht direkt speichern, wg. Load/Store-Architektur!
 | ||
| 
 | ||
| ### Register zurückschreiben
 | ||
| - Nummer des Zielregisters (Zielregisterselektor)
 | ||
|   - Stammt aus IR[15-11] oder IR[20-16], 5-bit Bereich für Werte 0-31
 | ||
| - Steuersignal
 | ||
|   - Zielregister zum Ende des Instruktionszyklus schreiben
 | ||
|   - Schreibsignal an Registersatz, falls nötig
 | ||
| - Pseudorelative Sprünge (jump xLabel)
 | ||
|   - Kein separater Addierer erforderlich, nur ein zusätzlicher MUX-Eingang
 | ||
|   - Oberste 4 Bits unverändert, untere 28 Bits werden ersetzt (4, 26, 2)
 | ||
|   - Jump-and-Link (jal) sichert alten Programmzähler in $31 (Subroutine)
 | ||
| 
 | ||
| ### erforderliche Steuerleitung
 | ||
| - Für Speicher
 | ||
|   - 2-bit Steuersignal: 0/8/16/32 Bit zum Datenspeicher schreiben
 | ||
|   - Instruktionsspeicher liest immer
 | ||
| - Für Registersatz
 | ||
|   - 2-bit Steuersignal: 0/8/16/32 Bit zum Registerfile schreiben
 | ||
| - Für 4 Multiplexer
 | ||
|   - 2-bit Steuersignal: Auswahl des Zielregisters (1 aus 3)
 | ||
|   - 2-bit Steuersignal: Datenquelle für Zielregister
 | ||
|   - 2-bit Steuersignal: Sprungziel wählen
 | ||
|   - 1-bit Steuersignal: Direkt- oder Registeroperand für ALU
 | ||
| - Für Arithmetik
 | ||
|   - 1-bit Steuersignal: Vorzeichenerweiterung ja/nein
 | ||
|   - 6-bit Steuersignal: ALU-Operation
 | ||
| 
 | ||
| Einzyklusmaschine ist unwirtschaftlich
 | ||
| - Komponenten arbeiten jeweils nur einen kleinen Teil der Gesamtzeit
 | ||
| - Zeitverlust bei potentiell kurzen Instruktionen
 | ||
| 
 | ||
| ## Mehrzyklen CPU
 | ||
| - Gesamtzyklus der bisherigen MIPS
 | ||
|   - Dauer des Instruktionszyklus ist die Summe der Einzelverzögerungen
 | ||
|   - Unteraktivitäten müssen abwarten, bis die Parameter sicher vorliegen
 | ||
|   - Anderenfalls können sich „spurious writes“ ergeben
 | ||
|   - z.B. in Registersatz oder in den Speicher
 | ||
| - Mehrzyklen-CPU als Überleitung zum Fließbandprinzip
 | ||
|   - Aufteilung der Befehlsausführung auf mehrere gleich lange Taktzyklen
 | ||
|   - Einfügen von Registern für in den Stufen entstandene Zwischenresultate
 | ||
|   - Noch immer nur eine Instruktion zu einem Zeitpunkt in Ausführung
 | ||
|   - CPU-Zustand bezieht sich auf eine einzelne aktuelle Instruktion
 | ||
| - Pipelined CPU – mit Fließbandprinzip
 | ||
|   - In jedem Taktzyklus beginnt eine neue Maschineninstruktion
 | ||
|   - Mehrere Instruktionen gleichzeitig in Ausführung
 | ||
|   - Aber unterschiedlicher Fertigstellungsgrad
 | ||
|   - Bessere Auslastung der Hardware
 | ||
|   - Höherer Durchsatz
 | ||
| - Große Pipeline-Tiefe:
 | ||
|   - Zusätzliche Ressourcen, höherer Energieaufwand (Taktfrequenz!)
 | ||
|   - Längere Instruktionssequenzen für gleichen oder besseren Speedup (→ Registeroverhead!)
 | ||
|   - Bei unterschiedlichen Stufenverzögerungen bestimmt die langsamste Stufe die Taktfrequenz
 | ||
| - Lange Instruktionssequenzen:
 | ||
|   - Meist wegen Daten- und Kontrollabhängigkeiten nicht machbar
 | ||
|   - Hohe Latenz – Füllen und Leeren der Pipeline!
 | ||
| - Warum geht die Anzahl der Pipeline-Stufen zurück?
 | ||
|   - hoher Energieverbrauch
 | ||
|   - hohe Leistungseinbußen durch Kontroll- und Datenabhängigkeiten (Füllen/Leeren der Pipeline)
 | ||
|   - mehr Parallelität in den einzelnen Pipeline-Stufen → superskalare Prozessoren
 | ||
|   - mehr Prozessorkerne mit geringerer Leistungsaufnahme pro Kern
 | ||
| - Fließband-Architektur (engl. pipeline architecture): Bearbeitung mehrerer Befehle gleichzeitig, analog zu Fertigungsfließbändern.
 | ||
| 
 | ||
| Aufgaben der einzelnen Phasen
 | ||
| - Befehlsholphase
 | ||
|   - Lesen des aktuellen Befehls; separater Speicher, zur Vermeidung von Konflikten mit Datenzugriffen
 | ||
| - Dekodier- und Register-Lese-Phase
 | ||
|   - Lesen der Register möglich wegen fester Plätze für Nr. im Befehlswort
 | ||
| - Ausführungs- und Adressberechnungsphase
 | ||
|   - Berechnung arithmetischer Funktion bzw. Adresse für Speicherzugriff
 | ||
| - Speicherzugriffsphase
 | ||
|   - Wird nur bei Lade- und Speicherbefehlen benötigt
 | ||
| - Abspeicherungsphase
 | ||
|   - Speichern in Register, bei Speicherbefehlen nicht benötigt
 | ||
| 
 | ||
| Pipeline-Hazards
 | ||
| > Structural Hazards (deutsch: strukturelle Abhängigkeiten oder Gefährdungen): Verschiedene Fließbandstufen müssen auf dieselbe Hardware-Komponente zugreifen, weil diese nur sehr aufwändig oder überhaupt nicht zu duplizieren ist.
 | ||
| 
 | ||
| > Definition: Ein Befehl i heißt von einem nachfolgenden Befehl j antidatenabhängig, falls j eine Speicherzelle beschreibt, die von i noch gelesen werden müsste.
 | ||
| 
 | ||
| > Definition: Zwei Befehle i und j heißen voneinander Ausgabeabhängig, falls i und j die selbe Speicherzelle beschreiben.
 | ||
| 
 | ||
| - Gleichheit der Register wird schon in der instruction decode-Stufe geprüft
 | ||
| - Sprungziel wird in separatem Adressaddierer ebenfalls bereits in der instruction decode-Stufe berechnet
 | ||
| - Sofern weiterhin noch Verzögerungen auftreten:
 | ||
|   - nächsten Befehl einfach ausführen (delayed branch)
 | ||
|   - oder weiterhin NOOP(s) einfügen (stall)
 | ||
| 
 | ||
| ### Pipelining – Zusammenfassung
 | ||
| - Die Fließbandverarbeitung (engl. pipelining) ermöglicht es, in jedem Takt die Bearbeitung eines Befehls abzuschließen, selbst wenn die Bearbeitung eines Befehls ≥ 1 Takte dauert
 | ||
| - Mehrere Pipelines -> pro Takt können mehrere Befehle beendet
 | ||
| werden
 | ||
| - 3 Typen von Gefährdungen des Fließbandbetriebs:
 | ||
|   - resource hazards
 | ||
|   - control hazards
 | ||
|   - data hazards (RAW, WAR, WAW)
 | ||
| - Gegenmaßnahmen
 | ||
|   - pipeline stall
 | ||
|   - branch prediction
 | ||
|   - forwarding / bypassing
 | ||
|   - delayed branches
 | ||
|   - out-of-order execution
 | ||
|   - dynamic sched
 | ||
| 
 | ||
| ## Sprungvorhersage
 | ||
| Je mehr die Parallelität ausgenützt werden soll, desto mehr sind Kontrollkonflikte der limitierender Faktor!
 | ||
| 
 | ||
| Dynamische Sprungvorhersage
 | ||
| - Zur Laufzeit durch Prozessor-Hardware
 | ||
| - Vorhersage, ob ein bedingter Sprung genommen wird oder nicht
 | ||
| - Abhängig von der Vorhersage: Füllen der Prozessor-Pipeline mit Befehlen ab der vorhergesagten Programm-Stelle
 | ||
| - Reduktion der branch penalty, falls vorhergesagtes Programm-Verhalten mit tatsächlichem übereinstimmt
 | ||
| 
 | ||
| ### Einfache lokale Prädiktoren
 | ||
| - Liefern Vorhersage, ob bedingter Sprung genommen wird oder nicht
 | ||
| - Prädiktion allein anhand der Historie des betrachteten, aktuellen Sprungs
 | ||
| - Historie eines Sprungs wird mit 1, 2 oder n Bits gepuffert
 | ||
| 
 | ||
| - Sprungvorhersage-Puffer
 | ||
|   - Branch prediction buffer oder branch history table
 | ||
|   - Kleiner Speicher, der mit (Teil der) Adresse des Sprungbefehls indiziert wird
 | ||
|     - Verwendet nur wenige untere Bits der Adresse
 | ||
|     - Enthält 1 Bit: Sprung beim letzten Mal ausgeführt (taken) oder nicht (not taken)
 | ||
|   - Prädiktion: Sprung verhält sich wie beim letzten Mal
 | ||
|   - Nachfolgebefehle ab vorhergesagter Adresse holen
 | ||
|   - Falls Prädiktion fehlerhaft: Prädiktionsbit invertieren
 | ||
| - Einfachste Art von Puffer (keine Tags, d.h. keine Überprüfung, ob Adresse tatsächlich im Puffer)
 | ||
|   - Entspricht sehr einfachem Cache
 | ||
|   - Hat eine bestimmte Kapazität
 | ||
|   - Kann nicht für alle Sprünge (aktuelle) Einträge enthalten
 | ||
| - Reduziert branch penalty nur, wenn branch delay länger als Berechnung der Zieladresse mit branch prediction buffer dauert
 | ||
|   - Prädiktion kann fehlerhaft sein
 | ||
|   - Prädiktion kann von anderem Sprungbefehl stammen (mit gleichen Bits im Indexteil der Adressen)
 | ||
| 
 | ||
| - Nachteile des einfachen 1-Bit Vorhersageschemas
 | ||
|   - Höhere Fehlerrate als überhaupt möglich, wenn Häufigkeit der Sprungentscheidungen betrachtet wird
 | ||
|   - D.h. auch wenn Sprung fast immer ausgeführt (taken) wird, entstehen 2 Fehler anstatt 1
 | ||
| 
 | ||
| 2-Bit Branch-Prediction Buffer
 | ||
| - Speicherung der Historie, Befehlsadressen als Zugriffsschlüssel:
 | ||
| 
 | ||
| Allgemein: n-Bit Prädiktor (Spezialfall: 2-Bit)
 | ||
| - Verwendet n-Bit Zähler
 | ||
|   - Sättigungsarithmetik (kein wrap around bei Überlauf)
 | ||
|   - Kann Werte zwischen 0 und 2 n - 1 annehmen
 | ||
|   - Wenn Zähler größer als Hälfte des Maximums (2 n - 1): Vorhersagen, dass Sprung ausgeführt wird; ansonsten vorhersagen, dass Sprung nicht genommen wird
 | ||
|   - Zähler wird bei ausgeführtem Sprung inkrementiert und bei nicht ausgeführtem dekrementiert
 | ||
| - In der Praxis: 2-Bit Prädiktor ähnlich gut wie n-Bit Prädiktor
 | ||
|   - In den meisten Prozessoren heute: 2-Bit Prädiktor für (lokale) Vorhersage
 | ||
| - Einschränkung des n-Bit (bzw. 2-Bit) Prädiktors:
 | ||
|   - Betrachtet nur (vergangenes) Verhalten eines Sprungs, um dessen (zukünftiges) Verhalten vorherzusagen.
 | ||
|   - Arbeitet rein lokal!
 | ||
| - Idee: Verbesserung durch Betrachtung des Verhaltens anderer Sprünge
 | ||
|   - Man erhält so genannten korrelierenden Prädiktor (correlating predictor) oder zweistufigen Prädiktor
 | ||
|   - Prinzip: Aufgrund globaler Information (anderer Sprünge) wird einer von mehreren lokalen Prädiktoren ausgewählt
 | ||
| 
 | ||
| 
 | ||
| ### Korrelierende Prädikatoren
 | ||
| - Beziehen zur Vorhersage des Verhaltens eines Sprungs Kontext-Information mit ein, d.h. die Historie anderer Sprungbefehle
 | ||
| - Prädiktor benutzt globale Kontext-Bits, um einen von mehreren lokalen Prädiktoren auszuwählen
 | ||
| 
 | ||
| - Betrachten wiederholte Ausführung des Codefragments (ignorieren dabei alle anderen Sprünge, inkl. dem für Wiederholung)
 | ||
| - Einschränkung: Statt aller möglicher Sequenzen: d wechselt zwischen 2 und 0
 | ||
| 
 | ||
| Zweistufiger Prädiktor
 | ||
| - Verwendet 1 Bit Kontextinformation
 | ||
| - Es existieren 2 lokale Prädiktoren, beide je 1-Bit
 | ||
|   - Kontext: Letzter (i.a. anderer) Sprung wurde ausgeführt/nicht ausgeführt (1 Bit)
 | ||
|   - Vorhersage des zweistufigen Prädiktors: Anhand des Kontexts wird lokaler Prädiktor für die Vorhersage des aktuell betrachteten Sprungs ausgewählt
 | ||
|   - Letzter Sprung ist i.a. nicht gleich aktuellem, vorherzusagendem Sprung (nur in einfachen Schleifen)
 | ||
| - Notation des Prädiktorstatus: <X>/<Y> mit
 | ||
|   - <X>: Vorhersage, falls letzter Sprung not taken, d.h. Kontext = NT
 | ||
|   - <Y>: Vorhersage, falls letzter Sprung taken, d.h. Kontext = T
 | ||
|   - <X> und <Y> Vorhersagen: jeweils entweder T oder NT
 | ||
| 
 | ||
| (m,n)-Prädiktor
 | ||
| - Betrachtet als Kontext das Verhalten der letzten m Sprünge, um aus $2^m$ vielen lokalen Prädiktoren einen n-Bit Prädiktor auszuwählen
 | ||
| - Vorteil gegenüber (rein lokalem) 2-Bit Prädiktor
 | ||
|   - Höhere Vorhersagegenauigkeit
 | ||
|   - Erfordert kaum Hardwareaufwand
 | ||
|   - Sprunggeschichte (Kontext, „Ausgang“ vorangegangener Sprünge) kann in m-Bit Schieberegister gespeichert werden (1 Bit für jeden der m vielen letzten Sprünge im Kontext, Bit gleich 1 wenn Sprung taken)
 | ||
| - Vorhersagepuffer adressiert via Konkatenation von
 | ||
|   - Unteren Adressbits der Sprungbefehlsadresse
 | ||
|   - m Bit globaler Sprunggeschichte
 | ||
| 
 | ||
| ### High Performance Befehlsdekodierung
 | ||
| In Hochleistungs-Pipelines ist reine Vorhersage eines Sprungs i.d.R. nicht ausreichend
 | ||
| - Insbesondere: Falls mehrere Befehle pro Takt auszugeben sind
 | ||
|   - Befehlsstrom mit großer Bandbreite erforderlich!
 | ||
|   - Kontrollflussabhängigkeiten dürfen nicht „wahrnehmbar“ sein 
 | ||
| - Maßnahmen hierfür
 | ||
|   - Pufferung von Sprungzielen, und nicht nur Vorhersage des Sprungverhaltens (branch target buffer)
 | ||
|   - Integrierte Einheit für das Holen der Befehle (d.h. nicht nur [relativ] einfache erste Stufe der Pipeline)
 | ||
|   - Vorhersage von Rücksprungadressen (bei Prozeduraufruf)
 | ||
| 
 | ||
| ### Branch Target Buffer
 | ||
| 5-stufige Pipeline, Auswertung von Sprungbedingungen in EX:
 | ||
| - Branch delay von 2 Takten
 | ||
| - Mit Sprungvorhersage (branch prediction buffer)
 | ||
|   - Zugriff erfolgt in ID (Adresse des Sprungbefehls schon in IF bekannt; aber:
 | ||
|   - evtl. angesprungenes Ziel erst nach Befehlsdecodierung [ID])
 | ||
|   - Nächste vorhergesagte Instruktion kann erst nach ID geholt werden
 | ||
|   - Branch delay = 1, falls Prädiktion korrekt
 | ||
| - Mit Pufferung des Sprungziels (branch target buffer)
 | ||
|   - Zugriff auf branch target buffer erfolgt in IF. Verhalten wie „echter“ Cache,
 | ||
|   - adressiert mit Sprungbefehlsadresse (überprüft, ob Cache-Hit)
 | ||
|   - Liefert vorhergesagte Adresse als Ergebnis, d.h. nächsten PC (d.h. nicht nur Vorhersage über Sprungverhalten)
 | ||
|   - Keine Verzögerung, falls Prädiktion korrekt!
 | ||
| 
 | ||
| Zusätzliche Speicherung auch des Sprungziels, z.B. Kombination mit branch prediction buffer
 | ||
| 
 | ||
| Bei geschickter Organisation kann das Fließband immer gefüllt bleiben; die Sprünge kosten dann effektiv keine Zeit; CPI <1 möglich.
 | ||
| 
 | ||
| Eigenschaften
 | ||
| - Verzögerung durch Sprung kann vollständig vermieden werden (sofern Vorhersage korrekt), da bereits in IF Entscheidung über nächsten Befehlszähler (PC) getroffen wird.
 | ||
| - Da Entscheidung allein auf Basis des PC getroffen wird, muss überprüft werden, ob Adresse im Puffer (impliziert, dass Sprungbefehl vorliegt)
 | ||
| - Speicherung im Prinzip nur für Sprünge notwendig, die als ausgeführt vorhergesagt werden (not taken = normale sequentielle Dekodierung geht weiter)
 | ||
| - Achtung – bei falscher Vorhersage
 | ||
|   - Entsteht ursprüngliche Sprung-Verzögerung, plus
 | ||
|   - Aufwand zur Aktualisierung des Vorhersagepuffers
 | ||
| 
 | ||
| ### Integrierte Befehls-Hol-Einheit (IF Unit)
 | ||
| Insbesondere mit Blick auf multiple-issue Prozessoren eigene (autonome) funktionale Einheit für Befehlsholphase
 | ||
| - Führt Befehlscodes in Pipeline ein
 | ||
| - Integrierte Funktionalitäten
 | ||
|   - Sprungvorhersage: Wird Teil der Befehlsholphase
 | ||
|   - Instruction Pre-fetch: Insbes. um mehrere Befehle pro Takt liefern (und später ausgeben) zu können, läuft Befehlsholen weiterer Dekodierung voraus (= pre-fetch)
 | ||
|   - Zugriff auf Befehlsspeicher: Bei mehreren Befehlen pro Takt mehrere Zugriffe erforderlich (bei Cache auf ggfs. mehrere cache lines). Werden hier koordiniert/geplant
 | ||
|   - Befehlspuffer: Befehle können hier (lokal im Prozessor!) von Issue-Stufe nach Bedarf abgerufen werden
 | ||
| 
 | ||
| ### Vorhersage von Rücksprungadressen
 | ||
| Allgemeines Ziel: Vorhersage indirekter Sprünge (d.h. bzgl. Basisadresse in Register)
 | ||
| - Hauptverwendung: Rückkehr aus Prozeduraufrufen
 | ||
|   - MIPS: Prozeduraufruf per jal proc, Rückkehr per jr $31
 | ||
|   - Vorhersage mit branch target buffer schlecht, da Aufruf aus unterschiedlichen Codeteilen heraus möglich
 | ||
| - Methode: (Stack-) Speicher für Rücksprungadressen
 | ||
|   - Push bei Prozeduraufruf (call), und
 | ||
|   - Pop bei Rücksprung (return)
 | ||
| - Vorhersagequalität „perfekt“, wenn Stack-Puffer größer als maximale Aufruftiefe
 | ||
| 
 | ||
| 
 | ||
| # Speicherarchitektur
 | ||
| 
 | ||
| 
 | ||
| # Microcontroller und Digitale Signalprozessoren
 | ||
| 
 | ||
| 
 | ||
| # Parallele Architekturen
 | ||
| 
 | ||
| 
 | ||
| # Leistungsbewertung
 |