指令集设计

指令集体系结构设计原则与RISC/CISC架构对比

Posted by CloudingYu on March 11, 2026

一、流水线实验回顾

1.1 实验进度

流水线中的组件本质上与单周期类似,主要新增的是各级之间的流水线寄存器(pipeline registers)。基础模块(单周期各组件)一定要测试好——单模块组件测试通过后,后面的连接和流水线级间寄存器就没有太多复杂的事。模块不对就没法调,没有什么能调的余地。

可以使用大模型帮助检查基础模块代码。

1.2 实验扩展支持

有同学想做额外的乘法器和除法器——不管有什么自己的想法,只要课程/lab 要求上没有也没关系,只要自己感兴趣,可以单独沟通实现要求。


二、指令集体系结构(ISA)设计

2.1 为什么要设计指令集

指令集Instruction Set Architecture, ISA)是软件和硬件之间的契约/语言。指令集设计的好坏直接决定了 CPU 实现的难易程度。

指令集就是给 CPU 下命令的语言。如果一门语言设计得不好,CPU 就会很痛苦。新指令集不断冒出来,又有老的不断死掉——都是经过了市场选择。

指令集有两个核心要求——清晰高效。对硬件设计者来说,指令集能不能让设计电路时简单一点?第一少干点活,第二干的活尽量简单,不要来回折腾。

看着上面的应用层跑得很开心,但底层硬件才是负重前行的。设计指令集的时候,得让硬件实现也轻松一点。

2.2 自然语言 vs 严谨形式语言的讨论

一个开放性问题:大模型时代,为什么不能用自然语言直接给计算机下指令?

数学之所以要有一套严谨的表达式和公式体系,是因为自然语言不严谨。拿一个不严谨的、开放的语言来让大模型替我们完成严谨的工作,这显然是有问题的。软件工程为什么强调”给我写个文档”——落到纸面上就会慎重,条列清楚才能看懂。

vibe coding 现在很火,但到底以后会怎么发展,值得思考。

2.3 指令的基本构成

一条指令需要包含以下信息:

  • 操作码(Opcode):告诉 CPU “干什么”
  • 操作数地址:数据在哪里(寄存器、内存、I/O端口、指令本身中的立即数)
  • 下一条指令地址:如何找到下一条指令(顺序执行或跳转)

数据和指令都存放在主存中,CPU 取指令和取数据可能产生冲突,需要仲裁机制。

2.4 指令格式:固定长度 vs 可变长度

一条指令的长度有两种策略:

  • 固定长度:每条指令长度相同,简单但可能浪费空间
  • 可变长度:根据指令复杂度长度可变,节省空间但解码复杂

指令格式要有足够的操作码位数预留。因为随着业务发展,新指令会不断出现。比如现在 AI 时代,英特尔发现某些 AI 算法中有些操作特别频繁,想加几条指令来支撑 AI 算法——操作码位数不够就完了,指令集就”死了”。


三、地址码与寻址方式

3.1 地址码数量

根据指令中显式指定的操作数地址个数,分为:

类型 地址码数 特点 示例
零地址 0 操作数位置隐式约定 nop, push, pop
一地址 1 另一个操作数默认在累加器 ACC add R1(ACC + R1 → ACC)
二地址 2 两个寄存器操作数 add R1, R2(R1 + R2 → R1)
三地址 3 两个源操作数 + 一个目标 add R1, R2, R3(R2 + R3 → R1)

3.2 历史演变与RISC的选择

早期硬件(电子管时代)非常昂贵,多一条指令都是要命的,所以指令集设计极度精简,能用软件解决的问题尽量不交给硬件。

现在是 RISC 风格——有钱了,就别那么抠了,指令格式规整、清清楚楚地写好,实现也简单。

x86 是从 8086 一步步发展起来的,上面承载着辉煌的历史,也承载着沉重的历史包袱。当接手一个老指令集时,”全都有”——想扔掉旧的?千万小心,一扔也许把公司就扔掉了。而 RISC-V 是白手起家,没有包袱。

RISC-V 经历了多个版本迭代(I, II, III, IV, V),到第5版才获得业界公认。RISC-V 的风格是:指令用二地址或三地址格式,寄存器-寄存器操作,load/store 单独两条指令访存,其他指令只在寄存器间操作。


四、RISC 设计原则

4.1 核心原则

  1. 指令尽量短小规整:固定长度,简化取指和解码
  2. 足够的操作码位数:为未来扩展预留空间
  3. Load/Store 架构:只有 loadstore 两条指令访问存储器,其余在寄存器间操作
  4. 简单就是美:硬件希望”少干点活,多拿点工资”——指令简单,电路就简单

4.2 硬件 vs 软件的权衡

维度 硬件 软件
复杂度代价 芯片面积增大 → 生产成本高 多写代码、熬夜加班
修改成本 流片后无法修改 随时可以更新
核心诉求 指令简单、固定格式 指令丰富、表达能力强的

软件工程师永远有活——硬件干完就没什么事了,但软件总在迭代。哪部分该软件辛苦一点熬夜,哪部分该硬件承担,架构师需要做权衡。因为硬件要生产——面积大就贵;软件熬两个通宵就做好了。

4.3 永远保留扩展空间

指令集设计必须为未来留空间。当 AI 算法出现后,发现某些计算模式特别频繁,能否在指令集中加入专用指令加速?如果操作码位数用尽,就只能眼巴巴看着竞争对手抢占 AI 芯片市场。