MIPS 1981 — 让编译器自己安排流水线,CPU 就不用管
是什么
MIPS 是 1981 年 Stanford 的 Hennessy 团队造的实验芯片,名字缩写从 Microprocessor without Interlocked Pipeline Stages(无互锁流水级的微处理器)来——读音正好是衡量 CPU 性能的 MIPS(百万指令每秒),一个双关。
它和同年 Berkeley 的 RISC I 是 RISC 革命的两个工业起点,哲学一样、手段不同。
日常类比:流水线工厂里有 5 道工位(取指 / 译码 / 执行 / 访存 / 写回)。一条指令做完要走完 5 站。问题:第 2 条指令进入译码时如果发现要用第 1 条的结果,但第 1 条还在执行——怎么办?
- 传统做法(interlock):装一个总管,发现冲突就让整条流水线停一拍——硬件保证不出错。
- MIPS 的做法:把流水线的所有”坑”都暴露给编译器,告诉它”你写的相邻两条指令之间有 1 拍延迟,自己想办法”。硬件不装总管,省下面积换更高频率。
这个”硬件偷懒、编译器加班”的思路,是 MIPS 区别于 RISC I 的核心招牌。
为什么重要
不理解 MIPS,下面这些事都解释不了:
- 为什么《计算机体系结构:量化研究方法》(Hennessy & Patterson 写的标准教材)从头到尾用 MIPS 当教学指令集
- 为什么”5 段流水线 IF-ID-EX-MEM-WB”成了全世界本科生第一次见到的 CPU 模型——MIPS 原型就长这样
- 为什么 RISC-V 在 2010 年代特地抛弃 delay slot——它正是 MIPS 哲学的代价
- 为什么 PlayStation、Nintendo 64、SGI 工作站当年都用 MIPS,后来又全部换掉
一句话:MIPS 是把”软件可以替硬件分担复杂度”这个思想推到极致的工业实验——成功也因它,被替换也因它。
核心要点
MIPS 1981 论文的关键招数有三条,每条都是 RISC 哲学的具体落地:
1. 暴露流水线(exposed pipeline)
经典 5 段流水线:
| 段 | 工作 |
|---|---|
| IF(Instruction Fetch) | 从内存取指令 |
| ID(Instruction Decode) | 译码 + 读寄存器 |
| EX(Execute) | ALU 算 |
| MEM(Memory) | 访存(load/store 才用) |
| WB(Write Back) | 写回寄存器 |
MIPS 不装”互锁电路”。如果第 N 条指令是 load r1, ...,第 N+1 条用 r1——硬件不停 pipeline,照常往下跑。结果:N+1 拿到的 r1 是旧值,结果错了。
那怎么办?答:编译器知道这个规则,会在 N 和 N+1 之间塞一条无关指令(或一个 NOP)。这个空位叫 load delay slot。
类比:餐厅服务员上完汤,告诉客人”等 30 秒再喝,太烫”。MIPS 把这个”等 30 秒”写进菜谱(ISA 规范),让顾客(编译器)自己记。
2. 分支延迟槽(branch delay slot)
跳转指令也有同样问题:CPU 决定”跳”时,下一条指令已经被取进 pipeline 了。
- 传统做法:丢掉那条指令(pipeline bubble),损失一拍。
- MIPS:延迟槽里那条指令照常执行,跳转在它之后才生效。编译器尽量塞一条”跳与不跳都对”的指令进去,否则塞 NOP。
这个 delay slot 写进 ISA,变成了二进制兼容性的一部分——后来这成了 MIPS 的甜蜜陷阱(见踩坑)。
3. 极简到底
- 无微码——所有指令直接由硬件电路实现
- 无 condition codes——比较结果直接进通用寄存器,不用专门的标志位
- 16 个通用寄存器(远少于 RISC I 的 138 个物理寄存器,靠编译器分配压榨)
- load/store architecture——只有 load/store 摸内存,其他全寄存器到寄存器
这些选择和 Berkeley RISC I 大体一致,差别在 MIPS 不做寄存器窗口——Hennessy 团队认为寄存器窗口”硬件复杂度高、收益看负载”,宁可让编译器做更聪明的寄存器分配。
实践案例
案例 1:load delay slot 长什么样
C 代码:
int x = a[i];return x + 1;朴素汇编:
lw $t0, 0($s0) # load a[i] 到 $t0addi $v0, $t0, 1 # $v0 = $t0 + 1在 MIPS 上这两行直接跑会错——lw 后面那一拍 $t0 还没就位。编译器自动改成:
lw $t0, 0($s0)nop # ← load delay slot(或塞别的无关指令)addi $v0, $t0, 1案例 2:MIPS vs RISC I 的设计取舍
| 维度 | Berkeley RISC I | Stanford MIPS |
|---|---|---|
| 寄存器策略 | 138 物理 / 8 窗口 | 16 个通用,无窗口 |
| 流水线冲突 | 硬件 interlock | 编译器调度 + delay slot |
| 函数调用成本 | 滑动窗口几乎免费 | 编译器存取栈 |
| 编译器复杂度 | 低 | 高 |
| 芯片面积 | 大(多寄存器) | 小(多频率) |
两条路在 1980 年代各有信徒,但工业界最终更接近 MIPS 一路——商用 MIPS、SPARC(继承窗口)、ARM、PowerPC、RISC-V 都偏向少寄存器 + 编译器优化。
案例 3:为什么 RISC-V 要抛弃 delay slot
RISC-V(2010 年 Berkeley 第二代 RISC)明确不要 delay slot。原因:
- 现代乱序执行 CPU 自己会调度,硬件 interlock 是基操,delay slot 反而碍事
- delay slot 写进 ISA 意味着流水线深度被冻结——MIPS 后来想改 pipeline 又怕破坏二进制兼容
- 编译器今天能处理的复杂度远超 1981 年——不用再靠 delay slot 这种”硬约束”压榨它
踩过的坑
-
delay slot 是甜蜜陷阱:写进 ISA 当时省硬件,但锁死了流水线宽度。MIPS 后来出 R10000(乱序、超标量)时不得不加 interlock 电路兼容旧二进制——绕了一圈回到起点。
-
load delay slot 编译器常填不满:早期编译器找不到合适的”无关指令”塞进去,大量 NOP 占位。直到 1990 年代调度算法成熟才好转。
-
暴露 pipeline 在乱序时代成负担:CPU 内部已经超标量、乱序、多发射时,让 ABI 还规定”延迟槽”是巨大累赘。这是 RISC-V 抛弃它的根因。
-
16 寄存器在大函数里压力很大:MIPS 没有寄存器窗口,函数调用要主动存取栈帧,编译器寄存器分配(图染色算法)变成关键瓶颈。
适用 vs 不适用场景
适用:
- 编译器质量高、面积紧张、追求高频率的场景——这是 1980 年代 VLSI 的真实约束
- 嵌入式、网络处理器、游戏机(PlayStation、N64)——MIPS 一度统治这些领域
- 教学——5 段流水线 + 无微码的清晰结构是最好的入门 CPU 模型
不适用:
- 二进制兼容比性能重要的桌面市场——x86 凭借兼容性守住地盘
- 现代乱序超标量 CPU——硬件已经做了所有调度,软件可见的 pipeline 反成累赘
- 编译器能力受限的早期场景——不如 RISC I 的寄存器窗口直接
历史小故事(可跳过)
- 1975 年:IBM John Cocke 内部搞 801 项目,已发现”砍指令反而快”,但 IBM 当宝贝藏起来。
- 1980 年:Berkeley Patterson 发《Case for RISC》论文(同期),独立提出 RISC。
- 1981 年:Stanford Hennessy 团队发 MIPS 1981 论文,Berkeley Patterson 团队发 RISC I——同年、同哲学、不同手段。
- 1984 年:Hennessy 创立 MIPS Computer Systems,把学术原型商业化。
- 1986 年:R2000 发布,开启商用 MIPS 时代;后来 SGI、PlayStation、N64 都用它。
- 2017 年:Hennessy + Patterson 因 RISC 思想共获图灵奖。
- 2018 年起:RISC-V 接过 RISC 旗帜,抛弃 delay slot,进入开源时代。
学到什么
- 复杂度可以在硬件和软件之间转移——MIPS 把 pipeline interlock 从硬件搬到编译器,是这个思想最大胆的工业实验。
- 写进 ISA 的妥协会跟你一辈子——delay slot 当年省了硬件,30 年后还在还债。
- 同时代的”对手”未必是错的——RISC I 的寄存器窗口和 MIPS 的暴露流水线都对,只是赌不同的硬件趋势。
- 学术原型 → 创业公司 → 教材 → 通用模型——MIPS 这条路是计算机体系结构史上最完整的一次范式转移。
延伸阅读
- 论文 PDF:MIPS: A VLSI Processor Architecture (1981)
- 教科书:Hennessy & Patterson, Computer Architecture: A Quantitative Approach(用 MIPS 当全书示例)
- 视频:Hennessy & Patterson 2017 图灵奖演讲
- risc-i-1981 —— 同年 Berkeley 的姊妹工作,对照看
- case-for-risc-1980 —— RISC 思想的奠基论文
关联
- risc-i-1981 —— 同年同哲学不同手段:RISC I 多寄存器,MIPS 软件调度
- case-for-risc-1980 —— RISC 哲学的论证书,给 MIPS 提供理论根基
- ssa —— MIPS 倒逼出来的现代编译器优化技术(寄存器分配、指令调度)
- llvm —— 现代编译器后端,继承 MIPS “编译器替硬件分担”的思路
反向链接
- case-for-risc-1980 —— Case for RISC 1980 — 一篇没有芯片的论文,掀起 CPU 半世纪革命
- cell-be-2005 —— Cell BE — 一颗 CPU 里塞 8 个加速核
- llvm —— LLVM — 模块化编译器框架
- risc-i-1981 —— RISC I — 砍掉 90% 指令反而让 CPU 跑得更快
- rt-thread —— RT-Thread — 中文社区主导的物联网 RTOS
- ssa —— SSA — 静态单赋值形式