2.1简单就是美——RISC-V架构的设计理念
2.1.1无病一身轻——架构的篇幅
1.关于RISC-V架构的文档可以到此网址下载https://riscv.org/technical/specifications/。
2.1.2能屈能伸——模块化的指令集
2.RISC-V 架构相比其他成熟的商业架构,最大的不同在于它是一个模块化的架构。因为RISC-V 架构不仅短小精悍,而且其不同的部分还能以模块化的方式组织在一起,从而试图 通过一套统一的架构满足各种不同的应用。
例如针对小 面积、低功耗的嵌入式场景,用户可以选择 RV32IC 组合的指令集,仅使用机器模式(Machine Mode);而针对高性能应用操作系统场景,则可以选择例如 RV32IMFDC 的指令集,使用机 器模式(Machine Mode)与用户模式(User Mode)两种模式。
2.1.3浓缩的都是精华——指令的数量
2.2RISC-V架构简介
2.2.1模块化的指令集
1.RISC-V的指令集使用模块化的方式进行组织。使用整数指令子集(以字母I结尾),便能狗实现完整的软件编译器。其他的指令集均为可选的模块,具有代表性的模块包括M/A/F/D/C。
2.以上模块的一个特定组合“IMAFD”也称为“通用组合”,用英文字母G表示。
3.为了提高代码密度,RISC-V架构提供可选的“压缩”指令子集,用英文字母C表示。压缩指令的编码长度为16位,而普通的非压缩指令的编码长度为32位。
4.为了进一步减少面积,RISC-V 架构还提供一种“嵌入式”架构,用英文字母 E 表示。 该架构主要用于追求极低面积与功耗的深嵌入式场景。该架构仅需要支持 16 个通用整数寄存器,而非嵌入式的普通架构则需要支持 32 个通用整数寄存器。
2.2.2可配置的通用寄存器组
5.RISC-V 架构支持 32 位或者 64 位的架构,32 位架构由 RV32 表示,其每个通用寄存器 的宽度为 32 比特;64 位架构由 RV64 表示,其每个通用寄存器的宽度为 64 比特。
6.整数寄存器x0是为常数0预留的。
7.如果使用浮点模块(F 或者 D),则需要另外一个独立的浮点寄存器组,包含 32 个通用 浮点寄存器。如果仅使用 F 模块的浮点指令子集,则每个通用浮点寄存器的宽度为 32 比特; 如果使用了 D 模块的浮点指令子集,则每个通用浮点寄存器的宽度为 64 比特。
2.2.3规整的指令编码
2.2.4简洁的存储器访问指令
8.RISC-V 架构使用专用的存储器读(Load)指令和存储器写(Store)指令访问存储器(Memory),其他的普通指令无法访问存储器。
存储器访问 的基本单位是字节(Byte)。RISC-V 的存储器读和存储器写指令支持一个字节(8 位)、半字 (16 位)、单字(32 位)为单位的存储器读写操作。如果是 64 位架构还可以支持一个双字(64 位)为单位的存储器读写操作。
9.RISC-V 架构推荐使用地址对齐的存储器读写操作,但 是也支持地址非对齐的存储器操作 RISC-V 架构。
10.RISC-V 架构仅支持小端格式。
11.RISC-V 架构的存储器读和存储器写指令不支持地址自增自减的模式。
12.RISC-V 架构采用松散存储器模型(Relaxed Memory Model),松散存储器模型对于 访问不同地址的存储器读写指令的执行顺序不作要求,除非使用明确的存储器屏障 (Fence)指令加以屏蔽。
2.2.5高效的分支跳转指令
13.RISC-V 架构有两条无条件跳转指令(Unconditional Jump),即 jal 指令与 jalr 指令。跳 转链接(Jump and Link)指令——jal 指令可用于进行子程序调用,同时将子程序返回地址 存在链接寄存器(Link Register,由某一个通用整数寄存器担任)中。
跳转链接寄存器(Jump and Link-Register)指令——jalr 指令能够用于子程序返回指令,通过将 jal 指令(跳转进入子程 序)保存的链接寄存器用于 jalr 指令的基地址寄存器,则可以从子程序返回。
14.RISC-V 架构有 6 条带条件跳转指令(Conditional Branch),这种带条件的跳转指令跟普通的运算指令一样直接使用两个整数操作数,然后对其进行比较。如果比较的条件满足,则 进行跳转,因此此类指令将比较与跳转两个操作放在一条指令里完成。
15.对于没有配备硬件分支预测器的低端 CPU,为了保证其性能,RISC-V 的架构明确要求 采用默认的静态分支预测机制。
如果是向后跳转的条件跳转指令,则预测为“跳”;如果 是向前跳转的条件跳转指令,则预测为“不跳”,并且 RISC-V 架构要求编译器也按照这种 默认的静态分支预测机制来编译生成汇编代码。
16.RISC-V 架构特地定义了所有的带条件跳 转指令跳转目标的偏移量(相对于当前指令的地址)都是有符号数,并且其符号位被编码在 固定的位置。
2.2.6简洁的子程序调用
17.RISC架构中程序调用子函数的过程如下:
(1)进入子函数之后需要用存储器写(Store)指令来将当前的上下文(通用寄存器等的 值)保存到系统存储器的堆栈区内,这个过程通常称为“保存现场”。
(2)在退出子程序时,需要用存储器读(Load)指令来将之前保存的上下文(通用寄存 器等的值)从系统存储器的堆栈区读出来,这个过程通常称为“恢复现场”。
2.2.7无条件码执行
18.RISC-V 架构则放弃使用这种带“条件码”指令的方式,对于任何的条件判断都使用普 通的带条件分支跳转指令。
例如在指令编码的头几位表示的是条件 码(Conditional Code),只有该条件码对应的条件为真时,该指令才被真正执行。
2.2.8无分支延迟槽
19.RISC-V架构放弃了分支延迟槽。
分支延迟槽 就是指在每一条分支指令后面紧跟的一条或者若干条指令不受分支跳转的影响,不管分支是否 跳转,这后面的几条指令都一定会被执行。
2.2.9零开销硬件循环指令
20.RISC-V架构放弃了该指令。
很多 RISC 架构还支持零开销硬件循环(Zero Overhead Hardware Loop)指令,其思想 是通过硬件的直接参与,设置某些循环次数寄存器(Loop Count),然后可以让程序自动地 进行循环,每一次循环则循环次数寄存器自动减 1,这样持续循环直到循环次数寄存器的值 变成 0,则退出循环。
2.2.10简洁的运算指令
21.最基本的整 数指令子集(I 字母表示)支持的运算包括加法、减法、移位、按位逻辑操作和比较操作。
22.整数乘除法指令子集(M 字母表示)支持的运算包括有符号或者无符号的乘法和除法操作。乘法操作能够支持两个 32 位的整数相乘得到一个 64 位的结果;除法操作能够支持两个 32 位的整数相除得到一个 32 位的商与 32 位的余数。
23.单精度浮点指令子集(F 字母表示)与双精度浮点指令子集(D 字母表示)支持的运算包括浮点加减法、乘除法、乘累加、开平方根和比较等操作,同时提供整数与浮点、单精度与双精度浮点之间的格式转换操作。
24.很多 RISC 架构的处理器在运算指令产生错误之时,例如上溢(Overflow)、下溢 (Underflow)、非规格化浮点数(Subnormal)和除零(Divide by Zero),都会产生软件异常。 RISC-V 架构的一个特殊之处是对任何的运算指令错误(包括整数与浮点指令)均不产生异 常,而是产生某个特殊的默认值,同时设置某些状态寄存器的状态位。
2.2.11优雅的压缩指令子集
2.2.12特权模式
25.RISC-V 架构定义了 3 种工作模式,又称为特权模式(Privileged Mode)。
Machine Mode:机器模式,简称 M Mode。
Supervisor Mode:监督模式,简称 S Mode。
User Mode:用户模式,简称 U Mode。
26.RISC-V 架构定义 M Mode 为必选模式,另外两种为可选模式,通过不同的模式组合可 以实现不同的系统。
27.RISC-V 架构也支持几种不同的存储器地址管理机制,包括对于物理地址和虚拟地址的 管理机制,使得 RISC-V 架构能够支持从简单的嵌入式系统(直接操作物理地址)到复杂的 操作系统(直接操作虚拟地址)的各种系统。
2.2.13CSR
28.RISC-V 架构定义了一些控制和状态寄存器(Control and Status Register,CSR),用于配 置或记录一些运行的状态。CSR 寄存器是处理器核内部的寄存器,使用自己的地址编码空间 和存储器寻址的地址区间完全无关系。
2.2.14中断和异常
2.2.15P扩展指令子集
2.2.16矢量指令子集
2.2.17自定义指令扩展
29.除了上述阐述的模块化指令子集的可扩展、可选择,RISC-V 架构还有一个非常重要的 特性,那就是支持第三方的扩展。用户可以扩展自己的指令子集,RISC-V 预留了大量的指 令编码空间用于用户的自定义扩展,同时还定义了 4 条 Custom 指令可供用户直接使用。每 条 Custom 指令都预留了几个比特位的子编码空间,因此用户可以直接使用 4 条 Custom 指 令扩展出几十条自定义的指令。