SICI · 天机门 · 第八章

通路驭令

指令的执行之旅 · 筑基二层

连线只是骨架。没有RTL指定数据流向,骨架不会动。数据通路 = 部件 + 连接 + 数据流描述。

门楣刻字:「线越多,我的领地越大」
序章

虚空布线

连上线就是CPU?

虚空。没有地面,没有天空,只有靛蓝色的网格线在黑暗中明灭。

靛蓝虚空中的网格线,五个悬浮的 CPU 部件等待连线

五个部件悬浮在你面前——PC、指令存储器、寄存器堆、ALU、数据存储器——像被拆散的器官,安静地等着你把它们拼回一具躯体。

诺依曼老祖 诺依曼老祖

「一条指令,从取指到执行,要走完一条完整的路。这条路,你来修。」

冒险之影 冒险之影

「连吧,连吧。线越多,我的领地越大。」

部件拖拽连线 + RTL 书写器

点击部件依次连线,再为加法指令书写 RTL。👆 先连线,再写 RTL

RTL 书写:R[rd] ← R[rs] + R[rt]
详解 · K08-01 数据通路构建 + K08-13 RTL 描述

数据通路是指令执行所经过的功能部件与连线的总称:PC 存指令地址,IMEM 取指令,寄存器堆供数,ALU 运算,DMEM 访存。把五者按数据流向连成链,就是一条最简 MIPS 通路。但部件只是静物——RTL(寄存器传输级)用 R[rd] ← R[rs] + R[rt] 这样的语句声明"哪个寄存器、在什么时刻、接收谁算出的值",它是硬件设计的通用语言:一条 RTL 语句对应一拍内的一次数据搬家,整套 RTL 序列就是这条指令的完整旅程。

第一幕 · 自信

连线成网 · ALU 控制与寄存器

控制信号是 ALU 的意志,边沿触发是数据的秩序

网格在你脚下铺开成一张电路图。ALU 和寄存器堆被推到你面前。

诺依曼老祖 诺依曼老祖

「ALU 会算术也会逻辑。但它不知道你此刻要它做加法还是减法——你得给它控制信号。」

冒险之影 冒险之影

「你看,多简单。你觉得这就是 CPU 了。」

ALU 控制信号拨码 + 寄存器读写 + 时钟脉冲

ALU 控制信号(4位)
当前:AND (0000)
数据输入 A / B →
时钟脉冲 ALU 输出:—
详解 · K08-02 ALU 控制信号

MIPS 风格 ALU 的 4 位控制编码:AND=0000、OR=0001、ADD=0010、SUB=0110、SLT=0111(NOR=1100)。这 4 位并非 opcode 本身,而是控制单元把 opcode(+funct 字段)翻译后的结果——翻译分两级:主控制器先产 2 位 ALUOp,ALU 控制器再结合 funct 展开成这 4 位。另一个要点:寄存器堆读是组合逻辑(给地址立刻出数),写是时序逻辑(只在时钟上升沿锁存)。读快写慢的不对称,正是"一个周期内先读、再算、边沿写回"能安全工作的根基。

第一幕 · 崩塌

单周期之困 · 关键路径

所有指令都被最慢的那条拖着走

你把 PC、指令存储器、寄存器堆、ALU、数据存储器全部连上。数据通路完整了。

诺依曼老祖 诺依曼老祖

「所有指令必须在一个时钟周期内完成。你来定这个周期多长。」

冒险之影 冒险之影

「800ps。每条指令都要 800ps。不管它是加法还是取数。你觉得这样……合理吗?」

单周期关键路径曲线追踪器

搭建通路 → 测量各指令延迟 → 设定时钟周期

指令延迟对比

详解 · K08-03 单周期实现与关键路径

单周期设计里每条指令一拍完成,因此时钟周期必须 ≥ 关键路径——全通路中最慢指令的延迟。经典账(取指 200 + 读寄存器 100 + ALU 100 + 访存 200 + 写回 100):lw=800ps、sw=700ps、R-type=600ps、beq=500ps。时钟被 lw 钉死在 800ps,beq 每拍空转 300ps。更隐蔽的浪费:单周期里每个部件一拍只用一次,却必须为每条指令各配一套(加法器就要三个),资源无法复用。CPI=1 很漂亮,T_clk 却很丑——性能账要到 S8 才算得平。

第一幕 · 崩塌

指令追踪 · 五路分叉

通路是骨架,控制信号是灵魂

通路静静地运转。你输入一条 add,数据从寄存器读出,经 ALU 相加,写回。完美。

你输入 lw——路径不同了。sw——又不同。beq——又不同。五条指令,五条路径,在同一个通路上分叉、交叉、汇合。

冒险之影 冒险之影

「你看,线越多,岔路越多。每一条岔路,都是我的领地。」

五类指令路径追踪 + 控制信号清单

选择指令,观察数据通路中的流动路径和控制信号

详解 · K08-04 指令执行路径追踪

同一条通路上,五类指令走出五条路:R-type 不碰存储器(REG→ALU→REG 写回);lw 走满全程(PC→IMEM→REG→ALU→DMEM→REG);sw 止步于 DMEM 写;beq 用 ALU 做减法判零后折返改 PC。路径分叉靠多路选择器(MUX)实现,而每个 MUX 的选择端就是一个控制信号:RegDst 选写回哪个寄存器、ALUSrc 选第二操作数是寄存器还是立即数、MemToReg 选写回 ALU 结果还是存储器数据、Branch 与 Zero 相与决定是否跳转。看清"路径 = 部件序列 + MUX 选择",控制信号清单就自然浮现了。

第二幕 · 挣扎

控制真值 · 硬布线设计

从真值表到布尔表达式到门电路

老祖把一块空白真值表推到你面前:「指令的 opcode 是输入,九个控制信号是输出。你把 S3 那张清单填进去——那就是真值表。」

诺依曼老祖 诺依曼老祖

「从真值表推出布尔表达式,用门电路实现。这就是硬布线控制。快——但改一条指令,你得重新接线。」

控制信号真值表公式组装器

填写真值表 → 推导布尔表达式 → 验证

详解 · K08-05 控制真值表 + K08-06 硬布线控制

主控制器的本质是组合逻辑函数:输入 6 位 opcode,输出 9 个控制信号。把每类指令的取值列成表(sw/beq 不写寄存器,故 RegDst、MemToReg 等标 X 表示无关项),每列输出都能写成 opcode 的最小项之和——RegWrite = R-type + lw + addi,MemWrite = sw,Branch = beq。用与或门阵列(或 PLA)直接实现这张表,就是硬布线控制:信号几拍之内直达,快得没有对手;代价是函数焊死在硅片上,新增一条指令就得重画真值表、重新流片。

第二幕 · 再崩塌

微码迷宫 · 灵活性的代价

微程序把硬逻辑变成软代码——但每读一条微指令就要访问 ROM

老祖递给你一块存储芯片:「不接线了。把每一步的控制信号写成一串微码,存进控制存储器。每条指令对应一段微程序。」

冒险之影 冒险之影

「你以为白拿的灵活性?天下没有白拿的东西。」

微指令编辑器 + 控制存储器 ROM + 延迟对比

为每类指令编写微指令序列,写入 ROM,对比延迟

硬布线 vs 微程序 延迟对比

详解 · K08-07 微程序控制 + K08-14 控制存储

微程序的思路:把每个执行步骤所需的全部控制信号编成一条微指令(若干位的控制字 + 下址字段),按执行顺序存进只读的控制存储器(control store)。执行一条机器指令 = 顺序取出它的那段微程序逐条执行——控制器从"电路"变成了"在微指令上跑的程序"。改指令集只需重写 ROM 内容,复杂指令(如 x86 的字符串操作)也能用循环微码实现,这正是 CISC 的生命线。代价赤裸可见:每条微指令都要一次 ROM 访问,延迟对比里硬布线 40ps、微程序 100ps——每拍慢 60ps。

第二幕 · 抉择

两条路 · 速度与灵活性

选择不是对错,是匹配:简单选快,复杂选灵活

虚空里浮现一杆天平。左盘是硬布线:快,但改一条指令要重新流片。右盘是微程序:灵活,但每拍多 60ps 延迟。

诺依曼老祖 诺依曼老祖

「RISC 指令集简单——硬布线够用。CISC 指令集复杂——微程序才能应对。选哪条路,取决于你的指令集。」

权衡天平 · 硬布线 vs 微程序

将方案拖上天平,为 RISC / CISC 场景做出正确匹配

详解 · K08-08 硬布线 vs 微程序权衡

这不是"谁更好"而是"谁配谁":RISC 指令少而规整,真值表小,硬布线既快又省面积,是天然搭档;CISC 指令成百上千、长度不一,真值表会爆炸,只有微程序的"代码化"才 hold 得住复杂度。历史也按这条线走:IBM 360 用微程序撑起整个兼容家族,MIPS/RISC-V 用硬布线榨干速度,现代 x86 则混血——简单指令走硬布线译码,复杂指令翻译成微操作(μops)再走微程序。工程里没有银弹,只有场景匹配。

第二幕 → 第三幕 · 转型

多周期之轮 · 共享与状态机

短时钟替换长时钟,代价是 CPI 从 1 变成 3-5

老祖把你的单周期通路拆散了:「800ps 的时钟,beq 只用 500ps,浪费 300ps。为什么不让每条指令按需取周期?」

诺依曼老祖 诺依曼老祖

「每个阶段一个时钟周期,200ps。阶段间加中间寄存器暂存——IR、MDR、A、B、ALUOut。」

冒险之影 冒险之影

「共享……你让多条指令排队用同一个部件。排队的地方,就是我的领地。」

多周期数据通路流水线动画器

选择指令 → 单步/自动执行 → 观察阶段流转和 FSM 状态

FSM 状态机

详解 · K08-09 多周期实现

把一条指令的执行拆成 IF/ID/EX/MEM/WB 五个阶段,每阶段各占一个 200ps 的短周期:lw 走满 5 拍,sw/R-type 4 拍,beq 3 拍——快指令终于不用陪慢指令罚站。拆分后同一部件可在不同周期复用(一个存储器既取指又访存,一个 ALU 既算地址又做运算),省下单周期的冗余硬件。代价有二:阶段之间必须插入中间寄存器(IR、MDR、A、B、ALUOut)暂存结果;控制也从一个组合函数变成一个 FSM——每个状态发出该拍需要的控制信号,并按指令类型决定转移路径。

第三幕 · 顿悟前兆

性能之秤 · CPU 时间公式

时钟短不一定快——CPI 会吃掉时钟的红利

老祖递给你一杆秤和三个数字盒:「CPU 时间 = 指令数 × CPI × 时钟周期。这三个盒子,缺一个都不能算。」

冒险之影 冒险之影

「你以为拆短了就快了?CPI 把你的红利全吃回去了。」

诺依曼老祖 诺依曼老祖

「如果有一种方法——CPI=1,时钟周期=200ps 呢?让多条指令重叠执行——流水线。」

CPU 性能公式组装器

组装公式 → 计算 CPI → 对比性能 → 流水线时空图

详解 · K08-10 CPI 分析 + K08-12 CPU 时间公式

性能的唯一裁判:CPU 时间 = 指令数 N × 平均 CPI × 时钟周期 T_clk。平均 CPI 按指令混合比加权——以 24% lw + 12% sw + 44% R-type + 18% beq + 2% j 为例:5×0.24 + 4×0.12 + 4×0.44 + 3×0.18 + 3×0.02 ≈ 4.04。于是多周期每条指令 4.04 × 200ps ≈ 808ps,竟然比单周期的 800ps 还略慢!短时钟的红利全被 CPI 吃掉了——多周期赢的是硬件复用与可扩展性,不是纸面速度。

详解 · K08-11 流水线初步

破局点:让多条指令重叠执行。五级流水线把 IF/ID/EX/MEM/WB 排成装配线,每拍流入一条新指令——稳态时 CPI 趋近 1,时钟周期保持 200ps,相对单周期理想加速 ≈ 800/200 = 4 倍。注意流水线提升的是吞吐率而非单条指令的延迟(一条 lw 仍要 1000ps 走完五级)。而"理想"的裂缝——数据冒险、控制冒险、结构冒险——正是门口那位 Boss 的本体。

第三幕 · 最高潮

Boss 战 · 冒险之影

数据冒险 / 控制冒险 / 结构冒险 — 三问对决

暗影从虚空边缘走了出来。它没有脸,只有一个轮廓——像流水线时空图上所有重叠的方块投下的影子。

冒险之影 冒险之影

「你说'并行'。你以为并行是免费的午餐?并行就是冲突。三问。答对了,你过去。答错了——你亲手搭的通路,我一条条拆。」

渊账累计 0 笔 · 三问全对后清零

第三幕 · 收束

流水长歌 · 通路驭令

指令集是灵魂,数据通路是躯体

冒险之影消散后,虚空恢复了靛蓝色。你的电路图完整地悬浮在面前——全部连接,全部亮着。

诺依曼老祖 诺依曼老祖

「你从 S0 走到 S9。搭了通路,定了时钟,追了指令,建了控制,走了微码,做了权衡,拆了周期,算了性能,打了冒险。一条指令的旅程——你走完了。」

诺依曼老祖 诺依曼老祖

「你的通路是为 MIPS 指令集设计的。如果换成 x86 呢?那是指令集与数据通路的关系——下一章的题。」

全章回顾 · 14 知识点碎片拼图

点击碎片拼入体系图,回顾全章知识链

详解 · 全章知识链复盘

把 14 个碎片串成一条线:通路(K08-01)按 RTL(K08-13)流动数据;ALU 控制(K08-02)指挥运算;单周期(K08-03)被关键路径拖慢;指令追踪(K08-04)逼出九个控制信号;真值表(K08-05)落到硬布线(K08-06),或换成微程序(K08-07)+控制存储(K08-14);权衡(K08-08)之后转向多周期(K08-09);CPI 分析(K08-10)套上 CPU 时间公式(K08-12)发现账算不平;最终由流水线(K08-11)打开吞吐之门——也引出了下一章的冒险正题。

交互实验

CPU 流水线吞吐

调节冒险率与流水级数,观察 IPC 如何随级数先升后受制于冒险。