计算机组成原理

计算机系统概述

  1. 冯·诺依曼机的特点

    • 计算机由五大部件组成:运算器、控制器、存储器、输入设备、输出设备
    • 指令和数据以同等地位存于存储器,可按地址寻访
    • 指令和数据用二进制表示
    • 指令由操作码和地址码组成
    • 存储程序
    • 以运算器为中心(现代计算机以存储器为中心)
  2. \(1\) 字节(Byte) = \(8\) 比特(bit) 即 \(1B\) = \(8b\)

  3. 在存储容量中:\(1K = 2^{10}, 1M = 2^{20}, 1G = 2^{30}, 1T = 2^{40}\)
    与时间相关中:\(1K = 10^3, 1M = 10^6, 1G = 10^9, 1T = 10^{12}\)
    \(1s = 10^3ms, 1ms = 10^3us, 1us = 10^3ns, 1ns = 10^3ps\)

  4. 以运算速度衡量机器的运行速度:FLOPS: 每秒执行的浮点运算次数 = 程序中的浮点运算次数/执行时间

    以机器主频衡量机器的运行速度:主频 = \(\frac{1}{\text{主时钟周期}}\)\(1.5\) GHz指 \(1\) 秒内有 \(1.5\) G \(=1.5 \times 10^9\) 个时钟周期,所以一个时钟周期的时间是 \(\frac{1}{1.5G}\)

    以指令执行速度衡量机器的运行速度:CPI:执行一条指令所需要的平均时钟周期数,即CPI = \(\frac{\text{执行程序所需要的时钟周期数}}{\text{程序中指令的条数}}\)
    平均指令周期:平均执行一条指令的时间 = CPI \(\times\) 时钟周期 = CPI / 主频
    MIPS:每秒内执行指令的平均条数(以百万为单位)

    以基准测试程序评价计算机的性能

信息表示

  1. C数据类型隐式转换:低精度向高精度转换:精度由低到高依次是:short、int、long;float、double
    无符号和有符号整数混合运算,按无符号整数运算
    短字长转换为长字长:无符号高位扩展 \(0\),有符号高位扩展符号位
    长字长转换为短字长:截断,取低位

  2. R进制数 \(\Rightarrow\) 十进制:按权展开相加:
    \(D=d_n\times R^n + \dots +d_0\times R^0 + d_{-1}\times R ^{-1} + \dots + d_{-m}\times R^{-m}\)

    十进制数 \(\Rightarrow\) R进制数:

    • 整数部分 除基数(R)取余
    • 小数部分 乘基数(R)取整
    • 先取到的都是靠近小数点的

    二进制数、八进制数、十六进制数之间的转换:

    • 以小数点为界,分别向左、向右分组,不足的位数补 \(0\)
    • 整数部分将 \(0\) 补在数的左侧,小数部分将 \(0\) 补在数的右侧
    • 二进制转八进制:三位为一组
    • 二进制转十六进制:四位为一组
  3. 定点数: 小数点固定在某个位置上的数(隐含约定)

    • 定点整数(小数点约定在最低位的右边,最高位为符号位:\(X_{n-1} X_{n-2} \cdots X_0\ .\)
    • 定点小数(最高位为符号位,小数点约定在符号位的右边:\(X_{n-1}\ . \ X_{n-2} \cdots X_0\)

    浮点数: 小数点位置可浮动的数, 尾数用定点小数表示,阶码用定点整数表示
    规格化浮点数:真值的尾数部分最高位是非 \(0\) 数字(这里指的是真值,而不针对具体的编码方式,具体的编码看真值 \(1\) 在这个编码中是 \(0\) 还是 \(1\) 而有所不同)

    • 左规:尾数每左移一次(小数点右移),阶码相应减 \(1\)
    • 右规:尾数每右移一次(小数点左移),阶码相应加 \(1\)

    尾数(真值)的规格化形式:
    \(M>0\)(正数):\(0.1\cdots\)
    \(M<0\)(负数):\(-0.1\cdots\)
    尾数用原码表示的规格化形式:
    \(M>0\)(正数):[M]原=\(0.1\cdots\)\(1/2 \le M < 1\)
    \(M<0\)(负数):[M]原=\(1.1\cdots\)\(-1 < M \le 1/2\)
    尾数用补码表示的规格化形式
    \(M>0\)(正数):[M]补= \(0.1\cdots\)\(1/2 \le M < 1\)
    \(M<0\)(负数):[M]补= \(1.0\cdots\)\(-1 \le M < 1/2\)
    注:由于[-1/2]补 = \(1.100\dots0\)\(1.1\cdots\) 的形式而不是 \(1.0\cdots\) ,所以为了统一方便的判断补码表示的小数是否是规格化数,规格化数中不表示 \(-0.5\),而多表示一个本来无法表示的数 \(1.000\dots0\)\(-1\)

    IEEE754:
    单精度: \(1\) 位符号位 \(S\)\(8\) 位阶码 \(E\)(移码表示,偏置数为 \(127\)), \(23\) 位尾数 \(M\)(原码表示)\(= (-1)^S \times (1.M) \times 2 ^{E - 127}\)
    阶码\(-127 \iff\) 阶码 \(-128 + 1\),而 \(128\)\(2^7\)
    尾数计算的时候记得恢复约定的 \(1\)

    浮点数IEEE754
  4. 真值原码反码补码的转换

    真值原码转换

    无符号定点整数的表示范围: \(0 \le X \le 2^{n-1}\)
    有符号定点整数的表示范围:

    • 原码:\(-(2^{n-1} - 1) \le X \le 2^{n-1}-1\)
    • 反码:\(-(2^{n-1} - 1) \le X \le 2^{n-1}-1\)
    • 补码:\(-2^{n-1} \le X \le 2^{n-1}-1\)
    • 移码:\(-2^{n-1} \le X \le 2^{n-1}-1\)

    负数的补码比原码多一种数码组合。因此,不能用取反加1的方法对 \((100 \dots 00)\) 补求原码,但可以从定义式求真值,为 \(-2^{n - 1}\)

  5. 小端方式(Little endian):高高低低,高字节存入高地址单元,低字节存入低地址单元(注意:存在低地址的内容写在前面)
    大端方式(Big endian):高低低高,高字节存入低地址单元,低字节存入高地址单元

运算方法与运算器

  1. 补码加法:\([X+Y]_补 = [X]_补+ [Y]_补\)
    补码减法:\([X-Y]_补 = [X]_补+ [-Y]_补 = [X]_补-[Y]_补\)
    求补公式:\([-Y]_补 = \overline{[Y]_补} + 1\) 即:对 \([Y]\) 补逐位取反(包括符号位在内), 末位加 \(1\)

  2. 运算结果的特征标志:
    SF(Sign Flag)符号标志,SF=1(0)表示结果为负数(正数)
    ZF(Zero Flag)零标志, ZF=1(0)表示结果为零(非零)
    OF(Overflow Flag)溢出标志 OF=1(0) 表示结果溢出(无溢出)
    CF(Carry Flag)进位/借位标志 CF=1 (0)表示有(无)进位/借位

    CF:无符号数运算结果是否超出范围,运算结果仍然正确
    OF:有符号数运算结果是否超出范围,运算结果已经不正确

    溢出判断方法:

    • 当两加数同号,但和的符号不同时,则溢出
      \(A_{n-1}、B_{n-1}、S_{n-1}\) 分别表示被加数、加数、和的符号,则 \(OF = A_{n-1} \cdot B_{n-1} \cdot \overline{S_{n-1}} + \overline{A_{n - 1}} \cdot \overline{B_{n - 1}} \cdot S_{n-1}\)
    • 进位判断法:\(OF = C_n \oplus C_{n-1}\)
    • 变形补码(双符号位)判断法:溢出——双符号位不同,不溢出——双符号位相同,即 \(OF=S_{f1} \oplus S_{f2}\)

    对于无符号数的减法运算,转换为加法后,其借位是运算产生的进位 \(C_n\) 的反,即 \(CF=C_n \oplus mode\)

  3. 移位运算:
    逻辑移位移空的部分补\(0\)
    算术移位符号位保持不变,数值部分移空的部分补真值 \(0\)(即具体补 \(1\) 还是 \(0\) 看编码方式

    移位运算
  4. 原码一位乘法:
    1)积的符号位由两乘数的符号位异或得到
    2)积的原码数值部分由两乘数原码数值部分相乘得到
    3)将积的符号与积的数值拼接就得到积的原码

  5. 原码加减交替除法:
    1)若余数 \(\ge 0\),上商 "1",余数左移一位,减除数
    2)若余数 \(< 0\),上商 "0",余数左移一位,加除数
    3)因为运算过程中有左移,需采用双符号位

存储系统

  1. 存储容量:以位(b)或字节(B)为单位,如:\(64KB\)
    用存储单元数乘以存储单元字长,如:\(64K \times 8\)
    存取时间 \(T_a\) :从存储器接收访存申请开始,到读出/写入信息所需要的时间
    存储周期 \(T_m\) :两次连续的存储器访问所需的最短时间间隔; \(T_m > T_a\) 存储器带宽(数据传输率、吞吐率):单位时间内存储器可读写的信息量:\(B_m = W / T_m\),其中 \(W\) 是字长
    单位价格:容量为 \(S\) 位的存储器总价为 \(C\), 则每位价格 \(P=C/S\)

  2. 层次化存储系统:寄存器、高速缓存、主存、辅助存储器
    实现前提:程序局部性原理
    相邻层次之间的传送单位:数据块
    遵循原则:包含性(上层为下层的副本)、一致性(同一数据在不同层应保持一致)

  3. 随机存取存储器(RAM):

    特点 SRAM(静态存储器) DRAM(动态存储器)
    存储信息 触发器 电容
    破坏性读出 不是
    刷新 不需要 需要
    送行列地址 同时送 分两次送(地址线减半)
    运行速度
    集成度
    存储成本
    主要用途 高速缓存 主存

    只读存储器(ROM):ROM、PROM、EPROM、EEPROM;闪存(Flash ROM,用作BIOS)

    RAM和ROM都采用随机存取的方式,而随机存取存储器是指RAM

    DRAM刷新:

    • 集中刷新:在数据丢失之前集中刷新所有行,控制简单,速度快,但存在死区
    • 分散刷新:各刷新周期分散安排在存取周期中,不存在死区
    • 异步刷新:各刷新周期分散安排在最大刷新间隔内,缩短了死区
    动态DRAM
  4. 位扩展(字长扩展):将多个存储芯片的地址端、片选端和读写控制端相应并联,数据端分别引出,相互独立,各芯片并行工作
    字扩展:将芯片的地址端、片选端和读写控制端相应并联,由片选信号来区分各芯片的地址范围(高地址进行译码作为片选信号),数据线并联,同一时间仅有一个芯片在工作
    字位同时扩展:首先位扩展,后字扩展

  5. 磁盘的操作流程:所有磁头同步寻道(由柱面号控制)(移动臂)→ 选择磁头(由磁头号控制) → 被选中磁头等待扇区到达磁头下方(由扇区号控制)(磁盘旋转) → 读写该扇区中数据

    磁盘平均存取时间 = 平均定位时间(平均寻道时间 + 平均旋转等待时间)+ 数据传输时间
    平均寻道时间与磁头移动速度和盘径有关,(最大寻道时间+最小寻道时间)\(/2\),即磁头从 \(0\) 磁道移动到一半位置的时间
    平均旋转等待时间与磁盘转速有关,用磁盘旋转半周所需的时间来表示
    数据传输时间 \(=\) 磁盘旋转一周时间 \(/\) 每个磁道扇区数,(即读取一个扇区所需要的时间

    道密度:沿磁盘半径方向单位长度上的磁道数,单位:道/mm或道/英寸(TPI:track per inch)
    位密度:沿磁道圆周方向单位长度上所能记录的二进制位数,单位:位/mm,或位/英寸(BPI)
    对各个不同半径的磁道、记录的信息量是相同的,故磁道内圈位密度高,外圈位密度低,位密度以内圈为准

    数据传输率:单位时间内磁盘存储器能读写的有效字节数,也称吞吐率 \((B/s) =\) 扇区内字节数 \(\times\) 每道扇区数 \(\times\) 磁盘转速 \((r/s) =\) 每条磁道的容量 \((B)\) \(\times\) 磁盘转速 \((r/s)\)

  6. CPU与Cache、 CPU与主存传输数据的单位:字
    Cache与主存传输数据的单位:块(数据块)
    主存地址:块地址 (块号) + 块内偏移(offset);块号即原本主存地址的高位

    Cache地址映像:

    • 直接映像(Direct):每个主存块映像到Cache的固定行
      Cache行号 = 主存块号 \(\mod Cache\) 总行数
      注:\(\mod 2^n \iff\) 只保留二进制中的低 \(n\) 位,而删去高位
      假设数据块是 \(2^bB\) 为一块,主存有 \(2^m\) 块,Cache有 \(2^c\) 行,则
      主存地址直接映像 所以当CPU接收到主存地址时,取出中间的 \(c\) 位(即Cache行号),访问Cache,查看该行的有效位是否有效,若有效,查看该行的Tag是否等于收到的地址的高 \(m-c\) 位,若相等,则命中,否则访问主存,并将主存的内容调入到Cache中

    • 全相联(Full Associate):主存块可装入任意cache行
      主存地址全相联映像
      CPU接收到主存地址时,将地址高 \(m\) 位与 Cache 中存入的所有块号进行比较(相联比较器),若找到对应的Cache地址则命中,否则访问主存,并调入内容至Cache的任一空闲行

    • 组相联(Set Associate):每个主存块映像到Cache固定组中任一行,即组间直接映像,组内全相联映像
      Cache组号 = 主存块号 \(\mod Cache\) 总组数
      一个组内,有 \(n\) 个高速缓存行,称为 \(n\) 路组相联,设 \(t = \log_2 n\)
      主存地址组相联映像 CPU接受到主存地址时,取出中间 \(c-t\) 位(即Cache组号),经过组内相联比较器,若找到对应的Cache行号,则命中,否则访问主存,并调入内容至Cache对应组中的任一空闲行

指令集架构

  1. 指令的格式:操作码+地址码
    操作码的长度决定指令系统的规模,操作数地址的长度决定寻址空间大小

    指令地址码
  2. 移位指令:移位位数由 rs2/imm 的低 \(5\) 位给出
    分支指令:12位立即数:imm[12:1],实际表示13位的字节地址偏移量 imm[12 : 0],RISC-V预留了16位的指令字长,为与其统一,只隐藏最低一位,imm[0]固定为0,不出现在指令中
    J型指令:用20位立即数表示,21位地址偏移量,隐藏最低位

  3. 寻址方式:

    寻址方式

RISC-V微架构

  1. 结构冲突:多条指令同时使用同一个功能部件

    • 寄存器堆访问:
      产生原因:在译码阶段需要从寄存器堆读取两个操作数, 在写回阶段需要将操作结果写入寄存器堆 解决方案:设计更多的独立端口,比如,设计两个读端口、一个写端口来满足需求
    • 存储器访问: 产生原因:前面指令正在访问存储器数据,同时当前指令需要从存储器中取指令
      解决方案:设计分立的指令存储器和数据存储器(哈佛结构)
      设计两个分立的Cache(指令Cache 和 数据Cache) 解决存储器访问类的结构冲突
  2. 数据冲突:后面指令用到前面指令的结果数据时,前面指令的结果还没产生
    先读后写、先写后写都不会产生冒险,先写后读有可能会产生数据冒险(读的时候读出的可能是旧值
    解决方案:

    • 软件阻塞:(如:编译器)在后面的数据相关指令前插入nop指令
    • 硬件阻塞:在数据相关指令的特定流水段“阻塞”指令继续执行(插入“气泡”),直到取得所需数据为止
    • 采用转发(Forwarding/Bypassing)技术:把前面指令执行过程中得到的数据直接传送到后面指令相应的流水段中
    • 对于load-use,采用“阻塞加转发”的方式解决数据冲突
    • 编译程序优化指令顺序

    如何判断需要转发:在译码阶段比较当前指令 源寄存器(rs1/rs2)与 流水线中前3条指令的目的寄存器(译码段、执行段、写回段流水线寄存器中rd)是否相同

  3. 控制冲突:转移类指令改变执行流程,后继指令在目标地址产生前已被取出
    解决方案:

    • 软件阻塞:(如:编译器)在控制相关指令后面插入nop指令
    • 硬件阻塞:在控制相关的正确目标指令被取出前,使流水线停顿若干时钟(插入“气泡”)
    • 采用静态或动态分支预测
    • 编译程序优化指令顺序(分支延迟)
  4. 流水线性能:

    • 加速比:不采用流水线方式执行 \(n\) 个任务所需时间 与 采用流水线方式执行 \(n\) 个任务所需时间的比值,反映了速度提高的倍数
    • 吞吐量:任务数 \(n\) 与流水线方式执行 \(n\) 个任务所需要时间的比值,反映了单位时间内流水线能够完成的任务数量
    • 效率:流水线各段的实际使用时间之和与整个流水线被占用时间之和的比值,反映了各功能段的利用率

输入输出系统

  1. I/O接口:位于主机与外设之间,协助完成数据传送和控制任务的逻辑电路,每个I/O接口包含一组寄存器
    I/O端口:I/O接口内能够被CPU直接访问的寄存器,用于在CPU与外设之间传递信息
    ① 数据信息 -> 数据端口(数据输入端口、数据输出端口)
    ② 状态信息 -> 状态端口
    ③ 控制(命令)信息 -> 命令端口
    CPU通过地址来区分和访问不同的I/O端口
    CPU与端口通过数据总线传递信息

  2. 单重中断:不允许在中断处理时被新的中断打断,所以直到中断返回前才开中断,单重中断系统无需设置中断屏蔽字
    中断嵌套 (多重中断):中断处理程序中必须开中断, 需设置屏蔽字,可动态改变中断处理的先后次序,一般屏蔽优先级较低的中断请求,使只有优先级比它高的中断请求才能被响应
    中断屏蔽字:同级和低级的设为中断屏蔽,高级设为中断允许

    中断优先级:
    中断响应优先级:由查询程序或硬件排优线路决定的优先权,反映多个中断同时请求时选择哪个响应
    中断处理优先级:由各自的中断屏蔽字来动态设定,反映本中断与其它中断间的关系

    多重中断