第三章 CPU的设计.docx
《第三章 CPU的设计.docx》由会员分享,可在线阅读,更多相关《第三章 CPU的设计.docx(33页珍藏版)》请在冰豆网上搜索。
第三章CPU的设计
第三章CPU的设计
3.1引言
如果说前面指令集的设计是计算机处理器设计的蓝图,那么如何实现将直接影响到指令集的性能,而处理器实现中的一些问题也会或多或少地影响到指令集的设计。
RISC思想的提出,就是针对CISC指令集处理器实现中的困难,从简化指令集出发,降低处理器实现的复杂度,达到降低处理器的开发成本,提高处理器并行度的目的。
处理器实现直接影响到两个重要的性能指标:
每条指令实现时钟数(clockperinstruction,CPI)和时钟频率。
正象一个木桶能装水的多少取决于它最短一块木头的长度,处理器中各部件最慢的一个决定了处理器的时钟频率,所以处理器的设计必须使每个部件都能以相近的速率协调运行。
通常,我们把处理器又分为两部分:
一部分执行算术逻辑运算,以完成"计算机"的计算功能,通常称为数据通道,另一部分则解释计算机机器指令代码,并按这些代码发出控制信号控制数据通道的工作以完成指令,称为控制器。
前者由ALU(算术逻辑运算模块,Arithmeticlogicunit)和一些寄存器构成,为处理器工作时数据实际流过的路径,故称为数据通道;后一部分则是处理器中的主控部分,是将指令转换为实际硬件动作的桥梁,故而设计上最复杂,也最容易体现一种处理器的特色。
一般处理器的设计主要就是指控制器设计。
3.2数据通道(datapath)
数据通道是处理器中处理数据的部件,数据从主存取出,经数据通道的处理,得到所需要的结果后,再送回主存存放。
整个数据通道的执行受控制器的控制,实际上也就是受指令的控制。
图3.1典型的数据通道组成示意图
图3.1是一个典型的数据通道组成示意图,在图中也表示出了控制器、主存与数据通道的密切关系,数据通道本身由一个算术逻辑部件(ArithmeticLogicUnits,ALU)和一些寄存器组成,并包括两者间的通信渠道。
在冯·纽曼体系中,程序数据的地位是等同的,一起存储在主存中,为了得到适由数据通道执行的指令,首先必须在主存中寻找到指令。
这项工作由一个叫程序计数器(ProgramCounter,PC)的部件来完成。
PC是一个专用的寄存器,存放当前所执行指令的地址,供控制器读取指令时使用。
同时,这个寄存器必须随时改变存放的内容,以便使程序能按序执行下去。
比如,在正常情况下,每条指令执行前都必须将PC中的值增加一个指令长度,取顺序执行的下一条指令,这项工作则由ALU完成。
ALU不仅是一个可以完成PC递增功能的部件,还是一个通用的计算功能模块。
它能独立完成所有的基本运算如加,减,与,或,异或和移位等,另外还可以在控制器的控制下完成一些更复杂的运算如乘除等,同时也能够对数据不加处理而直接传送。
由于冯纽曼体系计算机的基本功能就是数值计算,因此ALU具有十分重要的地位。
与寄存器部件不同,它是一种非记忆的逻辑部件,其输出完全依赖于当前输入;而寄存器部件则具有内部状态,其输出由当前输入和内部状态共同决定,建去的输入会影响内部状态,从而使寄存器具有记忆。
MAR和MDR是为了访问内存而设的。
MAR即MemoryAddressRegister,存放访问内存的地址,MDR则是memorydataregister,存放从内存取回的数据,它们的作用在后面还要讲到。
此外,Temp是一个数据访问中起着暂存作用的寄存器,IAR专为中断使用。
上述这些寄存器为专用寄存器,它们的特点是一般对用户是透明的,用户或者不能直接控制它们的内容(如PC和IAR),或者完全是处理器内部实现的细节,用户根本不知道它们的存在(如MAR,MDR,Temp等)。
这些寄存器为了完成处理器的某些特定功能而设,而不能自由地用于数据计算,这也是专用寄存器这个名称的来由。
与专用寄存器相对应的是通用寄存器,顾名思义,它们就是能被用户自动地用于数据计算中的寄存器。
在许多计算机中,以R1,R2...Rn来命名它们,它们的使用没有差别。
多个通用寄存器合起来组成一个寄存器堆(registerfile),它们也是存贮器层次结构中的最高层,属于最小也是最快的数据暂存部件。
因此,如何最大限度地在计算中利用通用寄存器是提高编译器性能的关键。
内部总线将各寄存器与ALU连接起来,在我们的例子中,这样的总线共有三条:
两条源总线S1,S2和一条目的总线Dest。
S1,S2传递ALU的源操作数级ALU,Dest则将ALU运算的结果送回各寄存器,这时,ALU若执行直接传输功能(PASS1,将S1上的数据传到Dest或PASS2,将S2上的数据传到Dest),就可以作为源和目的总线间的传输通道,完成数据在寄存器间的数据传递。
通用寄存器、一部分专用寄存器(如PC和IAR)和标志寄存器flag加在一起,就构成了程序状态(state)的主要部分,如果我们能保存这些寄存器的内容也就是说程序状态,那么以后我们只要将这些寄存器的值如数恢复成原先的,并重新开始运行,只要程序的输入不变,就能得到原先的运行结果,这一点对地多进程思想的出现具有重要影响。
当然实际程序状态除了包括寄存器外,还应包括内存中一些单元的值。
数据通道的实现影响着处理器主频大小。
数据计算到整个通道所以通道中最慢的部件就限制了整个处理器的主频。
又因为它是处理器中实际进行数据处理的部分,因此许多处理器优化技术如流水线(pipeline)、指令级并行(instructorlevelparallel,ILP)都是围绕着它展开的。
3.3指令执行原理
在讨论控制器的工作原理之前,我们先介绍一下数据通道应怎样工作,才能完成指令。
一般说来,一条指令的执行分为五步:
1.取指令(instructionfetch)。
在这一步中,由PC指示地址上的指令被取到指令寄存器IR中。
表示成
MAR<-PC;IR<-M[MAR]
PC的值首先传给MAR是因为在我们的例子中,PC不直接与主存相连
2.解码/寄存器读出。
(instructiondecode/registerfetch)。
在这一步中,控制器对读入指令进行解码,要操作的寄存器操作数从寄存器堆中放入A,B,为交ALU计算作计算作最后准备。
设置寄存器A,B,C和设置MAR,MDR的理由是类似的。
ALU和主存都属于无时钟部件,其输出值单纯由当前输入决定,而不象寄存器一样,按时钟(clock)而动作,输出值由有时钟触发时的输入决定,并一直保持到下一个时钟。
所以,为了保持计算和读存结果电信号的相对稳定,就必须在它们的输入设置寄存器。
A,B能保证ALU的计算结果稳定到被C保存为止,MAR,MDR则能使储存信号稳定到主存能稳定地读出或写入信息。
还要让PC进行自增以便使它指向下一条指令。
为了简便起见,设所有指令长度为4,于是我们有如下表示式:
A<-Rs1,B<-Rs2;PC<-PC+4
Rs1,Rs2为两个源操作寄存器
指令解码能与寄存器读出并行操作是有条件的,在我们的指令集中,假设了寄存器操作数始终处在指令的同一位置,这样,在指令解码的同时,控制器就能"知道"该将哪个寄存器的内容放入A,B。
3.执行/有效地址计算(Execution/effectiveaddress)
这一步的主角是ALU,根据不同的指令,由ALU计算数值或有效地址。
根据三种指令的不同情况讨论:
·访存指令:
MAR<-A+IR地址部分,MDR<-Rd(如为写指令)
Rd为目的寄存器(IR)
·ALU指令:
ALU输出<-A操作B或立即数
"操作"由解码决定
·跳转/条件跳转
ALU输出<-PC+相对地址;条件<-(A操作0)(如为条件跳转)
在条件为真时,跳转实行,条件中的"操作"由解码决定,如指令为bf,则操作为"等于"。
无条件跳转则视为条件永真的跳转。
我们模型的load/store结构决定了执行和有效地址计算可以在同一步之内完成。
在我们的模型中,没有一条指令既需要执行ALU功能,又需要计算有效地址。
4.访存/完成跳转。
(memoryaccess/branchcompletion)
只有两类指令要用到这一步,访存指令和跳转指令,ALU指令无需执行这步。
根据访存指令,表示为
①MDR<-M[MAR]或②M[MAR]<-MDR
对读存,执行①,写存执行②。
对跳转指令,表示为
if(条件为真),PC<-ALU输出
"条件"由一步计算,这一步根据条件实际改变PC值
4.写回(write-back)
表示为Rd<-C或MDR
对ALU指令,将ALU的计算结果送入目的寄存器,对读存,将MDR读入目的寄存器。
这就是执行指令要完成的步骤,控制器的目的就是要让数据通路按此步骤工作。
3.4控制器
控制器的设计是处理器设计中最困难的一部分,也是在新处理器的设计和调试中最容易出问题的部分,因为实际上,处理器的另一部分数据通道只是一个执行机构,没有什么很特别的地方,关键还在于如何控制数据通道。
于是在控制器设计中,我们不得不同时考虑两个因素:
实现的简单和运行的效率。
实现简单有于降低控制器设计的难度,减少错误,也就是缩短了设计和实现的时间,降低了设计成本。
而作为处理器内部的总控者,控制器是计算机"主控的主控",它的运行效率微小变化都会对计算机性能造成很大影响,所以控制器又必须有很高的效率。
不幸的是,这两方面的要求经常是互相矛盾的。
下面我们分别介绍控制器两种最常用的设计与实现途径:
硬连线控制(Hardwiredcontrol)和微程序控制(microprogrammedcontrol)
3.4.1硬连线控制
在硬连线控制中,控制器可看作一个有限状态图(finite-statediagram)。
每个状态对应一个时钟周期,各状态中有一些特定的输出对应着各时钟周期中数据通道要做的工作。
每个状态在一定的输入下有一个出口,指向在此输入下状态应转向的下一状态。
一条指令要经几个时钟周期完成,从而也对应着多个状态。
图3.2就是每条指令的头几步状态转换图。
图3.2每条指令头几步状态转换图
硬连线逻辑的复杂性是很大的,举个例子来说,一般一个load-store型CPU控制器至少也要50个状态(具体状态后面将举例描述)。
为表示这50个状态就需要6位(log250)。
同时,我们还需要几位数据通道和存贮器的反馈输入,来参与决定状态转换,如图3.2中的"访存未结束"。
当然,参与决定状态的还有指令码,如图3.2中就是根据指令码译码结果转换到以后状态的。
这样决定硬连线逻辑控制器,状态转换的就有了三个量:
当前状态(用6位表示),数据通道及存贮器反馈输入(用3位表示)及指令码(设为12位,6位操作码,6位操作数)。
这样的控制器通常要40线输出控制,于是复杂度就是50×(6+3+12)×40。
这是一个相当巨大的数字。
当然,我们应该注意到,指令码中的操作数对硬连线控制的状态变化不产生影响,于是只需要6位操作码就够了。
但即使如此,复杂度还是很大的。
如果我们用ROM来进行这样的状态转换,在其中就必须存贮26+3+6=221个单元,每个单元为40位长,共需约10MB的ROM,这样的存贮容量对处理器控制器来就显然是不可能的,所以需要使用一些办法来降低硬连线控制的成本,通常使用可编程逻辑阵列(Programmedlogicarray,PLA)可以降低控制器所需存贮容量。
PLA的基本思想是利用控制器存贮内容之间的相关性简化其存贮内容,删去冗余的信息。
为此付出的代价是增加了一些地址译码的时间。
PLA采用对输入项与输出间逻辑表达式的简化,来减少存储,在控制器,这样的部件中,常用计算机琰辅助进行简化,简化后,象前面例子中那样规模的控制器,其存贮容量可降为几百个字节。
PLA简化的效果和输入项的编码方式有密切关系,一个精心设计的输入编码可大大减少控制器所需存贮量。
输入中主要的就是状态量的编码和指令操作码的编码。
比如,状态量编码时如果尽可能把相邻状态(有相到直接转移关系的状态)的码编得相似,只差一位或两位,控制器就会大大简化,这种状态编码问题就称为状态指派问题(state-assignmentproblem)。
图3.3硬连线逻辑控制器示意图
3.4.2微程序控制
硬连线控制的复杂度是和其状态数和输入输出数有关的,且随着状态数的增加,输入数也随之增加,从而使复杂性成倍增长。
从而给逻辑设计,状态指派和输出表达式简化等带来很大困难。
为了降低控制器设计的复杂度,MauriceWilkes发明了一种新的控制器设计方法,称为微程序控制(microprogrammedcontrol)。
微程序控制的基本思想是编写固化在控制器里的"微程序",对于每条机器指令码,编写一段程序来实现它的功能。
"微程序"由"微指令"组成,每条"微指令"对应一个时钟节拍的操作。
这样就把控制器的设计从复杂的逻辑设计转化为简单的编程问题,并且可以利用上许多程序设计中的技术与技巧,如进行条件转移,函数调用等,微程序控制形式的控制器如图3.4所示。
图3.4微程序控制器示意图
如图所示,微程序执行地址由机器指令,数据通路来的信号及内部转移地址决定。
当一条指令执行时,微指令地址选择逻辑选出此条指令所需执行的微程序开始地址开始执行,并将地址填入微指令程序计数器(uPC)。
微指令可以是按序执行,通过累加器递增得到下一条应执行的微指令地址;也可以进行跳转或条件跳转,由微指令本身给出下一条微指令的地址。
而在有些机器中,所有下条微指令地址都由上一条微指令提供。
因为既然要进行跳转,在微指令中反正都必须包含一个地址域,这样做并不付出什么代价,反而可节约累加器等硬件。
微程序存贮器一般由ROM构成,但也有用可改写存贮器的,如IBM360计算机。
因为改写微程序就意味着改变指令的功能,所以使用可改写的微指令存贮器实际上还为用户自行重新设计指令集提供了可能。
微指令的结构
目的寄存器
ALU操作
源寄存器1
源寄存器2
常数
外部操作
跳转条件
跳转地址
3b4b4b4b5b3b4b6b
图3.5微指令的结构
微指令和机器指令一样,具有自己的内部结构,分成几个不同的域,执行各自的功能。
与机器指令不同的是,它的操作码直接作为电子控制信号送到数据通路控制其工作,而不象机器指令中那样还要经过控制器的解释。
图3.5是微指令格式一个最简单的例子。
"目的寄存器"域控制着一个数据通路中一个寄存器的输入端,其中的内容表示数据能从目的总线进入哪个寄存器。
"源寄存器1"源寄存器2"分别控制从寄存器到S1和S2总线的数据流动,表示哪个寄存器能向S1/S2总线输出数据。
此外"ALU操作"输出给ALU的运算信号,"条件","跳转地址"完成与微指令跳转有关的功能。
存放微指令的存贮器称作控存(controlstore),减少控存的容量是微指令控制器最重要的目标之一,因为可以减少CPU芯片面积,降低硬件成本。
要做到这一点,方法是精简微程序和缩短微指令长度,前者不仅可以减少控存,还可以减少每条指令所需时钟周期数CPI,加快运算速度。
所以有时宁可用修改硬件的方法来做到。
后者则可以通过对微指令各域编码的方法实现。
例如,"目的寄存器",要对每个寄存器的输入端进行控制,如果有N个寄存器就需要N位来实现控制,但如果规定了每次只能有一个寄存器接收数据,就可以根据这一点对此域编码,输出"1"表示对PC寄存器写入,"3"表示对C寄存器写入等。
从而只需要log2N位就可完成对N个寄存器的写入控制。
当然编码就意味着增加一些硬件电路来解释这些信号,而不是直接使用它们,这样的微指令编制方式称"垂直微代码(verticalmicrocode),而完全不编码的微指令称"水平微代码(horizontalmicrocode)"。
垂直微代码微指令短,所占控存少,格式紧凑但要附加硬件电路,硬件开销较大;水平微代码无需加解释电路,信号直接用于控制,时延短,硬件开销小,但微指令长度长,所占控存多,开销较大。
通常的机器微指令是这两种的一个折衷。
图3.6是三族机器(VAX,IBM360,IBM370)控存大小与微指令长度的关系图。
在图中,我们可以看到,对同族机器,控存大小几乎是要样的,差别只是在微指令长度上。
控存的大小对于同族机器一般总是一样的,所以对控制器设计者来说,将指令简单机型的微指令进行编码并不节约什么,反而增加了硬件解释电路。
因此对同族机器,一般总是将指令复杂的多作编码,缩短微指令长度;而将指令简单的少作编码,尽量利用控存空间,节约硬件解释电路。
图3.8三族机器(VAX,IBM360,IBM370)控存大小与微指令长度的关系图
例设图3.1中机器微指令的三个域源寄存器1,源寄存器2,目的寄存器如图3.7所示,比较垂直微代码和水平代码指令长度。
解:
由图3.7,目的寄存器有6个,加上一种"无目的寄存器"的操作(如条件转移指令中,运算结果只影响标志位,而不写入任何一个寄存器),共需7种输出,故水平微代码长度为7,而垂直微代码长度为[log27]=3;
源寄存器1和源寄存器2具有9种情况,其中8种相同,而图3.1中,A,B两寄存器实际上相互独立,4寄存器不可能输出到源总线2,B寄存器也不能输出到源总线1,故而实际上可共用一对信号,于是它们各应有9种输出,水平微代码长度为9,垂直微代码长度[log29]=4,
三个域水平微代码总长度7+9+9=25bit
垂直微代码总长度3+4+4=11bit,
编码使每条微指令节约了14bit
目的寄存器源寄存器1/源寄存器2
0无A/B
1CTemp
2TempPC
3PCIAR
4IARMAR
5MARMDR
6MDRIR(16位立即数)
7IR(16位立即数)
8常数
图3.7图3.1中机器微指令的源寄存器1,源寄存器2,目的寄存器三个域
控制器设计的衡量标准及优化
控制器设计优劣的衡量标准主要有四:
首先是机器的平均CPI和机器所能达到的时钟频率;其次是实现的硬件开销,包括硬连线中的连线数或微指令控制中的控存大小等;最后还必须考虑完成这样一个控制器所须的设计时间。
优化的目的就是要考虑以上几条,对这几个指标进行优化。
优化中最有效的是增强外围辅助硬件电路功能,减少状态数(硬连线控制中)或微指令条数(在微程序控制中)。
这样不仅减少了硬件复杂性,即硬连线中的接线数和微程序中的控存大小;还可以减少每条指令的CPI,可谓一举两得,下面就是一个这样的例子:
例:
如果对图S1所描述的CPU作一改进,使PC和MAR一样可以直接为内存访问提供地址,则机器性能提高多少(设原平均CPI为7,且此改进对时钟频率不产生影响)。
答:
若PC可直接访问内存,则图3.2的状态转换图中,无需PC<-MAR这一步,改进后的状态转换图见图3.8,比图3.2少了一个状态,由于这一步取指步骤是每条指令都必须进行的,故每条指令都是PI都少了1,于是性能提高
1/(7-1)=17%
图3.8图3.2状态转换图的改进
另一种减少平均CPI的方法则具有更强的针对性。
它的思想来源于admahl定理,在控制器设计中尽量缩短那些最常用的指令的CPI。
这些措施包括对最常用指令进行细化,编写适于多种情况的不同版本,如VAX8800就为CALLS转子指令设计了多种版本,根据寄存器保存情况的不同分别使用最有针对性的优化版本,从而可减少平均CPI。
但这种方法的关键在于找出哪些是最常用的指令。
这可以通过统计指令的使用频率做到,而对于处理器设计阶段,只有通过仿真设计中的处理器工作情况才能做到。
通过微指令控制器增加一些硬连线控制,也可以减少CPI。
例如,在在对内存操作期间,通常的微程序必须循环检测等待内存操作完成信号的到来。
这样当内存操作完成后,还必须多用一个时钟周期从控存中读出下一条微指令后,才能继续执行下去,为了节约这一个时钟周期,可以用一种叫作"stall"的技术,即不采用循环检测,而是在开始内存操作时,暂停微指令的执行,直等到内存操作完成后,才解除暂停状态,继续往下执行。
因为stall期间只是暂停了下一条微指令的执行而并未执行别的微指令,节约了一条微指令的装入时间。
对内存的操作在处理器操作中所占比重是比较大的,如在VAX780中,20%的时钟周期是在等待内存操作,这一步改进可对处理器性能改善产生不小影响。
还有一种减少CPI的方法是采用并行化方法,也就是在同一时钟周期里完成更多的操作,对硬连线逻辑,这种方法意味着要求更多的输出线,对微指令控制,这种方法意味着要有更宽的微指令。
在图3.6中我们可以看到,每一族机器中最快的机器,其微指令也最长,就是这种并行化的结果,但是,这种方法的应用范围是有限的,要受到整个指令执行中,所遇到的各个环节速度的牵制。
比如在8086这样的微处理器中,如果在处理器数据通路内加一条总线,加上6位的控制信号,可以使大部分指令的"执行"这一步(第三步)花的时间从3个时钟周期减少到2个。
但是,由于这样的改动并不加快所有微指令的操作,另一些不能并行的微指令与已并行化的微指令一起使用,从而最后无法体现出这种并行化的优势。
优化控制器也体现在优化硬件,降低硬件成本上。
比如,通过编写微程序公共过程,使得一部分指令为各微程序模块共享,可以减少微指令总条数,从而减少所需控存容量。
另一种常用的办法是利用机器指令中的某些域直接用作控制信号,这些控制信号可分为两类,一类可作为寄存器选择信号,另一种是机器指令中某些域用作ALU操作信号。
intel8086微处理器就同时使用了这两种技术。
由于一部分控制信号由机器指令直接产生,控存所占空间就可以大大缩减。
这样做的唯一缺点是控制信号一部分由硬连电路产生,从而增加了硬件电路设计调试的复杂性。
上面所说的第二种方法实际上是一种微程序控制器与硬连电路控制器的混合设计方法,从而我们也可看到硬连控制和微程序控制不是截然分开的,在实用中常吸取它们各自的优点,组成一种混合的优化电路。
3.5中断
如果说控制器的设计是整个处理器设计中的难点,那么中断处理部分就是控制器设计的难点。
中断是处理器的一项重要技术,在有某些重要事件发生时产生,用来使处理器转入对这些事件的处理。
这些事件包括软硬件错误,一些有实时要求的事件,和用户请求服务等。
下面列举了11种中断情况:
·I/O设备请求
·用户程序进行操作系统调用
·指令跟踪
·断点
·算术运算溢出,包括上溢(overflow)和下溢(underflow)
·页中断(在采用虚存的系统中,使用的当前页不在内存中)
·内存访问未对齐(misaligned)(在要求对齐(alignment)的系统中,访问未对齐的地址)
·违反内存保护(程序企图访问无权访问的内存区)
·使用未定义的指令
·硬件故障
·电源失效
(参见图3.9)
IBM360
VAX
Motorola680x0
Intel80x86
I/O请求
输入/输出中断
设备中断
例外(0-7级自动向量)
向量中断
系统调用
调用中断
例外
(自陷的变例)
例外-在macintosh中(未实现指令)
中断
(INT指令)
指令跟踪执行
无
例外(跟踪错)
例外(自陷)
中断(单步中断)
断点
无
例外(断点错)
例外(非法指令或断点)
中断(断点自陷)
算术运算溢出
程序中断(上溢或下溢例外)
错)
例外
(整数上溢自陷或浮点数下溢错)
例外
(浮点协处理器错)
中断
(上溢自陷或算术单元例外)
缺页中断
无
例外(不能传递错)
例外
(内存管理单元错)
中断(缺页)
内存访问不对齐
程序中断
(特殊例外)
无
例外
(地址错)
无
使用未定