向CPU请教知识。
有通用CPU和嵌入式CPU,通用CPU和嵌入式CPU的区别主要是根据应用模式的不同来划分的。通用CPU芯片一般功能强大,可以运行复杂的操作系统和大型应用软件。嵌入式CPU具有广泛的功能和性能。随着集成度的提高,在嵌入式应用中,人们倾向于将CPU、存储器和一些外围电路集成到一个芯片上,形成所谓的系统芯片(简称SOC),SOC上的CPU成为CPU核心。
现在,教学系统的优化设计有两个相反的方向。一种是增强指令的功能,设置一些功能复杂的指令,利用硬件的指令系统实现一些原来由软件实现的常用功能。这种计算机成为具有复杂指令系统的计算机。早期的Intel X86指令系统是CISC指令结构。
RISC是精简指令集计算机(Reduced Instruction Set Computer)的缩写,是20世纪80年代发展起来的。它尽可能地简化了指令功能,只保留那些功能简单可以一拍执行的指令,比较复杂的功能由一个子程序来实现。这个计算机系统成为一个简化指令系统计算机。目前,RISC架构处理器的芯片厂商有SUN、SGI、IBM的Power PC系列、DEC的Alpha系列、摩托罗拉的龙珠和Power PC等。
介绍MIPS系统。
MIPS是世界上非常流行的RISC处理器。MIPS的意思是“没有互锁流水线级的微处理器”,其机制是通过尽可能使用软件来避免流水线中的数据相关问题。它最初是由斯坦福大学教授Hennessy领导的研究小组在20世纪80年代初开发的。MIPS公司的R系列就是在此基础上开发的RISC工业产品的微处理器。这些系列产品被许多计算机公司用来组成各种工作站和计算机系统。
指令系统
要说CPU,首先要说指令系统。指令系统是指CPU能够处理的所有指令。
命令集是CPU的基本属性。比如我们现在用的CPU都是采用x86指令集,而且都是同一类型的CPU,无论是PIII、速龙还是约书亚。我们也知道世界上有比PIII和Athlon快很多的CPU,比如Alpha,但是他们不使用x86指令集,不能使用大量基于x86指令集的程序,比如Windows98。之所以说指令系统是CPU的根本属性,是因为指令系统决定了CPU能运行什么程序。
所有用高级语言编写的程序都需要翻译(编译或解释)成机器语言才能运行。这些机器语言包含指令。
1,指令格式
一条指令一般包括两部分:操作码和地址码。操作码其实就是指令序列号,用来告诉CPU需要执行哪条指令。地址码比较复杂,主要包括源操作数的地址、目的地址和下一条指令的地址。在某些指令中,地址码可以部分或全部省略,例如一条空指令只有操作码而没有地址码。
比如一个指令系统的指令长度是32位,操作码长度是8位,地址长度是8位,第一条指令是加法,第二条指令是减法。当它收到“0000000100000001000000100000110”的指令时,首先取出它的前八个操作码,即000000010,分析出这是一条指令。然后CPU取出内存地址00000100的被减数,取出0000001的被减数,送到ALU做减法,然后把结果送到00000110。
这只是一个相当简单化的例子,实际情况要复杂得多。
2.指令的分类和寻址方式
一般来说,当前的指令系统有以下类型的指令:
(1)算术逻辑运算指令
算术逻辑运算指令包括加、减、乘、除等算术运算指令和与或异或等逻辑运算指令。现在指令系统还增加了一些十进制运算指令和字符串运算指令。
(2)浮点运算指令
用于对浮点数进行操作。浮点运算比整数运算复杂得多,所以CPU中通常有一个浮点运算单元负责浮点运算。现在一般在浮点指令中加入矢量指令,用来直接操作矩阵,对于多媒体和3D处理非常有用。
(3)位操作指令
学过C的人都应该知道,C语言中有一套位操作语句,相应的,指令系统中也有一套位操作指令,比如左移一位,右移一位。对于计算机中用二进制代码表示的数据,这个操作非常简单快捷。
(4)其他说明
以上三条都是操作指令,还有很多其他指令都是不可操作的。这些指令包括:数据传输指令、栈操作指令、转移指令、输入输出指令和一些特殊指令,如特权指令、多处理器控制指令和等待、关机、空操作等。
对于指令中的地址码,会有很多不同的寻址方式,主要包括直接寻址、间接寻址、寄存器寻址、基址寻址、索引寻址等。一些复杂的指令系统会有几十种甚至更多的寻址模式。
3.CISC和RISC
CISC,复杂指令集计算机,复杂指令系统计算机。精简指令集计算机,精简指令系统计算机。虽然这两个术语是针对计算机的,但是下面我们还是只研究指令集。
(1)CISC的产生、发展和现状
一开始,计算机的指令系统只有几条基本指令,其他复杂指令都是在软件编译时通过简单指令的组合来实现的。举个最简单的例子,a乘以b的一个运算可以转化为a和b的相加,所以不需要乘法指令。当然,最早的指令系统已经有乘法指令了。为什么?因为用硬件实现乘法比加法合并快得多。
因为当时的计算机部件相当昂贵且速度慢,为了提高速度,越来越多的复杂指令被添加到指令系统中。然而,很快又出现了另一个问题:一个指令系统中的指令数量受到指令操作码数量的限制。如果操作码是8位,指令的最大数量是256 (2的8次方)。
那么我们该怎么办呢?增加指令宽度很难,聪明的设计者想出了一个方案:操作码扩展。前面说过,操作码后面是地址码,有些指令不需要地址码或者只用少量地址码。然后,您可以将操作码扩展到这些位置。
举个简单的例子,如果一个指令系统的操作码是2位,那么可以有四种不同的指令:00,01,10,11。现在保留11,操作码扩展为4位,所以可以有00,01,1100,1101,65438。包括1100,1101,1110,111。
然后,为了实现操作码扩展的前提:减少地址码,设计者们开动脑筋,发明了基址寻址、相对寻址等各种寻址方式,最大限度地压缩地址码长度,给操作码留出空间。
就这样,慢慢地,CISC指令系统诞生了。大量复杂的指令、可变的指令长度、多种寻址方式是CISC的特点,也是CISC的短板:因为这些都大大增加了解码的难度,而且随着高速硬件的发展,复杂指令带来的速度提升早已小于在解码上浪费时间。除了仍在个人电脑市场使用的x86指令集,CISC已不再用于服务器和更大的系统。x86之所以还存在,唯一的原因就是为了兼容x86平台上的大量软件。
]:(2)RISC的产生、发展和现状。
1975年,IBM的设计者约翰·科克研究了当时的IBM370CISC系统,发现只占指令总数20%的简单指令却占了程序调用的80%,而占指令80%的复杂指令只用了20%的时间。因此,他提出了RISC的概念。
事实证明RISC是成功的。80年代末,各公司的RISC CPU如雨后春笋般出现,占领了大量市场。90年代,奔腾、k5等x86 CPUs也开始使用先进的RISC内核。
RISC的特点是指令长度固定,指令格式少,寻址方式少。其中大多数是简单的指令,可以在一个时钟周期内完成。超标量和流水线很容易设计,寄存器数量多,寄存器之间的运算量大。因为下面提到的CPU核大部分都是关于RISC核的,所以这里就不介绍了,我来详细说说RISC核的设计。
RISC现在发展的如火如荼,英特尔的安腾最终也会抛弃x86,转向RISC架构。
二、CPU内核结构
好了,我们来看CPU。CPU核心主要分为两部分:运算器和控制器。
(1)算术单元
1,算术逻辑单元(ALU)
ALU主要完成对二进制数据的定点算术运算(加减乘除)、逻辑运算(与或非异或)和移位运算。在某些CPU中,还有专门处理移位操作的移位器。
通常ALU由两个输入和一个输出组成。整数单元有时被称为IEU(整数执行单元)。我们通常所说的“CPU是XX位”是指ALU能够处理的数据位数。
2.浮点单元
FPU主要负责浮点运算和高精度整数运算。有些fpu也有向量运算的功能,有些则有专门的向量处理单元。
3.通用寄存器组
通用寄存器组是一组速度最快的存储器,用于存储参与运算的操作数和中间结果。
RISC与CISC在通用寄存器的设计上有很大的不同。CISC通常寄存器很少,这主要是受当时硬件成本的限制。例如,x86指令集只有八个通用寄存器。因此,CISC的CPU执行大部分时间是访问内存中的数据,而不是寄存器中的数据。这会降低整个系统的速度。RISC系统往往有很多通用寄存器,使用重叠的寄存器窗口和寄存器文件来充分利用寄存器资源。
针对x86指令集只支持8个通用寄存器的缺点,Intel和AMD的最新CPU都采用了一种叫做“寄存器重命名”的技术,使得x86CPU突破了8个寄存器的限制,达到了32个甚至更多。但是,与RISC相比,该技术的寄存器操作需要多一个时钟周期来重命名寄存器。
4.专用寄存器
专用寄存器通常是一些状态寄存器,不能被程序改变,由CPU自己控制,表示某种状态。
(2)控制器
运算器只能完成运算,而控制器用来控制整个CPU。
1,指令控制器
指令控制器是控制器中非常重要的一部分。它需要取出并分析指令,然后交给执行单元(ALU或FPU)执行。同时还需要形成下一条指令的地址。
2.定时器
时序控制器的作用是为时序中的每条指令提供控制信号。时序控制器包括时钟发生器和倍频定义单元,时钟发生器通过石英晶体振荡器发出非常稳定的脉冲信号,该脉冲信号是CPU的主频;倍频定义单元定义CPU的主频是内存主频(总线频率)的几倍。
3.总线控制器
总线控制器主要用于控制CPU的内部和外部总线,包括地址总线、数据总线、控制总线等。
4.中断控制器
中断控制器用于控制各种中断请求,并将中断请求按优先级排队,交给CPU逐一处理。
(CPU内核的设计
是什么决定了CPU的性能?单个ALU的速度在一个CPU中起不到决定性的作用,因为ALU的速度都差不多。CPU性能的决定性因素在于CPU内核的设计。
1,超标量
既然ALU的速度无法大幅提升,有什么替代方法?并行处理的方法再次发挥了强大的作用。所谓超标量CPU,就是只集成多个alu、多个fpu、多个译码器和多个流水线,通过并行处理来提高性能的CPU。
超标技术应该很好理解,但是有一点需要注意,就是不要关注“超标”前的数字,比如“9路超标”。不同的厂商对这个数字有不同的定义,更多的它只是一种商业宣传手段。
2.管道
流水线是现代RISC核的重要设计,它极大地提高了性能。
对于一个特定的指令执行过程,通常可以分为五个部分:取指令、指令解码、取操作数、运算(ALU)、结果写入。前三步一般由指令控制器完成,后两步由运算器完成。按照传统的方式,所有指令都是按顺序执行的,所以首先指令控制器工作完成第一条指令的前三步,然后运算器工作完成后两步,然后指令控制器工作完成第二条指令的前三步,现在运算器完成第二条指令的后两部分...很明显,指令控制器工作的时候,运算器基本都在休息,但是运算器工作的时候,指令控制器在休息,造成了相当大的资源浪费。解决办法很容易想到。当指令控制器完成第一条指令的前三步时,它将直接开始第二条指令的操作,算术单元也是如此。这样就形成了一个管道系统,就是两级管道。
如果是超标量体系,假设有三个指令控制单元和两个运算器,那么第一条指令的地址完成后,可以直接开始第二条指令的地址。这时第一条指令是解码,然后第三条指令是寻址,第二条指令是解码,第一条指令带操作数...这是五级水线。显然,5级流水线的平均理论速度是无流水线的4倍。
流水线系统最大限度的利用了CPU资源,使得每个部件都在每个时钟周期工作,大大提高了效率。然而,管道有两个非常大的问题:相关性和传输。
在流水线系统中,如果第二条指令需要第一条指令的结果,这种情况称为相关性。以上面的五级管道为例。当第二条指令需要取操作数时,第一条指令的操作还没有完成。如果此时第二条指令取出操作数,将会得到错误的结果。所以,这个时候,整个流水线不得不停下来,等待第一条指令的完成。这是一个很烦人的问题,尤其是对于一个很长的流水线,比如20级,这个暂停通常会损失十几个时钟周期。目前解决这个问题的方法是乱序执行。乱序执行的原理是将不相关的指令插入到两条相关的指令中,使整个流水线顺畅。比如上面的例子,第一条指令执行完之后直接开始执行第三条指令(假设第三条指令无关),然后开始执行第二条指令,这样当第二条指令需要取操作数的时候,第一条指令刚刚结束,第三条指令快结束了,整个流水线也不会停止。然而,流水线阻塞是不能完全避免的,尤其是当有许多相关指令时。
另一个大问题是有条件转移。在上面的例子中,如果第一条指令是条件分支指令,那么系统将不知道接下来应该执行哪条指令?这时,你必须等待第一条指令的判断结果,才能执行第二条指令。条件转移导致的流水线停顿甚至比相关性更严重。因此,现在使用分支预测技术来处理转移问题。尽管我们的程序充满了分支,而且任何分支都是可能的,但在大多数情况下,我们总是选择一个分支。例如,在循环的末端有一个分支。除了最后一次需要跳出循环,我们总是选择继续循环。根据这些原理,分支预测技术可以在得到结果并执行之前预测下一条指令是什么。现在的分支预测技术可以达到90%以上的准确率,但是一旦预测错误,CPU还是要清理整个流水线,回到分支点。这样会损失很多时钟周期。因此,进一步提高分支预测的准确性也是正在研究的课题。
流水线越长,关联和转移这两个问题就越严重。所以流水线越长越好,多余的数量越多。找到速度和效率的平衡点才是最重要的。
1,解码单元
这是x86CPU独有的东西,它的作用是把不定长的x86指令转换成类RISC的定长指令,交给RISC内核。解码可以分为硬件解码和微解码。对于简单的x86指令,硬件解码就够了,速度更快,而对于复杂的x86指令,需要进行微解码,并分成几个简单的指令,速度慢且复杂。幸运的是,这些复杂的指令很少使用。
Athlon、PIII和旧的CISC x86指令集严重限制了他们的性能。
2.一级缓存和二级缓存
而缓存和二级缓存就是为了缓解更快的CPU和更慢的内存之间的矛盾而产生的,缓存通常集成在CPU内核中,而二级缓存以OnDie或板载的方式运行速度比内存快。对于一些数据交换量大的作业,CPU缓存尤为重要。