MIC-1的数据通路与微指令

IJVM与MIC-1

微体系结构层夹在数字逻辑层和指令系统层之间。设计CPU时通常先大致确定指令系统,然后设计微体系结构实现它,或是两者是并行设计的。通常RISC(精简指令集)的很多指令可在单个时钟周期完成。而Intel酷睿的x86指令集属于CISC(复杂指令集),一条指令可能需要多个时钟周期,会被分为多个操作步骤,其控制方式和简单的指令系统有较大区别。

微体系结构层没有太多一般性原理,很多都是特例。所以在学习微体系结构层时,需要预先引入一种具体的指令系统,然后再考虑怎么构建微体系结构层实现指令系统。这里将要引入的指令系统是JVM的一种子集IJVM,其仅包含部分整数指令,并且不包含面向对象特性。IJVM指令通常只有1-2个字段,第1个字段都是操作码(opcode),用于标识指令,有的包含操作数(operand)字段,用于提供额外信息。

虽然JVM通常是虚拟机,即JVM指令的实现不是微体系结构而是C语言程序。但JVM指令系统和实际CPU的指令系统有很大共性,并且也适合用于学习微体系结构,原因是IJVM指令集虽然不大,但其可看作复杂指令,有的指令需分为多个操作步骤执行,对于学习微体系结构更有帮助。

在学习IJVM指令系统、如何用微体系结构实现IJVM指令系统之前,先学习一种具体的微体系结构,称为MIC-1,其将被用于实现IJVM。而在微体系结构中,数据通路又是最重要的部分之一。

 

数据通路的组成

bb166654-c097-4d0b-9867-d7aae1f1c873

ed16b9fa-79ca-491a-be6b-7b594003ba3f

9c750c2a-28df-454e-8eb3-70d9cfcf8f4a

8f95dcd6-d05e-4469-9bcc-fb64237e93ae-1

CPU由不同数量的ALU、寄存器、内部总线、控制单元等组成。数据通路是数据在各部件之间传送的路径,所以其可看成是由ALU、寄存器、总线等复合而成的功能单元,粒度介于CPU和CPU部件之间。上图是MIC-1微体系结构的数据通路,这里分别说明一下其中的部件和信号:

1) ALU:ALU和之前讨论数字逻辑层用的ALU电路一样,左输入A右输入B对应之前ALU的A和B(把之前ALU的电路图贴出来了)。ALU左边的6箭头代表由F0、F1、INVA、ENA、ENB、INC(进位输入)组成的6个信号线,其组合可提供的功能如上图所示。另外ALU还有之前没有的N和Z两个输出,其值取决于ALU输出,N=1表示输出值为负(最高位等于1)Z=1表示输出值是零

2) 寄存器:ALU上面的长方形代表各种寄存器,除MBR是8位的,其他都是32位寄存器;

3) 移位器:用于接收ALU的输出并进行移位计算,其含2根移位器控制信号线,其中1根控制是否执行算数右移1位(右移1位,新最高位和原最高位相同。简称SRA1)计算,另1根控制逻辑左移8位(左移8位,空出来的低8位填0。简称SLL8)计算;

4) C总线:具有32位数据线,用于把移位器的输出写入一或多个寄存器

5) B总线:具有32位数据线,用于传出某一个寄存器的内容;

6) 空心箭头:将该寄存器内容输出到B总线的使能。注意到这些使能同时只能有1个有效,否则有歧义。MAR不连接B总线没有空心箭头,H寄存器是ALU的唯一左输入也没有空心箭头。注意MBR下面多个1个空心箭头,起作用之后会说明;

7) 实心箭头:将C总线数据写入该寄存器的控制信号。MBR不连C总线没有实心箭头;

从这个结构中可以发现,MIC的数据通路有这两大功能:

1) 让数据经“寄存器-B总线-ALU/移位器-C总线-寄存器”的路径传送和执行计算

2) 让数据经“寄存器-内存总线-内存”的路径传送。这里没具体画出这部分;

 

数据通路的时序逻辑

上面提到,数据会在数据通路中按“寄存器-B总线-ALU/移位器-C总线-寄存器”流动,而在一个时钟周期里只有两个“信号”,即依次出现的1个下降沿和1个上升沿(MIC-1的时钟以下降沿开始)。那么如何让数据通路在单个时钟周期里完成这么多个步骤(不考虑用多个周期完成)?

实现这一点的关键在于充分利用组合逻辑的特性和B、C两条总线,进而能够利用这两个边沿划分出更多个的子周期。这里以实现SP寄存器自增1为例,按时间顺序给出一个时钟周期里的各个子周期:

1) 时钟周期开始,电平出现下降沿,此时开始准备控制信号,比如控制SP接入B总线的信号、控制C总线接入SP的信号、让ALU执行B+1的控制信号等。然后等到这些控制信号稳定;

2) 等到B总线在ALU的B端的信号稳定(SP的当前数据);

3) 等到ALU的输出信号稳定;

4) 等到移位器的输出信号稳定;

5) 等到C总线在SP输入端的信号稳定(原SP+1后的数据);

每个子周期的时间应是已知的(工程师会测出来),这才能保证子周期的总时间不超过时钟低电平持续时间,并且还要多预留点时间应对误差。这些子周期除了开始的下降沿,再没有其他信号“通知”每个何时子步骤开始结束,但是只要有足够的时间,就会有稳定正确的原SP+1数据在SP寄存器的输入端,只要等待之后的时钟上升沿到来,新的SP+1数据就会被时钟以边沿触发的方式“打入”SP寄存器(这里回忆一下寄存器是由D触发器构建的,而D触发器是边沿触发的存储部件)。

需要注意到“打入”SP时,SP可被入写时间必须足够短,否则新SP寄存器数据会再一次经过B总线-ALU-C总线进入SP,导致SP可能自增2、自增3。所以硬件工程师必须做严格的时序控制,充分了解ALU、总线等部件的输出延迟。比如说如果控制SP可被入写时间短于B总线传输延迟+ALU输出延迟。实际CPU的设计也是这样,通过这些数据进行调整,确保时序的正确性。

可以猜测上面采用了B、C双总线而不是单总线的原因,可能是单总线难拆分太多的子周期。由于上述数据通路只使用了1个时钟周期,所以称其为单周期数据通路,相应的还有多周期数据通路。单周期数据通路有一个缺点,就是如果要执行复杂操作,又必须在一个时钟周期里完成,当原件的延迟比较大的时候,就要放慢时钟让每个子周期都有更长的时间,这会影响到其他简单操作的性能。

 

数据通路的内存操作

b6b10c4a-6473-487c-96d4-85873f681585

上图没画内存总线的形态,其地址和数据总线都是32位。注意这里的机器字长=MDR位数=内存数据线宽度=存储字长(大多数微体系结构也满足这个等式,但也有例外)。发起内存读写前,需先把内存地址放入相关寄存器,然后在内存控制总线发出读写信号。如果是内存读,内存会把相应的字通过内存总线送入相关寄存器,该数据通路有2种内存通信端口:

1) 32位按字寻址端口:由MAR(内存地址寄存器)MDR(内存数据寄存器)控制。MAR存字地址(其值0,1…k指第k个字),当把2存入MAR然后读内存,将得到内存第2个字(8-11字节),其值保存在MDR;

2) 8位按字节寻址端口:由PC寄存器(程序计数器)控制,其把一个字节读入到MBR(内存缓冲寄存器)的低八位。并且该端口只能读内存而不能写。 PC存放的是字节地址,当把2存入PC然后读内存,将得到内存第2个字节,其值保存到MBR;

两种端口用于操作不同的内存区域,目前阶段只能笼统认为32位端口用于指令系统层数据(用字组织),8位端口用于指令系统层可执行程序(用字节组织),其他存地址的寄存器都用字地址。这两种端口构成了MAR读/MAR写/PC读三类操作,这三类操作有惯用称呼,分别为read/write/fetch

两种端口的位数不同会有些小问题,假设内存按单字节编址,MAR想找第k个32位字怎么办?这只需按上图所示,通过“左移2位”即可实现这种倍数放大。类似的对于MBR(8位),其如何把数据放到32位的B总线数据线上?这需要将8位数据扩展为32位,图中MBR框框的长度短于其他寄存器,但虚线长度和其他寄存器一样,就是为了说明虽然MBR是8位的,但其可输出32位。扩展规则是符号扩展无符号扩展(零扩展),之前讨论过这两种扩展,MBR多出来的1个空心箭头就用于选择扩展方式

最后看内存操作的时序,以read为例。当在某个时钟周期里,内存地址已稳定存储于MAR,内存总线的控制线有稳定的read信号时。在下个时钟即将开始前,内存才会根据其地址线(MAR)和控制线(read)上的信号开始执行这个read操作。然后我们规定MIC-1的内存能够在下个时钟周期上升沿就把数据打入MDR(实际计算机需要很多个时钟周期),还是以read为例,第i周期执行read,第i+1周期的上升沿将送回的数据“打入”MDR,第i+2周期才能让MDR的数据进入ALU运算。最后说明一些重要的时序细节

1) 同一个时钟周期里,不允许C总线内存总线写入同一个寄存器。因为打入寄存器必须非常快,所以没有时间让这2个写入按部就班相继完成。这个操作会使寄存器的数据不可预料;

2) 同一个时钟周期里,允许C总线写入PC/MAR并基于写入后的PC/MAR发起内存操作。因为内存会在时钟周期快结束时执行操作,而C总线写入发生在上升沿,时间间隔足够让PC/MAR稳定;

 

微指令

ce4a6f9f-aace-48db-8942-37e31a998cc0-1

 

所有信号线的值会在每个时钟周期开始时同时确立,用于决定数据通路在该周期的行为,所以也称这组信号为微指令。可以所有这些信号整理成上述格式(共6类信号,29个信号线):

1) 9个C总线写入寄存器的控制信号线;

2) 8个寄存器输出到B总线的使能信号线;

3) 1个MBR寄存器的符号扩展无符号扩展的控制信号线;

3) 6+2个ALU与移位器的控制信号线;

4) 2个内存总线的控制信号线,用于发起read和write;

5) 1个内存总线的控制信号线,用于发起fetch;

然后再来看如何减少这29个信号线的数目,这里注意到9个输出到B总线的寄存器不能同时向B总线输出数据,即这9个使能在同一时刻只能有1个有效。这就适合用一个4-16译码器简化这9个线(输出端的另外7位闲置),这就把原来的9位信号线化简到4位,信号线总数从29减到24。

这24位只能控制一个时钟周期的数据通路,但通常还应该包含一些信息用于决定下个周期的操作。这里再额外加入共12位的ADDR和JAM字段,其用于决定下一次执行哪个微指令。这36位构成了最终的微指令系统。这些指令中有很多个基本的分组,排列这些组的次序的依据主要是CPU内部的布线难度

至此我们还不知道这多出来的12位的具体控制逻辑,这需要在完整的MIC-1微体系结构中讨论。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部