目录
- 1 存储器的分类
- 1.1 按存储介质分
- 1.2 按照存取方式分
- 1.3 按照在计算机中的作用分
- 2 存储器的层次结构
- 3 主存储器
- 3.1 主存的模型
- 3.2 半导体存储芯片的译码驱动方式
- 3.3 RAM(随机访问存储器)
- 3.3.1 静态RAM(SRAM)
- 3.3.2 动态RAM(DRAM)
- 3.3.3 SRAM和DRAM的比较
- 3.4 ROM(只读存储器)
- 3.4.1 ROM的发展历程
- 3.4.2 几种ROM的简介
- 3.5 存储器与CPU的连接
- 3.5.1 存储器容量的扩展
- 3.5.2 根据指定的地址范围连接CPU
- 3.6 存储器的校验
- 3.6.1 为什么要对数据做校验
- 3.6.2 如何进行校验
- 3.6.3 一个容错编码的例子——汉明码
- 3.7 提高访问速度的措施
- 4 高速缓冲存储器(Cache)
- 4.1 Cache的一些基本概念
- 4.1.1 Cache的工作原理
- 4.1.2 Cache的基本结构
- 4.1.3 Cache的读写操作
- 4.1.4 Cache的改进
- 4.2 Cache-主存的地址映射
- 4.3 替换算法
- 5 辅助存储器
- 参考文献
1 存储器的分类
1.1 按存储介质分
存储器 |
介质 |
半导体存储器(易失) |
TTL、MOS |
磁表面存储器(非易失) |
磁头(读/写)、载磁体(存储) |
磁芯存储器(非易失) |
硬磁材料,环状元件 |
光盘存储器(非易失) |
激光(读/写),磁光材料(存储) |
总的来说,目前使用的存储介质有三种,半导体、磁性材料、光学材料。其中半导体存储器和磁盘使用较多,磁芯存储器、光盘等已经被淘汰或正在慢慢消失。
1.2 按照存取方式分
存取时间与物理地址无关(随机访问):
存取时间与物理地址有关(串行访问):
1.3 按照在计算机中的作用分
Cache:
- 高速缓冲存储器,位于CPU和主存之间,用于缓存主存的数据。本质上是一块集成到CPU的SRAM。
主存储器:
- RAM
- 静态RAM(SRAM)
- 动态RAM(DRAM)
- ROM
- MROM(掩膜ROM)
- PROM(可编程ROM)
- EPROM(电可编程ROM)
- EEPROM(电可编程可擦除ROM)
辅助存储器:
- 闪存、磁盘等,速度上闪存 > 磁盘。因此有的磁盘会集中一小块闪存作为缓存,以提高访问速度。目前已经有计算机仅带有闪存,而不带磁盘。
2 存储器的层次结构
一个计算机系统中使用的存储器不只一种,这些存储器按照一定的层次结构(距CPU的距离)组织起来:
计算机使用到的存储器 |
寄存器 |
缓存 |
主存 |
辅存(如磁盘、闪存) |
以上存储器,从上到下,速度越来越慢;容量越来越大;成本越来越低。用多种存储器组建整个存储系统的目的在于为用户提供一个速度快、容量大、成本低的完美存储器,而这样的存储器目前是无法由一种存储器构成。当然,为了管理好各种存储器,需要CPU提供一些硬件机制;也需要操作系统提供一些软件机制。
2.1 缓存-主存
缓存到辅存的管理由CPU提供的硬件来完成,通常软件开发者不需要了解其中的细节。
2.2 主存-辅存
主存到辅存的管理由CPU提供的MMU以及操作系统提供的内存管理模块共同完成,不仅可以为每个进程提供独立的地址空间,还可以借助辅存让那些比主存容量还要大的程序得以运行。
3 主存储器
3.1 主存的模型
主存通常采用半导体存储芯片(DRAM),其与CPU的连线以及功能框图如下:
主存的寻址方式:
- 按字节寻址,每个地址对应一个字节
- 按字寻址,每个地址对应一个字
主存的技术指标:
- 存储容量:存放二进制数据的总位数或总字节数
- 存储速度:
- 存取时间:存储器的访问(读/写)时间,即给出地址信号到访问完成所需的时间
- 存取周期:连续两次独立的存储器访问操作所需的最小时间间隔,通常大于存取时间
3.2 半导体存储芯片的译码驱动方式
3.3 RAM(随机访问存储器)
在讨论RAM的时候,需要关注这么几点内容:
- 存储单元如何保存0和1
- 基本单元电路的构成
- 单元电路的读/写操作
- 典型芯片的结构
- 芯片的读/写操作
下文会按照这些内容讨论SRAM和DRAM。
3.3.1 静态RAM(SRAM)
SRAM使用触发器来保存0和1这两个状态。先简单介绍一下触发器,触发器是具有记忆功能的单元电路,由门电路构成,有双稳态、单稳态和无稳态几种。以RS触发器为例,这是一种双稳态的触发器,具有两个稳定的状态,即0、1两种状态。其逻辑图和逻辑符号如下:
当我们保证输入端R、S始终相反时,有如下的真值关系(1、0状态就保存在输出端Q):
输入 |
Q |
R = 0, S = 1 |
0 |
R = 1, S = 0 |
1 |
RS触发器就说到这里,下面来看SRAM的基本单元电路构成:
基本单元电路的读/写操作示意图如下:
以Intel的2114芯片为例,该芯片的结构如下:
芯片的读写操作示意图如下:
3.3.2 动态RAM(DRAM)
概括的说,DRAM使用电容来存储1、0。读数据时,当电容是高电平的时候为1,低电平的时候为0。写数据时,写1就是为电容充电,写0则是电容放电。由于电容会通过电路漏电,时间一久电荷就会流失,导致信息丢失,因此需要周期性的刷新电容(为电容充电)。
DRAM的基本单元电路结构有三管的也有单管的,其结构以及读/写操作的说明如下图所示:
典型的DRAM芯片Intel 1103的结构如下所示:
该芯片在读/写操作时,通过行地址和列地址锁定某个存储单元,再通过读/写控制信号使相应的管子导通,进而完成读/写操作,不再赘述。值得一提的是,有些DRAM为了节省地址线,会将行地址和列地址复用同一组引脚,此时付出的代价是增加了读/写时序的复杂度:需要专门的时序来完成行列地址的同步。
3.3.3 SRAM和DRAM的比较
从以下几个方面来比较SRAM和DRAM:
- 存储原理
输出DRAM使用电容存储数据;SRAM使用触发器存储数据
- 集成度
DRAM的基本单元电路结构更简单,方便大规模集成,因此DRAM集成度更高
- 引脚数量
DRAM通常将行列地址复用引脚,因此引脚数量少(进而芯片封装的体积较小);而SRAM出于速度的考虑,一般不会这样做
- 功耗
DRAM的功耗主要消耗在电容充放电(有电流)的时候,功耗较小;SRAM的使用触发器存放数据,而构成触发器的管子有部分是一直导通的,也就一直消耗功率,因此功耗较大
- 价格
同样存储一个bit,DRAM的单元电路简单,价格低;SRAM的单元电路复杂,用的管子多,因此价格高
- 速度
访问DRAM伴随着电容的充放电,因此速度较慢;而SRAM没有这个问题,访问速度快
- 刷新
DRAM需要周期性的刷新其中的电容,才能保持数据;SRAM则没有这个需要。
出于两者各自的特点,DRAM和SRAM在计算机中的用途也各不相同,DRAM通常被用作主存,也是大家通常所说的内存。SRAM则被用来作为高速缓存(Cache)。当然,这也不绝对,由于SRAM访问简单,无需初始化(不需要专门的时序和相应的硬件控制器),一些对内存容量要求不高的MCU直接使用SRAM作为程序运行所需的RAM。
3.4 ROM(只读存储器)
3.4.1 ROM的发展历程
- 早期的ROM在出厂时就会被厂家烧写好内容,且不支持用户再次对ROM进行编程
- 用户可以使用专门的擦写设备对芯片进行一次擦写,仅可擦写一次
- 用户可以使用专门的擦写设备对芯片进行多次擦写,比如用紫外线擦写的EPROM,这时候擦写还比较麻烦
- EEPROM的出现使得用户可以多次擦写ROM,且无需使用专门的擦写设备
3.4.2 几种ROM的简介
- MROM
行列选择线交叉处有MOS管则表示1,无MOS管则表示0。因为有无MOS管在芯片生产出来后就决定了,因此不可编程。
- PROM
PROM可一次性编程,通常实现为在行列选择线之间添加一根熔丝,编程时需要写0则加大电流让熔丝熔断,否则熔丝连通表示1。由于熔丝熔断后不可在连接,因此只可进行一次编程。
- EPROM
EPROM可通过对芯片中的N型沟道浮动栅MOS管的D端加电压,形成浮动栅,进而电路不导通表示0,反之表示1。浮动栅可由紫外线照射后消除,因此可以利用紫外线实现芯片的全部擦写,从而实现芯片的多次编程。
- EEPROM
EEPROM改进了芯片的擦写功能,实现了电可擦写,且既可局部擦写也可全局擦写。
- Flash Memory
闪存,较EEPROM成本更低,单元电路更为简单,集成度高,访问速度也更快。不过寿命(擦写次数)不如EEPROM,因此闪存通常用于保存大量数据,而EEPROM则用于存放不需要经常改变的一些系统参数(数据量少)。只有少数支持片上执行(XIP)的闪存(如NorFlash)才可以作为主存储器,存放程序(不可以随机写,因此无法存放程序运行时加工的数据)。而大部分闪存一般用作辅存。
3.5 存储器与CPU的连接
3.5.1 存储器容量的扩展
- 位扩展
电路连接时,两块或多块芯片共用地址线,数据线则分别与CPU的不同数据线连接
- 字扩展
电路连接时,共用低位的地址线,片选信号则通过译码器连接CPU地址线的高位,芯片数量少时,也可以不用译码器,直接使用非门
- 字、位扩展
先按字扩展将多个芯片组成一个位数更多的芯片组,各组之间再按照字扩展的连接方式与CPU连接
3.5.2 根据指定的地址范围连接CPU
示例:
CPU有16根地址线,A0~A15,可寻址空间为64KB,现有:4K x 8的ROM、4K x 8的RAM可选;要求:最小的4KB连接ROM,相邻的8KB连接RAM。
对于这种设计要求,我们可以按照以下步骤去思考并实现:
- 写出对应的二进制地址码
- 确定RAM、ROM的数量
- 分配地址线
A0~A11直接连接存储芯片的地址线,A12、A13、A14与译码器连接,进而连接到存储芯片的片选(这只是一种可能的设计),A15只有保持为低,地址信号才是合法的。
- 确定片选信号的连接
片选信号与译码器连接时,要注意A12、A13、A14和译码器输出的关系,确保RAM、ROM处在各自的地址范围中,最后连接的结果如下:
3.6 存储器的校验
3.6.1 为什么要对数据做校验
为什么要对存储器进行校验呢?因为在一些情况下,比如复杂的电磁环境下,工作中的存储器受到干扰,可能导致其内部存储的1、0发生翻转,即1变成0、0变成1,这样存储的信息就出错了。如果我们无法得知这一情况,而在程序中使用了错误的数据,那么就可能造成损失。
3.6.2 如何进行校验
对数据进行容错编码,就可以获得检错,甚至纠错的能力。这部分内容更多在信息论
课程中阐述,有兴趣的同学可以去了解以下,组成原理课程只是简单介绍。闲话不多说,先使用几个例子建立一个初步的映像:
检0位错,纠0位错
以上编码集合,采用3位编码,其中一个合法编码的任一位或多位出错得到的还是一个合法的编码,因此无检错和纠错能力。
检1位错,纠0位错
以上编码集合,采用3位编码,其中一个合法编码的一位出错时得到的是一个非法的编码,因此可以检出一位错,但是不能确定是哪一位出错,因此无法纠错。而两位出错时,得到的是一个合法编码,因此无法检出两位及更多位出错。
检1位错,纠1位错
以上编码集合,采用3位编码。显然,上述编码集合具有检出一位错的能力,并且能纠正一位错,如000出错为100,就是第一个bit出错了。但两位出错时,就无能为力了。如100也可能是111出错两位得到的,由于两位出错的概率小于一位出错,所以对任何非法编码仅当一位出错来纠正,如果真的是一位出错,则没有问题,如果是两位甚至更多位出错,那么纠正之后的结果是错误的。
检2位错,纠1位错
以上编码集合,采用4位编码。有了上文分析,很容易得出其检错和纠错的能力,不再赘述。
检2位错,纠2位错
以上编码集合,采用5位编码。有了上文分析,很容易得出其检错和纠错的能力,不再赘述。
本节的最后,再来思考一个问题:编码的检错和纠错能力与什么有关?
这里直接给出结论:
一个编码集合中,任意两个合法编码之间二进制位数的最少差异称为编码的最小距离,编码的纠错和检错能力与其最小距离有关。具体关系如下:
符号 |
含义 |
L |
编码的最小距离 |
D |
能够检错的位数 |
C |
能够纠错的位数 |
L - 1 = D + C (D >= C)
3.6.3 一个容错编码的例子——汉明码
汉明码是一种具有一位检错和一位纠错能力的编码,采用分组的奇偶校验。所谓奇偶校验指的是位数据增加一位校验位使得数据中1的个数位奇数(奇校验)或偶数(偶校验),分组则可以缩小校验的范围。看一个例子:
汉明码的分组方式要更为复杂,为了避免过于理论的表述,先看一个非常有趣的例子:
1000瓶水里有且只有一瓶毒药(从外部特征上不能区别),现有10只小鼠可以实验,但只能喂一次,利用这1次机会,找出毒药是哪瓶?
不兜圈子,直接给出这个趣味题的解,先对每瓶水进行编号,从1到1000:
每个编号的二进制也在图中给出,10个bit足够描述从1到1000。现在将所有编号的bit0为1的水归入P1组;所有bit1为1的水归入P2组,依次类推,共10组。不难看出,各组之间有交集。然后将各组的混合水分别喂给1到10的小鼠,最后看小鼠的情况。
假设小鼠1没有中毒,那么说明毒水的编号的bit0为0;小鼠2中毒了,则毒水的编号的bit1为1;小鼠3中毒了,则毒水的编号的bit2为1;剩余小鼠均未中毒,则毒水的编号的[10:3]为0。最终,毒水的编号为00 0000 0110。
以上就是汉明码的纠错原理了。可能这么说还不够明了,我们进一步用小鼠与毒水的趣味题来类比汉明编码:
小鼠与毒水 |
汉明编码 |
小鼠 |
校验位 |
1000瓶水 |
1000bit数据 |
唯一的毒水 |
发生错误的那一位(汉明码仅可检/纠错1位) |
值得一提的是,汉明码的校验码不是单独放置的,而是夹在数据当中,且所在位置较为特殊,只在第1、2、4、8…处放置校验码:
这样做是有意义的,处在这些特殊的位置,在分组时第1个校验码自然就被分到第一组,用于第一组的奇/偶校验,且不属于其它组(仅属于第一组,用于第一组的校验)。同理,第2个校验码自然就被分到第二组…。此外,校验码是1还是0,则取决于校验码所在组中1的个数,以及采用奇校验还是偶校验。
如果上述内容还是不能让你理解汉明码,那么不妨看看这篇博客,或许能有帮助:说人话,人话!! 汉明码(海明码、hamming code)通俗易懂的解释,说人话!!!!
3.7 提高访问速度的措施
- 采用高速的存储芯片
如SDRAM(同步DRAM)、RDRAM(由Rambus开发)、带Cache的DRAM等
- 采用层次结构 Cache-主存
根据程序的局部性原理,使用Cache将部分接下来可能访问的内存数据缓存起来
- 调整主存结构
1、单体多字系统
将存储器的和CPU的存储控制器的位宽设置为CPU字长(寄存器宽度)的整数倍,一次性可以读出多条指令或数据,缺点是写的时候,如果仅写一个字的内容比较麻烦,需要相应的硬件配合。
2、多体并行系统
主要思想是采用多个存储器并行工作,CPU访问第一个存储器后,在读到数据前,无需等待,直接访问下一个存储器。这样一轮下来,第一个存储器已经准备好了数据,并能够接收下一次访问(存取周期已到),于是再来一轮。如此,CPU和存储器都不会空闲。图示如下:
4 高速缓冲存储器(Cache)
使用Cache来缓存内存的数据,可以加速CPU访问数据和指令的速度,这对打破内存墙很有意义。本节就将介绍一些Cache的知识。
4.1 Cache的一些基本概念
4.1.1 Cache的工作原理
Cache之所以行之有效,就不得不提程序的局部性原理,这个原理的内含分两部分,一是时间的局部性:当前访问到的指令和数据在不久的将来很有可能还会被访问到;二是空间的局部性:当前访问的指令和数据的附近的指令和数据在不久的将来很可能会被访问到。因此,如果我们把当前访问的指令、数据及其附近的指令和数据都缓存到Cache,那么之后再访问时,CPU就无需访存了,进而提升了系统的性能。
再Cache-主存这一系统中,主存和Cache中的数据(包括指令)都是按块存储的,且块大小相同,换句话说,一处内存如果被缓存了,则它在主存中的块内偏移和Cache中的块内偏移是相同的。一个大体的结构图如下所示:
上图中,内存共被分为M块,缓存共C块,每块都含有B个字,通常M >> C,也就是说同一时间只有一小部分内存会被缓存。这样设计是很合理的,既可以控制成本和功耗,根据局部性原理,也可以保持较高的效率。
主存中的数据都是按块被缓存的,当某块被缓存时,由硬件为Cache的每一块维护的标记会记录下被缓存的主存块的块号。之后CPU访问该块的数据时,在缓存的标记中可以找到该块的块号,且相应缓存块有效,那么就不需要访存了,直接访问相应的缓存块即可。
当CPU需要访问的数据已经被缓存,即缓存的标记已经将相应的主存块和缓存块建立了关联,CPU无需访问主存即可获得数据,此时缓存命中,否则缓存未命中。CPU多次访问数据,其中缓存命中的比率称为Cache的命中率。命中率与Cahce的容量和块的大小有关,一般来说容量越大,块越大,则命中率越高。当然,凡是不能极端,缓存过大会提升成本和功耗,而块过大会减少块的数量,进而降低同一时间能够被缓存的主存块的数量。
除了命中率这一指标,还可以从访问数据耗时的角度来衡量Cache-主存系统的效率:
4.1.2 Cache的基本结构
Cache的基本结构可由下图描述,几个重要的机构用红框圈出:
4.1.3 Cache的读写操作
Cache的读操作流程如下:
写操作主要有两种方式:
- 写直达法(Write-throurh)
写操作时既写入Cache也写入主存,写操作时间即为访问主存的时间,Cache块退出时,不需要对主存执行写操作,因此Cache块的更新策略比较容易实现。
- 写回法(Write-back)
写操作时只把数据写入Cache而不写入主存,写操作时间即为访问Cache的时间,当Cache数据被替换出去时需要写回主存,因此增加了Cache的复杂性。
4.1.4 Cache的改进
- 增加Cache的层次级数
Cache本质上通常是SRAM,不过不同的单元电路组成的SRAM是有区别的,有的速度快、功耗高、成本高,有的速度慢、功耗低、成本低、且易于集成(具体内容可搜索LVT HVT关键字)。因此,参照整个存储系统的层次结构,Cache也可以细分出不同层次,比如L1 Cache、L2 Cache等,以此来获得性能、功耗、芯片面积、成本等方面的平衡。
- 参照哈佛架构分立缓存
采用独立的数据Cache和指令Cache。现代处理器基本上都采用了流水线结构,如果单独为数据和指令设置Cache,则在某条指令执行需要访问数据时,不会影响后面的指令的取指(一个是访问数据Cache,一个是访问指令Cache),从而提高计算机的性能。
4.2 Cache-主存的地址映射
Cache-主存的地址映射可分为三种映射方式:
- 直接映射
主存中的某个内存块只能唯一映射到一个缓存块,即只可被缓存到其所映射到的缓存块中。多个主存块会映射到同一个缓存块,这里的多个具体的说,就是主存块的数量 / 缓存块的数量,图示已经描述的很清楚了。这种结构的优点是结构简单、速度快,缺点是在Cache有很多空闲的情况下仍出现Cache冲突,影响Cache利用率。
- 全相联映射
从全相联的结构可知,这种结构相较直接映射能够提高Cache的利用率,因为一个主存块可以被缓存到任一缓存块。但缺点也正是源于此,无法根据主存地址确定地址所在主存块会被缓存到哪个缓存块,因此在检查缓存是否命中时,需要多个比较器同时比较主存地址中主存块的块号和所有缓存标记,造成电路结构复杂,功耗也更高。
- 组相连映射
直接映射中,一个主存块只可能被缓存到某个特定的缓存块;全相联映射正好相反,一个主存块可以被缓存到任一缓存块。可以说这两种方式走了两个极端,各有优缺点,而组相联映射是前两种映射方式的折中,实现了一个主存块可以被缓存到若干个缓存块(一组缓存块)中:
4.3 替换算法
当我们想要缓存一个主存块,而该主存块可以被缓存的那些个缓存块全部被占用了,那么就需要选出其中一个被占用的缓存块,将其中的内容替换为当前需要被缓存的主存块中的数据。如何选择将被替换的缓存块,由替换算法决定。
常见的替换算法有:
- 先进先出(FIFO)算法
FIFO的策略非常简单,直接替换掉最早被占用的那个缓存块。这个算法的缺点也很明显,如果最早被占用的那个缓存块经常被访问,那么FIFO就可能造成Cache颠簸,不能因为缓存块最早被占用,就得出它在不久的将来不太可能被访问这一结论。
- 最近最少使用(LRU)算法
LRU顾名思义,它会选择所有候选缓存块中最近一次访问距当前时刻最久的那个缓存块。这个替换策略的立足点在于,到现在为止很长时间都没有被访问的那个缓存块,在不久的将来也不太可能被访问。显然,LRU要比FIFO更加合理,因此效果也更好。
5 辅助存储器
辅助存储器一般不直接与CPU交换数据,有着速度慢、成本低、容量大的特点。常用的辅存有:
- 硬(磁)盘
- 软(磁)盘
- 光盘
- 闪存(U盘、固态硬盘)
各种辅存的存储介质在上文中有提及,它们具体的实现原理这里就不说了,网上可以很方便的查到。
参考文献
[1] 哈工大计算机组成原理课程