RISC-V

<image>

RISC-V（英語發音為「risk-five」）是一個基於精簡指令集（RISC）原則的開源指令集架構（ISA），簡易解釋為與開源軟體運動相對應的一種「開源硬體」。該項目於2010年在加州大學柏克萊分校啟動，但許多貢獻者是該大學以外的志願者和業界人士。

與大多數指令集相比，RISC-V指令集可以自由地用於任何目的，允許任何人設計、製造和銷售RISC-V晶片和軟體而不必支付給任何公司專利費。雖然這不是第一個開源指令集，但它具有重要意義，因為其設計使其適用於現代計算設備（如倉庫規模雲電腦、高端行動電話和微小嵌入式系統）。設計者考慮到了這些用途中的性能與功率效率。該指令集還具有眾多支持的軟體，這解決了新指令集通常的弱點。

RISC-V指令集的設計考慮了小型、快速、低功耗的現實情況來實做，但並沒有對特定的微架構做過度的設計。

截至2021年12月，RISC-V工作小組已經批准了版本 20191213 的非特權指令集（Unprivileged ISA，曾經稱為使用者級指令集 User-Level ISA），以及版本 20211203 的特權指令集（Privileged ISA）。

## 意義

RISC-V的作者們旨在提供數種可以在BSD許可證之下自由使用的CPU設計。該許可證允許像是RISC-V晶片設計等衍生作品可以像RISC-V本身一樣是公開且自由發行，也可以是閉源或者是專有財產。

相比而言，ARM控股和MIPS科技等商業晶片供應商會對使用其專利者收取高額的許可費用。他們也要求在接收其描述設計優點的文件和指令集前，還需要簽署保密協議。許多設計優點為完全專有，從來不會披露給客戶。這種保密制度阻礙了公共教育用途和安全審核，以及開發公共、低成本的自由及開放原始碼軟體編譯器和作業系統。

處理器設計需要多種專業的設計知識，包括電子邏輯、編譯器和作業系統，這種資源很難在專業工程團隊之外見到。所以現代且高質量的通用電腦指令集近年來除了學術環境以外並沒有在任何地方被廣泛使用，甚至沒有被闡述。正因如此，許多RISC-V貢獻者將此視為整個社群付出的成果，而這也是RISC-V有很多工程上的應用的一項原因。

RISC-V的作者們還有大量研究和使用者經驗來驗證他們在矽片和仿真中的設計。RISC-V指令集是從一系列的學術電腦設計項目直接發展而來的。它一開始的目的有一部分是為了幫助這些項目。

## 歷史

### 前身

RISC的歷史可追溯到1980年左右。在此之前，人們覺得簡單的電腦可能會有用，但是沒有很多人去闡述其設計原則。這種簡單而有效的電腦一直都是學術界的興趣。

學術界的學者們為了出版第一版的《計算機體系結構：量化研究方法》（Computer Architecture: A Quantitative Approach）ISBN 978-1558600690，所以於1990年訂立了RISC指令集DLX。大衛·帕特森（David Patterson）是其中一位作者，後來協助RISC-V的開發。但是DLX只用於教育用途，學術界和業餘愛好者使用FPGA來實做它，但並沒有取得商業運用。

版本2及更早版本的ARM CPU具有公共域指令集，並且仍有GCC的支持。該指令集有三個開源內核，但從未被製造。

OpenRISC是一款基於DLX的開源指令集，並且具有相關的RISC設計。OpenRISC 完全支持GCC並且有實做在Linux上，但是它很少有商業上的實做。

### RISC-V基金會及RISC-V國際協會

加州柏克萊分校的Krste Asanović教授發現開放原始碼的電腦系統有很多用途。在2010年他決定用三個月的時間來開發並發表一個開放原始碼的電腦系統。這個計畫是用來幫助包括學術以及工業的使用者。柏克萊分校的大衛·帕特森教授也參加了這個計畫。帕特森也是原來伯克利分校RISC的設計者，RISC-V只是他眾多RISC CPU研究計畫的一個．RISC-V計畫早期一些經費來自DARPA。

有參與支援RISC-V基金會的公司以及機構包括了超微半導體、晶心科技、英國航太系統、加州大學伯克利分校、Bluespec、Cortus、Google、GreenWaves Technology、慧與科技、華為、IBM、Imperas Software、中國科學院、北京清華大學、印度理工學院、萊迪思半導體、邁倫科技、美高森美、美光科技、輝達、恩智浦半導體、甲骨文公司、高通、Rambus、威騰電子、SiFive、阿里巴巴集團、紅帽公司、成為資本。

2019年6月，圖靈獎得主、RISC-V基金會創始人之一大衛·帕特森（David Patterson）在瑞士宣布，將依託清華—伯克利深圳學院（TBSI），在內部建設RISC-V國際開源實驗室（RISC-V International Open Source Laboratory），又稱大衛帕特森RIOS圖靈實驗室。清華大學稱實驗室將瞄準世界CPU產業戰略發展新方向和粵港澳大灣區產業創新需求，聚焦於開源指令集CPU研究，建設以深圳為根節點的RISC-V全球創新網路和以技術成果轉移為主要使命的非營利組織，全面提升RISC-V生態系至最先進可商用水平。預判屆時將面對國際大廠法律層面發起挑戰問題上，伯克利加州大學和清華大學的法學院將與之建立聯繫。

2020年3月，RISC-V基金會為規避美國對中國的貿易限制而將總部搬遷至瑞士，並更名為RISC-V國際協會（RISC-V International），以非盈利商業協會的身份在瑞士註冊。

### 獎項

- 2017： The Linley Group's Analyst's Choice Award for Best Technology（對其指令集）

<image>

## 激勵要求

RISC設計者們認為指令集因為位於硬體和軟體之間，所以是電腦主要的溝通橋梁，因此如果有一個設計良好的指令集是開源而且可以被任何人使用的，就可以讓更多的資源能夠重複利用，而大大的減少軟體的成本。而這樣的指令集也會增加硬體供應商市場的競爭力，因為硬體供應商們可以挪用更多資源來進行設計，減少處理軟體支援的事務。

設計者聲稱在指令集設計領域裡，新的設計準則漸漸變得罕見，而近四十年中，大多數成功的設計變得越來越相似。至於那些失敗的指令集，大多數是因為他們的贊助商賺不了錢，而不是因為其指令集在技術上有多差。所以，一個在成熟的設計準則之下開發且設計良好的開源指令集想必能吸引許多供應商長期的支援。

許多先前的開源指令集架構使用GNU通用公共授權條款來鼓勵使用者們允許他們的實作方法被其他人複製或是使用。

設計者們表示，RISC-V指令集是給實際上的電腦使用的，它不像其他學術上的指令集設計，只有為了比較好闡述理念而做最佳化。而RISC-V指令集有一些功能是可以增加電腦速度又可以減少成本和電源使用。這些特色包含，Load/store架構，在CPU裡面的位元表示方法來簡化數據多工器（MUX），以標準為基礎來簡化的浮點數，架構中立的設計和把最高有效位（Most significant bit，MSB）放到固定位置來加速符號擴充（Sign extension）。而sign extension常常就是靜態時序分析裡面的關鍵路徑（Critical timing path）。

RISC-V 指令集是設計來給各式各樣的用途使用的，而它支援三個不同的字組大小，分別是32位元、64位元、128位元以及與這三種字組大小有關的各式各樣的指令子集。而這些指令子集的定義會按照那三個字組大小來做些微的改動。透過這些指令子集的向量處理器與資料中心等級的機櫃式平行電腦/平行運算來幫助嵌入式系統、個人電腦和超級電腦。

該指令集採取不固定的編碼長度而且還可以再擴充，因此在未來，還可以一直加入更多位元的編碼方式。該指令集有特別留空間給128位元的延伸版本，因為60年的產業界經驗顯示在指令集設計領域裡，最無法復原的錯誤就是缺少記憶體定址空間。截至2016年，128位元的指令集仍然刻意地維持在「未凍結 (軟體工程)」的狀態，這是因為到現在為止，人們很少有實際上操作這麼大記憶體的系統的經驗。

然而，RISC-V也可以拿來做學術上的使用。它擁有簡化的整數指令子集允許學生拿來做基本的練習，而整數指令子集就是一個簡單的指令集架構（ISA）讓軟體可以控制研究上的機器。而不定長度的指令集架構也允許擴充功能來滿足研究或是學生練習上的需求。分割出來的特權指令集可以支援在不重新設計編譯器的情況下，進行作業系統方面的研究。RISC-V的開放的智慧財產權允許相關的設計被發布、使用和修改。

## 軟體

一個新的CPU指令集通常的問題是缺少CPU的硬體設計跟軟體的支援。在RISC-V的網站有一個user mode指令集的規格，還有一個用來支援作業系統模式的優先指令集的初步規格。

市面上已經有好幾個使用RISC-V開源架構的CPU設計可以供參考，包括64-bit Berkeley Out of Order Machine（BOOM）、64-bit Rocket、柏克萊設計的五個32-bit Sodor CPU、Clifford Wolf 的 picorv32、Syntacore 的 scr1、蘇黎世聯邦理工學院／波隆納大學的 PULPino （Riscy and Zero-Riscy），以及很多其他的設計。使用三層指令分段的 Sodor CPU 是一個適合嵌入式設計的小型CPU。Rocket可能適用在小型低功耗的個人電腦或其他個人裝置。BOOM 使用了大部分Rocket的架構，但是功能更加強大，適合個人電腦、伺服器或超級電腦。picorv 跟 scr1 都是使用Verilog 設計的 32位元 MCU 等級的 RV32IMC。PULPino的核心使用了一個適合微控制器的簡單的 RV32IMC ISA架構(Zero-Riscy)，以及另外一個更強大的DSP版本 RV32IMFC ISA 可以支援一些嵌入式信號處理的特別 DSP 指令集。

設計軟體包括了一個設計編譯器 Chisel (硬體描述語言)，它可把設計編譯成Verilog代碼。網站上還有測試用的參考資料可以用來驗證設計的正確性。

RISC-V目前提供的軟體有 GNU Compiler Collection （GCC） toolchain（具有偵錯器 GDB）、一套 LLVM toolchain、OVPsim模擬器（以及RISC-V快速處理器模式的軟體參考庫）、Spike 模擬器，以及一套在QEMU上運行的模擬器。

作業系統的支援包括 Linux 核心、FreeBSD，以及 NetBSD，但是監督模式的指令直到版本 1.11 的特權指令集才被標準化，所以這方面的支援還不是正式的。有一個早期的 RISC-V 的FreeBSD 作業系統已經在2016年2月上傳到開放原始碼社群，而且包含在 FreeBSD 11.0。Debian跟Fedora的版本也有人在移植，並且在逐漸穩定中。已經有人做了一個 Das U-Boot 的移植版本。UEFI Spec v2.7 定義了RISC-V UFEI 的規格，而且慧與科技公司的工程師已經做好一個 TianoCore 的移植版本，並且將會上傳到開放原始碼社群。已經有人做好了一個 L4 microkernel family 的移植。還有一個在網頁上用JavaScript寫的 RISC-V Linux 系統模擬器。

## 設計

### 指令子集

RISC-V 指令使用模塊化設計，包括幾個可以互相替換的基本指令集，以及額外可以選擇的擴充指令集。所有基本跟擴充的指令集都是由科技產業、研究機構跟學術界合作開發的。基本指令集規範了指令跟他們的編碼、控制流程、暫存器數目（以及它們的長度）、記憶體跟定址方式、邏輯（整數）運算以及其他。只要有軟體以及一個通用的編譯器的支援，只用基本指令集就可以製作一個簡單的通用型的電腦。

標準的擴充指令集可以搭配所有的基本指令集以及其他擴充指令集，而不會發生衝突。

很多 RISC-V 電腦可能使用精簡擴充指令集來降低電力消耗、程式的大小以及記憶體的使用。未來也有計畫支援hypervisor和虛擬化。

只要再加上一個監督指令集 (S) 的擴充，以及以下 RVGC 指令集，就有足夠的指令可以支援一個 Unix-style 作業系統。

指令集名稱｜描述｜版本｜狀態

基本指令集

RVWMO｜RISC-V 弱記憶體模型｜2.0｜已批准

RV32I｜基本整數指令集, 32位元｜2.1｜已批准

RV32E｜基本整數指令集(嵌入式系統), 32位元, 16 個暫存器｜2.0｜已批准

RV64I｜基本整數指令集, 64位元｜2.1｜已批准

RV64E｜基本整數指令集(嵌入式系統), 64位元, 16 個暫存器｜2.0｜已批准

RV128I｜基本整數指令集, 128位元｜1.7｜開放

標準擴充指令集

M｜整數乘除法標準擴充｜2.0｜已批准

A｜不可中斷指令(Atomic)標準擴充｜2.1｜已批准

F｜單精度浮點標準擴充｜2.2｜已批准

D｜雙精度浮點標準擴充｜2.2｜已批准

Zicsr｜控制與狀態暫存器｜2.0｜已批准

Zifencei｜指令抓取屏障｜2.0｜已批准

G｜所有以上的擴充指令集以及基本指令集的總和的簡稱｜不適用｜不適用

Q｜四精度浮點標準擴充｜2.2｜已批准

L｜十進位浮點標準擴充｜0.0｜開放

C｜壓縮指令標準擴充｜2.0｜已批准

B｜位元運算標準擴充｜1.0｜已批准

J｜動態指令翻譯標準擴充｜0.0｜開放

T｜順序記憶體存取標準擴充｜0.0｜開放

P｜單指令多資料流（SIMD）運算標準擴充｜0.9.10｜開放

V｜向量運算標準擴充｜1.0｜開放

Zk｜標量加密標準擴充｜1.0.1｜已批准

H｜Hypervisor 標準擴充｜1.0｜已批准

S｜Supervisor 標準擴充｜1.12｜已批准

Zam｜非對齊不可中斷指令標準擴充｜0.1｜開放

Zihintpause｜暫停提示｜2.0｜已批准

Zihintntl｜非時間局部性提示｜0.3｜已批准

Zfa｜額外浮點運算指令標準擴充｜1.0｜已批准

Zfh｜半精度浮點標準擴充｜1.0｜已批准

Zfhmin｜半精度浮點最小集標準擴充｜1.0｜已批准

Zfinx｜整數寄存器單精度浮點標準擴充｜1.0｜已批准

Zdinx｜整數寄存器雙精度浮點標準擴充｜1.0｜已批准

Zhinx｜整數寄存器半精度浮點標準擴充｜1.0｜已批准

Zhinxmin｜整數寄存器半精度浮點最小集標準擴充｜1.0｜已批准

Zmmul｜整數純乘法標準擴充｜1.0｜已批准

Ztso｜全存儲排序標準擴充｜1.0｜凍結

為了分辨各種不同的指令組合，非特權指令集標準中訂定了一些專有名詞。首先先指明基本指令集的種類，包括表示 RISC-V 的代號 RV，然後是暫存器的寬度跟其他變化，例如 RV64I 或 RV32E。然後用上表的字母（以及表列的順序）表示用了哪種擴充指令，例如 RV64IMAFD。

基本指令集、擴充整數或浮點運算、多CPU系統使用的同步指令擴充，標準擴充指令MAFD被認為是大部分的一般運算都需要的，所以有一個字母的簡稱 G 用來表示 IMAFDZicsr_Zifencei。

使用嵌入式系統的一個小的32位元電腦可能用 RV32EC，而大型的64位元電腦可以用 RV64GC，即 RV64IMAFDCZicsr_Zifencei 的簡稱。

隨著擴充指令集數量的增加，指令集標準提供了另外一種命名方式，用 Z 字首緊接著字母名稱表示標準擴充，例如 Zifencei 表示指令抓取屏障擴充。

### 寄存器集

RISC-V 有 32 個整數暫存器（在嵌入式版本則是 16 個）。當浮點延伸集被實作的時候，還有 32 個浮點暫存器。除了「記憶體存取指令」之外，一般指令「只能」定址暫存器而無法存取記憶體。

如同有些 RISC 指令集（MIPS, SPARC, DEC Alpha），其中一個暫存器為「零暫存器」（zero register），剩下的暫存器為通用暫存器。在 RISC-V 當中，第一個整數暫存器是零暫存器，儲存數值到零暫存器是沒有作用的，而讀取零暫存器的數值將始終得到 0。使用零暫存器可以讓指令集設計更簡單。比方說，把「暫存器 X 複製到暫存器 Y」 (MOV Y, X)，可以使用「將暫存器 X 與 0 相加後，複製到暫存器 Y」 (ADD Y, X, r0) 實作。

RISC-V 有提供「控制暫存器」及「狀態暫存器」，但是 user-mode 程式只能存取用來「量測效能」及「浮點管理」的部分。

RISC-V 並沒有指令可以儲存和回復（save and restore。註：通常用於 context-switch，中斷處理，或是函數呼叫）多個暫存器。這些設計在 RISC-V 當中，被認為是不必要的，過於複雜的，可能過慢的設計。

### 記憶體存取

就像許多的 RISC 一樣，RISC-V 屬於載入-儲存架構，只有 load 與 store 指令可以存取記憶體。

Load 和 Store 指令可以直接使用程式碼中的常數、在堆疊中的本地變數、或是資料結構中的內容。定址的方式是使用基底暫存器與 12-bit 的 signed 相對地址 (± 2KB)。如果基底暫存器是 0，則資料或是常數可以在低位址，或是高位址（負的相對地址，導致繞回到高的記憶體地址。比方說 ROM 的記憶體地址）。

記憶體的定址單位是 8-bit 的 byte，以 little-endian 存放在記憶體。Load 與 Store 支援的資料長度從 8-bit 到電腦的 word 大小。記憶體存取並不需要對齊到 word 的大小，不過如果有對齊的話，可以增加效能。這項功能可以減小程式碼大小，而且透過軟體的模擬，還可以簡化硬體的設計（會觸發一個「對齊失敗」的中斷）。

和其他類似成功的電腦一樣，RISC-V 也是 little-endian。這稍稍降低了複雜度與成本，因為所有大小的 word 的讀取都遵循一樣的順序。舉例來說，RISC-V 的指令集都是從最低位址的 byte 開始解碼。RISC-V 的規格書保留了實作 big-endian 的可能性。

如同許多的 RISC 指令集一樣，RISC-V 並沒有可以「寫入多個暫存器」的定址模式。比方說：不支援 auto-incrementing（像是 *ptr++ 就無法使用一個指令完成，而必須拆解成「一個 load 指令」及「一個 ADDI 指令」。）

RISC-V 管理 CPU 與 thread 之間的共用記憶體的方式是確保在單一的 thread 當中，記憶體存取指令的執行順序永遠是遵照原本的編譯順序。不過在不同的 thread 以及在 I/O 裝置之間，RISC-V 不保證存取的順序──除非有像 FENCE 這樣的指令出現。

FENCE 保證在其之前的執行結果，一定會被其後的 thread 或 I/O 裝置看到。FENCE 有 8-bit 可以分別指定 memory read/write 與 I/O read/write 的各種組合順序。透過這些組合，FENCE 可以保證記憶體與 memory-mapped I/O 之間的執行順序。比方說：其中一個組合是可以在不影響 I/O 運算的情況下，只保證記憶體的讀取和寫入順序。也就是說，如果 I/O 運算可以和記憶體同時執行的話，FENCE 不會強迫他們之間要互相等待。單一 CPU 上執行單一 thread 的情況下，可以把 FENCE 視作 NOP 指令。

有些 RISC CPUs（例如：MIPS、PowerPC、DLX、Berkeley's RISC-I）在 Load/Save 指令當中使用 16-bit 位移。使用 load upper word 指令來設定最高的 16-bit。這讓最高的 16-bit 資料可以很容易被設定，而不需要位移指令。然而，大部分使用 load upper word 的時機都是為了要載入一個常數（比如：地址）。RISC-V 則是使用類似 SPARC 12-bit 與 20-bit 的設計，而 RISC-V 所採用的 12-bit 設計可以讓指令更小。也就是說，這使得 32-bit 的 load/store 指令，就算需要在 32 個暫存器（需要 5-bit 定址）當中選兩個來用（一共 10-bit），還是有足夠的 bit 數目來支援 RISC-V 的可變長度指令編碼 (variable-length instruction coding)。

註：請參考 32-bit 的 I-type 指令格式，就會發現這個 12-bit 位移比 16-bit 來得優異的地方。這使得 32-bit 的空間當中，扣掉 12-bit 的常數值，以及最低的兩個 bit 為 11（表示這是一個 32-bit 長的指令），再扣掉兩個 5-bit 的暫存器位址，還有將近 8-bit 的空間可以留給 opcode 及 func3。如果是使用 16-bit immediate 的話，會使得空間不夠放下兩個 5-bit 的暫存器位址。舉例來說，SLLI Rd, Rs, immediate (Shift Left Logical Immediate) 將會被迫拆解成兩個指令來完成：LDR Ri, immediate; SLLI Rd, Rs, Ri。

### 立即數

RISC-V 讀取 32-bit 常數與位址是透過設定 upper 20-bit 的指令達到的。LUI 指令（Load Upper Immediate）把（指令中的）20-bit 讀取到暫存器的 31~12 bits 當中。

另一個 AUIPC 指令，也是一樣讀取 upper 20-bit，同時又加上 PC（Program Counter）之後，存放到某個基底暫存器。這個指令讓地址無關代碼能夠支援「相對於程式碼位置的 32-bit 地址」。

這個基底暫存器可以再搭配 12-bit 位移，使用在 Load 與 Store 指令當中。如果需要的話，也可以使用 ADDI 指令，將 lower 12-bit 的常數加到一個暫存器中（註：這樣就完成一個完整的 32-bit 常數讀取）。在 64-bit 架構下，LUI 與 AUIPC 執行的結果會被位元擴充至 64-bit。

有些高速的 CPU 會把一些指令「融合」成一個指令。比如說：上述的 LUI 與 AUIPC 就很適合和 Load/Save 指令一起融合。

### 函數呼叫、跳躍和分支

RISC-V 的函數呼叫 JAL（Jump and Link）把回傳地址放入一個暫存器。由於相較於其他把回傳地址存入堆疊的設計，它省下了一次對堆疊記憶體的存取，所以在許多的處理器設計中是比較快速的。

JAL 有一個 20-bit signed 位移。這個位移會被乘上 2 之後，加到 PC 當中，以產生指向 32 位元指令的相對位址。如果該位址沒有對齊到 32-bit 位址（即不可被 4 整除），CPU 會觸發一個例外。

RISC-V 的 JALR（Jump and Link Register）指令與 JAL 相似，但是 JALR 是把一個 12-bit 的相對位移和某一個暫存器相加，而 JAL 是用 20-bit 的相對位移與 PC 相加。

JALR 的指令格式與使用暫存器的 load/store 指令相似。搭配另一個設定高位 20-bit 的基底暫存器，可以組成一個 32-bit 的地址（可以是絕對位址，例如 LUI；或是相對於 PC 的位址，例如 AUIPC）。（使用零暫存器當基底暫存器，則可以跳到 0 ± 2KB 的絕對位址）

透過使用零暫存器，兩種無條件跳躍：「20-bit PC 相對位址」以及「暫存器為底的 12-bit」，分別使用 JAL 與 JALR 兩個指令來實作。在這個情況下，因為目的地暫存器是零存器，所以回傳位址會被丟棄。

如同許多的 RISC 系統，在一個函數呼叫當中，RISC-V 編譯器必須使用多個指令將暫存器一個一個地存到堆疊當中，然後在函數結束的時候，一個一個地將暫存器自堆疊中還原。RISC-V 沒有「儲存多個」或是「還原多個」暫存器的指令，因為這些指令被認為會讓 CPU 變得過於複雜，而且可能更慢。然而 RISC-V 的這種設計會增加程式大小，而設計者原本的規劃是透過呼叫子程序來減少程式大小。

RISC-V 沒有條件碼暫存器。設計者相信條件碼暫存器會讓高速 CPU 的設計更加複雜，因為它強迫了不同執行階段的指令之間進行交互。這樣的設計會使得高精度計算變得更複雜，有些數值計算需要更多的能量。

相反地，RISC-V 透過比較兩個暫存器來實現分支，指令包括：相等、不相等、小於、無號數小於、大於、無號數大於。十種「比較分支」運算，可以透過反轉運算元順序的方式，只用上述六種指令實作出來。舉例來說：「如果大於時跳躍」可以用運算元順序相反的「如果小於或等於時跳躍」來實作。

這六種比較分支指令具有 12-bit 的有號位移，可以跳到 PC±4KB 的範圍內。

RISC-V 要求 CPU 實作「預設分支預測」（default branch prediction）。如果是往回跳躍 (例如：中的 expr 判斷式），CPU 要預測跳躍會發生，也就是預測 expr 「會」成立。如果是向前跳躍（例如：} 中的 else 部分），CPU 預測這個跳躍會發生，也就是預測 expr 「不會」成立。CPU 判斷往回或向前的方法，是看指令中相對位址的最高位元，也就是有號數（signed bit）的部分：如果是 1，表示是負數，要往回跳躍；如果是 0，表示是正數，要向前跳躍。當然，複雜的 CPU 實作也可以加入更多的分支預測。

RISC-V 手冊也建議軟體（如：編譯器）利用預設分支預測的特性，來避免分支造成 pipeline 被停滯。方法就是利用上一段提到的 signed bit 來「暗示」 CPU 這個分支會不會發生。所以，就是算是簡單又便宜的 CPU，也可以透過編譯器來優化效能。如果有需要，編譯器也可以透過統計等方式來優化效能。

所以，為了避免不必要的分支預測電路（以及不必要的 pipeline 停滯），無條件跳躍不要用「比較分支」來實作。

RISC-V 並不支援「條件執行」指令（conditional execution，註：當某個條件成立的時候，才執行該指令）。設計者宣稱沒有這種設計的 CPU 比較容易設計，而且編譯器在進行優化的時候，也比較不容易假設錯誤。設計者宣稱高速又不照順序執行的 CPU 反正都會同時執行正反兩種結果，之後再丟棄其中一個。他們也宣稱，即使在簡單的 CPU 當中，條件執行其實是比較沒有價值的，不如跳躍預測來的有用。不使用條件執行的程式碼會比較大，但是他們宣稱壓縮指令集在大部分的情況下，可以解決這樣的問題。

許多的 RISC 設計都有「分支延遲槽」（branch delay slot），用來充份使用跳躍指令的下一個記憶體位址，這可以略略增加整體的 CPU 效能。RISC-V 並不支援這個功能，因為他會讓多時序、超純量，以及 long pipeline 變得很複雜。而動態分支預測其實已經做得很好，可以不需要這個功能了。

### 算術和邏輯集

RISC-V 把數學運算指令歸類到一個很小的 I 子集當中，包括：加法、減法、位移、位元運算，及比較分支。這些可以使用軟體的方式去模擬其他大部分的 RISC-V 指令（atomic 運算是值得一提的例外）。RISC-V 目前沒有「數開頭有幾個零」以及一些用來加速軟體浮點運算的位元運算。

整數乘法子集（M 子集）包括：有號數與無號數的乘法與除法。

浮點子集（F 子集）包括單精度運算，以及類似於整數的「比較分支」。它需要額外的 32 個浮點暫存器，這些暫存器是與整數暫存器分開的。雙精度浮點子集（D 子集）一般假設浮點暫存器是 64 位元，而且會與 F 子集一起協作。RISC-V 亦有定義四精度 128-bit 浮點子集（Q 子集）。沒有支援硬體浮點指令的 RISC-V CPU，依舊可以使用軟體的浮點程式庫。

RISC-V 在遇到運算錯誤的時候，並不會拋出異常，包括：overflow、underflow、subnormal 及 divide by zero。相反的，整數運算和浮點運算都會產生合理的預設數值，而且浮點運算指令還會設定狀態位元。Divide-by-zero 可以透過在除法運算之後放置分支指令來發現。這些狀態位元可以也可以被作業系統或是定期的中斷檢查到。

### 原子記憶體操作

RISC-V 支援電腦在多個 CPU 與線程之間共享記憶體。RISC-V 的標準記憶體同步模式是「釋放一致」原則。也就是說，讀取和寫入順序可以被重排，但是有些讀取可以被設定成「獲取」（acquire）運算，必須在其後的存取之前被執行；有些寫入可以被當作「釋放」（release）運算，必須在其之前的存取的後面執行。

基本指令集包含了以FENCE指令提供的最小支援，來保證記憶體存取順序。儘管這已經足夠了（FENCE R, RW 提供「獲取」，FENCE RW, W 提供「釋放」），使用組合操作指令可以更有效率。

原子操作子集（A 子集）支援兩種類型的原子記憶體操作，以實現釋放一致性。首先，它提供了通用的 load-reserved 及 store-conditional 指令。執行加載，並嘗試為其執行緒保留該地址。僅當該保留未被來自另一個來源的干預性寫入破壞時，才會執行對保留地址的 store-conditional。如果寫入成功，則將零放入目標暫存器中；如果失敗，則以非零值表示軟體需要重試操作。在任何一種情況下，保留都會被釋放。

第二組原子指令 AMO（Atomic Memory Operation）執行 Read-modify-write 操作：讀取（可選為讀取-獲取）到目標暫存器，然後執行讀出值和來源暫存器值之間的操作，然後寫入（可選為寫入-釋放）結果。將記憶體屏障設計為可選的，允許了多個操作的組合。每個 AMO 的操作碼中都有「獲取」及「釋放」位元，用於啟用可選的記憶體屏障。

## RISC-V處理器

### 商業實現

#### 阿里巴巴玄鐵910

<image>

阿里巴巴旗下半導體公司平頭哥發布了它的首款 RISC-V 處理器「玄鐵 910」（XuanTie910），名字取自金庸小說《神鵰俠侶》。阿里巴巴稱它是目前性能最強的 RISC-V 處理器，支持16核，主頻 2.5GHz，單核性能達到 7.1 Coremark/MHz。阿里巴巴稱其性能突破源自兩大創新：一是它採用3發射8執行的複雜亂序執行架構，是業界首個實現每周期 2 條記憶體訪問的 RISC-V 處理器；二是它基於 RISC-V 擴展了 50 餘條指令，系統性增強了 RISC-V 的計算、存儲和多核等方面能力。

2021年平頭哥半導體釋出玄鐵C910處理器開源項目，同時還發布出C910的LLVM編譯器源代碼。

#### SiFive公司的RISC-V半導體IP核系列

RISC-V創始人所創辦的SiFive公司提供一系列RISC-V半導體IP核，包含高性能、高效能、低功耗及嵌入式RISC-V處理器。

#### 晶心科技的RISC-V CPU IP系列

晶心提供可配置性高的32/64位元高效能CPU核心，包含DSP、FPU、Vector、超純量 (Superscalar)、亂序執行 (Out-of-Order)及多核心系列。

### 開源實現

#### 中國科學院「香山」

中國科學院計算所在2020年釋出「香山」高性能RISC-V處理器開源項目，香山以Chisel (硬體描述語言)硬體描述語言(Scala領域特定語言)開發。第一版「雁棲湖架構」使用台積電的28nm製程，工作頻率為1.3GHz。

#### 威騰電子「SweRV」

威騰電子在2018年釋出SweRV RISC-V處理器開源項目，SweRV 目標應用環境為儲存裝置控制器，從開源以來已有多家廠商採用。

## 參見

- 精簡指令集 (RISC)
- OpenRISC，以GNU General Public License授權
- OVPsim，RISC-V處理器指令子集、內核和系統的指令精確模擬器。免費為非商業用途提供。
- ARM架構
- 開源運算硬體列表

## 拓展閱讀

- The RISC-V Instruction Set Manual
- Instruction Sets Should Be Free: The Case For RISC-V Whitepaper by Krste Asanović and David A. Patterson
- The RISC-V Instruction Set HotChips 25 (2013)
- The RISC-V Software Ecosystem HPCA 2015, Tutorial
- Rocket Chip HPCA 2015, Tutorial
- The RISC-V Compressed Instruction Set Manual Version 1.9 (draft)

## 外部連結

- Pulpino: A developed, open-source system-on-chip based on RISC-V, 4 August 2016

## 基本資料

- 設計師：加州大學柏克萊分校
- 字長/暫存器資料寬度：32、64、128
- 始創時間：2010年
- 版本：非特權指令集：20191213、特權指令集：20211203
- 形式：RISC
- 類型：載入-儲存架構
- 編碼：不定長度
- 分支預測結構：比較和分支
- 位元組序：小端序
- 擴展名：M、A、F、D、Q、C、P
- 啟用：是
- 通用暫存器：16、32（包括一個始終為零的寄存器）
- 浮點寄存器：32（可選；寬度取決於選用的擴展指令集，可為32、64、128位元）