解剖RISC-V架构(一)
目前就职公司正大力使用RISC-V架构,加速国产化自主芯片的进程。借此契机,学习总结并分享相关知识,多多交流。
CPU基本知识介绍:
- 请注意区分“处理器”和“处理器核”,以及“CPU”和“Core”的概念。
- “处理器核”和“Core”是指处理器内部最核心的部分,是真正的处理器内核。
- “处理器”和“CPU”往往是一个完整的 SoC,包含了处理器内核和其他的设备或者存储器。
- 在现实中大多数文章往往不会严格地遵循两者的差别,时常混用。
- CPU 的灵魂 — 指令集架构(Instruction Set Architecture,ISA)。指令集,顾名思义是一组指令的集合,而指令是指处理器进行操作的最小单元(譬如加减乘除操作或者读/写存储器数据)。
- 至于MCU以及MPU感兴趣可以查找相关资料。
指令集架构(Instruction Set Architecture,ISA)介绍:
指令集架构,有时简称为“架构”或者称为“处理器架构”。有了指令集架构,便可以使用不同的处理器硬件实现方案来设计不同性能的处理器。处理器的具体硬件实现方案称为微架构(Microarchitecture)。虽然不同的微架构实现可能造成性能与成本的差异,但是,软件无须做任何修改便可以完全运行在任何一款遵循同一指令集架构实现的处理器上。因此,指令集架构可以理解为一个抽象层,如下图所示。该抽象层构成处理器底层硬件与运行于其上的软件之间的桥梁与接口,也是现在计算机处理器中重要的一个抽象层。
为了让软件程序员能够编写底层的软件,指令集架构不仅仅是一组指令的集合,它还要定义任何软件程序员需要了解的硬件信息,包括支持的数据类型、存储器(Memory)、寄存器状态、寻址模式和存储器模型等。
综上可见,指令集架构才是区分不同 CPU 的主要标准,这也是 Intel 和 AMD 公司多年来分别推出了几十款不同的 CPU 芯片产品的原因。虽然来自于两个不同的公司,但是它们仍被统称为 x86 架构 CPU。
指令集架构主要分为复杂指令集(Complex Instruction Set Computer,CISC)和精简指令集(Reduced Instruction Set Computer,RISC),两者的主要区别如下:
CISC 不仅包含了处理器常用的指令,还包含了许多不常用的特殊指令。其指令数目比较多,所以称为复杂指令集。
RISC 只包含处理器常用的指令,而对于不常用的操作,则通过执行多条常用指令的方式来达到同样的效果。由于其指令数目比较精简,所以称为精简指令集。
在 CPU 诞生的早期,CISC曾经是主流,因为其可以使用较少的指令完成更多的操作。但是随着指令集的发展,越来越多的特殊指令被添加到CISC指令集中,CISC的诸多缺点开始显现出来。譬如:
典型程序的运算过程中所使用到的80%指令,只占所有指令类型的 20%,也就是说,
CISC指令集定义的指令,只有20%被经常使用到,而有80%则很少被用到。那些很少被用到的特殊指令尤其让CPU设计变得极为复杂,大大增加了硬件设计的
时间成本与面积开销。基于以上原因,自从RISC诞生之后,基本上所有现代指令集架构都选择使用RISC架构。
32 位与 64 位架构介绍:
除了 CISC 与 RISC 之分,处理器指令集架构的位数也是一个重要的概念。通俗来讲,处理器架构的位数是指通用寄存器的宽度,其决定了寻址范围的大小、数据运算能力的强弱。譬如 32 位架构的处理器,其通用寄存器的宽度为 32 位,能够寻址的范围为 232 Byte,即 4GB的寻址空间,运算指令可以操作的操作数为 32 位。
处理器指令集架构的宽度和指令的编码长度无任何关系。并不是说 64 位架构的指令长度为 64 位(这是一个常见的误区)。从理论上来讲,指令本身的编码长度越短越好,因为可以节省代码的存储空间。因此即便在 64 位的架构中,也大量存在 16 位编码的指令,且基本上很少出现过 64 位长的指令编码。综上所述,在不考虑任何实际成本和实现技术的前提下,理论上来讲:
通用寄存器的宽度,即指令集架构的位数越多越好,因为这样可以带来更大的寻址范围和更强的运算能力。
指令编码的长度越短越好,因为这样可以更加节省代码的存储空间。
常见的架构位数分为 8 位、16 位、32 位和 64 位。早期的单片机以 8 位和 16 位为主,如知名的 8051 单片机是使用广泛的 8 位架构。
RISC-V架构简单的背景介绍:
RISC-V 架构主要由美国加州大学伯克利分校(简称伯克利)的 Krste Asanovic 教授、Andrew Waterman 和 Yunsup Lee 等开发人员于 2010 年发明,并且得到了计算机体系结构领域的泰斗 David Patterson 的大力支持。伯克利的开发人员之所以发明一套新的指令集架构,而不是使用成熟的 x86 或者 ARM 架构,是因为这些架构经过多年的发展变得极为复杂和冗繁,并且存在着高昂的专利和架构授权问题。并且修改 ARM 处理器的 RTL 代码是不被支持的,而 x86 处理器的源代码根本不可能获得到。其他的开源架构(譬如 SPARC、OpenRISC)均有着或多或少的问题(感兴趣可以自行查阅资料)。有感于计算机体系结构和指令集架构已经过数十年的发展非常成熟,但是像伯克利这样的研究机构竟然“无米下锅”(选择不出合适的指令集架构供其使用)。伯克利的教授与研发人员决定发明一种全新的、简单且开放免费的指令集架构,于是 RISC-V 架构诞生了。
最初设计它是为了支持计算机体系架构研究和教育,但我们现在希望它也将成为一种标准的自由和开放的行业实现体系架构。
RISC-V(发音为risk-five)是一种新的指令集体系架构(ISA),“V”包含两层意思,一是这是伯克利从 RISC I 开始设计的第五代指令集架构;二是它代表了变化(Variation)和向量(Vectors)。
RISC-V的不同寻常不仅在于它是一个最近诞生的指令集架构(它诞生于最近十年,2011年推出,而大多数其他指令集都诞生于20世纪70到80年代),而且在于它是一个开源的指令集架构。
经过几年的开发,伯克利为 RISC-V 架构开发出了完整的软件工具链以及若干开源的处理器实例,得到越来越多的人的关注。2016 年,RISC-V 基金会(Foundation) 正式成立开始运作。RISC-V 基金会是一个非营利性组织,负责维护标准的 RISC-V 指令集手册与架构文档,并推动 RISC-V 架构的发展。RISC-V 基金会负责维护标准的 RISC-V 架构文档和编译器等 CPU 所需的软件工具链,任何组织和个人可以随时在 RISC-V 基金会网站上免费下载(无须注册)。RISC-V 架构的目标如下:
1. 成为一种完全开放的指令集,可以被任何学术机构或商业组织所自由使用。
2. 成为一种真正适合硬件实现且稳定的标准指令集。
RISC-V基金会(开放的,非营利性质的)的目标是保持RISC-V的稳定性,仅仅出于技术原因缓慢而谨慎地发展它,并力图让它之于硬件如同Linux之于操作系统一样受欢迎。
深入RISC-V架构
RISC-V模块化指令集简介
RISC-V 的指令集使用模块化的方式进行组织,每一个模块使用一个英文字母来表示。
RISC-V 最基本也是唯一强制要求实现的指令集部分是由 I 字母表示的基本整数指令子集。使用该整数指令子集,便能够实现完整的软件编译器。其他的指令子集部分均为可选的模块,具有代表性的模块包括 M/A/F/D/C/P,如下所示:
节选自RISC-V架构与嵌入式开发快速入门 胡振波
节选自The RISC-V Instruction Set Manual Volume I: Unprivileged ISA (RISC-V非特权架构文档)的目录
此外“IMAFD”,也被称为“通用”组合,用英文字母 G 表示。因此 RV32G 表示 RV32IMAFD,同理 RV64G 表示 RV64IMAFD。为了提高代码密度,RISC-V 架构也提供可选的“压缩”指令子集,用英文字母 C 表示。压缩指令的指令编码长度为 16 比特,而普通的非压缩指令的长度为 32 比特。
RISC-V的不同寻常之处,除了在于它是最近诞生的和开源的以外,还在于和几乎所有以往的ISA不同,它是模块化的。它的核心是一个名为RV32I的基础ISA,运行一个完整的软件栈。RV32I是固定的,永远不会改变。这为编译器编写者,操作系统开发人员和汇编语言程序员提供了稳定的目标。模块化来源于可选的标准扩展,根据应用程序的需要,硬件可以包含或不包含这些扩展。这种模块化特性使得RISC-V具有了袖珍化、低能耗的特点,而这对于嵌入式应用可能至关重要。RISC-V编译器得知当前硬件包含哪些扩展后,便可以生成当前硬件条件下的最佳代码。惯例是把代表扩展的字母附加到指令集名称之后作为指示。例如,RV32IMFD将乘法(RV32M),单精度浮点(RV32F)和双精度浮点(RV32D)的扩展添加到了基础指令集(RV32I)中。它们仍是可选的,不会像在增量ISA中那样成为未来所有实现的必要组成部分。 计算机体系结构的传统方法是增量ISA,新处理器不仅必须实现新的ISA扩展,还必须实现过去的所有扩展。感兴趣的查找相关资料。
即使是指令格式也能从一些方面说明 RISC-V 更简洁的 ISA 设计能提高性能功耗比。首先,指令只有六种格式,并且所有的指令都是 32 位长,这简化了指令解码。用于寄存器-寄存器操作的 R 型指令,用于短立即数和访存 load 操作的I型指令,用于访存 store 操作的S型指令,用于条件跳转操作的B 型指令,用于长立即数的U 型指令和用于无条件跳转的J型指令。如下图所示:
为了进一步减少面积,RISC-V 架构还提供一种“嵌入式”架构,用英文字母 E 表示。该架构主要用于追求极低面积与功耗的深嵌入式场景。该架构仅需要支持 16 个通用整数寄存器,而非嵌入式的普通架构则需要支持 32 个通用整数寄存器。
• 嵌入式架构仅支持 32 位架构,在 64 或 128 位架构中不支持该嵌入式架构。即只有RV32E,而没有 RV64E。
• 在嵌入式架构中推荐使用压缩指令子集(由字母 C 表示),即 RV32EC,以增加嵌入式系统中关注的代码密度。
• 在嵌入式架构中不支持浮点指令子集。如果需要选择支持浮点指令子集(F 或者 D),则必须使用非嵌入式架构(RV32I 而非 RV32E)。
• 嵌入式架构仅支持机器模式(Machine Mode)与用户模式(User Mode),不支持其他的特权模式。
• 嵌入式架构仅支持直接的物理地址管理,而不支持虚拟地址。
除了上述模块,还有若干的模块如 L、B、P、V 和 T 等。目前这些扩展大多数还在不断完善和定义中,尚未最终确定,因此不做详细论述。
通用的RV32G 和 RV64G指令集列表
上述图片均节选自The RISC-V Instruction Set Manual Volume I: Unprivileged ISA (RISC-V非特权架构文档)-Chapter 24