当前位置:   article > 正文

计算机系统课程 笔记总结 CSAPP第四章 处理器体系结构(4.1-4.3)_csapp第四章总结

csapp第四章总结

目录

4.1 Y86-64指令集体系结构

4.1.1 程序员可见的状态

4.1.2 Y86-64指令

4.1.3 指令编码

加法指令(QPq)

4.1.4 Y86-64异常

4.1.5 Y86-64程序

4.2 逻辑设计和硬件控制语言HCL

4.2.1 逻辑门

4.2.2 组合电路和HCL布尔表达式

4.2.3 字级的组合电路和HCL整数表达式

4.2.4 集合关系

4.2.5 存储器和时钟

4.3 Y86-64的顺序实现

4.3.1 将处理组织成阶段

4.3.2 SEQ硬件结构

4.3.3 SEQ的时序

4.3.4 SEQ阶段的实现


 

4.1 Y86-64指令集体系结构

 

 

 

 

 

 

 

 

 

 

 

 

 

定义一个指令集体系结构包括定义:

  • 各种状态单元
  • 指令集
  • 指令集的编码
  • 一组编程规范
  • 异常事件处理

 

 

 

 

 

 

 

 

指令的层次

  • 指令系统处在软/硬件交界面,同时被硬件设计者和系统程序员看到
  • 硬件设计者角度:指令系统为CPU提供功能需求,要求易于硬件设计
  • 系统程序员角度:通过指令系统来使用硬件,要求易于编写编译器
  • 指令系统设计的好坏还决定了:计算机的性能和成本

 

 

 

 

ISA指令系统的设计原则

  • RICS还是CISC
    • 还是Risc+Cisc
  • 完备性:ISA的指令足够使用
    • 功能齐全:不能没有加法指令,但可以没有inc指令
  • 有效性:程序能够高效率运行
    • 生成代码小:频率高的操作码、操作数短
  • 规整性:对称性、匀齐性、一致性
    • push rsp / pop rsp   应保证栈顶恢复
  • 兼容性:相同的基本结构、共同的基本指令集
  • 灵活性
    • 如操作数的寻址方式:满足基本的数据类型访问
  • 可扩充性:操作码字段预留一定的空间

4.1.1 程序员可见的状态

 

 

 

 

 

 

 

 

  • 内存:很大的字节数组,保存程序和数据
  • 虚拟地址:用来引用内存位置
    • 硬件和操作系统联合将虚拟地址翻译成实际或物理地址
    • 虚拟内存系统向Y86-64程序提供了单一的字节数组映像

 

 

 

 

4.1.2 Y86-64指令

 

 

 

 

 

 

 

 

  • x86-64的mov指令分成4个不同的指令
    • irmovq, rrmovq, mrmovq, rmmovq
    • 分别指明源和目的的格式
    • 源可以是立即数(i)、寄存器(r)、内存(m)
    • 目的可以是寄存器(r)、内存(m)
    • 不允许:
      • 内存地址直接传送到另一个内存地址
  • 4个整数操作指令,QPq
    • addq, subq, andq, xorq
    • Y86-64中只对寄存器进行操作
    • 3个条件码:ZF(零)、SF(符号)、OF(溢出)
  • 7个跳转指令
    • jmp, jle, jl, je, jne, jge, jg
    • 根据条件选择分支
  • 6个条件传送指令
    • cmovle, cmovl, cmove, cmovne, cmovge, cmovg
  • call指令将返回地址入栈,ret指令从这样的调用中返回
  • pushq和popq指令实现入栈和出栈
  • halt指令停止指令的执行
    • x86-64:hlt

 

 

 

 

4.1.3 指令编码

寄存器编码:

 

指令集功能码:

 

 

  • 4位:代码code部分
  • 4位:功能function部分(一组相关指令共用一个代码时使用)

加法指令(QPq)

两字节编码:

  • 第一字节指出指令类型
  • 第二字节指出源和目的寄存器

  • e.g. addq %rax,%rsi    编码: 60 06

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

当寄存器和内存移动是,内存m是rB

 

 

 

 

 

 

4.1.4 Y86-64异常

 

 

 

 

 

程序员可见的状态码Stat

 

  • 遇到异常后,我们简单地让处理器停止执行指令;
  • 更完整的设计中,处理器会调用异常处理程序(exception handler

 

 

 

4.1.5 Y86-64程序

  • 尽量多用C编译器
    • 用 C 编码
    • 在 x86-64 中用gcc –Og –S 编译
    • 把X86-64的asm直译到 Y86-64 中
    • 现代编译器使得这个过程更加复杂

4.2 逻辑设计和硬件控制语言HCL

 

 

 

 

 

  • 数据类型
    • bool: 布尔
      • a, b, c, …           (小写)
    • int:
      • A, B, C, …           (大写)
      • 不指定字大小——字节, 64-位 字, …
  • 声明
    • bool a = 布尔表达式 ;
    • int A = 整数表达式 ;

 

通过返回值的类型分类

  • 布尔表达式
    • 逻辑操作
      • a && b, a || b, !a
    • 字比较
      • A == B, A != B, A < B, A <= B, A >= B, A > B
    • 集合成员
      • A in { B, C, D }
        • 与A == B || A == C || A == D一样
  • 字表达式
    • 情况表达
      • [ a : A; b : B; c : C ]
      • 按顺序评估测试表达式 a, b, c, …
      • 返回和首次成功测试对应的字表达式A, B, C, …

 

 

 

  • 计算
    • 通过组合逻辑实现
    • 计算布尔函数
    • 连续地对输入变化响应
  • 存储
    • 寄存器
      • 存储
      • 当时钟上升时加载
    • 随机存取存储器
      • 存储
      • 可能有多个读/写端口
      • 输入地址变化 --> 读取字
      • 时钟上升 --> 写入字

4.2.1 逻辑门

4.2.2 组合电路和HCL布尔表达式

  • 逻辑门的输入必须连接到下述之一:
    • 一个系统输入(主输入)
    • 某个存储器单元的输出
    • 某个逻辑门的输出
  • 两个逻辑门的输出不能连接在一起
  • 无环

 

 

 

 

 

位相等:bool eq = (a&&b)||(!a&&!b)

 

字相等:bool Eq = (A == B)

 

 

 

HCL和C语言区别:

  • HCL输入变化后,一定延迟,输出也相应变化;C语言只会在程序执行过程中被遇到时才进行求值
  • C的逻辑表达式允许参数是任意整数,逻辑门只对位值01进行操作
  • C的逻辑表达式可能只被部分求值,若一个and或er操作的结果只用对第一个参数求值就能确定,那就不会对第二个参数求值了;逻辑门只是简单地响应输入地变化
    • a&&func()
    • 若a为真,则不进入func函数

4.2.3 字级的组合电路和HCL整数表达式

  • bool Eq = ( A == B )
  • A B为int型

4.2.4 集合关系

4.2.5 存储器和时钟

  • 时钟寄存器,简称寄存器
    • 存储单个位或字
    • 时钟信号控制寄存器加载输入值
    • 边缘触发锁存器的集合
  • 随机访问存储器,简称内存
    • 存储多个字
    • 用地址来选择该读或该写哪个字

寄存器:时钟上升沿加载输入

随机存取存储器

  • RAM:存储内存中的多个字
    • 通过输入的地址来决定读/写哪个字,写由clk控制。
  • RF:寄存器文件
    • 硬件寄存器:稳态、组合逻辑的屏障,CLK边沿触发。如:PC、CC、Stat 等
    • 程序寄存器:存储数据,可按ID读、写的存储单元。汇编级%rax, %rsp, %r14等,机器级-寄存器ID标识符作为地址(0000-1110) 15 (0xF) 表示不执行读写
  • PORTS:多端口
    • 在每个周期可以同时读/写多个字
      • 每个端口有单独的地址和数据输入/输出

寄存器文件

  • 2读端口
    • 地址输入:srcA, srcB (source)
    • 数据输出:valA, val B (value)
    • 类似组合逻辑
  • 1个写端口
    • 地址输入:dstW (destination)
    • 数据输:valW
    • 类似寄存器
    • 只在时钟上升沿更新
  • 多端口随机访问寄存器,允许同时进行多个读和写操作
  • 每个端口都有一个地址输入,表明该选择哪个程序寄存器
  • 还有一个数据输出对应该程序寄存器的输入值

 

 


4.3 Y86-64的顺序实现

4.3.1 将处理组织成阶段

 

 

 

 

 

 

 

 

 

  • rA存数值
  • rB存地址
  • M[rB+D]=rA / rA=M[rB+D]

 

 

 

 

 

 

 

 

 

 

 

 

  • valE = %rsp的值 栈顶元素的地址
  • M[valA] = 原栈顶元素

 

 

 

SEQ各阶段

  • 取指
    • icode:ifun <-- M1[PC]
    • rA:rB <-- M1[PC+1]
    • valP <-- PC+2(mov有D10,jxx/callDest9,ret/halt/nop1
  • 译码:需要“读入”用来操作的寄存器里的数
    • val <-- R[rA]
    • val <-- R[rB]
  • 执行
    • valE=……
  • 访存:有用到内存时(读出/写入)
    • valA <--> M[valB]
  • 写回:写入寄存器
    • R[rB] <-- rA/val
  • 更新PC
    • PC <-- valP

4.3.2 SEQ硬件结构

 

 

 

 

 

 

 

 

 

 

 

 

4.3.3 SEQ的时序

原则:从不回读

4.3.4 SEQ阶段的实现

 

 

 

 

 

 

 

 

 

# Determine instruction code

int icode = [

imem_error: INOP;

1: imem_icode;

];

 

# Determine instruction function

int ifun = [

imem_error: FNONE;

1: imem_ifun;

];

 

bool need_regids =    icode in

     { IRRMOVQ, IOPQ, IPUSHQ, IPOPQ,

  IIRMOVQ, IRMMOVQ, IMRMOVQ };

 

bool instr_valid = icode in

{ INOP, IHALT, IRRMOVQ, IIRMOVQ,   

           IRMMOVQ, IMRMOVQ, IOPQ, IJXX, ICALL,

           IRET, IPUSHQ, IPOPQ };

 

bool need_valC = icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ, IJXX, ICALL };

 

 

 

译码/写回逻辑

  • 寄存器文件
  • 读端口 A, B
  • 写端口 E, M
  • 地址为寄存器的ID
    • 或 15 (0xF) -无法访问

 

 

 

 

 

 

 

 

 

int srcA = [

  icode in { IRRMOVQ, IRMMOVQ, IOPQ, IPUSHQ  } : rA;

  icode in { IPOPQ, IRET } : RRSP;

  1 : RNONE; # 不需要寄存器

];

 

int dstE = [

icode in { IRRMOVQ } && Cnd : rB;

icode in { IIRMOVQ, IOPQ} : rB;

icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP;

1 : RNONE;  # 不写任何寄存器

];

 

word srcB = [

         icode in { IOPQ, IRMMOVQ, IMRMOVQ  }    : rB;

                icode in { IPUSHQ, IPOPQ, ICALL, IRET } : RRSP;

            1 :               RNONE;  # Don't need register

];

 

int word dstM = [        

    icode in { IMRMOVQ, IPOPQ } : rA;        

    1 :             RNONE;  # Don't write any register

];

 

 

 

执行逻辑

  • 单元
    • ALU
      • 实现四种所需的功能
      • 生成条件码
    • CC
      • 包含三个条件码位的寄存器
    • cond
      • 计算条件转移或跳转标识
  • 控制逻辑
    • Set CC: 是否加载条件码寄存器?
    • ALU A: 数据A送ALU
    • ALU B: 数据B送ALU
    • ALU fun: ALU执行哪个功能?

 

 

 

 

 

 

 

 

 

int aluA = [

icode in { IRRMOVQ, IOPQ } : valA;

icode in { IIRMOVQ, IRMMOVQ, IMRMOVQ } : valC;

icode in { ICALL, IPUSHQ } : -8;

icode in { IRET, IPOPQ } : 8;

# 其他指令不需要ALU

];

 

int alufun = [

icode == IOPQ : ifun;

1 : ALUADD;

];

 

int aluB = [

icode in { IRMMOVQ, IMRMOVQ, IOPQ, ICALL,                            IPUSHQ, IRET, IPOPQ }         : valB;

       icode in { IRRMOVQ, IIRMOVQ    }         : 0;

# 其他指令不需要ALU

];

 

bool set_cc = icode in { IOPQ };

 

 

 

访存逻辑

  • 访存
    • 读写内存里的数据字
  • 控制逻辑
    • stat: 指令状态是什么?
    • Mem. read: 是否读数据字?
    • Mem. write: 是否写数据字?
    • Mem. addr.: 选择地址
    • Mem. data.: 选择数据

 

 

 

 

 

 

 

 

 

## 决定指令状态

int Stat = [

imem_error || dmem_error : SADR;

!instr_valid: SINS;

icode == IHALT : SHLT;

1 : SAOK;

];

 

int mem_addr = [

icode in { IRMMOVQ, IPUSHQ, ICALL, IMRMOVQ } : valE;

icode in { IPOPQ, IRET } : valA;

# 其他指令不需要地址

];

 

bool mem_read = icode in {IMRMOVQ,IPOPQ,IRET };

 

bool mem_write = icode in { IRMMOVQ, IPUSHQ, ICALL };

 

word mem_data = [        

         # Value from register

icode in { IRMMOVQ, IPUSHQ } : valA;

# Return PC

icode == ICALL : valP;        

# Default: Don't write anything];

 

 

 

更新PC逻辑

 

 

 

 

 

 

 

 

 

int new_pc = [

icode == ICALL : valC;

icode == IJXX && Cnd : valC;

icode == IRET : valM;

1 : valP;

];

 

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/973518
推荐阅读
相关标签
  

闽ICP备14008679号