本系列文章是学习了网课《哈尔滨工业大学–计算机组成原理》之后,用以梳理思路而整理的听课笔记及相关思维拓展。本文涉及到的观点均为个人观点,如有不同意见,欢迎在评论区讨论。
CPU的结构
CPU包含运算器和控制器两部分:
运算器就是算数逻辑单元,完成算数运算和逻辑运算。
控制器负责协调并控制计算机各部件执行程序。其基本功能是:取指令、分析指令和执行指令。
1、取指令,控制器能够自动地从存储器中取出指令。
2、分析指令。其一,分析指令要干什么,从而发出相应的操作命令;其二,分析本次操作的操作数地址。
3、执行指令,根据操作命令和操作数地址,形成控制信号序列,从而控制运算器、存储器及IO设备等。
CPU需要:
1、控制程序的顺序执行
2、产生每条指令所需的控制命令(加法操作需要控制各种寄存器等)
3、各种控制命令需要按照时间来进行
4、对数据进行算数运算和逻辑运算
5、处理中断
产生以下CPU结构:
1、首先需要存放当前指令的地址 -> 寄存器
2、需要存放指令和译码 -> 寄存器和译码部件
3、翻译出来指令之后,形成控制序列 -> CU
4、可能需要算数运算和逻辑运算 -> ALU
5、异常情况 -> 中断系统
上述CPU结构可以分为四个部分:ALU、寄存器、中断系统和CU。
在计算机运算方法部分,算是介绍了算数逻辑单元部分;
CU(控制单元)将在下一章节介绍。
下面先介绍寄存器部分,分为两类:
1、用户可见寄存器,用户可以对这些寄存器进行编程。
2、控制和状态寄存器,用户不对这些寄存器进行编程,其被控制部件使用。
用户可见寄存器:
通用寄存器,可以存放操作数或者地址等。
数据寄存器,一般用于存放操作数,有的机器允许用于操作数地址的计算。
地址寄存器,存放地址,也有通用性。
条件码寄存器,算数操作产生的正、负、溢出等结果会保存在条件码寄存器中。
寄存器什么都可以保存,只是数据类型分为了很多种,需要满足不同类型数据的数据长度;部分种类寄存器可以灵活调配,有通用性。
控制和状态寄存器:
MAR:存储器地址寄存器,存放将被访问的存储单元的地址;
MDR:存储器数据寄存器,用于存放要存入寄存器的数据或者最近从存储器中读取出的数据;
PC:程序计数器,存放现行指令的地址,通常具有计数功能;
IR:指令寄存器,存放当前要执行的指令。
指令周期
指令周期的概念
CPU取出并执行一条指令所需的全部时间称为指令周期,包含取指周期、执行周期,示意图如下:
上述只是一般的指令周期,根据不同的指令操作,指令周期也会不同。
比如无条件转移指令JMP X,取指完成之后,在执行阶段不需要访问主存,在取指周期的后期直接转移地址就行,其指令周期就是取指周期。
加法指令ADD X,在执行阶段需要从存储单元中取出操作数,然后和ACC的内容相加,结果存于ACC中,在取指和执行阶段各访问一次存储器,指令周期中包含两个存取周期。
乘法操作在执行阶段完成的操作比加法指令多得多,执行周期远超加法指令。
当遇到间接寻址时,还需要间址周期以寻找操作数的地址。
例如,当CPU用中断方式实现主机与IO设备交换信息时,CPU在每条指令执行阶段结束前,发送中断查询信号,以检测是否有某个>IO设备提出中断请求。如果有,CPU需要进入中断响应阶段,这时称为中断周期。
共有取指、间址、执行和中断四个子周期。
指令周期的数据流
取指周期的数据流:
PC存放现行指令的地址,将地址送到MAR并送到地址总线;
然后控制部件CU向存储器发送命令,使MAR中的地址对应的数据送至MDR中;
再送至IR,CU控制PC加1,形成下一条指令的地址。
间址周期的数据流:
上述取指周期结束,CU便检查IR中的内容,确定是否有间址操作
如果有,MDR中的地址的右n位送到MAR,再送至地址总线,此后CU向存储器发读命令,以获取有效地址送至MDR。
中断周期的数据流
CU将保存程序断点的存储器特殊地址送至MAR,送到地址总线上,然后CU向存储器发写命令;
再将PC的内容送至MDR,最终使程序断点经数据总线存入存储器;
CU还将中断服务程序的入口地址送至PC。
指令流水
通过前面几章的讲解,访存速度会限制处理器的速度。为了提高访存速度,一方面可以提高存储芯片的性能。另一方面,从体系结构上提高速度,DMA、快速进位链,系统的并行性等。
指令流水相当于工厂的流水线,一条流水线的产品装配按照顺序进行。取指令和执行指令周而复始,取指令时,执行部件空闲,执行部件时,取指令部件空闲。
如果指令执行阶段不访问内存,则可以利用这段时间读取下一条指令,此时取下一条指令的操作和执行当前指令的操作同时进行,称之为指令的二级流水。
上述二级流水的执行情况是理想情况,可能存在执行指令2时,取指令3,但是执行指令2完成后,不再执行指令3了。可能需要执行指令5。这种情况下,需要舍弃指令3。但是该方式依然会获得一定程度上的加速。
将上述取指和执行再细分:
1、取指(FI):从存储器取出一条指令并暂时存入指令部件的缓冲区。
2、指令译码(DI):确定操作性质和操作数地址的形成方法。
3、计算操作数地址(CO):计算操作数的有效地址。
4、取操作数(FO):从存储器中取操作数。
5、执行指令(EI):执行指令所需的操作,并将结果存于目的位置。
6、写操作数(WO):将结果存入存储器。
拆分成六个过程,意味着可以创建六条流水线,同时可以对六条指令进行加工,从下图中可以看到,理想情况下,9条指令14个时间单位就可以完成,而串行执行需要54个时间单位。
影响流水线性能的因素
要想流水线有良好的性能,流水线需要有条不紊的流动起来,但是很显然通常不会这么顺利,有三个障碍:1、结构相关;2、数据相关;3、控制相关。
1、结构相关,当多条指令进入流水线后,硬件资源满足不了指令重叠执行的要求时产生的;
2、数据相关,指令在流水线中重叠执行时,后续指令需要用到钱吗指令的执行结果时产生的;
3、控制相关,当流水线遇到分支指令和其它改变PC值的指令时引起的。
为了简便起见,将流水线分成5段,由取指令(IF)、指令译码/读寄存器(ID)、执行/访存有效地址计算(EX)、存储器访问(MEM)、结果写回寄存器(WB)。
1、结构相关
不同指令争用同一功能部件产生资源冲突时产生的。
大多数机器都是将指令和数据放置在同一个寄存器中,且只有一个访问口,如果在某个时钟周期内既要完成一条指令对操作数的存储器访问,又要完成另一条指令的取指操作,就会造成访存冲突。
问题:下图在第4个时钟周期,MEM和IF产生了访存冲突。
解决方案1:在前一条流水线访存时,暂停取后一条指令的操作。
解决方案2:
设置两个独立的存储器分别存放操作数和指令,以免取指令和取操作数同时进行时互相冲突。
2、数据相关
流水线中的各条指令因重叠操作,可能改变对操作数的读写访问顺序,从而导致了数据相关冲突。
比如流水线要执行两条指令:
ADD R 1 R_1 R1, R 2 R_2 R2, R 3 R_3 R3 ;( R 2 R_2 R2)+( R 3 R_3 R3)-> R 1 R_1 R1
SUB R 4 R_4 R4, R 1 R_1 R1, R 5 R_5 R5 ;( R 1 R_1 R1)-( R 5 R_5 R5)-> R 4 R_4 R4
这里想要的情况是,先做加法,将结果存放到 R 1 R_1 R1,然后第二条指令做减法,用到 R 1 R_1 R1中的数据,有先后顺序。
但是采用流水线时,由于重叠操作,读写的先后顺序发生了变化(不采用流水,第二条指令在第一条指令之后,不存在问题)
解决方案1:将相关指令延迟到所需操作数被写回寄存器后,再进行操作,就是等一会儿。但是这样流水线还有什么意义呢,相比于非流水线也没快到那里。
解决方案2:不需要等待ADD操作完之后,将结果写回到 R 1 R_1 R1中,旁边开个小门(旁路),顺便将结果也送给其它指令中去。可以不用像解决方案1那样等待太长时间。
3、控制相关
由转移指令引起。
假设指令3是转移指令,在指令2执行完之后,执行指令3,指令3跳转到指令15,此时对指令4、5、6、7做的操作全部报废。从而造成性能损失。
流水线中的多发技术
假设一条指令分成四个阶段:取指(IF)、译码(ID)、执行(EX)和写回(WR)。
1、超标量技术
在一个时钟周期内发送多条独立指令,需要多个功能部件、译码电路、寄存器端口和总线以同时执行多个操作。
下面左边的三条指令相互独立,可以实现指令级并行;右边三个存在数据相关,不能并行执行。
2、超流水技术
将原来的时钟周期再分段,使超流水线的处理器周期比普通的短。
3、超长指令字技术
超长指令字技术是编译程序在编译时挖掘出指令之间潜在的并行性之后,把多条能并行操作的指令组合成一条具有多个操作码字段的超长指令。