从晶体管到CPU:基于ETH神课的数字设计与计算机体系结构学习路线
2026/9/2 12:09:03 网站建设 项目流程

最近在B站刷到一门宝藏课程——苏黎世联邦理工学院(ETH Zurich)2026年最新重制的《数字设计与计算机体系结构》公开课,并且是中文配音版!这门课被誉为“计算机体系结构神课”,它最吸引人的地方在于,它真的从最基础的晶体管开始,一步步带你构建逻辑门、算术单元、处理器,最终设计出一个完整的CPU。对于很多学过《计算机组成原理》但感觉知识零散、无法串联的同学,或者想深入理解硬件底层、甚至自己动手写Verilog实现CPU的开发者来说,这门课提供了一个绝佳的、系统性的学习路径。

本文将结合这门课程的核心脉络,以及当前硬件开发的热点(如Verilog、FPGA、CPU/GPU架构、缓存),为你梳理出一条从晶体管到现代CPU的完整学习路线。我们不仅会解读课程精华,还会补充关键的实践环节,包括Verilog代码示例、FPGA仿真验证思路以及核心概念解析,帮助你真正打通从理论到实战的全链路。

1. 课程核心价值与学习目标定位

苏黎世联邦理工学院的《Digital Design and Computer Architecture》课程之所以备受推崇,在于它采用了独特的“自底向上”(Bottom-Up)与“自顶向下”(Top-Down)相结合的教学方法。这与许多国内课程先讲抽象概念再讲细节的方式不同。

自底向上:课程从半导体物理基础(MOSFET晶体管)开始,讲解其如何作为开关,进而构建出与非门(NAND)、或非门(NOR)等基本逻辑门。然后,这些门电路被组合成更复杂的组合逻辑电路(如多路选择器、加法器)和时序逻辑电路(如锁存器、寄存器)。最终,这些部件被集成为一个简单的处理器(如课程中经典的“LC-3”或“RISC-V”教学架构)。

自顶向下:在理解底层构建块的同时,课程也会从程序员的角度(高级语言、汇编指令)出发,分析处理器需要提供哪些功能(指令集架构,ISA),然后向下拆解这些功能需要哪些硬件模块来支持。

通过这种方式,学习者能清晰地看到一条完整的因果链:程序员写的C代码 -> 编译成的机器指令 -> 处理器内部的数据通路与控制信号 -> 由ALU、寄存器文件等模块执行 -> 这些模块又由更基本的逻辑门构成 -> 逻辑门最终由晶体管实现。这彻底打破了软件与硬件之间的认知壁垒。

学完本课程/本文路线,你将能够:

  1. 理解计算机的根本工作原理:不再将CPU视为黑盒,明白一条ADD指令在时钟驱动下,数据是如何在芯片内部流动和计算的。
  2. 掌握数字电路设计的基本方法:学会使用真值表、逻辑表达式、卡诺图进行逻辑优化,理解时序电路中的建立/保持时间等关键概念。
  3. 使用硬件描述语言(Verilog)进行设计:能够用Verilog描述组合逻辑、时序逻辑以及简单的处理器模块。
  4. 建立CPU核心组件的设计能力:独立设计并验证ALU、寄存器文件、单周期/多周期CPU数据通路。
  5. 洞悉现代CPU性能提升技术:深入理解流水线、缓存(Cache) hierarchy、超标量等高级概念的原理与挑战。
  6. 具备FPGA开发的基础技能:了解如何将Verilog代码综合到FPGA上进行功能验证和性能评估。

2. 学习环境与工具准备

在跟随课程学习或进行自主实践前,需要搭建一个合适的软硬件仿真环境。对于初学者,我们优先推荐使用软件仿真工具,成本低且易于调试。

2.1 软件工具链

  1. Verilog仿真器(必需):用于编写和仿真你的数字电路设计。

    • 推荐:Icarus Verilog (iverilog) + GTKWave
      • Icarus Verilog:一个轻量级、开源、跨平台的Verilog仿真编译器。它可以将你的Verilog代码编译成一种中间格式,然后进行仿真。
      • GTKWave:一个开源的波形查看器,用于可视化仿真生成的信号波形,是调试电路的利器。
    • 安装(以Ubuntu/WSL或Mac为例)
      # Ubuntu/Debian sudo apt-get install iverilog gtkwave # Mac (使用Homebrew) brew install icarus-verilog gtkwave # Windows # 可以安装MSYS2或直接下载预编译的安装包。
    • 替代方案:ModelSim/QuestaSim (Intel FPGA Edition):功能更强大的商业软件免费版,适合更复杂的设计,但安装包较大。
  2. 代码编辑器/IDE(必需):编写Verilog代码。

    • Visual Studio Code (VSCode):强烈推荐。通过安装扩展(如“Verilog-HDL/SystemVerilog/Bluespec SystemVerilog” by mshr-h)可以获得语法高亮、代码片段、简单的 linting 等功能。
    • 安装VSCode扩展:在扩展商店搜索“Verilog”并安装上述插件。
  3. RISC-V工具链(可选但推荐):如果你想实践课程中涉及的RISC-V处理器设计,需要一套交叉编译工具,将C程序编译成RISC-V机器码,用于测试你的CPU。

    • 安装:可以搜索“riscv-gnu-toolchain”按照官方指南编译,或使用预编译版本。

2.2 硬件平台(进阶可选)

当你完成软件仿真,希望将设计运行在真实硬件上时,需要FPGA开发板。

  • 入门推荐:Xilinx Artix-7系列(如Basys 3、Nexys A7)或Intel Cyclone IV/V系列(如DE10-Lite)的开发板。它们性价比高,资源足够运行教学用的CPU。
  • 配套软件:需要安装FPGA厂商的Vivado(Xilinx)或Quartus Prime(Intel)软件,用于综合、布局布线和生成比特流文件下载到板卡。

版本说明:本文示例代码和命令基于Icarus Verilog 11.0+ 和通用的Verilog-2001标准,大部分工具的最新稳定版均可使用。具体操作请以你的实际环境为准。

3. 数字逻辑基础:从晶体管到逻辑门

课程的第一部分会深入半导体物理,我们这里聚焦于其数字抽象——布尔代数与逻辑门。这是所有复杂数字系统的基石。

3.1 晶体管的开关模型

现代数字电路主要使用CMOS(互补金属氧化物半导体)技术。一个CMOS反相器(NOT门)由一个PMOS管和一个NMOS管构成。

  • NMOS:栅极(Gate)接高电平(1)时,源极(Source)和漏极(Drain)导通,相当于开关闭合;接低电平(0)时断开。
  • PMOS:与NMOS相反,栅极接低电平(0)时导通,接高电平(1)时断开。

通过将NMOS和PMOS以特定方式组合,可以构建出任何逻辑门。例如,一个二输入的CMOS与非门(NAND)由两个串联的NMOS和两个并联的PMOS组成。

3.2 基本逻辑门与Verilog描述

在数字设计层面,我们直接使用逻辑门的符号和功能。以下是基本门及其Verilog表示。

逻辑门符号功能(真值表)Verilog运算符
NOT三角形+圆圈输入取反~
AND半圆形全1出1&
OR弧线形有1出1|
NANDAND+圆圈全1出0~&!(a & b)
NOROR+圆圈有1出0~|!(a | b)
XOR带加号的弧线相异出1^

Verilog示例:一个简单的组合电路假设我们要实现一个功能:当三个输入a, b, c中至少有两个为1时,输出f为1。这可以通过逻辑表达式f = (a & b) \| (a & c) \| (b & c)实现。

// 文件:majority.v module majority( input wire a, b, c, output wire f ); // 使用逻辑运算符直接实现 assign f = (a & b) | (a & c) | (b & c); endmodule

代码解释

  • module定义了一个名为majority的模块。
  • input wire声明了输入端口,output wire声明了输出端口。wire表示线网类型,用于连接。
  • assign语句用于描述组合逻辑,右侧的表达式会持续驱动左侧的信号f

3.3 组合逻辑设计与优化

设计组合逻辑的典型流程:

  1. 问题描述:用文字定义输入输出关系。
  2. 真值表:列出所有输入组合对应的输出。
  3. 逻辑表达式:从真值表推导出(通常使用卡诺图或布尔代数定理进行简化)。
  4. 电路图/Verilog代码:用门电路或HDL实现简化后的表达式。

常见误区

  • 未考虑毛刺(Glitch):组合逻辑的输出在输入变化时,由于路径延迟不同,可能产生短暂的错误脉冲。在时钟电路中,这可能被寄存器捕获导致错误。课程会深入讲解冒险(Hazard)与消除方法。
  • 代码风格导致锁存器(Latch):在Verilog的always块中,如果未完整定义所有输入分支的条件,综合工具可能推断出非预期的锁存器,这通常不是设计本意。应使用完整的if-elsecase语句,或为输出指定默认值。

4. 时序逻辑与存储元件:构建CPU的记忆

CPU需要记住当前的状态(如程序计数器PC、寄存器值),这依赖于时序逻辑电路。其特点是输出不仅取决于当前输入,还取决于过去的输入序列(电路状态)。

4.1 基本存储单元:锁存器与触发器

  • SR锁存器(Set-Reset):由两个交叉耦合的或非门(或与非门)构成,能存储1比特信息,但对输入脉冲敏感。
  • D锁存器:在SR锁存器前加控制门,在使能信号有效时,输出跟随输入;使能无效时,保持之前的值。电平敏感
  • D触发器(DFF):计算机中最关键的存储元件。它通常采用主从结构,只在时钟信号的边沿(上升沿或下降沿)将输入D的值捕获到输出Q,并在下一个边沿到来之前保持不变。边沿敏感

Verilog示例:一个带异步复位的D触发器

// 文件:dff_async_reset.v module dff_async_reset( input wire clk, input wire async_rst_n, // 低电平有效的异步复位 input wire d, output reg q ); // always块描述时序逻辑 // @(posedge clk or negedge async_rst_n) 表示在clk上升沿或async_rst_n下降沿触发 always @(posedge clk or negedge async_rst_n) begin if (!async_rst_n) begin // 复位有效时,输出清零 q <= 1'b0; end else begin // 否则,在时钟上升沿将d的值赋给q q <= d; end end endmodule

代码解释

  • output reg q声明q为寄存器(reg)类型,它可以在always块中被赋值。
  • always @(posedge clk or negedge async_rst_n)是敏感列表,定义了块执行的触发条件。
  • <=是非阻塞赋值符,在时序逻辑中推荐使用,它模拟了硬件寄存器在时钟边沿同时更新的行为。

4.2 寄存器与寄存器文件

多个D触发器并行排列,就构成了一个寄存器(Register),可以存储一个多位的数据(如32位)。多个寄存器组合在一起,加上地址译码器和读写控制逻辑,就构成了寄存器文件(Register File),它是CPU中通用寄存器(R0-R31)的硬件实现。

寄存器文件的关键操作

  1. 读端口:输入寄存器地址(如rs1,rs2),输出对应寄存器的数据。
  2. 写端口:在时钟边沿,如果写使能有效,将数据写入目标地址(rd)对应的寄存器。

5. 构建算术逻辑单元(ALU)与数据通路

ALU是CPU的执行引擎,负责完成算术(加、减)和逻辑(与、或、移位)运算。

5.1 ALU的设计

一个简单的32位ALU支持加、减、与、或等操作,通过一个多路选择器根据操作码(alu_op)选择输出结果。

Verilog示例:一个简单的32位ALU

// 文件:simple_alu.v module simple_alu( input wire [31:0] a, b, input wire [2:0] alu_op, // 操作码 output reg [31:0] out, output wire zero // 结果是否为0的标志,用于分支判断 ); // 定义操作码常量(本地参数) localparam OP_ADD = 3'b000; localparam OP_SUB = 3'b001; localparam OP_AND = 3'b010; localparam OP_OR = 3'b011; localparam OP_XOR = 3'b100; wire [31:0] adder_result; assign adder_result = a + b; // 简单的加法器 always @(*) begin // 组合逻辑,使用阻塞赋值= case (alu_op) OP_ADD: out = a + b; OP_SUB: out = a - b; OP_AND: out = a & b; OP_OR: out = a | b; OP_XOR: out = a ^ b; default: out = 32'b0; // 默认值 endcase end // 零标志位:当out全为0时,zero为1 assign zero = (out == 32'b0); endmodule

5.2 单周期CPU数据通路

单周期CPU是最简单的模型,它在一个时钟周期内完成一条指令的取指、译码、执行、访存、写回所有阶段。其数据通路是将PC、指令存储器、寄存器文件、ALU、数据存储器、控制单元等模块按照指令执行流程连接起来。

关键路径分析:单周期CPU的时钟周期必须大于最复杂指令(如lw,需要访问内存)所需的时间。这导致执行简单指令时效率低下,因为时钟周期被最慢的指令拖慢。这是单周期设计的主要缺点,也引出了多周期和流水线设计。

6. 从单周期到流水线:CPU性能的飞跃

为了提升性能,现代CPU普遍采用流水线(Pipeline)技术,其思想类似于工厂的装配线。

6.1 流水线的基本概念

将指令执行过程划分为多个阶段(如经典的5级流水线:取指IF、译码ID、执行EX、访存MEM、写回WB),每个阶段由一个专门的硬件阶段负责。这样,多条指令可以重叠执行,每个时钟周期都有一条指令完成(理想情况下),极大提高了吞吐率。

5级流水线数据通路示意图(文字描述)

时钟周期 | Stage 1 (IF) | Stage 2 (ID) | Stage 3 (EX) | Stage 4 (MEM)| Stage 5 (WB) ------------------------------------------------------------------------------- 周期1 | 指令1 (I1) | | | | 周期2 | 指令2 (I2) | I1 | | | 周期3 | 指令3 (I3) | I2 | I1 | | 周期4 | 指令4 (I4) | I3 | I2 | I1 | 周期5 | 指令5 (I5) | I4 | I3 | I2 | I1 周期6 | ... | I5 | I4 | I3 | I2

理想情况下,吞吐率提高到接近5倍。

6.2 流水线的挑战:冒险(Hazard)

流水线引入的并行性带来了新的问题,即冒险。

  1. 结构冒险:硬件资源冲突。例如,单端口内存无法同时供IF和MEM阶段使用。解决方案:使用分离的指令缓存(I-Cache)和数据缓存(D-Cache)。
  2. 数据冒险:后续指令需要用到前面指令尚未产生的结果。例如:ADD R1, R2, R3后紧跟SUB R4, R1, R5SUB在ID阶段需要R1,但ADD在WB阶段才写回R1
    • 解决方案
      • 前递(Forwarding / Bypassing):将ALU结果直接从EX/MEM或MEM/WB流水线寄存器提前送到需要它的ALU输入端。这是硬件解决方案,能解决大部分数据冒险。
      • 流水线停顿(Stall / Bubble):插入空操作(NOP),等待数据就绪。由硬件检测并插入,软件上表现为性能损失。
  3. 控制冒险:分支指令(如beq)改变PC值,导致已预取进入流水线的后续指令无效。
    • 解决方案:分支预测(Branch Prediction)。从简单的静态预测(总是预测不跳转)到复杂的动态预测(基于历史记录的模式预测)。

Verilog思路:流水线寄存器实现流水线的关键是在各阶段之间插入流水线寄存器,用于传递阶段间的数据和控-制信号。

// 文件:if_id_reg.v (IF/ID流水线寄存器示例) module if_id_reg( input wire clk, input wire rst_n, input wire stall, // 流水线停顿信号 input wire flush, // 流水线冲刷信号(如分支预测失败) input wire [31:0] if_pc, input wire [31:0] if_instr, output reg [31:0] id_pc, output reg [31:0] id_instr ); always @(posedge clk or negedge rst_n) begin if (!rst_n) begin id_pc <= 32'b0; id_instr <= 32'b0; end else if (flush) begin // 冲刷时,插入NOP(全0指令或特定编码) id_pc <= 32'b0; id_instr <= 32'b0; end else if (!stall) begin // 正常情况,传递数据 id_pc <= if_pc; id_instr <= if_instr; end // 如果stall有效,则id_pc和id_instr保持原值 end endmodule

7. 存储体系结构:缓存(Cache)原理

CPU速度与主存(DRAM)速度的差距(“内存墙”)越来越大。缓存作为CPU和主存之间的高速缓冲区,其目的是让CPU大部分时间都能以接近寄存器的速度访问数据。

7.1 缓存的基本工作原理

缓存基于局部性原理

  • 时间局部性:刚被访问的数据很可能再次被访问。
  • 空间局部性:访问某个地址后,其附近地址很可能也被访问。

缓存由许多缓存行(Cache Line)组成,每个行包含一个数据块(Block)、一个标签(Tag)和有效位(Valid)等状态位。

7.2 缓存映射方式

  1. 直接映射:每个主存块只能映射到缓存中唯一的一个行。简单,但容易发生冲突失效。
  2. 全相联映射:每个主存块可以映射到缓存中的任意行。命中率高,但查找电路复杂(需要比较所有行的Tag)。
  3. 组相联映射:缓存的折中方案。缓存分为若干组(Set),每个组包含若干行(Way)。主存块映射到特定的组,但可以放在该组内的任意一行。这是现代CPU最常用的方式(如4路、8路、16路组相联)。

7.3 缓存一致性(Cache Coherence)

在多核处理器中,每个核心都有自己的私有缓存(L1 Cache)。当某个核心修改了自己缓存中的数据副本时,必须确保其他核心缓存中对应的数据副本是无效的或得到更新,否则会导致程序错误。维护这种一致性的协议称为缓存一致性协议,最著名的是MESI协议(Modified, Exclusive, Shared, Invalid)。

8. 完整实战:设计一个简单的流水线RISC-V CPU(概要)

让我们将以上知识串联起来,勾勒一个简化的5级流水线RISC-V CPU的设计框架。这里不给出全部代码,但提供核心模块和设计思路。

8.1 顶层模块设计

module riscv_pipeline_cpu( input wire clk, input wire rst_n, // 指令存储器接口(简化,实际可能通过AXI总线) output wire [31:0] imem_addr, input wire [31:0] imem_data, // 数据存储器接口 output wire [31:0] dmem_addr, output wire dmem_we, output wire [31:0] dmem_wdata, input wire [31:0] dmem_rdata ); // 定义各阶段间的流水线寄存器连线 wire [31:0] if_pc, id_pc, ex_pc, mem_pc, wb_pc; wire [31:0] if_instr, id_instr, ex_instr, mem_instr, wb_instr; // ... 其他控制信号和数据信号 // 实例化各阶段模块 // 1. 取指阶段 (IF) if_stage if_stage_inst ( .clk(clk), .rst_n(rst_n), .stall(stall_from_id), // 来自ID阶段的停顿信号 .branch_taken(branch_taken_from_ex), // 来自EX阶段的分支跳转信号 .branch_target(branch_target_from_ex), .pc(if_pc), .imem_addr(imem_addr) ); // 连接指令存储器 assign if_instr = imem_data; // 2. 译码阶段 (ID) id_stage id_stage_inst ( .clk(clk), .rst_n(rst_n), .if_pc(if_pc), .if_instr(if_instr), // 流水线寄存器输入 .id_pc(id_pc), .id_instr(id_instr), // 寄存器文件读写端口 // 前递数据输入 .forward_data_ex(forward_data_ex), .forward_data_mem(forward_data_mem), // 产生的控制信号 .alu_op(alu_op_to_ex), .reg_we(reg_we_to_ex), // 冒险检测单元 .stall(stall_from_id), .flush(flush_from_id) ); // 3. 执行阶段 (EX) ex_stage ex_stage_inst ( .clk(clk), .rst_n(rst_n), .id_pc(id_pc), .id_instr(id_instr), // ... 接收ID的控制和数据 // 执行ALU操作 // 计算分支目标并判断是否跳转 .branch_taken(branch_taken_from_ex), .branch_target(branch_target_from_ex), // 输出到MEM阶段的数据和控制信号 .ex_pc(ex_pc), .ex_instr(ex_instr), .alu_result(alu_result_to_mem) ); // 4. 访存阶段 (MEM) mem_stage mem_stage_inst ( .clk(clk), .rst_n(rst_n), .ex_pc(ex_pc), .ex_instr(ex_instr), .alu_result(alu_result_to_mem), // 连接数据存储器 .dmem_addr(dmem_addr), .dmem_we(dmem_we), .dmem_wdata(dmem_wdata), .dmem_rdata(dmem_rdata), // 输出到WB阶段的数据 .mem_pc(mem_pc), .mem_instr(mem_instr), .mem_result(mem_result_to_wb) ); // 5. 写回阶段 (WB) wb_stage wb_stage_inst ( .clk(clk), .rst_n(rst_n), .mem_pc(mem_pc), .mem_instr(mem_instr), .mem_result(mem_result_to_wb), // 写回寄存器文件 .wb_reg_we(wb_reg_we), .wb_reg_addr(wb_reg_addr), .wb_reg_data(wb_reg_data) ); // 6. 前递单元 (Forwarding Unit) forwarding_unit forwarding_unit_inst ( .id_rs1(id_instr[19:15]), .id_rs2(id_instr[24:20]), .ex_rd(ex_instr[11:7]), .ex_reg_we(ex_reg_we), .mem_rd(mem_instr[11:7]), .mem_reg_we(mem_reg_we), .forward_a(forward_a_to_id), // 控制ID阶段操作数A的选择 .forward_b(forward_b_to_id) // 控制ID阶段操作数B的选择 ); endmodule

8.2 仿真测试与验证

设计完成后,必须进行充分的仿真测试。

  1. 编写测试平台(Testbench):用Verilog编写一个顶层模块,实例化你的CPU,并为其提供模拟的指令内存和数据内存。
  2. 加载测试程序:将编译好的RISC-V机器码(一个.bin.hex文件)读入测试平台中的指令存储器数组。
  3. 运行仿真:使用Icarus Verilog编译并运行仿真。
    iverilog -o cpu_sim riscv_pipeline_cpu.v cpu_tb.v vvp cpu_sim
  4. 查看波形:在Testbench中可以使用$dumpfile$dumpvars系统任务将信号变化记录到VCD文件中,然后用GTKWave打开分析。
    // 在Testbench的initial块中 initial begin $dumpfile("cpu_wave.vcd"); $dumpvars(0, cpu_tb); // 0表示转储所有层级的信号 // ... 其他初始化 end
    gtkwave cpu_wave.vcd

9. 常见问题与调试技巧

在设计和仿真CPU的过程中,你一定会遇到各种问题。以下是一些常见坑点及排查思路。

问题现象可能原因排查思路
仿真波形全为X(不定态)寄存器或线网未初始化;存在组合逻辑环路。1. 检查所有regwire是否有合理的复位或初始赋值。
2. 检查always @(*)组合逻辑块,确保所有输入分支都有明确的输出赋值,避免锁存器。
3. 使用$display在仿真中打印关键信号值。
CPU执行第一条指令后卡住PC(程序计数器)更新逻辑错误;指令存储器内容错误。1. 检查IF阶段:PC在每个时钟周期是否正常递增(非分支时)?
2. 检查指令存储器:地址imem_addr对应的imem_data是否正确?
3. 检查分支逻辑:是否错误地产生了分支信号?
寄存器写回值错误数据冒险未正确处理;写回地址或使能信号错误。1. 检查前递单元:当前递发生时,ALU的操作数是否被正确替换为来自EX或MEM阶段的最新结果?
2. 查看WB阶段:wb_reg_wewb_reg_addrwb_reg_data在波形中是否正确?
3. 检查寄存器文件:写端口的时序逻辑是否正确(在时钟边沿写入)?
访存(Load/Store)指令出错地址计算错误;存储器接口时序不对齐。1. 检查EX阶段:访存地址alu_result计算是否正确?
2. 检查MEM阶段:dmem_we(写使能)信号是否与数据和地址对齐?对于Load指令,是否在下一个周期正确读取了dmem_rdata
综合到FPGA后行为异常时序违例(建立/保持时间不满足);异步复位/时钟处理不当。1. 查看综合和实现后的时序报告,关注关键路径的Slack是否为负。
2. 检查是否使用了FPGA不支持的Verilog语法(如initial块用于初始化寄存器,需改为复位逻辑)。
3. 确保时钟和复位信号通过全局时钟网络(BUFG)输入。

调试技巧

  • 增量开发:不要一次性写完整CPU。先从单周期的非流水线CPU开始,确保它能正确执行几条简单指令(如addi,sw,lw,beq)。然后再逐步添加流水线寄存器、前递单元、冒险检测单元。
  • 波形分析:GTKWave是你的好朋友。将PC、指令、控制信号、ALU结果、寄存器读写等关键信号添加到波形中,逐周期比对预期行为和实际行为。
  • 对比仿真:用一个已知正确的软件模拟器(如Spike、QEMU的RISC-V模式)运行相同的测试程序,将你的硬件仿真结果与软件模拟器的结果(寄存器值、内存值)进行逐条指令对比。

10. 深入学习路线与资源推荐

完成一个简单的流水线CPU只是计算机体系结构学习的起点。要深入理解现代高性能CPU和GPU,可以沿着以下路径继续探索:

  1. 深入流水线

    • 超标量(Superscalar):每个时钟周期发射多条指令。需要研究指令调度、寄存器重命名、保留站(Reservation Station)、重排序缓冲区(ROB)。
    • 乱序执行(Out-of-Order Execution):克服指令间的数据依赖,最大化利用功能单元。这是现代CPU性能的核心。
    • 分支预测进阶:动态分支预测器(如两位饱和计数器、GShare、TAGE预测器)的实现。
  2. 存储子系统

    • 多级缓存(L1, L2, L3):研究其组织结构、替换策略(LRU、Random等)、写策略(Write-through/Write-back)。
    • 虚拟内存与TLB:理解页表、地址转换、TLB的结构与缺失处理。
  3. 并行架构

    • 多核与多线程:对称多处理(SMP)、缓存一致性协议(MESI及其变种)、内存模型(Memory Model)。
    • GPU架构:理解SIMT(单指令多线程)模型、Warps/SIMD单元、层次化内存(全局内存、共享内存、寄存器)。
  4. 实践与资源

    • 书籍:《Computer Organization and Design: The Hardware/Software Interface》(David Patterson & John Hennessy)是经典必读。《计算机体系结构:量化研究方法》是进阶宝典。
    • 开源项目:在GitHub上学习开源RISC-V CPU实现,如香山(XiangShan)、蜂鸟E203Rocket ChipBOOM。阅读代码和文档是极佳的学习方式。
    • 课程:除了ETH Zurich的这门课,还可以学习UC Berkeley的CS61C、MIT的6.004、CMU的18-447等公开课。
    • 社区:积极参与RISC-V国际基金会、相关开源社区、知乎、Stack Overflow的讨论。

计算机体系结构是一个深奥但极其迷人的领域。通过这门苏黎世的神课,你已经拿到了打开这扇大门的钥匙。从理解晶体管到设计流水线CPU,这个过程不仅会让你对计算机如何工作有颠覆性的认识,其背后的设计思想——分层抽象、权衡取舍、并行优化——也将深刻影响你作为软件工程师或硬件工程师的思维方式。动手去写Verilog,去仿真,去调试,当你第一次看到自己设计的CPU成功运行一段汇编程序时,那种成就感是无与伦比的。学习路径很长,但每一步都算数。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询