02 Arithmetic and memory

What to know before arithmetic and memory

After logic gates: the parts a simple CPU core needs and the circuits to meet first inside the ALU, then one addition traced through fetching, decoding, computing and saving, to show why a result has to be stored once it is computed. It ends by matching what comes next to chapters of CS:APP.

This note is only available in Chinese for now.

前一篇整理了逻辑门的规则,以及怎样根据真值表组合出需要的电路。接下来要把一位信号扩展成多位数据,再让电路保存计算结果,继续参与下一次运算。

二进制计算、选择数据和保存状态,都是构成 CPU 核心所需的基础能力。先把各个部件负责什么、彼此怎样配合梳理出来,后面搭加法器或寄存器时,就知道正在补上哪一块。

1. 一个简单 CPU 核心需要哪些部件?

先以一个简单的同步整数处理器为例。它需要读取指令,按指令要求处理数据,并保存结果和执行进度。下面按功能列部件,具体实现时,有些功能可以共用电路。

这里“整数”表示先处理整数运算;“同步”表示保存新状态的时刻由时钟协调。可以先把指令理解成一条操作要求,例如“把这两个位置里的数相加,再存到第三个位置”。程序就是按一定顺序组织起来的这些指令。

部件或功能 负责什么 一个直接的例子
算术逻辑单元(ALU) 根据控制信号,对输入的数据做指定运算 这次把两个数相加,下次对它们逐位做 AND
寄存器与寄存器组 在核心内部保存正在使用的数据 保留两个操作数,把运算结果写入某个寄存器
选择器(MUX)与数据通路 选择数据来源,把数据送到需要的位置 ALU 的一个输入来自寄存器,或来自指令中的常数
译码与控制逻辑 识别指令,产生选路、运算、读写等控制信号 指定 ALU 做加法,并允许目标寄存器写入
程序计数器(PC)及更新逻辑 保存取指位置,决定后续从哪里取指令 顺序前进,或者按跳转条件换到另一处
存储器访问接口 传递地址、读写数据和控制信号 从某个地址读一个数,或把结果写回该地址
时钟、复位与状态更新机制 协调什么时候保存新状态,以及从什么状态开始 在规定的时钟边沿写入结果,复位后从指定位置执行

这里的数据通路是数据流经的寄存器、运算电路、选择器和连线的整体;控制逻辑决定每一步怎样使用这条通路。ALU 是其中负责运算的一部分。这样的划分也出现在 MIT 的处理器与指令集讲义中。

寄存器通常位于核心内部,主存通常位于核心之外,由访问接口连接。缓存用于缓解速度差异,它在具体芯片中怎样分布,属于后续的存储层次问题。先搭一个能运行程序的简单核心,可以从寄存器和基本存储器接口开始。

2. 计算单元里面,先认识哪些电路?

ALU 的名字里有「算术」和「逻辑」,所以它既处理数字,也处理位。下面这些运算能力可以由不同电路实现,也可能共用部分硬件。

运算部件 处理什么 先这样理解
加法器 把两个二进制数相加 从低位开始算,装不下的部分进到高一位,和竖式加法类似
减法电路 求两个数的差 把减去 B 改成加上负 B;补码让加法器也能处理这件事
按位逻辑电路 对各位做 AND、OR、XOR、NOT 等运算 每个位置各算各的,例如 8 位 AND 就让 8 对输入分别做 AND
比较电路 判断相等、大小,或结果是否为零 比较前先明确这些位按什么数来读;同一串位可能表示正数,也可能表示负数
移位电路 把位向左或向右移动 左移通常在右边补 0;右移可以在左边补 0,也可以补原来的最高位,要看采用哪种运算
运算结果选择电路 从几种候选结果中选出本次结果 控制信号指定哪一路结果送到输出

进位、零值、有符号溢出等也可能形成供控制逻辑使用的信号。有些指令集会把其中一部分保存在标志寄存器里,有些采用其他方式表达比较结果,具体要看指令集和实现。

乘除法器、浮点运算单元、向量运算单元可以在后面继续了解。它们是否独立设置、支持哪些操作,取决于处理器的目标。当前先理解整数运算和数据保存,足够支撑最初的核心设计。

3. 用一次加法,把这些部件串起来

用 R3 ← R1 + R2 表示「取出 R1、R2 保存的数,相加后写入 R3」。这只是说明操作含义的记法,尚未指定某种机器指令的编码。

R1、R2、R3 是三个寄存器的名字,像三个有编号的小格子,名字中的数字不是格子里保存的数值。箭头 ← 表示把右侧算出的结果写入左侧的位置。这次操作只写 R3,不会因为读了 R1、R2,就把它们原来的内容拿走。

  1. 取指令: 根据 PC 给出的位置,从指令存储器取出指令。
  2. 读懂要求: 译码后确定这次做加法、读取 R1 和 R2、把结果交给 R3。
  3. 送入数据: 寄存器组提供两个值,选择器把它们送到 ALU 的输入端。
  4. 算出结果: 加法电路计算各位及进位,经过传播延迟后结果稳定。
  5. 保存并继续: 在规定的更新时刻把结果写入 R3,并按设计更新 PC,继续执行。

假设 R1 保存 3,R2 保存 5,ALU 算出 8;写入之前,R3 仍保留自己的旧值。这个区别就是「已经算出一个结果」与「已经保存这个结果」的区别。

例如 R3 原来保存 9,这次操作可以这样核对:

时刻 R1 的内容 R2 的内容 R3 的内容
操作前 3 5 9
已算出 8,但尚未写入 3 5 9
完成写入后 3 5 8

上述步骤描述的是各部件的职责。一次指令需要几个时钟周期,取决于核心采用单周期、多周期还是流水线等实现,后面再结合具体电路讨论。

如果数最初放在主存里,还需要通过存储器读取它;若要求把结果存回主存,也需要一次相应的写入。怎样把这些操作组织成指令,与选择的指令集有关。

4. 从计算到保存数据

二进制的表示、进制转换和计算,单独记在第三篇:二进制与二进制速算里。这里继续看计算结果怎样保存,并交给后续操作使用。

4.1 算出结果,还要把它保存下来

计算电路根据输入给出结果;如果输入变了,结果也可能跟着变。要把某一次的结果留住,就需要存储电路。

例如,把结果 8 写进寄存器以后,即使加法器开始算别的数,这个寄存器也可以继续保存 8,直到下一次写入新值。保存下来的值,就是后续计算可以继续使用的状态。

一个存储单元保存一位,八个一起就能保存一个八位数。把多个保存位置按编号组织起来,就可以按地址读写数据。地址负责指出位置,数据是这个位置里保存的内容。

例如某块存储器的地址 12 中放着 8:“读地址 12”得到的是数据 8;“把 5 写到地址 12”之后,位置仍叫 12,内容变成 5。地址不是这次要参与加法的数,它是在指出去哪里取数或存数。

在这里先考虑有时钟的设计:计算电路先算出结果,存储部件再按约定的时刻接收它。算好与存好是两个步骤,这也是后面需要同时考虑运算和时钟的原因。

4.2 后面的内容,用到时再展开

下面这些先知道用途就够了,具体推导和接线跟着实践补充:

内容 现在先知道什么 到哪一步再详细讲
半加器、全加器 加法要同时算本位结果和进位;全加器还接收低位送来的进位 搭一位和多位加法器时
补码、减法与溢出 负数需要约定表示规则;补码让加法器可以参与完成减法;固定的位数也可能装不下结果 开始处理负数和减法时
选择器、译码器 选择器从几路数据中挑一路;译码器根据编号选中对应位置 需要选 ALU 输入、运算结果或存储位置时
反馈、锁存器、触发器 反馈是把输出接回前面的输入;合适的结构能够保存状态,存储部件还要控制何时接收新值 开始搭保存一位数据的电路时
寄存器组、RAM 的读写规则 按编号选位置,读取其中的数据,或在允许写入时放入新数据 把多个保存位置组织起来时
指令、控制与 PC 指令规定做什么,控制信号安排各部件,PC 记录从哪里取指令 把运算和存储连接成完整核心时

这些内容会在后续搭建中用到,但需要配合解释、推导和验证来理解。先看懂输入输出的含义,再动手接线;做到哪个部件,就把那个部件的原理补完整。

5. 与《CS:APP》怎样对应?

这些内容涉及数字逻辑、计算机组成与指令集。《CS:APP》第三版中,可以按正在解决的问题回看相应章节。下面的对应关系依据作者公开的目录与前言整理:

当前问题 对应章节 重点
计算机有哪些主要部件,程序怎样开始运行? 第 1 章:计算机系统漫游 处理器、主存与系统整体关系
位怎样表示数,加减法为什么会溢出? 第 2 章:信息的表示和处理 位运算、整数编码、补码与整数运算
程序怎样使用寄存器、内存和跳转? 第 3 章:程序的机器级表示 从机器指令观察状态和数据操作
门、寄存器和控制怎样组成处理器? 第 4 章:处理器体系结构 组合逻辑、存储与时钟、数据通路及处理器实现
寄存器、缓存和主存为什么需要分层? 第 6 章:存储器层次结构 存储技术、局部性、缓存和层次关系

近期先以第 2 章的整数表示和运算、第 4 章的逻辑与处理器组成为主线。锁存器、反馈电路和加法器的具体搭建,再结合数字逻辑材料展开;缓存、流水线、浮点数等内容留到基本的数据计算与保存流程清楚之后。

这一阶段先建立的联系是:位组成数,逻辑门计算这些位,存储电路保留结果,控制逻辑安排下一步。