[RISC-V指令集架构的设计] 为什么要发明一个新的指令集?

2020-07-25  本文已影响0人  znjw

最近看了篇UC Berkeley的RISC-V指令集设计的技术报告,主要是设计者们阐述设计思路,说明为何要如此设计,相当于RISC-V标准的补充文档了。里面第二章名为“为什么要发明一个新的指令集”,实则为“对所有其他指令集的吐槽”,跟说相声似的乐的不行。特此把此章节选翻译了一下。翻译水平不高,因为很多词汇对应的中文拿捏不准,见谅 。

英文文献地址

本文允许转载,但必须附上简书原址 https://www.jianshu.com/p/a543b092f312

本章中,作者解释了为何RISC-V项目要另起炉灶,而不是基于已有指令集进行修改。作者对已有的几套指令集进行了分析,解释了其为何不适合作为RISC-V项目的基础。节选翻译片段如下:

  1. MIPS
  2. SPARC
  3. Alpha
  4. ARMv7
  5. ARMv8
  6. OpenRISC
  7. 80x86

每段开头会有一段对指令集历史的介绍,和维基差不多,翻译中省去。想看黑成碳的直接跳到x86和ARM段即可

MIPS

…尽管学术用途上简单的MIPS-I微架构很好设计,但是这套指令集有一些技术缺陷,导致在高性能实现上差强人意:

除了技术因素以外,MIPS是私有指令集,在很多用途上并不适合。MIPS对非对齐load和store指令申请了专利,导致其他人无法完整实现此指令集。曾有一个案例,一个公司已经在其实现中移除了非对齐load和store,但仍遭到起诉,因为MIPS声称在内核中模拟这些指令仍然属于侵权。尽管现在这些专利已经过期,但MIPS商标仍属于Imagination;MIPS兼容的处理器必须由他们认证。

SPARC

…尽管如此,一些指令集设计上的决定导致其相比MIPS-I缺乏吸引力。

SPARC和其他1980年代的RISC指令集一样,都有很多短视的设计。其目标是实现一个单发射、顺序、五级流水线的处理器,所以指令集的设计包含了这种假定。SPARC加入了分支指令的延迟槽,以及各种短视的、暴露给上层的hazard,对软件编译和高性能实现都没有好处。另外,它也缺乏位置无关寻址能力。最后,SPARC无法添加压缩指令集,因为其没有预留足够的空闲编码空间。

和其他商业RISC不同,SPARC V8是一个开放标准,这一点归功于Sun。SPARC International对V8和V9延续了开放的许可政策,只需$99管理费。开放的指令集下涌现出了很多免费的设计,其中两个是Sun自己的Niagara微架构的衍生。尽管如此,SPARC的后续——Oracle SPARC Architecture——是私有的,而且高性能软件大概率会追随Oracle的脚步,逐渐抛弃老旧的开放SPARC。

Alpha

Digital Equipment Corporation (DEC) 的架构师们在1990年代设计Alpha时有很多前人经验可供学习。他们去除了很多早期RISC指令集中最不受欢迎的特性,包括分支指令延迟槽、条件码、寄存器滑窗,最终设计出了一个干净、简单、支持高性能的64位指令集。除此以外,Alpha的架构师们小心的将特权指令和硬件平台的细节隔离在了一个抽象接口之下——Privileiged Architecture Library (PALcode)

尽管如此,DEC仍然针对顺序执行微架构做了过度优化,加入了一些对现代处理器并不友好的特性:

Alpha的例子也突出了使用商业ISA的风险:他们可能会死亡。90年代末,Compaq收购了衰颓的DEC公司,不久之后,他们就决定暂停Alpha的开发,换用Intel的安腾架构。Compaq将Alpha的产权卖给了Intel。最后一款Alpha处理器在2004年由惠普(在收购Compaq之后)发布。

ARMv7

…精简ARMv7或者扩展它都是被明令禁止的;即使在微架构上进行创新也需要购买ARM所谓的架构许可。

即使知识产权上不存在障碍,ARMv7也存在一些技术缺陷,严重阻碍了我们使用其设计新指令集:

ARMv7既庞大又复杂。ARM和Thumb单单整数指令就超过600条。其整数SIMD和浮点扩展指令,NEON,又增加了数百条。即使法律上允许我们实现ARMv7,技术上我们也会有重大挑战。

ARMv8

…新的架构移除了ARMv7中一些增加复杂度的特性:比如,PC现在不再是一个通用寄存器;predication被移除;LDM和SDM被移除;指令编码更加规律。但是很多累赘仍然留了下来,包括条件码,以及一些不怎么那么通用的寄存器(链接寄存器是隐式的,x31在不同的上下文中要么是栈指针要么是0)。另外,更多的瑕疵被引入了,包括一个巨大的、事实上强制性的、subword长度的SIMD架构。总体上,这个指令集既复杂又笨重:一共有1070条指令,53种编码格式,8种寻址模式,需要5778页文档描述。既然如此,一堆重要特性的缺席未免让人感到吃惊:比如,仍然缺少比较后分支指令。

像大多数架构一样,ARMv8继续混杂用户指令和特权指令,时不时暴露底层实现。有一个让人无法理喻的例子——一个混杂了复杂语义、未定义行为、虚伪通用寄存器的特殊性质的例子——load-pair指令可能会给用户空间返回一个非精确异常。

如果指令编码标记了前变址寻址或者后变址寻址,并且(t==n || t2==n) && n != 31,那么以下三种行为之一可能会出现

  • 此指令未定义
  • 此指令被视为NOP
  • 此指令依照标注的寻址模式进行load,基址寄存器被设为UNKNOWN。另外,如果此指令过程中出现异常,基址寄存器数据可能会被损坏,此指令无法再被重复。

另外,随着ARMv8的推出,ARM停止了压缩指令编码的支持。Thumb指令集并未被带入64位中。从定长指令集的标准来看,ARMv8确实很紧凑,但是我们将会在第五章中提到,其无法与变长指令集比拼代码尺寸。不出所料,ARM第一款64位处理器的指令缓存相较于32位处理器增大了50%。

最后,ARMv8仍是一个封闭标准。其无法被精简,导致其实现嵌入式处理器和专用加速器时太笨重。事实上,使用这个指令集的情况下,根本无法设计一个强耦合的协处理器,因为除了ARM以外任何人都不能扩展它。即使架构师想在微架构上进行创新也需要一个昂贵的许可证,限制了可以设计ARMv8的人数。

OpenRISC

…就像DLX那样,其有一些技术缺陷限制了其应用前景:

我们2010年调研OpenRISC时,这套指令集还有两个额外的缺陷:强制的分支指令延迟槽,无64位支持。但必须称赞他们的是,这两个问题都被纠正了。延迟槽变为了可选,64位版本发布了(尽管据我们所知,还没有实现过)。最终,我们决定从头开始设计指令集,而不是基于OpenRISC修改。

x86

(编者按:重头戏来了)

…其如此流行的原因有很多:IBM PC中x86的无处不在;Intel对于二进制兼容的精益求精;他们微架构设计的激进前卫;以及他们生产工艺的遥遥领先。

但是指令集设计的品质可能不在其中。

1994年,AMD的80x86架构师,Mike Johnson,说出了那句名言:“x86真的没有那么的复杂——它只是毫无道理而已。”在那个时候,这句玩笑对x86的历史包袱轻描淡写。但是在过去二十年内,这句话显得如此的不靠谱:2015年的x86极度的复杂。现在有1300条指令,繁杂的寻址模式,大量的专用寄存器,众多的译址方式。毫不意外地,在AMD K5微架构率先试验成功后,所有的Intel乱序处理器都跟着采用了将x86动态翻译成类RISC指令的方案。

如果x86最终实现了更加高效的处理器的话,那么它的复杂性其实上可以接受。但是时至今日Johnson名言的下半句还是对的。是个人都会怀疑这个设计当初进行了多少考量

这些指令集设计上的决定对于静态代码尺寸有着深远的影响。我们将在第五章看到,本来可以实现非常高密度的编码,x86却根本没做到:IA-32只比定长32bit ARMv7密了一点点,x86-64比ARMv8甚至还稀疏了不少。

尽管有这些问题,x86编码程序时一般需要更少的动态指令数量,因为x86指令能编码多个基础操作。比如,C语句x[2]+=3在MIPS中编译成三条指令,但是IA-32只需要一条。在动态指令密度上的优势有以下好处:比如,它可以减少指令fetch单元的能耗。但是它也加大了实现的难度,无论什么级别的实现。在这个例子中,一般的流水线会产生两个structural hazard,因为这条指令执行了两次访存和两次加法。

最后,80x86是一套私有指令集。勇于实现x86微处理器去和Intel竞争的架构师大概率会面临法律上的挫折:历史上,Intel非常喜欢打官司,哪怕是自己被告反垄断的官司。

上一篇 下一篇

猜你喜欢

热点阅读