微结构(Microarchitecture)对应的是底层硬件如何实现指令执行的,那么指令集架构(Instruction Set Architecture)对应的是程序员所看到的程序的模样。
具体指令是如何被处理器一步一步完成执行任务的,这交给了微结构。而到底有哪些指令可供使用、指令是什么格式、哪些通用寄存器可以用,以及这些指令在程序员看来是要如何执行的,就是ISA的范畴了。
因此程序员在某个ISA上写的程序,这个程序的每一步执行了什么操作,最终结果如何,程序员是知道的。而程序员不知道的是,每一步到底是如何被处理器完成的。
比如一个加法操作“add A,B,C”,在程序员的视角看来,就是将寄存器A和B里的数相加的结果存放在寄存器C中,之后程序员就可以把寄存器C作为A和B相加的结果来继续使用。
而在微结构的视角(假设为乱序执行),则是处理器读取到了一条指令,通过译码逻辑得知这是一条加法指令,这条指令需要寄存器A和B里的数据作为输入,因此要检查有没有正在执行的指令要写入寄存器A和B(即寻找寄存器A和B的重命名寄存器),并为其结果寄存器C进行寄存器重命名,同时在重排序缓存(ROB)中为该指令申请一个位置,然后送入指令队列(即保留站),并不断检查寄存器A和B里的数据是否可用,该指令会等待直到源数据可用,且加法运算单元空闲时,则该指令的操作码以及寄存器A和B的数据(或来自寄存器堆,或来自旁路,或来自尚未退休指令的ROB项)会送入加法运算单元,当加法运算单元完成后将结果通过总线写回到该指令对应的ROB项中,并修改该项的状态为已完成,退休(retire)逻辑每拍检查若干ROB的项,按照程序顺序完成指令的执行,即将其结果写回寄存器堆,并回收ROB项和重命名寄存器。
若有指令在退休时被发现有例外,则要冲刷流水线,进入例外处理。若运行期间来了中断,则需要保存现场去处理中断。若在此之前有一个读操作读取数据到A(或B)且未命中缓存,则该指令需要一直等待,而该指令之后的指令由于乱序可能先于这个加法操作完成执行。若该指令运行在错误的分支预测路径上,则分支结果出来后该指令会被取消掉。不同的微结构下,如何完成这条指令的执行,通常是不一样的。但程序员并不需要知道内部是如何完成的,只需要知道这条指令可以将寄存器A和B的数据相加并存入寄存器C就可以了。这就是ISA了。
微结构负责实现每条指令是如何完成执行任务的,而ISA则可以描述指令序模型(instruction sequencing model),有两种指令序模型:
基于顺序的控制流(sequential control-flow)的指令序,对应经典的冯诺伊曼架构。控制流架构下有单一的程序计数器(PC),其决定了指令的获取、执行和提交的顺序。此时的指令是在PC的指挥下一条一条顺序执行的。目前大多数ISA都是基于控制流的。基于数据流(data-flow execution)的指令序,对应数据流架构(Dataflow Architecture)。其在逻辑上没有PC的存在,指令的执行并不是按照程序所写明的顺序,而是按照数据依赖关系。 虽然学术上有不少对数据流架构的讨论,但是商业上并没有纯粹数据流架构的通用处理器,不过在数字信号处理、网络路由、数据仓库等领域则有【1】。从某种意义上来说,处理器核内部的乱序执行结构也是一种数据流架构,此时指令只要满足了数据依赖,就可以送去执行了,这恰恰打乱了顺序的指令流【2】。ISA涵盖的内容,包括但不限于以下几点:
指令格式:定长或变长;每个位的含义(操作码,寄存器编号,立即数等);操作数的个数;寻址访存:寻址范围(地址空间);寻址模式;寻址粒度(单比特/字节/64比特等);访存方式(如load/store结构,专门的IO指令);地址对齐;数据类型:8/16/32/64位整数,浮点;有/无符号;复杂数据类型(BCD码、字符串、链表);寄存器:通用寄存器数量以及每个寄存器含义、宽度;整数、浮点、向量寄存器;大小端;特殊用途寄存器(如标志寄存器、架构相关的寄存器如MIPS的协处理器寄存器);通常ISA都会包含以下三类指令:
运算指令:算术运算(加减乘除),逻辑运算(与或非),移位运算,向量运算等;分支指令:条件分支指令,非条件分支指令(如函数调用、无条件跳转)等;访存指令:load/store结构;寻址模式(寄存器寻址、基址寻址等);IO指令等;此外还有:
架构相关指令:原子操作(如ll/sc);内存栅栏;缓存相关的指令;TLB相关的指令;等复杂操作指令:FFT、三角函数、平方根;等其他特殊用途:虚拟化指令;例外和中断(有哪些例外,是否是精确例外);核心态/用户态;访存权限检查、禁止运行位等安全方面;非对齐访存;功耗管理;延迟槽;特殊寄存器的访问;等最后说一句,在汇编层面还有一些“伪指令”,其只对汇编器有用,不会被翻译成机器码。MIPS中的“.set“指令会影响汇编器如何将汇编翻译成机器码:“.set mips16”使汇编器进入MIPS 16模式;“.set mips3”则告诉汇编器下面的指令是MIPS IV(64位指令集,兼容32位指令)中的指令【3】。还有一些“伪指令”,只有汇编器认识,CPU不认识,在编译的时候会被汇编器翻译成 CPU 认识的汇编指令,完成相应的功能,如“li”指令通常会被翻译成“lui”和“ori”。
Complex Instruction Set Computer,即CISC,复杂指令集计算机。 Reduced Instruction Set Computer,即RISC,精简指令集计算机。
笼统的对比一下CISC和RISC,不完全正确,但能反应其本质上的差别:
对比CISC(x86)RISC(ARM,MIPS,etc)访存模式多种寻址模式load/store指令宽度变长定长操作数来源内存或寄存器寄存器IO通信专用的IO指令和IO地址空间内存映射访存对齐不需要需要数据类型多而复杂少而简洁寄存器堆相对更小相对更大设计原则功能多样的复杂指令集功能完备的精简指令集可见RISC更加简洁,因此单从架构优势上来说,普遍认为RISC更优于CISC:
RISC的定长指令宽度以及相对规整的指令格式,简化了译码逻辑,也使得指令之间相关性的判断也更容易,比较容易实现多发射结构,此外也能节省面积、降低功耗RISC只有简单的数据类型,同样可以简化硬件的实现RISC的load/store访存模式,简化了指令相关性的判断,简化了访存操作的处理,也使得其他指令只能操作寄存器,从而可以更快地执行完成RISC可以用更简单的逻辑实现,比如译码结构,节省下来的面积可以使得寄存器堆更大,从而容纳更多的指令进行乱序执行,提高性能。同时更多的寄存器也可以降低编译器的复杂性,使优化工作更容易进行RISC的每条指令只执行很简单的操作,大多可以在一拍内完成,因此主频可以做到很高,流水线的吞吐量可以接近每拍完成1条指令(多发射则更多)总的来说,由于RISC更加简单化,因此微结构的实现可以更加高效,指令的执行效率更容易通过流水线、多发射、乱序执行等技术来提高。对于CISC所拥有的复杂指令,比如FFT,RISC则是通过软件来实现。这种复杂指令的使用场景也非常少,因此RISC也符合“常用的做得快,少用的只要对”的原则【4】。
自从1985年以后,所有的ISA都是RISC结构。如今唯一的CISC就是x86指令集,而实际上其微结构的实现也融合了RISC的优点。
x86指令集在个人电脑的市场占有率上毫无疑问是王者,其创立者为Intel。可以说x86指令集是目前世界上最流行的指令集了,也被认为是现存唯一的CISC指令集。
Intel主导下的x86架构,并不一直是处理器架构做得最好的,历史上出现过的Alpha等RISC处理器其架构设计就比同时代的x86更优,1976年乔布斯和沃兹尼亚克推出的使用8位6502处理器的Apple II计算机也击败过x86架构【5】。但x86的兼容性(Compatibility)做得最好,其他如Alpha过于追求更先进的技术,甚至Alpha指令集代与代之间完全不兼容,从而淡出了市场,而x86的兼容性,使得即使在如今64位时代下,其仍能运行16位乃至8位的程序。显然如果客户每次升级处理器,都需要重写一遍程序的话,那绝对是受不了的。
而在兼容性之外,还有Intel和AMD本身的实力,足以下很多功夫在其他方面(工艺、架构)上来提高性能,以弥补架构上的差距。同时,x86架构也逐渐吸取了RISC架构的优势,在处理器内部,通过复杂的译码逻辑,将变长的复杂指令转换成定长的、简洁的微码,随后再流水执行。这样带来的缺点就是x86的译码逻辑相对于纯正的RISC来说要复杂很多,但这也许并不全是坏处。
说起指令集兼容性的重要性,有一件事十分典型,即x86从32位发展到64位时。首先是Intel与惠普联合推出了IA-64指令集,但其与32位的x86不兼容,因此难以推广。随后AMD推出了x86-64架构,是在32位的基础上增加了64位扩展,很快占据了市场。之后IA-64彻底失败,Intel也接纳了x86-64作为x86架构在64位时代的版本。
x86架构处理器的两大厂商,即Intel和AMD,只是提供处理器,并不生产整机。因此Intel和AMD都与IBM达成了合作,搭上了IBM这班飞速发展的快车。此外微软的操作系统也是长期支持x86架构。总的来看,x86处理器芯片有Intel和AMD,电脑整机有IBM,操作系统有微软,在这几大厂商的联合下,使得x86指令集架构占据了绝大部分的个人电脑市场。其他整机厂商,如1984年成立的DELL所推出的第一台计算机Turbo PC也是基于Intel 8088处理器【6】。
此外让人津津乐道的,也有AMD和Intel之间的竞争。进入20世纪后,更明确说是2006年之后,Intel几乎是压制AMD,后者也不得不在价格和性能上妥协来避免直接竞争。但在20世纪前,AMD不见得比Intel差到哪去,相反在x86最初的二十年里,AMD的实力丝毫不输于Intel,甚至更强。而AMD之所以落后则是有多方面原因,包括领导的不力、方向性的错误、Intel的不正当竞争【7】。最近几年随着锐龙架构的兴起,AMD也逐渐跟上了Intel的脚步,而Intel则饱受工艺研发的痛苦,被困在14nm工艺长达5年之久,不断滞后了先前承诺的10nm计划。
关于x86指令集的更详细内容,可以移步Intel和AMD提供的开发手册了。【8】【9】
ARM,即Advanced RISC Machine,或更早些时候的Acorn RISC Machine,是一系列RISC架构处理器。如果说x86统治了个人电脑(Personal Computer,即PC)市场,那么ARM则是统治了移动设备市场,主要是手机、平板以及嵌入式系统。这得益于RISC架构的优势,其简洁性可以很容易的实现低功耗需求,降低设计难度和散热性要求,同时具备良好的扩展性可以满足众多需求。
英国计算机公司Acorn Computers于1978年在剑桥成立,其在1980s推出了Acorn RISC Machine architecture,用于自家的PC。Acorn的第一款基于ARM的产品是一种协处理器模块,用于BBC Micro系列计算机,而BBC系列计算机也用于开发用于芯片设计的仿真软件,以及用于ARM2开发的CAD工具。
在1980s末期,Apple Computer公司和VLSI Technology公司开始和ARM合作开发新的架构。1990年Acorn将芯片设计团队独立出去,成立了Advanced RISC Machines Ltd,其母公司则为ARM Holdings,与Apple和VLSI共同开发处理器核。在1992年推出了ARM6架构,而Apple使用了基于ARM6的ARM610作为Apple Newton PDA的基础。Acorn在破产前一直在销售基于ARM的PC,而ARM Holdings则在销售芯片架构设计【10】。
ARM并不生产芯片,而是出售芯片设计,供其他厂商使用。ARM架构的授权方式主要有两类:核心级授权和架构级授权【11】:
前者只提供处理器核,可以和其他模块组合在一起形成可用的芯片。该授权下主要有两种级别,一种是提供门级网表(gate netlist)以及一些仿真模型和测试程序,因此无法修改核心架构,使用这种授权模式的有三星的Hummingbird和Exyno、苹果的A4、A5和A5X等。另外一种是提供HDL级的处理器核架构,此时相当于有了源代码,厂家可以自行修改,进行个性化开发,使用这种授权模式的有苹果、高通、华为、三星、博通、Xilinx等等。后者则是指令集授权,可以使用ARM的ISA,内核可以自行设计,但仍需服从ARM架构。使用这种授权模式的有高通、苹果等。比较知名的RISC,除了ARM外,简单介绍一下四种:【12】
MIPS(Microprocessor without Interlocked Piped Stages Architecture)是一种十分简洁的RISC架构,其出身可谓是名门之家,由斯坦福大学的Hennessy教授领导的研究小组研制开发。由于MIPS是经典的RISC架构,且广泛用于体系结构领域的教学上,如Patterson和Hennessy的系列著作《计算机体系结构·量化研究方法》就主要以MIPS为例。如今除了ARM外,再说其RISC基本上就是MIPS了。我国的龙芯也是基于MIPS指令集,拓展了自己的指令后形成了LoongISA。Power是IBM开发的RISC指令集。IBM于1980年推出了全球第一台基于RISC的原型机,而1980年也是IBM在PC市场上称霸的起步时期,但IBM却选择了RISC用于高性能领域,其成功也证明了RISC比CISC在高性能上更具优势。Power架构在超算、金融等高端服务器领域表现十分成功,至今IBM仍在迭代发展Power架构。Alpha是一种64位的RISC指令集架构,由DEC公司设计开发,被用于DEC自己的工作站和服务器中。Alpha是一款优秀的处理器,它不仅是最早跨过GHz的企业级处理器,而且还是最早计划采用双核,甚至是多核架构的处理器。2001年,康柏收购DEC之后,逐步将其全部64位服务器系列产品转移到Intel的安腾处理器架构之上。2004年,惠普收购康柏,从此Alpha架构淡出了人们的视野。SPARC(Scalable Processor ARChitecture),是由Sun公司在1985年设计的指令集架构,是一种非常有代表性的高性能RISC架构。Oracle收购Sun公司之后,SPARC架构归Oracle所有。2017年9月,Oracle公司宣布正式放弃硬件业务,也包括了收购自Sun的SPARC处理器。RISC-V是一个开源的指令集架构,遵循RISC的设计原则,即力求简洁性,同时保持开放性。这个开源项目于2010年起源于伯克利,随后一直发展至今。
RISC-V最大的意义在于其开源性。现有的ISA基本上都十分昂贵,如ARM的授权。此外,设计CPU也是一个很复杂、很费钱的工作,不仅需要有经验的架构设计人员,还需要不断的经历仿真、验证、流片测试,而这则是普通公司难以承受的。
RISC-V自诞生之日起就是为了解决这些问题,提供一个开源的、广泛应用的、经过验证的指令集。经过若干年的开发,RISC-V具备了完整的软件工具链,以及若干开源的处理器架构设计。2016年,RISC-V基金会成立,作为一个非盈利组织,负责维护RISC-V指令集手册和架构文档,并推动RISC-V持续发展。许多著名科技公司,如谷歌、惠普、Oracle、西部数据等,都是RISC-V基金会的创始会员,越来越多的芯片公司也开始使用或计划使用RISC-V架构。此外,许多体系结构领域的教材,如Patterson和Hennessy的系列著作《计算机体系结构·量化研究方法》,其作者本身也大力支持RISC-V架构,因此后续越来越多的教材也将以RISC-V为例。而随着物联网时代的加速到来,有一个统一的、通用的、开源的指令集架构是很有意义的。【13】
然而RISC-V的野心太大,无论是PC的王者Intel,还是移动设备的霸主ARM,都不会任由其发展下去。目前的形势下,正在兴起的物联网、AI则是RISC-V主要的发展方向【14】。
胡老师的书中提出了四点指令集设计原则【4】:
兼容性:指令集架构更新不能扔掉历史包袱,而设计的时候也要为未来留出空间。通用性:功能上要完备,能够支持各种软件,如网络应用、科学计算、操作系统等等。高效性:即简洁、规整,便于CPU的优化、编译器的实现。安全性:满足安全需求。只有这四点是不够的,或者说这四点只是针对通用处理器的指令集设计而言。
而在设计一个专用处理器的ISA的时候,常常在各方面都会面临多种选择,最重要的是清楚不同设计下的优势和劣势,根据实际的需求选择设计方案。尽管真正从零开始设计一个ISA的机会并不多,但通过这种分析可以对指令集架构有更好的了解。此外目前 RISC-V架构 的发展提供了更多接触指令集设计的机会。从2014年逐渐发展起来的深度学习处理器,也出现了许多面向深度学习处理的指令集架构。
运算类型:即指令集实现的功能。复杂指令越多,其单条指令能完成的功能越多,因此可以减少程序的存储空间,提高内存利用率,编译器的实现更简单,但也降低了编译优化的空间。此外复杂指令需要更复杂的硬件逻辑支持,包括译码逻辑、功能单元等。语义鸿沟:即可读性。指令集越复杂,提供的指令种类越多,其可读性越好,而越精简的指令集,其许多功能需要软件实现,可读性就更差。指令格式:变长的指令格式可以减少程序本身所需的存储空间,但会增加译码的复杂度;定长的指令格式常常需要更大的空间存储指令,但其译码更加简单,不仅更容易译码单条指令,而且更容易实现同时译码多条指令,支持更多指令同时发射。定长的指令常常也有更加统一的指令格式,如最高若干位通常表示操作码,这才是降低译码复杂度的主要原因。寄存器堆:寄存器堆越大,实现的复杂度就越高,对芯片设计的要求也更高,需要处理访问时间、功耗、面积等各方面的问题。但越大的寄存器堆可以支持更多的指令在流水线中,提供更多的乱序空间,同时降低了编译优化的难度。此外越大的寄存器堆,就需要在指令中占据更多的位来对寄存器编码。寻址模式:寻址模式越多,对编程越友好,可以增加可读性,但会加大芯片设计的难度,也会影响编译器的实现。其他方面:如何处理例外和中断;是否需要/如何保证精确例外;是否需要虚拟内存;是否需要对齐访存;是否需要向量部件;需要支持哪些数据类型;使用什么存储模型;等等[1] WiKiPedia.Dataflow architecture[EB/OL].(2019-03-05)[2019-05-04].https://en.wikipedia.org/wiki/Dataflow_architecture
[2] Onur Mutlu.Dataflow[EB/OL].(2013-10-31)[2019-05-04].https://www.archive.ece.cmu.edu/~ece740/f13/lib/exe/fetch.php?media=onur-740-fall13-module5.2.1-dataflow-part1.pdf
[3] adaptiver.set伪指令(mips)[EB/OL].[2019-05-04].https://blog.csdn.net/adaptiver/article/details/6760220
[4] 胡伟武.计算机体系结构(第2版)[M].清华大学出版社:北京,2017:55-71.
[5] Gary Anthes.Timeline: A brief history of the x86 microprocessor[EB/OL].(2008-06-05)[2019-05-05].https://www.computerworld.com/article/2535019/timeline–a-brief-history-of-the-x86-microprocessor.html
[6] Smithsonian.PC’S Limited Microcomputer[EB/OL].[2019-05-05].https://americanhistory.si.edu/collections/search/object/nmah_1321866
[7] Graham Singer.The Rise and Fall of AMD[EB/OL].(2012-11-21)[2019-05-07].https://www.techspot.com/article/599-amd-rise-and-fall/page1.html
[8] Intel.Intel® 64 and IA-32 Architectures Software Developer Manuals[EB/OL].[2019-05-07].https://software.intel.com/en-us/articles/intel-sdm#combined
[9] AMD.Developer Guides, Manuals & ISA Documents[EB/OL].[2019-05-07].https://developer.amd.com/resources/developer-guides-manuals/
[10] David Chisnall.Understanding ARM Architectures[EB/OL].(2010-8-23)[2019-05-07].https://www.informit.com/articles/article.aspx?p=1620207
[11] WiKiPedia.ARM architecture[EB/OL].(2019-03-03)[2019-05-07].https://en.wikipedia.org/wiki/ARM_architecture#History
[12] 胡振波.ISA众生相[EB/OL].(2018-05-23)[2019-05-07].http://book.51cto.com/art/201805/574072.htm
[13] 胡振波.RISC-V架构与嵌入式开发快速入门[M].人民邮电出版社:北京,2019:19-23.
[14] 半导体行业观察.RISC-V未来将面临怎样的挑战?[EB/OL].(2019-03-10)[2019-05-07].https://www.chainnews.com/articles/711647751312.htm