mini|Logo mini|Prototyp eines RISC-V Mikroprozessors aus dem Jahr 2013 mini|190x190px|ESP32-C6, Mikrocontroller mit zwei RISC-V-Kernen, aus der populären ESP32-Familie RISC-V, offizielle Aussprache in Englisch: „“ [], ist eine Befehlssatzarchitektur (, ISA) zur Konstruktion von Computer-Prozessoren, die sich auf das Designprinzip des Reduced Instruction Set Computers (RISC) stützt. Es ist ein offener Standard, welcher der freien BSD-Lizenz unterliegt. Das bedeutet, dass RISC-V nicht patentiert ist und frei verwendet werden darf. Somit ist es jedem erlaubt, RISC-V-Mikroprozessoren zu entwerfen, herzustellen, weiterzuentwickeln und zu verkaufen, auch als Open-Source-Hardware. Zahlreiche Unternehmen bieten RISC-V-Hardware an. Insbesondere bei Mikrocontrollern hat sich RISC-V etabliert, beispielsweise bei manchen ESP32-Modellen, der CH32-Reihe oder dem Raspberry Pi Pico 2.
Der Befehlssatz besitzt Eigenschaften, die die Rechnergeschwindigkeit erhöhen, aber trotzdem die Kosten und den Energieverbrauch senken. Dies schließt eine Load/Store-Architektur ein, sowie Bit-Muster, um die Multiplexer in einer CPU zu vereinfachen, vereinfachte Standard-basierte Gleitkommazahlen, einen architekturneutralen Entwurf und das Setzen des höchstwertigen Bits an eine festgelegte Position, um die Vorzeichenerweiterung zu beschleunigen. Bezüglich weitverbreiteten Architekturen hat RISC-V am meisten Ähnlichkeit mit der ARM-Architektur.
Geschichte Das Projekt begann 2010 an der University of California, Berkeley unter der Leitung von Krste Asanovic und David A. Patterson. Anders als andere akademische Entwürfe, die üblicherweise auf einfache Erläuterung optimiert sind (vgl. Mikrocodesimulator MikroSim), wurde der RISC-V-Befehlssatz für die praktische Anwendung in Rechnern entworfen.
2015 wurde das Projekt an die neugegründete gemeinnützige RISC-V International-Organisation übergeben, unter deren Aufsicht der Befehlssatz von Hard- und Softwareentwicklern weltweit weiterentwickelt und gefördert wird. An der Entwicklung von RISC-V und dazugehöriger Hard- und Software sind viele Forschungseinrichtungen und Firmen beteiligt (siehe unten bei den Implementierungen).
Im Jahre 2019 wurde die Version 2.2 des Userspace-ISA und im Jahre 2021 die Version 1.12 des privilegierten ISA festgelegt und ermöglichen es Software- und Hardwareherstellern, diesen zu nutzen oder zu implementieren. Eine Fehlersuch-Spezifikation ist in der Spezifikation der privilegierten ISA enthalten.
Architektur Der RISC-V-Befehlssatz steht in der Tradition der RISC-Prozessoren, die sich auf möglichst wenige, einfach zu dekodierende Maschinenbefehle konzentrieren. Dementsprechend hat der einfachste RISC-V-Befehlssatz (RV32I) nur 40 Befehle.
RISC-V hat in allen Varianten eine Wortgröße von 32 bit. Demnach sind alle regulären standardisierten Befehle 32 bit groß, und die kleinstmögliche Registergröße ist 32 bit. Für einige Befehle gibt es in der C-Erweiterung (siehe unten) alternative Kodierungen, die nur 16 bit (Halbwort) groß sind, allerdings dasselbe Verhalten aufweisen wie der entsprechende 32-bit-Befehl. Die Größe eines Maschinenbefehls kann an den untersten zwei Bits des Befehls abgelesen werden, und Maschinenbefehle mit 64 und 128 bit Größe sind hier bereits vorgesehen. Ist die C-Erweiterung nicht implementiert, müssen Befehle an 4-Byte-Grenzen ausgerichtet sein, andernfalls können es auch 2-Byte-Grenzen sein (selbst für 32-bit-Befehle).
Der RISC-V Befehlssatz wurde für eine Vielzahl von Anwendungsfällen entworfen. Er hat daher eine variable Datenwortbreite und ist erweiterbar, so dass jederzeit mehr Kodierungsbits hinzugefügt werden können. Er unterstützt drei Datenwortbreiten: 32, 64 und 128 Bit und eine Auswahl an Unterbefehlssätzen. Die Definitionen jedes Unterbefehlssatzes variieren geringfügig zwischen den drei Wortbreiten. Die Unterbefehlssätze unterstützen kompakte eingebettete Systeme, persönliche Rechner, Hochleistungsrechner mit Vektorprozessoren und Parallelrechner.
Der Befehlssatzraum für den auf 128 Bit gedehnten Befehlssatz wurde reserviert, weil 60 Jahre Industrieerfahrung gezeigt haben, dass die meisten nicht wieder gut zu machenden Fehler in der Gestaltung von Befehlssätzen durch fehlenden Speicheradressraum verursacht wurden. Noch im Jahr 2016 blieb der 128-Bit-Teil des Befehlssatzes absichtlich undefiniert, da bisher wenig Erfahrung mit solch großen Speichersystemen besteht. Es gibt Vorschläge, Instruktionen mit einer variablen Breite bis zu 864 Bit zu implementieren.
RISC-V ist eine Little-Endian-Architektur. Befehle werden immer in Little-Endian-Reihenfolge gelesen; daher auch die Kodierung der Befehlsgröße in den untersten Befehlsbits, die sich immer im ersten gelesenen Byte befinden. Falls die Implementierung dies unterstützt, kann nur für Datenzugriffe im Hauptspeicher auf Big-Endian umgeschaltet werden.
Architekturaufbau und Erweiterungen RISC-V ist nicht eine einzige Architektur, sondern eine ganze Familie an Architekturen, die modular aufeinander aufbauen. So gibt es die drei Grundarchitekturen namens RV32I, RV64I und RV128I, die entsprechend der Zahl im Namen eine Register- und Speicherbreite von 32, 64 bzw. 128 bit besitzen. Auch wenn streng genommen RV64I keine einfache Erweiterung von RV32I ist, werden alle existierenden Befehle mit neuer Bedeutung übernommen; der ADD-Befehl addiert beispielsweise nun statt zweier 32-bit Zahlen zwei 64-bit Zahlen. Die Grundarchitekturen enthalten entsprechend des „I“ im Namen nur Integer-Befehle, d. h. Befehle, die mit Ganzzahlen rechnen. Dazu kommen andere, fast immer benötigte Befehle wie bedingte und unbedingte Sprungbefehle, Speicherzugriffsbefehle und Software-Interrupt-Befehle. Alle weiteren Funktionalitäten sind in standardisierte Befehlssatzerweiterungen zusammengefasst, die jeweils eine 32-bit, 64-bit und 128-bit-Version besitzen. Wichtige Erweiterungen und ihre Namen sind:
M für Ganzzahl-Multiplikation und -Division A für atomare Speicheroperationen in Multiprozessorsystemen F, D und Q für Gleitkommaoperationen nach IEEE 754: binary32, binary64 bzw. binary128 Zicsr für Control and Status Registers (CSRs) (siehe unten) C für komprimierte Befehle, das sind 16-bit-Kodierungen häufig verwendeter Befehle, die somit den Speicherverbrauch reduzieren.
Es ist explizit vorgesehen, dass proprietäre bzw. Drittanbieter-Erweiterungen für RISC-V verfasst werden, die einen mit X beginnenden Namen führen. Beispiele dafür sind XTheadBb, XTheadSync oder XVentanaCondOps.
Verfügt eine RISC-V-Implementierung nun über eine bestimmte Sammlung an Erweiterungen, so kann diese entsprechend der Kurznamen kompakt bezeichnet werden, beispielsweise RV64IMCZicsr für einen Prozessor, der über die 64-bit-Basisarchitektur mit Ganzzahlmultiplikationen, komprimierten Befehlen und CSR-Unterstützung verfügt. Manche Erweiterungen hängen wiederum von anderen ab; so ist die Unterstützung von 64-bit-Gleitkommazahlen (D) nur gleichzeitig mit CSRs (Zicsr) und 32-bit-Gleitkommazahlen (F) möglich. Für eine CPU, die ein Endbenutzer-Betriebssystem ausführen kann, werden eine ganze Reihe an Erweiterungen benötigt, die unter der Pseudo-Erweiterung G (general purpose) zusammengefasst werden. RV64G bedeutet demnach eigentlich RV64IMAFDZicsr_Zifencei, also die Basisarchitektur inklusive sieben Erweiterungen.
Basisarchitektur RISC-V besitzt 32 Register, die ganze Zahlen enthalten. Die Basisarchitektur bestimmt deren Größe; so hat RV32 eben 32-bit-Register und RV64 64-bit-Register. Die Register werden mit den Architekturnamen x0 bis x31 bezeichnet. Dabei ist x0 ein besonderes Register, da es beim Lesen immer 0 liefert und alle Schreibvorgänge auf x0 ignoriert werden. Dies wird genutzt, um verschiedene Funktionen ohne zusätzliche Befehle möglich zu machen: # Subtrahiert x6 von x0, d.h. negiert x6 sub x5, x0, x6 # Prüft, ob x0 kleiner als x13 ist, d.h. ob x13 größer als 0 ist slt x2, x0, x13 # Speichert die Addition von 0 und x0 in x0; kanonisches NOP addi x0, x0, 0 Viele dieser Funktionen sind in diversen Assembler-Pseudobefehlen verfügbar; für die drei Befehle oben wären es neg, sgtz bzw. nop.
Rechenbefehle verfügen immer über drei Operanden: zwei Quellregister rs1 und rs2 und ein Zielregister rd. Anders als bei anderen Architekturen ist das erste Quellregister nicht automatisch auch das Zielregister, wobei es natürlich möglich ist, dasselbe Register für Quelle und Ziel anzugeben. Befehle mit konstanten Operanden, sogenannte Immediate-Befehle, ersetzen rs2 durch eine Konstante, die im Befehl selbst enthalten ist. Einige Beispiele für Rechenbefehle: # Addiert x0 (0) und 42 und speichert das Ergebnis in x7 # d.h. lädt die Konstante 42 in x7 addi x7, x0, 42 # Konstante 10 wird in x6 gespeichert addi x6, x0, 10 # Subtrahiert x7 von x6 und speichert das Ergebnis in x5 sub x5, x6, x7 # Exklusives Oder mit Immediate xori x4, x5, 0x1111 # Arithmetische Bitverschiebung nach rechts sra x8, x4, x5 # Multipliziert x5 mit x4 und speichert das Ergebnis in x10 mul x10, x5, x4
Konstanten, LUI und AUIPC Gewöhnliche Immediate-Befehle können aufgrund der Befehlskodierung ausschließlich 12-bit-Konstanten enthalten. Je nachdem, ob die Konstante vorzeichenlos oder vorzeichenbehaftet ist, bedeutet dies einen Wertebereich von 0 bis 4096 bzw. −2048 bis 2047. Um auch größere Konstanten kodieren zu können, gibt es den Befehl Load Upper Immediate (lui). lui lädt eine 32-bit-Konstante, deren obere 20 bit dem Immediate entstammen und deren untere 12 bit auf 0 gesetzt werden. Mittels einer darauffolgenden Addition kann so mit zwei Befehlen jede 32-Bit-Zahl geladen werden: # Die Zahl 987654321 (0x3ADE6'8B1) soll in Register x20 geladen werden.
# Lade in x20 die Konstante 0x3ADE7'000, # Das 20-bit-Immediate-Argument wird in Bit 31...12 geschrieben, Bit 11...0 werden genullt lui x20, 0x3ADE7
# Addition der 12 bit sign extended Konstante 0x8B1 (-0x74F) addi x20, x20, 0x8B1
# Verbreitete Assembler unterstützen den Makrobefehl li (load immediate) # welcher je nach Konstante 1 oder 2 Befehle erzeugt: li x20, 0x3ADE68B1 Der Befehl Add Upper Immediate to Program Counter (auipc) addiert einen solchen 20-Bit-Immediate stattdessen zum aktuellen Programmzähler (Program Counter), womit effizient Speicheradressen in der Nähe des Programmcodes abgerufen werden können und der Code positionsunabhängig wird.
Speicherzugriffe RISC-V hat als Load/Store-Architektur keine Befehle, die direkt auf Daten im Speicher Rechenoperationen durchführen können. Eine Ausnahme hiervon bilden die atomaren Befehle aus der A-Erweiterung, die solche Funktionalität zur Prozessorsynchronisierung benötigen (amoadd, amoor, amoswap etc.). Für reguläre Speicherzugriffe ist nur ein einfaches Laden oder Speichern vom/zum Hauptspeicher möglich, und der Addressierungsmodus ist immer Register+Konstante. Beispielsweise kann das Register die Startadresse einer Struktur enthalten und die Konstante den Offset eines Felds in der Struktur. # Lade Byte von Adresse 0x40 lb x11, 0x40(x0) # Lade erstes Wort auf dem Stack (x2 ist der Stack Pointer) lw x12, 4(x2) # Lade Halbwort (16 bit) ohne Vorzeichenerweiterung lhu x13, 2(x2)
# Speichere Doppelwort (nur RV64 und RV128) sd x13, 8(x2) Speicherzugriffe müssen ausgerichtet sein, z. B. Wortzugriffe auf Vielfache von 4 Byte und Doppelwortzugriffe auf 8 Byte. Eine Implementierung kann auch unausgerichtete Speicherzugriffe unterstützen, dies ist jedoch in der Regel nicht der Fall und wird eventuell in der Firmware emuliert (fast trap and emulate).
Kontrollfluss RISC-V besitzt anders als die meisten heutzutage verbreiteten Architekturen kein Statusregister und keine Flags. Kontrollflussentscheidungen werden immer auf der Basis eines konkreten Vergleichs durchgeführt, zum Beispiel: # Springe falls x4 < x5 (ganze Zahlen) blt x4, x5, label1 # Springe falls x7 >= x9 (natürliche Zahlen) bgeu x7, x9, label2 # Springe falls x1 = 0 (Pseudobefehl beqz) beq x1, x0, label3