第三章:主存储器
第三章:主存储器
思维导图

数电内容在此略过
寄存器就是能够存储一定位数的二进制位的电子元件
机器字长:CPU一次能够处理的数据的位数,与CPU的寄存器位数有关

bus是读口,RA和RB是输入要读的寄存器的编号,busW是写口,配合CLK时钟信号和WE使能端,RW写入寄存器地址,往寄存器内写入信息。
主存储器存储原理
一个字节等于8位二进制,这是计算机普遍适用的规律
也就是1B = 8Bit
所以有 1024B = 1KB
1024KB = 1MB
在计算机内部是1024为进率
所以4GB = 4 * 1024 * 1024* 1024 /8B
= 2 ^ 29个存储字
平时下载速度不是波特率而是比特率。
ROM
只读,正常工作时只能读出数据,切断电源信息也不会消失,存储不经常改变的信息

掩膜只读寄存器(Mask ROM)
掩膜ROM由地址译码器和存储都阵列两部分组成,结构如下:

可以看到,先是一个3-8译码器直接连接CPU,并且四根位线与8根字字选择线相交,并且在某些交点用二极管链接,那么输入地址和数据输出就是以下关系:
| A2 | A1 | A0 | F0 | F1 | F2 | F3 |
|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 1 | 1 | 0 |
| 0 | 0 | 1 | 1 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 | 1 | 0 | 1 |
| 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 | 0 | 1 | 1 |
| 1 | 1 | 0 | 0 | 1 | 1 | 0 |
| 1 | 1 | 1 | 0 | 1 | 0 | 0 |
3根地址线,有2^3=8个地址,每个地址存 放4位二进制,总容量8*4=32bit
一次性读出来4位二进制称作一个存储字(存储单元),存储字长就是4,
存储元:存储一个位的电路
如果有10根地址线,8根位线,那就是2^10 * 8 = 1K * 8 = 1KB
存储信息只读,这就是为什么使用二极管链接。
可编程ROM
可编程只读存储器(PROM)

存储元改为使用熔丝链接,熔丝只能允许一次数据交换,之后便会自行熔断,所以只能写入一次。
可擦除可编程只读存储器(EPROM)

能够反复写入擦除读取,不过擦除需要专门工具,而且是MOS工艺,速度比较慢,而且一旦擦除整个数据都会消失
电擦除电改写只读存储器(EEPROM)

使用电来擦除
快闪只读存储器(FM)
RAM
随机存取存储器
随机:按地址访问存储单元,因为每个地址译码时间是一样的,所以每个单元的访问时间是一个常数,与地址无关。

唯一需要运算的地方就是地址译码器。
这样的译码方式叫一维译码,只适用于小容量。
二维译码(重合法,双译码法):使用两个译码器。

一个黑块就是一个存储单元,那么两个译码器就构成了64个存储单元,这样的结构称为存储阵列。
但是如果XY(也就是行地址译码器和列地址译码器)分别只输入了一位,那意味着能够直接读取一行。

静态SRAM
SRAM存储元一开始保存的是0还是1是随机的。

存储阵列示意图:

可以看到每个列地址使用了6个MOS管来构成双稳态触发器,访问速度非常快而且通电时数据就永久保持。
X地址选择5,Y选择3,那么Y=3的线连接两个MOS管导通,WE为低电平,将数据线传输的数据写到存储单元(5,3)中。
动态DRAM


可以看到每个列地址是一个MOS管加一个电容来连接。电容会漏电,数据会丢失,访问慢。
所以,读取数据的同时,会清空存储电荷的电容,导致原始数据被破坏。因此,必须在读取后立即执行一次“再生”操作,将数据重新写回。
存储器的存储周期
读出时间:指从存储器接收到读命令开始,到读取出信息所需时间
写入时间:指从存储器接收到写命令开始,至信息被写入存储器所需的时间
存储周期:进行一次操作需要的时间,也就是存\取时间+恢复时间。
DRAM刷新
DRAM的电容会缓慢放电,放电过多会导致信息丢失,破坏性读取后也会直接清空电容电量,所以必须定时给电容充电,这个过程称为刷新或者读后再生。
刷新是以行为单位进行的,是由刷新计数器和刷新控制器来进行的
刷新周期定义为:上次对整个存储器刷新结束时作为开始点,到下次对整个存储器全部刷新一遍为止的时间间隔。
和总线的仲裁类型差不多,这里有刷新也有刷新策略:
集中刷新
- 在规定的一个刷新周期内,对全部存储元集中一段时间进行逐行刷新
- 存储阵列式128*128,刷新周期是2ms,存储周期是0.5us,刷新单行的时间可以看作是存储(读取)单行的时间,那就是128 * 0.5us=64us,那么刷新周期为2ms,也就是2000us,我们就划分为前1936us来进行读写操作,后64us刷新,刷新时间为死时间,在这个时间内无法进行读写。

分散刷新
- 对每行存储单元的刷新分散到每个存储周期内完成。将存储周期分为两段,前段存取,后半段刷新。
- 存储阵列式128*128,刷新周期是2ms,存储周期是0.5us,Tm是存取,Tr是刷新操作,Tc就是读取并刷新一行的时间。这样没有死时间但是会延长存储周期一倍或者更多。到点就强制刷新,这可能会干扰CPU正在进行的操作。

异步刷新
- 前两种方式的结合,能够缩短死时间,又可以充分利用最大刷新间隔为2ms的特点。
- 存储阵列式128*128,刷新周期是2ms,存储周期是0.5us,将刷新周期平均分配到每一行上,那么刷新间隔是2ms/128行 = 15.6us,那么在存取一行后就会刷新一次。

DRAM和SRAM
SRAM是“快而贵”的缓存,DRAM是“大而便宜”的主存
| 特性维度 | SRAM(静态随机存储器) | DRAM(动态随机存储器) |
|---|---|---|
| 基本存储单元 | 6个晶体管(MOS管)构成一个****双稳态触发器 | 1个晶体管(MOS管) + 1个****电容 |
| 数据保持原理 | 只要通电,数据就****永久保持(静态) | 电容会漏电,数据****会丢失,需要定期刷新(动态) |
| 速度 | 非常快(访问周期约10ns级别) | 较慢(访问周期约50ns级别,含刷新开销) |
| 集成度/容量 | 低(一个单元要6个晶体管) | 高(一个单元只需1个晶体管1个电容) |
| 功耗 | 较高(持续通电) | 较低(待机时功耗低,但刷新会增加总功耗) |
| 成本 | 高(芯片面积大,制造复杂) | 低(芯片面积小,结构简单) |
| 主要应用 | CPU高速缓存(L1, L2, L3 Cache) | 主存储器(内存条/运行内存) |
| 核心挑战 | 面积大,成本高 | 需要刷新电路,设计更复杂 |
主存如何与CPU连接
我们将之前讲过的逻辑电路看成一块集成电路IC,称作存储芯片

单个存储芯片不可能做得很大,为我们需要扩展存储芯片的容量大小。

CPU通过主存控制器与存储芯片链接。

现代计算机中,主存控制器已被集成到CPU中,所以有些图不会画出主存控制器。
m是MDR的位数,也就是存储字长,n是MAR的位数,2^n是存储字数量。
建议配合上图理解。

主存的扩展
如果说一个主存是1K * 4Bit,说明存储字数量为1K,存储字长为4位,主存容量就是4096位,根据一个字节8位那就是512B(这里的B是字节Byte),那么也就是一共有1024个存储单元,每个存储单元能够存储4位二进制,芯片通过4根数据线换数据。
- 位扩展:增大存储字
- 我们希望有8根数据线进行是数据交换,字长就被扩张到8位

注意看,第一芯片链接D0-D3,第二芯片链接D4-D7,那就是一共有8个数据线来交换数据,这就增加了存储字长。
- 字扩展:增加存储字数量
- 我们通过加一个芯片,扩大地址数,也就是扩大存储字数量。

注意看,我们用两个芯片并联了地址信号并用一个非门将两芯片的片选信号连接起来,这就使得地址数扩大了一倍,那就是扩大了存储字数量。
- 字,位扩展
- 两个方法的结合,能够同时扩大存储字长和存储字数量。

CPU和主存链接的例题

同步主存储器SDRAM(DRAM)
MFC异步通信很大程度拖慢了CPU时间。
行缓冲器
SDRAM的行缓冲器是集成在SDRAM芯片内部的一个高速静态存储器(SRAM)缓存。它的作用是:当CPU要访问SDRAM时,并不直接去庞大的存储单元阵列中读取数据,而是先把整个一行数据(通常几千位)一次性从慢速的DRAM阵列预取到这个高速的行缓冲器中,后续的读写操作都在这个缓冲器上完成,从而极大提升访问速度。

如果地址线输入01,那就是选中了第二行,行缓存器会提取所有第二行的数据并保存,
随即传入列地址00,就能够从缓冲器中读取第一列的八位数据。基于行缓冲器SRAM的高速率,这个过程是非常快的。
突发传输

行缓冲器中有两个寄存器,一个是BL,保存突发长度,第二个是CL,CAS(列地址信号)潜伏期
DDR(Double Data Rate) SDRAM

DDR技术也在不断更新

按字节寻址
温习一下主存结构:

八根数据线,那每次能够读写一个字节。
有32个地址线,使用二进制表示地址太长了,所以我们往往使用十六进制来表示,例如0x00000004等。
所以每个地址对应一个字节,根据地址来找到地址就是根据字节寻址。
如果每个地址存储的字节数 <=1的话,那就只能使用按字节寻址。
按字寻址
如果每个地址存放的字节数多比如32位,那因为一个字节等于八个二进制位(这是计算机的普遍标准),我们就可以定义四个字节为一个字,那么每个地址对应1个字,我们就能够通过查找字来确定要查找的数据的位置,也就是按字寻址。
| 特性 | 按字节寻址 | 按字寻址 |
|---|---|---|
| 基本寻址单位 | 字节 | 字 |
| 地址对应数据量 | 1个字节 | 1个字(如32位系统下为4个字节) |
| 灵活性 | 高,可精确访问任意字节 | 低,以字为单位访问 |
| 地址空间利用 | 地址线与字节地址对应 | 地址线与字地址对应,相同地址线可管理更大物理内存 |
| 常见应用 | 现代通用计算机(如x86架构) | 某些早期或特定领域的硬件系统 |
事实上按字寻址凭借相同地址线能够管理更大内存,是对早期计算机制造瓶颈的妥协。
现在不存在技术瓶颈,使用字节寻址是现代计算机的绝对主流。
高速缓存Cache
时间局限性:被访问的某个存储单元带一个叫短时间间隔内可能又被访问,比如for循环等
空间局限性:被访问的某个存储单元的邻近单元在一个较短时间间隔内也可能被访问。比如顺序执行的指令,遍历数组等
而Cache的设计,就是****预测程序的行为会遵循局部性原理。一方面他会保存最近使用的数据等待再次访问,另一方面他会预取相邻的数据等待CPU访问。如果下一次CPU要访问的数据刚好在Cache中,那么就能利用Cache的高速访问来缩短时间,这样的情况我们称之为”命中(Hit)“。这样的机制能够使速度提升很多倍。

这个代码的作用是求和数组,函数中有for循环,这符合时间局部性,而且数组在内存中是顺序排列的,这就是符合空间局部性。

注意看,C语言中,数组是按行存储的,程序一的按行访问,正好对应了顺序访问的局部性原则,程序二却是按列访问,这意味着访问完A[0][0]之后会直接跳转到A[0][2047]这会大大降低Cache命中的概率,所以空间局部性很差。
Cache基本工作原理
Cache往往集成到CPU中,并于主存控制器,ALU等连接到一起,在CPU正式操作前,他会预取一部分的数据和指令保存,供CPU使用

总结一下

如果CPU访问主存单元所在的主存块在Cache中,则称为Cache命中(hit)。 命中的概率称为命中率(hitrate),它等于命中次数与访问总次数之比。 如果CPU访间主存单元所在的主存块不在Cache 中,则称为Cache 不命中(miss)。 不命中的概率称为缺失率(missrate),它等于不命中次数与访问总次数之比。
主存块的划分和相关地址的计算

Cache和主存块的三种映射方式是直接映射,组相联映射,全相联映射。
抱歉,这三个映射方式我没看,也许有时间会补上。