本文为《BUT HOW DO IT KNOW – The Basic Principles of Computer for everyone 》笔记,文章绝大部分图片来自于这本书,用visio重新绘制,并增加不同的颜色,更便于阅读。

任何一个计算机核心都是有必不可少的部分:一个是RAM,另一个就是CPU(Central Processing Unit),如下图所示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(1)

RAM负责数据存储,CPU负责数据处理。右侧是RAM部分,我们已经介绍过了,具体见J Pan:(1)计算机是如何读懂0和1的?- RAM ,现在开始介绍CPU如何构成。


对于CPU而言,主要的任务就是干活。那怎么样才能有效的完成这个任务?——我们也可以类比一下人类社会。原始部落的干活效率是很低的,主要靠个人的体力生活,身强力壮的就能成为头领。随着生产力的发展,后来产生了组织,对整体行为进行某种 “调度”,完成这种工作的人就是组织的“神经中枢”——比如部落的酋长等,此时,酋长不一定是最强壮的那个人,更多的需要“大脑”进行工作。到现代社会,就有了“政府”的概念,整个国家的行为进行规划和管理。可以设想一下,在现代社会一个没有“政府”或者“政府”组织混乱的国家是什么样。有了这样的概念,我们就知道了,要想有效的干活(特别是大型劳动),需要两个条件:大量干活的个体以及把这些个体连接起来的“调度”。对于CPU来说,我们把具体干活的部分称之为ALU,把起调度功能的部分称之为“Control section”,即控制单元。

CPU的基本构型如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(2)

首先能看到的是总线绕了一个大圈,分别连接在RAM的数据端和地址端。有六个寄存器挂在总线上,分别是:R0, R1, R2, R3, TMP, ACC。其中R0, R1, R2, R3是CPU用于短期存储数据的寄存器,他们的输入输出都是通过总线与外界连接,这四个寄存器用处很多,称得上是万金油寄存器,通用叫法是“通用寄存器”。TMP称为临时寄存器,它的输入来自总线数据,输出到一个粉色的框框,只有“写”指令,没有“读”指令,也就是说这个寄存器会一直输出。ACC称为累加器,它接受来自问号框框的数据,输出连接到总线上,所以它的输出数据可以搬运到任何总线到达的地方。

中间有一个大框,写着“Control Section”称之为控制单元,是CPU中最复杂的部分,它控制了CPU和RAM中所有“读”和“写”(s和e)使能情况,这个后面会详细讲。

左侧还有一个带“问号”的框框是什么呢?——它的名字叫ALU(Arithmetic and Logic Unit),也就是算数与逻辑单元。我们先来研究一下它。


1、逻辑门

在介绍ALU之前,我们有必要再学复习几种新的逻辑门电路,具体如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(3)

分别为与非门、与门、或门及异或门门。前三个都比较简单,简单说一下异或门,从真值表上可以看出,它的逻辑是通入相同为0,不同为1。为什么说它呢?——因为加法器会用到它。


2、什么是加法器

说道算数与逻辑,一个首先要解决的问题就是加法问题。我们先从最简单的1位加法开始。

对于1位加法器,我们知道:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(4)

我们把上述语法用逻辑门电路来实现,非常简单,一个与门,一个异或门:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(5)

其中,a和b为1位的输入,sum为和,carry为进位,这称之为半加器,我们可以把它抽象成:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(6)

现在难度升级,假如输入也有进位,该如何处理呢?——那就在加一个半加器呗!两个半加器只要有一个有进位,那carry out就是1,因此可以用一个或门来实现。

cpu性能怎么算出来的(计算机是如何读懂0和1的)(7)

这称之为全加器,其真值表为:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(8)

具体实现为:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(9)

能看出来其中的逻辑吗?我们把全加器抽象为:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(10)

有了一位全加器,还会发愁8位全加器吗?

cpu性能怎么算出来的(计算机是如何读懂0和1的)(11)

8位全加器可以抽象为:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(12)


3、什么是移位器

前面我们解决了加法问题,那乘法问题如何解决呢?——移位器。

举个例子,加入有一个二进制数是00010000,转换成10进制是16,现在左移一位,变成00100000,转换成10进制就变成了32,这说明什么?——在二进制中,左移就是乘以2,右移就是除以2,这样就把乘法和除法解决了。

我们来看看左移具体是怎么实现的?

cpu性能怎么算出来的(计算机是如何读懂0和1的)(13)

很简单,就是两个寄存器,连线的时候左移1位即可。当R1的“e”处于on时,R2的“s”先on后off,这样R1中所有数据就会传递到R2中,不过数据左移了一位。通常情况下,shift in会和shift out连接。

和左移类似,右移就是两个寄存器连线的时候右移1位。

cpu性能怎么算出来的(计算机是如何读懂0和1的)(14)

我们可以把左移和右移抽象成如下形式:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(15)


4、什么是比较器

顾名思义,比较器的功能就是对输入的两个数据进行比较,输出两个标志位:是否相等;若不等,谁大?

相等是比较容易实现的,用异或门就可以实现:每一位输出相同,则异或门输出off,如果所有位的输出都是off,则两个输入相等。

cpu性能怎么算出来的(计算机是如何读懂0和1的)(16)

如果是8位的话,可以将输入输出端用总线表示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(17)

也就是说我们可用用异或门实现两个输入是否相同;要比较两个数谁大,事需要一点小技巧的。要从最开始为进行比较,开始位若不同,则为1的那个数大;若开始位不同,则比较下一位;如此往复,直至最后一位。

就需要的异或门的基础上,再增加4个逻辑门,比较器中每一位的实现逻辑如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(18)

每一位比较器的输入有2个:a和b;

从上一位传递过来的另外2个输入(前面位的比较结果):all bits above are equal,“a”larger。

输出是截止至当前位的比较结果:all bits equal so far,“a”larger。

下面具体分析一下:

如果非门2当前位输出为on,且从之前位传过来的标志也为on,表明截止至当前位,输入a和b是相同的,这个可以通过与门3来实现;

与门4输出为on时需要满足三个条件:1)当前位a和b不同;2)a的状态为on;3)所有之前位都是相等的。当着三个条件都满足时,表示a大;

当与门4输出为on时,或门5输出为on;并且在当前位之后的所有位置,或门5都是on。

当b大的时候,equal标志位和a larger 标志位都为off。

把8个1位比较器堆积起来,就是一个8位比较器了,如下所示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(19)

可以简单抽象成:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(20)

比较器可以和异或门共用一部分电路,同时增加两个输出标志equal和a larger。


5、什么是ALU

前面我们已经建立了4个逻辑电路:加法器、移位器(左)、移位器(右)、比较器。加上我们已经很熟悉的三个逻辑电路:与门、非门、或门,我们就可以做成一个ALU(算数与逻辑单元)了,组成如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(21)

仔细观察上图,所有的单元都有输入a,对于需要两个输入的单元,b也被连接。所有单元的输入端一直保持连接,输出端都增加了使能器E,使能器的控制端来自译码器,也就是说,同时只会有一个单元被使能。译码器有一位输出并未连接至任何使能器,当该位为on时,7个单元均未被选择,大家都不工作,仅有a larger和equal有输出,代表的比较运算。通过op操作码,可以选择不同的逻辑或算数单元。

可进一步抽象,如下所示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(22)

op操作码所对应的选择为:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(23)

其中CMP(比较器)的标志位输出一直工作。


6、什么是时钟信号

在文章最开始的时候,我们已经认识了非门,如下图所示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(24)

它的输出是0101010101…,如果我们把图画出来,会呈现出这个样子:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(25)

高低电平交互出现,周期和信号传递需要的时间相关,倘若我们信号传输电缆的长度:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(26)

就可以得到不同频率的波形:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(27)

可以将时钟信号抽象成如下样式:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(28)

假如我们将输出信号的延长,就可以得到一个 相位之后的时钟信号:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(29)

将两路信号用与门和或门处理一下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(30)

就可以的得到如下波形:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(31)

其中clk e为“读”使能信号,clk s为“写”使能信号。抽象模型如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(32)

由于CPU的任务众多,我们需要用流水线的形式分成多步来实现,比如我们可以分成7步:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(33)

我们不妨称之为stepper,这个stepper是怎么实现的呢?——抽丝剥茧,一步一步来。首先是把步与步之间区分开来:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(34)

输入是一个时钟信号,通过非门产生一个相差180°的时钟信号,如下图所示:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(35)

除两个时钟信号外,还有12个1位寄存器(只有“写”控制端),交替分成了2组,其中一组的“写”控制信号为clk,另一组为not clk。最左侧第一个寄存器的输入信号为高电平。不难分析,这个电路的功能就是逐渐的将高电平信号从最左侧传递到最右侧。

cpu性能怎么算出来的(计算机是如何读懂0和1的)(36)

显然,这不是我们想要的最终信号,我们想要只在当前step是高电平信号,其余为低电平。怎么办呢?再加一点逻辑:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(37)

这样我们就可以得到最终的stepper信号:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(38)

Stepper的抽象模型如下:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(39)

如果将step 7和reset连接起来:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(40)

就可以生成连续不断的控制信号:

cpu性能怎么算出来的(计算机是如何读懂0和1的)(41)

,