论文知识地图

如果说上一讲的《计算机组成与设计》是 RISC-V 的「教科书」,那这一份就是 RISC-V 的「出生证明」——Andrew Waterman 的伯克利技术报告《Design of the RISC-V Instruction Set Architecture》(UCB/EECS-2016-1,2016 年 1 月)。

Waterman 是谁?RISC-V 的两位创始人之一(另一位是 Krste Asanović),后来 RISC-V 国际学会的 CTO。这份 117 页的报告,是他在 RISC-V 公开之前,把整个指令集的设计动机、每个决策的「为什么」、以及和所有前辈 ISA 的正面对比数据一次性摊牌的文档。

教科书告诉你 RISC-V「是什么」,这篇论文告诉你 RISC-V「为什么长这样」。两份材料对着读,很多细节会突然变得顺理成章。

第 2 章:为什么非要造一个新 ISA?

这是全文最锋利的一章。Waterman 先替读者问出了那个经典质疑:现有 ISA 这么多,软件生态都是现成的,再造一个新的图什么?

他给出两个无法绕开的理由:

  1. 现存的 ISA 全都有「历史包袱」——为了兼容几十年前的芯片,堆积了大量今天没人用、但硬件必须永远背负的东西;
  2. 商业 ISA 都在收费墙上——你想用,先谈钱;想改,免谈。学术界想做个新分支预测器的实验,光是拿授权就可能卡死。

然后他给 MIPS、SPARC、Alpha、ARMv7、ARMv8、OpenRISC、x86 七大 ISA 逐一做「体检」,检查五项现代 ISA 的及格线:

七大 ISA 体检表

结论冷酷:没有一家全绿。

  • MIPS、SPARC:长年没跟进压缩指令(SPARC 甚至把 1/4 的 opcode 空间花在 CALL 一条指令上);
  • x86:免费开源和经典可虚拟化双双缺席,还有隐式条件码、破坏性两地址指令这些「激进微架构的噩梦」;
  • OpenRISC:倒是开源了,但缺 64 位、缺压缩指令,指令集本身也没经过严格的软硬件协同评估;
  • ARMv8 最接近,但它不是自由的。

体检表里那行全绿的 RISC-V,就是这份论文存在的理由。这不是「又一个 ISA」,而是第一个把「免费、开放、模块化、经典可虚拟化」同时当成立项要求来设计的 ISA。

第 3 章:基础指令集——47 条指令的极简主义

RV32I 是全书的根基。Waterman 先声明设计目标:基座必须小到适合教学和极低端嵌入式,又必须完整到能支撑现代软件——于是有了 47 条指令的 RV32I。

几个关键决策值得细品:

寄存器:32 个,x0 恒零。 相比 x86 的 8 个(溢出到内存太频繁)和 ARM 的 16 个,32 个寄存器是编译器研究的甜蜜点;x0=0 则让 mvneg、比较等一票伪指令「免费」实现。

三种主要指令格式 + 访存/分支变体。 看一眼论文第 18 页这张图(RV32I 六种格式全家福):

RV32I 指令格式

R 型纯寄存器运算、I 型带立即数、S 型访存存数、B 型条件分支、U 型长立即数、J 型远跳转。所有格式共用位置固定的 opcode / rd / rs1 / funct3 字段——硬件在分清指令类型之前就能并行解码公共字段,这是流水线友好性的来源。

无标志位寄存器。 x86 有 EFLAGS,ARM 有 CPSR,RISC-V 什么都没有——比较结果直接写进通用寄存器(beq 直接比较两个寄存器)。代价是偶尔多一条指令,收益是:无隐式状态 → 分支预测与乱序执行实现大幅简化,多核时代这越来越值钱。

整数字长可伸缩:RV32I / RV64I / RV128I。 同一套指令格式,XLEN(整数字长)参数化。RV64I 不是「重新设计一遍 64 位」,而是同一架构换参数——当年敢预留 RV128I(128 位地址空间),靠的就是这种参数化信心。

性能计数器进基座。 cycleinstrettime 三个只读计数器是架构强制的——论文还给了一段防撕裂的 64 位读取代码(RV32 上分两次读高 32 位并比对)。「测不了就优化不了」,这个信念写进了指令集。

RV32E 彩蛋:16 个寄存器的极简变体,专为 1 美元级的深度嵌入式芯片。为这么小的市场专门定义一个基座变体——「模块化」两个字的分量由此可见。

第 4 章:标准扩展——M、A、F/D 的取舍

基座故意「缺胳膊少腿」,缺的部分用扩展补:

M 扩展(乘除法)mul/mulh/div/rem 全家桶。妙的是 mulh(取高 32 位)单独成指令——编译器做 64 位乘法和定点运算时不再需要玄学技巧。除法语义也定了铁规矩:除零不触发异常,返回「全 1」——因为嵌入式系统里异常处理太贵,让软件自己查余数更划算。这种「把异常变约定」的决策贯穿整个 RISC-V。

A 扩展(原子操作):多核同步的地基。从 Dekker/Dijkstra 算法讲起(纯 load/store 互斥要 O(n) 次操作,不可扩展),最终方案是 LR/SC 对(load-reserved / store-conditional):LR 标记一块内存「我盯上了」,SC 尝试写入,若期间被别人插脚则失败重试。

对比 x86 的复杂指令前缀锁定(lock cmpxchg),LR/SC 的好处是:只需这两条指令就能实现锁、无锁队列、事务内存——理论上可扩展到任意复杂的原子序列,硬件不用为每种原子操作做专门电路。

F/D 扩展(单/双精度浮点):完整 IEEE 754-2008,32 个独立浮点寄存器。值得记住的细节:NaN 载荷可以携带自定义信息(比如把哪条指令产生的错误编码进去),这是很多老 ISA 没做对的。

第 5 章:RVC 压缩扩展——本论文最硬核的贡献

如果说前面是「设计」,这章就是「自证」:RISC-V Compressed(RVC)给指令集引入 16 位短指令,与 32 位指令自由混排。

设计哲学:无模式(modeless)

这是全章最重要的一词。Thumb-1 时代,ARM 用「模式切换」压缩代码——切到 Thumb 模式后只能跑 16 位指令,和 32 位指令互斥,函数之间切换模式有开销还有 bug 温床。

RVC 完全不同:RVC 不是独立 ISA,而是同一 ISA 的加密方式。处理器逐条取指,opcode 低位(00/01 象限)是 16 位指令,11 是 32 位指令,一条流水线上自然共存,不需要任何模式切换位

而且 RVC 有条铁律:压缩版指令必须和对应的 32 位指令语义完全一致——C 系列只是「常用指令的缩写」,不引入新语义。这保证了编译器生成 RVC 代码时零心智负担。

对基座的「预谋」

最见功力的一点:RISC-V 基座从第一天就给 RVC 留了位——32 位编码只用了一小部分 opcode 空间(对比 SPARC 那种大手大脚),寄存器编码位置设计成「常用 8 个寄存器 3 位可表示」。RVC 不是事后补丁,是基座设计时就写好的伏笔。

实测数据:说话要靠图

RVC 压缩效果

论文用 SPEC CPU2006 全套基准 + Dhrystone/CoreMark/Linux 内核做了横评:

  • RVC 相对纯 RV32I:静态代码体积平均省约 30%,取指流量同步下降;
  • 横向对比:RV32C 的代码密度超过了 x86-64 和 ARMv8——RISC 这个「指令多占空间」的老黄历,被 RVC 翻篇了;
  • 性能零损失:因为无模式、无新语义,RVC 只省空间不省性能。

这一章还留了一个精彩的「拒绝的艺术」小节:要不要像 Thumb/microMIPS 那样加 load-multiple/store-multiple(一次压栈 8 个寄存器)?团队反复权衡后拒绝了——压栈能用 16 位指令逐个编码,收益有限还占编码空间。「指令集架构师最重要的工作,是决定不做什么」——这句话值得每个做设计的人抄下来。

安全性一笔

变长指令有个经典安全隐患:跳到指令中间,字节流会被重新解释成另一条指令。论文讨论了 NaCl(Google 原生客户端)的分块校验思路如何适用——又一个「把别人踩过的坑都翻了一遍」的例子。

第 6 章:特权架构——把「地基」和「房子」分开

RISC-V 的用户态 ISA 和特权架构完全正交——用户态指令集在实时系统、桌面、服务器上通用,特权架构按需叠加。这个「用户 ISA 不绑定特权模型」的决策,是 RISC-V 能从 1 美元芯片铺到超算的结构性原因。

特权级别按需支持:

级别 名称 支持的组合
U 用户/应用 单独存在
S 管理者 M,U
H 虚拟机监督 M,S,U
M 机器/可信 全部
  • M-Mode:CPU 复制后所在层,管中断、时钟、异常。mstatus/mepc/mtvec/mcause 一套 CSR 是它的仪表盘;
  • S-Mode:操作系统层,sptbr(页表基址,后来改名 satp)、sepcscause 等;
  • CSRs 编码即权限:CSR 地址低位直接编码读写权限与最低访问级别(如 0xC00 的 cycle 用户可读),寄存器布局本身就是权限表;
  • 核间中断:多核必备,论文的实现里各核 CSR 直接映射到物理地址空间,互相写中断 pending 位即可。

2016 年当时 Hypervisor 模式还只是「预留了编码空间」——这份报告是诚实的:哪里做完了、哪里还没做,白纸黑字

第 7 章:未来方向——一份 2016 年的许愿单

结章很短,回看全是神预言:

  • 特权架构未完待续(后来有了 1.10 → 1.12 版本,H 扩展也在 2021 年定稿);
  • 多核内存模型待明确(后来发展为 RVWMO);
  • 更宽的地址空间(后来真的有了 RV128I 讨论);
  • 位操作、加密扩展(今天的 Zbb、Zk 系列扩展)。

对照今天 RISC-V 的实际演进,你会发现这份许愿单基本全部兑现——一个开放项目「边走边立规矩」的生命力,正是它和商业 ISA 最大的不同。

结语:设计教科书级的方法论

这份报告真正值得学的,不只是 RISC-V 本身,而是它示范的做设计的完整闭环

  1. 立项先「体检」:把所有先例的优缺点列成表,找到真正的空白点(第 2 章的 Table 2.1);
  2. 每个决策都有 why:47 条指令、无标志位、LR/SC、modeless 压缩,每一条都写清代价与收益;
  3. 用数据自证:RVC 不是「我觉得好」,而是 SPEC 全套基准跑出来的 30% 代码密度优势;
  4. 诚实标注未完成:预留 Hypervisor 编码空间、明确列 Future Directions,不装完人。

「指令集架构师最重要的工作,是决定不做什么。」——这份 117 页的论文,就是对这句话最完整的示范。


延伸阅读:本站《RISC-V 从入门到实战》(动手路线)、《计算机组成与设计 RISC-V 版精讲》(教科书视角);本文图片取自原报告插图,仅作学习讲解用途。原报告:UCB/EECS-2016-1,作者 Andrew Waterman。