RISC-V是基于精简指令集计算原理建立的开放指令集架构,V表示为第五代RISC(精简指令集计算机),表示此前已经出现四代RISC处理器原型芯片。每一代RISC处理器都是在同一人带领下完成,那就是美国加州大学伯克利分校的David A.Patterson教授。它虽然不是第一个开源的指令集(ISA),但它可以免费用于任何制造和销售的RISC-V芯片和软件中。RISC-V第一个被设计成可以根据具体场景,来选择适合指令集的指令集架构。基于RISC-V指令集架构,可以设计服务器CPU、家用电器CPU、工控CPU和小型传感器中的CPU。
RISC-V是一种新兴的开源精简指令集架构,由加州大学伯克利分校在2010年首次发布。RISC-V的出现和迅速发展有其必然的原因,它是建立在现有的体系结构(如X86、ARM、MIPS等)经长期发展所暴露出的种种问题之上,顺应现代信息系统设计需求和体系结构发展趋势而“诞生”的。这些问题包括:
(1)现有体系结构往往缺乏开放性,存在许多知识产权等非技术性问题。例如,Intel公司持有X86架构的专利(自1978年开始),他人使用X86指令集相关技术需要向其支付高昂的授权费用,对X86指令集的模拟也将引发法律上的争议。这种封闭的态势与体系结构发展的开放趋势背道而驰,抬高了系统研发与成果转化的成本,阻碍了技术的推广和进步。而RISC-V具有开源、免费、开放、自由的特点,其基金会总部于2020年3月正式迁往永久中立国瑞士,更是释放了坚持服务全世界的信号,使任何组织和个人都可以不受地缘政治影响、自由平等地使用RISC-V。
(2)现有体系结构经过长期发展,多个版本的迭代积累了许多历史遗留问题。基于各历史版本的技术产品在市场生态中共存,使得新版本的研发必须考虑向后兼容性。例如,AMD64是对32位X86架构的64位扩展,面向64位开发与应用环境;但它同时仍要向后兼容32位甚至16位的X86架构,使早期X86架构下开发的应用同样可以在AMD64系统中正常运行。这种积重难返的状态削弱了现有体系结构的可定制化能力,难以满足现代信息系统对于多样化的工作环境与功能表现的需求。而RISC-V作为一种从零开始设计的新体系结构,在吸收现有各体系结构优点的同时,去除了对历史遗留问题的考量和旧有技术的依赖;RISC-V采用模块化设计,并提供大量自定义编码空间以支持对指令集的扩展,从而允许开发者根据资源、能耗、权限和实时性等不同需求,基于部分特定的模块和扩展指令集进行精细化的系统设计研发,体现了强大的系统可定制化能力。
(3)现有主流架构的文档资源种类繁多、内容冗长,学习与维护的成本较高,使开发者难以在短时间内掌握所需的技术,遇到问题时也不易迅速定位到相关的信息区间。例如,ARMV8-A架构的官方手册仅一卷就多达8 538页;相比之下,RISC-V官方手册仅有两卷共329页,包括238页的指令集手册和91页的特权架构手册,文档精简,学习门槛更低,更有助于研发团队的不断壮大和技术实力的不断进步。因此,对于RISC-V的研究已成为近年来学术界和工业界的一大热点,并涌现了许多突破性成果,如美国西部数据公司研发的基于RISC-V的通用架构SweRV、中国阿里巴巴公司研发的64位高性能嵌入式RISC-V处理器Xuantie-910、中国科学院计算技术研究所在RISC-V中国峰会发布的开源高性能RISC-V处理器核“香山”、上海交通大学开源的基于RISC-V的可信执行环境安全系统“蓬莱”等。
RISC-V作为一种指令集架构,一方面它规定了硬件设备在设计电路、组装元件时应当实现的功能目标,根据指令集的内容,决定运算单元、存储单元等元件的种类、数目、位宽及接线方式。另一方面,它是对硬件能力的一种抽象,提供了机器所能完成的操作种类、地址空间大小、数据格式、访问权限信息;上层软件应用可以将指令集视为硬件运行环境,而无须特别关注具体的硬件实体。
RISC-V的指令集包括基础指令集和扩展指令集两类。RISC-V指令集架构被定义为一个基础指令集和若干可选扩展指令集的组合,并在一种权限模式下进行工作。
RISC-V的基础指令集包含了能够为编译器、汇编器、链接器和操作系统(结合额外的特权操作)等提供必要功能实现的最小指令集合。它们是构筑ISA和软件工具链的骨架,可以围绕它们来构建更多定制的处理器ISA。根据最新的RISC-V规范,RISC-V共有5种基础指令集即RVWMO、RV32I、RV64I、RV32E、RV128I,其分别代表了弱内存次序指令集、32位整数指令集、64位整数指令集、32位嵌入式整数指令集、128位整数指令集。其中,RV32I和RV64I是最主要的两种,分别针对32位和64位工作环境而设计;RV32E是为嵌入式环境设计的一个RV32I的简化版本,RV128I将用于未来的128位环境,而RVWMO描述了RISC-V所使用的内存一致性模型。任何一种RISC-V指令集架构都必须完整地实现一种基础指令集。
RISC-V的扩展指令集用于为ISA提供特定方面的功能操作指令。一个ISA可以选择加入多个扩展指令集。为了使多个指令集能够共存,各指令集的编码空间均按照RISC-V国际基金会(RVI)的编码要求进行了划分,以避免冲突。现有RISC-V扩展指令集主要有24种,涉及乘法和除法扩展(M扩展)、原子指令扩展(A扩展)、单精度浮点扩展(F扩展)、双精度浮点扩展(D扩展)、四精度浮点扩展(Q扩展)和压缩指令扩展等。此外,RISC-V系统设计者还可以根据实际需要,制定其他自定义扩展指令集,并将其加入指令集架构中。
很多RISC-V开发者首次接触的RISC-V CPU core就是Rocket。Rocket Chip Generator可以生成包括Rocket core的一整套SoC,各种参数统统可配置。Rocket Chip是用Chisel开发的。Rocket Chip带MMU支持操作系统,可以运行Linux操作系统。Rocket Chip使用Tilelink总线,支持缓存一致性的一款总线。Rocket是64位CPU core采用经典五级流水,顺序执行,单发射,还支持各种分支预测。BOOM(berkeley out-of-order machine)基于Rocket乱序执行,BOOM有比较详细的文档。Rocket目前较为成熟,基于Rocket核的产品市面上较为广泛。
Hammingbird E203是在国内RISC-V社区芯来科技(武汉)有限公司开发的RISC-V MCU系列。E203是其开源的一款单privilege mode,两级流水的MCU,主打小面积、低功耗,使用Verilog开发。开源的E203在GitHub上其实是一个SoC平台。E203使用自定义的类AXI接口,支持debug spec 0.11。唯一的缺憾是没有官方的verilator环境。
提到开源RISC-V就不能不提Riscy系列,尤其是zero-riscy使用很广泛。Ibex是脱胎于zero-riscy的core,支持RV32IMC及一些Z系列指令,由Low RISC维护。Ibex小巧精悍,文档翔实,学习资料丰富并支持verilator。Ibex支持机器模式和用户模式两种特权模式,可以实现比单机器模式更加丰富的功能。Ibex采用system verilog开发,也支持指令Cache,提高了性能。Ibex使用类TLUL的自定义接口,官方的SoC是PULP。Google的OpenTitan项目也是基于Ibex。
RISC-V指令集架构必须工作在一种确定的权限模式下。根据RISC-V权限规范,目前共有以下4种权限模式:机器模式(machine,M模式)、用户模式(user,U模式)、管理模式(supervisor,S模式)、监视模式(hypervisor,H模式)。其中,H模式暂时处于草案状态,因此通常设计时仅考虑前3种特权模式。RISC-V通过CSR来控制当前的权限模式。通过设置CSR中特定2位的值,可以切换到不同的模式。RISC-V权限模式见表3-7。
表3-7 RISC-V权限模式
(1)机器模式(M模式)。机器模式是RISC-V指令集架构中最高级别的权限模式,具有执行任何机器操作的权限,也是在系统设计中必须被实现的一个工作模式。相比之下,U/S/H等其他权限模式都是可选的,不同的系统可以根据运行环境和实际需要,决定是否支持实现某一级别的权限模式。
(2)用户模式(U模式)。用户模式是RISC-V特权系统中最低级别的权限模式,又被称为“非特权模式”。它通常用于执行来自用户等外部环境的不可信操作,通过对其操作范围的限制来保护系统内的各种资源不受侵害。
(3)管理模式(S模式)。管理模式具有比用户级更高的操作权限,可用于操作一台机器中的敏感资源。RISC-V管理模式需要与机器模式和用户模式共同实现,因此,不能出现系统中只存在S模式而不存在U模式的情况。
(4)监视模式(H模式)。监视模式可用于管理跨机器的资源,或者将机器整体作为组件承担更高级别的任务。如H模式可以协助实现一台机器系统的虚拟化操作。
RISC-V指令集架构具有32位和64位,其寄存器宽度也分别是32位和64位。RISC-V的基本整数指令集中包含32个整数寄存器x0~x31以及一个程序计数器保存当前指令的地址。基本RISC-VISA具有32位固定长度指令,并且必须在32位边界对齐。然而,标准RISC-V编码模式被设计成支持变长指令的扩展,在这个扩展中,每条指令长度可以是16位指令包裹(parcel)长度的整数倍,并且这些指令包裹必须在16位边界对齐。
基本RISC-VISA具有一个小端存储器系统,但是非标准变种可以提供大端或双端存储器系统。指令被保存在存储器中,每个16位包裹以实现的端字节顺序,被保存到一个存储器半字中。包含一条指令的包裹,被保存到递增的半字地址,其中最低寻址的包裹保存着指令规范中最低位的二进制值,也就是说,指令总是按照一系列包裹的小端顺序保存,而不管存储器的端字节顺序。
RISC-V定义的三种模式(U/S/M),均可发生异常。但是只有特权模式(S/M)才能处理异常。当处理器的程序在正常执行当中发生了异常,处理器就会强行跳转到一个指定的PC地址。这个过程定义为“陷阱(trap)”。
RISC-V架构一共定义了4种中断类型:
(1)外部中断。指处理器核的一个单比特输入信号,如果要支持更多的外部中断,就需要在这个单比特信号的基础之上引入中断控制器。
(2)计时器中断。RISC-V架构定义了两个64位的寄存器mtime与mtimecmp。mtime寄存器里的值以恒定频率递增,当mtime的值大于等于mtimecmp的值时,就会产生计时器中断。
(3)软件中断。指软件自己触发的中断。
(4)调试中断。用于调试器实现调试功能。
RISC-V架构中MIE寄存器可以使能或屏蔽外部中断、计时器中断、软件中断,但是调试中断无法屏蔽。RISC-V架构中MIP寄存器可以用来查询:外部中断、计时器中断、软件中断,是否处于等待状态。
RISC-V架构在硬件上没有中断嵌套机制,需要在软件上来实现。因为在进入异常之后,mstatus寄存器的MIE全局中断使能位会被置0(也即中断被全局关闭,再也无法响应新的中断)。如果硬要有中断嵌套的机制,就需要从软件角度在异常服务程序中将MIE全局中断使能位打开,以及嵌套保存上下文。这一设计让处理器硬件设计变得简单,但是软件的设计就变得复杂。