Design-Praxis RISC-V Von den Grundlagen bis zum Prototyp

I. RISC-V Prinzipien nach ISA-Spezifikation

Anwendungs-Ebene nach [1]

Ein Prozessor-Handbuch dokumentiert für den Anwender im Wesentlichen das Adressverzeichnis der Unterblöcke und den Funktionsumfang in Assemblersprache. Dagegen greift die RISC-V ISA-Spezifikation [1] eine Stufe tiefer: sie dokumentiert die binäre Befehlsstruktur mit dem asm-Code und dazu die Entscheidungsgrundlage für das jeweilige Design. Ohne Anspruch auf Vollständigkeit werden im Folgenden ein paar grundlegende Aspekte daraus zusammengefasst.

Unabhängig von der Länge des Anwendungs-Adressraumes (32, 64 oder 128 Bit) enthält jeder RISC-V-Prozessor, den mit der Endung I gekennzeichneten Basisbefehlssatz. Nach Spezifikation muss dieser Basisbefehlssatz nicht vollständig in Hardware ausgeführt sein. Der Basisbefehlssatz I kann mit einer Reihe von Standardsätzen erweitert werden, die keine Namenskonflikte untereinander haben. Die Allzweckerweiterung G enthält die Sätze M (Multiplikation), A (elementare Bitmanipulation), F (Fließkommarechnung), D (Double-Fließkommarechnung).

Die Basisbefehle messen 32-Bit Länge. Befehlserweiterungen können beliebige ganzzahlige Vielfache von 16 Bit messen: die Befehlslänge wird mit den ersten Bits, und bei langen Befehlen in zusätzlichen weiteren Befehlsabschnitten (imm[u:l]) angegeben. Für ressourcen-effiziente Anwendungen sind die komprimierten Befehlssätze direkt einsetzbar, aber nicht notwendig. Jede Null- oder Einsfolge überführt den Prozessor in den Fehlerzustand: so werden defekte Speicherzustände direkt erfasst.

Da little-endian byte-Ordnung im embedded-Segment weit verbreitet ist,
wird diese auch vom RISC-V-Standard verwendet. big-endian-Ordnung müsste durch eine proprietäre Erweiterung implementiert werden. Bei Verschiebung von Befehlsfolgen zwischen den Registern muss diese Ordnung im Auge behalten werden, damit das Rechenwerk die Befehlslänge korrekt erfassen kann. Für den Transfer vom Speicher zum Rechenregister gibt der Standard ein verifiziertes Verfahren vor [4]. Tritt eine Ausnahmebedingung synchron zur Befehlsausführung auf, heißt das bei RISC-V exception, interrupts werden asynchrone Ausnahmebedingungen genannt. Eine exception kann das System in einen trap-Zustand überführen.

Der Basissatz R32I zählt 47 Befehle. Er kann sämtliche Standarderweiterungen, bis auf die Bitmanipulationen A, nachbilden. Das Programmiermodell zählt 32 32-Bit-Register x0 bis x31. x0 ist nicht beschreibbar und trägt die NULL, x1 sollte die Antwortadresse eines Aufrufes tragen. Die Spezifizierung heißt das verwendete Drei-Adressformat effizient, zur vollständigen Ausführung in einem Schritt sind damit typischerweise 32 Register notwendig. Applikationsabhängig reichen acht Register zur dynamischen Ausführung der komprimierten 16-Bit-Folgen: hier bietet R32E eine sparsame Variante mit 16 Registern.

Die 32-Bit-Befehle kommen in vier Archetypen R/S/I/U vor (Bild 1, oben). I steht für Register-Immediate-, R für Register-Register-Manipulationen, S ist ein Speicherformat, das U-Format ist u.a. geeignet um Konstanten zu generieren (z.B. Adressen). Adressinformationen befinden sich in allen Befehlen an der gleichen Stelle um Fehler zu minimieren, Zwischenwerte z.B. Parametrierungen wandern zwischen diesen Klassen in unterschiedliche Befehlsabschnitte. Die Zwischenwerte besitzen fast immer ein Vorzeichen und befinden sich in der Sequenz so weit links wie möglich. Verzweigungen und Sprünge (B/J für Branch/Jump) sind analog zu S/U gebaut, die Zwischenwerte werden dabei zusätzlich in Untersequenzen aufgeteilt. Verzweigungen basieren dabei auf dem direkten arithmetischen Vergleich zweier Registereinträge. Zur Steigerung der Ausfallsicherheit verortet RISC-V das Vorzeichen eines Zwischenwertes immer in Bit 31.

Die Basisbefehle lösen nie eine arithmetische exception aus. Ein Pufferüberlauftest ist dabei nicht als separater Befehl ausgeführt, da dieser effizienter als zusätzliche Verzweigung auf die Addition bewältigt wird.

Neben den Grundrechenarten enthält R32I auch zwei fence-Befehle um Hardware-threads* in einer Ausführungsumgebung zu synchronisieren, elementare Test- und Statusbefehle (CSR), sowie timer- und Ausführungssteuerung (call and break).

RV32E ist eine zusätzliche 32-Bit-Architektur, für Applikationen die mit 16 Registern x0-x15 auskommen. Ruft ein Befehl ein fehlendes Register (x16-x31) auf, löst das eine exception mit Rückmeldung "illegale Anweisung" aus.
Mögliche Standard-Erweiterung für R32VE sind M, A und C.

Die Standard-Erweiterung M (Bild 1, unten) enthält separate Befehle für Multiplikation und Division, die im Archetyp R ausgeführt sind. Die Division durch Null überführt als einzige Anweisung im Standard-Befehlssatz eine exception in einen trap. Die exception ist in einer zusätzlichen Verzweigung
nach der Multiplikation ausgeführt.

Unter bestimmten Voraussetzungen können die komprimierten
Befehle R32E eingesetzt werden. Aufgrund der Lesbarkeit wurde die Kompression Eins-zu-Eins umgesetzt: gerade für das debugging wäre eine weitere, potenziell verschachtelte Kompression, zu komplex. Der Kompressionssatz sollte auch als ergänzende Befehlsbibliothek verstanden sein, eine in R32E geschlossene Applikation ist im Allgemeinen nicht möglich. Die spezifizierte Kompression unterscheidet RISC-V von gebräuchlichen Formaten des embedded-Segements wie Arm v8. Sie soll einen Performanzgewinn durch Reduktion fehlerhafter Befehls-Vorladezyklen (cache-miss), mit dem kürzeren Maschinenbefehl bringen. In einem Praxisbeispiel ergab sich damit eine ähnliche Performanz wie mit doppeltem Befehlsspeicher-Umfang [5].