中央处理器(Central Processing Unit, CPU)

CPU的基本架构和工作原理其实百科上讲得已经相当清楚了,不过我觉得有些事情呢还是给个例子出来比较方便学习。
本文会先从内存地址,计算机的一般架构之类的基础知识出发,然后逐步为读者"拼装"出一个超级简单的8-bit CPU。。。就像下图这样(大图点开)

这就是本文的目标:拼装这样一个结构的CPU

-----------------------------------------------------------------------------------------------------------------------

选1选择器,A,B,S为输入,Z为输出,它们可取的值当然都只有0和1
怎么工作的呢?
以该图为例:
当S=1的时候,输出值Z = 输入值B
当S=0的时候,输出值Z = 输入值A
比如说A=1,B=0,S=0的时候输出是多少?S=0就是说:选择A的值输出,也就是说输出值Z=A=1
就这么简单

同样地,我们也可以有4选1选择器

只不过控制输入S变成了两位(00,01,10,11,分别对应一二三四),道理还是一样的

如果你对这个东东怎么做成的感兴趣的话。。。下面就是4选1选择器的其中一种电路 = =

哦,还有。。本文使用的逻辑门符号均是ANSI/IEEE Std 91-1984中的Distinctive shape,不是用方框符号。。。= =

你只要知道数据选择器是干啥的就好,不用惦记上边那电路。。

------------------------------------------------------------------------------------------------------------

1. 计算机架构(Computer Architecture)

CPU、内部存储器(Internal Storage Device)和输入/输出设备(Input/Output Device, I/O)是电子计算机三大核心部件。内部储存器可以是硬盘,内存,缓存等;输入设备可以是鼠标,键盘;输出设备可以有屏幕,音箱等等。。

当你打开电脑硬盘上安装的某个程序时,你的操作系统会把硬盘上的相应内容放入内存中。至于怎么放,在内存的什么地方放那可是一门大学问,光这个就够一般人喝一壶的。。相关知识可以在大学的操作系统课程里学到

比如说你放个音乐。要放音乐,先用鼠标点开一个mp3文件,于是你就使用了一个输入设备。这个输入设备会把一个中断请求(Interrupt Request)送到CPU那边,结合来自操作系统的信息后CPU就知道:哦,你用鼠标点开那个mp3文件了!于是:
1. CPU执行操作系统里关于文件关联的代码,于是你的电脑就知道要用WMP打开文件了
2. 你的操作系统开始把WMP这个程序里含有的指令和mp3文件的内容从硬盘上拉进内存里(还是CPU的工作)
3. 然后你的CPU开始一条一条地(双核的话那你就当成两条两条地好了)执行内存里的WMP程序指令(也就是如何解码mp3),并且把解码后的PCM比特流传到声卡上,再由声卡把数字信号转换成模拟信号送到音箱/耳机(输出设备)里。So now you have music!

又比如说你要编辑一个txt文件。还是先得用鼠标点开文件,又用了一次输入设备。于是:
1. CPU执行操作系统里关于文件关联的代码,于是你的电脑就知道要用notepad打开文件了
2. 你的操作系统把notepad的程序指令和文件内容拉进内存
3. 然后你的CPU又开始执行Notepad程序的指令了
4. 每当你敲一次键盘(还是输入设备!!),都会向CPU发送一个中断请求好让CPU知道你敲了某个键。比如说你敲个Y,那么CPU就会把Y这个字符写进内存里。然后你要保存的时候操作系统就会把内存里改过的东东倒进硬盘里!~

。。。好吧我承认实际过程跟这儿说的不大一样并且复杂得多,有些细节会在后面详细讲,but that's the basic idea.

这大约就是CPU,输入/输出设备和内存之间的互动方式了。

---------------------------------------------------------------------------------------------------

字节的内存!

这个数字换算一下就可以得出它相当于4GB。现在你知道为什么32位系统不支持4GB以上的内存了吗?

------------------------------------------------------------------------------------------------------

和1而已。那CPU如何从这些0和1里知道指令是什么呢?这就是指令编码的内容了。

先说说CPU。您说,CPU能干啥?其实很简单,无非就是加减乘除,读写内存,逻辑运算什么的。若是复杂些的CPU可能指令集要大些,不过基本的指令大概就这些。CPU内部也有自己的储存单元,叫做寄存器(Register),也是暂时用来放数据的地方,速度特别快,容量特别小。
就拿我经常用的NIOS II来说,它内部有32个寄存器,它可以执行的指令包括(不好意思我要用汇编语言了=_=):

add rA,rB,rC #把寄存器rB,rC里的数加起来,结果放入寄存器rC
addi rB, rA, IMM16 #把rA里的数跟一个16位的数相加,结果放入rB
beq rB,rA,LABEL #若rA=rB,则跳到LABEL指定的内存地址开始执行指令,否则继续按照内存地址顺序执行指令
stwio rB, b_o(rA) #从内存地址rA+b_o处读取一个字节,数据放入rB
ldwio rB, b_o(rA) #从内存地址rA+b_o处开始写入一个字节,写入的数据在rB里


等等

总结起来,CPU可以有以下几个功能:
1.进行寄存器之间的运算和比较
2.由寄存器内指定的地址读写内存
3.分支指令,类似于C语言里的if语句。比如跳到某个寄存器里指定的内存地址开始读取并执行指令

当然,更复杂的指令集是有可能的,不过这里就不说了

---------------------------------------------------------------------------------------------

位数字和一个操作码

31-27位代表指令里寄存器rA的编号
26-22位代表寄存器rB的编号
21-6位是一个16位的二进制数
5-0位是操作码

例子:
NIOS II汇编指令 addi r6,r7,310表示把寄存器r7里的数加上310,结果放入寄存器r6。如果我们规定addi运算对应的六位操作码是000011,那么请问整条指令的编码是?
解答:
寄存器r6的编号是6,即00110
寄存器r7的编号是7,即00111
数字310对应的二进制数是0000000100110110
addi的操作码是000011
所以整条指令的编码就是00110 00111 0000000100110110 000011
-----------------------r6-----r7--------310---------addi------
共32位!
这就是I-type指令在内存里存在的形式!!~

----------------------------------------------------------------------------

就好 = =

例子:
汇编指令 add r10,r9,r8是典型的R-type指令。它表示把寄存器r9,r8里的数加起来,然后把结果写入寄存器r10(目标寄存器)。若规定add运算的操作码为00000011111,请问整条指令的编码是?
解答:
寄存器r10的编号是10,即01010
寄存器r9的编号是9,即01001
寄存器r8的编号是8,即01000
add运算操作码是00000011111
OP = 000000
所以整条指令的二进制编码是01001 01000 01010 00000011111 000000
---------------------------r9-----r8---r10------add-------OP
共32位!

-----------------------------------------------------------------------------------------

位的数字(通常是内存地址)和一个6位的操作码

31-6位是数字
5-0位是操作码

例子:
汇编指令 call ROUTINE_3是典型的J-Type指令,它表示该指令执行完毕后CPU将从ROUTINE_3开始的内存地址读取并执行其他指令。若ROUTINE_3开头指令的内存地址是0x00002b3c,call的操作码是000000,请问整条指令的二进制编码是?
解答:
16进制数0x00002b3c = 0000 0000 0000 0000 0010 1011 0011 1101
call操作码是000000
所以整个指令的编码是00000000000000000010101100111101 000000
------------------------------ROUTINE_3--------------call--
还是32位!

变1(rising edge)的时候,CPU里面的元件就会做点什么。

数据通路(Datapath)是一个能够执行任何指令集内的指令的电路,但是它需要控制电路告诉它应该在什么时候执行什么指令。数据通路包括了寄存器组,算术逻辑单元(Arithmetic logic unit, ALU)以及很多其他的元件。

控制电路负责解码指令并且正确设置控制信号,于是数据通路就能根据这些控制信号知道应当执行哪一条指令。

----------------------------------------------------------------------------------------------------------

5. 好了,开始搭CPU吧 = =

如果读者到目前为止都还能懂的话,那么恭喜!你终于有了足够的基础知识来搭建一个简单的CPU了。
当然了,CPU这玩意不是说搭就搭的。我们的CPU能干些什么?能执行些什么指令?指令是怎么编码的?它由哪些小模块组成?都有哪些控制信号?这些问题都必须有明确的回答。

从现在开始,我强烈建议读者拿几张空白的纸出来记下这些问题的回答,因为我们即将面对的是众多的指令,模块以及控制信号。这可比拼装家具复杂多了,如果不记下来的话到时大概会头晕目眩。

当初LZ对这个CPU做一丁点儿小改动的时候,可得对着一张电路图,大大的控制信号表格以及超长的Verilog HDL代码,花了不少时间和草稿纸呢

I will be back tomorrow or after 3 hours...~

--------------------------------------------------------------------------------------------------------------

,好让CPU调出下一条指令

-------------------------------------------------------------------------------------------------

;如果某个运算结果为零,那么Z就被设定为1。我们将会在跳转指令里用到这两个比特位。

该CPU可以执行10种指令:

1. LOAD R1 (R2)
实现方法:
TMP = MEM[R2]
R1 = TMP
PC = PC + 1
这条指令是把内存地址R2处的数据读出来,然后放进寄存器R1里。接着PC寄存器加一为下一条指令做准备。看出来了吗?下面将不再有这种文字描述,全部使用简写。

2. STORE R1 (R2)
实现方法:
MEM[R2] = R1
PC = PC + 1

3. ADD R1 R2 [加法运算]
实现方法: 
TMP = R1 + R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

4. SUB R1 R2 [减法运算]
实现方法:
TMP = R1 - R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

5. NAND R1 R2 [NAND逻辑运算]
实现方法:
TMP = R1 NAND R2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

6. ORI IMM5 [OR逻辑运算]
实现方法:
TMP = R1 OR IMM5, IMM5是一个5-bit的二进制数
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

7. SHIFT L/R R1 IMM2 [移位运算]
实现方法:
IF (L) THEN TMP = R1 << IMM2
ELSE TMP = R1 >> IMM2
R1 = TMP
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;
PC = PC + 1

8. BZ IMM4 [如果Z=1,就跳过IMM4个指令]
实现方法:
IF (Z == 1) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

9. BNZ IMM4 [跟上一条指令相反]
实现方法:
IF (Z == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

10. BPZ IMM4 [若N = 0,就跳过IMM4个指令]
实现方法:
IF (N == 0) PC = PC + 1 + (SIGN-EXTEND8(IMM4))
ELSE PC = PC + 1

这些描述都比较抽象,做拼装的时候这些东西应该会表现得更具体些。

---------------------------------------------------------------------------------------------------

个指令的编码方式都是:
7-6位是寄存器R1的编号
5-4位是寄存器R2的编号
3-0位是操作码

ORI指令的编码

SHIFT指令的编码

三个跳转指令的编码

--------------------------------------------------------------------------------------------------------------------------

条线,因为是8-bit的
data out ---------- 输出寄存器的数据,8条线,因为是8-bit的
控制信号write ---------- 是否允许写入数据。是的话write = 1, 否则 write = 0
clock ---------- 时钟信号
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

数据选择器

相信诸位都应该知道这玩意怎么工作的吧?当然输入输出都是8条线
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

通用寄存器组

通用寄存器R0-R3都在这里面。
reg1,reg2 ----------说明指令里涉及哪两个寄存器
regw ---------- 指明要往哪个寄存器里写数据(应该是2条线,没画出来)
data0 ---------- 从reg1指定的寄存器中输出数据
data1 ---------- 从reg2指定的寄存器中输出数据
dataw ---------- 实际写入寄存器的数据从这里进去(应该是8条线,没画出来)
控制信号write ---------- 是否允许写入数据?是的话write = 1,否则write = 0
clock ---------- 时钟信号
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

算术逻辑单元(ALU)

这个模块就是CPU做运算的地方了。它能实现加减法,NAND和OR运算,以及移位运算。
In0,In1 ---------- 输入
控制信号ALUop ---------- 告诉ALU应该做哪个运算
Z,N ---------- 前面提过的特殊比特位,ALU要负责根据运算结果设置Z和N
OUT ---------- 运算结果输出

-----------------------------------------------------------------------------------------------------------------

继续说CPU组件。。。

指令内存

addr ---------- 指定从哪个内存地址读取指令
Out ---------- 从内存里输出的指令在这里去往CPU
控制信号Read ---------- 是否允许读取指令?是的话Read = 1, 否则 Read = 0
我们假设指令内存是只读(Read Only)的
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

数据内存

addr ---------- 指定从哪个内存地址读取数据
Din ---------- 往内存里写的数据从这里进去
Dout ---------- 从内存里读取的数据从这里出去
Clock ---------- 时钟信号
控制信号MemWrite ---------- 是否允许数据写入内存?是的话MemWrite = 1, 否则为0
控制信号MemRead ---------- 是否允许读取?是的话MemRead = 1,否则为0
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

-------------------------------------------------------------------------------------------------

能执行加法指令的电路

前面说过加法指令ADD R1 R2的编码形式如下

该指令会把寄存器R1和R2里的数字加起来,然后把结果写回R1。
INST线的3-0位是操作码,会被送到控制电路那边解码。解码后控制电路会设置好各个控制信号使得CPU的数据通路执行加法运算。我们以后再详细说说控制电路的事情,现在让我们来看看在数据通路里,INST线7-4位是如何使用的。


上图是一个可以执行加法指令的电路(图里的数字有点小错误,不要在意)
INST 7-6位代表R1的编号,作为通用寄存器组的reg1和regw输入
INST 5-4位代表R2的编号,作为reg2的输入
然后R1和R2里的数据从data0,data1输出,送到ALU做加法运算(ALUop会告诉ALU做加法运算)
TMP = R1 + R2完成
然后加法运算的结果被送到寄存器组的dataw输入。这时RFWrite = 1。由于此时regw指定的寄存器编号是R1,所以加法运算的结果就被写回了寄存器R1
R1 = TMP完成
此外,ALU还会把N和Z这两个特殊的比特位根据运算结果设置好
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;完成

这条指令还没完,我们需要把PC寄存器里的数字加一,这样CPU才能取得下一条指令。因此还得加点东西。

有了上面那个电路之后
PC = PC + 1就可以完成了

同样的电路也可以用作执行SUB和NAND指令。唯一不同的是控制信号ALUop会让ALU做减法或者NAND运算。

-----------------------------------------------------------------------------------------

执行ORI指令的电路

ORI IMM5的编码

这个指令会把寄存器R1里的数字与一个5-bit的二进制数做OR运算,然后把结果写回R1
要实现这个指令只需把上面的电路稍作更改即可


可以看到这个电路增加了两个数据选择器(图中的reg0,reg1应分别为reg1,reg2)
首先,因为ORI指令总是在寄存器R1上进行操作,不像ADD,SUB,NAND等其他指令需要指定在哪些寄存器上进行操作,所以我们加入一个控制信号为R1Sel的选择器。
当执行ORI指令时,R1Sel = 1,这样reg1的输入在执行ORI指令时总会是01
所以data0输出也总是会输出R1的数据到ALU
这时,ALU的另外一个输入应当是指令里的IMM5,而不是从寄存器组那边过来的输入
于是我们加入另一个控制信号为ALU2的选择器,这样我们就可以选择是从寄存器组还是从INST线那边输入ALU数据。
当执行ORI指令时,ALU2 = 1,这样ALU就会把INST 7-3位的5-bit二进制数作为输入
然后控制信号ALUop告诉ALU进行OR运算
TMP = R1 OR IMM5完成
结果写回R1
R1 = TMP完成
ALU根据运算结果设置N和Z
IF (TMP == 0) Z = 1; ELSE Z = 0;
IF (TMP < 0) N = 1; ELSE N = 0;完成
PC寄存器加一,CPU为下一条指令做好准备
PC = PC + 1完成

-----------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------

能执行内存读取以及SHIFT指令的电路

LOAD R1 (R2)
STORE R1 (R2)
由于这两条指令里的R2部分总是作为地址使用,所以寄存器R2的输出要连到数据内存的addr输入;而R1在STORE指令中是作为数据源的寄存器使用的,所以连接到Datain输入。R1在LOAD指令中是作为放内存读出数据的寄存器使用的,所以连回到寄存器组的dataw输入。中间加了一个RFin选择器,这样寄存器组就可以选择是从ALU还是从数据内存那边写入数据。

现在我们要把数据内存加入我们的电路里,如下图:

最后我们还把ALU2选择器扩展了一下,使得执行SHIFT指令时ALU能够选择从INST线读到运算需要的数据(图中的INST 5-2应当为INST 4-3,因为SHIFT指令的IMM2在指令编码的4-3位)。

然后这个CPU的数据通路就基本完成了!!

[No0000166]CPU的组成结构及其原理的更多相关文章

  1. 【翻译】CEDEC2013 BANDAI NAMCO 了解游戏格斗动画中的身体运动结构和原理

    CEDEC搬运工程开始~   这篇会议PPT的作者 元梅幸司曾经就职在TECMO参与开发了死或生2,3[ DEAD OR ALIVE],忍龙「NINJA GAIDEN」后来加入NAMCO(现在是BAN ...

  2. CPU的硬件结构和汇编语言

    (已更正) 这个问题包括CPU的硬件结构和汇编语言的范畴. 这里梳理一下. 首先, 题主"李建国"自问自答的部分说的是正确的, CPU的指令集是软件与CPU这两个层级之间的接口, ...

  3. Jmeter 结构、原理介绍

    Jmeter结构.原理介绍 一.Jmeter 简介 1.是基于java语言的开源的应用软件. 2.可以进行接口测试.性能测试.接口及性能的自动化测试. 二.Jmeter体系结构 元件:可以理解为每一个 ...

  4. CPU处理器架构和工作原理浅析

    CPU处理器架构和工作原理浅析 http://c.biancheng.net/view/3456.html 汇编语言是学习计算机如何工作的很好的工具,它需要我们具备计算机硬件的工作知识. 基本微机设计 ...

  5. 3D-camera结构光原理

    3D-camera结构光原理 目前主流的深度探测技术是结构光,TOF,和双目.具体的百度就有很详细的信息. 而结构光也有双目结构光和散斑结构光等,没错,Iphone X 的3D深度相机就用 散斑结构光 ...

  6. B/S结构通信系统原理

    本文介绍JavaWeb的B/S结构通信原理 概念:        Javaweb中B/S架构是一种系统架构形式,这里的B是Browser(浏览器),S是Server(服务器),是一种系统的架构形式,有 ...

  7. 聊聊高并发(三十四)Java内存模型那些事(二)理解CPU快速缓存的工作原理

    在上一篇聊聊高并发(三十三)从一致性(Consistency)的角度理解Java内存模型 我们说了Java内存模型是一个语言级别的内存模型抽象.它屏蔽了底层硬件实现内存一致性需求的差异,提供了对上层的 ...

  8. 详细了解 InnoDB 内存结构及其原理

    最近发现,文章太长的话,包含的信息量较大, 并且需要更多的时间去阅读.而大家看文章,应该都是利用的一些碎片时间.所以我得出一个结论,文章太长不太利于大家的吸收和消化.所以我之后会减少文章的长度,2-3 ...

  9. Map实现之HashMap(结构及原理)(转)

    java.util包中的集合类包含 Java 中某些最常用的类.最常用的集合类是 List 和 Map.List 的具体实现包括 ArrayList 和 Vector,它们是可变大小的列表,比较适合构 ...

随机推荐

  1. 【LeetCode】242. Valid Anagram (2 solutions)

    Valid Anagram Given two strings s and t, write a function to determine if t is an anagram of s. For ...

  2. 【概念原理】四种SQL事务隔离级别和事务ACID特性

    摘要: SQL事务隔离级别和事务的ACID特性 事务是一组读写操作,并且具有只有所有操作都成功才算成功的特性.   事务隔离级别 SQL事务隔离级别由弱到强分别是:READ_UNCOMMITTED.R ...

  3. php 实现发送微信模板消息(转)

    <?php namespace Org\Weixin; /** * Created by PhpStorm. * User: StandOpen * Date: 15-1-7 * Time: 9 ...

  4. 文件批量上传-统一附件管理器-在线预览文件(有互联网和没有两种)--SNF快速开发平台3.0

    实际上在SNF里使用附件管理是非常简单的事情,一句代码就可以搞定.但我也要在这里记录一下统一附件管理器能满足的需求. 通用的附件管理,不要重复开发,调用尽量简洁. 批量文件上传,并对每个文件大小限制, ...

  5. 如何修改mac的root密码

    mac如果密码忘了,可以同过几个命令重置root密码.前提是你有执行sudo权限的用户: jackdeMacBook-Air:~ jack$ sudo bash jackdeMacBook-Air:~ ...

  6. Socket网络编程--简单Web服务器(4)

    上一小节已经实现了对图片的传输,接下来就是判断文件是否为js,css,png等格式.我们增加一个函数用于判断格式 int WebServer::get_filetype(char *type,char ...

  7. ElasticStack系列之九 & master、data 和 client 节点

    在生产环境下,如果不修改elasticsearch节点的角色信息,在高数据量,高并发的场景下集群容易出现脑裂等问题. 默认情况下,elasticsearch 集群中每个节点都有成为主节点的资格,也都存 ...

  8. (转)Windows系统白名单以及UAC机制

    用户帐户控制 深入了解 Windows 7 用户帐户控制 Mark Russinovich   概览: 标准用户帐户 用户帐户控制 内容 UAC 技术 提升与恶意软件安全性 Windows 7 中的不 ...

  9. 配置Django

    第一步,安装Python,在这里下载,如果你安装在C:\Python27, 把C:\Python27;C:\Python27\Scripts;C:\Python27\Lib 加到你的Path 第二步: ...

  10. React Native常用组件之ScrollView

    1. 两个要点 1.1 ScrollView必须有一个确定的高度才能正常工作 它实际上所做的就是将一系列不确定高度的子组件装进一个确定高度的容器(通过滚动操作) 通常有两种做法: 第一种: 直接给该S ...