从零到单周期CPU
从零到单周期 CPU
CPU 的设计就是从一套指令系统规范到一个数字逻辑电路的过程。这个数字逻辑电路包括组合逻辑电路和数字逻辑电路,数据在这个电路上流转,我们称这些逻辑电路为数据通路。为了控制数据通路的流向,我们必须要有这些通路的“交通信号”,这个“交通信号”被称为“控制逻辑”。一个 CPU 从宏观上来说由数据通路和控制逻辑组成。本文使用的指令系统是 MIPS32 指令系统的一个子集。
单周期 CPU 的数据通路设计
我们以一些指令作为例子描述数据通路应该怎样组成:
ADDU 指令
汇编格式:ADDU rd, rs, rt
功能描述:将寄存器 rs 的值与寄存器 rt 的值相加,结果写入 rd 寄存器中。
操作定义:GPR[rd] ← GPR[rs] + GPR[rt]
取指
将 pc(程序计数器,控制指令的位置)进行虚实地址转换,得到指令在内存的物理地址。
PC
PC 将送到虚实地址转换部件。
MIPS32 指令中指令的宽度为 32bit,因此我们用一组 32 位的触发器来存放 PC。
PC 的输入有两个,一个是复位值 0xBFC00000(MIPS 指令系统规范定义的),另一个是执行完一条指令后的下一条指令:PC+4(4 的来源是因为按字存取,一字(word)为四字节(byte))。32 位 CPU 的指令长度是 32,所以理解成按一条指令的长度存取也可以。也可以理解成 PC+1(字)。
虚实地址转换部件
被送到虚实地址转换部件上的 PC 进行地址转换。
任何时候 CPU 上运行的程序中出现的地址都是虚地址,而 CPU 本身访问内存、I/O 所用的地址都是物理地址。
在实现TLB MMU之前,我们的 CPU 都将采用 固定映射 的地址映射机制,即将虚地址 kseg0 和 kesg1 (分别是 0x80000000 ~ 0x9FFFFFFF 与 0x00000000 ~ 0x1FFFFFFF) 映射至 物理地址 (0x00000000 ~ 1FFFFFFF)。其余三个段的虚地址等于物理地址。
指令 RAM
得到 PC 的物理地址后将该地址送往内存(即指令 RAM)。
在单周期 CPU 中,我们只能使用异步读 RAM(当拍请求当拍得到数据)、同步写 RAM(第一拍请求下一拍得到数据)来实现指令 RAM(和数据 RAM)。
译码
分析指令,得到指令的行为。
执行
寄存器堆
根据指令的行为,我们需要一个寄存器组,根据 MIPS32 规范定义,这个寄存器组有 32 项,每项 32 位。
从 ADDU 指令的操作定义中我们知道,为了在一个周期内能完成 ADDU 指令,这个寄存器至少需要两个读端口和一个写端口。
加法器
为了实现运算,这个操作需要一个加法器,这个加法器接受两个 32 位的输入 src1、src2,输出一个 32 位的结果 result。
ADDIU 指令
汇编格式:ADDIU rd, rs,imm
功能描述:将寄存器 rs 的值与符号扩展至 32 位的立即数(imm,在指令码中被直接给出)相加,结果写入 rd 寄存器中。
操作定义:GPR[rd] ← GPR[rs] + sign_extend(imm)
ADDIU 和 ADDU 指令高度相似,因此我们需要改变的只有:
加法器
第二个输入前引入 二选一 部件,输入 寄存器堆读端口 2 和 指令码的一部分,选择后输出到加法器的第二个输入 src2。这个 二选一 部件还需要一个选择信号,这一部分交给我们的 控制逻辑 来管理。
SUBU 指令
汇编格式:SUBU rd, rs, rt
功能描述:将寄存器 rs 的值与寄存器 rt 的值相减,结果写入 rd 寄存器中。
操作定义:GPR[rd] ← GPR[rs] - GPR[rt]
SUBU 和 ADDU 指令同样高度相似。
加法器
第二个输入前再引入一个 二选一 部件,选择减法。
LW 指令
汇编格式:LW rt, offset(base)
功能描述:将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存(访问内存)的虚地址。(每次存取一个字,因此地址必须是 4 的倍数,否则触发例外)
操作定义:vAddr ← GPR[base] + sign_extend(offset)
(pAddr, CCA) ← AddressTranslation(vAddr, DATA, LOAD)
memword ← LoadMemory(CCA, WORD, pAddr, vAddr, DATA)
- 得到虚地址:ADDIU vAddr, base, offset
- 得到物理地址
- 访存
值得注意的是,此处转换后的访存物理地址需要和指令分开,因此用的是一个单独的虚实地址转换部件。
数据 RAM 和指令 RAM 设计上大致相同。
寄存器堆
之前接收加法器的结果,现在又要接收数据 RAM 的输出,因此又需要一个 二选一 部件。
SW 指令
汇编格式:SW rt, offset(base)
功能描述:将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存(访问内存)的虚地址。(每次存取一个字,因此地址必须是 4 的倍数,否则触发例外)
操作定义:vAddr ← GPR[base] + sign_extend(offset)
(pAddr, CCA) ← AddressTranslation(vAddr, DATA, LOAD)
dataword ← GPR[rt]
StoreMemory(CCA, WORD, dataword, pAddr, vAddr, DATA)
LW 读 RAM 写寄存器,SW 读寄存器写 RAM
寄存器堆
之前接收加法器的结果,数据 RAM 的输出,现在又加一个 RAM 的写端口。
BEQ 和 BNE 指令
汇编格式:BEQ rs, rt, offset
功能描述:如果 rs == rt 则转移,否则顺序执行。转移目标由立即数 offset 左移两位并进行符号拓展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
操作定义:
I. condition ← GPR[rs] = GPR[rt]
target_offset ← sign_extend(offset||00)
I+1. if condition then
PC ← PC + target_offset
endif
汇编格式:BNE rs, rt, offset
功能描述:如果 rs ≠ rt 则转移,否则顺序执行。转移目标由立即数 offset 左移两位并进行符号拓展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
操作定义:
I. condition ← GPR[rs] ≠ GPR[rt]
target_offset ← sign_extend(offset||00)
I+1. if condition then
PC ← PC + target_offset
endif
在加入了两条跳转指令后,PC 的更新也有了两种情况:PC+4 与 PC + target_offset。
PC
PC 前加入一个二选一部件。
JAL 指令
汇编格式:JAL target
功能描述:无条件跳转,跳转目标为分支指令对应的延迟槽指令的 PC 的最高四位与立即数 instr_index 左移两位后的值拼接得到。同时将 PC+4 + 4 给 31 号寄存器中。
操作定义:
I. FPR[31] ← PC +8
I+1: PC ← PC[31:28] || instr_index || 00
JAL 指令与函数调用有关,跳转到函数对应的地址时为了不丢失当前的 PC 信息,因此需要存储下一条 PC 的地址。为了实现 PC + 8:
PC
PC 改为 三选一 ,新增的 in2 输入为拼接后的结果。
ALU
in0 由原来的只接入寄存器堆改为 二选一 :寄存器堆和PC
in1 有原来的 二选一 改为 三选一:加入一个常数 8
JR 指令
汇编格式:JR rs
功能描述:无条件跳转,跳转目标为寄存器 rs 中的值。
操作定义:
I. temp ← GPR[rs]
I+1: PC ← temp
分成两步是因为 I 操作在一个周期的后半部分,而 I+1 这个操作需要在一个周期的前半部分。
很显然,这条指令是用来和 JAL 指令配合来完成函数调用的。
PC
PC 改为 四选一 in3 来自通用寄存器
SLT 和 SLTU 指令
汇编格式:SLT rd, rs, rt
功能描述:将寄存器 rs 的值和寄存器 rt 中的值进行有符号数比较,如果 rs 中的值小,则寄存器 rd 置 1,否则置 0
操作定义:
if GPR[rs] < GPR[rt] then
GPR[rd] ← 1
else
GPR[rd] ← 0
endif
汇编格式:SLTU rd, rs, rt
功能描述:将寄存器 rs 的值和寄存器 rt 中的值进行无符号数比较,如果 rs 中的值小,则寄存器 rd 置 1,否则置 0
操作定义:
if (signed)GPR[rs] < (signed)GPR[rt] then
GPR[rd] ← 1
else
GPR[rd] ← 0
endif
ALU
ALU 中加入比较器功能。
SLL、SRL 和 SRA 指令
ALU
ALU 中加入移位功能。
LUI、AND、OR、XOR 和 NOR 指令
ALU
ALU 中进行加入位运算。
单周期 CPU 的控制信号生成
多选一部件:
nextPC 的四选一:PC+4, PC+(offset), PC+(instr_index), 寄存器堆
指令 RAM 的片选信号:暂时恒为 1
指令 RAM 的写使能信号:暂时恒为 0
ALU 的源操作数 src1 的三选一:寄存器堆、PC、指令码
ALU 的源操作数 src2 的三选一:寄存器堆、指令码、常值 8
ALU 内部的多路选择器:对应指令
数据 RAM 的片选信号:暂时恒为 1
数据 RAM 的写使能信号:暂时恒为 1
通用寄存器堆写地址的三选一:rd, rt, 常值 31
通用寄存器堆写数据的二选一:ALU 的结果,load 指令的返回值(待添加)
单周期 CPU 的复位
复位就是初始化。复位信号包括同步复位和异步复位,本文中只讨论同步复位的情况。
复位信号有效期间不对外发起第一条指令的取值请求。