存储器之校验码(下)

前言

额,主要是校验码上篇好像布局有点问题。就拆了一个下篇。

海明码(又称汉明码)

根据上篇,我们可以得知海明码主要解决的是“规则”这个问题,主要从以下几个角度进行分析:

  • 一串数据需要几个检测位
  • 检测位加在什么地方
  • 检测位需要监督哪些位置的数据
  • 如何验证检测位和数据位的关系

一串数据需要几个检测位

设欲检测的二进制代码有n位,为使其具有纠错能力,需增加k位,组成n + k的代码。为了能准确对错误定位以及指出代码没错,k需要满足以下关系: 2k >= n + k + 1

这个不等式的意思就是:检测位的所能表示的状态需要大于等于 n + k + 1 个(这里额外加1是全正确的情况下,即000…)

检测位加在什么地方

放在 2i - 1 的位置上,比如:

  1. 第一个检测位,就放在第1的位置上
  2. 第二个检测位,就放在第2的位置上
  3. 第三个检测位,就放在第4的位置上

数据位按序依次填到检测位和检测位之间的间隔中去。

比如二进制代码:“0010”

  1. 通过2k >= n + k + 1,解出k为3。需要3个检测位
  2. 我们用“?”代替检测位:??0?010

检测位需要监督哪些位置的数据

  1. 第一个检测位,需要检测1、3、5、7、9…每检测一个跳过一个
  2. 第二个检测位,需要检测2、3、6、7、10、11…每检测两个跳过两个
  3. 第三个检测位,需要检测4、5、6、7、12、13、14、15…每检查四个跳过四个

用公式总结一下
第i个检测位,每检测完 2i - 1 ,就跳过 2i - 1,再检测下一个范围 2i - 1

这样分组能有以下这些特点:

  1. 每个小组有且仅有一位被该组所独占,该位是其他组没有的。
  2. 每两个小组(gi和 gj)共同占有一位,该位是其他组没有的。即 gi和 gj 共同占有第 2i-1 + 2j-1
  3. 每三个小组(gi、gj和gt)共同占有一位,该位同样是其他组没有的。即 gi、 gj 、gt共同占有第 2i-1 + 2j-1 + 2t-1

比如二进制代码:“1101 1010”

  1. 通过2k >= n + k + 1,解出k为4。需要4个检测位
  2. 我们用“?”代替检测位:??1? 101? 1010
  3. 检测位需要对要监督的位置进行异或(⊕)

    • 第一位检测位:需要检查1、3、5、7、9… 根据题目判断(这里的3、5、7、9表示位置) 3 ⊕ 5 ⊕ 7 ⊕ 9 ⊕ 11 = 1 ⊕ 1 ⊕ 1 ⊕ 1 ⊕ 1 = 0。所以第一位检测位是0。
    • 第二位检测位:需要检查2、3、6、7… 根据题目判断 3 ⊕ 6 ⊕ 7 ⊕ 10 ⊕ 11 = 1 ⊕ 0 ⊕ 1 ⊕ 0 ⊕ 1 = 1
    • …后面的如上所示
    • 最后得出0110 1010 1010

为什么使用异或?
答:因为异或运算符正好满足相同为0,不同为1的情况

如何验证检测位和数据位的关系

Pi表示从左到右的位数。

比如第一组,只要验证P1 ⊕ P3 ⊕ P5 ⊕ P7 ⊕ P9 ⊕ P11 = 0 即可。
如果所有的小组异或后为0,那么就代表数据没有问题

比如:
|情况| P8 | P4 | P2 | P1 |
| :-: | :-: | :-: | :-: | :-: |
| 1 | 0 | 0 | 0 | 0 |
| 2 | 0 | 1 | 1 | 0 |
| 3 | 1 | 1 | 0 | 0 |

  • 第一种情况,所有的数据全部正确
  • 第二种情况,P2和P4的数据有问题,说明P2和P4的交叉位置有错。将二进制转换成十进制,可以直接得出第6位数据有误(第6位正好是P2组和P4组负责的)。
  • 第三种情况,P4和P8的数据有问题,说明P4和P8的交叉位置有错。将二进制转换成十进制,可以直接得出第12位数据有误。

例子

按配奇原则(偶数个数的“1”,用1表示;奇数个数的“1”,用0表示)配置1100 101的海明码

  1. 通过2k >= n + k + 1,解出k为4。需要4个检测位
  2. ??1?100?101
  3. 计算校验位
    • P1 = P3 ⊕ P5 ⊕ P7 ⊕ P9 ⊕ P11… = 1
    • P2 = P3 ⊕ P6 ⊕ P7 ⊕ P10 ⊕ P11…= 1
    • P4 = P5 ⊕ P6 ⊕ P7 ⊕ P12 ⊕ P13 ⊕ P14 ⊕ P15…= 0;
    • P8 = P9 ⊕ P10 ⊕ P11 ⊕ P12 ⊕ P13… = 1;
  4. 新配置的汉明码为1110 1001 101

按配偶原则(偶数个数的“1”,用0表示;奇数个数的“1”,用1表示)配置0110 101的海明码

  1. 通过2k >= n + k + 1,解出k为4。需要4个检测位
  2. ??0?110?101
  3. P1 = 1;P2 = 0;P3 = 0;P8 = 0;
  4. 新配置的汉明码为1000 1000 101

小结

海明码通常用于一位纠错、两位检错,实际使用时需要再加一位检测码。

存储器之校验码(上)

在数据传输过程中,难免会有数据出现问题,所以需要及时发现错误和纠错。

校验码的相关术语

  • 编码的距离:一串代码A 和 另一串代码B 相比较,两串代码相同位置上的不同位的个数称为码组的距离。
  • 编码的最小距离(码距):任意两组代码之间的最小二进制位数的差异。

    1
    2
    根据纠错理论得出如下得公式:
    L - 1 = D + C

    编码最小距离(L)越大,能检测的位数(D) 和 能纠错的位数(C)就越大,且纠错能力恒小于等于检错能力。

什么是检测和纠错

  • 检测:当收到的信息按一定规则推导时,发现一个以上的错误位置,而通过已知信息无法推导孰对孰错,只能是知道有错误而已。
  • 纠错:当收到的信息按一定规则推导时,发现错误位置且能纠正错误位置。
    这两方面的内容基本都是通过 添加相关冗余位 来实现的。

以下是详解差错控制之码距、检错与纠错一文看到的例子,觉得讲的很透彻。

有很多网友和学员不明白,为什么有些编码能检查出错误,而不能纠正错误?下面来举一个生活当中简单的例子来说明这一点。若希赛公司发出一个通知:“明天14:00~16:00开会”,但在通知过程中由于行政部工作人员疏忽,变成了“明天10:00~16:00开会”。员工收到这个错误通知后由于无法判断其正确与否,就会按这个错误时间去安排与组织。

为了使接收者能判断正误,可以在通知内容中增加“下午”两个字,即改为:“明天下午14:00~16:00开会”。这时,如果仍错为:“明天下午10:00~16:00开会,则收到此通知后,根据“下午”与“10:00”信息即可判断出通知发生了错误。但仍不能纠正其错误,因为无法判断是“下午”与“10:00”哪一信息出错,即无法判断公司原来制定开会的具体时间。这时,接收者可以告诉发送方再发一次通知(员工向行政部人员询问,行政部再次确认会议时间),这就是检错重发(这也就是我们所说的能检错,但无法纠错)。

为了实现不但能判断通知准确性(检错),同时还能正确判断会议开始的具体时间(纠错),行政部可以把通知内容再增加“两个小时”四个字,即改为:“明天下午14:00~16:00开会两个小时”。这样,如果其中“14:00”错为“10:00”,不但能判断出错误,同时还能纠正错误,因为其中增加的“两个小时”这个标识可以判断出正确的时间为“14:00~16:00”。当然,这显然也增加了信息的冗余,降低了数据处理的效率。但随着带宽的不断提高,数据执行与处理的能力日益增强,可靠性与效率的均衡,这是值得的。

码距和纠错检错有什么关系?

规则1. “A”字母代表1,“B”字母代表0。

1) 当发送端发送“1” 和 “0”,接收端收到“1” 和 “1”时。接收端无法通过规则推导判断孰对孰错。
2) 现在在规则1的基础上增加规则2:每次发送的第0位都是和第1位相同的代码。

* 当发送端发送“11” 和 “00”时,接收端收到“10” 和 “00”时。接收端能通过已有规则得知第一串代码有误,但是无法得知第一串代码哪里有错(此规则下,通常会让客户端重发)。

3) 现在在规则1、规则2的基础上增加规则3:每次发送的第0位和第1位、第2位均相同。

* 当发送端发送“111” 和 “000”时,接收端收到“101” 和 “000”时。接收端能通过已有规则得知第一串代码有误,而根据 **误码少的概率大于误码多的概率的规律**,判断第一串代码应该是“111”。

上面的规则不是很严谨,但是确实说明了接收端和发送端的最小码距越大,检错和纠错能力越强。

笔者个人认为最小码距是指 编码后编码前 的最小长度差异(这句是笔者的观点)。

比如发送“1”代表A,如果按规则1和规则2编码,客户端会发送“11”。“11” 和 “1”相比多了一位,即最小长度为1,检测位数为2,纠错位数为0;如果按规则1、2、3编码,客户端会发送“111”。“111” 和 “1” 相比多了两位,检测位数为2(问题Q1),纠错位数为1(问题Q2)

  • 问题Q1
    为什么检测位数不是3,换句话说不可能是3个全错?
    答:三个同时发生的几率很低,不考虑

  • 问题Q2
    为什么纠错位数不是2?
    答:因为规则3后面是根据“少数服从多数”判断的,必然有两个数是一样的,另外一个被校正为和其他。被校正位只会有一个,所以纠错位为1

小结

处理前的数据(又称原数据) –“规则”–> 处理后的数据

处理后的数据长度 - 处理前的数据长度 = 最小码距 (这句是笔者的观点)

根据检测和纠错的例子,我们可以看出来“规则”就是如何处理 原数据,即 如何添加检测位 以及 检测位如何倒推

存储器之主存结构

概要

前面了解过,CPU速度 提升的会越来越快,存储芯片速度 提升的相比来说就会比较慢。比如CPU五年提高50%,存储芯片10年提高50%。
因为CPU需要的程序、数据都在存储器里;CPU又需要将计算结果存储在存储器里;所以如果两者的执行速度差就会越来越大,那么即使CPU速度再快也无济于事。
这种问题在业界内称为 存储墙问题

所以为了提高存储芯片的性能,我们前面介绍了以下几种方法:

  • 提高芯片性能(SRAM、DRAM等等)
  • 存储系统的层次结构(CPU-缓存-主存)

本节就是要讲另外一种提高存储器速度的方法:改变主存内部的结构

主存的结构

单体多字处理系统

单体多字系统的核心在于:扩展存储字长。
比如原来是一个 存储字长(=机器字长),现在将存储字长提高为原来的N倍。

假设现在机器字长为16位,存储字长为64位。如下图所示:

单体多字处理系统

单体多字处理系统的要点:

  1. 图中存储体那行,其实分成了四块(每一块的存储字长都是和机器字长相等的,即16位),共组成了一个64位的存储单元
  2. 当CPU要获取数据时,先将 一个存储单元内的数据(即64位) 读到 数据寄存器中,下一次要用时可以直接用

这样就能提高存储器的带宽,但是它也有自己的缺点:

  1. CPU每次写入时,由于只能写入16位的数据,所以每次都需要先写入图中的单字寄存器,然后由单字寄存器写回存储体。但是对于存储体来说,每次应该写入64位,所以在写入过程中可能会发生误伤的情况(覆盖了不必要的数据)
  2. CPU读取数据时,如果数据不是连续的,就会产生浪费。比如读到一条指令,该指令要跳转到后面的存储地址,那么此次读就会产生浪费

多体并行之高位交叉

多体并行的核心在于:让多个存储体并行操作,每个存储体有各自独立的地址寄存器(MAR)、数据寄存器(MDR)、地址译码、驱动电路、读/写电路等等。而高位交叉如下图所示

多体并行之高位交叉

高位表示体号、低位表示体内地址(可以参考字扩展),由于程序因按体内地址顺序存放(一个体存满后,再存入下一个体),故又有顺序存储之称。这种编码方式,只要合理调动,使不同的请求源访问不同的体,便可实现并行工作。

缺点:
如果CPU经常访问同一个个体,其他个体就会空闲着,就会产生“一体有难,三核围观”的现象。

多体并行之低位交叉(又称交叉存储)

多体并行就不赘述了,这里讲一下低位交叉,因为高位交叉是顺序存储的,只有当一个存储体全部用完后才会使用后面的存储体,所以多体并行就可能发生CPU一直访问一个存储体,而不访问其他存储体的问题。

而低位交叉正好解决了这个问题,让低位作为体号,高位作为体内地址,如下图所示

多体并行之低位交叉

每次先将第一排放满,再放第二排,第三排…

多体并行的总结

虽然对于每个存储操作来说,周期没有缩短,但由于CPU交叉访问各体,使四个存储体的读/写重叠在一起,最终在一个存储周期内完成,存储器向CPU提供了四个存储字。时间关系如下图所示

交叉访问的时间关系

在每一个读写周期内,会执行多次总线传输。保证T(存取周期) = n(存储体个数) * τ(总线传输周期)。注意,读写周期并没有缩短,而是让读/写过程重叠进行,最终在一个存取周期内 开始(注意图,不是完成,而是启动存储体的时间,正好在一个存取周期内。),存储器最终向CPU提供了4个字节。

用流水线表示低位交叉的多体并行系统的图如下所示:
四体低位交叉系统

很明显,读取四个字所花费的时间是 T + 3τ:在第一个存取周期内开始所有体的读/写操作。并在延迟3τ之后全部完成。

可见,对于低位交叉来说,如果连续读取n个 ,所需要花费的时间为:t = T + (n - 1) * τ

对于高位交叉(即顺序存储)来说,如果连续读取n个 ,所需要花费的时间为:t = n * T

注意这里的概念:存取周期是指连续开始两次读/写操作的间隔时间,这个指标是对于存储器来说的;总线传输周期是指完成地址分配、传指、传数、结束阶段的时间。总线传输周期总会小于存取周期,因为CPU的处理速度几乎远大于主存处理的速度。

例子:
设有四个模块组成的四体存储器结构,每个体的存储字长为32 位,存取周期为200ns。

假设数据总线宽度为32 位,总线传输周期为50ns,试求顺序存储和交叉存储的存储器带宽。

解:

  1. 对于四个低位存储体来说,连续读取4个字所花费的时间为:t = T + (n - 1) * τ = 200 + 3 * 50 = 350ns
  2. 对于四个高位存储体来说,连续读取4个字所花费的时间为:t = T * n = 200 * 4 = 800ns

  3. 交叉存储的带宽即为:32 * n / t = 32b * 4 / 350ns = 0.3657 * 10^9 bps

  4. 顺序存储的带宽即为:32 * n / t = 32b * 4 / 800ns = 0.16 * 10^9 bps

存储器(三)之随机存储器

随机存储器

随机存储器根据 存储信息的原理不同,分为静态随机存储器和动态随机存储器。

静态RAM

静态RAM基本单元电路

存储器中用于寄存 “0” 和 “1”代码的电路称为存储器的基本单元电路。如下图所示,图中T1 ~ T4是一个由MOS管组成的触发器基本电路,T5、T6受行地址选择信号控制,只要有高电压进来,该开关就会被打开(连通,否则就阻断)。T7和T8是列选择器,列选择器是共有的,不包含在基本单元电路内,而是芯片同一列的各个基本单元电路所共有的。

假设触发器内已经保存有 “1”这个信息,即A点为高电平。当需读出时,只要使行、列地址选择信号均有效,使T5、T6、T7、T8均导通,A点高电平通过T6,再由位线A通过T8作为读出放大器的输入信号,在读选择有效时,将1信号输出。

由于静态RAM是用触发器工作原理存储信息,因此即使信息读出后,它仍保持其原状态,不需要再生。但电源掉电时,原存信息丢失,故属于易失性半导体存储器。

静态RAM存储结构

当要写入“1”时,数据从DIN进入写电路,通过写左边的写放大器,向T7输入低电压;经过右边的写放大器,向T8输入高电压。选中的那行及那列就会导通(即T1~T6被导通),A点就是高电压,A’点就是低电压。这样就把欲写入的信息写到了该基本单元电路中。

静态RAM举例

2144芯片由6个MOS管组成,如图所示A9 ~ A0 为地址输入端;I/O1 ~ I/O4为数据输入/输出端;CS- 为片选信号(低电平有效);WE-为写允许信号(低电平为写,高电平为读);Vcc为电源端;GND为接地端。

2144芯片外特性

下图为2144芯片结构的说明图,A3~A8作为行地址选择先,共有2^6条。而因为I/O线有4条,所以每次读/写都应该产生四个数据,所以列选择器也会有四个。

2144芯片结构

举个例子,如果现在要向某个单元格进行写入,先通过行地址线和列地址线选择出具体的单元格。如下图所示

地址单元选择示意图

找到对应的地址单元后,如果做读操作,先使CS-为低电平(被选中),然后WE-为高电平(执行写操作),然后在四个I/O口输出数据。如果做写操作,先将数据送到四个I/O口处,并使CS-为低电平、WE-为高电平,这样输入数据就会被写入到指定单元格内。

静态RAM读时序

  1. WE-的低电平信号长期有效
  2. 在tA - tCO的时间内,必须发出片选信号
  3. 在tCO的时间内,经过tcx时间(注意tcx不能超过tCO),必须发出数据,并在t片选信号失效前保证数据稳定
  4. 在片选信号失效后,tOTD - tOHA这段时间里,数据仍有效。
  5. 在地址、片选信号均失效后,在OHA时间里数据仍有效

注意,第四项、第五项都表明了,即使当片选信号、地址失效后,数据也不是立马就消失的

读时序

静态RAM写时序

注意:

  1. 这里的滞后时间,是因为上一个操作结束后留下来的。为了避免无效数据的写入,所以需要等待一段时间。
  2. tWR > tDH是为了有充足的时间进行写入

写时序

总结

在静态RAM的每个读写周期内,地址都是有效的。

动态RAM

三管MOS动态RAM

读过程

  1. 对T4进行预充电,T4被打开,使读数据线的电压达到VDD
  2. 读选择线打开T2
  3. 如果电容Cg里有电容(即存储的数据为“1”时),T1被打开
  4. 因为T2 和 T1 被接通,导地,读数据线变为低电平,输出0

3管MOS读过程

写过程

  1. 写选择线打开T3
  2. 写数据经过写数据线,Cg就能保存一个电平

3管MOS写过程

单管MOS动态RAM

读过程

  1. 字线传来高电平,使T导通
  2. 如果Cs内包含数据,则向数据线输出

写过程

  1. 字线传来低电平,使T导通
  2. 若数据线内为高电平,经T管对Cs进行充电

三管MOS动态RAM举例

这是1K x 1位的存储芯片,每一个小方块都代表一个三管MOS基本电路。
由于三管MOS读选择线和写选择先不是通过一条线的一个高低电平就能决定的(需要两条线各控制读/写)。
所以行地址译码器比5条多一条,每一行都会占用读、写两条选择线。

三管MOS动态RAM

读出时预充电信号,只有在行、列选择器共同作用下的基本单元电路才能将信息从D输出。

写入时,受行地址译码器选中一行,受列地址译码器选中一列,从D获取信息写入到,行、列选择器共同作用的基本电路单元格中。

单管动态RAM举例

单管动态RAM4116芯片

该存储器自带了一个小的控制器(顶部的长方形):

  • RAS-表示行选通信号
  • CAS-表示列选通信号
  • WE-表示写/读信号

它们对应的输出行时钟、列时钟、写时钟。

本来4116芯片是16K x 1位的(即2^7 x 2^7),但由于4116的外特性,它只能拥有7个管脚。所以写入行地址时,需要传7位,暂存到行地址缓冲器中;写入列地址时,传七位到列地址缓冲器中。

比如说行地址输入:0111111(6个1,即64),列地址输入0000000(7个0,即0):

  1. 确定行地址63,打开63行的MOS管;确定列地址0,打开0列的MOS管
  2. 假设电容Cs里存有数据“1”,那么在读放大器左边就是“1”;反之则是“0”
  3. “1”即高电压,经过读放大器后,会往右输出“0”即低电压。
  4. 由于一路的MOS管都已经打开,就理所当然的进入I/O缓冲器内
  5. 最后输出

4116读信号

比如说行地址输入:0000000(7个0,即0),列地址输入0000000(7个0,即0)。其写流程如下所示:

  1. 确定行地址0,打开第0行的MOS管;确定列地址0,打开0列的MOS管。
  2. 输入的信息只能通过已打开的电路
  3. 经过读放大器后进入相反的一侧,例如存入数据“1”,则从右往左经过读放大器的时候会变成“0”,信息就写入到电容里了。

4116写信号

注意,由于经过读放大器都会进入相反的状态,所以存“1”(实际存“0”),取出来时(实际取“0”),经过读放大器成为取“1”。

动态RAM刷新

刷新的实质是刷新放大器将原信息读出,再由刷新放大器形成原信息再写入的过程。
上面的4116芯片里的读放大器、三管MOS动态RAM里的刷新放大器都是起到刷新的作用。

由于存储单元被访问是随机的,无法确定哪些存储单元会被访问,所以需要隔一段时间就对全部的基本单元电路进行刷新,一般取2ms。这个时间称刷新周期,又称再生周期。

刷新是 一行行进行的,由专用的刷新电路来完成对基本单元电路的逐行刷新,才能保证动态RAM内的信息不丢失。

1) 集中刷新
集中刷新是指 每行数据的刷新时间集中在一段时间内刷新。如图所示,假设对于128 x 128的矩阵来说,读/写周期为0.5us,刷新时间需要2us。2ms(刷新周期内)内会占4000个存取周期,而在这4000个周期里,3872个周期用来读/写;128个周期用来刷新。

这128个周期(占64us)被称为“死时间”,又称“死区”,所占比率为 128 / 4000 * 100% = 3.2%。在死时间内,CPU无法访问存储器。

集中刷新

2) 分散刷新
分散刷新是指 每行存储单元在存储时都进行一次刷新。如图所示,假设对于128 x 128的矩阵来说,读/写一次所花费的时间为(0.5us + 0.5us),128us就刷新一次完所有行。而要求只需要在2000us内刷新,所以在电容失效之前的这段时间里总共刷新15.625次,极其浪费资源。

分散刷新

3) 异步刷新
异步刷新是指 前两种方式的结合,在一段时间内进行刷新。该方法相比集中式刷新,解决了死区范围过大的问题;相比分散刷新,将每行刷新的时间控制在最大限度内。
如图所示
每一次完整的刷新需要在2ms内,总共128行,所以每隔(2000 / 128) us 要刷新一行

异步刷新

如果动态RAM的刷新安排在CPU对指令的译码阶段,由于这个阶段CPU不访问存储器,所以不会出现集中刷新里面的“大量死区”的问题。

总结

条目 动态RAM 静态RAM
速度 慢(体现在电容上)
价格 便宜
集成度
功耗

存储器之主存与CPU的联系

主存储器

主存的基本构成

主存储器需要根据MAR中的地址访问某个存储单元,还需要经过地址译码、驱动等电路,才能找到所需要访问的单元。

当主存储器写入时,会从MDR中取出数据经过写入电路,才会被写入到选中的单元中。

当主存储器被读时,会从 被选中单元中取出数据,经过读取放大器,最后送入到MDR。

主存和CPU的联系

现代主存通常将 译码器驱动器读/写电路做在主存储器中;将 MDRMAR 集成在CPU中。两者通过总线相连接。

当CPU要读取数据时:

  1. CPU会将待读取地址发送到MAR,地址经MAR发送到主存
  2. CPU发出读命令。
  3. 主存接到命令后,读取指定地址单元上的内容
  4. 将单元的内容读至数据总线上

当CPU要写入数据时:

  1. CPU会将待写地址发送到MAR,地址经MAR发送到主存
  2. CPU将要写入的数据发送到MDR,数据经MDR发送到主存
  3. CPU发出写入命令
  4. 主存街道命令,将数据线上的信息写入到对应地址单元。

主存中存储单元地址分配

不同的机器,存储字长不同,通常存储字长是8的倍数。CPU可按字地址查找,也可以通过字节查找。如果存储字长为8位,机器字长32位(每一个字有32位),每个字都包含4个可独立寻址的字节,字地址是用该字的高位字节来表示的。

不同机器的字地址和字节地址

如图a所示,对24位地址线的主存而言,按字节寻址的范围是 2^24 bit,按字寻址的范围是 2^22 bit(先算出按字节算的个数,然后再除以一个字占用的字节)。
如图b所示,对24位地址线的主存而言,按字节寻址的范围是,2^24 bit,按字寻址的范围是 2^23 bit。

主存的技术指标

存储容量

存储容量是指 主存能存放二进制代码的总位数,即

1
2
3
    存储容量 = 存储单元个数 X 存储字长         

存储容量 = 存储单元个数 X 存储字长 / 8

存储速度

存储速度是由存取时间和存取周期来表示的。
存取时间又称为 存储器的访问时间(Memory Access Time) , 是指启动一次存储器操作(读或写)到完成该操作所需的全部时间。

存取时间分为 读出时间写入时间

  • 读出时间:存储器接收到有戏地址开始,到产生有效输出所需的全部时间。
  • 写入时间:存储器接受到有效地址开始,到数据写入被选中单元为止所需的全部时间。

存取周期是指存储器进行连续 开始 两次独立的存储操作所需的最小间隔时间(开始读取操作到下一次开始读取操作这段时间称为存取周期)。

译码驱动方式

线选法

一根字选择先,直接选中一个存储单元(比如一个字节)。这种方式适用于容量不大的存储芯片,因为容量大了之后所需要的字线根数就会很大。如图所示

重合法

对于1K X 1位存储芯片,采用重合法就只需要32 + 32根选择线,重合法就和x、y轴确定一个点一样,所以当地址线输入全为0时,x0和y0就有效了,矩阵中第0行、第0列共同选中的那行就被选中了。所以当x、y线都被选中时才能决定地址,所以称为重合法。
重合法

存储器之概述

按作用分的存储结构

  • 主存:可以和CPU直接交换信息
  • 辅存:是主存的后援存储器,用来存放当前暂时不用的程序和数据。它不能和CPU直接交换信息。
  • 缓存:用在两个速度不同的部件之中
  • 闪速存储器:类似于辅存,用于保存数据的媒介

观察者模式

例子及分析

观察者就好比一个可以检测身体信息的手环,该手环每各一段时间会更新一下你的数据,并通过震动(或语音播报)提示你查看数据。

在上面这个例子中,手环就是起到观测者(Observer)的作用,身体是被观测者(Observed),我们将 观测者 注册到(戴到) 被观测者 上, 被观测者的数据发生了变化后主动去告诉 观测者

类图

类图

IObserver是观察者的接口,IObserverd是被观察者的接口。
Observed实现IObserved接口,ConcreteObserver实现IObserver接口。

代码

1
2
3
4
5
6
7
8
9
10
// 观察者接口
public interface IObserver{
// 这里需要传个参数,否则不知道更新了啥
void update(float newVal);
}
// 被观察者接口
public interface IObserved{
void addObserver(IObserver observer);
void removeObserver(IObserver observer);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// 被观察者实现,这里拿上面的例子举例
public class Body implements IObserved, Runnable{
private float heartRate;
private List<IObserver> observers;
@Override
public void run(){
while(true){
// 不断更新数据
// ......

try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}

/**
* 添加观察者
* @param observer 观察者实例
*/
@Override
public void addObserver(IObserver observer){
this.observers.add(observer);
}

/**
* 移除观察者
* @param observer 观察者实例
*/
@Override
public void removeObserver(IObserver observer){
this.observers.remove(observer);
}

/**
* 通知观察者
*/
@Override
public void notifyObserver(){
// 防止在通知过程中,心率数值发生改变
float heartRate = this.heartRate;
for(IObserver observer: observers){
observer.update(heartRate);
}
}
}
1
2
3
4
5
6
7
8
9
10
// 观察者具体实现
public class Band implements IObserver{
/*
* 当心率数据发生变化时,通知该观察者
*/
@Override
public void update(float newVal){
System.out.println("语音播报:心率发生变化 -----> " + newVal);
}
}
1
2
3
4
5
6
7
8
9
10
public class RealWorld{
public static void main(String[] args){
// 实例化一个人
Body body = new Body();
// 实例化一个智能手环
Band band = new Band();
// 把手环戴手腕上
body.addObserver(band);
}
}

结论

观察者模式在软件架构中,通常是用在数据监听方面,当数据改变后实时进行通知,这里的数据定义比较广泛,有时候是状态——比如Tomcat的Lifecycle组件:当一个容器进入某个状态,会通知所有的组件“我已经进入XXX状态,你们要做什么快做!”;有时候也真的是数据——比如Android上的LoadingProgress,每处理完一部分通知它重新绘制一下。

总的来说,观察者模式的核心在于回调。

系统总线(二)

总线控制

集中控制优先仲裁方式

  • 链式查询
    链式查询

BR是接口向总线控制部件发起占用请求

BG到达的接口有总线请求,BG信号就不再往下传了,意味着该接口获得了总线使用权。

BS是接口获得了总线使用权后,和总线控制部件建立的总线繁忙信号,表示它占用了总线。

该种查询方式中,离总线控制部件最近的设备具有最高的优先级。

这种方式的特点是:只需要很少几根线就能按一定优先次序实现总线控制,并且很容易扩充设备,但对电路故障很敏感,且优先级别低的设备可能很难获取请求。

  • 计数器定时查询
    计数器定时查询

该种查询方式相比前面的查询多了一条设备地址线,少了一根BG线,总线控制部件接收到BR送来的总线请求信号后,在总线未被使用(BS=0)的情况下,总线控制部件中的计数器开始计数,并通过设备地址线,向各设备发出一组地址信号。当某个 请求占用总线 的设备地址与计数器一致时,该设备就获得总线使用权。

计数可以从“0”开始,也可以从上一次计数的终止点开始,当然也可以由程序设置。这种方式对电路故障不如 链式查询 敏感,但增加了设备地址数,控制也较复杂。

  • 独立请求方式
    独立请求方式

该种查询方式内,每台设备均有一对总线请求先BRi和总线同意线BGi。当设备要求使用总线时,便发出该设备的请求信号。总线控制部件中有一排队电路,可根据优先次序确定响应哪一台设备的请求。该方式响应速度快,优先次序控制灵活,但控制线数量多。

总结

链式查询中仅用两根线确定总线使用权属于哪个设备;在计数器查询中大致用log2n根线,其中n是允许接纳的最大设备数,而独立请求方式需要采用2n根线。如果问几根控制线,还要再加上2。

总线通信控制

众多部件共享总线,在争夺总线使用权时,应按各部件的优先等级来解决。而在通讯时间上,则应按分时方式来处理,即哪一个部件获得使用权,此刻就由他传送,等到该部件释放总先后,下个部件继续获得总线。这样一个个轮流交替。
总线周期通常分为四个阶段;

  • 申请分配阶段:由需要使用设备的主模块提出申请,经过仲裁后授予某一部件权限
  • 寻址阶段:取得了使用权的主模块通过总线发出本次要访问的从模块的地址
  • 传输阶段:数据由源模块发出,经数据总线流入目的模块
  • 结束阶段:主模块的有关信息均从系统总线上撤除,让出总线使用权

同步通信

通信双方由统一时标控制数据传输 称为 同步通信。时钟通常由CPU的总线控制部件发出,送到总线上的所有部件;也可以由每个部件各自的时序发生器发出,但必须由总线控制部件发出的时钟信号对它们进行同步。

同步通信

这里的读指令总共分为4个阶段(假设申请总线成功):

  1. 寻址阶段,取得了使用权的主模块通过总线发出要读取的设备地址,从T1上沿持续到T4结束
  2. 传输阶段,主模块向从模块发送读取命令,从T2上沿持续到T3结束
  3. 传输阶段2,从模块准备数据,持续一个T3
  4. 结束阶段,主模块撤销读取命令,从模块撤销数据

而对于写指令,也分为4个阶段:

  1. 寻址阶段,取得了使用权的主模块通过总线发出要读取的设备地址,从T1上沿持续到T4结束
  2. 传输阶段,主模块提供数据
  3. 传输阶段2,主模块发出写命令,从模块收到命令后,得在指定时间内将数据写到从模块里。
  4. 结束阶段,主模块撤销写入命令、撤销数据

优点:

  • 简单、好配合

缺点:

  • 需要强制主、从模块的时间“同步”,必须在规定时间内完成要求
  • 需要对所有从模块都用同一限时,所以必须得考虑最慢得设备

异步通信

异步通信相比同步通信,对时间要求没有这么严格,允许各个部件得速度不一致。异步通信采用应答得方式实现,主模块发出请求信号时,一直等待从模块反馈“响应”信号后才开始通信。不过这就要求主、从模块间增加两条应答线。

异步通信分为不互锁、半互锁、全互锁三种。

不互锁

主模块发出请求后,不必等待从模块得响应信号,而是经过一段时间后撤销请求信号;从模块接收到请求信号后,在条件允许得情况下发出回答信号,一段时间后撤销回答信号。这个过程双方并无互锁关系。

半互锁

主模块发出请求信号,必须待接到从模块得回答信号后再撤销其请求信号,有互锁关系。而从模块在发送完回答信号后不必等待主模块撤销请求信号,而是隔一段时间自动撤销回答信号

全互锁

主模块发出请求信号,从模块需要发出回答信号,等主模块撤销了请求信号后,从模块才能撤销回答信号。

// 这里有几个例子

半同步通信

为了让同步通信也能像异步通信这样允许不同速度得模块和谐工作,为此增设了一条“WAIT”响应信号线,采用插入时钟(等待)周期得措施来协调通信双方得配合问题。

系统总线(二)

总线标准

前面在总线结构里介绍的系统总线、存储总线都是抽象的,没有具体说明采用什么技术来实现。本小节就是为了说明总线的具体实现标准。

ISA总线

优点:

  • ISA总线是使用独立于CPU的总线时钟,因此CPU可以使用高于总线频率的时钟。有利于CPU性能的提高
    缺点:
  • 没有总线仲裁的硬件逻辑,因此它不能支持多台主设备(不支持多台具有申请总线控制权的设备)系统
  • ISA上的所有数据都需要经过CPU或DMA接口来管理,因此CPU需要花费大量时间来控制与外部设备交换数据。
  • ISA时钟频率为8MHZ,最大传输率为16MBps,数据线为16位,地址线为24位。

EISA总线

优点:

  • ISA的优点
  • 能支持多个总线主控器和突发方式的传输

VESA总线

总线结构

单总线结构

总线连接之单总线结构

将CPU、主存、I/O设备都挂在一组总线上,这种结构 简单易于扩充,它 不允许两个以上得部件在同一时刻向总线传输信息。这类总线多数被小型计算机或微型计算机采用。而且当I/O设备数量足够多得时候,总线发出得控制信号从一端顺序的传到第n个设备,其 传播延时会严重地影响系统的工作效率

当数据传输需求量和传输速度要求不太高的情况下,为克服总线瓶颈问题,尽可能增加总线宽度和提高传输速率来解决;

当数据传输需求量和传输速度要求较高时,单总线结构不能满足系统工作的需要,因此不得不采用多总线结构。

多总线结构

双总线结构

双总线结构的特点 是将速度较低的I/O设备从单总线上分离出来,形成主存总线与I/O总线分开的结构。低俗I/O由通道这个特殊的处理器进行管理。将速率不同的组件进行分类,然后将它们连接在不同的通道上,那么计算机系统的工作效率就会得到提升。

通道

该部件主要时为了 使一些原来由CPU处理的I/O人物转由通道来承担,从而把CPU从繁杂的I/O任务解脱出来,仅当通道完成了规定的I/O任务后,才向CPU发中断信号。实际上,I/O通道是一种特殊的处理机,它具有 执行I/O指令的能力,并通过执行 通道(I/O)程序来控制I/O操作

I/O通道的特点有以下两个方面:

  • 指令类型单一,只能处理I/O方面的内容
  • 通道没有自己的内存,只能和CPU共享主存

三总线结构

三总线结构

该结构多了主存总线和DMA总线,在三种总线里,任意时刻只能使用一种总线:使用DMA总线时,无法使用主存总线;I/O总线只有在CPU执行I/O指令时才能用得到。

三总线结构变种

三总线结构变种

CPU和Cache之间有一个局部总线,我们可以挂载多个I/O设备在局部总线上。Cache直接连接到系统总线上,这样Cache就可以和主存互相交换数据,而且I/O设备和主存间的交换也不需要经过CPU。还有一条扩展总线,他将局域网、SCSI、Modem等等都串联在一起,扩展总线通过扩展总线接口与系统总线相连,由此便可实现两者的数据传输。

四总线结构

四总线结构
该结构相比三总线结构多了一层高速总线,在高速总线上会挂接一些高速的I/O设备。它们通过Cache控制机构中的高速总线或高速缓冲 和 局部总线相连,使得这些高速设备与CPU更密切。而一些低速设备仍然挂载在扩展总线上。这种结构的优点就是高速设备不需要过多依赖CPU的功能,同时高速设备相比扩展总线上的设备更接近CPU,各自的效率会更高。

总线控制

集中控制优先仲裁方式

  • 链式查询
    链式查询

BR是接口向总线控制部件发起占用请求

BG到达的接口有总线请求,BG信号就不再往下传了,意味着该接口获得了总线使用权。

BS是接口获得了总线使用权后,和总线控制部件建立的总线繁忙信号,表示它占用了总线。

该种查询方式中,离总线控制部件最近的设备具有最高的优先级。

这种方式的特点是:只需要很少几根线就能按一定优先次序实现总线控制,并且很容易扩充设备,但对电路故障很敏感,且优先级别低的设备可能很难获取请求。

  • 计数器定时查询
    计数器定时查询

该种查询方式相比前面的查询多了一条设备地址线,少了一根BG线,总线控制部件接收到BR送来的总线请求信号后,在总线未被使用(BS=0)的情况下,总线控制部件中的计数器开始计数,并通过设备地址线,向各设备发出一组地址信号。当某个 请求占用总线 的设备地址与计数器一致时,该设备就获得总线使用权。

计数可以从“0”开始,也可以从上一次计数的终止点开始,当然也可以由程序设置。这种方式对电路故障不如 链式查询 敏感,但增加了设备地址数,控制也较复杂。

  • 独立请求方式
    独立请求方式

该种查询方式内,每台设备均有一对总线请求先BRi和总线同意线BGi。当设备要求使用总线时,便发出该设备的请求信号。总线控制部件中有一排队电路,可根据优先次序确定响应哪一台设备的请求。该方式响应速度快,优先次序控制灵活,但控制线数量多。