第 1 章
不存在的第二条路
VAX-11/780的技术手册没有前言。它从第1页直接进入指令编码表,每条指令占据一行,操作码、操作数格式、执行周期数、受影响的标志位,排列得如同电话簿。第127页定义了一条用于多项式求值的指令,硬件直接支持霍纳算法的迭代步骤。第203页是队列操作指令,维护头尾指针的原子更新。第311页是循环冗余校验指令,将原本需要数十行汇编代码的比特流计算压缩为单条指令的一次调用。这本手册在1980年秋季的修订版中厚度增加到超过600页,而DEC的工程师们已经在为下一版准备新增的指令条目。这不是某一家公司的技术偏好。DEC的VAX架构只是最显眼的样本。同一时期,摩托罗拉68000的参考手册在梅萨的实验室里逐章成型,最终定义了14种寻址模式和超过80条指令。Intel的8086指令集手册列出了从1字节到6字节不等的可变长度指令编码,其后续产品80286的规划文档中,新增的保护模式指令和内存管理原语正在逐月增加。
每一家主流微处理器厂商都在同一方向上推进:指令集应该增长,应该更贴近高级语言的语义结构,应该用硬件直接实现程序员最常用的操作序列。这不是阴谋,不是某个技术委员会的决策失误。这是一种产业共识,它在1970年代末已经牢固到不需要任何论证就可以支配设计决策的程度。要理解这个共识的结构,需要回到更早的起点。1964年4月,IBM宣布System/360系列时,它引入了一个在当时看来激进的主张:一个统一的指令集架构将跨越从低端到高端的所有机型。客户可以在不重写软件的情况下升级硬件。这个承诺的商业力量是压倒性的。到1960年代末,System/360及其后续产品已经锁定了大型机市场的主流客户群。竞争对手不是没有更好的技术方案——Burroughs的B5000系列拥有更优雅的堆栈架构,CDC的6600在科学计算领域性能领先——但它们都无法撼动IBM的生态优势。软件投资的重力比任何硬件参数都更沉重。
System/360确立的技术范式包括一个关键组件:微码。微码是一层介于机器指令和硬件执行单元之间的软件,它将每条复杂指令翻译成一系列更简单的内部操作。这个设计的原始动机是工程上的务实考虑:它允许硬件实现逐年优化而不破坏指令集的外观。当IBM在1970年推出System/370时,底层电路完全重新设计,但客户看到的指令集基本不变。微码还降低了指令集扩展的边际成本。添加一条新指令不再需要重新设计整个控制逻辑,只需要在微码存储中增加一段新的翻译序列。这个便利在短期内是真实的收益,但它也移除了指令集膨胀的主要制动机制。在微码出现之前,每条新指令都意味着控制单元硬连线的复杂度增加,设计者必须审慎权衡。微码让这种审慎变得不再必要。到1970年代中期,半导体工艺的进步为这个范式注入了新的燃料。摩尔定律在1975年的修订版中调整为每两年晶体管数量翻倍,这个速率一直保持到1980年代初期。每一代新工艺节点都释放出更多的晶体管预算。
1971年Intel 4004的2300个晶体管在1974年变成8080的4500个,在1978年变成8086的29000个,在1979年摩托罗拉68000达到了68000个。这个增长速度产生了一个具体的心理效应:硬件复杂度看起来是免费的。如果下一代工艺可以容纳两倍的晶体管,而其中一部分可以分配给更丰富的指令集,那么从单个项目的角度看,这似乎是不需要论证的合理选择。没有人需要为晶体管预算的浪费负责,因为预算本身在持续增长。但这个计算忽略了一个关键变量:验证成本。每条新增指令不仅消耗晶体管,还需要在所有可能的操作数组合、边界条件和异常状态下进行测试。指令之间的交互数量以组合方式增长。VAX-11/780的微码验证耗费了DEC工程团队的大量时间,而且随着指令集的膨胀,后续产品的验证周期持续延长。到1980年,一个完整的微处理器设计周期已经从早期的18个月延长到3年以上。
这些成本被分散到多个财年和多个部门,没有在任何一份管理报告中以总成本的形式呈现。DEC的硬件设计团队不负责计算软件维护的成本。市场部门不负责计算芯片面积的浪费。微码工程师的绩效评估基于他们实现了多少条新指令,而不是他们避免了多少条不必要的指令。组织结构的碎片化是这个问题的重要维度。在一家典型的小型机或微处理器公司中,指令集的定义过程涉及至少四个独立的决策层:系统架构师确定整体设计目标,微码工程师负责将指令翻译成内部操作序列,硬件设计师负责实现执行单元,市场部门负责收集客户对功能的需求。这四个群体的激励并不一致。系统架构师可能倾向于简洁的设计,但他们的权威在1970年代末已经被微码工程师的专项知识所侵蚀。微码工程师对指令集的丰富程度有直接的职业利益——他们的工作是将复杂指令分解为微操作,指令集越复杂,这项工作的技术含量就越高,他们的不可替代性就越强。
硬件设计师关注芯片面积和时序收敛,但他们通常只在设计周期的后期才介入,此时指令集的大部分已经冻结。市场部门则不断从客户现场带回需求:客户想要更快的字符串处理,客户想要更便捷的十进制运算,客户想要与上一代机器完全兼容。兼容性这个要求本身是合理的。一家保险公司在1975年为它的理赔系统购买了VAX-11/780,编写了数十万行COBOL代码。当DEC在1980年推出升级机型时,这家公司期望它的软件无需修改就能运行。如果DEC不能满足这个期望,这家公司在下一次采购时就会考虑其他供应商——或者更准确地说,它会选择那个能够保证兼容性的供应商。这个市场逻辑在大型机时代已经被反复验证。IBM在1960年代用System/360的兼容性承诺击败了多个技术更先进的竞争对手。这个教训被整个产业吸收。到1980年,向后兼容已经成为微处理器市场的基本准入条件,而不是差异化优势。兼容性的技术代价是指令集的单向锁定。
一旦某个指令编码被分配给一条特定的操作,它就永远不能被重新定义,因为可能有某个客户的某个程序依赖那个编码。即使测量数据表明某条指令在99.9%的应用程序中从未出现,删除它仍然不可接受——那0.1%的客户可能是最重要的企业用户。结果是指令集架构的演化变成了纯粹的叠加过程。新指令被追加到操作码表的空白区域。旧指令即使被证明低效或冗余,也永久保留。微码引擎必须同时支持从最早版本到最新版本的所有指令,其复杂度不是线性增长,而是随着指令之间的交互以更陡峭的曲线上升。VAX系列从1977年的243条指令增长到1980年代中期的超过300条,微码存储的容量增加了数倍,其中相当比例用于支持那些使用频率极低的指令。这个系统在1980年仍然是自洽的。晶体管预算在增长,验证成本被分摊,兼容性的市场收益显而易见。没有任何一家主流厂商的内部力量足以挑战这个均衡。但均衡不等于最优。它只是意味着系统内部没有足够的动力去改变。
在产业主流之外,一些不同的观测正在积累。1975年,IBM托马斯·沃森研究中心的约翰·科克启动了一个名为801的实验项目。科克的背景是编译器设计,而不是硬件工程。他的问题不是“如何用硬件支持更丰富的指令”,而是“编译器实际上需要哪些指令”。他的团队对IBM System/370上实际运行的程序进行了动态指令跟踪,测量了每一条指令的执行频率。结果令人不安:大约20%的指令占据了超过80%的执行时间。大量精心设计的复杂指令——字符串翻译、十进制除法、多字段格式化——在绝大多数工作负载中从未被调用。它们存在的唯一功能,是让汇编语言程序员在编写特定类型的代码时少打几行字。但汇编语言编程本身正在被高级语言编译器取代。当程序员用FORTRAN或COBOL编写应用程序时,编译器生成的指令序列只使用了指令集的一个精简子集。那些为汇编程序员设计的复杂指令变成了硅片上的装饰品。
科克的团队提出了一个反向的设计原则:从编译器优化器的需求出发,定义最小化的指令集。所有指令都在一个时钟周期内完成。只有加载和存储指令访问内存,所有运算都在寄存器之间进行。微码引擎被完全取消——指令直接由硬件执行。801项目在1979年完成了一台原型机,其性能在多个内部测试中超过了同时期的IBM商业产品,但使用的晶体管数量少得多。然而,IBM没有将801商业化。System/370的生态投资太大,兼容性承诺太深,精简指令集的设计在公司内部被视为一项有学术价值但商业上不可行的探索。科克的论文在内部流传,部分内容通过会议演讲和预印本扩散到了学术界。加州大学伯克利分校的大卫·帕特森在1979年读到了801项目的相关材料。他当时正在寻找一个研究生课题,能够让学生在一个学期内完成从架构设计到芯片布局的完整处理器设计流程。VAX那样的复杂指令集显然不可能在学术环境中复现。帕特森决定尝试科克的精简思路。
他的团队定义了31条指令,建立了加载-存储架构,取消了微码,采用单周期执行和流水线技术。整个设计由几个研究生在几个月内完成。他们把这个项目命名为RISC-I,精简指令集计算机。1980年发表的论文包含了详细的性能对比数据:在相同的基准测试中,RISC-I的每时钟周期指令执行数超过了VAX-11/780,而芯片面积和功耗只是后者的一小部分。几乎同时,斯坦福大学的约翰·轩尼诗启动了MIPS项目,从编译器优化的角度得出了类似的结论。轩尼诗的团队证明,一个精心设计的精简指令集配合流水线调度优化,可以实现比复杂指令集更高的有效吞吐量。复杂指令的优势——单条指令完成更多工作——被它们消耗的额外时钟周期所抵消。一条VAX的多项式求值指令可能需要数十个微码周期才能完成,而用简单指令组合实现同样的计算,在流水线充分填充的情况下,总时钟周期数可能更少。
更重要的是,精简设计释放了芯片面积用于更快的寄存器文件和更大的缓存,这些资源的性能收益超过了复杂指令的微码加速。这些学术发现在1980年代初的计算机架构会议上引发了激烈辩论。DEC的工程师指出,VAX的复杂指令在操作系统内核和中断处理等特定场景中确实提供了性能优势。摩托罗拉的团队强调,68000丰富的寻址模式使得C语言编译器的代码生成更加直接。Intel的代表则认为,向后兼容的商业价值远远超过任何架构效率的损失。这些论点都有各自的数据支撑。帕特森和轩尼诗没有在所有的基准测试中胜出。他们证明的是,精简指令集可以接近甚至匹敌复杂指令集的性能,同时大幅降低设计复杂度和硬件成本。这个结论在1980年还不是决定性的,但它打开了一个之前被产业共识封闭的选项空间。然而,学术论证不足以改变产业方向。伯克利的RISC-I和斯坦福的MIPS都是大学实验室的原型,没有商业软件生态,没有客户基础,没有兼容性承诺的负担。
它们的存在证明了精简设计的技术可行性,但没有回答一个关键问题:一家真实的公司,面临着真实的客户、真实的竞争对手和真实的财务约束,如何能够从复杂指令集的轨道上脱离。这个问题的答案不在伯克利或斯坦福的实验室里。它将在1980年代早期,在一个与主流产业几乎完全隔绝的环境中,由一家挣扎求生的英国小公司被迫给出。1980年的Acorn Computers还不知道RISC这个缩写。这家位于剑桥的公司刚刚从一家名为CPU Ltd的咨询机构中分离出来,专注于基于6502处理器的微型计算机。它的第一款产品Acorn System 75使用的是国家半导体公司的SC/MP处理器,一个早已过时的8位芯片。公司的工程师团队规模很小,但包括了一些在剑桥大学计算机实验室受过训练的人。他们熟悉当时的微处理器市场格局:6502便宜但功能有限,Z80兼容性好但性能平庸,8086性能更强但价格昂贵且需要复杂的外围芯片。
1980年,Acorn推出了Atom,一款面向爱好者和教育市场的低成本计算机,仍然基于6502。Atom的设计团队已经开始讨论下一款产品,代号“质子”。他们需要选择一颗能支撑未来几年产品线的处理器。这个选择在1980年看起来并不困难。摩托罗拉68000是技术上的领先者,苹果已经选定了它用于Lisa项目。Intel的8086正在成为IBM PC的标准。Zilog的Z8000也有一定的市场。Acorn的工程师们评估了这些选项,发现了一个共同的障碍:价格。作为一家小型公司,Acorn的采购量不足以获得有竞争力的芯片单价。更糟糕的是,这些新一代16位或32位处理器的外围芯片——内存控制器、中断控制器、DMA控制器——同样昂贵,而且通常需要从同一家供应商捆绑采购。Acorn的财务状况不允许这种水平的投入。公司1983年的盈利达到了860万英镑,但在1980年,这个数字还远未实现。
Acorn的工程师们开始考虑一个在主流产业看来近乎荒谬的选项:自己设计处理器。这个想法在1980年提出时,几乎违反了所有的产业常识。处理器设计被认为是资本密集、人才密集、周期漫长的活动,只有Intel、摩托罗拉、DEC这样的巨头才能承担。但Acorn的团队注意到了一些不同的信号。他们访问了美国西海岸的半导体公司,看到了伯克利和斯坦福的研究成果。他们参观了VLSI Technology公司的设计中心,了解到一种新的设计方法论正在兴起:用高级语言描述硬件逻辑,通过计算机辅助工具自动生成芯片布局。这种方法的效率远高于传统的手工晶体管级设计。更重要的是,VLSI Technology愿意为小型客户提供制造服务,将他们的设计转化为实际硅片。Acorn的工程师史蒂夫·弗伯和罗杰·威尔逊开始认真研究精简指令集的可能性。他们的计算表明,一个简单的32位处理器,只包含最必要的指令,可以在25000个晶体管内实现。
这个数字在1983年是可以管理的——VLSI Technology的3微米工艺可以轻松容纳。相比之下,摩托罗拉68000使用了68000个晶体管,Intel 80286使用了134000个。Acorn的设计在复杂度上低了一个数量级。这意味着更短的设计周期、更低的制造成本、更少的功耗。对于一家资金紧张的小公司而言,这些不是理论上的优势,而是生存条件。这个选择在当时被主流产业视为边缘案例。Acorn不是一家处理器公司,它的自研芯片不会对Intel或摩托罗拉构成威胁。但正是这种边缘位置赋予了Acorn一种主流厂商已经失去的自由:它没有需要兼容的旧指令集,没有需要保护的软件生态,没有微码工程师团队要求增加指令以证明自身价值。当弗伯和威尔逊在1983年开始设计ARM架构时,他们面临的设计约束与DEC或Intel的工程师完全不同。他们不是在现有指令集上叠加新功能,而是在一张白纸上定义最小化的指令集。
这种设计哲学并非凭空产生。弗伯和威尔逊在剑桥的实验室里没有使用复杂的指令跟踪工具,但他们有一个更直接的约束:晶体管预算。25000个晶体管意味着每一个逻辑门都必须被严格审计。ARM1的设计过程中,每一条指令的增加都伴随着一个不可回避的问题:它消耗的晶体管能否在性能上获得等价回报?这个问题的答案在绝大多数情况下是否定的。复杂寻址模式需要额外的地址计算硬件。多周期指令需要状态机来控制微操作序列。微码引擎本身就需要数千个晶体管来存储控制序列。当弗伯将ARM1的指令集精简到45条时,他实际上是在执行一种在主流产业中已经消失的纪律:将硬件复杂度视为必须被最小化的成本项,而非可以无限透支的信用额度。
这种纪律的消失并非偶然。在DEC或Intel的组织结构中,没有任何一个角色被赋予“复杂度审计”的职责。系统架构师定义指令集的功能规格,但他们不直接承担芯片面积和功耗的后果——这些后果由硬件设计团队在数月之后才会面对,而那时指令集已经冻结。硬件设计师可以抱怨某条指令实现起来过于复杂,但他们没有权力删除它,因为市场部门已经向客户承诺了兼容性。微码工程师是唯一有动力处理复杂度的群体,但他们的处理方式是将其吸收到微码层中,而不是消除它。结果是一个三方共谋的结构:架构师添加指令以满足功能清单,市场部门要求指令以保护客户投资,微码工程师将指令翻译为内部操作序列从而使添加指令的成本看起来可控。没有任何一方有动力说“不”。而说“不”恰恰是精简指令集设计的核心动作。
Acorn的处境打破了这种共谋。弗伯同时扮演了架构师、硬件设计师和微码工程师的角色——实际上,ARM1根本没有微码,所以最后一个角色被完全取消。市场部门的需求不是来自外部客户,而是来自Acorn自身的下一代产品计划。当弗伯决定ARM1不支持乘法指令时,他不需要经过任何委员会的批准。他的理由是:乘法器需要消耗约3000个晶体管,超过总预算的十分之一,而乘法操作可以通过加法序列在软件中实现。这个决定在DEC或Intel是不可想象的——VAX和8086都提供了硬件乘法指令,因为客户期望如此,因为竞争对手已经提供,因为微码工程师可以处理它。但弗伯的计算是:用3000个晶体管换取更大的寄存器文件和更高效的流水线,对整体性能的提升超过硬件乘法器带来的收益。这个判断后来被证明是正确的,但更重要的是,它能够被执行。Acorn的组织结构没有为指令集膨胀提供任何制度性的推动力。
这种自由是有代价的。ARM1在1985年问世时,没有任何第三方软件可以运行。它没有操作系统,没有编译器,没有应用程序。Acorn的工程师们必须自己编写一切:从汇编器到BASIC解释器,从简单的调试工具到初步的操作系统内核。这与IBM PC形成了残酷的对比。当IBM在1981年推出PC时,它已经拥有Microsoft的BASIC、Digital Research的CP/M操作系统、以及大量第三方应用程序。兼容性承诺的商业力量在这里表现得最为清晰:IBM PC的客户不需要等待软件生态的建立,因为8086的指令集已经存在了多年,开发者社区已经围绕它形成了成熟的工具链。ARM1的客户——最初只有Acorn自己——必须从零开始构建一切。这解释了为什么精简指令集的思想在学术上被证明可行之后,仍然需要近十年的时间才能获得商业牵引。技术优势本身不足以克服生态缺失的劣势。需要额外的条件:一个足够大的市场,其中的客户对兼容性的需求较弱;一个足够小的核心应用集,使得软件从零开发是可行的;或者一个足够低的芯片成本,使得精简设计的经济优势可以压倒生态劣势。
这些条件在1980年代中期的嵌入式系统中开始缓慢出现。移动电话、打印机控制器、磁盘驱动控制器——这些设备中的处理器不需要运行大型操作系统或继承数十年前的代码库。它们需要的是低成本、低功耗和足够处理特定任务的性能。这正是精简指令集设计天然擅长的领域。但这条路径在1985年仍然模糊不清。Acorn的ARM1被用于公司的Archimedes个人计算机,这款产品在英国教育市场取得了一定的成功,但从未对Intel的全球主导地位构成威胁。精简指令集的商业突破需要等待另一个条件:一家拥有足够市场影响力的大型公司愿意承担生态建设的成本,将精简指令集从边缘带入主流。这个条件在1980年代后期才开始成形,而它的出现依赖于一个与计算机架构完全无关的产业变动——移动通信的兴起。但在1980年,所有这些都还隐藏在未来的迷雾中。产业主流看到的是一张天衣无缝的网:晶体管预算在增长,指令集在膨胀,兼容性在锁定,没有任何内部力量足以撕裂这个自洽的系统。
每一条候选指令都必须证明自己的必要性:它是否被编译器频繁使用?它是否可以在一个时钟周期内完成?它是否增加了控制逻辑的复杂度?如果答案不令人满意,它就被删除。这种设计哲学在1980年代早期的产业主流中是找不到的。它来自一个特定的处境:资源极度有限,兼容性负担为零,决策权集中在两三个工程师手中,没有任何组织部门能够为了自身利益而推动指令集膨胀。Acorn的绝境不是精简指令集思想的起源——伯克利和斯坦福已经提供了学术论证——但它是将这种思想转化为商业产品的第一个真实案例。而它之所以能够做到这一点,恰恰是因为它被排斥在主流产业的封闭系统之外。1985年4月26日,VLSI Technology制造出了第一颗Acorn RISC处理器,ARM1。它只有25000个晶体管,没有乘法部件,功耗低到可以用电池驱动。同一年10月17日,Intel发布了80386,集成了275000个晶体管,向后兼容8086和80286的所有指令。
ARM1在性能上无法与80386竞争,在市场影响力上也是微不足道。但它的存在证明了一件事:那条看似不可动摇的技术逻辑——指令集必须持续增长,复杂度必须持续增加,向后兼容是唯一可行的道路——并不是唯一的选项。另一条路在技术上是可行的,在商业上则需要不同的条件才能成立。这些条件在1985年还不存在。但它们正在被另一组力量缓慢地创造出来。