💻 CSC3060 Week 6-7 Processor SW and HW
Week 6-7 Processor Architecture and Logic Design
指令到底是怎么在处理器里跑起来的?
Week 5 计算机架构:ISA (x86, ARM, RISCV…);Week 6 处理器微架构:同一 ISA 下的不同实现 (Single-cycle、Multi-cycle、Pipelined、Out-of-Order…)
处理器微构架
- Data Path:运算、处理或搬运数据,负责数据流
- Control:指令的更新、抓取,负责指令流
Cycle
- CPU 并非连续运作,而是按照 “fetch, decode, execute” (从内存/缓存取指、用 ISA 解译命令、运算或访问)的循环周期性工作。最小时间单位为 cycle (不同实现时长不同),以 GHz (频率)计算,比如 3GHz 的 CPU每秒处理 3x109 个 cycle。
- 取指令 、拆开指令字段并根据 ISA 解释、根据不同指令类型执行不同运算 (然后可能需要访存、写回寄存器、最后PC += 4)。(⚠️ RV32I 的 C-extension 情况下命令宽为 16b,就需要 PC += 2)
单周期:每条指令都必须在一个周期内完成。导致周期向上对齐——所有指令和最慢的 (即 lw) 一样耗时。(最快的命令是 Jump,比如 jal)
多周期:**把一条指令拆成多个阶段,每个阶段一个周期。**RISC 推动了周期缩短的革命,多周期执行明显更高效。
CPU 性能公式
⚠️ CPU Time = Instruction-Count x CPI x Clock-Cycle-Time
即:命令的执行用时 = 需要执行多少指令 x 每条指令平均用多少周期 x 周期时长
- Instruction count 受 ISA、compiler、具体算法的影响;
- CPI 受 ISA、处理器微架构的影响;
- Clocktime 受处理器微架构、硬件技术的影响。
判断性能需要同时考虑三者而不是只看执行多少指令!比如使用包含 FMA 的 ISA 导致 Instruction count 减小,若是 Single-cycle,CPI 仍为 1 但 Clocktime 变大;若是 Multi-cycle 则 CPI 变大但 Clocktime 不变。
总体归结为:CISC (短、长、长) vs. RISC (长、短、短) —— 故以 x86 为例的现代高性能 CPU 往往:ISA 像 CISC,内部翻译成 micro-ops (微操作) 执行像 RISC,兼有两者的优点。
单周期、多周期与流水线
Single-cycle:让指令都在 1 个 “长周期” 完成 —— 特点:CPI = 1 但周期很长。
Multi-cycle:让指令分步走 —— 特点:CPI > 1 但周期变短。
⚠️ Pipeline:把不同指令的不同阶段重叠起来做。例如:第 1 条指令在执行的同时、第 2 条在译码、第 3 条在取指。pipeline 可以视作 ILP 的基础形式,
逻辑设计基础
处理器说到底就是电路。
0 伏附近的低电压表示 0,1 伏附近的高电压表示 1。1 根电线传输 1-bit,多位数据用总线 (bus) 表示。
三大硬件成分
组合逻辑元件 (Combinational elements):负责对输入做 (函数) 运算并输出,无状态 (即记忆)。
状态/时序逻辑元件 (State / Sequential elements):负责存储状态信息 (如寄存器、存储器)。
时钟 (Clock signals):调节什么时候更新记忆元件。
而处理器执行一条指令,本质上就是:
在一个周期内通过组合逻辑计算出 “下一状态”,然后在时钟即将进入下一周期时把它写进时序逻辑。
基础逻辑门
组合电路元件
- MUX (Multiplexer, 多路复用器):
Y = S ? I1 : I0(如果选择信号 S=1 输出 I1,否则输出 I0),三元运算逻辑。“二选一” 或 “多选一” 问题,本质全靠 MUX (e.g.: ALU 第二输入到底选寄存器,还是立即数?PC 下一个值是 PC+4,还是 branch target?) - ALU:
Y = F(A, B)由控制信号决定做 add/sub/and/or/compare… - Comparator:输出 L:A < B;E:A == B;G:A > B。特别适合 branch 的条件判断。
组合电路始终在 “工作”,输入一变,输出就会在延迟后改变。(一个组合电路的延迟由从任一输入到任一输出的最长逻辑路径决定,这就是 critical path)
时序元件
- 寄存器 Regs:用来存储数据,依赖时钟信号上升边沿触发更新 (Clk 从 0 到 1 时)。
- Register with write control 多了写的权利:信号 Write = 1 正常更新;Write = 0 保持旧值不变。不是每条指令都需要写寄存器 —— ⚠️ 对于 RV32I 的 Branch/Store 指令,Write 信号恒为 0。
时钟
一个周期的要求是:
从某个状态元件输出开始,经过组合逻辑,必须在下一个时钟边沿之前稳定到达另一个状态元件输入。
时钟不能太快,否则数据未稳定就被写入产生错误,所以时钟周期的下限取决于最长组合路径。
RV32I 处理器的 “MVP 模型”
(图示为最简可运行的单周期 RV32I 处理器子集的模型)
⚠️ 圆形岔口表示多线并行,而图中从左到右三处圈出来的岔口必须用 MUX —— PCSrc (要 Branch/Jump 吗?)、ALU inSrc (用立即数还是寄存器?)、MemtoReg (从内存还是 ALU 写回?)
-
R-type 比如
add x3, x1, x2:同时并行PC += 4(用左侧的 ADD) 和 PC 给 Instruction memory 传地址。后者拆开命令, ALUSrc MUX 选择寄存器输入,ALUctr 要求计算x1 + x2,不用 Data Mem.,MemtoReg MUX 选择 ALU 输入,从 Data 接口写回寄存器 x3。 -
I-type 比如
addi x3, x1, 42: ALUSrc MUX 选择 Sign-extended Imm 输入。其余与 R-type 类似。 -
Load 比如
lw x3, 8(x1):ALUSrc MUX 选择(Sign-extend 12 to 32) 8,ALUctr 计算x1 + 8,Data Mem. 读取计算结果对应的内存,MemtoReg MUX **选择 Data Mem. 输入,从 Data 接口写回寄存器 x3。 -
Store 比如
lw x3, 8(x1):反之把 x3 值写入data memory[x1 + 8],不写回数据。其余与 Load 类似。 -
Branch 比如
beq x1, x2, 88:ALUSrc MUX 选择寄存器输入,ALUctr 用 Comparator 比较 x1 和 x2。同时计算 PC + 4 和 PC + 88,根据比较结果决定 PCSrc 取哪个。 -
Jump 在 MemtoReg 处需要多一个 WBsel (Write Back Select) 元件,后续再讨论。
Control
- 1bit MUX 选择 PCSrc
- 1bit MUX 选择 MemtoReg (写回的是 ALU 值还是内存值)
- 1bit MUX 选择 ALUSrc
- 1bit Write Enable 控制是否做 Mem. read/write
- 4bit ALUctr 控制 ALU 做 add/sub/and/or…
比如 lw:ALUSrc = 1 (SE Imm); MemRd = 1 (需要读内存); MemtoReg = 1 (从内存写回寄存器); RegWr = 1 (需要写回寄存器)。
又比如 sw:ALUSrc = 1;MemWr = 1; RegWr = 0。
How to Design a Processor?
我们以单周期 RV32I 最小子集为例。
第 1 步:分析指令集需求
把每条指令的语义写成寄存器传送 (register transfer) 形式:
⚠️ 总结出 datapath 至少需要:1、(Instruction) Memory;2、Register File (32 × 32 bit);3、PC;4、Extender (立即数扩展);5、ALU;6、用于 PC+4 或 PC+imm 的加法器。
第 2 步:选择数据通路组件与时钟方法
1、CLA-Adder:
2、寄存器:依赖 Clk (clock input) 信号作为 Write-Enable (1/0:有/无 “写权利”)
3、寄存器文件:32 个寄存器
- Datapath:2 个 32-bit 读口 (Read) 总线 (busA, busB)、1 个 32-bit 写口 (Write) 总线 (busW);
- Control:3 个 5-bit 选择寄存器编号的线 RA、RB、RW (对应 ISA 的 rs1, rs2, rd)。
- 特殊的,2-wide superscalar 至少需要 4 个读口、FMA 需要 3 个读口。
4、主存 (Memory)
- Datapath:1 个 32-bit 读口总线、1 个 32-bit 写口总线;
- Control:32-bit Address、Write Enable (0/1)。
第 3 步:组装 datapath
1、取指模块 (Instruction fetch unit) 都是相似的,“fetch”:mem[PC] 和 “update”:MUX: PC += 4 or PC += Imm (next instruction 还是 branch?)
一个加法器够吗?
—— 理论上某些设计中可以复用,但在单周期里不够用,往往要同时计算 PC+4 与 PC+immediate。
beq 为什么不能用 “
sub rs3, rs1, rs2 = 0” 而要用 comparator?
—— overflow!如果一定要用减法比较,则要引入如 V (overflow) / C (carry) flags 辅助判断。
2、其余的执行模块应当用 MUX 集成在一个最小复用电路中:
MUX 核心要义:不要想着每条指令单独造一套电路,尽量共用数据通路,再用控制信号配置它。
比如上图中典型地把内存类指令和 R-type 指令的 datapath 合并。
3、上下文切换 (context switch) 本质上就是 “切换 state (状态)”。
不是把机器里所有东西都存下来,而是把 “恢复这个执行流所必需的架构状态 (architectural state)” 保存/恢复 —— 包括 PC、Register Files(通用和特殊寄存器)、SP (栈指针)、RA (返回址)。
- Thread switch 保存 processor registers
- Process switch 保存 PCB (包括 registers)
cache / control signals / pipeline state 等微架构状态 (Microarchitectural state) 不一定要保存
4、整体电路:(增加一条 jal 需要的通路:跳转到目标地址并把返回地址 PC+4 写入 rd)
5、时钟周期:一个寄存器可以在同个周期里被读出,经过组合逻辑运算,再在同周期末写回。
读发生在时钟边沿后电路传播的阶段;写发生在下一个时钟边沿前 (Clk 上升期)。
- “时钟周期的下限取决于最长组合路径。” —— 即
lw的传播路径经过以下计算:
Critical Path = “PC’s Clk-to-Q” + “Instruction Memory Access Time” + “Register File Access Time” + “ALU 32-bit Addition Time” + “Data Memory Access Time" + “Register File Setup Time” + “Clock Skew”.
(PC’s Clk-to-Q:时钟到来后,PC 输出稳定需要一点时间。Setup time:写回寄存器前,输入必须提前稳定一段时间。Clock skew:时钟信号传递到不同部件有时差。)
- 所以单周期 CPU 的频率上限,通常被最慢路径
lw卡死。
单周期处理器的明显缺陷
- 因为没有 ILP,资源不复用,需要多个冗余 Adder(PC 更新和 ALU 计算);
- 同周期里不能反复经过同一组合逻辑/状态元件;
- 寄存器文件无需复制,但要多端口(2 read, 1 write);
mul和div计算是迭代性的,得在单周期里 “重复展开”,开销非常昂贵。
所以更现实的方法是允许多周期执行,用 counter 控制重复使用同一硬件资源,代价是这些指令的 CPI 变大。
第 4 步:分析每条指令对应哪些控制点
确定每条指令在不同 MUX 处如何分类选择。
第 5 步:组装控制逻辑
实现从 opcode / funct 到控制信号的译码电路。
这五步就是从 ISA 到微架构的工程路线。
常用术语总表