Ich habe den folgenden Text aus Laborarbeit 2 des Computerarchitekturkurses der CMU erhalten. Ich versuche dieses Praktikum eigentlich aus eigenem Interesse selbst zu machen und bin in keiner Weise ein Student der CMU.
Die Maschine hat eine Single-Cycle-Mikroarchitektur: Jeder Befehl benötigt genau einen Zyklus, um ausgeführt zu werden . Abgesehen von der Korrektheit (wie von den Architekturspezifikationen definiert) ist dies die einzige Einschränkung, die wir der Mikroarchitektur der Maschine auferlegen. Solange diese beiden Einschränkungen erfüllt sind (d. h. Korrektheit und Einzelzyklus ), können Sie die Mikroarchitektur beliebig implementieren. Als Orientierungshilfe bieten wir eine abstrakte Beschreibung der Einzelzyklus-Mikroarchitektur, wie wir sie im Unterricht besprochen haben.
- Der Architekturzustand der Maschine (ohne Speicher) wird in Registern gespeichert: dem Programmzähler und Mehrzweckregistern
- Es gibt eine globale Leitung namens \clock", die mit allen Registern verbunden ist.
- Wenn ein Register eine steigende Flanke an der Uhr sieht, erfasst das Register den momentanen "Schnappschuss" der Werte an seinem Eingang. Von da an hält das Register die erfassten Werte und führt sie seinem Ausgang zu.
- Die Ausgabe von dem/den Register(n) wird in eine kombinatorische Schaltung eingespeist, die aus Logikgattern (z. B. ADD) besteht. Der Ausgang der Logikgatter wiederum wird als Eingang zu dem/den Register(n) zurückgeführt.
- Bei der nächsten steigenden Taktflanke erfasst das Register wieder die Werte an seinem Eingang
.
Mein Zweifel: Es fordert mich auf, eine Einzelzyklusarchitektur zu implementieren, aber die von 1 bis 5 nummerierten Punkte scheinen kein Einzelzyklus zu sein.
Nehmen Sie die Anweisung ADD R1, R2, R3 an. Gemäß den Schritten von 1 bis 5 dauert dies zwei Taktzyklen und nicht 1 Taktzyklus.
An der Pos-Flanke eines Taktzyklus werden die Adressregister (Adresse in der Registerdatei) R1 und R2 zwischengespeichert und die Werte in diesen Registern werden zur Addition an die ALU gesendet.
In der nächsten Pos-Flanke wird die Ausgabe von ALU in das Register R3 zurückgeschrieben.
Es dauert also eigentlich zwei Zyklen, oder? EWarum wird es dann als Einzelzyklusanweisung bezeichnet?
Die einzige mir bekannte Möglichkeit, Lese- und Schreibvorgänge im selben Taktzyklus durchzuführen, besteht darin, Registerlesevorgänge bei positiver Flanke und Registerschreibvorgänge bei negativer Flanke (oder umgekehrt) auszulösen und dann Ihre Daten so zu machen Pfadlogik breitet sich vollständig innerhalb einer halben Taktperiode aus. In einer Single-Cycle-Architektur ist es wirklich nur ein semantischer Unterschied, ein bisschen Trickserei.
In ausgefeilteren Taktschemata können Sie tatsächlich mehrere Taktphasen haben, sodass die „Flankentrigger“-Beziehung nicht symmetrisch sein muss, wie ich es beschrieben habe. Wenn Ihr Kern per Pipeline geleitet wird, ist dies tatsächlich aus Gründen der Korrektheit wichtig, damit Sie kein Rennen zwischen Ihren Register-Lese- und Rückschreibphasen haben.
Ich denke, Sie sind zu Recht verwirrt darüber, wie Lese- und Schreibvorgänge in der Registerdatei zusammenhängen, aber das erfordert, dass Sie sich etwas tiefer mit der Implementierung eines Einzelbitregisters auf Transistorebene befassen. Ich denke, Sie werden feststellen, dass es ein Rennen gibt, wenn beide Ereignisse (Lesen und Schreiben) von derselben Taktflanke ausgelöst werden und Ihre kombinatorische Logik eine Änderung propagieren kann, bevor der Registerstatus vollständig verriegelt ist. Schauen Sie sich diese Webseite für eine logische Dekonstruktion eines flankengetriggerten D-Flip-Flops an.
Warnung: Ein-Zyklus- Unterricht kann ein Marketing-Schachzug sein.
Betrachten Sie das Datenblatt für PIC18F4xK22.
An den auffälligsten Stellen sieht man folgendes:
Alle Befehle sind Einzelzyklen, mit Ausnahme von Programmverzweigungen
Hört sich cool an? Aber irgendwo im Dokument vergraben sehen Sie Folgendes:
Ein „Befehlszyklus“ besteht aus vier Q-Zyklen: Q1 bis Q4.
In Wirklichkeit führt Ihr Befehl also 4 Systemtakte aus.
Ich habe das in den Kommentaren gesagt, aber es ist ein bisschen fragmentiert.
Grundsätzlich haben Sie Recht, dass es zwei Taktzyklen dauern würde, um einen ADD-Befehl auszuführen und ihn dann in ein Register zu speichern.
Wenn Sie jedoch die nächste Anweisung ausführen, speichert dies das vorherige Ergebnis im Register. Wenn Sie also zwei ADDs hintereinander ausführen, erhalten Sie das richtige Ergebnis und es dauert nur zwei Zyklen.
Nebenbei bemerkt ist es nur relevant, ein Ergebnis in einem Register zu speichern, wenn Sie eine Anweisung darauf ausführen möchten. Wenn der letzte Befehl in Ihrem Code ein ADD war und Sie danach nicht erneut getaktet haben, enthalten die Register nicht das neueste Ergebnis, aber das spielt keine Rolle, da Sie sie nicht erneut lesen. Sobald Sie eine Anweisung erneut ausgeführt haben, um sie zu lesen, würden sie verriegeln, und dann würde Ihre Anweisung ausgeführt und das richtige Ergebnis geliefert.
Es ist eine Single-Cycle-Architektur! Wenn die Addition r1, r2, r3 in den kombinatorischen Decoder kommt, dekodiert er die Nachricht und teilt der ALU mit, die Addition von r1, r2 durchzuführen, und das Ergebnis ist eine Eingabe in das Register r3. Jetzt kann der Additionswert bei der nächsten steigenden Taktflanke oder bei der fallenden Flanke (bevorzugt) zurückgeschrieben werden. Da das Zurückschreiben den Decoderteil der Mikroarchitektur nicht beeinflusst, wird die nächste Anweisung decodiert und so weiter. Ich hoffe es hilft.
Kein Grund, warum Sie dies nicht in einem einzigen Zyklus implementieren können, zu Beginn des Zyklus geben die Register ihren aktuellen Wert aus, Ihr Befehlsdecoder sieht und addiert, sieht die Eingangsregister und erzeugt kombiniert die Summe dieser Elemente, er sieht auch die Ziel und kombiniert das Ergebnis in den Eingang zu r3 auf der steigenden Flanke, die diesen einzelnen Zyklus beendet, r3 erhält die Summe von r1 und r2. Kein Grund, eine fallende Flanke oder ähnliches zu verwenden.
Wenn sich die Register jetzt in einer Registerdatei befunden hätten, hätten Sie ein viel größeres Problem. Sie können die beiden Eingänge nicht in einer einzigen Uhr lesen, ohne die Definition einer Uhr zu ändern (die Verwendung der fallenden Flanke ist Betrug, der nur die Definition einer Uhr ändert). in zwei Uhren).
Da die Register voneinander getrennt sind und über eigene Ein- und Ausgänge verfügen und der Speicher nicht gezählt wird (manchmal können Sie dies auch noch tun), können Sie problemlos eine Maschine mit einem Zyklus erstellen. Zu Beginn des Zyklus sind die Registerausgänge bereit, kombinatorisch berechnen Sie die Registereingänge vor dem Ende des Zyklus.
Wenn die Register dreistufig mit busA und busB gekoppelt sind, sobald die Opcodes decodiert sind, und diese internen Busse die Operanden an ALU leiten, wobei die ALU-Funktion aus diesem winzigen Teil des Befehlscodes ausgewählt wird und das Zielregister die Der ALU-Ausgang wird an die Eingangspins dieses Registers gelegt, dann der nächste Taktzyklus (alle Taktaktionen erfolgen MCU-weit an derselben Flanke), dann haben Sie eine MCU mit einem einzigen Taktzyklus.
Es liegt an Ihnen, das Tristate-Verhalten zu definieren, um dies zu implementieren.
BeB00
Markus Müller
BeB00
Markus Müller
BeB00
Markus Müller
BeB00
BeB00
Schmied
BeB00
Markus Müller
ADD
, dass R3 im nächsten Zyklus einen neuen Wert hat, findet also im Strom stattBeB00
Schmied
BeB00
BeB00
AP