有点出乎意料。

我一直以为应该是先有基本的CPU的框架,再在cpu框架上设计各种指令集。

但是,我看到很多文章都是先有一套指令集,然后再设计cpu来配合这套指令集。

为什么会呢?

另外,如果是指令集在先,那么是不是意味著:

1、我们可以在arm上去实现x86、riscv的指令集?

2、理论上谁都可以造一份指令集出来?cpu的开发就是个体力活了?

3、如果指令集有bug怎么办?


ARM,x86,这种可以叫做架构,

ARMv7,ARMv8,x86,amd64,AVX这种可以叫指令集,

A52,A72,skylake,zen这种可以叫微架构。


所以第一个问题你是想用一个指令集去实现另一个指令集?当然可以啦, 中间加一层二进位转换,surface pro x用ARM跑windows不就是嘛。

当然你想问的可能是用ARM处理器的微架构(硬体)去跑x86的指令集?那就不行了,指令集和微架构是相辅相成的,难以剥离的。


第二个问题,造指令集,理论上是谁都可以造。但CPU开发却不是体力活那么简单。

当然你按体力活的方法去搭硬体也不是不可以,只不过从性能上说就不好看了。更重要的是如果你指令集设计得太不合理或者难度太高的话就GG了。

先有指令集再造硬体的说法是合理的,就像软体开发要先定需求,写开发文档再写代码一样。

当然很多在职码农也会反驳说自己公司是边写代码边写文档,或者写了代码没有文档,但这样就很难团队间合作了咯。而造CPU硬体本身的难度通常是大于普通中小软体开发的,牵一发而动全身。


第三个问题,指令集本身复杂度是会很高,但限定了规则的话其实还没那么容易出错的。

但相比之下微架构设计这种硬体层面的东西才更复杂,更容易出错。现在CPU出bug很多啊,比如Intel就经常要发微码去更新填补漏洞,再比如TSX指令集的硬体设计也是两次出bug被禁用到现在。还比如spectre这样的漏洞,就很难补。

换句话说,指令集本身只是规定了什么对外可见,什么操作对外提供,哪些要求限制依赖需要满足。事实上微架构的重要性可以说比指令性更高,能发挥的余地也更大。

比如x86这么多年了,本质上没做太大修改,但底下硬体明明已经翻天覆地面目全非了。

指令集算是介面,微架构是内部实现。介面出bug是大问题,而内部实现更加复杂,出bug就寻常多了。


至于你说的,先造好CPU硬体再在基础上设计指令集……但是指令集一改,硬体或多或少也要跟著改,流片不要钱的嘛……

不过大家这时候可能会上FPGA搞设计和验证,这也算是变相符合了你说的做法吧。


well,事实上,是同时进行的。

通常,人们谈到CPU的指令集,是指x86,ARM这些。然而,实际上CPU真正在执行的时候,(大部分)并非是直接执行这些指令。

学过CPU微架构的话,应该知道CPU的指令队列连接著一个解码器。这个解码器就是将上面的指令集翻译成CPU真正的操作码,通常称为(OP)。

因为外部的指令集决定了上层软体环境,如果自造一套指令集,则等于抛弃了从编译器到网页脚本这整个现存的软体环境,除非是军事医疗等特别领域,对于通用领域来说这等于自己挖坑,对于CPU的设计来说是致命的。

然而另外一方面,CPU要实现省电、高性能等要求,指令集如果一成不变,则会对CPU当中的数字电路设计形成很大制约。况且,还有复杂的专利保护等问题。所以,当今CPU多数内部有另外一套本地的操作码,但是对于外部则以通用指令集公开。这样在保证兼容性的同时,可以对CPU内部的设计进行很多优化升级,并且容易绕开其它公司的专利,形成自己的核心技术。

至于非x86架构的CPU执行x86的指令集,这是完全可以(虽然有一定限制)并且实际上这样的产品过去存在过。比如索尼的PCG-U3:

这货采用的CPU其实是128bit的非x86 CPU。但是其CPU内部有个软体,可以将最多4条x86命令拼接成一条128bit的命令来执行。

当时这样设计的初衷是为了降频,从而省电。(理论上,因为一次可以执行4条x86命令,那么只要1/4的频率就可以达到同等性能)。但是实际上,命令的转换需要额外的开销,且命令当中有跳转,并非永远都会执行连续的4条命令,以及,x86命令为变长命令等问题,这个CPU的实际性能很烂。在U3之后,据我所知再没有人采用这个CPU,厂商也早关门成为了历史了。

(当然这个机子最大的问题还不是CPU,而是它搭载的1寸机械硬碟。看清楚,是1寸,当时是绝无仅有,现在估计也是。。。。)

至于ARM跑x86,除开虚拟机这种不算,因为ARM是固定长指令集而x86是变长指令集,这个比较难了。


好问题。你可以认为指令集是硬体模块的介面。先定介面再设计其实是比较常规的思路,无论是不是CPU。甚至设计软体也会这么搞。而且指令集不只是介面,还是CPU的完整功能的定义。没需求文档没法开发。

当然实际上是迭代著来的,从最初的一些简单功能慢慢发展起来。去看看MIPS的wiki页面,你会看到很多版本。x86也是一样,随著计算机硬体成本的降低,扩充到了x64。不过迫于历史原因甚至还背负著以前16位机的一些包袱。

下面回答问题:

1、我们可以在arm上去实现x86、riscv的指令集?

可以。用软体实现就是虚拟机。用硬体实现……那就不叫arm了

2、理论上谁都可以造一份指令集出来?cpu的开发就是个体力活了?

是的。问题是需要有人买你的帐。而且你不能抄别人的指令集。你的指令集也需要有人给开发编译器。

3、如果指令集有bug怎么办?

改,虽然厂商很不愿意。这点在硬体迭代的历史过程中应该是有的,硬体更新了之后老的指令集出了问题。我记得x86就有过这种经历(具体例子忘了)


本人主做编译兼做一些架构。虽然主要是DSP而不是CPU,但大的方向是一致的,所以泛泛而谈一下。

我认为你这话是不对的,或者你的理解可能有问题。正确理解应该是,先有处理器的ISA (Instruction Set Architecture),然后基于ISA做微架构设计。

从名字可以看出来,ISA主要分成两个部分指令集(Instruction Set)架构(Architecture)

我想误会可能来源于这两部分通常写在一个文档里,而很多时候文档名也并不是ISA,而是Instruction Set Manual或者Instruction Specification等等,再加上这篇文档通常篇幅最长最为人关注的还是指令集部分。所以,我们经常会叫某架构的ISA文档为某架构的指令集文档。

但不管怎么称呼,一个架构首先需要定义的是ISA,包含Architecture(处理器结构,模块划分,data path,寄存器,内存,pipeline等)和Instruction Set(指令定义,使用的说明,约束等)。而这两者是相辅相承不大可能独立存在的。 (RISCV比较特殊,因为它定义基本指令集,而依架构而变的部分多依赖于自己扩展,这里提一下不展开了)

尤其指令集的定义是依赖架构定义的。

例如,TI的C64+ DSP是分簇式的,每一簇多个FU共用一个general register file。而CEVA DSP则是各个FU(GCU, PCU, DAAU, etc)有自己专有的register file。显然,TI DSP我们不需要设计指令进行FU之间的register transfer,但需要考虑簇与簇之间的register transfer。而CEVA DSP则需要定义指令进行不同register file之间的transfer。

反过来指令集的定义也会影响架构定义。

还是以TI举例,TI C64+ DSP一簇有4个FU对应一个32-bits general register file,那么4个FU可能需要同时写这个register file,并且.L, .M, .S FU都可以做 32-bits op 32-bits = 64-bits运算,所以4个FU需要8个读,7-8个写,如果只有一个register file,显然连线非常复杂。但因为register是32-bits,实际上每次写64-bits都会写入两个连续的register。

于是register可以变成下面这样,我们把一个register file分成odd和even两个register file,把每个FU的dst也分成odd和even,这样单个register file的写口就少了很多。read也是类似的,但这样又反过来使指令的读受到了限制,比如一cycle内并发的不同指令总共只能有4个对一个寄存器的读操作,显然也是因为8个读口分别在odd, even寄存器上的原因。

PS: TI C64+ DSP的register file没有上述这么简单,我只是抽取其中一部分来说明,事实上不同FU的策略也有不同,还要考虑不同簇间register file的cross path等。


指令集就是人有30多颗牙齿

200多块骨骼

一个肛门

这些通过进化变味时代的标准

指令集这是不断地进化

进化也是需要时间的

架构可以理解为不同的国家

社会形态,法律,制度等

两个是共同进化的


推荐阅读:
相关文章