第一章 CPU之前世今生
1.1、CPU众生相
1.1.1 处理器(cpu)和处理器内核(core)的区分
处理器严格意义上是soc,包含了内核和其他设备或者存储器.
1.1.2 不同CPU架构的诞生时间
CPU架构 | 诞生时间 |
---|---|
Intel 8086 | 1978年 |
ARM | 1985年 |
MIPS | 1985年 |
AMD64 | 2003年 |
1.1.3 ISA–CPU的灵魂
指令是指处理器进行操作(加减乘除)的最小单元。有了指令集开发人员就可以使用不同的处理器实现方案来设计不同性能的处理器。处理器的具体硬件实现被称为“微架构”。不同的微架构会造成性能与成本上的差异,但软件无须做任何修改便可以完全运行在任何一款遵循同一指令集架构实现的处理器上。
1.1.4 CISC与RISC-V架构
- CISC是复杂指令集,不仅包含了处理器常用的指令,还包含了许多不常用的特殊指令
- RISC是精简指令集,对于不常用的指令,则通过执行多条常用指令的方式达到同样的效果
1.1.5 32位架构与64位架构
处理器架构的位数是指通用寄存器的宽度,它决定了寻址范围的大小、数据运算能力的强弱。例如对于32位架构的处理器,通用寄存器的宽度为32位,拥有4GB(2^32)的寻址空间,运算指令可以操作的操作数有32。并不是说指令长度是32位。
1.1.6 ISA众生相
- X86架构。Intel公司使用微码化克服了CISC架构的部分缺点。
- SPARC架构。这是一种非常有代表性的RISC架构。占用很多的芯片不适用于PC和嵌入式领域。但是相对开发,在航天领域应用较多,但是2017年退出历史舞台。
- MIPS架构。RISC架构。
- Power架构是IBM开发的一种RISC架构。这一架构在银行金融、大型企业、超算都有很好的应用,可靠性、可用性和可维护性较好。
- ARM架构
- RISC-V架构
1.2、 国产CPU
- MIPS:龙芯、君正
- X86:北大众志、上海兆芯、天津海光
- ARM:飞腾、海思、展讯、ARM授权主要分为两种:一种是授权IP,一种是授权ARM架构。前三家公司主要是根据架构设计自己的处理器核
- RISC-V:平头哥、芯来科技
对于一款CPU来说,绝对的硬件技术水平不是最重要的,又有依附于x86或者ARM阵营的商业公司,才能够实现商用。
1.3、 ARM统治着世界
ARM公司虽然也设计处理器核,但是其商业模式是作为知识产权供应商。
- Cortex-A:面向性能密集型系统的应用处理器核
- Cortex-R:面向实时应用的高性能核
- Cortex-M:面向各类嵌入式应用的微控制器核
1.3.1 Cortex-M系列
是一组用于低功耗微控制器领域的32位RISC处理器系列,包括M0、M0+、M1、M3、M4(F)、M7(F)等。如果M4包含FPU则带F
1.3.2 Cortex-A系列
是一组用于高性能低功耗应用处理器领域的32和64位RISC处理器系列。从32型号开始都是64位
第二章 大道至简——RISC-V架构之魂
模块化的RISC-V架构能够位用户灵活地选择不同的模块组合,例如针对小面积低功耗的嵌入式场景,用户可以选择 RV32IC组合的指令集,仅使用机器模式;针对高性能应用操作系统场景则可以选择注入RV32IMFDC的指令集,使用机器模式和用户模式。基本指令只有40多条,加上其他的模块化拓展指令欧洲你公公几十条指令。
2.2 RISC-V架构简介
2.2.1 模块化的指令集
RISC-V的基本指令集如下表
基本指令集 | 指令数 | 描述 |
---|---|---|
RV32I | 47 | 支持32位地址空间与整数指令,支持32个通用整数寄存器 |
RV32E | 47 | RV32I 的子集,仅支持16个通用寄存器 |
RV64I | 59 | 支持64位地址与整数指令,同时支持 部分32位的整数指令 |
RV128I | 71 | 支持128位地址与整数指令,同时支持 部分64、32位的整数指令 |
RISC-V的拓展指令集如下表
拓展指令及 | 指令集 | 描述 |
---|---|---|
M | 8 | 整数乘除指令 |
A | 11 | 存储器原子操作指令和Load Reserved/Store Conditional指令 |
F | 26 | 单精度浮点指令 |
D | 26 | 双精度浮点指令 |
C | 46 | 压缩指令,指令长度为16 |
“IMAFD”为一个特定组合,称为G,即RV32G表示RV32IMFAD。
为了提高代码密度,RISC-V架构提供可供选择的压缩指令子集,压缩指令的编码长度为16位,而普通的非压缩指令的编码长度为32位。
E代表着一种“嵌入式”架构,追求极低面积与功耗的嵌入式场景,仅仅需要支持16个通用整数寄存器。
2.2.2 可配置的通用寄存器组
RISC-V架构的整数通用寄存器组包含32个(I架构)或者16个(E架构)通用整数寄存器,其中整数寄存器x0是为常数0预留的,其他的31个或15个为普通的通用整数寄存器。如果使用浮点模块,则需要另外一个独立的 浮点寄存器组。
2.2.3 规整的指令编码
RV32I规整的指令编码格式如图2-3所示。因此指令译码器可以非常方便地译码出寄存器索引然后读取通用寄存器。
2.2.4 简洁的存储器访问指令
RISC-V采用专用的存储器读(load)指令和存储器写(store)指令访问存储器(memory),使用其他的指令无法访问存储器,这个是RISC架构常用的一个基本策略。存储器的读写指令支持以一字节(8位)、半字(16位)、单字(32位)为单位的存储器读写操作。
存储器访问指令有如下显著特点:
- 推荐使用地址对齐的存储器读写操作
- 仅支持小端格式。大端模式: 是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;小端模式: 是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中。
- 存储器读和存储器写指令不支持地址自增自减模式。
- 采用松散存储器模型,对于访问不同地址的存储器读写指令的执行顺序没有要求。
2.2.5 高效的分支跳转指令
RISC-V架构有两条无条件跳转(unconditional jump)指令,即jal指令与jalr指令。
跳转链接指令(jump and link,jal)指令可用于进行子程序调用,同时将子程序返回地址存放在链接寄存器(link register,由某一个通用整数寄存器担任)中。
跳转链接寄存器指令(jalr)指令能够用于从子程序返回。
RISC-V架构有6条带条件的跳转指令,相当于把比较和跳转两个操作放到一条指令里完成
2.2.6简洁的子程序调用
一般的RISC的调用过程如下
- 进入子函数之后需要用存储器写指令来将当前的上下文(通用寄存器等的值)保存到系统存储器的栈区内,这个过程称为保存现场。
- 在退出子程序时,需要用存储器读指令来将之前保存的上下文(通用寄存器等的值)从系统存储器的栈区读出来,这个过程通常称为恢复现场。
这两个操作会消耗CPU的执行时间。有些RISC架构采用一次写多个寄存器的值到存储器中的指令,好处在于可以一条指令干很多事,但是会影响时许,加大硬件设计难度限制CPU主频。然而RISC-V架构则放弃使用一次读多个寄存器的指令和一次写多个寄存器的指令。
2.2.7 无条件码执行
很多早期的RISC架构支持带条件码的指令,例如指令编码的头几位表示的是条件码,只有该条件码对应的条件为真,该指令才真正执行。
RISC-V放弃了这种带条件码的指令的方式,对于任何的条件判断都使用普通的带条件分支的跳转指令。
2.2.8 无分支延迟槽
早期的RISC都使用了分支延迟槽(delay slot)。MIPS就是代表。分支延迟槽就是指在每条分支指令后面都紧跟一条或者若干条指令,它们不受分支跳转的影响,不管分支是否跳转,这些指令都会执行。
RISC-V放弃了这个,因为现代高性能处理器的分支预测算法已经非常准确了
零开销硬件循环指令
2.2.10 简洁的运算指令
RISC-V架构使用模块化的方式组织不同的指令子集,基本的整数指令子集(I)支持的操作包括加法减法、移位、按位逻辑操作和比较操作。这些操作可以通过组合或者函数库的方式完成更多的复杂操作。
2.2.11 CSR
控制与状态寄存器(CSR)用于重置或记录一些运行的状态。CSR是处理器核内部的寄存器,使用自己的地址编码空间,和存储器寻址的地址区间完全无关系。