RISC-V:他们本应更清楚
摘要
Dmitry.GR 批评了RISC-V的设计,认为它并非对所有用例都最优,尤其是在微控制器领域,因为代码密度和中断延迟的问题。
<p><a href="https://lobste.rs/s/pu3yzg/risc_v_they_should_have_known_better">评论</a></p>
查看缓存全文
缓存时间: 2026/08/14 19:34
# RISC-V:他们本应更清楚 - Dmitry.GR
来源:https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts
RISC-V:他们本应更清楚
## 目录
1. 为所有人提供一切 (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_7ee90f1aff8577b64b1f388c92ba12d2)
2. 可选性 (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_4ced7b79eb1d4cceebd5e3ae666ba5fa)
3. 缺失显而易见的部分 (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_81e58a7d3a7f2a7a9bf1e198085aa4c6)
4. 荒谬的编码 (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_80fd4ec9e84689c9a0e4be38e9a9bf29)
5. 貌似合理的修正 (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_1e7bceb85b3c9ff409fc006c5fea2d9f)
6. 我们如何陷入此境,又该往何处去? (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_b37e564a22dc948ba370e91cff386548)
7. 这是否意味着 RISC-V 注定失败? (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_77273826e5e870a86d03ca0ee6a9f959)
8. 评论... (https://dmitry.gr/?proj=12.+RV&r=06.+Thoughts#_TOC_7e1e75c32bc9b275daf70df8cba8efb5)
经常有人问我解释为何不喜欢 RISC-V,而我发现自己总是零零碎碎地解释。他们的反应通常是"你只是不理解这一切的精妙之处",这当然根本算不上论据。在第 N 次被要求解释后,我决定把一切都写在一个地方,这样下次被问到时,我可以直接链接到这里。此外,如果有人希望,他们可以以本文为参考,清晰详细地引用我的观点来形成一个连贯的反驳。文中所有观点均为我个人意见,不代表我的雇主、任何神祇或我的房东的看法。我的猫们部分同意,部分反对,并将在稍后发表它们的意见。
## 为所有人提供一切
RISC-V 最终将占据极其廉价的单次使用微控制器领域。并非因为其 ISA 设计,而是尽管其如此。
第一个也是最简单的问题是,不可能对所有用例都最优。RISC-V 的粉丝会让你相信,RISC-V 很快将主宰所有超级计算机,同时也将主宰所有微小的微控制器用例,以及介于两者之间的一切。这是不可能的,对任何 ISA 来说也同样不可能。简而言之,高端 CPU 所需的东西与小成本节约型微控制器内核所需的东西截然相反。设计选择不仅影响微架构,实际上(也必然)会影响 CPU 架构本身。但就我所知,我 100% 确定 RISC-V *将*最终占据极其廉价的单次使用微控制器领域。并非因为其 ISA 设计,而是尽管其如此。它将通过改进 8051 而从其手中夺取这个角色——这是一个如此之低的门槛,仅仅是一个减速带而已。
廉价的微控制器内核需要什么?让我们看看它们的用途。典型用例是在更大的芯片中与硬件模块接口并快速重新配置它们,例如在 MP3 播放器、SD 卡或 USB 设备中。繁重的工作由定制 IP 完成,CPU 内核只是偶尔拨动寄存器或配置某些东西。在此情况下,重要的是中断延迟(越低越好)和尺寸(越小越好)。通常,你不会期望在这种内核上进行太多数学运算。大规模生产的成本缩减设备会让代码从真正的 ROM(如果不可更新)或 RAM(如果可更新)运行;NOR 闪存成本太高,对于真正大规模生产的东西来说不是选项。当从 ROM 运行时,代码大小很重要,因为 ROM 并不十分紧凑。当从 RAM 运行时,代码大小很重要,因为 SRAM 也会在芯片上占据大量空间。因此,代码密度对这些用例很重要。由于不预期进行太多数学运算,像硬件除法器(甚至乘法器)这样的东西可以摒弃。在这种单次使用情况下,也无需权限分离——不会期望从外部获取不可信代码。但是,你可能会说,"你刚刚描述了 RV32IC(或 RV32EC)!"
因此,在这种嵌入式内核唯一的目的上,RISC-V 明显比现有的领先竞争对手更差。
确实,它有些接近,但实际上你需要 RV32I_Zicsr 才能声称这点。没有 Zicsr,没有符合规范的方式来处理中断,因为没有临时位置来暂存寄存器以便你可以暂存其余寄存器。MIPS 为这个目的保留了两个寄存器($k0 和 $k1)。没有它们,RISC-V 需要 mscratch/sscratch。没有 Zicsr,你没有这些,只能坚持用奇怪的其他方法来做事情。于是我们回到了 8051 的领域——它专精于用奇怪的方式做事。小型嵌入式内核不是乱序执行怪兽。如果你能从它们那里每个周期得到一条指令,你就该感到幸运了。考虑到这一点,让我们乐观地计算中断处理程序需要多少个周期来暂存 ABI 要求的寄存器并调用一个用 C 编写的处理程序。首先,我们用一个 CSRRW 来暂存一个寄存器(为方便解释,假设是 t0)并获取一个基地址,用于暂存其余部分。然后我们需要暂存 ra, sp, gp, tp, t1-t6 以及 a0-a7。接着我们需要使用另一个 CSRRW 来取回旧的 t0 值并同样暂存它。这*至少*需要 21 个周期。退出时,计算类似:一个 CSRRW 读取暂存寄存器的地址,以及 19 次加载来加载它们。这*至少*需要 20 个周期。但这还不是全部。由于这必须用汇编语言完成,我们需要实际计算跳转到我们的 C 处理程序的 JAL 和从那里返回的 RET。我们大方地假设它们各需要两个周期。因此,每个中断在 C 处理程序开始做任何工作之前,至少有 44 个周期的开销。Cortex-M0(竞争的廉价 32 位内核)进入中断需要 15 个周期,退出需要 12 个周期,并且由于它在硬件上推送 ABI 损坏的寄存器,处理程序可以直接用 C 编写。因此,这里每个中断只有 27 个周期的开销。哦...那快多了!你可能会抗议我不公平,因为没有考虑 RV32E。通过拥有一半的寄存器,它可以将初始推送加快 6 个周期,弹出也类似,使其开销为 38 个周期。仍然比 Cortex-M0 多三分之一以上。哦...因此,在这种嵌入式内核唯一的目的上,RISC-V 明显比现有的领先竞争对手更差。CLIC*和*各种专有的 "快速 IRQ" / 自动堆栈扩展的存在是额外的控诉。基础 ISA 迫使厂商发明非标准的硅片以达到与十年前的 Cortex-M0 相当的水平。这反过来进一步碎片化了"标准"(如果可以这样称呼的话)。滑稽的是,即使有压缩扩展,典型的 IRQ 序言也比 Cortex-M0 的零字节硬件路径更大更慢。
现在,谈谈那些压缩指令。让我们详细看看它们。它们的设计简直糟糕得令人发笑。假设你想将一个字节存储到寄存器加偏移量。一个 16 位指令能编码多大的偏移量范围?零到三。不是三十三,也不是三百零三。三!嗯,也许存储半字更好?不...零或二。这到底是什么?为什么?至少存储字时,你能得到一个合理的范围,零到 124 字节,但其他的那些是怎么回事?更糟的是,存储半字的指令编码方式类似于存储字节的指令,但不知何故它的偏移量选项更少?为什么?嗯,存储字节使用的一个用于偏移量的位被硬连线为零...它本可以用来将范围至少扩展到 6,但它没有!相比之下,Cortex-M0 很乐意让你对字节使用零到 31 的偏移量,对半字使用零到 62,对字使用零到 124——显然这覆盖了更多的用例。那么这里发生了什么?说实话,我不知道,但这确实难以合理解释。一个典型的托词是对于这些更大的偏移量,只需使用全长度指令。当然,但密度会受损——正是 RISC-V 粉丝最近在吹捧 C 扩展时所夸耀的那种密度。但等等,还有更多。那些存储字节和半字的指令甚至不在 C 扩展中。它们在另一个叫做 Zcb 的扩展中,所以即使它们微不足道的范围在你的情况下足够用,你可能根本无法访问它们。我们稍后会谈到"扩展"。
服务器内核需要什么?原始吞吐量。这里,我们处于乱序内核的世界,硅片或多或少是免费的,因为无论你的内核多大,缓存都会使其相形见绌。现代乱序内核一次解码八条甚至十条指令,并同时发射到多个端口;许多现代内核可以在同一周期处理多条分支指令(想一想,让它沉淀一下...是的)。代码密度在这里确实不像过去那样是主要顾虑。它仍然重要,但制作一个稍大的 L1i 并不复杂,而且再次强调,在这类小东西上,硅面积或多或少是免费的。你真正想要的是能够尽可能轻松地同时获取和解码尽可能多的指令。在做这件事时,如果指令能尽可能多地透露其意图也会有所帮助,以便你可以最高效地将它们与其他指令合并或拆分成片段。表面上,这两个愿望相互矛盾,在某种程度上确实如此。"易于解码"众所周知,拉丁语意思是"固定长度",而"尽可能多"希腊语意思是"长"。显然我们不想要固定长度的超长指令。我们在哪里划线?让指令长度为 2 的幂次方使得许多其他事情(如对齐)更容易,那么接下来呢?两个字节太短。八个字节太长。答案是固定长度的 4 字节指令是一个很好的折中。它提供了足够的编码空间来编码几乎任何你想要的东西,即:每条指令编码 3 个寄存器,分支指令有长偏移量。为什么这听起来很耳熟?因为 aarch64(和 A32)已经证明这非常有效。MIPS 出于同样的原因做出了相同的选择。
你现在可能抗议 ARM 也有 Thumb,MIPS 有 microMIPS。然而,在高性能计算领域,Thumb 已经死亡。当 Apple 与 ARM 一起设计 aarch64 时 (https://web.archive.org/web/20210106015533/https://twitter.com/stuntpants/status/1346470705446092811),大量的建模和测试表明,对于每瓦指令数和每秒指令数来说,它都是净损失。如果 MIPS 能活得足够长以达到当前的成本/晶体管状况,MIPS 肯定也会杀死 microMIPS。主要的关键点是,压缩指令在大型内核中没有用武之地,它们通过使查找边界变慢而阻碍了快速并行解码多条指令。你可能抗议说 "RISC-V 使得查找指令长度很容易",但 "容易" 不等于固定长度指令给你的 "即时且免费"。
他们花了**两年时间**才意识到数组的存在!
回到我们对高性能内核需要展示的原始性能的讨论。任何代码执行的最常见操作之一是什么?数组访问。这就是为什么 x86 有像 [ebx + esi * 4] 这样的寻址模式,ARM 有 [R0, R1, LSL #2]。没有它,你就被迫像傻瓜一样,先将一个寄存器左移两位,然后将其加到另一个寄存器,最后才用那个来访问内存。一次数组访问需要三条指令。对这种不可原谅的缺乏远见,通常的借口是 "指令融合会在快速内核中将这三条指令融合成一条"。是的...如果有人能做到这点,他们将赢得许多奖项。据我所知,没有内核能融合超过两条连续指令。没有。原因相当明显——需要考虑、跟踪和处理的组合爆炸式可能组合数量。所以既然我们已经确定那个屁话借口就是个屁话,那能做什么呢?嗯,在规范发布*多年*后,一个扩展被提出以帮助解决这个问题——Zba。它提供三种形式为 SHxADD 的指令,x 为 1、2 或 3。这结合了移位和加法,基本上将我们的数组访问从三条指令缩短为两条。这仍然比拥有寄存器 + 移位寄存器寻址模式要差,但至少现在 "内核可以融合它们" 变得不那么扯淡且更可信,假设有人能制造出这样的内核。问题在于:SHxADD 总是 4 字节长,而内存访问指令本身是 2 或 4 字节,所以数组访问变成 6 或 8 字节代码,而 ARM 是 4 字节。这就是所有那些刚才还在为 C 扩展的密度及其对高性能内核的巨大好处而欢呼的人们悄悄闭嘴并看着地板的原因。是的...作为加分项,Zba 扩展直到 2021 年才正式批准,距离基础规范发布已超过两年。他们花了*两年*才意识到数组的存在!
当你能成功让高通听起来像是理性的声音时,你就知道你真的搞砸了。
奇怪的是,这很容易修复。目前 3/4 的编码空间分配给了压缩指令(所有低 2 位不是 0b11 的指令)。将一些编码空间重用于更好的寻址模式是明智之举,将产生更密集的代码和更好的数组寻址能力。不幸的是,这太有道理了,以至于没人会真正去做。在所有可能的理智捍卫者中,高通...提出了这样做,甚至制作了原型。但无疾而终...当你能成功让高通听起来像是理性的声音时,你就知道你真的搞砸了。但是,回到我们的 SHxADD。无法保证你会使用它们,因为 Zba 是一个扩展,因此是可选的。你是否已经厌倦听到 "可选" 了?让我们接下来讨论这个。
## 可选性
RISC-V 与 USB-C 和 RCS 有何共同点?这些表面上都是标准,没错,但有趣的是,声称符合其中一项标准意味着毫无意义,同时技术上又是真实的。我的 USB-C 线缆只接线用于 USB 2.0 有效吗?当然,USB 3 扭绞线对是可选的。我的非电子标签线缆有效吗?当然,电子标记器是可选的。我的 USB 3.0 USB-C 线缆可以选择不支持 20Gbps 吗?当然,20Gbps 支持是可选的。它可以支持 20Gbps 但不支持 100W 充电吗?当然,那也是可选的。我手机的完全符合 RCS 规范的实现可以不支持将文本消息升级为视频通话吗?当然!MIVC 是可选的。它可以在通话时无法发送图片吗?当然,那是可选的!可以不支持加密吗?当然,那也是可选的!那么,如果一切都是可选的,符合规范到底意味着什么?基本上意味着规范编写者花了太多时间进行脑内自慰,而与现实世界接触太少。这有两种方式发生:学者没有意识到办公室外有现实世界的存在,以及委员会设计情况,现实中的人根本没有席位——未能及时提出动议以让主席将其付诸表决。
看看这句话:"RISC-V B(位操作)扩展是一组标准的指令集增强集合,旨在通过高效的位级操作提高性能和代码密度。它被分为不同的子扩展:Zba、Zbb、Zbc 和 Zbs。" 只有委员会设计流程才会如此一本正经地产生这一系列文字。
编写规范时,你将每件事设为可选,你就分裂了...
相似文章
第三世界嵌入式工程师回应“RISC-V: They Should Have Known Better”
一位来自第三世界的嵌入式工程师对文章‘RISC-V: They Should Have Known Better’作出回应,分享了关于RISC-V架构及其影响的见解。
RISC-V 势不可挡:State of the Union 主题演讲指出
在 RISC-V 欧洲峰会 2026 上,Krste Asanović 宣布开放标准 ISA 状态强劲,并强调其扩展至高性能服务器级芯片,以及被 Qualcomm、Nvidia 和 Google 等主要科技公司采用。
书籍:RISC-V系统芯片设计
一本涵盖RISC-V微处理器和系统芯片详细设计的教材,包括用于单发射、超标量和多核实现的开源SystemVerilog代码和测试用例。
突破 RISC-V 模拟的极限
这篇博客文章探讨了如何通过在非 RISC-V 机器上使用提前重编译器来加速 RISC-V 执行,该重编译器通过尾调用连接基本块,并利用 Clang 的 preserve_none 调用约定,作为 Axiom 的 OpenVM 项目的一部分。
RISC-V 与浮点运算
关于 RISC-V 架构浮点功能及更新的报告。