ALU介绍
在计算机系统中,ALU(Arithmetic Logic Unit)是中央处理器的主要组成部分,它代表算术逻辑单元,执行算术和逻辑运算。它也称为整数单元 (IU,integer unit),它是 CPU 或 GPU 内的逻辑电路,是处理器中执行计算的最后一个组件。它能够执行所有与算术和逻辑运算相关的过程,例如加法、减法和移位运算,包括布尔比较(XOR、OR、AND 和 NOT 运算)。此外,二进制数可以完成数学和按位运算。ALU分为AU(算术单元)和LU(逻辑单元)。ALU 使用的操作数和代码告诉它必须根据输入数据执行哪些操作。当 ALU 完成输入处理后,信息被发送到计算机的内存中。
图2 ALU在四级流水中的示意图
除了执行与加法和减法相关的计算外,ALU 还可以处理两个整数的乘法,因为它们旨在执行整数计算;因此,它的结果也是一个整数。但是,除法运算通常不能由 ALU 执行,因为除法运算可能会产生浮点数的结果。相反,浮点单元 (FPU,floating-point unit) 通常处理除法运算;FPU 也可以执行其他非整数计算。
浮点数的由来:用科学计数法的方式表示小数时,小数点的位置就变得「漂浮不定」了,这就是相对于定点数,浮点数名字的由来。
图2 浮点数示例
虽然 ALU 是处理器中的主要组件,但 ALU 的设计和功能在不同的处理器中可能会有所不同。例如,有些 ALU 设计为仅执行整数计算,而有些则用于浮点运算。一些处理器包含单个算术逻辑单元来执行操作,而其他处理器可能包含许多 ALU 来完成计算。ALU 执行的操作是:
逻辑运算:逻辑运算包括 NOR、NOT、AND、NAND、OR、XOR 等。
移位操作:它负责将位的位置向右或向左位移一定数量的位置,也称为乘法运算。
算术运算:虽然它执行乘法和除法,但这是指位加法和位减法。但是乘法和除法运算的成本(逻辑复杂度和面积)更高。在乘法运算中,加法可以用作除法和减法的替代。
ALU的信号
ALU 包含各种输入和输出连接,这使得外部电子设备和 ALU 之间可以投射数字信号。ALU 输入从外部电路获取信号,作为响应,外部电子设备从 ALU 获取输出信号。
数据:ALU 包含三个并行总线,包括两个输入和输出操作数。这三个总线处理的信号数量是相同的。
操作码:当 ALU 将要执行操作时,操作选择码描述了 ALU 将执行哪种类型的运算或逻辑运算。
输出:ALU 操作的结果由状态输出以补充数据的形式提供,因为它们是多个信号。通常,诸如溢出、零、执行、负数等状态信号都包含在通用 ALU 中。当 ALU 完成每个操作时,外部寄存器包含状态输出信号。这些信号存储在外部寄存器中,使它们可用于未来的 ALU 操作。
输入:当 ALU 执行一次操作时,状态输入允许 ALU 访问更多信息以成功完成操作。此外,存储的来自先前 ALU 操作的进位被称为单个“进位”位。
图3 ALU输入输出示意图
ALU 是一种组合逻辑电路,这意味着它的输出将随着输入变化而异步变化。在正常操作中,稳定信号被施加到所有 ALU 输入,当信号通过 ALU 电路传播足够的时间(称为“传播延迟”)时,ALU 操作的结果出现在 ALU输出。连接到 ALU 的外部电路负责确保 ALU 输入信号在整个操作过程中的稳定性,并在对 ALU 结果进行采样之前留出足够的时间让信号通过 ALU 传播。
通常,外部电路通过向 ALU 的输入施加信号来控制 ALU。通常,外部电路采用时序逻辑来控制 ALU 操作,该操作由频率足够低的时钟信号来控制,以确保 ALU 输出有足够的时间在最坏情况下稳定下来。
图4 74181型四比特ALU
例如,CPU 通过将操作数从它们的源(通常是寄存器)路由到 ALU 的操作数输入来开始 ALU 加法操作,而控制单元同时将值应用于 ALU 的操作码输入,将其配置为执行加法。同时,CPU 还将 ALU 结果输出路由到将接收和的目标寄存器。在 CPU 等待下一个时钟时,允许 ALU 的输入信号在下一个时钟之前保持稳定,通过 ALU 传播到目标寄存器。当下一个时钟到达时,目标寄存器存储 ALU 结果,并且由于 ALU 操作已经完成,ALU 输入可以设置为下一个 ALU 操作。
ALU 的配置
每个算术逻辑单元都包括以下配置:Instruction Set Architecture、Accumulator、Stack、Register-Register Architecture、Register - Stack Architecture、Register and Memory。
Accumulator:每个操作的中间结果都包含在累加器中,这意味着指令集架构(ISA)并不复杂,因为只需要保存一位。通常,它们速度更快且不太复杂,但使 Accumulator 更稳定;需要编写附加代码以用适当的值填充它。不幸的是,对于单个处理器,很难找到累加器来执行并行性。累加器的一个例子是桌面计算器。
Stack:每当执行最新操作时,这些操作都会存储在以自上而下顺序保存程序的堆栈中,这是一个小寄存器。当新程序被添加执行时,它们会推送旧程序。
Register-Register Architecture:它包括 1 个目标指令和 2 个源指令的位置,也称为 3 - Register操作机。该指令集架构必须更长,以存储三个操作数、1 个目标和 2 个源。运算结束后,将结果写回寄存器会很困难,而且字的长度也应该更长。但是,如果在这个地方遵循写会规则,可能会导致更多的同步问题。
Register - Stack Architecture:通常,寄存器和累加器操作的组合称为寄存器 - 堆栈架构。需要在寄存器堆栈架构中执行的操作被压入堆栈顶部。它的结果保存在堆栈的顶部。借助反向抛光方法,可以分解更复杂的数学运算。一些designer为了表示操作数,使用二叉树的概念。这意味着反向抛光方法对这些程序员来说很容易,而对其他程序员来说可能很困难。要执行 Push 和 Pop 操作,需要创建新的硬件。
Register and Memory:在这种架构中,一个操作数来自寄存器,另一个来自外部存储器,因为它是最复杂的架构之一。其背后的原因是每个程序都可能非常长,因为它们需要保存在完整的内存空间中。该技术一般与Register-Register 技术相结合,实际上不能单独使用。
ALU的功能
一算术运算
加法:A 和 B 相加,和出现在 Y 和进位。
进位加法:A、B 和进位相加,总和出现在 Y 和进位处。
减法:从 A 中减去 B(反之亦然),差值出现在 Y 和进位。对于此功能,结转实际上是一个“借”指标。这个操作也可以用来比较A和B的大小;在这种情况下,处理器可能会忽略 Y 输出,处理器只对操作产生的状态位(特别是零和负数)感兴趣。
借位减法:借位(进位)从 A 中减去 B(反之亦然),差值出现在 Y 和进位(借出)处。
二进制补码:从零中减去 A(或 B),差值出现在 Y 处。增量计算:A(或 B)加 1,结果值出现在 Y。减量计算:A(或 B)减 1,结果值出现在 Y。
Pass through:A(或B)的所有位在Y处显示为未修改。此操作通常用于确定操作数的奇偶校验或是否为零或负数,或将操作数加载到处理器寄存器中。
二位逻辑运算
AND:A 和 B 的按位与出现在 Y 处。
OR:A 和 B 的按位 OR 出现在 Y 处。
异或:A 和 B 的按位异或出现在 Y 处。
1 的补码:A(或 B)的所有位都被反转并出现在 Y 处。
三位移操作
ALU 移位操作导致操作数 A(或 B)左移或右移(取决于操作码),移位后的操作数出现在 Y。简单的 ALU 通常只能将操作数移位一位,而更复杂的 ALU 使用桶形移位器允许他们在一次操作中将操作数移动任意位数。在所有单位移位操作中,移出操作数的位出现在进位输出;移入操作数的位的值取决于移位的类型。
算术移位:操作数被视为二进制补码整数,这意味着最高有效位是“符号”位并被保留。
逻辑移位:将逻辑零移入操作数。这用于移动无符号整数。
循环:操作数被视为循环位缓冲区,因此其最低有效位和最高有效位有效相邻。
进位循环:进位位和操作数共同被视为位的循环缓冲区。
图5 八比特ALU位移计算示意图