RISC-V

意义

RISC-V的作者们旨在提供数种可以在BSD许可证之下自由使用的CPU设计。该许可证允许像是RISC-V芯片设计等派生作品可以像RISC-V本身一样是公开且自由发行，也可以是闭源或者是专有财产。
相比而言，ARM控股和MIPS科技等商业芯片供应商会对使用其专利者收取高额的许可费用。他们也要求在接收其描述设计优点的文件和指令集前，还需要签署保密协议。许多设计优点为完全专有，从来不会披露给客户。这种保密制度阻碍了公共教育用途和安全审核，以及开发公共、低成本的自由及开放源代码软件编译器和操作系统。
开发一个CPU需要多种专业的设计知识，包括电子逻辑、编译器和操作系统。这种资源在专业工程团队之外很难见到。所以现代且高质量的通用计算机指令集近年来除了学术环境以外并没有在任何地方被广泛使用，甚至没有被阐述。正因如此，许多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的支持，而GCC是一个受欢迎且免费的软件编译器。该ISA有三个开源内核，但尚未制造。
OpenRISC是一款基于DLX的开源ISA，并且具有相关的RISC设计。它完全支持GCC并且有实做在Linux上。但是它很少有商业上的实做，直到2018年下半年SiFive公司10月推出一系列全新CPU设计图产品线应用涵盖5G、网通、存储、增强现实（AR）、虚拟现实（VR）等，其 E系列与U系列的CPU方案已经威胁到ARM(安谋)公司的收费产品并且拥有后者缺乏的64位架构产品。。
ARM公司受到威胁后上线了一个网站riscv-basics.com，列举了对RISC-V的批判，包括：成本、生态系统、碎片化风险、安全性问题、设计验证。但最终迫于业界舆论恶评，ARM关闭了该网站。

基金会

加州柏克莱分校的Krste Asanović教授，发现开放源代码的计算机系统有很多用途。在2010年他决定用三个月的时间来开发并发表一个开放源代码的计算机系统。这个项目是用来帮助包括学术以及工业的用户。柏克莱分校的大卫·帕特森教授也参加了这个项目。帕特森也是原来伯克利分校RISC的设计者，RISC-V只是他众多RISC CPU研究项目的一个．RISC-V项目早期一些经费来自DARPA。
有参与支持RISC-V基金会的公司以及机构包括了超微半导体，晶心科技，英国航太系统，加州大学伯克利分校，BLuespec，Cortus，Google，GreenWaves Technology，慧与科技，华为，IBM，Imperas Software，中国科学院，北京清华大学，印度理工学院，莱迪思半导体，迈伦科技，美高森美，美光科技，英伟达，恩智浦半导体，甲骨文公司，高通，Rambus Cryptography Research，西部数据，SiFive，阿里巴巴集团，红帽公司。
2019年6月，图灵奖得主、RISC-V基金会创始人之一大卫·帕特森（David Patterson）在瑞士宣布，将依托清华-伯克利深圳学院（TBSI），在内部建设RISC-V国际开源实验室（RISC-V International Open Source Laboratory），又称大卫帕特森RIOS图灵实验室。北京清华大学称实验室将瞄准世界CPU产业战略发展新方向和粤港澳大湾区产业创新需求，聚焦于开源指令集CPU研究，建设以深圳为根节点的RISC-V全球创新网络和以技术成果转移为主要使命的非营利组织，全面提升RISC-V生态系至最先进可商用水平。预判届时将面对国际大厂法律层面发起挑战问题上，伯克利加州大学和清华大学的法学院将与之创建联系。

激励要求

RISC设计者们认为指令集因为位于硬件和软件之间，所以是计算机主要的沟通桥梁，因此如果有一个设计良好的指令集是开源而且可以被任何人使用的，就可以让更多的资源能够重复利用，而大大的减少软件的成本。而这样的指令集也会增加硬件供应商市场的竞争，因为硬件供应商们可以挪用更多资源来进行设计，减少处理软件支持的事务。
设计者声称在指令集设计领域里，新的设计准则渐渐变得罕见，而近四十年中，大多数成功的设计变得越来越相似。至于那些失败的指令集，大多数是因为他们的赞助商赚不了钱，而不是因为其指令集在技术上有多差。所以，一个在成熟的设计准则之下开发且设计良好的开源指令集想必能吸引许多供应商长期的支持。
许多先前的开源指令集架构使用GNU通用公共许可协议来鼓励用户们允许他们的实现方法被其他人复制或是使用。
设计者们表示，RISC-V指令集是给实际上的计算机使用的，它不像其他学术上的指令集设计，只有为了比较好阐述理念而做最优化。而RISC-V指令集有一些功能是可以增加计算机速度又可以减少成本和电源使用。这些特色包含，Load/store 架构，在CPU里面的比特表示方法来简化MUX（数据多任务器），以标准为基础来简化的浮点数，架构中立的设计和把MSB(Most significant bit)放到固定位置来加速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，但是监督模式的指令在2016年11月10日还没有标准化，所以这方面的支持还不是正式的。有一个早期的RISC-V 的FreeBSD 操作系统已经在2016年2月上传到开放源代码社群，而且包含在FreeBSD 11.0 。Debian跟Fedora的版本也有人在移植，并且在逐渐稳定中。已经有人做了１个 U-Boot 的移植版本。UEFI Spec v2.7 定义了RISC-V UFEI 的规格，而且惠普公司的工程师已经做好一个TianoCore的移植版本，并且将会上传到开放源代码社群。已经有人做好了一个L4 microkernel family 的移植。还有一个在网页上用JavaScript写的RISC-V Linux 系统模拟器。

寄存器集

RISC-V 有 32 个整数寄存器(在嵌入式版本则是16 个)。当浮点延伸集被实现的时候，还有32 个浮点寄存器。除了“存储器访问指令”之外，一般指令“只能”定址寄存器(注：无法访问存储器）。
如同有些RISC 指令集（MIPS, SPARC, DEC Alpha），其中一个寄存器为“零寄存器”（zero register，注：其值永远为零），剩下的寄存器为通用寄存器。在 RISC 当中，第一个整数寄存器是零寄存器。存储数值到零寄存器是没有作用的。使用零寄存器可以让指令集设计更简单。比方说，把“寄存器 X 复制到寄存器Y” (MOV Y, X)，可以使用“将寄存器X 与 0 相加后，复制到寄存器Y” (ADD Y, X, r0) 实现。 [4]
RISC-V 有提供“控制寄存器”及“状态寄存器”，但是 user-mode 程序只能访问用来“量测性能”及“浮点管理”的部分。
RISC-V 并没有指令可以存储和恢复（save and restore。注：通常用于context-switch，中断处理，或是函数调用）多个寄存器。这些设计在RISC-V 当中，被认为是不必要的，过于复杂的，可能过慢的设计。 [4]

存储器访问

就像许多的RISC 一样， RISC-V 只有 load 与 store 指令可以访问存储器。
存储器的定址单位是8-bit 的 byte。，以 little-endian 存放在存储器。Load 与 Store 支持的数据长度从8-bit 到计算机的word 大小。访问并不需要对齐到word 的大小，不过如果有对齐的话，可以增加性能。这项功能可以减小代码大小，而且透过软件的模拟，还可以简化硬件的设计（会触发一个“对齐失败”的中断。
Load 和 Store 指令可以直接使用代码中的常量，在堆栈中的本地变量，或是数据结构中的内容。定址的方式是使用基底寄存器与12-bit 的 signed 相对地址(+- 2KB)。如果基底寄存器是0，则数据或是常量可以在低地址，或是高地址（负的相对地址，导致绕回到高的存储器地址。比方说ROM 的存储器地址）。
那么，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 指令集一样，RISC-V 并没有可以“写入多个寄存器”的定址模式。比方说：不支持auto-incrementing（像是*ptr++ 就无法使用一个指令完成，而必须拆解成“一个 load 指令”及“一个 addi 指令”。）
和其他类似成功的计算机一样，RISC-V 也是 little-endian。这稍稍降低了复杂度与成本，因为所有大小的读取，都遵循一样的顺序（注：例如 64-bit 与 128-bit 的读取，都是从最小的word 开始读进来，只要一直shift 就可以了）。举例来说，RISC-V 的指令集都是从最低的那个byte 开始解码（注：opcode）。RISC-V 的规格书保留了实现big-endian 的可能性。[4]
有些 RISC CPUs（例如：MIPS, PowerPC, DLX, and 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)。[4]
注：请参考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) 之后，存放到某个基底寄存器。这个指令让PIC 程序（Position-Independent Code）能够支持“相对于代码位置的32-bit 地址”。这个基底寄存器可以再搭配12-bit 位移，使用在Load 与 Store 指令当中（注：访问本地的static 变量?)。如果需要的话，也可以使用addi 指令，将 lower 12-bit 的常量加到一个寄存器中（注：这样就完成一个完整的32-bit 常量读取）。在 64-bit 架构下，LUI 与 AUIPC 运行的结果会被比特扩展至64-bit (sign-extent)。
有些高速的CPU 会把一些指令“融合”成一个指令。比如说：上述的LUI 与 AUIPC 就很适合和Load/Save 指令一起融合。

函数调用、跳跃和分支

RISC-V 的函数调用JAL (Jump and Link) 把回传地址放在一个寄存器当中。由于它省下了一次访问推叠存储器，所以在许多的设计当中是比较快速的。JAL 有一个20-bit signed 位移。这个位移会被乘上2 之后，加到PC 当中。如果没有对齐到32-bit 地址，CPU 会触发一个例外。
RISC-V 的 JALR (Jump and Link Register) 指令和JAL 很像，但是他是把一个12-bit 的相对位移，和某一个寄存器相加。（而 JAL 是用20-bit 相加）
JALR 的指令格式有点像使用寄存器的load/store 指令。搭配另一个设置高20-bit 的基底寄存器，可以组成一个32-bit 的地址（可以是绝对地址，例如 LUI; 或是相对于PC 的地址，例如 AUIPC）。（使用零寄存器当基底寄存器，则是可以跳到0 +- 2KB 的绝对地址）
透过使用零寄存器，底下两种无条件跳跃（其他组语中的JUMP 或 JMP）：“20-bit PC 相对地址”以及“寄存器为底的12-bit”，分别使用JAL 与 JALR 两个指令来实现。在这个情况下，因为目的地寄存器是零存器，所以回传地址会被丢弃。[4]
如同许多的RISC 系统，在一个函数调用当中，RISC-V 编译器必须使用多个指令将寄存器一个一个地存到堆栈当中，然后在函数结束的时候，一个一个地将寄存器自堆栈中还原。RISC-V 没有“存储多个”或是“还原多个”寄存器的指令。因为这些指令被认为会让CPU 变得复杂，而且可能更慢[51]。 然而 RISC-V 的这种设计，会增加程序大小。而设计者原本是希望透过一种特别的routine 来减小程序（注：可以参考这份文件 的 1.7 Optimizing Register Save/Restore Code Size）。
RISC-V 没有旗标寄存器（注：原文是conditional code register，就是指传统的旗标寄存器flag register，用以存放计算结果，给接下来的指令使用，例如：进位旗标carry flag）。设计者相信旗标寄存器会让CPU 设计更加复杂，因为它必须强迫了指令们在不同的运行阶段之间的交互作用。这样的设计，会使得高精度计算变得更复杂，有些数值计算需要更多的能量。[4]
相反地，RISC-V 直接比较两个寄存器，操作数包括：相等，不相等，小于，无号数小于，大于，无号数大于。十个“比较跳跃”操作数，可以透过翻转顺序的方式，可以只用上述六个操作数实现出来。举例来说：“如果大于时跳跃”可以用“小于或等于时跳跃”来实现。
这六个比较跳跃有12-bit 的有号位移，可以跳到PC+-4KB 的范围内。
RISC-V 要求 CPU 实现“默认分支预测” (default branch prediction)。如果是往回跳耀(例如： do {...} while (expr) 中的expr 判断式），CPU 要预测跳跃会发生，也就是预测expr “会”成立。如果是向前跳跃（例如：if (expr) {...} else {...} 中的else 部分），CPU 预测这个跳跃会发生，也就是预测expr “不会”成立。CPU 判断往回或向前的方法，是看指令中相对地址的最高比特，也就是有号数的部分(signed bit)：如果是1，表示是负数，要往回跳跃。如果是0，表示是正数，要向前跳跃。当然，复杂的CPU 实现也可以加入更多的分支预测。
RISC-V 手册也建议软件（如：编译器）利用默认分支预测的特性，来避免分支造成pipeline 被停滞。方法就是利用上一段提到的signed bit 来让“暗示” CPU 这个分支会不会发生。所以，就是算是简单又便宜的CPU ，也可以透过编译器来优化性能。如果有需要，编译器也可以透过统计等方式来优化性能。
所以，为了避免不必要的分支预测电路（以及不必要的pipeline 停滞），无条件跳跃不要用“比较分支”来实现。[4]
RISC-V 并不支持“条件运行”指令（condition execution，注：当某个条件成立的时候，才运行该指令）。设计者宣称没有这种设计的CPU 比较容易设计，而且编译器在进行优化的时候，也比较不容易假设错误。设计者宣称高速又不照顺序运行的CPU 反正都会同时运行正反两种结果，之后再丢弃其中一个。他们也宣称，即使在简单的CPU 当中，条件运行其实是比较没有价值的，不如跳跃预测来的有用。不使用条件运行的代码会比较大，但是他们宣称压缩指令集在大部分的情况下，可以解决这样的问题。[4]
许多的RISC 设计都有“分支延迟槽”（branch delay slot），用来充份使用跳跃指令的下一个存储器地址，这可以略略增加整体的CPU 性能。RSIV-V 并不支持这个功能，因为他会让多时序，超标量，以及 long pipeline 变得很复杂。而动态分支预测其实已经做得很好，可以不需要这个功能了。[4]

算术和逻辑集

RISC-V 把数学运算指令归类到一个很小的I 子集当中，包括：加法，减法，位移，位操作，及比较跳跃。这些可以使用软件的方式去模拟其他大部分的RISC-V 指令（atomic 运算是值得一提的例外）。RISC-V 当前没有“数开头有几个零”以及一些用来加速软件浮点运算的位操作。
整数乘法子集（M 子集）包括：有号数与无号数的乘法与除法。
浮点子集包括单精度运算，以及类似于整数的“比较跳跃”。它需要额外的32 个浮点寄存器，这些是与整数寄存器分开的。双精度浮点子集一般假设浮点寄存器是64 比特，而且会与F 子集一起协作。RISC-V 亦有定义四精度128-bit 浮点指令。没有支持硬件浮点指令的CPU，依旧可以使用软件的浮点程序库。
RISC-V 在遇到运算错误的时候，并不会发出例外，包括：overflow, underflow, subnormal 及 divide by zero。相反的，整数运算和浮点运算都会产生合理的默认数值，然后设置状态比特。Divide-by-zero 可以用一个跳跃指令来处理。这些状态比特可以也可以被操作系统或是定期的中断检查到。

原子内存操作

RISC-V 支持多个CPU 与 thread。其标准存储器同步模式是“释放一致”原则。也就是说，读取和写入顺序可以重排，但是有些读取可以被设置成“获取”运算，会在其后的访问之前被运行，有些写入可以被当作“释放”运算，必须在其之前的访问的后面运行。
基本指令当中包含了最少的支持，使用 fence 指令来保证存储器访问顺序。尽管这很简单（fence r/rw 提供“获取”，fence rw/w 提供“释放”），组合起来还是可以很有效率。

RISC-V处理器

阿里巴巴旗下半导体公司平头哥发布了它的首款RISC-V 处理器玄铁910（XuanTie910），名字取自金庸小说《神雕侠侣》。阿里巴巴称它是当前性能最强的RISC-V 处理器，支持16核，主频2.5GHz，单核性能达到7.1 Coremark/MHz。阿里巴巴称其性能突破源自两大创新：一是它采用3发射8执行的复杂乱序执行架构，是业界首个实现每周期2 条内存访问的RISC-V 处理器；二是它基于RISC-V 扩展了50 余条指令，系统性增强了RISC-V 的计算、存储和多核等方面能力。