无忧启动论坛

 找回密码
 注册
搜索
WEPE笔记本电脑手机维修小包 IT发烧友的必备工具最纯净的「微PE装机优盘」UEPON大师作品卡瑞飞系统和装机二合一超级U盘
无忧启动论坛唯一网址:bbs.wuyou.net系统gho:最纯净好用系统下载站广告联系 QQ:184822951 微信:wuyouceo
查看: 1505|回复: 26

整理有关 RISC-V 的资料

  [复制链接]
发表于 2019-4-12 11:32:25 | 显示全部楼层 |阅读模式
本帖最后由 不点 于 2019-4-12 12:02 编辑

先贴一篇文章:《终于有人把 RISC-V 讲明白了》

邓佳佳 发表于 2018-03-27 http://m.elecfans.com/article/653167.html

0、 RISC-V 和其他开放架构有何不同

如果仅从“免费”或“开放”这两点来评判,RISC-V 架构并不是第一个做到免费或开放的处理器架构。

在开始之前,我们先通过论述几个具有代表性的开放架构,来分析 RISC-V 架构的不同之处以及为什么其他开放架构没能取得足够的成功。

0.1 平民英雄——OpenRISC

OpenRISC 是 OpenCores 组织提供的基于 GPL 协议的开放源代码 RISC 处理器,具有以下特点:

    采用免费开放的 32/64 位 RISC 架构。
    用 Verilog HDL(硬件描述语言)实现了基于该架构的处理器源代码。
    具有完整的工具链。

OpenRISC 被应用到很多公司的项目之中。可以说,OpenRISC 是应用非常广泛的一种开源处理器实现。
OpenRISC 的不足之处在于其侧重于实现一种开源的 CPU Core,而非立足于定义一种开放的指令集架构,因此其架构的发展不够完整,指令集的定义也不具备上节中提到的 RISC-V 架构的优点,更加没有上升到成立专门的基金会组织的高度。OpenRISC 更多的时候被认为是一个开源的 Core,而非一种优美的指令集架构。此外,OpenRISC 的许可证为 GPL,这意味着所有的指令集改动都必须开源(而 RISC-V 则无此约束)。


0.2 豪门显贵——SPARC

SPARC 架构作为经典的 RISC 微处理器架构之一,SPARC 最早于 1985 年由 Sun 电脑所设计。SPARC 也是 SPARC 国际公司的注册商标之一,这家公司于 1989 年成立,目的是向外界推广 SPARC 架构以及为该架构进行兼容性测试。为了推广 SPARC 的生态系统,SPARC 国际公司将标准开放,并授权多家生产商采用,包括德州仪器、Cypress 半导体和富士通等。由于 SPARC 架构也对外完全开放,因此,也出现了完全开放源码的 LEON 处理器。不仅如此,Sun 公司还于 1994 年推动 SPARC v8 架构成为 IEEE 标准(IEEE Standard 1754-1994)。

由于 SPARC 架构的初衷是面向服务器领域而设计,其最大的特点是拥有一个大型的寄存器窗口,符合 SPARC 架构的处理器需要实现从 72 到 640 个之多的通用寄存器,每个寄存器宽度为 64 bits,组成一系列的寄存器组,称之为寄存器窗口。

这种寄存器窗口的架构,由于可以切换不同的寄存器组快速地响应函数调用与返回,因此,能够产生非常高的性能,但是这种架构由于功耗面积代价太大,而并不适用于 PC 与嵌入式领域处理器。而 SPARC 架构也不具备模块化的特点,使得用户无法裁剪和选择。很难作为一种通用的处理器架构对商用的 x86 和 ARM 架构形成替代。

设计这种超大服务器 CPU 芯片又非普通公司与个人所能涉足,而有能力设计这种大型 CPU 的公司也没有必要投入巨大的成本来挑战 x86 的统治地位。随着 Sun 公司的衰弱,SPARC 架构现在基本上退出了人们的视野。感兴趣的读者请在网络上自行搜索文章《再见 SPARC 处理器,再见 Sun》。


0.3 名校优生——RISC-V

关于 RISC-V 在伯克利大学诞生的经历,本节在此不做重复赘述。

因为多年来在 CPU 领域已经出现过多个免费或开放的架构,很多高校也在科研项目中推出过多种指令集架构。因此,当笔者第一次听说 RISC-V 之时,以为又是一个玩具,或纯粹学术性质的科研项目而不以为意。

直到笔者亲自通读了一遍 RISC-V 的架构文档,不禁为其先进的设计理念所折服。同时,RISC-V 架构的各种优点也得到了众多专业人士的青睐好评和众多商业公司的相继加盟。并且 2016 年 RISC-V 基金会的正式启动在业界引起了不小的影响。如此种种,使得 RISC-V 成为至今为止最具备革命性意义的开放处理器架构。

1、简单就是美——RISC-V 架构的设计哲学

RISC-V 架构作为一种指令集架构,在介绍细节之前,让我们先了解设计的哲学。所谓设计的“哲学”便是其推崇的一种策略,譬如说我们熟知的日本车的设计哲学是经济省油,美国车的设计哲学是霸气外露等。RISC-V 架构的设计哲学是什么呢?是“大道至简”。

笔者最为推崇的一种设计原则便是:简单就是美,简单便意味着可靠。无数的实际案例已经佐证了“简单即意味着可靠的”真理,反之越复杂的机器则越容易出错。

所谓大道至简,在 IC 设计的实际工作中,笔者曾见过最简洁的设计实现安全可靠,也曾见过最繁复的设计长时间无法稳定收敛。最简洁的设计往往是最可靠的,在大多数的项目实践中一次次的得到检验。

IC 设计的工作性质非常特殊,其最终的产出是芯片,而一款芯片的设计和制造周期均很长,无法像软件代码那样轻易升级和打补丁,每一次芯片的改版到交付都需要几个月的周期。不仅如此,芯片的一次制造成本费用高昂,从几十万美金到百千万美金不等。这些特性都决定了 IC 设计的试错成本极为高昂,因此能够有效的降低错误的发生就显得非常重要。

现代的芯片设计规模越来越大,复杂度越来越高,并不是说要求设计者一味的逃避使用复杂的技术,而是应该将好钢用在刀刃上,将最复杂的设计用在最为关键的场景,在大多数有选择的情况下,尽量选择简洁的实现方案。

笔者在第一次阅读了 RISC-V 架构文档之时,不禁击节赞叹,拍案惊奇,因为 RISC-V 架构在其文档中不断地明确强调,其设计哲学是“大道至简”,力图通过架构的定义使得硬件的实现足够简单。其简单就是美的哲学,可以从几个方面容易看出,后续小节将一一加以论述。


1.1 无病一身轻——架构的篇幅

在处理器领域,目前主流的架构为 x86 与 ARM 架构,笔者曾经参与设计 ARM 架构的应用处理器,因此需要阅读 ARM 的架构文档,如果对其熟悉的读者应该了解其篇幅。经过几十年的发展,现代的 x86 与 ARM 架构的架构文档长达几百数千页。打印出来能有半个桌子高,可真是“著作等身”。

之所以现代 x86 与 ARM 架构的文档长达数千页,且版本众多,一个主要的原因是因为其架构的发展过程也伴随了现代处理器架构技术的不断发展成熟。

并且作为商用的架构,为了能够保持架构的向后兼容性,其不得不保留许多过时的定义,或者在定义新的架构部分时为了能够将就已经存在的技术部分而显得非常的别扭。久而久之就变得极为冗长。

那么现代成熟的架构是否能够选择重新开始,重新定义一个简洁的架构呢,可以说是几乎不可能。其中一个重要的原因便是其无法向前兼容,从而无法得到用户的接受。试想一下如果我们买了一款搭配新处理器的电脑或者手机回家,之前所有的软件都无法运行而变砖,那肯定是无法让人接受的。

而现在才推出的 RISC-V 架构,则具备了后发优势,由于计算机体系结构经过多年的发展已经成为比较成熟的技术,多年来在不断成熟的过程中暴露的问题都已经被研究透彻,因此新的 RISC-V 架构能够加以规避,并且没有背负向后兼容的历史包袱,可以说是无病一身轻。

目前的“RISC-V 架构文档”分为“指令集文档”(riscv-spec-v2.2.pdf)和“特权架构文档”(riscv-privileged-v1.10.pdf)。“指令集文档”的篇幅为 145 页,而“特权架构文档”的篇幅也仅为 91 页。熟悉体系结构的工程师仅需一至两天便可将其通读,虽然“RISC-V 的架构文档”还在不断地丰富,但是相比“x86 的架构文档”与“ARM 的架构文档”,RISC-V 的篇幅可以说是极其短小精悍。

感兴趣的读者可以在 RISC-V 基金会的网站上(https://riscv.org/specifications/)无需注册便可免费下载其文档,如图 1 所示。

(图略)
图1 RISC-V 基金会网站上的架构文档


1.2 能屈能伸——模块化的指令集

RISC-V 架构相比其他成熟的商业架构的最大一个不同还在于它是一个模块化的架构。因此,RISC-V 架构不仅短小精悍,而且其不同的部分还能以模块化的方式组织在一起,从而试图通过一套统一的架构满足各种不同的应用。

这种模块化是 x86 与 ARM 架构所不具备的。以 ARM 的架构为例,ARM 的架构分为 A、R 和 M 三个系列,分别针对 Application(应用操作系统)、Real-Time(实时)和 Embedded(嵌入式)三个领域,彼此之间并不兼容。

但是模块化的 RISC-V 架构能够让用户灵活选择不同的模块组合,以满足不同的应用场景,可以说是“老少咸宜”。譬如针对小面积低功耗嵌入式场景,用户可以选择 RV32IC 组合的指令集,仅使用Machine Mode(机器模式);而高性能应用操作系统场景则可以选择譬如 RV32IMFDC 的指令集,使用Machine Mode(机器模式)与 User Mode(用户模式)两种模式。而他们共同的部分则可以相互兼容。


1.3 浓缩的都是精华——指令的数量

短小精悍的架构以及模块化的哲学,使得 RISC-V 架构的指令数目非常的简洁。基本的 RISC-V 指令数目仅有 40 多条,加上其他的模块化扩展指令总共几十条指令。

2、RISC-V 指令集架构简介

本章简要介绍 RISC-V 指令集架构诸多特性。

2.1 模块化的指令子集

RISC-V 的指令集使用模块化的方式进行组织,每一个模块使用一个英文字母来表示。RISC-V 最基本也是唯一强制要求实现的指令集部分是由I字母表示的基本整数指令子集,使用该整数指令子集,便能够实现完整的软件编译器。其他的指令子集部分均为可选的模块,具有代表性的模块包括 M/A/F/D/C,如表 1 所示。

表1 RISC-V 的模块化指令集

基本指令集
指令数
描述
RV32I
47
32 位地址空间与整数指令,支持 32 个通用整数寄存器
RV32E
47
RV32I 的子集,仅支持 16 个通用整数寄存器
RV64I
59
64 位地址空间与整数指令及一部分 32 位的整数指令
RV128I
71
128 位地址空间与整数指令及一部分 64 位和 32 位指令
扩展指令集
指令数
描述
M
8
整数乘法与除法指令
A
11
存储器原子(Atomic)操作指令和 Load-Reserved/Store-Conditional 指令
F
26
单精度(32 比特)浮点指令
D
26
双精度(64 比特)浮点指令,必须支持 F 扩展指令
C
46
压缩指令,指令长度为 16 位

为了提高代码密度,RISC-V 架构也提供可选的“压缩”指令子集,由英文字母 C 表示。压缩指令的指令编码长度为 16 比特,而普通的非压缩指令的长度为 32 比特。以上这些模块的一个特定组合“IMAFD”,也被称为“通用”组合,由英文字母 G 表示。因此 RV32G 表示 RV32IMAFD,同理 RV64G 表示 RV64IMAFD。

为了进一步减少面积,RISC-V 架构还提供一种“嵌入式”架构,由英文字母 E 表示。该架构主要用于追求极低面积与功耗的深嵌入式场景。该架构仅需要支持 16 个通用整数寄存器,而“非嵌入式”的普通架构则需要支持 32 个通用整数寄存器。

通过以上的模块化指令集,能够选择不同的组合来满足不同的应用。譬如,追求小面积低功耗的嵌入式场景可以选择使用 RV32EC 架构;而大型的 64 位架构则可以选择 RV64G。

除了上述的模块,还有若干的模块包括 L、B、P、V 和 T 等。这些扩展目前大多数还在不断完善和定义中,尚未最终确定,因此本文在此不做详细论述。


2.2 可配置的通用寄存器组

RISC-V 架构支持 32 位或者 64 位的架构,32 位架构由 RV32 表示,其每个通用寄存器的宽度为 32 比特;64 位架构由 RV64表示,其每个通用寄存器的宽度为 64 比特。

RISC-V 架构的整数通用寄存器组,包含 32 个(I 架构)或者 16 个(E 架构)通用整数寄存器,其中整数寄存器 0 被预留为常数 0,其他的 31个(I 架构)或者 15 个(E 架构)为普通的通用整数寄存器。

如果使用了浮点模块(F 或者 D),则需要另外一个独立的浮点寄存器组,包含 32 个通用浮点寄存器。如果仅使用 F 模块的浮点指令子集,则每个通用浮点寄存器的宽度为 32 比特;如果使用了 D 模块的浮点指令子集,则每个通用浮点寄存器的宽度为 64 比特。


2.3 规整的指令编码

在流水线中能够尽早尽快的读取通用寄存器组,往往是处理器流水线设计的期望之一,这样可以提高处理器性能和优化时序。这个看似简单的道理在很多现存的商用 RISC 架构中都难以实现,因为经过多年反复修改不断添加新指令后,其指令编码中的寄存器索引位置变得非常的凌乱,给译码器造成了负担。

得益于后发优势和总结了多年来处理器发展的教训,RISC-V 的指令集编码非常的规整,指令所需的通用寄存器的索引(Index)都被放在固定的位置,如图 2 所示。因此指令译码器(Instruction Decoder)可以非常便捷的译码出寄存器索引然后读取通用寄存器组(Register File,Regfile)。


31        25
24      20
19      15
14     12
11        7
6        0

funct7
rs2
rs1
funct3
rd
opcode
R-type

imm[11:0]
rs1
funct3
rd
opcode
I-type

imm[11:5]
rs2
rs1
funct3
imm[4:0]
opcode
S-type

imm[31:12]
rd
opcode
U-type

图2 RV32I 规整的指令编码格式

2.4 简洁的存储器访问指令

与所有的 RISC 处理器架构一样,RISC-V 架构使用专用的存储器读(Load)指令和存储器写(Store)指令访问存储器(Memory),其他的普通指令无法访问存储器,这种架构是 RISC 架构的常用的一个基本策略,这种策略使得处理器核的硬件设计变得简单。

存储器访问的基本单位是字节(Byte)。RISC-V 的存储器读和存储器写指令支持一个字节(8 位),半字(16 位),单字(32 位)为单位的存储器读写操作,如果是 64 位架构还可以支持一个双字(64 位)为单位的存储器读写操作。

RISC-V 架构的存储器访问指令还有如下显著特点:

    为了提高存储器读写的性能,RISC-V 架构推荐使用地址对齐的存储器读写操作,但是地址非对齐的存储器操作 RISC-V 架构也支持,处理器可以选择用硬件来支持,也可以选择用软件来支持。
    由于现在的主流应用是小端格式(Little-Endian),RISC-V 架构仅支持小端格式。有关小端格式和大端格式的定义和区别,本文在此不做过多介绍,若对此不甚了解的初学者可以自行查阅学习。
    很多的 RISC 处理器都支持地址自增或者自减模式,这种自增或者自减的模式虽然能够提高处理器访问连续存储器地址区间的性能,但是也增加了设计处理器的难度。RISC-V 架构的存储器读和存储器写指令不支持地址自增自减的模式。
    RISC-V 架构采用松散存储器模型(Relaxed Memory Model),松散存储器模型对于访问不同地址的存储器读写指令的执行顺序不作要求,除非使用明确的存储器屏障(Fence)指令加以屏蔽。

这些选择都清楚地反映了 RISC-V 架构力图简化基本指令集,从而简化硬件设计的哲学。RISC-V 架构如此定义非常合理,能屈能伸。譬如:对于低功耗的简单 CPU,可以使用非常简单的硬件电路即可完成设计;而对于追求高性能的超标量处理器则可以通过复杂设计的动态硬件调度能力来提高性能。


2.5 高效的分支跳转指令

RISC-V 架构有两条无条件跳转指令(Unconditional Jump),jal 与 jalr 指令。跳转链接(Jumpand Link)指令 jal 可用于进行子程序调用,同时将子程序返回地址存在链接寄存器(Link Register:由某一个通用整数寄存器担任)中。跳转链接寄存器(Jumpand Link-Register)指令 jalr 指令能够用于子程序返回指令,通过将 jal 指令(跳转进入子程序)保存的链接寄存器用于 jalr 指令的基地址寄存器,则可以从子程序返回。

RISC-V 架构有 6 条带条件跳转指令(Conditional Branch),这种带条件的跳转指令跟普通的运算指令一样直接使用 2 个整数操作数,然后对其进行比较,如果比较的条件满足时,则进行跳转。因此,此类指令将比较与跳转两个操作放到了一条指令里完成。

作为比较,很多的其他 RISC 架构的处理器需要使用两条独立的指令。第一条指令先使用比较指令,比较的结果被保存到状态寄存器之中;第二条指令使用跳转指令,判断前一条指令保存在状态寄存器当中的比较结果为真时则进行跳转。相比而言 RISC-V 的这种带条件跳转指令不仅减少了指令的条数,同时硬件设计上更加简单。

对于没有配备硬件分支预测器的低端 CPU,为了保证其性能,RISC-V 的架构明确要求其采用默认的静态分支预测机制,即:如果是向后跳转的条件跳转指令,则预测为“跳”;如果是向前跳转的条件跳转指令,则预测为“不跳”,并且 RISC-V 架构要求编译器也按照这种默认的静态分支预测机制来编译生成汇编代码,从而让低端的 CPU 也能得到不错的性能。

为了使硬件设计尽量简单,RISC-V 架构特地定义了所有的带条件跳转指令跳转目标的偏移量(相对于当前指令的地址)都是有符号数,并且其符号位被编码在固定的位置。因此,这种静态预测机制在硬件上非常容易实现,硬件译码器可以轻松的找到这个固定的位置,并判断其是 0 还是 1 来判断其是正数还是负数,如果是负数则表示跳转的目标地址为当前地址减去偏移量,也就是向后跳转,则预测为“跳”。当然对于配备有硬件分支预测器的高端 CPU,则可以采用高级的动态分支预测机制来保证性能。


2.6 简洁的子程序调用

为了理解此节,先介绍一般 RISC 架构中程序调用子函数的过程:

    进入子函数之后需要用存储器写(Store)指令来将当前的上下文(通用寄存器等的值)保存到系统存储器的堆栈区内,这个过程通常称为“保存现场”。
    在退出子程序之时,需要用存储器读(Load)指令来将之前保存的上下文(通用寄存器等的值)从系统存储器的堆栈区读出来,这个过程通常称为“恢复现场”。

“保存现场”和“恢复现场”的过程通常由编译器编译生成的指令来完成,使用高层语言(譬如 C 或者 C++)开发的开发者对此可以不用太关心。高层语言的程序中直接写上一个子函数调用即可,但是这个底层发生的“保存现场”和“恢复现场”的过程却是实实在在地发生着(可以从编译出的汇编语言里面看到那些“保存现场”和“恢复现场”的汇编指令),并且还需要消耗若干的 CPU 执行时间。

为了加速这个“保存现场”和“恢复现场”的过程,有的 RISC 架构发明了一次写多个寄存器到存储器中(Store Multiple),或者一次从存储器中读多个寄存器出来(Load Multiple)的指令,此类指令的好处是一条指令就可以完成很多事情,从而减少汇编指令的代码量,节省代码的空间大小。但是此种“Load Multiple”和“Store Multiple”的弊端是会让 CPU 的硬件设计变得复杂,增加硬件的开销,也可能损伤时序使得 CPU 的主频无法提高,笔者在曾经设计此类处理器时便深受其苦。

RISC-V 架构则放弃使用这种“Load Multiple”和“Store Multiple”指令。并解释,如果有的场合比较介意这种“保存现场”和“恢复现场”的指令条数,那么可以使用公用的程序库(专门用于保存和恢复现场)来进行,这样就可以省掉在每个子函数调用的过程中都放置数目不等的“保存现场”和“恢复现场”的指令。

此选择再次印证了 RISC-V 追求硬件简单的哲学,因为放弃“Load Multiple”和“Store Multiple”指令可以大幅简化 CPU 的硬件设计,对于低功耗小面积的 CPU 可以选择非常简单的电路进行实现,而高性能超标量处理器由于硬件动态调度能力很强,可以有强大的分支预测电路保证 CPU 能够快速的跳转执行,从而可以选择使用公用的程序库(专门用于保存和恢复现场)的方式减少代码量,但是同时达到高性能。


2.7 无条件码执行

很多早期的 RISC 架构发明了带条件码的指令,譬如在指令编码的头几位表示的是条件码(Conditional Code),只有该条件码对应的条件为真时,该指令才被真正执行。

这种将条件码编码到指令中的形式可以使得编译器将短小的循环编译成带条件码的指令,而不用编译成分支跳转指令。这样便减少了分支跳转的出现,一方面减少了指令的数目;另一方面也避免了分支跳转带来的性能损失。然而,这种“条件码”指令的弊端同样会使得 CPU 的硬件设计变得复杂,增加硬件的开销,也可能损伤时序使得 CPU 的主频无法提高,笔者在曾经设计此类处理器时便深受其苦。

RISC-V 架构则放弃使用这种带“条件码”指令的方式,对于任何的条件判断都使用普通的带条件分支跳转指令。此选择再次印证了 RISC-V 追求硬件简单的哲学,因为放弃带“条件码”指令的方式可以大幅简化 CPU 的硬件设计,对于低功耗小面积的 CPU 可以选择非常简单的电路进行实现,而高性能超标量处理器由于硬件动态调度能力很强,可以有强大的分支预测电路保证 CPU 能够快速的跳转执行达到高性能。


2.8 无分支延迟槽

很多早期的 RISC 架构均使用了“分支延迟槽(Delay Slot)”,最具有代表性的便是 MIPS 架构,在很多经典的计算机体系结构教材中,均使用 MIPS 对分支延迟槽进行过介绍。分支延迟槽就是指在每一条分支指令后面紧跟的一条或者若干条指令不受分支跳转的影响,不管分支是否跳转,这后面的几条指令都一定会被执行。

早期的 RISC 架构很多采用了分支延迟槽诞生的原因主要是因为当时的处理器流水线比较简单,没有使用高级的硬件动态分支预测器,所以使用分支延迟槽能够取得可观的性能效果。然而,这种分支延迟槽使得 CPU 的硬件设计变得极为的别扭,CPU 设计人员对此往往苦不堪言。

RISC-V 架构则放弃了分支延迟槽,再次印证了 RISC-V 力图简化硬件的哲学,因为现代的高性能处理器的分支预测算法精度已经非常高,可以有强大的分支预测电路保证 CPU 能够准确的预测跳转执行达到高性能。而对于低功耗小面积的 CPU,由于无需支持分支延迟槽,硬件得到极大简化,也能进一步减少功耗和提高时序。


2.9 无零开销硬件循环

很多 RISC 架构还支持零开销硬件循环(Zero Overhead Hardware Loop)指令,其思想是通过硬件的直接参与,通过设置某些循环次数寄存器(Loop Count),然后可以让程序自动地进行循环,每一次循环则 Loop Count 自动减 1,这样持续循环直到 Loop Count 的值变成 0,则退出循环。

之所以提出发明这种硬件协助的零开销循环是因为在软件代码中的 for 循环(for i=0; i ...)

然而有得必有失,此类零开销硬件循环指令大幅地增加了硬件设计的复杂度。因此,零开销循环指令与 RISC-V 架构简化硬件的哲学是完全相反的,在 RISC-V 架构中自然没有使用此类零开销硬件循环指令。


2.10 简洁的运算指令

在本章第 2.1 节中曾经提到 RISC-V 架构使用模块化的方式组织不同的指令子集,最基本的整数指令子集(I 字母表示)支持的运算包括加法、减法、移位、按位逻辑操作和比较操作。这些基本的运算操作能够通过组合或者函数库的方式完成更多的复杂操作(譬如乘除法和浮点操作),从而能够完成大多数的软件操作。

整数乘除法指令子集(M 字母表示)支持的运算包括,有符号或者无符号的乘法和除法操作。乘法操作能够支持两个 32 位的整数相乘得到一个 64 位的结果;除法操作能够支持两个 32 位的整数相除得到一个 32 位的商与 32 位的余数。

单精度浮点指令子集(F 字母表示)与双精度浮点指令子集(D 字母表示)支持的运算包括浮点加减法,乘除法,乘累加,开平方根和比较等操作,同时提供整数与浮点,单精度与双精度浮点彼此之间的格式转换操作。

很多 RISC 架构的处理器在运算指令产生错误之时,譬如上溢(Overflow)、下溢(Underflow)、非规格化浮点数(Subnormal)和除零(Divide by Zero),都会产生软件异常。RISC-V 架构的一个特殊之处是对任何的运算指令错误(包括整数与浮点指令)均不产生异常,而是产生某个特殊的默认值,同时,设置某些状态寄存器的状态位。RISC-V 架构推荐软件通过其他方法来找到这些错误。再次清楚地反映了 RISC-V 架构力图简化基本的指令集,从而简化硬件设计的哲学。


2.11 优雅的压缩指令子集

基本的 RISC-V 基本整数指令子集(字母 I 表示)规定的指令长度均为等长的 32 位,这种等长指令定义使得仅支持整数指令子集的基本 RISC-V CPU 非常容易设计。但是等长的 32 位编码指令也会造成代码体积(Code Size)相对较大的问题。

为了满足某些对于代码体积要求较高的场景(譬如嵌入式领域),RISC-V 定义了一种可选的压缩(Compressed)指令子集,由字母 C 表示,也可以由 RVC 表示。RISC-V 具有后发优势,从一开始便规划了压缩指令,预留了足够的编码空间,16 位长指令与普通的32位长指令可以无缝自由地交织在一起,处理器也没有定义额外的状态。

RISC-V 压缩指令的另外一个特别之处是,16 位指令的压缩策略是将一部分普通最常用的的 32 位指令中的信息进行压缩重排得到(譬如假设一条指令使用了两个同样的操作数索引,则可以省去其中一个索引的编码空间),因此每一条 16 位长的指令都能一一找到其对应的原始 32 位指令。因此,程序编译成为压缩指令仅在汇编器阶段就可以完成,极大的简化了编译器工具链的负担。

RISC-V 架构的研究者进行了详细的代码体积分析,如图 3 所示,通过分析结果可以看出,RV32C 的代码体积相比 RV32 的代码体积减少了百分之四十,并且与 ARM,MIPS 和 x86 等架构相比都有不错的表现。

(图略)
图3 各指令集架构的代码密度比较(数据越小越好)


2.12 特权模式

RISC-V 架构定义了三种工作模式,又称特权模式(Privileged Mode):

    Machine Mode:机器模式,简称 M Mode。
    Supervisor Mode:监督模式,简称 S Mode。
    User Mode:用户模式,简称 U Mode。

RISC-V 架构定义 M Mode 为必选模式,另外两种为可选模式。通过不同的模式组合可以实现不同的系统。

RISC-V 架构也支持几种不同的存储器地址管理机制,包括对于物理地址和虚拟地址的管理机制,使得RISC-V 架构能够支持从简单的嵌入式系统(直接操作物理地址)到复杂的操作系统(直接操作虚拟地址)的各种系统。


2.13 CSR 寄存器

RISC-V 架构定义了一些控制和状态寄存器(Control and Status Register,CSR),用于配置或记录一些运行的状态。CSR 寄存器是处理器核内部的寄存器,使用其自己的地址编码空间,和存储器寻址的地址区间完全无关系。

CSR 寄存器的访问采用专用的 CSR 指令,包括 CSRRW、CSRRS、CSRRC、CSRRWI、CSRRSI 以及 CSRRCI 指令。


2.14 中断和异常

中断和异常机制往往是处理器指令集架构中最为复杂而关键的部分。RISC-V 架构定义了一套相对简单基本的中断和异常机制,但是也允许用户对其进行定制和扩展。

2.15 矢量指令子集

RISC-V 架构目前虽然还没有定型矢量(Vector)指令子集,但是从目前的草案中已经可以看出,RISC-V 矢量指令子集的设计理念非常的先进,由于后发优势及借助矢量架构多年发展成熟的结论,RISC-V 架构将使用可变长度的矢量,而不是矢量定长的 SIMD 指令集(譬如 ARM 的 NEON 和 Intel 的 MMX),从而能够灵活的支持不同的实现。追求低功耗小面积的 CPU 可以选择使用长度较短的硬件矢量进行实现,而高性能的 CPU 则可以选择较长的硬件矢量进行实现,并且同样的软件代码能够彼此兼容。

2.16 自定制指令扩展

除了上述阐述的模块化指令子集的可扩展、可选择,RISC-V 架构还有一个非常重要的特性,那就是支持第三方的扩展。用户可以扩展自己的指令子集,RISC-V 预留了大量的指令编码空间用于用户的自定义扩展,同时,还定义了四条 Custom 指令可供用户直接使用,每条 Custom 指令都有几个比特位的子编码空间预留,因此,用户可以直接使用四条 Custom 指令扩展出几十条自定义的指令。

2.17 总结与比较

处理器设计技术经过几十年的衍进,随着大规模集成电路设计技术的发展直至今天,呈现出如下特点:

    由于高性能处理器的硬件调度能力已经非常强劲且主频很高,因此,硬件设计希望指令集尽可能的规整、简单,从而,使得处理器可以设计出更高的主频与更低的面积。
    以 IoT 应用为主的极低功耗处理器更加苛求低功耗与低面积。
    存储器的资源也比早期的 RISC 处理器更加丰富。

如上种种这些因素,使得很多早期的 RISC 架构设计理念(依据当时技术背景而诞生),时至今日不仅不能帮助现代处理器设计,反而成了负担桎梏。某些早期 RISC 架构定义的特性,一方面使得高性能处理器的硬件设计束手束脚;另一方面又使得极低功耗的处理器硬件设计背负不必要的复杂度。

得益于后发优势,全新的 RISC-V 架构能够规避所有这些已知的负担,同时,利用其先进的设计哲学,设计出一套“现代”的指令集。本节再次将其特点总结如表 2 所示。


表2 RISC-V 指令集架构特点总结

特性
x86 或 ARM 架构
RISC-V
架构篇幅
数千页
少于三百页
模块化
不支持
支持模块化可配置的指令子集
可扩展性
不支持
支持可扩展定制指令
指令数目
指令数繁多,不同的架构分支彼此不兼容
一套指令集支持所有架构。基本指令子集仅 40 余条指令,以此为共有基础,加上其他常用模块子集指令,总指令数也仅几十条
易实现性
硬件实现的复杂度高硬件设计与编译器实现非常简单:
 仅支持小端格式
 存储器访问指令一次只访问一个元素
 去除存储器访问指令的地址自增自减模式
 规整的指令编码格式
 简化的分支跳转指令与静态预测机制
 不使用分支延迟槽(Delay Slot)
 不使用指令条件码(Conditional Code)
 运算指令的结果不产生异常(Exception)
 16 位的压缩指令有其对应的普通 32 位指令
 不使用零开销硬件循环

评分

参与人数 1无忧币 +5 收起 理由
zhczf + 5 很给力!

查看全部评分

发表于 2019-4-12 12:30:10 | 显示全部楼层
围观一下,目测在嵌入式领域应该能分一杯羹...
回复

使用道具 举报

 楼主| 发表于 2019-4-12 18:15:23 | 显示全部楼层
本帖最后由 不点 于 2019-4-13 15:27 编辑

中国也成立了 RISC-V 联盟(China RISC-V Alliance),不过,中文名字叫做 “开放指令生态联盟”:

http://crva.io/

在联盟的下载页,给出了 RISC-V 手册的中文版:

http://crva.ict.ac.cn/documents/RISC-V-Reader-Chinese-v2p1.pdf

目前联盟成员有以下单位和个人:

一、指导单位

中央网信办信息化发展局

工信部信息化和软件服务业司

中科院科技促进发展局


二、咨询委员会专家(按拼音序,下同)

方之熙(RISC-V基金会中国顾问委员会主席)

卢  山(中国电子信息产业发展研究院院长)

孙凝晖(中国科学院计算技术研究所所长)

涂  强(长虹北美研发中心总经理)

严晓浪(浙江大学教授)

叶甜春(中国科学院微电子所所长)


三、依托单位

理事长(单位):  倪光南院士(中国科学院计算技术研究所)

常务副理事长单位:中国电子信息产业发展研究院


四、副理事长单位

北京百度网讯科技有限公司

北京大学

北京紫光展锐科技有限公司

杭州中天微系统有限公司

华为技术有限公司

清华大学

四川长虹电器股份有限公司

腾讯科技股份有限公司

中国科学院微电子研究所

五、常务理事单位

鹏城实验室

睿思芯科(深圳)技术有限公司

上海交通大学

西安中科创星科技孵化器有限公司

中科创达软件股份有限公司

中国科学院上海微系统与信息技术研究所

致象尔微电子科技(上海)有限公司


六、单位会员

国家超级计算深圳中心

华米(北京)信息科技有限公司

江苏金羿智芯科技有限公司

浪潮电子信息产业股份有限公司

宁波中国科学院信息技术应用研究院

澎峰(北京)科技有限公司

青岛本原微电子有限公司

人民邮电出版社有限公司

苏州国芯科技有限公司

天博电子信息科技有限公司

芯来科技(武汉)有限公司

中国科学技术大学

珠海全志科技股份有限公司


七、个人会员

陈铁军

宫晓利

郝沁汾

李诚

刘国旗

宋威

孙浩

魏继增

许冠斌

严智

周平强


八、秘书处

设于中国科学院计算技术研究所

秘书长:包云岗

成  员:张科、唐丹、常轶松、王卅、解壁伟、赵然


九、联系方式

地址:北京市海淀区中关村科学院南路6号,邮编:100190

中国科学院计算技术研究所

电话:010-62601013/62601015    邮箱:info@crva.io

回复

使用道具 举报

发表于 2019-4-15 21:36:16 | 显示全部楼层
这个开源的rsicv看起来比较有趣啊,或许未来真正的开源硬件cpu很可能会以此为设计基础了。。。

点评

我关注这个指令集设计,也是在为编程语言设计打下哲学铺垫。 目前总觉得编程语言欠缺点啥东西,但又说不清究竟欠缺啥。 从这个 risc-v 的设计哲学中,我好像隐隐约约有那么点思路了。 初步设想,一个编程语  详情 回复 发表于 2019-4-16 10:40
回复

使用道具 举报

 楼主| 发表于 2019-4-16 10:40:40 | 显示全部楼层
gnuxwy 发表于 2019-4-15 21:36
这个开源的rsicv看起来比较有趣啊,或许未来真正的开源硬件cpu很可能会以此为设计基础了。。。

我关注这个指令集设计,也是在为编程语言设计打下哲学铺垫。

目前总觉得编程语言欠缺点啥东西,但又说不清究竟欠缺啥。

从这个 risc-v 的设计哲学中,我好像隐隐约约有那么点思路了。

初步设想,一个编程语言,应该做到如下几点:

1、简单。去掉复杂的功能。risc-v 的核心部分,连乘除法运算都去掉了,可谓大胆。我们往往是因为不够大胆、不敢否定,才失去创造力的。设想这个新的语言,在核心部分,也要去掉复杂的东西,比如,不支持 “面向对象”,只支持普通 C 的 struct 以及函数操作。

2、即时编译。语言应该像 BASIC 语言那样,一句一句的。BASIC 是解释式的,效率低。我们把它改成即时编译,就像 cling 那样。

3、语言同时涵盖 shell 的功能。就是说,语言一开始就是一个最简单的 shell,能够敲入 shell 命令(仅仅执行外部命令而已)。然后逐步增加其它特性,比如数据类型、控制转移结构、函数调用,等等。

4、语言能够用来编写机器指令,就是说,同时具有汇编语言的功能。

5、扩展性。将来可以扩展出其它特性,比如面向对象。

如果这几条做到了,那就是个十分强大的语言了。

点评

怎么感觉和c没什么太大区别了啊 c的功能以及够简单了,而且是编译式的。语言通过库函数就可以直接调用shell(非语言自身支持,稍微麻烦点),可以直接用指针等操作硬件,具有大部分汇编功能,不支持的也可以内嵌  详情 回复 发表于 2019-4-16 12:48
回复

使用道具 举报

发表于 2019-4-16 12:48:24 | 显示全部楼层
不点 发表于 2019-4-16 10:40
我关注这个指令集设计,也是在为编程语言设计打下哲学铺垫。

目前总觉得编程语言欠缺点啥东西,但又说 ...

怎么感觉和c没什么太大区别了啊

c的功能以及够简单了,而且是编译式的。语言通过库函数就可以直接调用shell(非语言自身支持,稍微麻烦点),可以直接用指针等操作硬件,具有大部分汇编功能,不支持的也可以内嵌汇编。上层语言也可以轻易扩展,比如有部分c++编译器就是把c++编译成c语言的

点评

C 有很多优点,所以,是一个重要的参考。许多操作系统都是用 C 写成的。C 的通用性强。操作系统有很多 C 的 lib。 但 C 也有缺点。C 的编译器太大。C 的规范也不够简练。 C 是编译式的语言,但却不是交互式的  详情 回复 发表于 2019-4-16 15:15
回复

使用道具 举报

 楼主| 发表于 2019-4-16 15:15:07 | 显示全部楼层
2013olly 发表于 2019-4-16 12:48
怎么感觉和c没什么太大区别了啊

c的功能以及够简单了,而且是编译式的。语言通过库函数就可以直接调用 ...

C 有很多优点,所以,是一个重要的参考。许多操作系统都是用 C 写成的。C 的通用性强。操作系统有很多 C 的 lib。

但 C 也有缺点。C 的编译器太大。C 的规范也不够简练。

C 是编译式的语言,但却不是交互式的。cling 是交互式的,而且能即时编译,但 cling 太庞大了。庞大就表明复杂。复杂就不符合 “简单就是美、简单才安全”的哲学。

前一帖解释了,我从 risc-v 的设计哲学中,学到了胆量——就是敢于提出疑问、敢于否定的胆量。

当然,也不是说全都否定。本来也就不可能全盘否定。最后是个权衡:权衡出哪些需要肯定,哪些需要否定,就差不多了。

点评

那我觉得可以看看c的早期版本,比如c89,c99之类,看看哪个版本比较精简,没那么复杂。再进行fork 早期的代码读起来应该比较容易些  详情 回复 发表于 2019-4-16 16:09
回复

使用道具 举报

发表于 2019-4-16 16:09:32 | 显示全部楼层
不点 发表于 2019-4-16 15:15
C 有很多优点,所以,是一个重要的参考。许多操作系统都是用 C 写成的。C 的通用性强。操作系统有很多 C  ...

那我觉得可以看看c的早期版本,比如c89,c99之类,看看哪个版本比较精简,没那么复杂。再进行fork
早期的代码读起来应该比较容易些

点评

对的,这也是个思路。但去年我改造 cling 的时候,对 C 语言的复杂,就有点后怕了。当然,我可能是受到 C++ 复杂性的影响了。记得编译 cling 就要花费 4 个小时以上,而且内存得有 2G 才行。这显然太复杂、太庞大。  详情 回复 发表于 2019-4-16 16:37
回复

使用道具 举报

 楼主| 发表于 2019-4-16 16:37:38 | 显示全部楼层
2013olly 发表于 2019-4-16 16:09
那我觉得可以看看c的早期版本,比如c89,c99之类,看看哪个版本比较精简,没那么复杂。再进行fork
早期 ...

对的,这也是个思路。但去年我改造 cling 的时候,对 C 语言的复杂,就有点后怕了。当然,我可能是受到 C++ 复杂性的影响了。记得编译 cling 就要花费 4 个小时以上,而且内存得有 2G 才行。这显然太复杂、太庞大。

从早期版本入手,或许是一个思路。确实也应该有人往这方面去探索。另外,早期的 Linux  可能也比较精简,里面的后门可以认为是不存在的。但是,早期的 Linux 可能只支持 x86,不支持 ARM 等其它架构,这也是个问题,这都需要权衡。所以,我能理解,为什么有人从头开发 minix、redox 等新操作系统。

同样,设计和实现一种新语言,也并不特别让人难以接受。每年似乎都有新语言出现。所以,我隐隐约约觉得,可能需要设计新语言了,说不定这样做来得更自然一些,工作量也可能更少一些。总之,思路有很多,权衡也有很多。不同的思路、不同的权衡、不同的判断、不同的决定,都是对的。

点评

个人还是感觉开发新操作系统,必然会对“兼容性”造成影响,旧的软件未经修改很难直接用于新的系统,尤其是那些闭源的应用软件。 早期系统,至少拥有不少可用的软件和工具(尽管可能是比较老的版本)添加内核功能  详情 回复 发表于 2019-4-29 11:27
回复

使用道具 举报

发表于 2019-4-29 11:27:17 | 显示全部楼层
不点 发表于 2019-4-16 16:37
对的,这也是个思路。但去年我改造 cling 的时候,对 C 语言的复杂,就有点后怕了。当然,我可能是受到 C ...

个人还是感觉开发新操作系统,必然会对“兼容性”造成影响,旧的软件未经修改很难直接用于新的系统,尤其是那些闭源的应用软件。

早期系统,至少拥有不少可用的软件和工具(尽管可能是比较老的版本)添加内核功能相比修改大量应用软件来说,工作量还是要小得多。如果内核的新功能确信没有副作用,移植到之前的版本也比移植到一个新的系统要来得容易。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2019-12-9 16:59

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表