Lernziele
In dieser Aufgabe …
- verknüpfen die Studierenden die theoretische Funktionsweise von Pipelines mit beispielhaften Schaltungslatenzen.
- werden die Auswirkungen von bedingten Sprüngen auf den Durchsatz demonstriert.
Beim Basteln an Ihrer eigenen RISC-V-Implementierung stellen Sie folgende Latenzen in den einzelnen Stufen des Datenpfades fest.
| IF | ID | EX | MEM | WB |
|---|---|---|---|---|
| 250 ps | 350 ps | 150 ps | 300 ps | 200 ps |
Sie möchten potenzielle Hazards vorerst ignorieren.
Diese Aufgabe stammt aus Kapitel 4, Aufgabe 4.16 von "Computer Organization and Design. The Hardware/Software Interface. RISC-V Edition" (Patterson & Hennessy, 2018).
Level 1: Wissen
Auf welche Frequenz müssen Sie die Clock (CLK) setzen, um sicherzustellen,
dass jede Instruktion korrekt ausgeführt wird, wenn Pipelining deaktiviert bzw.
aktiviert ist?
Die Clock-Frequenz richtet sich immer nach dem Glied mit der höchsten Latenz.
Verwenden wir eine Pipeline, ist dieses die ID-Stufe mit 350 ps.
Daraus ergibt sich eine Taktrate von 1 ÷ 350 ps $\approx$ 2.857.142.857 Hz $\approx$ 2,86 GHz.
Ohne Pipelining hat der gesamte Datenpfad insgesamt 1.250 ps Latenz. Daraus ergibt sich eine Taktrate von 1 ÷ 1.250 ps = 800.000.000 Hz $\approx$ 800 MHz.
Level 1: Wissen
Sie machen eine theoretische Überlegung und nehmen an, Sie könnten nun eine der fünf Stufen in zwei neue aufteilen, jeweils mit der halben Latenz der ursprünglichen Stufe.
Für welche Stufe entscheiden Sie sich, wenn Sie den Durchsatz verbessern möchten? Wie verändert sich das Clock-Intervall mit und ohne Pipelining?
Um den Durchsatz zu verbessern, müsste die Stufe mit der größten individuellen
Latenz aufgeteilt werden, also hier die ID-Stufe:
| IF | ID_0 | ID_1 | EX | MEM | WB |
|---|---|---|---|---|---|
| 250 ps | 175 ps | 175 ps | 150 ps | 300 ps | 200 ps |
Das Glied mit der höchsten Latenz, das dadurch auch die neue Clock-Frequenz
bestimmt, ist nun die MEM-Stufe mit 300 ps (3,33 GHz). Ohne Pipelining bleibt das
Ergebnis unverändert.
Level 3: Anwenden
Sie möchten auf Ihrer Pipeline nun folgenden Code ausführen.
_start:
beq t0, zero, target
addi t4, x0, 1
addi t5, x0, 2
addi t6, x0, 3
target:
add s1, t2, t3
Gehen Sie davon aus, dass t0 auf 0 initialisiert ist.
Nutzen Sie QtRVSim als Referenzarchitektur (fünfstufige Pipeline, keine Hazard-Behandlung, kein Cache).
Was müssen Sie bei der Berechnung des Durchsatzes beachten? Wie viel Zeit benötigt die Ausführung des Codes mit einer theoretischen Ausführungsdauer von 300 ps je Pipeline-Stufe?
Nach dem Ausführen der beq-Instruktion in der Execute-Stufe (EX) springt
der Prozessor zur Adresse des target-Labels (hier mit ↩️ markiert). Dann
müssen alle Instruktionen, die sich zum Zeitpunkt des Sprungs bereits in der
Pipeline befinden, geflusht, also invalidiert werden (hier mit ⚡ markiert).
Das Programm fährt mit der Instruktion fort, zu der gesprungen wurde.
Insgesamt beginnt die Pipeline also mit der Bearbeitung von vier Instruktionen. Dafür benötigt sie insgesamt acht Taktzyklen, also benötigt die Ausführung des Codes 8 · 300 ps = 2.400 ps.
_start:
beq t0, zero, target
addi t4, x0, 1
addi t5, x0, 2
addi t6, x0, 3
target:
add s1, t2, t3| Zyklus/Instruktion | Zeile 2 | Zeile 3 | Zeile 4 | Zeile 7 |
|---|---|---|---|---|
| 1 | IF | |||
| 2 | ID | IF | ||
| 3 | EX ↩️ | ID | IF | |
| 4 | MEM | EX⚡ | ID⚡ | IF |
| 5 | WB | MEM⚡ | EX⚡ | ID |
| 6 | WB⚡ | MEM⚡ | EX | |
| 7 | WB⚡ | MEM | ||
| 8 | WB |
In dieser Aufgabe …