ALU

  • 算术逻辑单元 (Arithmetic and Logic Unit, ALU) 是计算机实际完成数据算术逻辑运算的部件

    • 数据由寄存器 (Registers) 提交给ALU, 运算结果也存于寄存器

    • ALU可能根据运算结果设置一些标志 (Flags), 标志值也保存在处理器内的寄存器中

    • 控制器 (Control Unit) 提供控制ALU操作和数据传入送出ALU的信号

      image-20250119215221171

加法

全加器

image-20250119215228863

  • 注意: 异或门只能由2个输入端, 故需要6个门, 3与门, 1或门, 2异或门

    image-20250119215238060

  • 优化: 实际需要2与门, 1或门, 2异或门, 但是延迟更高了

    image-20250119215245621

  • 不足: 延迟高

串行进位 (行波进位) 加法器 RCA

image-20250119215252451

  • 实际就是将多个全加器连在一起

  • 延迟:

    • Cn = 2n
    • Fn = Cn-1 + 3 = 2(n - 1) + 3 = 2n + 1 (n ≥ 3, 当n = 1 或 2 时, F = 6)
  • 不足: 高位的运算必须等待低位的"进位输出信号"

  • 思考: 能否提前计算出"进位输出信号"?

全先行进位加法器 CLA

image-20250119215258583

  • 设:

    • C0, Xi, Yi 都是已知输入
    • 生成 (Generate) 信号: Gi = Xi * Yi
    • 传播 (Propagate) 信号: Pi = Xi + Yi

image-20250119215305507

image-20250119215310687

  • 延迟:

    • 1 (P和G同时计算) + 2 (C的与或门延迟依次计算) + 3 (F的第二个异或门延迟) = 6
  • 优点: 延迟和加法器的位数无关

  • 不足: 难以实现, 越到高位需要的与门越多

部分先行进位加法器

image-20250119215318591

  • 采用多个CLA并将其串联, 取得计算时间硬件复杂度之间的权衡

image-20250119215323859

  • 延迟:

    • 3 (第一个CLA算出C8的总延迟) + 2 (第二个CLA算C16的与或门延迟) + 2 (同前一个) + 5 (同前一个外还有F的第二个异或门延迟) = 12

溢出问题

image-20250119215345885

image-20250119215350874

减法

  • 溢出判断与加法相同

乘法

image-20250119215400202

  • 特征: 乘数右移一位, 被乘数左移一位, 中间结果直接与部分积累加

  • 需要: n位支持右移寄存器, 2n位支持左移寄存器, 2n位寄存器和2n位加法器

image-20250119215407873

流程优化

  • 加法和移位并行

    image-20250119215414661

乘法器优化

  • 减少不必要的硬件

image-20250119215425794

  • 需要: 1个n位加法器, 1个n位寄存器 (存被乘数), 1个2n位支持右移的寄存器 (乘数和乘积共用)

image-20250119215432011

image-20250119215436587

问题1 : [X * Y]c ≠ [X]c * [Y]c

原码一位乘法

  • 被乘数乘数由补码表示改为原码表示

  • 符号位数值位分开运算

  • 乘积结果由原码表示改为补码表示

image-20250119215448772

补码一位乘法 – 布斯算法

image-20250119215455682

image-20250119215500793

  • 运算步骤:

    1. 增加 y0 = 0
    2. 根据 yi+1yi 决定是否执行 [Pi]c + [±X]c
    3. 右移部分积
    4. 重复 步骤2 和 步骤3 共n次, 得到最终结果

image-20250119215505873

  • 补的第n位 = 原第n位

    • 原来第n位为0, 右移后补0; 原来第n位为1, 右移后补1

问题2 : 溢出

  • 对于带符号整数

    • -2n-1 ≤ x * y ≤ 2n-1 - 1不溢出
    • 即: 当乘积的高n位全0或全1, 并等于低n位的最高位时, 不溢出
  • 对于无符号整数

    • 0 ≤ x * y ≤ 2n - 1不溢出
    • 当乘积的高n位全0时, 不溢出

image-20250119215517033

除法

  • 被除数的左侧补充符号位, 将除数最高位被除数次高位对齐

  • 被除数中减去除数, 若够减, 则上为1; 若不够减, 则上为0

  • 右移除数, 重复上述步骤

image-20250119215525315

除法器

image-20250119215530890

  • 需要:

    • 一个2n位加法器
    • 一个2n位寄存器 : 被除数/余数
    • 一个2n位支持右移寄存器 : 除数
    • 一个n位支持左移寄存器 : 商

运算过程

image-20250119215536008

流程图

image-20250119215541688

除法器优化

  • 余数除数的减法运算中, 实际上只有n位参与了运算

  • 余数除数寄存器中, 至少有一个需要支持左移或右移

  • 寄存器必须支持左移, 且只需要n位

image-20250119215547736

  • 需要:

    • 一个n位加法器
    • 一个n位支持左移寄存器 : 被除数/余数
    • 一个n位支持左移寄存器 : 余数/商
    • 一个n位寄存器 : 除数

异号的除法

  • 异号, 需要取补码, 余数本身就是补码

image-20250119215553289

比较余数和除数 (比较绕, 多理理)

  • 如何判断 “够减” : 余数是否足够"大"

    • 如果余数和除数的符号相同 : 减法
    • 如果余数和除数的符号不同 : 加法
    • 够 : 补1; 不够 : 补0恢复

image-20250119215601974

  • 余数除数

    • 绝对值变小
    • 符号不能变 (0视为不变)

运算过程

image-20250119215608629

流程图

image-20250119215613045

问题 : 恢复余数成本高

  • 思路: 不恢复余数

    • 只考虑减法
      • 如果余数Ri足够大 : Ri+1 = 2Ri - Y
      • 如果余数Ri不够大 : Ri+1 = 2(Ri + Y) - Y = 2Ri + Y

补码不恢复余数除法

image-20250119215624579

image-20250119215629331

image-20250119215651740

  • 最后还要判断余数和除数是否相同, 若相同要进行处理**(这是不恢复余数除法的固有bug)**

其他

  • 只有一种情况发生溢出

    • -2n-1 / -1 = 2n-1
  • 编译器处理一个变量2n相除时, 一般采用右移运算实现

    • 无符号: 逻辑右移
    • 带符号: 算术右移
    • 能整除时: 直接右移得到结果, 被移除的全为0
    • 不能整除时: 被移出数存在非0, 采取朝零舍入
      • 无符号: 直接右移得到结果, 移出的低位直接舍弃
      • 带符号: 加偏移量2k - 1, 然后再移k位, 低位截断

image-20250119215658664