目录
RISC-V指令集架构介绍
通用寄存器模型
RISC-V特权级
RISC-V指令集描述
RISC-V总结
RISC-V指令集架构介绍
RISC-V(英文发音为"risk-five")是一个全新的指令集架构,该架构最初由美国加州大学伯克利分校的EECS部门的计算机科学部门的Krste Asanovic教授、Andrew Waterman和Yunsup Lee等开发人员于2010年发明。 其中"RISC"表示精简指令集,而其中"V"表示伯克利分校从RISC I开始设计的第五代指令集。
2010年,加州大学伯克利分校的研究团队分析了ARM、MIPS、SPARC、X86等多种指令集,发现这些指令集不仅复杂度不断提升,且还存在知识产权风险,而处理器架构种类和处理能力并无直接关联。针对以上问题,该小组设计并推出了一套基于BSD协议许可的免费开放的指令集架构RISC-V,其原型芯片也于2013年1月成功流片。RISC-V指令集具有性能优越,彻底免费开放两大特征。RSIC-V的设计目标是能够满足从微控制器到超级计算机等各种复杂程度的处理器需求,支持从FPGA、ASIC乃至未来器件等多种实现方式,同时能够高效地实现各种微结构,支持大量定制与加速功能,并与现有软件及编程语言可良好适配。RISC-V产业生态正进入快速发展期。加州大学伯克利分校在2015年成立非盈利组织RISC-V基金会,该基金会旨在聚合全球创新力量共同构建开放、合作的软硬件社区,打造RISC-V生态系统。三年多来,谷歌、高通、IBM、英伟达、NXP、、西部数据、Microsemi、中科院计算所、麻省理工学院、华盛顿大学、英国宇航系统公司等100多个企业和研究机构先后加入了RISC-V基金会。
RISC-V基金会负责维护RSIC-V指令集标准手册与架构文档,每年RISC-V基金会都会举办各种专题讨论会和全球活动,将广阔的生态系统聚集在一起,讨论当前和未来RISC-V项目和实施,以促进RISC-V阵营的交流和发展。一款指令集架构能否取得成功,很大程度依赖于软件生态环境。当前可用的RISC-V软件工具包括GNU编译器集合(GCC工具链、GDB调试器),LLVM工具链,OVPsim仿真器(以及RISC-V快速处理器模型库),Spike仿真器和QEMU模拟器。当前支持该指令集架构的操作系统包括FreeRTOS、SylixOS、RT-Thread、Linux等。RTRISC-V架构在短时间内还无法撼动x86和ARM架构,但是随着越来越多的公司和项目采用RSIC-V架构的处理器,相信RSIC-V的软件生态会逐渐壮大起来。
通用寄存器模型
RISC-V具有32个整数寄存器x0~x31,其中31个通用寄存器x1~x31,它们保存了整数数值,寄存器x0是硬件连线的常数0。当实现浮点扩展时具体32个浮点寄存器f0~f31。对于RV32,其x寄存器是32位宽度的,对于RV64,它们是64位宽度的。
其中RISC-V寄存器调用约定如下图:
RISC-V调用约定尽可能在寄存器中传递参数,其多达8个整数寄存器a0-a7,和多达8个个浮点寄存器fa0-fa7用于这个目 的。 函数的返回值存放在整数寄存器a0和a1、浮点寄存器fa0和fa1中。返回值包含1个或者2个浮点值的结构体时候通过浮点寄存器返回,其他返回值能放入a0和a1。更大的返回值都全部通过存储器返回,调用者分配这些存储器区域,并将它作为第一个隐藏参数传递给被调用者。在标准RISC-V调用约定中,栈是向下增长并且栈指针总是对齐到16字节。
除了参数寄存器和返回值寄存器之外,7个整数寄存器t0-t6和12个浮点寄存器ft0-ft11是临时寄存器,它们在调用过程中被破坏,如果后面还有使用的话,在调用者中必须先保存。12个整数寄存器s0-s11和12个浮点寄存器fs0-fs11在调用过程后被保持不变,如果需要使用的 话,在被调用者中必须保存。
RISC-V特权级
RISC-V定义了四种特权级模式。不同的特权级包含多个 CSR(control and status register,控制和状态寄存器)寄存器。四种特权级信息如下表1.1:
特权级被用于在不同的软件栈部件之间提供保护,试图执行当前特权模式不允许的操作,将导致一个异常的产生。机器级是*特权,也是RISC-V硬件平台唯一必须的特权级。运行于机器模式(M-mode)下的代码是固有可信的,因为它可以在低层次访问机器的实现。用户模式(U-mode)和管理员模式(S-mode)被分别用于传统应用程序和操作系统,而 Hypervisor 模式(H-mode)则是为了支持虚拟机监视器。
所有硬件实现必须提供 M-mode,因为这是唯一的模式可以不受限制地访问整个机器。 最简单的 RISC-V 实现可以仅提供M-mode,虽然这样做不能为防止不正确的、恶意应用代码提供保护。许多RISC-V实现还支持至少一个用户模(U-mode)以对系统的其他部分进行 保护,防止被应用程序代码破坏。
标准 RISC-V ISA 设置了一个 12 位的编码空间(csr[11:0])可用于 4096 个 CSR。根据约定,CSR 地址的高 4 位(csr[11:8])用于编码CSR根据特权级读写的可访问性。最高2位(csr[11:10])指示这个寄存器是否是可以读/写(00、01或者10),还是只读 的(11)。后面 2 位(csr[9:8])指示了能够访问这个 CSR 所需要的最低特权级(用户级是 00, 管理员级是 01)。
试图访问一个不存在的CSR将产生一个非法指令异常。试图访问一个没有相应特权的CSR或者写一个只读寄存器,也将产生一个非法指令异常。一次读/写寄存器可能包含了某 些位是只读的,此种情况下,写入只读位被忽略。
CSR相关寄存器相关描述可参考特权级指令手册,其中机器模式寄存器如下图:
用于读取CSR的汇编语言伪指令CSRR rd, csr被编码为CSRRS rd, csr, x0。用于写CSR的汇编语言伪指令CSRW csr, rs1 被编码为 CSRRW x0, csr, rs1,而伪指令 CSRWI csr, zimm 被编码 为 CSRRWI x0, csr, zimm。
RISC-V指令集描述
RISC-V 被设计成可以支持丰富的定制化和特殊化。基本整数 ISA 可被一个或者多个可选指令集扩展进行增强,但是基本整数指令集不能被重新定义。我们将RISC-V指令集扩展分为标准扩展和非标准扩展。标准扩展一般都是有用的,并且与其它的标准扩展并不冲突。非标准扩展是高度特殊化的,并可能与其它的标准扩展或者非标准扩展冲突。指令集扩展根据基本整数指令集宽度不同,可能有轻微的功能差异。RISC-V为基本指令和指令集扩展开发了一个命名规则,其命令规则如下图。
为了支持更一般的软件开发,定义了一组标准扩展,提供乘法/除法、原子操作以及单精度、双精度浮点算术。基本整数 ISA 被命名为“I”(依据整数寄存器宽度不同,前缀 RV32 或者 RV64),其中包含了整数计算指令、整数 load、整数 store 和控制流指令,并且在所有RISC-V实现中,都是必须的。标准整数乘法和除法扩展被命名为“M”,其中增加了对保存在整数寄存器中的值进行乘法和除法的指令。标准原子指令扩展被命名为“A”,其中增加了对存储器进行原子的读、修改和写操作的指令,以支持处理器间的同步。标准单精度浮点 扩展,被命名为“F”,增加了浮点寄存器、单精度计算指令、单精度 load 和 store 指令。标准双精度浮点扩展,被命名为“D”,扩展了浮点寄存器,并增加了双精度计算指令、load 和 store 指令。一个基本整数内核加上这四个标准扩展(“IMAFD”),被缩写为“G”,它提供 了一个通用的标量指令集。RV32G 和 RV64G 现在是我们编译器工具链的缺省目标机器。 下图描述了这些扩展以及其他计划中的标准 RISC-V 扩展。
名称 | 描述 | 版 | 状态[a] |
---|---|---|---|
基础 | |||
RV32I | 基本整数指令集,32位 | 2.0 | 冻结的 |
RV32E | 基本整数指令集(嵌入式),32位,16个寄存器 | 1.9 | 打开 |
RV64I | 基本整数指令集,64位 | 2.0 | 冻结的 |
RV128I | 基本整数指令集,128位 | 1.7 | 打开 |
延期 | |||
M | 整数乘法和除法的标准扩展 | 2.0 | 冻结的 |
A | 原子指令的标准扩展 | 2.0 | 冻结的 |
F | 单精度浮点的标准扩展 | 2.0 | 冻结的 |
D | 双精度浮点的标准扩展 | 2.0 | 冻结的 |
G | 基础和上述扩展的简写 | N / A | N / A |
Q | 四精度浮点的标准扩展 | 2.0 | 冻结的 |
L | 十进制浮点的标准扩展 | 0.0 | 打开 |
C | 压缩指令的标准扩展 | 2.0 | 冻结的 |
B | 位操作的标准扩展 | 0.36 | 打开 |
J | 动态翻译语言的标准扩展 | 0.0 | 打开 |
T | 事务性内存的标准扩展 | 0.0 | 打开 |
P | Packed-SIMD指令的标准扩展 | 0.1 | 打开 |
V | 矢量运算的标准扩展 | 0.2 | 打开 |
N | 用户级中断的标准扩展 | 1.1 | 打开 |
基本RISC-V ISA具有32位固定长度指令,并且必须在32位边界对齐。然而,标准RISC-V编码模式被设计成支持变长指令的扩展,在这个扩展中,每条指令长度可以是16位指令包裹长度的整数倍,并且这些指令包裹必须在16位边界对齐。标准压缩ISA扩展,通过提供压缩的16位指令,减少了代码大小,并放松了对齐要求,允许所有指令(16 位和 32 位)对齐到任意 16 位边界,以提高代码密度。
标准RISC-V指令长度编码约定。所有基本ISA中的32位指令的最低2位被设置为11。可选的压缩16位指令集扩展中的指令,最低 2 位被设置为 00、01 或者 10。 超过32位的标准指令集扩展,在低位有额外的位被设置为 1,48 位、64 位长度约定如图 1.1 所示。指令长度在 80 位到 176 位之间的长度信息,被编码到一个 3 位的字段[14:12]中,给 出了 16 位字的数量,加上最开始的 5×16 位字。位[14:12]编码为 111,保留给未来更长的 指令编码。
在基本ISA中,有四种核心指令格式(R/I/S/U),如图 2.2所示。所有的指令都是固定 32位长度的,并且在存储器中必须在4字节边界对齐。当发生一个条件分支或者无条件转移 而且目标地址不是对齐到4字节时,将会产生一个指令地址不对齐的异常。如果条件分支没 有发生(not taken),那么将不会产生一个取指不对齐异常。
在所有格式中,RISC-V将源寄存器(rs1和rs2)和目标寄存器(rd)固定在同样的位置,以简化指令译码。在指令中,立即数被打包,朝着最左边可用位的方向,并且是分配好的,以减少硬件复杂度。特别地,所有立即数的符号位总是在指令的第31位,以加速符号扩 展电路。
一般操作系统底层开发人员才涉及编写汇编代码,且一般使用编译器提供伪指令进行编程,RISC-V支持的伪指令如下图。掌握下面的伪指令已经足够满足汇编程序员进行汇编代码编写。
表21.2 RSIC-V CSR伪指令
RISC-V总结
开放而免费的RISC-V架构已经吸引了国内外一大批知名企业、科研院校和初创公司致力于开发基于RISC-V指令集架构的处理器,其中就包括谷歌、惠普、Oracle和西部数据等。当前国内还处在起步阶段,国内很多科研院校和初创公司都基于一些开源的RISC-V IP核或者SiFive公司的开源SOC上做增量开发。
元峰公司作为其中的一员致力于RISC-V嵌入式实时操作系统及其开发环境的生态搭建,当前主要工作是移植FreeRTOS操作系统到SiFive公司的HiFive1开发板上并提供配套的开发环境。开发环境提供基本的编译、运行和调试环境,包括OpenOCD、Jlink等硬件调试环境,并提供FreeRTOS操作系统项目用于用户开发FreeRTOS应用。后续还将支持RT-Thread、SylixOS等操作系统并集成到开发环境,方便用于开发调试。
后续将陆续编写<<基于HiFive1开发板的RISC-V开发环境搭建>>以及<<如何将FreeRTOS操作系统移植到RISC-V体系结构>>。