Gültigkeitsprüfung der zwischengespeicherten Daten
Wenn mehrere Geräte, z.B. die CPU und Peripheriegeräte, einen Speicherbereich gemeinsam nutzen, dessen Inhalte im Cache zwischengespeichert werden, kann es zu Unterschieden (Inkohärenzen) zwischen Cache und Speicher kommen. Angenommen, die CPU greift auf ein Speicherelement zu. Der Inhalt dieses Speicherelements wird daraufhin in den Cache geladen. Nun kann es passieren, dass ein Peripheriegerät, das auf die gleichen Daten zugreift, das Speicherelement direkt verändert unter Umgehung des Cache. Benötigt die CPU abermals die Daten, entsteht durch den Speicherzugriff ein Cache-Hit, da eine (inzwischen veraltete) Version des Speicherelements ja in den Cache geladen wurde. Die CPU liest die alten Daten statt der neuen. Dasselbe Problem tritt auf, wenn die CPU in ein Speicherelement schreibt, das im Cache zwischengespeichert ist, und die Daten von einem Peripheriegerät ausgegeben werden. Die Daten werden nur im Cache und nicht im Speicher aktualisiert, von wo das Peripheriegerät die Daten liest. In diesem Fall sind Cache und Speicher inkohärent.
Zur Veranschaulichung der Kohärenzprotokolle wird angenommen, dass ein Peripheriegerät Daten in einen Eingabepuffer des L2-SRAM schreibt (Bild 5), die CPU dann die Daten liest, verarbeitet und zurück in einen Ausgabepuffer schreibt, von dem die Daten in ein anderes Peripheriegerät geschrieben werden. Die Daten werden durch den DMA-Controller übertragen. Bei einem DMA-Schreibvorgang füllt das Peripheriegerät einen Eingabepuffer mit Daten. Im Einzelnen ist der Ablauf hier wie folgt:
Das Peripheriegerät fordert einen Schreibzugriff auf Zeile 1 (vom L1D im L2-SRAM abgebildete Zeilen) im L2-SRAM an.
Der Controller des L2-Cache überprüft die lokale Kopie des L1D-Tag-RAM dahingehend, ob die Zeile, die gerade für einen Schreibvorgang angefordert wurde, im L1D zwischengespeichert ist. Hierfür werden das Gültigkeitsbit und das Tag überprüft. Wenn die Zeile nicht im L1D zwischengespeichert ist, muss keine weitere Aktion durchgeführt werden und die Daten werden in den Speicher geschrieben.
Ist die Zeile im L1D zwischengespeichert, so sendet der L2-Controller den Befehl SNOOP-INVALIDATE an den L1D. Dadurch wird das Gültigkeitsbit der entsprechenden Zeile auf Null gesetzt, was stets geschieht, wenn der Controller die Zeile auf „Ungültig“ setzt. Die neuen Daten aus dem Peripheriegerät werden in den L2-SRAM geschrieben.
Beim nächsten Zugriff der CPU auf das Speicherelement kommt es zu einem Miss im L1D. Die Zeile mit den vom Peripheriegerät geschriebenen neuen Daten wird in den L1D geschrieben und von der CPU gelesen. Wäre die Zeile nicht auf „ungültig“ gesetzt, hätte die CPU den „alten“ Wert gelesen, der im L1D zwischenspeichert wurde.
Der DMA-Lesevorgang funktioniert umgekehrt. Dabei wird der in Bild 5 grau dargestellte „output buffer“ genutzt. Die Reihenfolge der Abfragen ist wie folgt:
Die CPU schreibt neue Daten in den Ausgabepuffer des L1D. Voraussetzung ist, dass der Ausgabepuffer vorab im L1D zugewiesen wurde. Nur die zwischengespeicherte Kopie der Daten im L1D wird aktualisiert, der „output buffer“ im L2-SRAM wird jedoch nicht aktualisiert.
Wenn das Peripheriegerät eine DMA-Leseanforderung an den Speicherplatz im L2-SRAM sendet, prüft der Controller erneut, ob die Zeile, die das angeforderte Speicherelement enthält, im L1D zwischengespeichert ist.
Ist die Zeile zwischengespeichert, so sendet der L2-Controller den Befehl SNOOP an den L1D. Der SNOOP-Befehl prüft zunächst, ob die entsprechende Zeile verändert wurde. Ist dies nicht der Fall, kann das Peripheriegerät den Lesezugriff auf den L2-SRAM vollständig ausführen.
Wenn das „dirty“-Bit gesetzt ist, veranlasst der SNOOP-Befehl, dass die veränderte Zeile zurück in den L2-SRAM geschrieben wird.
Erst dann wird der Schreibzugriff ausgeführt, bei dem das Peripheriegerät die von der CPU geschriebenen „neuen“ Daten aus dem L2-SRAM liest.