前言
本系列文章将梳理《计算机组成原理》这门课的相关知识点,教材使用的是《计算机组成原理:硬件/软件接口》MISP版,原书第五版。本文所属章节为处理器章节,重点内容为单周期数据通路和多周期数据通路。
Ps:流水线章节在这本黑书中有涉及,但因笔者学校本学期的课程安排并未将这部分内容纳入其中,所以本文不涵盖基于流水线的处理器设计。
一. 单周期MISP子集数据通路的实现
1. MISP子集
本章选取9条指令构成MISP核心子集如下:
- R型:add、sub、and、or、slt
- 访存:lw、sw
- 决策:beq、j
2. 一个指令周期概况
一个指令周期,即一条MISP指令执行分为五个阶段:
- IF取指令:从存储器取指令;修改PC指向下一条指令。
- ID译码与读寄存器:分析指令字段,读取一个或两个寄存器。
- EX运算:ALU运算R型指令的结果 / 计算出访存地址 / 计算beq两个源操作数是否相等。
- MEM访存与分支:访存指令向存储进行读和写 / 分支指令完成分支。
- WB写回:R型指令写回rd,I型指令写回rt。
下面给出MISP子集单周期的数据通路图。
3. 各个指令周期的数据通路部件
3.1 取指令周期IF
- 功能:取出指令,执行PC+4。
3.2 译码和读寄存器周期
- 部件:寄存器堆
- 寄存器堆含有32个通用寄存器。
- 输入接口从上到下依次是rs、rt、rd的寄存器的5位编码以及32位的写数据接口。
- 对于输入的寄存器编号,最多两个寄存器用于读取。例如,R型指令和beq指令需要读取两个寄存器,而对于sw指令,只读取一个寄存器。
- 对于输入的寄存器编号,最多一个寄存器用于写。其中,R型写回rd寄存器,lw写到rt寄存器。
- 符号扩展和移位逻辑:
- beq中的地址,访存指令中的16位偏移量需要经过符号扩展到32位。
- beq:需要经过一个移位逻辑,左移两位。
3.3 运算周期EX
- R型指令:ALU执行相应算术运算/逻辑运算,得到结果。
- 访存指令:将基地址和偏移量相加,得到真正的地址。
- 分支指令:将源操作数做减法,判断是否相等。
- 同时,加法器得到符号扩展并左移两位后的PC相对地址,将其与PC+4相加,得到分支目标地址。
3.4 访存与分支周期MEM
- 访存指令向存储器进行读写。
- 分支指令完成分支。
3.5 写回周期WB
- R型指令将结果写回rd寄存器。
- lw指令将结果写入rt寄存器。
- 在单周期实现中,每条指令都只在一个时钟周期内完成。lw使用了五个时间阶段,所以时钟周期取决于lw的执行时长。
- 在多周期实现中,可以缩短时钟周期到1个阶段的长度,一条指令占用多少个阶段,就会执行多少个时钟周期。即虽然CPI=4,5,但是时钟周期缩短了1/5。
二. 单周期控制单元
1. 控制信号总览
- RegDst:写回阶段,是写回rd寄存器还是rt寄存器。0表示rt,1表示rd。
- RegWrite:寄存器写使能信号。
- ALUSrc:ALU的第二个算子来源。从下图数据通路截取中可以看出,ALU的第一算子是固定的,ALU的第二个算子则来源于两个地方,可能是rt,也可能是符号扩展后的立即数。
- Branch:0表示PC+4取代,1表示beq指令的地址取代。
- PCSrc:Branch信号 & ALU的zero输出,两者均为1才将beq目标地址取代PC+4。(这一点图上没有标注出来,可能会造成误解。)
- MemRead:内存读使能信号,1表示内存可读。
- MemWrite:内存写使能信号,1表示将数据端数据写入指定存储单元。
- MemToReg:写入寄存器的数据来源。0表示ALU,1表示内存。
- ALUOp:两位的ALU控制信号,用于与R型指令的funct字段一起形成4位ALU控制信号。
总结来讲,控制信号大致可以分为:分支1个,写回3个(写不写回,从哪里写回,写回到哪里),内存2个(读和写),运算2个(算子来源,执行什么运算)
2. 二级译码—ALU控制单元
ALU的控制由多级译码进行实现。主控制单元发出4位的控制信号,决定ALU要执行什么运算,如add、sub、and等。与此同时,ALUOp根据主控制单元发送的信号和R型指令的funct字段,生成2位的ALU操作码,如下图所示。
- 4位的ALU控制信号:决定ALU最终执行什么运算,是add、sub、and、or等,需要记忆下面两个信号。
- 0010:add
- 0110:sub
- 2位的ALU操作码:主控根据指令的op字段,解码后向ALU控制单元输出一个2位的控制信号ALUOp。
- 00:访存指令。需要ALU执行加法:ALU控制线为0010。
- 01:beq指令。需要ALU执行减法:ALU控制线为0110。
- 10:R型指令。需要ALU根据funct字段进一步确定,映射到add sub and or slt
ALUOp由主控制单元发出的ALUOp和R型指令的funct字段两级共同决定,这种多级译码方式,即控制功能不只是由主控实现,而是要经过ALU控制单元这种中间控制单元的译码方式,有利于提高控制器性能。
下面给出4位ALU控制信号和2位ALUOp的总结表格:
3. 主控制单元详解
3.1 lw指令分析
- 指令案例:
lw $t0, 12($s0)
- 控制信号分析:
- 写回:
- RegDst:0,写回rt寄存器。
- RegWrite:1,寄存器写使能
- MemToReg:1,从内存写回,而不是从ALU写回。
- 内存:
- MemRead:1:需要读取内存
- MemWrite:0,不需要写内存
- PC:
- Branch:0,不需要分支。
- 运算:
- ALUSrc:1,ALU第二个算子选取符号扩展后的立即数。
- ALUOp:00,访存指令
- ALU控制信号:0010,加法指令
- 写回:
3.2 beq指令分析
- 指令案例:
beq $t0, $zero, Loop
- 控制信号分析:
- 写回:
- RegDst:x
- RegWrite:0,不写
- MemToReg:x
- 内存:
- MemRead:0:不需要读取内存
- MemWrite:0,不需要写内存
- PC:
- Branch:1,需要分支。
- 运算:
- ALUSrc:0,ALU第二个算子选取rt字段。
- ALUOp:01,分支指令
- ALU控制信号:0110,sub指令
- 写回:
3.3 R型指令
- R型号指令控制信号分析:
- 写回:
- RegDst:1,写回rd字段。
- RegWrite:1,写回。
- MemToReg:0,从ALU写。
- 内存:
- MemRead:0:不需要读取内存
- MemWrite:0,不需要写内存
- PC:
- Branch:0,不需要分支。
- 运算:
- ALUSrc:0,ALU第二个算子选取rt字段。
- ALUOp:10,R指令
- ALU控制信号:取决于funct字段
- 写回:
3.4 sw指令
- sw指令控制信号分析:
- 写回:
- RegDst:x
- RegWrite:0,不写回。
- MemToReg:x
- 内存:
- MemRead:0:不需要读取内存
- MemWrite:1,不需要写内存
- PC:
- Branch:0,不需要分支。
- 运算:
- ALUSrc:1,ALU第二个算子选取符号扩展后的立即数字段。
- ALUOp:00,访存指令
- ALU控制信号:0010,add指令
- 写回:
3.5 总结
下面给出控制信号表的总结。
3.5 J指令
- 伪直接寻址:
- J指令跳转地址 = PC+4的高4位拼接上28位跳转地址(26位左移两位)
- 硬件设计:
- PC分支板块的最后再加多一个MUX。选择到底是PC+4/分支目标跳转地址的结果,还是Jump指令的跳转地址。 这样就会形成两个多路选择器,第一个选择PC+4 还是分支,第二个为是否Jump。
- J指令的控制信号:多了个Jump信号,其余信号基本用不到,branch信号设置为0。但是注意,写信号用不到就关闭,内存信号用不到也都关闭,其它设置为x即可。
- Jump:0,低有效!
- 写回:
- RegDst:x
- RegWrite:0,不写回。
- MemToReg:x
- 内存:
- MemRead:0:不需要读取内存
- MemWrite:0,不需要写内存
- PC:
- Branch:0,不需要beq分支。
- 运算:
- ALUSrc:x
- ALUOp:xx
三. 多周期数据通路
1. 多周期数据通路的特点
- 时钟周期:将一个指令的执行过程划分为多个阶段,每个阶段占用一个时钟周期。
- 存储器:指令存储器和数据存储器合成一个存储器。
- ALU:ALU和两个加法器合为一个ALU。
- 寄存器:每个功能单元后都增加一个暂存寄存器,直到下个周期才将其内容送入下个功能单元。
- IR:指令寄存器
- MDR:数据缓冲寄存器
- A、B寄存器:从rs和rt从读出的操作数放到A、B两个寄存器中。
- ALUOut:ALU的运算结果。
下面给出多周期实现机制下的数据通路图。
五个周期
- IF:取指
- ID:译码和读寄存器
- EX(BC):执行/地址计算(分支完成)
- MEM(WB):存储器访问(R型指令写回)
- WB:写回
2. 各个周期数据通路详解
RTL语言:Register-Transfer Language
本节将用RTL语言描述每个周期到底做了什么事情。
2.1 取指周期IF
- 根据PC从存储器选取一条指令,放入IR。
IR = Memory[PC];
- 将PC+4写回PC。
PC = PC+4
2.2 译码和读寄存器ID
- 读取rs和rt字段的操作数。
A = Reg[IR[25-21]];
B = Reg[IR[20-16]];
- 如果是beq,计算分支目标地址。因为ALU当前空闲。
ALUOut = PC + (sign-extend(IR[15-0]) << 2)
2.3 执行/地址计算周期EX
由于RTL语言会在考试中考察,这几天RTL语言需要注重记一下。
根据指令类型的不同,执行不同操作:
- R型:
ALUOut = A op B
- 访存指令:
ALUOut = A + sign-extend(IR[15-0])
- 条件分支:
if(A==B) PC=ALUOut;
- 跳转分支:
PC = { PC[31-28],(IR[25-0] << 2)}
2.4 访存周期(MEM)和R型写回周期(WB)
- lw:
MDR= Memory[ALUOut];
- sw:
Memroy[ALUOut] = B;
- R型指令:
Reg[IR[15-11]] = ALUOut;
写操作是发生在时钟周期的后沿时刻。
2.5 LW指令写回周期WB
- lw指令将数据写回寄存器:
Reg[IR[20-16]] = MDR;
2.6 小结
下面给出各类指令在多周期数据通路中的执行情况。
3. 指令视角练习RTL语言
3.1 R型指令—以sub为例
假设汇编代码为:sub $t0,$t1,$t2;
# IF
IR <= Memory[PC];
PC <= PC+4;
# ID
A <= Reg[IR[25-21]];
B <= Reg[IR[20-16]];
ALUOut <= PC + ( sign-extend(IR[15:0]) << 2)
# EX
ALUOut <= A op B
# WB
Reg[IR[15:11]] = ALUOut;
3.2 lw指令
# IF
IR <= Memory[PC];
PC <= PC+4;
# ID
A <= Reg[IR[25-21]];
B <= Reg[IR[20-16]];
ALUOut <= PC + ( sign-extend(IR[15:0]) << 2)
# 前两个周期都是一样的
# EX
ALUOut <= A + sign-extend(IR[15:0]);
# Memory Access
MDR <= Memory[ALUOut];
# WB
Reg[IR[20:16]] = MDR;
3.3 sw指令
# 前两个周期都是一样的。
# EX
ALUOut <= A + sign-extend(IR[15:0]);
# MemoryWrite
Memory[ALUOut] <= B;
3.4 beq指令
# 前两个周期都是一样的
# EX
if(A== B) then PC <= ALUOut;
3.5 J指令
# 前两个周期都是一样的
# EX
PC <= {PC[31:28] , (IR[25:0] >> 2) }
4. 多周期下的CPI
- CPI:每条指令所占用的平均周期数。
- 各指令所占用的周期数:
- lw:5
- sw:4
- R:4
- beq:3
- j:3
例题:某CPU按以上多周期方式执行一段程序,其中load 指令占指令总数的22% ,store指令占11% , R-type 指令占49% , branch指令占16% , jump指令占2% 。假设各类指令每个阶段占用一个时钟周期,求其CPI值是多少?
解答:CPI = 总周期数 / 总指令数 = 0.22 x 5 + 0.11 x4 + 0.49 x 4 + 0.16 x3 + 0.02 x3 = 4.04
四. 多周期数据通路下控制单元的实现
1. 控制信号下完整的数据通路
带有控制信号的完整数据通路如下图所示:
同样的,我们可以将控制信号大致分为:写回、内存、PC、运算。下面我们将粗略展示各个控制信号的功能。
- PC相关:5个
- IorD:存储地址从哪来?0表示PC,1表示ALUOut。前者表示取指令,后者表示取数据。
- IRWrite:指令寄存器IR写使能。1表示将指令写入IR。
- PCWrite:PC写使能。1表示打开。
- PCWriteCond:带条件的PC写使能,Zero输出有效。
- PCSource:2位。
- 00表示将ALU运算结果送入PC。表示PC+4
- 01表示将ALUOut送入PC。表示分支目标地址。
- 10表示将IR低26位左移2位后与PC+4高4位拼接的内容送入PC。
- ALU相关:2个
- ALUSrcA:ALU第一个操作数。0表示来源PC,1表示来源寄存器A。(这是因为多周期数据通路将PC+4的加法器省略了。)
- ALUSrcB:ALU的第二个操作数。2位。
- 00表示来源于B寄存器。
- 01表示常数4。
- 10表示IR的低16位立即数拓展得到(用于lw和sw)。
- 11表示IR的低16位立即数拓展后左移两位得到。
- ALUOp:00加法(访存),01减法(beq),10由funct决定。
- 内存相关:
- MemRead:数据存储器读使能。
- MemWrite:数据存储器写使能。
- 写回相关:
- MemtoReg:写入寄存器的数据来源,为0表示来源于ALUOut,为1表示来源MDR。
- RegWrite:寄存器堆写使能。
- RegDst:写寄存器目标。0表示写入rt,1表示写入rd。
下面给出各个控制信号的功能小结表格。
2. 指令执行各个阶段控制信号分析
2.1 取指阶段
取值阶段:首先需要通过PC读取指令存储器的值,并且放入IR。其次,需要将PC+4写入PC。
- PC相关
- IorD=0
- PCWrite=1
- PCWriteCond=0
- IRWrite=1
- PCSource=00
- ALU相关
- ALUSrcA=0:PC
- ALUSrcB=01:常数4
- ALUOp=00:加法
- 内存相关:
- MemRead=1:需要读取内存
- MemWrite=0:不需要写使能
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.2 译码阶段
译码阶段:IR中的rs字段和rt字段分别放到A寄存器和B寄存器。同时ALU计算分支偏移地址。
- PC相关:不该写别写,该写就打开,其它随意。
- IorD=x
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:(ALU这个阶段没闲着哦!)
- ALUSrcA=0:第一个操作数来自PC
- ALUSrcB=11:符号扩展后左移两位的立即数
- ALUOp=00:加法
- 内存:
- MemRead=0:不需要读取内存
- MemWrite=0:不需要写使能
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.3 执行阶段
执行阶段根据指令类型不同,执行的任务也不同。
2.3.1 访存指令
如果是访存,就是计算偏移地址放入ALUOut。
- PC相关:写使能关闭,其它随意。
- IorD=x
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:
- ALUSrcA=1:寄存器A
- ALUSrcB=10:符号扩展的常数,但是不左移。
- ALUOp=00:加法
- 内存:都关闭
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.3.2 R型指令
如果是R型,就是对运算并将结果放入ALUOut。
- PC相关:写使能关闭,其它随意。
- ALU相关:
- ALUSrcA=1:寄存器A
- ALUSrcB=0:寄存器B
- ALUOp=10:根据funct字段确立。
- 内存:都关闭
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.3.3 分支指令
如果是条件分支地址,就是判断条件并且执行分支,赋值给PC。
- PC相关:
- IorD=x
- PCWrite=0,我们可以看看完整的数据通路图,PC = PCWrite OR (PCWriteCond AND ZERO),所以这里PCWrite应该关掉。
- PCWriteCond=1
- IRWrite=0
- PCSource=01,表示将ALUOut结果送入PC
- ALU相关:
- ALUSrcA=1:寄存器A
- ALUSrcB=0:寄存器B
- ALUOp=01:SUB
- 内存:都关闭
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.3.4 跳转指令
跳转指令负责拼接PC的值,送回PC。
- PC相关:
- IorD=x
- PCWrite=1
- PCWriteCond=0,不是分支
- IRWrite=0
- PCSource=10,表示将跳转地址送回PC
- ALU相关:
- ALUSrcA=1:x
- ALUSrcB=0:xx
- ALUOp=01:xx
- 内存:都关闭
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.4 访存阶段
2.4.1 lw指令
访存阶段,lw将读取数据存储器并将结果放到MDR中。
- PC相关:
- IorD=1
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:
- ALUSrcA=1:x
- ALUSrcB=0:xx
- ALUOp=01:xx
- 内存:
- MemRead:1
- MemWrite:0
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.4.2 sw指令
将寄存器B的内容放入到内存中。
- PC相关:
- IorD=1,表示数据存储器。
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:
- ALUSrcA=1:x
- ALUSrcB=0:xx
- ALUOp=01:xx
- 内存:
- MemRead:0
- MemWrite:1
- 写回相关:寄存器写使能关闭,其它设置为X即可。
2.4.3 R型指令写回
将ALUOut的结果送入到寄存器中。
- PC相关:
- IorD=x,表示数据存储器。
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:
- ALUSrcA=1:x
- ALUSrcB=0:xx
- ALUOp=01:xx
- 内存:
- MemRead:0
- MemWrite:0
- 写回相关:
- RegWrite:1
- MemToReg:0表示从ALU写。
- RegDst:1,写回rd。
2.5 lw指令写回
将MDR中的内容,写到rt字段。
- PC相关:
- IorD=x,表示数据存储器。
- PCWrite=0
- PCWriteCond=0
- IRWrite=0
- PCSource=xx
- ALU相关:
- ALUSrcA=1:x
- ALUSrcB=0:xx
- ALUOp=01:xx
- 内存:
- MemRead:0
- MemWrite:0
- 写回相关:
- RegWrite:1
- MemToReg:1表示从MDR写。
- RegDst:0,写回rt
3. 控制信号实现—有限状态机
多周期控制的实现有两种方法,第一种是有限状态机的方法,第二种是微程序控制器的方法。这里介绍前者。
首先,这里给出有限状态机(FSM)的状态图。
接下来就是画出真值表,化简真值表,设计组合逻辑电路和时序逻辑电路的过程,这部分属于数字逻辑的内容,一般不在这门课考察,这里不多讲述。
至此,处理器章节的内容就结束了,本章重点考察的内容是一条各个阶段执行的具体分析和控制信号。特别地,如果数据通路是多周期的话,会考察使用RTL语言描述各个周期的指令执行过程以及考察写出各个周期的控制信号值。