第三讲:处理器流水线基础
各位同学,今天我们聊聊流水线。说实话,流水线这个概念,是CPU设计里最让我着迷的部分之一。它就像一条精心设计的汽车装配线——每个工位只做一件事,但所有工位同时工作,产量就上去了。
经典5级流水线回顾
RISC-V的5级流水线,说白了就是把一条指令的执行拆成5个步骤。我当年在学校第一次看到这个结构时,觉得它简单得有点过分。但后来在项目中才发现,越是简单的东西,越容易在细节上翻车。
这5级分别是:
- IF(取指):从指令存储器里把指令捞出来
- ID(译码):看懂这条指令想干什么,顺便把寄存器读出来
- EX(执行):ALU干活,或者算地址
- MEM(访存):读写数据存储器
- WB(写回):把结果写回寄存器
每个阶段用一个流水线寄存器隔开。嗯,这里要注意:这些寄存器不仅仅是存数据,它们还负责把控制信号也往后传。我见过不少新手设计,只传数据不传控制信号,结果执行阶段不知道自己要干什么。
核心要点:流水线寄存器里,数据和控制信号是绑在一起的。控制信号从译码阶段产生,一路跟着指令走到写回阶段。
数据通路与控制信号
数据通路,就是指令流经的物理路径。控制信号,就是告诉这条路径上的每个部件「你该干什么」的指令。
举个例子,一条加法指令 add x1, x2, x3:
- IF阶段:PC指向指令地址,从IMEM读出32位指令码
- ID阶段:译码器认出这是R型指令,读出x2和x3的值
- EX阶段:ALU收到控制信号「做加法」,算出x2+x3
- MEM阶段:什么都不做(控制信号告诉MEM阶段「别动」)
- WB阶段:把结果写回x1
你看,每个阶段都在等控制信号。我曾经在调试一个芯片时,发现加法结果总是错的。查了两天才发现——译码阶段产生的控制信号,在流水线寄存器里少传了一拍。结果执行阶段收到的是上一条指令的控制信号,把加法当成了减法做。
个人经验:我习惯在设计初期就把控制信号的流水线传递图画出来。每个信号从哪一级产生,到哪一级消耗,画清楚再写代码。这能省掉至少一半的调试时间。
流水线冒险简介
流水线不是完美的。三条指令同时在不同阶段跑,难免会打架。打架的情况有三种:
结构冒险
说白了就是硬件资源不够用。比如IF阶段要读指令存储器,MEM阶段要读数据存储器。如果指令存储器和数据存储器是同一个物理RAM,那就撞车了。
RISC-V的设计很聪明——它把指令存储器和数据存储器分开。所以结构冒险在RISC-V里基本不存在。但如果你自己加自定义扩展指令,比如一条指令既要读指令又要读数据,那就得小心了。
数据冒险
这是最常见的问题。比如:
add x1, x2, x3 // 第1条指令,写x1
sub x4, x1, x5 // 第2条指令,读x1
第2条指令在ID阶段读x1时,第1条指令还在EX阶段,x1的值还没写回去。读到的就是旧值。
解决办法有三种:
- 插入气泡(stall):让第2条指令等一拍。简单但性能损失大。
- 转发(forwarding):把EX阶段算出的结果直接「抄近路」送给ID阶段。这是主流做法。
- 代码重排:编译器在两条指令之间插入一条不相关的指令。这是软件层面的优化。
避坑指南:我曾经在实现转发逻辑时,忘了考虑「写后读」和「读后写」的区别。结果转发路径搭错了,数据从错误的方向流了过去。调试了整整一个周末。记住:转发只解决写后读(RAW)冒险,读后写(WAR)和写后写(WAW)在5级流水线里基本不会出现,但如果你改流水线级数,就得重新分析。
控制冒险
分支指令带来的问题。比如:
beq x1, x2, target // 如果相等,跳转到target
add x3, x4, x5 // 下一条指令
beq指令在EX阶段才能算出是否跳转。但IF阶段已经把add指令取进来了。如果beq决定跳转,add指令就是白取的。
最简单的办法是预测「不跳转」。如果猜对了,流水线照常跑。如果猜错了,把已经取进来的指令清掉(flush),从目标地址重新取。
分支预测是个大话题。我个人建议初学者先做静态预测(默认不跳转),等流水线跑通了再考虑动态预测。
流水线结构图
下面这张图,是我用SVG画的5级流水线核心结构。你仔细看,每个阶段之间的寄存器,以及数据转发路径,都在上面了。
这张图里,你看到的是数据流从左往右走,控制信号从上往下产生,然后跟着指令一起往右传。转发路径用红色虚线标出来了——它从EX阶段的输出,直接绕回ID阶段的输入。
我的习惯:每次设计新指令时,我都会在这张图上走一遍。看看新指令在每个阶段需要什么控制信号,会不会跟现有指令抢资源。走通了再写代码,走不通就改设计。这比写完代码再仿真快得多。
好了,流水线的基础就讲到这里。你想想看,5级流水线其实就是一个「分工协作」的模型。每个阶段只做一件事,但所有阶段同时做不同的事。理解了这个,后面我们讲自定义扩展指令怎么插入流水线,就容易多了。
公众号:蓝海资料掘金营,微信deep3321