跳过正文

造一个最简单的CPU

·122 字·1 分钟
Banson
作者
Banson

所有这一切触发器都是按照时钟的节律同步变化的。当时钟上升沿到来时,印度女工更新 reg,同时也更新 pc(依据正是 inst、reg、pc 这三个经过一大坨 组合逻辑 后算出的结果)

一个 CPU 的核心状态就是由指令寄存器(instruction, inst)、寄存器文件(register file, regfile)、指令计数寄存器(program counter, pc)组成。所谓状态,哲学一点说就是某个系统在某一时刻所具有的所有内在特性,这些特性共同决定了系统的行为和演化。对于计算机而言,这些内在特性就是由 CPU 中的关键寄存器和计数器的值所决定的。

一旦这些寄存器中存储的内容确定,CPU 的某些重要特性就已经被决定。比如,当前指令的执行、存储的数据、以及下一条指令的地址等,都已经“锁定”在这些寄存器中。换句话说,只要我们知道这些寄存器的内容,CPU 的行为就是可预测的。因此,寄存器的内容在某种意义上定义了计算机的“命运”。

自从 $t_0$ 时刻的时钟上升沿产生后,这些寄存器存储的值,从它们的输出端,经过组合电路的运算,又反馈到这些寄存器的输入端,等待着在 $t_0 + 1$ 时刻时钟上升沿更新到这些寄存器中,替代旧值。读者可以把它看作类似“水坝”的结构,每当时钟上升沿到来时,水坝开闸,“水”流入池子中。

将要提到的重要组件
#

首先介绍一些基本的组件。

RegFile
#

RegFile

RegFile 对应的就是印度女工的“短期记忆”。可以认为它是一组(例如在 MIPS 处理器中,是 32 个)带编号的格子。它在读取时可以被视为组合电路,即 $output=f(addr)$。只要给定一个地址(addr),无需时钟参与,另一端就会输出对应格子中存放的数。在图中,寄存器拥有两个读端口,这意味着 reg1_data 由 reg1_addr 指定读取,reg2_data 由 reg2_addr 指定读取。

另一方面,在写入时,它的表现和同步触发器相同。在写入端(write_data)准备好的数据,在时钟上升沿到来时,会被写入到编号为 write_reg_addr 的格子(前提是 RegWrite 值为 1)。

ALU
#

算术逻辑单元。这是一个纯组合电路:

ALU

输入两个操作数 alu_in1 / 2、操作符 ALUOp,输出 Result = ALUOp(alu_in1, alu_in2)。所谓操作符,就是加减乘除、逻辑与或非运算等等中的一种。

内存
#

内存

在这个阶段,读者可以简单地把它理解为“容量更大的寄存器”。读为组合逻辑,写为同步时序逻辑。在印度女工的比喻中,这就是那条纸带。

既然内存和寄存器如此相像,为何要设置两个部件?我将在未来的一篇杂谈(Memory hierarchy)中详细谈一谈。参见:存储器层次结构

执行一条指令的步骤
#

我们将要描述一个单周期 CPU 是如何工作的。所谓单周期是指以下几个过程中所有控制信号的计算全部是由组合电路在两个相邻的上升沿之间完成的。也就是说,除了写存储器、结果写回、更新 PC 这样的“更新状态”的操作需要下一个时钟上升沿的参与,其他所有诸如指令译码、指令执行等操作全都是一大坨组合电路,它的组合延迟小于时钟周期,因此可以在“单”周期内完成。

  1. 取指令:CPU 根据 PC(程序计数器,Program Counter)中的指令地址,在指令存储器中获取相应的指令,之后 PC 的值会自动改变,移动到下一条指令的地址。
  2. 指令译码:对获取的指令进行分析,确定这个指令要完成什么操作,改变相应的控制信号。
  3. 指令执行:相关组件获取控制信号,执行相应操作,并将结果反馈。
  4. 存储器访问:如果指令涉及读取、存储内存,则需要对存储器中相应地址进行读取或者写入。
  5. 结果写回:将得到的数据(访问存储器或者修改寄存器的值获得)写回相应的寄存器。
  6. 循环 1-5

单周期 CPU 架构
#

单周期 CPU 架构

这是一个简单的单周期 CPU 架构示意。图中,我用红色方框标出了开头提到的核心状态:pc、inst、regfile;黄色方框标注的是内存,它也是系统状态的一部分,但在我们的印度女工比喻中,它是纸带,因此不是核心的一部分。其他所有部分都是组合电路。

注:图中把指令内存和数据内存分开画了,这主要是为了绘图的简便以及一些涉及到 Cache 的高级议题。读者可以暂时把它们理解为一块拥有两个读端口的内存(就像图中的寄存器一样),只不过被拆开画了。

概括来说,我们的主要工作就是不停地根据以上状态,使用组合电路来计算各种控制信号,并且在下一个时钟上升沿到来时,根据这些控制信号来改变这些状态。

  • ALU:算术逻辑单元。是组合电路。如果是加减乘除等算术指令,就负责计算结果;如果是分支指令,就负责计算跳转的目标地址。
  • NPC:Next PC。是组合电路。根据指令的内容(是否为跳转指令)、ALU 结果(目标地址)、当前 PC,计算出下一个 PC。
  • MUX:多路选择器。是组合电路。根据指令的类型,决定把什么结果写回 regfile:
    • 读访存指令:选中 Data Memory 的值
    • 算术指令:选中 ALU 的输出值
    • 立即数指令:选中指令字中解析出的值

Reference
#

本篇的大多数图片、表格来源于 BIT Build Your PC。这主要是因为我太懒了,不想自己准备这些素材。

相关文章