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

  • Post author:
  • Post category:其他



目录


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的逻辑表达式允许

    参数是任意整数

    ,逻辑门只对位值

    0





    1

    进行操作
  • 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有D





      10


      ,j


      xx/call





      Dest





      9


      ,ret


      /halt/nop





      1



  • 译码:

    需要“读入”用来操作的寄存器里的数

    • 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;

];



版权声明:本文为gzn00417原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。