-
Hintergrund
-
Prozessoren umfassen typischerweise einen oder mehrere Zirkularpuffer zum Speichern von Daten. Zum Beispiel können Out-of-order-Prozessoren verbesserte Leistungsfähigkeit bereitstellen, indem Anweisungen in einer Sequenz ausgeführt werden, die von der Reihenfolge in dem Programm verschieden ist, so dass Anweisungen ausgeführt werden, wenn ihre Eingangsdaten verfügbar sind, statt darauf zu warten, dass die vorausgehende Anweisung in dem Programm ausgeführt wird. Solche Out-of-order-Prozessoren besitzen typischerweise einen Umordnungspuffer (ROB), um eine Ausführung der Anweisungen außerhalb der Reihenfolge, aber in Reihenfolge übergeben, zu ermöglichen. ROB werden typischerweise als Zirkularpuffer mit einer festen Größe gebildet.
-
Die nachfolgend beschriebenen Ausführungsformen sind nicht auf Implementierungen beschränkt, die beliebige oder alle der Nachteile bekannter Puffer lösen.
-
Stand der Technik
-
US 2006/0153185 A1 offenbart Systeme und Methoden für die dynamische Veränderung von Ringgrößen in Netzwerk-Prozessen und bezieht sich somit allgemein auf Arrays. Die Nutzung von Zirkularpuffern ist allgemein in „Dipa Rao: Circular Buffering on TMS320C600. Application Report SPRA645A, Texas Instruments Inc., April 2001 (HTTPS:/IWWW.TI.COM/LlT/AN/SPRA645A/SPRA645A.PDF?TS=1687998769026)“ offenbart worden. Der zuvor genannte Bericht behandelt das Konzept von Zirkularpuffern, deren Aufbau und Handhabung sowie ein Beispiel einer konkreten Anwendung.
-
Kurzfassung
-
Die vorliegende Kurzfassung wird angegeben, um eine Auswahl von Konzepten in vereinfachter Form einzuführen, die später in der ausführlichen Beschreibung weiter beschrieben werden. Die vorliegende Kurzfassung soll nicht Schlüsselmerkmale oder wesentliche Merkmale des beanspruchten Gegenstands identifizieren und auch nicht als Hilfe beim Bestimmen des Schutzumfangs des beanspruchten Gegenstands verwendet werden.
-
Es werden Verfahren und Vorrichtungen zur dynamischen Größenänderung (engl. resizing) von Zirkularpuffern beschrieben, wobei Zirkularpuffer dynamisch zugeteilte Arrays aus einem Pool von Arrays sind. Das Verfahren umfasst das Empfangen entweder einer Anforderung, Daten zu einem Zirkularpuffer hinzuzufügen oder Daten aus einem Zirkularpuffer zu entfernen. Falls die Anforderung eine Hinzufügungsanforderung ist und der Zirkularpuffer voll ist, wird ein Array aus dem Pool dem Zirkularpuffer zugeteilt. Falls die Anforderung jedoch eine Entfernungsanforderung ist und die Entfernung der Daten ein leeres Array erzeugt, wird ein Array von dem Zirkularpuffer freigegeben (bzw. eine Zuteilung eines Arrays an den Zirkularpuffer aufgehoben) und an den Pool zurückgegeben. Etwaige Arrays, die nicht einem Zirkularpuffer zugeteilt sind, können deaktiviert werden, um Strom zu sparen.
-
Die hier beschriebenen Verfahren können durch Software in maschinenlesbarer Form auf einem berührbaren Speichermedium ausgeführt werden, z.B. in Form eines Computerprogramms, das Computerprogrammcodemittel umfasst, die ausgelegt sind zum Ausführen aller Schritte beliebiger der hier beschriebenen Verfahren, wenn das Programm auf einem Computer laufen gelassen wird, und wobei das Computerprogramm auf einem computerlesbaren Medium realisiert werden kann. Beispiele für berührbare (oder nichtflüchtige) Speichermedien wären Platten, USB-Sticks, Speicherkarten usw. und umfassen keine sich fortpflanzenden Signale. Die Software kann zur Ausführung auf einem Parallelprozessor oder einem Seriellprozessor geeignet sein, so dass die Verfahrensschritte in einer beliebigen geeigneten Reihenfolge oder gleichzeitig ausgeführt werden können.
-
Hierdurch wird anerkannt, dass Firmware und Software wertvolle, separat handelbare Güter sein können. Es ist beabsichtigt, Software einzuschließen, die auf „dummer“ oder Standardhardware läuft oder diese steuert, um die gewünschten Funktionen auszuführen. Außerdem ist beabsichtigt, Software einzuschließen, die die Konfiguration von Hardware „beschreibt“ oder definiert, wie etwa HDL-Software (Hardwarebeschreibungssprache), so wie sie für den Entwurf von Siliziumchips oder zum Konfigurieren von universellen programmierbaren Chips verwendet wird, um gewünschte Funktionen auszuführen.
-
Die bevorzugten Merkmale können gegebenenfalls kombiniert werden, so wie es für Fachleute ersichtlich ist, und können mit beliebigen der Aspekte der Erfindung kombiniert werden.
-
Kurze Beschreibung der Zeichnungen
-
Ausführungsformen der Erfindung werden beispielsweise mit Bezug auf die folgenden Zeichnungen beschrieben. Es zeigen:
- 1 eine Schemadarstellung eines bekannten Zirkularpuffers;
- 2 eine Schemadarstellung einer beispielhaften Zirkularpufferstruktur;
- 3 eine Schemadarstellung der Zirkularpufferstruktur von 2, nachdem Daten zu dem ersten Zirkularpuffer hinzugefügt wurden;
- 4 eine Schemadarstellung der Zirkularpufferstruktur von 3, nachdem Daten zu dem ersten Zirkularpuffer hinzugefügt wurden;
- 5 eine Schemadarstellung der Zirkularpufferstruktur von 4, nachdem Daten aus dem ersten Zirkularpuffer entfernt wurden;
- 6 eine Schemadarstellung der Zirkularpufferstruktur von 5, nachdem Daten aus dem zweiten Zirkularpuffer entfernt wurden;
- 7 ein Flussdiagramm eines Verfahrens zur dynamischen Größenänderung von Zirkularpuffern unter Verwendung der Zirkularpufferstruktur von 2 bis 6;
- 8 ein Flussdiagramm eines Verfahrens zum dynamischen Zuteilen eines Arrays an einen Zirkularpuffer;
- 9 ein Flussdiagramm eines Verfahrens zum dynamischen Nehmen der Zuteilung eines Arrays von einem Zirkularpuffer;
- 10 eine Schemadarstellung der Zirkularpufferstruktur von 6, nachdem ein leeres Array neu an den zweiten Zirkularpuffer zugeteilt wurde;
- 11 eine Schemadarstellung eines Out-of-order-Prozessors mit einem Umordnungspuffer mit der Zirkularpufferstruktur von 2 bis 6; und
- 12 eine Schemadarstellung eines Multi-Thread-Out-of-order-Prozessors mit mehreren Umordnungspuffern, die sich einen Pool von Arrays teilen.
-
In den Figuren werden durchweg gemeinsame Bezugszahlen benutzt, um ähnliche Merkmale anzugeben.
-
Ausführliche Beschreibung
-
Im Folgenden werden Ausführungsformen der vorliegenden Erfindung lediglich beispielsweise beschrieben. Diese Beispiele repräsentieren die besten Arten des Umsetzens der Erfindung in die Praxis, die dem Anmelder derzeit bekannt sind, obwohl sie nicht die einzigen Weisen sind, auf die dies erzielt werden könnte. Die Beschreibung legt die Funktionen des Beispiels und die Sequenz von Schritten zum Konstruieren und Betreiben des Beispiels dar. Dieselben oder äquivalente Funktionen und Sequenzen können jedoch durch andere Beispiele erreicht werden.
-
Ein Zirkularpuffer (auch als zyklischer Puffer oder Ringpuffer bezeichnet) ist eine Datenstruktur, die zum Speichern von Daten benutzt wird. Zirkularpuffer besitzen typischerweise eine feste Anzahl von Elementen und werden durch einen Kopfzeiger und einen Endezeiger gesteuert. Der Kopfzeiger zeigt auf den Anfang gültiger Daten und der Endezeiger zeigt auf das Ende gültiger Daten. Wenn Daten zu einem Zirkularpuffer hinzugefügt werden, wird der Endezeiger vergrößert, und wenn Daten aus einem Zirkularpuffer entfernt werden, wird der Kopfzeiger vergrößert. Wenn einer der Zeiger das Ende des Puffers erreicht, läuft der Zeiger zum Anfang des Puffers um. Wenn der Kopfzeiger den Endezeiger einholt, ist der Puffer leer. Wenn umgekehrt der Endezeiger den Kopfzeiger einholt, ist der Puffer voll.
-
Es wird nun auf 1a, 1 b und 1c Bezug genommen, die Schemadarstellungen eines herkömmlichen Zirkularpuffers 100 zeigen. Der Zirkularpuffer 100 besteht aus fünf Elementen 102, 104, 106, 108 und 110 und besitzt einen Kopfzeiger 112 und einen Endezeiger 114. 1a zeigt den Zirkularpuffer mit Daten 116, 118 und 120 in drei Elementen 106, 108 und 110. Der Kopfzeiger 112 zeigt auf das dritte Element 106 und der Endezeiger 114 zeigt auf das fünfte Element 110. 1b zeigt den Zirkularpuffer 100, nachdem Daten aus einem Element entfernt wurden. Der Kopf-Zeiger 112 wurde inkrementiert, so dass er nun auf das vierte Element 108 zeigt, um den Umstand widerzuspiegeln, dass das dritte Element 106 keine gültigen Daten mehr enthält. Der Endezeiger 114 zeigt weiter auf das fünfte Element 110. 1c zeigt den Zirkularpuffer 100, nachdem neue Daten hinzugefügt wurden. Der Kopf-Zeiger 112 zeigt weiter auf das vierte Element 108, aber der Endezeiger 114 wurde inkrementiert, um auf das erste Element 102 zu zeigen, um den Umstand widerzuspiegeln, dass Daten 122 zu dem ersten Element 102 hinzugefügt wurden. Wie oben beschrieben, läuft, da sich der Endezeiger 114 am Ende des Puffers 100 befand, als neue Daten hinzugefügt wurden, er zum Anfang des Puffers 100 um.
-
Die feste Länge herkömmlicher Zirkularpuffer, wie etwa des Zirkularpuffers 100, bedeutet, dass sie sich nicht dynamisch an ändernden Anforderungen bezüglich Pufferbetriebsmitteln anpassen können. In Situationen, bei denen der Zirkularpuffer nicht alle der an ihn zugeteilten Betriebsmittel benötigt, kann der Zirkularpuffer folglich Betriebsmittel und Strom verschwenden. In Situationen, bei denen der Zirkularpuffer zusätzliche Betriebsmittel benötigt, muss ferner der den Zirkularpuffer verwendende Prozess möglicherweise anhalten, bis ein Element aus dem Zirkularpuffer entfernt ist.
-
Wie oben beschrieben, umfassen Prozessoren typischerweise einen oder mehrere Zirkularpuffer zum Speichern von Daten. Zum Beispiel besitzen Out-of-order-Prozessoren typischerweise einen Umordnungspuffer (ROB), um eine Ausführung der Anweisungen außerhalb der Reihenfolge, aber innerhalb der Reihenfolge übergeben, zu ermöglichen. Da ROB typischerweise als Zirkularpuffer gebildet werden, treten bei ihnen die mit herkömmlichen Zirkularpuffern verbundenen Betriebsmittel- und Stromprobleme auf. Diese Probleme werden typischerweise in einem Multi-Thread-Out-of-order-Prozessor, der typischerweise einen ROB pro Thread aufweist, vervielfacht.
-
Zu bekannten Lösungen dieses Problems gehören Zirkularpuffer, die eine Verkettungslistenstruktur zum Speichern von Daten verwenden. Speziell umfasst jedes Element einen Zeiger, der auf die Speicherstelle des nächsten Elements im Puffer zeigt.
-
Die folgende Beschreibung beschreibt eine verbesserte Zirkularpufferstruktur, bei der Zirkularpuffer Betriebsmittel aus einem gemeinsam benutzten Pool von Betriebsmitteln dynamisch zugeteilt bekommen. Speziell gibt es bei den hier beschriebenen Zirkularpufferstrukturen einen Pool von Arrays (jedes Array umfasst ein oder mehrere Elemente), die sich ein oder mehrere Zirkularpuffer teilen. Wenn ein Zirkularpuffer zusätzliche Betriebsmittel benötigt, wird ein freies Array aus dem Pool dem Zirkularpuffer zugewiesen, und wenn ein Zirkularpuffer nicht mehr alle ihm zugewiesenen Betriebsmittel benötigt, wird ein Array von dem Zirkularpuffer freigegeben und an den Pool zurückgegeben. Einem Zirkularpuffer ein neues Array zuzuweisen umfasst ein Aktualisieren des Endezeigers, um auf das neue Array zu zeigen. Umgekehrt umfasst das Freigeben eines Arrays von einem Zirkularpuffer ein Aktualisieren des Kopfzeigers, um auf das nächste dem Zirkularpuffer zugewiesene Array zu zeigen. Betriebsmittel (z.B. Arrays) in dem gemeinsam benutzten Pool, die nicht an einen Zirkularpuffer zugeteilt sind, können deaktiviert werden, um Stromersparnisse zu erzeugen.
-
Die hier beschriebenen Zirkularpufferstrukturen erlauben einen leichten Zugriff auf ein beliebiges Element in dem Zirkularpuffer. Dies steht in starkem Kontrast zu dem Verknüpfungslisten-Zirkularpuffer, der ein Durchlaufen der Verknüpfungsliste zum Zugriff auf ein bestimmtes Element erfordert. Diese hier beschriebenen Zirkularpufferstrukturen verringern auch die Menge an Speicherung, die für jeden Zirkularpuffer erforderlich ist, im Gegensatz zu dem Verknüpfungslisten-Zirkularpuffer. Speziell erfordert wie oben beschrieben der Verknüpfungslisten-Zirkularpuffer einen Zeiger pro Element. Im Gegensatz dazu erfordern die hier beschriebenen Zirkularpufferstrukturen maximal drei Zeiger (einen Kopfzeiger, einen Endezeiger und gegebenenfalls einen Zuteilungszeiger). Jeder dieser Zeiger wird nachfolgend ausführlich beschrieben.
-
Es wird nun auf 2 Bezug genommen, worin ein Schemadarstellung einer Zirkularpufferstruktur 200 gemäß einer Ausführungsform gezeigt ist. Die Zirkularpufferstruktur 200 umfasst einen Pool von Arrays 202, die dynamisch durch Puffersteuerlogik 208 an einen oder mehrere Zirkularpuffer 204 und 206 zugeteilt werden. Der hier verwendete Ausdruck „Array“ soll ein mehrelementiges Hardware-Speicherbetriebsmittel fester Größe bedeuten.
-
Bei der in 2 gezeigten Ausführungsform umfasst der Pool von Arrays 202 fünf Arrays 210, 212, 214, 216 und 218. Für Fachleute ist jedoch erkennbar, dass der Pool von Arrays 202 mehr oder weniger Arrays umfassen kann.
-
Jedes Array 210, 212, 214, 216 und 218 umfasst mehrere Elemente 220-258, die zum Speichern von Daten verwendet werden können. Jedes Element repräsentiert einen separaten Speicherplatz und kann als ein Speicherelement bezeichnet werden. Jedes Element kann zum Beispiel in RAM (Direktzugriffsspeicher), Hardwareregistern oder anderen geeigneten Formen von Speicherung implementiert werden. Bei der in 2 gezeigten Ausführungsform weist jedes Array 210, 212, 214, 216 und 218 vier Elemente 220-258 auf.
-
Für Fachleute ist jedoch erkennbar, dass die Arrays 210, 212, 214, 216 und 218 mehr oder weniger Elemente aufweisen können.
-
Bei der beispielhaften Zirkularpufferstruktur 200 von 1 gibt es zwei Zirkularpuffer 204 und 206, die sich den Pool von Arrays 202 teilen. Für Fachleute ist jedoch erkennbar, dass nur ein Zirkularpuffer vorliegen kann, der Zugriff auf den Pool von Arrays 202 hat, oder mehr als zwei Zirkularpuffer vorliegen können, die Zugriff auf den Pool von Arrays 202 haben.
-
Jeder Zirkularpuffer 204 und 206 besitzt einen Kopfzeiger 260 oder 262, der auf das erste Element in dem Zirkularpuffer 204 oder 206 mit gültigen Daten zeigt, und einen Endezeiger 264 oder 266, der auf das letzte Element in dem Zirkularpuffer 204 oder 206 mit gültigen Daten zeigt. Das erste Element mit gültigen Daten wird hier als das Kopfelement bezeichnet, und das letzte Element mit gültigen Daten wird hier als das Endeelement bezeichnet. In bestimmten Fällen besitzt jeder Zeiger 260, 262, 264 und 266 zwei Teile (z.B. einen Teil „a“ und einen Teil „b“). Der erste Teil (260a, 262a, 264a, 266a) identifiziert das Array, in dem das Kopf-/Endeelement sitzt, und der zweite Teil (260b, 262b, 264b, 266b) identifiziert das Element in dem Array, in dem das Kopf-/Endeelement sitzt. Die zwei Teile können zusammen als ein einziger Wert gespeichert und die einzelnen Teile wie erforderlich extrahiert werden.
-
In bestimmten Fällen kann jeder Zirkularpuffer 204 und 206 auch einen Zuteilungszeiger 268 oder 270 aufweisen, der auf das letzte dem Zirkularpuffer 204 oder 206 zugeteilte Array zeigt. Wie in 2 gezeigt, können in bestimmten Fällen der Zuteilungszeiger 268 oder 270 auf dasselbe Array wie der erste Teil des Endezeigers (264a oder 266a) zeigen. Dies muss jedoch nicht immer der Fall sein, insbesondere wenn jeder Zirkularpuffer 204 oder 206 eine Mindestanzahl von Arrays aufweisen muss. Dies ist in 10 dargestellt.
-
Die Puffersteuerlogik 208 steuert den Betrieb der Zirkularpuffer 204 und 206. Speziell steuert die Puffersteuerlogik 208 das Hinzufügen und Entfernen von Daten zu/von den Zirkularpuffern 204 und 206 und teilt dynamisch die Arrays 210, 212, 214, 216 und 218 an die Zirkularpuffer 204 und 206 zu und hebt die Zuteilung dieser von ihnen auf, wenn Betriebsmittel benötigt werden oder nicht mehr benötigt werden. Dies wird nachfolgend ausführlicher beschrieben. Die Puffersteuerlogik 208 kann in Hardware implementiert werden.
-
In bestimmten Fällen kann die Puffersteuerlogik 208 aus einem (nicht gezeigten) Elementhinzufügungs-/-entfernungsmodul und einem (nicht gezeigten) Arrayzuteilungs-/- freigabemodul bestehen. Das Elementzusatz-/-entfernungsmodul wickelt Hinzufügungs- und Entfernungsanforderungen ab, bei denen sich die Zuteilung der Arrays 210, 212, 214, 216 und 218 an die Zirkularpuffer 204 und 206 nicht ändert. Das Arrayzuteilungs-/-freigabemodul wickelt die Zuteilung und Aufhebung der Arrays 210, 212, 214, 216 und 218 an die Zirkularpuffer 204 und 206 ab. Wenn das Elementhinzufügungs-/-entfernungsmodul detektiert, dass eine Änderung der Arrayzuteilung erforderlich ist, arbeitet es in Verbindung mit dem Arrayzuteilungs-/-freigabemodul, um Arrays 210, 212, 214, 216 und 218 aus dem/an den Pool 202 zu erhalten und/oder zurückzugeben.
-
Das Elementhinzufügungs-/entfernungsmodul kann einen Sub-Teil für jeden Zirkularpuffer 204 und 206, die sich den Pool von Arrays 202 teilen, aufweisen. Jeder Sub-Teil führt die Hinzufügungs- und Entfernungsanforderungen für einen einzelnen Zirkularpuffer 204 oder 206 aus. Zum Beispiel kann in 2 die Elementhinzufügungs-/-entfernungsmodullogik zwei Sub-Teile umfassen. Der erste Sub-Teil kann Hinzufügungs- und Entfernungsanforderungen für den ersten Zirkularpuffer 204 verwalten, und der zweite Sub-Teil kann Hinzufügungs- und Entfernungsanforderungen für den zweiten Zirkularpuffer 206 verwalten.
-
Das Trennen der Funktionen der Puffersteuerlogik 208 auf diese Weise verringert die zwischen verschiedenen Zirkularpuffern (z.B. den Zirkularpuffern 204 und 206) erforderliche Synchronisation, wodurch diese beim Arbeiten mit Betriebsmitteln, die sie zugeteilt bekommen haben, unabhängig operieren können.
-
Da es möglich ist, dass zwei Zirkularpuffer (z.B. die Zirkularpuffer 204 und 206) gleichzeitig Änderungen an der Arrayzuteilung erfordern, kann das Arrayzuteilungs-/-freigabemodul ausgelegt sein, mit Situationen umzugehen, bei denen es mehrere Zuteilungs-/- freigabeanforderungen gleichzeitig empfängt. In bestimmten Fällen kann das Arrayzuteilungs-/-freigabemodul ausgelegt sein, auf eine zweite gleichzeitige Zuteilungsanforderung zu reagieren, indem es den zugeordneten Sub-Teil benachrichtigt, dass es keine verfügbaren Arrays im Pool gibt. Dies kann bewirken, dass der Sub-Teil eine vorbestimmte Zeit wartet und es dann nochmals versucht. Ähnlich kann das Arrayzuteilungs-/-freigabemodul ausgelegt sein, auf eine zweite gleichzeitige Entzuteilungsanforderung zu reagieren, indem es den zugeordneten Sub-Teil benachrichtigt, dass das Arrayzuteilungs-/-freigabemodul nicht verfügbar ist. Dies kann bewirken, dass der Sub-Teil eine vorbestimmte Zeit wartet und es dann nochmal versucht. In anderen Fällen kann das Arrayzuteilungs-/-freigabemodul ausgelegt sein, mehrere Zuteilungen/Entzuteilungen parallel zu unterstützen. Die Entscheidung, ob mehrere Zuteilungen/Freigaben zu unterstützen sind, kann dafür erfolgen, einen Kompromiss zwischen der durch Unterstützen mehrerer Zuteilungen/Freigaben realisierten vergrößerten Leistungsfähigkeit und der zur Unterstützung hiervon erforderlichen komplizierteren Logik zu treffen.
-
In 2 wurden dem ersten Zirkularpuffer 204 das erste und zweite Array 210 und 212 zugewiesen, und dem zweiten Zirkularpuffer 206 wurden das vierte und fünfte Array 216 und 218 zugewiesen. Die jedem Zirkularpuffer 204 oder 206 zugewiesenen Arrays sind logisch verknüpft, so dass sie ein einziges kontinuierliches Array bilden. Zum Beispiel ist das letzte Element 226 im ersten Array 210 logisch mit dem ersten Element 228 im zweiten Array 212 verknüpft, um ein kontinuierliches Array zu bilden, und das letzte Element 250 im vierten Array 216 und das erste Element 252 im fünften Array 218 sind logisch verbunden, um ein weiteres kontinuierliches Array zu bilden. Das übrige Array 214 wird als unbenutztes oder freies Array bezeichnet und kann deaktiviert werden, bis es von einem der Zirkularpuffer 204 oder 206 benötigt wird.
-
Der Kopfzeiger 260 des ersten Zirkularpuffers 204 zeigt auf das zweite Element 222 im ersten Array 210, und der Endezeiger 264 zeigt auf das dritte Element 232 im zweiten Array 212. Der Kopfzeiger 262 des zweiten Zirkularpuffers 206 zeigt auf das vierte Element 250 im vierten Array 216 und der Endezeiger 266 zeigt auf das zweite Element 254 im fünften Array 218.
-
Wenn die Puffersteuerlogik 208 eine Anforderung zum Hinzufügen oder Pushen neuer Daten in einen Zirkularpuffer 204 oder 206 empfängt, legt sie die Puffersteuerlogik 208 in das nächste freie Element des bzw. der Arrays, das bzw. die bereits dem Zirkularpuffer 204 oder 206 zugewiesen ist bzw. sind. Der Endezeiger 264 oder 266 wird dann inkrementiert, um das neue Endeelement des Zirkularpuffers widerzuspiegeln. Wenn es keine freien Elemente in dem Array bzw. den Arrays, das bzw. die bereits dem Zirkularpuffer 204 oder 206 zugewiesen ist bzw. sind, gibt, wird eines der freien oder unbenutzten Arrays dem Zirkularpuffer 204 oder 206 zugewiesen, um die Kapazität des Zirkularpuffers 204 oder 206 zu vergrößern. Wenn es keine unbenutzten oder freien Arrays gibt, kann der Prozess, der versucht, die Daten zu dem Zirkularpuffer 204 oder 206 hinzuzufügen, anhalten. Es wird nun auf 3 und 4 Bezug genommen, worin ein Prozess des Hinzufügens oder Pushens von Daten auf einen Zirkularpuffer 204 oder 206 gezeigt ist.
-
Speziell zeigt 3 eine Schemadarstellung der Pufferstruktur 200 von 2, nachdem neue Daten auf den ersten Zirkularpuffer 204 hinzugefügt oder gepusht wurden. In diesem Fall gibt es ein freies Element 234 in den Arrays 210 und 212, die bereits dem Zirkularpuffer 204 zugewiesen sind, so dass die neuen Daten zum nächsten freien Element 234 hinzugefügt werden. Der Endezeiger 264 wird auch inkrementiert, um widerzuspiegeln, dass das vierte Element 234 des zweiten Arrays 212 das neue Endeelement ist.
-
4 zeigt eine Schemadarstellung der Pufferstruktur 200 von 3, nachdem neue Daten zum ersten Zirkularpuffer 204 hinzugefügt wurden. In diesem Fall gibt es für die neuen Daten kein freies Element in den Arrays 210 und 212, die bereits dem Zirkularpuffer 204 zugewiesen sind. Dementsprechend wird ein neues Array 214 dem Zirkularpuffer 204 zugewiesen und die neuen Daten werden zum ersten Element 236 des neuen Arrays 214 hinzugefügt. Der Endezeiger 264 wird auch inkrementiert, um widerzuspiegeln, dass das erste Element 236 im neuen Array 214 nun das Endeelement ist.
-
Wenn die Puffersteuerlogik 208 eine Anforderung zum Entfernen oder Poppen von Daten aus einem Zirkularpuffer 204 oder 206 empfängt, entfernt die Puffersteuerlogik 208 die Daten aus dem Kopfelement und inkrementiert den Kopfzeiger 260 oder 262, um das neue Kopfelement des Puffers 204 oder 206 widerzuspiegeln. Wenn das Kopfelement das letzte Element in einem Array ist, so dass Entfernung der Daten in dem Kopfelement ein leeres Array erzeugt, wird, nachdem die Daten entfernt sind, das leere Array von dem Puffer 204 oder 206 getrennt oder freigegeben und wird ein freies oder unbenutztes Array. Wenn dies der Fall ist, bewegt das Inkrementieren des Kopfzeigers 260 oder 262 den Kopfzeiger 260 oder 262 zum nächsten mit dem Puffer 204 oder 206 assoziierten Array.
-
Es wird nun auf 5 und 6 Bezug genommen, worin der Prozess des Entfernens oder Poppens von Daten aus einem Zirkularpuffer 204 oder 206 dargestellt ist. Speziell zeigt 5 eine Schemadarstellung der Pufferstruktur 200 von 4, nachdem Daten aus dem ersten Zirkularpuffer 204 entfernt oder gepoppt wurden. In 4 ist das Kopfelement 222 des ersten Zirkularpuffers 204 nicht das letzte Element in einem Array, und deshalb erzeugt die Entfernung der Daten im Kopfelement 222 nicht ein leeres Array. Wie in 5 gezeigt, wird dementsprechend nach der Entfernung der Daten im Kopfelement 222 der Kopfzeiger 260 einfach inkrementiert, um auf das nächste Element 224 im Array 210 zu zeigen.
-
6 zeigt eine Schemadarstellung der Pufferstruktur 200 von 5, nachdem Daten aus dem zweiten Zirkularpuffer 206 entfernt oder gepoppt wurden. In 5 ist das Kopfelement 250 des zweiten Zirkularpuffers 206 das letzte Element in einem Array 216, und deshalb erzeugt eine Entfernung der Daten im Kopfelement 250 ein leeres Array 216. Dementsprechend wird wie in 6 gezeigt nach Entfernung der Daten aus dem Kopfelement 250 das leere Array 216 von dem Zirkularpuffer 206 getrennt und wird ein freies oder unbenutztes Array. Der Kopfzeiger 262 des zweiten Zirkularpuffers 206 wird dann inkrementiert, um auf das erste Element 252 im übrigen Array 218 zu zeigen.
-
Wie oben kurz beschrieben, kann der Pool von Arrays 202 von mehreren Zirkularpuffern geteilt werden oder nur einem einzigen Zirkularpuffer zugänglich sein. Wenn der Pool von Arrays 202 von mehreren Zirkularpuffern geteilt wird, kann die für alle Zirkularpuffer erforderliche Gesamtspeicherung verringert werden. Da die Zirkularpuffer nur Arrays aus dem geteilten Pool nehmen, wenn sie benötigt werden, und sie zurückgeben, sobald sie nicht mehr benötigt werden, kann speziell die Gesamtzahl erforderlicher Speicherelemente verringert werden.
-
Ungeachtet der Anzahl der Zirkularpuffer (z.B. einer oder mehr als einer), die sich den Pool von Arrays 202 teilen, kann der Stromverbrauch verringert werden, indem man mindestens einen Teil jeglicher freien oder unbenutzten Arrays ausschaltet oder deaktiviert. Es gibt typischerweise zwei Verfahren zum Deaktivieren von Speicherelementen. Beim ersten wird das Taktsignal für die unbenutzte Speicherung gehalten, so dass alle Flipflops aufhören, sich zu aktualisieren. Sobald die Speicherung aufhört, das Taktsignal zu empfangen, hören die Flipflops auf, sich zu aktualisieren, so dass der einzige Stromverbrauch vom Lecken der Flipflops kommt. Beim zweiten wird die Stromversorgung in die Speicherung ausgeschaltet. Dieses Verfahren ist typischerweise schwieriger zu implementieren als das erste Verfahren, da es mehrere Stromversorgungsdomänen bei der Hardware und Signalklemmung an der Peripherie erfordert. Dieses Verfahren benötigt außerdem mehrere Taktzyklen, damit sich der Zustand der Speicherung stabilisiert, nachdem sie wieder eingeschaltet wird.
-
Bei bestimmten Anwendungen (z.B. Umordnungspuffern und Reservierungsstationen in Out-of-order-Einzel-Thread- oder Multi-Thread-Prozessoren) kann das Teilen eines Pools von Arrays 202 zu vergrößerter Leistungsfähigkeit führen, da ein vielgebrauchter Zirkularpuffer Zugriff auf mehr Betriebsmittel haben kann, wodurch der zugeordnete Prozess fortgesetzt werden kann, ohne durch die Länge des Zirkularpuffers eingeschränkt zu werden. Zum Beispiel wird in einem System mit herkömmlichen Zirkularpuffern fester Länge jedem Zirkularpuffer eine feste Anzahl von Elementen für seine private Verwendung zugeteilt. Da jeder Puffer nur seine eigenen zugeteilten Elemente benutzen darf, ist er selbst dann auf diese Elemente beschränkt, wenn es Zirkularpuffer gibt, die nicht alle ihre zugeteilten Elemente verwenden. In Fällen, bei denen sich mehrere Zirkularpuffer einen Pool von Arrays 202 teilen, hat dagegen jeder Zirkularpuffer Zugriff auf alle Arrays in dem Pool, und somit kann die Größe des Zirkularpuffers dynamisch vergrößert werden, wenn die Arrays von anderen Puffern nicht mehr benötigt werden. Dadurch können Zirkularpuffer je nach Bedarf expandieren, um die Zirkularpufferelemente effizienter zu benutzen.
-
In bestimmten Fällen können alle Arrays 210, 212, 214, 216 und 218 ausgelegt sein, dieselbe Anzahl von Elementen 220-258 aufzuweisen. Zum Beispiel besitzen wie in 2 bis 6 gezeigt alle Arrays 210, 212, 214, 216 und 218 vier Elemente. In diesen Fällen kann die Anzahl der Elemente in jedem Array 210, 212, 214, 216 und 218 so ausgewählt werden, dass Stromersparnisse und Flexibilität ausgeglichen werden. Speziell ergeben größere Arrays mehr Stromersparnisse, wenn sie ausgeschaltet oder deaktiviert werden, verringern aber die Flexibilität. Ein Zirkularpuffer, bei dem das Kopfelement das letzte Element in einem Array ist und das Endeelement das erste Element in einem anderen Array ist, verbraucht zum Beispiel immer noch alle Betriebsmittel in beiden Arrays, obwohl ein kleineres Array für die Bedürfnisse des bestimmten Zirkularpuffers ausreichend wäre.
-
In anderen Fällen können die Arrays 210, 212, 214, 216 und 218 ausgelegt sein, verschieden viele Elemente aufzuweisen. Zum Beispiel können bestimmte der Arrays zwei Elemente aufweisen, während andere Arrays vier Elemente aufweisen können. In diesen Fällen kann die Puffersteuerlogik 208 komplizierter sein als in Fällen, bei denen die Arrays alle dieselbe Größe (z.B. dieselbe Anzahl von Elementen) aufweisen, es kann aber zu einer effizienteren Zuteilung von Pufferbetriebsmitteln führen. In bestimmten Fällen kann als Mittel zur Bestimmung, ob einem Zirkularpuffer ein kleines oder großes Array zuzuteilen ist, verwendet werden, wie schnell das Endeelement das Ende eines Arrays einholt. Falls zum Beispiel das Endeelement eines Zirkularpuffers schnell das Ende eines Arrays einholt, kann dem Zirkularpuffer ein größeres Array zugewiesen werden. Falls umgekehrt das Endeelement eines Zirkularpuffers das Ende eines Arrays langsam einholt, kann dem Zirkularpuffer ein kleineres Array zugewiesen werden. Speziell ist es wahrscheinlicher, dass ein Puffer seine aktuelle Position behält, falls das Endeelement langsam aufholt, als falls das Endeelement schnell aufholt.
-
In bestimmten Fällen kann den Zirkularpuffern 204 und 206 eine beliebige Anzahl von Arrays aus dem Pool 202 zugewiesen werden. In diesen Fällen ist es möglich, dass ein Zirkularpuffer 204 oder 206 keine Arrays im Pool 202 oder alle Arrays im Pool 202 zugewiesen bekommt.
-
In anderen Fällen kann es eine Grenze für die Mindest- und/oder Maximalzahl von Arrays geben, die einem beliebigen Zirkularpuffer 204 oder 206 zugewiesen werden kann. Zum Beispiel kann in bestimmten Fällen die Puffersteuerlogik 208 ausgelegt sein, jedem Zirkularpuffer 204 oder 206 wenigstens ein Array zuzuweisen, gleichgültig, ob der Zirkularpuffer 204 oder 206 ein Array benötigt. In anderen Fällen kann die Puffersteuerlogik 208 ausgelegt sein, sicherzustellen, dass keinem Zirkularpuffer mehr als eine Anzahl oder ein Prozentsatz (z.B. 90%) der Arrays im Pool 202 zugewiesen wird. In weiteren Fällen kann die Puffersteuerlogik 208 ausgelegt sein, sowohl eine Mindest- als auch eine Maximalschwelle bezüglich der Anzahl einem beliebigen Zirkularpuffer 204 oder 206 zugewiesener Arrays zu implementieren.
-
Wenn der Anzahl von den Zirkularpuffern 204 oder 206 zugewiesenen Arrays Maximal- oder Mindestschwellen auferlegt werden, können die Schwellen für alle Zirkularpuffer 204 oder 206 gleich sein oder die Schwellen können für bestimmte oder alle der Zirkularpuffer 204 und 206 verschieden sein.
-
Jegliche Mindest- und/oder Maximalschwellen können vorbestimmt oder dynamisch berechnet werden. In bestimmten Fällen können die Mindest- und/oder Maximalschwellen dynamisch abhängig davon ausgewählt werden, ob Stromersparnisse oder Geschwindigkeit zur Zeit von größter Bedeutung sind. Zum Beispiel kann die Puffersteuerlogik 208 ausgelegt sein, die Maximalschwelle zu verkleinern, wenn die Puffersteuerlogik 208 detektiert, dass eine Situation aufgetreten ist, bei der Stromsparen wichtiger ist als Jobs schnell auszuführen. Umgekehrt kann die Puffersteuerlogik 208 ausgelegt sein, die Maximalschwelle zu vergrößern, wenn die Puffersteuerlogik 208 detektiert, dass Geschwindigkeit wichtiger als Stromverbrauch ist. Falls zum Beispiel ein Einzel-Thread-Prozessor von Wechselstromversorgung zu Batteriestromversorgung wechselt, kann die Puffersteuerlogik 208 ausgelegt sein, die Maximalschwelle automatisch zu verringern, um den Stromverbrauch zu verringern und somit die Lebensdauer der Batterie zu verlängern.
-
In anderen Fällen können die Mindest- und/oder Maximalschwellen dynamisch ausgewählt werden, um Lastausgleich zu implementieren. Das
GB-Patent 2,372,847 beschreibt einen Prozess, wodurch ein auf einem Thread eines In-order-Multi-Thread-Prozessors ausgeführtes Programm seine Benutzung von Prozessorbetriebsmitteln dergestalt steuert, dass die Verarbeitungsanforderungen sowohl dieses Programms als auch etwaiger auf anderen Threads ausgeführter Programme erfüllt werden. Speziell entscheidet in dem
GB-Patent 2,372,847 die Ausgabestufe, welcher der Threads in einem bestimmten Zyklus ausgeführt werden soll, abhängig davon, wie gut die Threads ihre Leistungsfähigkeitsanforderungen erfüllen und/oder wie schnell ein bestimmter Thread zur Zeit ausgeführt wird. Das
GB-Patent 2,372,847 stellt auch eine Auflösung für Anweisungen mit in Konflikt stehenden Betriebsmittelanforderungen bereit, indem eine Prioritätsreihenfolge der Threads bereitgestellt wird, so dass die Anweisungen aus dem wichtigsten Thread bzw. den wichtigsten Threads zur Zeit ausgeführt werden.
-
Die in dem
GB-Patent 2,372,847 beschriebenen Verfahren können in einem Out-of-order-Multi-Thread-Prozessor verwendet werden, um zwischen Anweisungen aus verschiedenen Threads in der Reservierungsstation zu entscheiden, die am Kopf jeder Out-of-order-Pipeline existieren (siehe
12 für ein Beispiel für einen Out-of-order-Multi-Thread-Prozessor). Der Hauptunterschied ist, dass, statt dass die Ausgabestufe die nächste Anweisung auf jedem Thread entscheidet, die Reservierungsstation die nächste Anweisung eines bestimmten Typs auf jedem Thread entscheidet. Zum Beispiel kann eine bestimmte Reservierungsstation nur die Multiplikationsanweisungen empfangen. In diesem Fall entscheidet die Reservierungsstation das nächste Multiplizieren auf jedem Thread.
-
Ein ähnliches Verfahren kann verwendet werden, um indirekt die Ausführungsrate eines bestimmten Threads durch Steuern der Größe des Umordnungspuffers zu steuern. Wenn der Umordnungspuffer groß ist, können mehr Anweisungen auf einmal für einen bestimmten Thread „im Gange“ sein, wodurch die Leistungsfähigkeit dieses Threads gesteigert werden kann. Diese Leistungsfähigkeitssteigerung entsteht aus einer verringerten Anzahl von leerlaufenden Out-of-order-Pipelines pro Zyklus, sowie aus einer Zunahme des Anteils aller anstehenden Anweisungen, die zu diesem Thread gehören (mehr anstehende Anweisungen für einen bestimmten Thread führen zu einer höheren Wahrscheinlichkeit, dass eine aus diesem Thread ausgewählt wird). Wenn der Umordnungspuffer klein ist, sind weniger Anweisungen für diesen Thread „im Gange“, was aus den entgegengesetzten Gründen zu einer Verringerung der Leistungsfähigkeit führen kann. Dementsprechend können die Mindest- und Maximalschwellen für die Umordnungspuffer gemäß der gewünschten Ausführungsrate gesteuert werden. Zum Beispiel kann die Maximalschwelle mit einer höheren gewünschten Ausführungsrate zunehmen und mit einer niedrigeren gewünschten Ausführungsrate abnehmen. Die Mindestschwelle kann zum Beispiel mit einer höheren gewünschten Ausführungsrate zunehmen und mit einer niedrigeren gewünschten Ausführungsrate abnehmen; mit der gewünschten Ausführungsrate anderer Threads zunehmen und mit niedrigeren gewünschten Ausführungsraten abnehmen; mit einer höheren relativen Priorität des Threads zunehmen und mit einer niedrigeren relativen Priorität abnehmen; mit der Knappheit freier Arrays im Pool zunehmen; oder eine beliebige Kombination davon.
-
Es wird nun auf 7 Bezug genommen, worin ein Flussdiagramm eines beispielhaften Verfahrens 700 zur dynamischen Größenänderung von Zirkularpuffern unter Verwendung der Zirkularpufferstruktur 200 von 2 bis 6 gezeigt ist. Im Schritt 702 empfängt die Puffersteuerlogik 108 eine Anforderung, Daten zu einem bestimmten Zirkularpuffer 204 oder 206 hinzuzufügen/aus diesem zu entfernen. Im Schritt 704 bestimmt die Puffersteuerlogik 208, ob die Anforderung eine Hinzufügungsanforderung oder eine Entfernungsanforderung ist. Falls die Puffersteuerlogik 208 bestimmt, dass die Anforderung eine Hinzufügungsanforderung ist, schreitet das Verfahren 700 zum Schritt 706 voran. Andernfalls ist die Anforderung eine Entfernungsanforderung und das Verfahren 700 schreitet zum Schritt 708 voran.
-
Im Schritt 706 teilt die Puffersteuerlogik 208 dynamisch dem bestimmten Zirkularpuffer 204 oder 206 ein Array zu, falls es erforderlich ist, in der Lage zu sein, Daten dem Zirkularpuffer hinzuzufügen. Zum Beispiel kann die Puffersteuerlogik dem bestimmten Zirkularpuffer 204 oder 206 ein freies Array zuteilen, falls die gerade dem bestimmten Zirkularpuffer 204 oder 206 zugeteilten Arrays keine freien Elemente aufweisen. Ein beispielhaftes Verfahren zum Implementieren von Schritt 706 des Verfahrens 700 wird mit Bezug auf 8 beschrieben. Im Schritt 708 hebt die Puffersteuerlogik 208 dynamisch die Zuteilung eines Arrays von dem bestimmten Zirkularpuffer 204 oder 206 auf, falls eine Entfernung von Daten aus dem bestimmten Zirkularpuffer 204 oder 206 ein leeres Array erzeugt. Zum Beispiel kann die Puffersteuerlogik 208 die Zuteilung eines Arrays von dem bestimmten Zirkularpuffer 204 oder 206 aufheben, falls eine Entfernung der Daten eines der dem bestimmten Zirkularpuffer 204 oder 206 zugeteilten Arrays leer lässt. Ein Array wird als leer betrachtet, falls es keine gültigen Daten für den Zirkularpuffer enthält. Ein beispielhaftes Verfahren zum Implementieren von Schritt 708 des Verfahrens 700 wird mit Bezug auf 9 beschrieben.
-
Es wird nun auf 8 Bezug genommen, worin ein Flussdiagramm eines beispielhaften Verfahrens 800 zum dynamischen Zuteilen eines Arrays an einen Zirkularpuffer gezeigt ist. Im Schritt 802 empfängt die Puffersteuerlogik 208 eine Anforderung von einem Prozess, Daten einem bestimmten Zirkularpuffer 204 oder 206 hinzuzufügen. Im Schritt 804 bestimmt die Puffersteuerlogik 208, ob der identifizierte Zirkularpuffer 204 oder 206 voll ist (z. B. ob er am Ende des Zirkularpuffers 204 oder 206 ein freies Element aufweist). Das Bestimmen, ob der identifizierte Zirkularpuffer voll ist, kann zum Beispiel umfassen, zuerst zu ermitteln, ob das Endeelement (das durch den zweiten Teil des Endezeigers 264b oder 266b identifizierte Element) das letzte Element in dem Array (dem durch den ersten Teil des Endezeigers 264a oder 266a identifizierten Array) ist. Falls das Endeelement nicht das letzte Element in dem Array ist, kann bestimmt werden, dass der identifizierte Zirkularpuffer 204 oder 206 nicht voll ist (z. B. ein freies Element aufweist).
-
Falls das Endeelement das letzte Element im Array ist, kann die Puffersteuerlogik 208 ermitteln, ob der erste Teil des Endezeigers 264a oder 266b und des Zuteilungszeigers 268 oder 270 auf dasselbe Array zeigen. Falls der erste Teil des Endezeigers 264a oder 266a und der Zuteilungszeiger 268 oder 270 auf dasselbe Array zeigen, kann bestimmt werden, dass der identifizierte Zirkularpuffer 204 oder 206 voll ist (z.B. kein freies Element aufweist). Falls der erste Teil des Endezeigers 264a oder 266a und der Zuteilungszeiger 268 oder 270 jedoch nicht auf dasselbe Array zeigen, kann bestimmt werden, dass der identifizierte Zirkularpuffer 204 oder 206 nicht voll ist (z.B. ein freies Element aufweist). Falls speziell der erste Teil des Endezeigers 264a oder 266a und der Zuteilungszeiger 268 oder 270 nicht auf dasselbe Array zeigen, wurde bereits ein freies Array zum Ende des Zirkularpuffers 204 oder 206 hinzugefügt und Daten können ohne Hinzufügen eines neuen Arrays zum Zirkularpuffer 204 oder 206 hinzugefügt werden.
-
Falls die Puffersteuerlogik 208 bestimmt, dass der identifizierte Zirkularpuffer 204 oder 206 nicht voll ist (z.B. es ein freies Element in dem Zirkularpuffer 204 oder 206 gibt), schreitet das Verfahren 800 zu Schritt 806 voran. Falls die Puffersteuerlogik 208 jedoch bestimmt, dass der Puffer voll ist (z.B. es kein freies Element am Ende des Zirkularpuffers 204 oder 206 gibt), schreitet das Verfahren 800 zu Schritt 808 voran.
-
Im Schritt 806 fügt die Puffersteuerlogik 208 die neuen Daten zum nächsten freien Element im Zirkularpuffer 204 oder 206 hinzu. Hinzufügen der neuen Daten zum nächsten freien Element im Zirkularpuffer 204 oder 206 kann ein Inkrementieren des Endezeigers (z.B. des Endezeigers 264 oder 266) umfassen, um auf das nächste freie Element im Zirkularpuffer zu zeigen, und dann die neuen Daten zu dem neuen Endeelement hinzuzufügen. Falls zum Beispiel der Endezeiger 264 oder 266 anfänglich auf das erste Element in einem Array zeigt, umfasst das Inkrementieren des Endezeigers 264 oder 266 ein Justieren des zweiten Teils des Endezeigers 264b oder 266b, um auf das zweite Element im Array zu zeigen. In einem anderen Beispiel umfasst, falls der Endezeiger 264 oder 266 anfänglich auf das letzte Element in einem Array zeigt, das Inkrementieren des Endezeigers 264 ein Justieren des ersten Teils des Endezeigers 264a oder 266a, um auf das nächste zugeteilte Array zu zeigen, und ein Justieren des zweiten Teils des Endezeigers 264b oder 266b, um auf das erste Element im Array zu zeigen. Nachdem der Endezeiger 264 oder 266 inkrementiert wurde, werden die neuen Daten zum neuen Endeelement hinzugefügt. Nachdem die neuen Daten zum Zirkularpuffer 204 oder 206 hinzugefügt wurden, endet das Verfahren 800.
-
Im Schritt 808 bestimmt die Puffersteuerlogik 208, ob es irgendwelche freien oder unbenutzten Arrays im Pool von Arrays 202 gibt, die dem identifizierten Zirkularpuffer 204 oder 206 zugewiesen oder zugeteilt werden können. Wenn es keine freien oder unbenutzten Arrays gibt, schreitet das Verfahren 800 zu Schritt 810 voran. Falls es jedoch wenigstens ein freies oder unbenutztes Array gibt, schreitet das Verfahren 800 zu Schritt 812 voran.
-
Im Schritt 810 benachrichtigt die Puffersteuerlogik 208 den Prozess, der versucht, Daten dem Zirkularpuffer hinzuzufügen, dass der Zirkularpuffer 204 oder 206 voll ist. Dies kann bewirken, dass der Prozess anhält, bis ein Array frei wird.
-
In bestimmten Fällen prüft die Puffersteuerlogik 208, statt den Prozess, der versucht, Daten zu dem Zirkularpuffer 204 oder 206 hinzuzufügen, zu benachrichtigen, dass der Zirkularpuffer 204 oder 206 voll ist, ob es irgendwelche anderen freien Elemente in den dem Zirkularpuffer zugeteilten Arrays gibt. Zum Beispiel können einem Zirkularpuffer zwei Arrays zugewiesen sein. Der Kopfzeiger 260 oder 262 zeigt auf das letzte Element in einem Array und der Endezeiger 264 oder 266 zeigt auf das letzte Element im anderen Array. Falls in diesem Beispiel eine Anforderung, Daten zu dem Zirkularpuffer 204 oder 206 hinzuzufügen, empfangen wird, wird gemäß Schritt 804 bestimmt, dass es keine freien Elemente im Array gibt, da es keine freien Elemente am Ende des Arrays (z.B. im zweiten/Endarray) gibt. In diesem Fall kann der Prozess anhalten, bis ein Array verfügbar wird, obwohl es freie Elemente im ersten Array gibt. Um dieses Problem zu behandeln, kann in bestimmten Fällen die Puffersteuerlogik 208, bevor zum Schritt 810 vorangeschritten wird, prüfen, ob es irgendwelche freien Elemente am Anfang des Zirkularpuffers 204 oder 206 gibt. Wenn es freie Elemente am Anfang des Zirkularpuffers 204 oder 206 gibt, fügt die Puffersteuerlogik 208 die neuen Daten zum nächsten freien Element hinzu und aktualisiert den Endezeiger 264 oder 266, um die neuen Daten widerzuspiegeln. Dadurch können die Zirkularpuffer 204 oder 206 effektiv auf ähnliche Weise wie die in Bezug auf 1 beschriebenen herkömmlichen Zirkularpuffer umlaufen. Falls es keine freien Elemente am Anfang des Zirkularpuffers gibt, schreitet das Verfahren zu Schritt 810 voran.
-
Es sollte beachtet werden, dass, wenn neue Daten zum Zirkularpuffer 204 oder 206 auf diese Weise hinzugefügt werden, eine Chance besteht (die mit einer schnellen Hinzufügungsrate oder einer langsamen Entfernungsrate zunimmt), dass der Endezeiger 264 oder 266 den Kopfzeiger 260 oder 262 einholt, was bewirkt, dass der Prozess anhält. Falls dies auftritt, ist es gleichgültig, wie viele Arrays in der Zwischenzeit verfügbar werden, der Prozess hält weiter an, bis der Kopfzeiger 260 oder 262 vorrückt. Selbst falls der Kopfzeiger 260 oder 262 nicht vorrückt, besteht weiterhin ein hohes Risiko, dass das Anhalten nochmal auftritt (weil der Kopf- und Endezeiger näher beieinander sind), bis der Kopfzeiger in das nächste Array vorrückt. Es den Zirkularpuffern 204 oder 206 zu erlauben, umzulaufen, wenn keine Arrays im Pool 202 verfügbar sind, erlaubt es einem Prozess dementsprechend, kurzfristig fortgesetzt zu werden, kann aber langfristig größere Probleme verursachen.
-
Im Schritt 812 weist oder teilt die Puffersteuerlogik 208 dem identifizierten Zirkularpuffer 204 oder 206 eines der freien oder unbenutzten Arrays zu. Wenn alle Arrays dieselbe Größe aufweisen, wählt die Puffersteuerlogik 208 einfach eines der freien oder unbenutzten Arrays und weist es dem identifizierten Zirkularpuffer 204 oder 206 zu. Wenn die Arrays jedoch verschiedene Größen aufweisen, kann die Puffersteuerlogik 208 zuerst bestimmen, welches der Arrays für den identifizierten Zirkularpuffer 204 oder 206 am besten geeignet ist, und kann dann das am besten geeignete Array dem identifizierten Zirkularpuffer zuweisen oder zuteilen. Wie oben beschrieben, kann in bestimmten Fällen die Puffersteuerlogik 208 überwachen, wie schnell das Endeelement das Ende eines Arrays einholt, und mit diesen Informationen bestimmen, ob dem identifizierten Zirkularpuffer ein kleines oder großes Array zugeteilt werden soll.
-
Nachdem die Puffersteuerlogik 208 ein freies oder unbenutztes Array ausgewählt hat, wird das Array dem identifizierten Zirkularpuffer 204 oder 206 zugewiesen oder zu diesem hinzugefügt, indem der Endezeiger 264 oder 266 aktualisiert wird, um auf das erste Element im neuen Array zu zeigen. Zum Beispiel kann der erste Teil des Endezeigers 264a oder 266a aktualisiert werden, um auf das dem Zirkularpuffer 204 oder 206 zugewiesene neue Array zu zeigen, und der zweite Teil des Endezeigers 264b oder 266b kann aktualisiert werden, um auf das erste Element im Array zu zeigen. Nachdem ein freies oder unbenutztes Array dem identifizierten Zirkularpuffer zugewiesen wurde, schreitet das Verfahren 800 zu Schritt 814 voran.
-
Im Schritt 814 werden die neuen Daten zu dem neuen Endeelement (dem ersten Element im neuen Array) hinzugefügt. Nachdem die neuen Daten zum identifizierten Zirkularpuffer 204 oder 206 hinzugefügt wurden, endet das Verfahren 800.
-
Wenn die Puffersteuerlogik 208 ausgelegt ist, Maximal- und/oder Mindestschwellen bezüglich der Anzahl von Arrays, die einem Zirkularpuffer 204 oder 206 zugewiesen werden können, aufzuerlegen, kann die Puffersteuerlogik 208 ermitteln, ob der identifizierte Zirkularpuffer 204 oder 206 seine Grenze erreicht hat, bevor das Array dem Zirkularpuffer 204 oder 206 zugewiesen oder zu diesem hinzugefügt wird. Falls der identifizierte Zirkularpuffer 204 oder 206 nicht seine Maximalschwelle erreicht hat, schreitet das Verfahren zu Schritt 812 voran. Falls der identifizierte Zirkularpuffer 204 oder 206 jedoch seine Maximalschwelle erreicht oder überschritten hat, schreitet das Verfahren zu Schritt 810 voran.
-
Es wird nun auf 9 Bezug genommen, worin ein Flussdiagramm eines beispielhaften Verfahrens 900 zum dynamischen Freigeben eines Arrays von einem Zirkularpuffer 204 oder 206 gezeigt ist. Im Schritt 902 empfängt die Puffersteuerlogik 208 eine Anforderung von einem Prozess, Daten aus einem bestimmten Zirkularpuffer 204 oder 206 zu entfernen. Im Schritt 904 ruft die Puffersteuerlogik 208 die Daten aus dem Kopfelement (dem durch den Kopfzeiger 260 oder 262 identifizierten Element) ab und führt sie dem Prozess zu, der die Daten anfordert. Nachdem die Daten dem anfordernden Prozess zugeführt wurden, schreitet das Verfahren 900 zu Schritt 906 voran.
-
Im Schritt 906 inkrementiert die Puffersteuerlogik 208 den Kopfzeiger 260 oder 262, um auf das nächste Element im Zirkularpuffer zu zeigen, um den Umstand widerzuspiegeln, dass Daten aus dem Zirkularpuffer entfernt wurden. Falls zum Beispiel der Kopfzeiger 260 oder 262 anfänglich auf das erste Element eines Arrays zeigte, umfasst das Inkrementieren des Kopfzeigers 260 oder 262 ein Justieren des zweiten Teils des Kopfzeigers 260b oder 262b, um auf das zweite Element im Array zu zeigen. In einem anderen Beispiel umfasst, falls der Kopfzeiger 260 oder 262 anfänglich auf das letzte Element in einem Array zeigte, das Inkrementieren des Kopfzeigers 260 oder 262 ein Justieren des ersten Teils des Kopfzeigers 260a oder 262a, um auf das nächste dem Zirkularpuffer 204 oder 206 zugeteilte Array zu zeigen, und ein Justieren des zweiten Teils des Kopfzeigers 260b oder 262b, um auf das erste Element im Array zu zeigen. Nachdem der Kopfzeiger inkrementiert wurde, schreitet das Verfahren 900 zu Schritt 908 voran.
-
Im Schritt 908 bestimmt die Puffersteuerlogik 208, ob eine Entfernung der Daten im Kopfelement ein leeres Array erzeugt hat. Das Bestimmen, ob die Entfernung ein leeres Array erzeugt hat, kann umfassen, zu ermitteln, ob das Kopfelement das erste Element in einem Array ist (z.B. es das letzte Element in einem Array war, bevor die Daten entfernt wurden).
-
Wenn das Kopfelement das erste Element in einem Array ist, kann bestimmt werden, dass die Entfernung von Daten ein leeres Array erzeugt hat. In bestimmten Fällen kann, falls das Kopfelement nicht das erste Element in einem Array ist, bestimmt werden, dass die Entfernung von Daten nicht ein leeres Array erzeugt hat.
-
In anderen Fällen kann, falls das Kopfelement nicht das erste Element im Array ist, die Puffersteuerlogik 208 auch ermitteln, ob der Kopfzeiger gleich dem Endezeiger ist. In diesen Fällen kann, falls der Kopfzeiger gleich dem Endezeiger ist, bestimmt werden, dass nun ein leeres Array vorliegt. Falls jedoch der Kopfzeiger nicht gleich dem Endezeiger ist, kann bestimmt werden, dass kein leeres Array vorliegt.
-
Falls die Puffersteuerlogik 208 bestimmt, dass die Entfernung der Daten nicht ein leeres Array erzeugt hat, endet das Verfahren 900. Falls die Puffersteuerlogik 208 jedoch bestimmt, dass die Entfernung von Daten ein leeres Array erzeugt hat, schreitet das Verfahren 900 zu Schritt 910 voran.
-
Im Schritt 910 hebt die Puffersteuerlogik 208 die Zuteilung oder Zuweisung des leeren Arrays von dem identifizierten Zirkularpuffer 204 oder 206 auf. Nachdem das Array freigegeben wurde, wird es ein freies oder unbenutztes Array, das einem beliebigen Zirkularpuffer 204 oder 206 zugewiesen werden kann. Das Verfahren 900 schreitet dann zu Schritt 912 voran.
-
Im Schritt 912 deaktiviert die Puffersteuerlogik 208 das leere Array, um Strom zu sparen. Nachdem das Array deaktiviert wurde, endet das Verfahren 900.
-
Wenn die Puffersteuerlogik 208 ausgelegt ist, der Anzahl von Arrays, die einem Zirkularpuffer 204 oder 206 zugewiesen sind, eine Mindestschwelle aufzuerlegen, kann die Puffersteuerlogik 208 ermitteln, ob der identifizierte Zirkularpuffer 204 oder 206 seine Mindestschwelle erreicht hat, bevor die Zuweisung des Arrays im Schritt 910 vom Zirkularpuffer 204 oder 206 aufgehoben wird. Falls der identifizierte Zirkularpuffer 204 oder 206 nicht seine Mindestschwelle erreicht hat, schreitet das Verfahren zu Schritt 910 voran. Falls jedoch der identifizierte Zirkularpuffer 204 oder 206 seine Mindestschwelle erreicht hat, kann die Puffersteuerlogik 208 bestimmen, ob die Mindestschwelle 1 oder größer als 1 ist. Falls die Mindestschwelle 1 ist, kann das Verfahren 900 nach Schritt 908 enden. Speziell wird das übrige dem Zirkularpuffer 204 oder 206 zugewiesene Array weder vom Zirkularpuffer freigegeben noch deaktiviert. In bestimmten Fällen kann, bevor das Verfahren endet, die Puffersteuerlogik 208 den Kopf- und Endezeiger 260 oder 262 und 264 oder 266 justieren, um auf den Anfang des Arrays zu zeigen, um die Benutzung des Arrays in der Zukunft zu optimieren. Zum Beispiel können sowohl der Kopf- als auch der Endezeiger 260 oder 262 und 264 oder 266 auf das erste Element in dem dem Zirkularpuffer 204 oder 206 zugeteilten Array gesetzt werden.
-
Falls jedoch die Mindestschwelle größer als 1 ist, kann die Puffersteuerlogik 208 ausgelegt sein, das leere Array wie im Schritt 910 beschrieben vom identifizierten Zirkularpuffer aufzuheben und es dann neu dem Ende des identifizierten Zirkularpuffers 204 oder 206 zuzuweisen.
-
5, 6 und 10 werden verwendet, um Aufhebung der Zuweisung und Neuzuweisung eines Arrays an einen Zirkularpuffer zu demonstrieren. In 5 werden dem zweiten Zirkularpuffer 206 zwei Arrays 216 und 218 zugewiesen. Der Kopfzeiger 262 zeigt auf das letzte Element 250 des vierten Arrays 216 und der Endezeiger 266 zeigt auf das zweite Element 254 des fünften Arrays 218. Wenn ein Element aus dem Zirkularpuffer 206 entfernt wird, wird der Kopfzeiger 262 inkrementiert, um auf das erste Element 252 des fünften Arrays 218 zu zeigen (dies ist in 6 gezeigt). Das Array 216 ist nun ein leeres Array. Wenn die Mindestanzahl von einem Zirkularpuffer 204 oder 206 zugewiesenen Arrays 2 ist, wird, statt das leere Array 216 wie im Schritt 912 beschrieben zu deaktivieren, das leere Array 216 neu dem Ende des Zirkularpuffers 206 zugewiesen. Speziell wird der Zuteilungszeiger 270 aktualisiert, so dass er auf das leere Array 216 zeigt, und es wird eine logische Verknüpfung zwischen dem letzten Element 258 des fünften Arrays 218 und dem ersten Element 244 des vierten Arrays 216 erzeugt (dies ist in 10 gezeigt).
-
Es wird nun auf 11 Bezug genommen, worin ein Schemadarstellung eines Out-of-order-Prozessors 1100 gezeigt ist, der einen Umordnungspuffer mit der Zirkularpufferstruktur von 2 bis 6 aufweist. Der Out-of-order-Prozessor 1100 umfasst eine Abrufstufe 1102, die ausgelegt ist, Anweisungen aus einem Programm (in Programmreihenfolge) wie durch den Programmzähler (PC) angegeben abzurufen, und eine Decodierungs- und Umbenennungsstufe 1104, die ausgelegt ist, die Anweisungen zu interpretieren und Registerumbenennung durchzuführen. Durch Registerumbenennung können mehr Anweisungen außerhalb der Reihenfolge ausgeführt werden, indem Schreiben-nach-Lesen- bzw. WAR-Abhängigkeiten beseitigt werden.
-
Wenn eine Anweisung die Umbenennungsstufe 1104 durchläuft, wird sie in einen Umordnungspuffer 1106 (ROB) eingefügt. Der Umordnungspuffer 1106 ist ein Puffer, der Ausführung der Anweisungen außerhalb der Reihenfolge, aber in der Reihenfolge übergeben, ermöglicht. Der Umordnungspuffer 1106 hält die Anweisungen, die in ihn eingefügt werden, in Programmreihenfolge, aber die Anweisungen in dem ROB können durch Out-of-order-Pipelines 1108 außerhalb der Sequenz ausgeführt werden. In diesem Fall ist der Umordnungspuffer 1106 als Zirkularpuffer mit der Zirkularpufferstruktur 200 von 2 bis 6 ausgebildet.
-
Der Prozessor 1100 umfasst außerdem einen Verzweigungsprädiktor 1112, der ausgelegt ist, vorherzusagen, welche Richtung der Programmfluss im Fall von Anweisungen, die bekanntermaßen mögliche Flussänderungen verursachen, wie etwa eine Verzweigungsanweisung, nehmen wird. Verzweigungsprädiktion ist nützlich, da sie ein spekulatives Ausführen von Anweisungen durch den Out-of-order-Prozessor ermöglicht, bevor das Ergebnis der Verzweigungsanweisung bekannt ist. Der Verzweigungsprädiktor 1112 kann Eingaben aus der Abrufstufe 1102 und der Decodierungs- und Umbenennungsstufe 1104 in Bezug auf neue Anweisungen empfangen, sowie Eingaben aus den Pipelines 1108 und der Übergabestufe 1104 in Bezug darauf, wie ausgegebene Anweisungen ausgeführt worden sind.
-
Es wird nun auf 12 Bezug genommen, worin eine Schemadarstellung eines Multi-Thread-Out-of-order-Prozessors 1200 gezeigt ist. Der Prozessor 1200 umfasst zwei Threads 1202 und 1204. Jeder Thread 1202 und 1204 umfasst eine Abrufstufe 1206 oder 1208, eine Decodierungs- und Umbenennungsstufe 1210 oder 1212, einen Umordnungspuffer 1214 oder 1216 und eine Übergabestufe 1218 oder 1220 wie oben mit Bezug auf 11 beschrieben. Die Threads 1202 und 1204 teilen sich einen Verzweigungsprädiktor 1222 und die Out-of-order-Pipelines 1224. Die Umordnungspuffer 1214 und 1216 teilen sich auch einen Pool von Arrays 1226 und Puffersteuerlogik 1228 wie oben mit Bezug auf 2 bis 6 beschrieben.
-
In der obigen Beschreibung werden Verfahren und Vorrichtungen zum dynamischen Zuteilen von Betriebsmitteln an Zirkularpuffer beschrieben. Diese Verfahren können auf einen beliebigen Zirkularpuffer (z.B. Umordnungspuffer oder Reservierungsstation) in einem Prozessor angewandt werden. Die oben beschriebenen Verfahren können auf alle Zirkularpuffer in einem Prozessor oder auf eine Teilmenge der Zirkularpuffer angewandt werden. Wenn die Verfahren nur auf eine Teilmenge der Zirkularpuffer angewendet werden, können die Verfahren zum Beispiel auf eine spezielle Art von Zirkularpuffern (z.B. Umordnungspuffer) angewandt werden.
-
Die Ausdrücke „Prozessor“ und „Computer“ werden hier als Bezeichnung für eine beliebige Vorrichtung mit Verarbeitungsfähigkeit, so dass sie Anweisungen ausführen kann, verwendet. Für Fachleute ist erkennbar, dass solche Verarbeitungsfähigkeiten in viele verschiedene Vorrichtungen integriert sind, und deshalb umfasst der Ausdruck „Computer“ Set-Top-Boxes, Medien-Player, Digitalradios, PCs, Server, Mobiltelefone, Personal Digital Assistants und viele andere Vorrichtungen.
-
Für Fachleute ist erkennbar, dass zum Speichern von Programmanweisungen benutzte Speichervorrichtungen über ein Netz verteilt sein können. Zum Beispiel kann ein entfernter Computer ein Beispiel für den als Software beschriebenen Prozess speichern. Ein lokaler oder Terminal-Computer kann auf den entfernten Computer zugreifen und die Software ganz oder teilweise herunterladen, um das Programm auszuführen. Als Alternative kann der lokale Computer Stücke der Software je nach Bedarf herunterladen oder bestimmte Softwareanweisungen im lokalen Endgerät und andere im entfernten Computer (oder Computernetz) ausführen. Außerdem ist für Fachleute erkennbar, dass durch Benutzung von Fachleuten bekannten herkömmlichen Techniken die Softwareanweisungen ganz oder teilweise durch eine dedizierte Schaltung, wie etwa einen DSP, ein programmierbares Logikarray oder dergleichen ausgeführt werden können.
-
Eine konkrete Erwähnung von „Logik“ bezieht sich auf eine Struktur, die eine Funktion oder Funktionen ausführt. Ein Beispiel für Logik wären Schaltungen, die ausgelegt sind, diese Funktion(en) auszuführen. Zum Beispiel können solche Schaltungen Transistoren und/oder andere Hardwareelemente umfassen, die in einem Herstellungsprozess verfügbar sind. Solche Transistoren und/oder anderen Elemente können zur Bildung von Schaltungen oder Strukturen verwendet werden, die beispielsweise Speicher wie Register, Flipflops oder Latches, logische Operatoren wie boolsche Operatoren, mathematische Operatoren wie Addierer, Multiplizierer oder Schieber implementieren und/oder enthalten und diese miteinander verbinden. Solche Elemente können als angepasste Schaltungen oder Standardzellenbibliotheken, Makros oder auf anderen Abstraktionsebenen bereitgestellt werden. Solche Elemente können in einer speziellen Anordnung miteinander verbunden werden. Logik kann Schaltungen umfassen, die eine feste Funktion aufweisen, sowie Schaltungen, die programmiert werden können, eine Funktion oder Funktionen auszuführen; eine solche Programmierung kann aus einem Firmware- oder Software-Aktualisierungs- oder -Steuermechanismus bereitgestellt werden. Zur Ausführung einer Funktion identifizierte Logik kann auch Logik umfassen, die eine Bestandteilsfunktion oder einen Subprozess implementiert. In einem Beispiel weist Hardwarelogik Schaltungen auf, die eine Festfunktionsoperation oder -operationen, einen Automaten oder einen Prozess implementieren.
-
Jeder Bereichs- oder Vorrichtungswert, der hier angegeben wird, kann erweitert oder geändert werden, ohne den gewünschten Effekt zu verlieren, wie für Fachleute ersichtlich ist.
-
Es versteht sich, dass die oben beschriebenen Nutzen und Vorteile eine Ausführungsform oder mehrere Ausführungsformen betreffen können. Die Ausführungsformen sind nicht auf diejenigen beschränkt, die beliebige oder alle der angegebenen Probleme lösen, oder diejenigen, die beliebige oder alle der angegebenen Nutzen und Vorteile aufweisen.
-
Jede Erwähnung „eines“ Elements bezieht sich auf eines oder mehrerer dieser Elemente. Der Ausdruck „umfassend“ wird hier so verwendet, dass er die identifizierten Verfahrensblöcke oder Elemente einschließend bedeutet, aber solche Blöcke oder Elemente keine exklusive Liste umfassen, und eine Vorrichtung kann zusätzliche Blöcke oder Elemente enthalten und ein Verfahren kann zusätzliche Operationen oder Elemente enthalten.
-
Die Schritte der Verfahren, die hier beschrieben werden, können in einer beliebigen geeigneten Reihenfolge oder gegebenenfalls gleichzeitig ausgeführt werden. Außerdem können einzelne Blöcke aus beliebigen der Verfahren gelöscht werden, ohne vom Gedanken und Schutzumfang des Gegenstands, der hier beschrieben wird, abzuweichen. Aspekte beliebiger der oben beschriebenen Beispiele können mit Aspekten beliebiger der anderen beschriebenen Beispiele kombiniert werden, um weitere Beispiele zu bilden, ohne den gewünschten Effekt zu verlieren. Wenn Elemente der Figuren durch Pfeile verbunden gezeigt sind, versteht sich, dass diese Pfeile nur einen beispielhaften Fluss der Kommunikation (einschließlich Daten und Steuernachrichten) zwischen Elementen zeigen. Der Fluss zwischen Elementen kann in jeder Richtung oder in beiden Richtungen erfolgen.
-
Es versteht sich, dass die obige Beschreibung einer bevorzugten Ausführungsform lediglich als Beispiel gegeben wird und dass Fachleute verschiedene Modifikationen vornehmen können. Obwohl oben verschiedene Ausführungsformen mit einem gewissen Grad von Detailliertheit oder mit Bezug auf eine oder mehrere einzelne Ausführungsformen beschrieben wurden, könnten Fachleute zahlreiche Abänderungen an den offenbarten Ausführungsformen vornehmen, ohne vom Gedanken oder Schutzumfang der vorliegenden Erfindung abzuweichen.