Der Prozessor des Typs Cortex A8 ist das ausgefeilteste Low-Power-Design, das ARM je hervorgebracht hat. Um das hier verwirklichte hohe Rechenleistungs-Niveau zu erzielen, wurden neue Mikroarchitektur-Elemente hinzugefügt, die es in der ARM-Architektur bislang nicht gab. Dazu gehören eine „Dual In-Order Issue ARM Integer Pipeline“, ein integrierter L2-Cache und eine 13-stufige Pipeline.
Superskalare-Pipeline
Möglicherweise die entscheidendste neue Eigenschaft ist die Dual-Issue In-Order ARM Integer Pipeline mit statischem Scheduling. Durch die Fähigkeit zur gleichzeitigen Ausgabe zweier Datenverarbeitungs-Instruktionen können in einem Taktzyklus erheblich mehr Befehle verarbeitet werden. Mit der Entscheidung, das „In-Order-Issue“-Verfahren beizubehalten, verfolgte man die Absicht, die zusätzlich abfallende Verlustleistung auf ein Minimum zu reduzieren. Das „Out-of-Order-Issue- und Retire“-Konzept könnte dagegen zu einem deutlich höheren Logikaufwand führen, was die Leistungsaufnahme entsprechend erhöhen würde. Die Wahl der In-Order-Issue-Technik ermöglicht zudem ein Instruction-Issuing nach dem „Fire-and-Forget“-Prinzip, was kritische Signalwege aus dem Design entfernt und den Aufwand an speziell entwickelter Logik in der Pipeline verringert. Das statische Scheduling wiederum schafft die Voraussetzungen für umfangreiches „Clock-Gating“ (Transistoren zur Abschaltung von Chipfunktionen) zur Senkung der Leistungsaufnahme während der Verarbeitung.
Die beiden symmetrischen ALU-Pipelines (Arithmetic Logic Unit) ALU 0 und ALU 1 können den Großteil der arithmetischen Befehle verarbeiten. In der ALU Pipe 0 befindet sich stets der ältere von zwei ausgegebenen Befehlen. Zwar besitzt der Prozessor Cortex-A8 auch Multiplizierer- und Load-Store-Pipelines, doch führen diese den beiden ALU-Pipelines keine zusätzlichen Befehle zu, sondern man kann sie als „abhängige“ Pipelines betrachten, da sie stets im Verbund mit einer der beiden ALU-Pipelines verwendet werden müssen. Während die Multiplizierer-Pipeline nur mit Befehlen in der ALU-0-Pipeline kombiniert werden kann, lässt sich die Load-Store-Pipeline mit Instruktionen in beiden Pipelines koppeln.
Verzweigungs-Vorhersage
Mit der Entscheidung zugunsten einer 13-stufigen Pipeline wollte man die Voraussetzungen für wesentlich höhere Taktfrequenzen schaffen, als sie mit den bisherigen Generationen von ARM-Mikroarchitekturen möglich waren. Die mit F0 bezeichnete Stufe wird übrigens nicht mitgezählt, da sie lediglich der Adressgenerierung dient. Um den Mehraufwand zu minimieren, der durch eine derart tiefe Pipeline bei Verzweigungen entsteht, bedient sich der Cortex-A8-Prozessor einer Funktion zur Vorhersage von Verzweigungen. Diese Stufe beruht auf einer zweistufigen, globalen Verarbeitungs-Historie und enthält zwei verschiedene Strukturen, nämlich den „Branch Target Buffer“ (BTB) und den „Global History Buffer“ (GHB). Auf beide wird bei „Instruction Fetches“ (Befehl holen) parallel zugegriffen.
Der BTB signalisiert, ob sich an der aktuellen Fetch-Adresse ein Verzweigungsbefehl befindet und welche Zieladresse die Verzweigung hat. Dieser Puffer enthält 512 Einträge. Bei einem Hit im BTB wird eine Verzweigung prognostiziert und ein Zugriff auf den GHB ausgeführt. Der GHB enthält insgesamt 4096 sättigende 2-bit-Zähler, die die Stärke und Richtungsinformation von Verzweigungen codieren. Der GHB wird durch eine 10 bit umfassende Historie der Richtung der letzten zehn ausgeführten Verzweigungen sowie durch 4 bit des Programmzählers indiziert.
Ergänzend zu diesem dynamischen Branch Predictor dient ein Return Stack zur Vorhersage der Rücksprungadresse von Unterprogrammen. In den 32-bit-Einträgen des „Return Stack“ wird jeweils der Wert des Link-Registers in Register 14 (r14) sowie der ARM- oder Thumb-Status der aufrufenden Funktion abgelegt. Wird die Ausführung einer Instruktion vom Typ Return prognostiziert, stellt der Return Stack die zuletzt per „Push“ gespeicherte Adress- und Statusinformation zur Verfügung. Bei einer falsch vorhergesagten Verzweigung verliert man 13 Taktzyklen (Bild 2).
Level-1-Cache
Im Cortex A8 entsteht durch schnelle Schreib- und Lesezugriffe auf die Level-1-Caches ein Mehraufwand von einem Zyklus. Daten- und Befehls-Caches können auf 16 oder 32 Kbyte konfiguriert werden. Jeder Cache ist nach dem „4-Way Set Associative“-Prinzip (4-fach satzassoziativ) organisiert und verwendet ein als „Hash Virtual Address Buffer (HVAB) Way-Prediction“ bezeichnetes Verfahren, um das Timing zu verbessern und die Leistungsaufnahme zu senken. Die Cache-Speicher werden physikalisch adressiert (virtueller Index, physikalischer Tag) und verfügen über Hardwareunterstützung zur Vermeidung von „Aliased Entries“. Die Parität wird mit einem Paritätsbit pro Byte unterstützt.
Der Austausch von Einträgen im Daten-Cache erfolgt nach dem „Write-Back“-Verfahren ohne „Write Allocates“. Ebenfalls enthalten ist ein „Store Buffer“ zum Zusammenführen von Daten vor dem Überschreiben an den Hauptspeicher. Die HVAB-Technik ist ein neuartiges Verfahren zur Verringerung des mit Cache-Zugriffen einhergehenden Energiebedarfs. Mit Hilfe eines besonderen Vorhersageverfahrens wird erst unmittelbar vor einem Zugriff die jeweilige Cache-Zeile der vier pro Satz aktiviert („4-way set associative“ bedeutet, dass ein Satz von vier Cachezeilen vorgehalten wird).
Level-2-Cache
Die Cortex-A8-Architektur sieht einen integrierten Level-2-Cache vor, der sich durch eine breitbandige Schnittstelle zum Level-1-Cache mit geringer Latenzzeit auszeichnet. Dies minimiert die Latenzzeit von „Linefills“ des Level-1-Cache und vermeidet Konflikte mit dem Datenverkehr auf dem Haupt-Systembus. Der Level-2-Cache lässt sich für Kapazitäten von 64 Kbyte bis 2 Mbyte konfigurieren.
Der Level-2-Cache wird physikalisch adressiert und ist nach dem „8-Way Set Associative“-Prinzip organisiert. Der für Befehle und Daten genutzte Cache bietet optional Unterstützung für ECC (Fehlerkorrektur) und Parität. Abhängig von den „Page-Table“-Einstellungen wird nach dem „Write-Back“-, „Write-Through“- oder „Write-Allocate“-Verfahren gearbeitet und es kommt ein pseudo-zufälliges Zuordnungs-Verfahren zur Anwendung. Während sich der Inhalt des Level-1-Daten-Cache und der Inhalt des Level-2-Cache gegenseitig ausschließen, ist der Inhalt des Level-1-Befehls-Cache stets eine Teilmenge des Level-2-Cache. Zur Senkung der Leistungsaufnahme wird auf die Tag- und Daten-RAMs des Level-2-Cache seriell zugegriffen.
NEON Media Engine
Die „NEON Media Processing Engine Pipeline“ des Cortex-A8-Prozessors beginnt im Anschluss an die Haupt-Integer-Pipeline (Bild 3). Jegliche „Exceptions“ (Ausnahmen) und fehlge-schlagenen Verzweigungs-Prognosen sind somit aufgelöst, bevor Befehle bis zu ihr gelangen. Wichtiger noch ist die Tatsache, dass für den Zugriff auf Daten im Level-1-Cache kein Mehraufwand entsteht, denn die Integer-Einheit erzeugt die Adressen für NEON-Load- und Store-Operationen bereits beim Durchlaufen der Pipeline. Die Daten können somit aus dem Level-1-Cache geholt werden, noch bevor sie von einer Datenverarbeitungs-Operation in der NEON Engine benötigt werden. Tiefe Puffer für Befehle und geladene Daten zwischen der NEON Engine, der Integer-Einheit und dem Speichersystem sorgen dafür, dass die Latenzzeit von Level-2-Zugriffen bei Daten-Streaming nicht zutage tritt. Ein Store-Puffer verhindert außerdem, dass NEON-Stores die Pipeline blockieren und erkennt Adresskonflikte zwischen Zugriffen der Integer-Einheit und NEON-Ladeoperationen.
Die NEON-Engine wird durch die „NEON Instruction Queue“ (NIQ) von der Integer-Pipeline entkoppelt. Die „Instruction Execute Unit“ kann in jedem Taktzyklus bis zu zwei gültige Instruktionen an die NEON-Engine übergeben. Von der NEON-Einheit führen 128 bit breite Load- und Store-Pfade zum Level-1- und zum Level-2-Cache, und auch das Daten-Streaming aus beiden Caches wird unterstützt.
Die NEON Media Engine besitzt eine eigene 10-stufige Pipeline, die am Ende der Integer-Pipeline beginnt. Da wie erwähnt alle fehlgeschlagenen Verzweigungs-Vorhersagen und Exceptions in der Integer-Einheit aufgelöst wurden, muss eine an die NEON Media Engine übergebene Instruktion stets ausgeführt werden, denn Exceptions können von ihr nicht mehr erzeugt werden. Die NEON Engine enthält drei SIMD-Integer-Pipelines, ei-ne Load-Store/Permute-Pipeline, zwei SIMD-Single-Precision Floating-Point-Pipelines und eine Vektor-Gleitkomma-Einheit (Vector Floating-Point Unit – VFPLite) ohne Pipeline.
Die NEON-Instruktionen werden entsprechend ihrer Reihenfolge ausgegeben und abgelegt. Bei einer Datenverarbeitungs-Anweisung handelt es sich stets um einen NEON-Integer-Befehl oder um einen NEON-Gleitkomma-Befehl. Die NEON Engine im Cortex A8 gibt niemals zwei Datenverarbeitungs-Instruktionen gleichzeitig aus, um den Mehraufwand an Chipfläche durch die dann notwendige Vorhaltung zweier Datenverarbeitungs-Blöcke zu vermeiden. Außerdem verhindert man hierdurch, dass durch das Multiplexing der Lese- und Schreibregister-Ports Signalpfade mit kritischem Timing und zusätzlicher Komplexität entstehen.
Der Integer-Datenpfad der NEON Engine enthält drei Pipelines, nämlich die „Integer Multiply/Accumulate Pipeline“ (MAC), die „Integer Shift Pipeline“ und die „Integer ALU Pipeline“. Eine „Load-Store/Permute Pipeline“ ist für sämtliche Load/Store-Operationen der NEON Engine, für Datentransfers von und zur NEON Integer Einheit sowie für Datenpermutations-Operationen (z.B. Interleave und De-Interleave) zuständig. Der „NEON-Floating-Point“-Datenpfad (NFP) ist mit zwei Pipelines ausgestattet, nämlich einer Multiplizier-Pipeline und einer Addier-Pipeline. Die separate VFPLite-Einheit ist eine ohne Pipeline ausgeführte Implementierung der ARM-VFPv3-Gleitkomma-Spezifikation und ausgelegt für IEEE-754-konforme Gleitkomma-Unterstützung mit mittlerer Rechenleistung. Die VFPLite-Einheit sorgt für Abwärtskompatibilität zu existierendem ARM-Gleitkomma-Code und dient zur Bereitstellung von Arithmetik-Funktionen mit einfacher und doppelter Genauigkeit gemäß IEEE 754. Bild 4 gibt einen Überblick über die verschiedenen NEON-Pipelines.