P7-CPU设计文档

本文最后更新于 2024年12月2日 晚上

P7-CPU设计文档

流水线架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
- mips.v
- TC0 # 计时器0
- TC1 # 计时器1
- BRIDGE # 系统桥
- CPU.v # 单周期CPU的封装模块
- IF #取指阶段
- pc
- IF_ID #IF与ID之间流水寄存器
- ID #译码阶段
- ID_CTRL #采用分布式译码
- GRF # 寄存器堆
- EXT # 立即数扩展
- CMP # 比较2个数
- NPC # 为B类/J计算下条地址
- ID_EX #ID与EX之间的寄存器
- EX #执行阶段
- EX_CTRL #采用分布式译码
- ALU # 多功能计算模块
- MULT_DIV # 乘除模块
- EX_MEM #EX与MEM之间的寄存器
- MEM #存储阶段
- MEM_CTRL #采用分布式译码
- MEM_EXT # MEM输出数据扩展位数
- MEM_WB #MEM与WB之间的寄存器
- HAZARD_CTRL #冒险控制模块
- CP0 #协处理器

IF

顶层

Instruction Fetch阶段,从指令寄存器中读取指令

端口 In/Out? 位宽 功能
clk in 时钟信号
reset in 重置信号
req in 中断请求信号
enablePC in 使能信号
NPC in [31:0] PC地址输入
ID_OP in [3:0] ID区处理指令分支类型
IF_PC out [31:0] 输出PC地址
IF_BD out IF区当前指令是否为延迟槽指令
IF_ExcCode out [4:0] IF区异常码

PC部件

端口 In/Out? 位宽 功能
clk in 时钟信号
reset in 重置信号
req in 中断请求信号
enable in 使能信号
NPC in [31:0] PC地址输入
PC out [31:0] 输出PC地址
PC部件处理逻辑说明

信号优先级:reset > req > enable

1
2
3
4
5
6
7
8
9
10
11
always @(posedge clk)begin
if (reset) begin
reg_pc<=32'h3000; // PC重置
end
else if (req)begin
reg_pc <= 32'h4180; // 跳转至32'H4180,处理异常逻辑代码
end
else if (enable) begin
reg_pc<=NPC;
end
end

IF区IF_BD信号逻辑说明

IF_BD信号用于指定当前IF区指令是否为延迟槽指令;

根据ID_OP信号决定:

1
assign IF_BD = (ID_OP != `ID_NOJUMP) ? 1 : 0;
  • 若ID区指令为跳转指令(branch, jal, jr, beq, bne, ...),IF_BD置1
  • 反之,IF_BD置0

依次经过IF_ID,ID_EX,EX_MEM间流水寄存器,直到PC0,PC0根据该信号决定eret跳转地址(即EPC)

1
EPC <= (BD_in == 1) ? VPC - 32'D4 : VPC;
  • 若VPC(受害PC)为延迟槽指令,则EPC设置为该指令的上一条指令地址
  • 若VPC(受害PC)不是延迟槽指令,则EPC设置为该指令地址

注:若在4180H处理异常逻辑代码中不修改EPC,直接使用eret指令会导致死循环

IF_ID

在时钟上升沿将IF_PC,IF_instr的值传递给ID_PC,ID_instr

端口 In/Out? 位宽 功能
clk in 时钟信号
reset in 重置信号
req in 中断请求信号
flush in 冲洗信号
enable in 使能信号
IF_PC in [31:0] IF传入PC地址
IF_instr in [31:0] IF传入指令
IF_ExcCode in [4:0] IF区异常码
IF_BD in IF区延迟槽指令信号
ID_PC out [31:0] ID接收PC地址
ID_instr out [31:0] ID接收指令
ID_ExcCode out [4:0] ID接收异常码
ID_BD ID接收延迟槽指令信号

优先级:reset > req > enable/flush

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
if (reset)begin
ID_PC <= 32'h3000;
ID_instr <= 32'h0;
ID_ExcCode = 5'b0;
ID_BD = 1'b0;
end
else if (req)begin
ID_PC <= 32'h4180; // 异常处理程序入口地址
ID_instr <= 32'b0; // nop
ID_ExcCode <= 5'b0;
ID_BD <= 1'b0;
end
else if (enable)begin
if (flush)begin
ID_PC <= 32'h3000;
ID_instr <= 32'h0;
ID_ExcCode <= 5'b0;
ID_BD <= 1'b0;
end
else begin
ID_PC <= IF_PC;
ID_instr <= IF_instr;
ID_ExcCode <= IF_ExcCode;
ID_BD <= IF_BD;
end
end

ID

Instruction Decode阶段

顶层

端口 In/Out? 位宽 功能
clk in
reset in
IF/ID输入
IF_PC in [31:0] IF区的PC,用于正常的地址+4操作
ID_PC in [31:0] ID区的PC
ID_instr in [31:0] ID区的指令
ID_RD1_forward in [31:0] 转发的Data1
ID_RD2_forward in [31:0] 转发的Data2
ID_ExcCode in [4:0] ID区的异常码
WB输入
WB_WD in [31:0] 写入数据,来自于WB阶段
WB_A3 in [31:0] 写入寄存器地址,来自于WB阶段
WB_PC in [31:0] 写入数据对应PC地址,传递给\(display语句,作为显示,来自于WB阶段 | | **ID输出** | | | | | ID_RD1 | out | [31:0] | ID输出rs寄存器读出值 | | ID_RD2 | out | [31:0] | ID输出rt寄存器读出值 | | ID_IMM32 | out | [31:0] | ID输出经过位扩展的立即数 | | ID_A3 | out | [4:0] | ID阶段的A3,向后传递用 | | ID_WD | out | [31:0] | ID阶段的写入数据,向后传递 | | NPC | out | [31:0] | ID阶段(内部NPC模块)计算的下一个地址 | | ID_A1_USE | out | [1:0] | ID阶段rs寄存器的\)T_{USE}$
ID_A2_USE out [1:0] ID阶段rt寄存器的\(T_{USE}\)
ID_MD out ID区当前是否在处理乘除相关指令
ID_EX_ExcCode out [4:0] ID区处理后的异常码
ID_OP out ID区指令的分支类型
IF_ID_FLUSH out 对IF_ID间流水寄存器的冲洗信号

EXT部件

立即数扩展

端口 In/Out? 位宽 功能
imm16 in [15:0] 输入的16位立即数
ExtControl in 决定零扩展还是符号扩展
imm32 out [31:0] 输出的为扩展后的32位立即数

CMP部件

判断两个输入(从寄存器取出来的两个值)是否相等,输出zero,用于处理beq信号通路

端口 In/Out? 位宽 功能
A in [31:0] 输入数据,接收的是转发的Data1(RD1_forward)
B in [31:0] 输入数据,接收的是转发的Data2(RD2_forward)
CMPControl in [3:0] CMP部件控制信号(选择比较方式)
zero out 若相等则输出1,否则输出0

CMPControl信号表

指令 CMPControl
cmpBeq 4'b0000
cmpBgez 4'b0001
cmpBgtz 4'b0010
cmpBlez 4'b0011
cmpBltz 4'b0100
cmpBne 4'b0101
bnumeq 4'b1000

NPC部件

计算下一个PC地址

端口 In/Out? 位宽 功能
IF_PC in [31:0] IF输出的PC
ID_PC in [31:0]
ID_imm26 in [25:0] Jal指令中[25:0]位,指定跳转的绝对地址
imm32 in [31:0] 经过EXT扩展的立即数
Jr_Reg_Data in [31:0] Jr指定的寄存器的值
EPC_out in [31:0] CP0传递的跳转指令
Branch in Branch信号(beq激活)
Jal in Jal信号(jal激活)
Jr in Jr信号(jr激活)
Eret in Eret信号(eret激活)
NPC out [31:0] 下一个PC地址
跳转地址表
指令 跳转地址
Branch类(beq,bne) \(ID\_PC+4+signed(imm32 << 2)\)
Jal \((ID\_PC+4)_{31:28}||ID_imm26||2'b0\)
Jr \(Jr\_Reg\_Data\)
Eret \(EPC\_out\)
default \(IF_PC+4\)

Control部件(共用)

控制信号生成部件,这里我们采用的是分布式译码,这里展示的共用Control部件在ID阶段被使用的端口

端口 In/Out? 位宽 功能
instr in [31:0] 输入的指令
zero in ID_RD1_forward与ID_RD2_forward是否相等
Branch out Branch信号(beq激活)
Jal out Jal信号(jal激活)
Jr out Jr信号(jr激活)
Eret out Eret信号(eret激活)
ExtControl out 控制ext部件的信号
Sel_ID_WD out 与jal相关,若执行jal指令则为1,该信号为1时将Write Data(写入寄存器)指定为ID_PC+8
ID_A3 out [4:0] 解码阶段输出的写入寄存器地址
ID_A1_USE out [1:0] rs的\(T_{USE}\)
ID_A2_USE out [1:0] rt的\(T_{USE}\)
CMPControl out [3:0] CMP部件控制信号(选择比较方式)
ID_MD out ID区当前是否在处理乘除相关指令
ID_OP out [3:0] ID区当前指令分支类型
ri out 未知指令异常信号
SYSCALL out 系统调用指令信号

ID控制信号表

指令/信号 ExtControl ID_A3
ori 1(立即数零扩展) rt
add \ rd
sub \ rd
lw 0(立即数符号扩展) rt
sw 0(立即数符号扩展) $0
beq 0(立即数符号扩展) $0
lui 0(立即数符号扩展)(其实随意) rt
jal \ $31
jr \ \
swc \ rd
bonall 0(立即数符号扩展) 31
lh 0 rt
sh 0 \
lb 0 rt
sb 0 \
and \ rd
or \ rd
slt \ rd
sltu \ rd
addi 0 rt
andi 0 rt
mult \ $0
multu \ $0
div \ $0
divu \ $0
mflo \ rd
mfhi \ rd
mtlo \ $0
mthi \ $0
mfc0 \ rt

其余信号:

  • \(beq/bne\rightarrow Branch\)

  • \(jal\rightarrow Sel\_ID\_WD\)

  • \(jal\rightarrow Jal\)

  • \(jr\rightarrow Jr\)

  • \(eret\rightarrow Eret\)

  • \(mult/multu/div/divu/mfhi/mflo/mthi/mtlo(8)\rightarrow ID\_MD\)

  • \(branch/jal/jr\rightarrow ID\_OP=JUMP,else\rightarrow NOJUMP\)

  • \(syscall\rightarrow SYSCALL\)

\(T_{USE}\)

ID_A1_USE ID_A2_USE
cal_r 1 1
cal_i 1 3
load 1 3
store 1 2
cal_md 1 1
load_md 3 3
store_md 1 3
branch 0 0
cal_jal 3 3
cal_jr 0 3
P7新增指令(未分类)
eret 3 3
mfc0 3 3
mtc0 3 2
syscall 3 3

GRF部件

32个32bit寄存器组成的寄存器堆

端口 In/Out? 位宽 功能
clk in
reset in
A1 in [4:0] A1读出寄存器地址
A2 in [4:0] A2读出寄存器地址
A3 in [4:0] A3写入寄存器地址
WD in [31:0] 写入数据
PC in [31:0] 当前PC($display用)
RD1 out [31:0] A1寄存器读出值
RD2 out [31:0] A2寄存器读出值

ID_EX

端口 In/Out? 位宽 功能
clk in
reset in
enable in 使能信号
flush in 冲洗信号,和reset作用相同
ID_PC in [31:0]
ID_instr in [31:0]
ID_RD1 in [31:0]
ID_RD2 in [31:0]
ID_imm32 in [31:0]
ID_A3 in [4:0]
ID_WD in [31:0]
ID_BD in ID区branch delay信号
ID_EX_ExcCode in [4:0] ID区异常码
EX_PC out [31:0]
EX_instr out [31:0]
EX_RD1 out [31:0]
EX_RD2 out [31:0]
EX_imm32 out [31:0]
EX_A3 out [4:0]
EX_WD out [31:0]
EX_BD out EX区接收branch delay信号
EX_ExcCode out [4:0] EX区接收异常码

EX

顶层

端口 In/Out? 位宽 功能
clk in
reset in
EX_instr in [31:0] EX阶段的指令
EX_imm32 in [31:0] 32位扩展的立即数
EX_WD in [31:0] EX阶段接收的写入寄存器堆的数据
EX_RD1_forward in [31:0] 接收hazard ctrl部件向EX阶段传递的转发数据寄存器A1值
EX_RD2_forward in [31:0] 接收hazard ctrl部件向EX阶段传递的转发数据寄存器A2值
EX_ExcCode in [4:0] EX接收区异常码
EX_MEM_RES out [31:0] 传递ALU计算结果
EX_MEM_WD out [31:0] 传递给EX_MEM流水寄存器的Write Data
EX_MEM_RD2 out [31:0] 传递给EX_MEM流水寄存器的Read Data2
EX_NEW out [1:0] EX阶段的\(T_{NEW}\)
MULT_DIV_BUSY out
MULT_DIV_START out
EX_MEM_ExcCode out [4:0]

MULT_DIV部件

端口 In/Out? 位宽 功能
clk in 时钟信号
reset in 重制信号
A in [31:0] 计算数A
B in [31:0] 计算数B
start in 有效一个时钟周期,启动信号
MULT_DIV_OP in [2:0] 乘除模块计算方式
MFHI in mfhi信号
MFLO in mflo信号
busy out 输出延迟信号
HI out [31:0] $hi值
LO out [31:0] $lo值

乘除槽相关信号表

指令/信号 MULT_DIV_OP MULT_DIV_START
mult mult | 1 | | multu |multu 1
div div | 1 | | divu |divu 1

ALU部件

端口 In/Out? 位宽 功能
SrcA in [31:0] 操作数A
SrcB in [31:0] 操作数B
ALUOp in [3:0] 计算方式
ALURes out [31:0] ALU计算结果
overflow out 是否溢出

Control部件(共用)

端口 In/Out? 位宽 功能
instr in [31:0]
ALUOp out [3:0] 选择ALU操作方式
ALU_A_Sel out
ALU_B_Sel out 选择32位立即数或者寄存器rt的值
WD_Sel out 选择Write Data来源(1:ID阶段的PC+8,0:ALURes)
EX_NEW out 当前EX阶段\(T_{USE}\)
MULT_DIV_OP out 乘除模块计算方式
MULT_DIV _START out 乘除模块开始信号
MTHI out mthi信号,下同理
MTLO out
MFHI out
MFLO out
MTC0 out
LOAD out
STORE out

EX控制信号表

指令/信号 ALUOp ALU_B_Sel WD_Sel
ori aluOr | 1(选择立即数) | 0(Write Data选择aluRes) | | add |aluAdd 0(选择rt寄存器) 0
sub aluSub | 0(选择rt寄存器) | 0 | | beq | \ | \ | \ | | lw |aluAdd 1(选择立即数) 0
sw aluAdd | 1(选择立即数) | 0 | | lh |aluAdd 1 0
sh aluAdd | 1 | 0 | | lb |aluAdd 1 0
sb aluAdd | 1 | 0 | | lui |aluLui 1(选择立即数) 0
jal \ \ 1(Write Data选择ID传递值)
jr \ \ \
and aluAnd | 0(选择rt寄存器) | 0 | | or |aluOr 0(选择rt寄存器) 0
slt aluSlt | 0 | 0 | | sltu |aluSltu 0 0
addi aluAdd | 1 | 0 | | andi |aluAnd 1 0
mult \ \ 0
mflo \ \ \
mfhi \ \ \

EX\(T_{NEW}\)

EX_NEW
cal_r 1
cal_i 1
load 2
store 0
cal_md 0
load_md 1
store_md 0
cal_jal 0
cal_jr 0
branch 0
P7新增指令(未分类)
mfc0 2
mtc0 0
eret 0
syscall 0

EX_MEM

端口 In/Out? 位宽 功能
clk in
reset in
flush in
req in
EX_PC in [31:0] EX阶段PC地址
EX_instr in [31:0] EX阶段指令
EX_A3 out [4:0] EX阶段传递的A3
EX_WD out [31:0] EX阶段Write Data
EX_RES out [31:0] EX阶段ALURes
EX_RD2 out [31:0] EX阶段Read Data2
EX_BD
MEM_PC out [31:0] MEM阶段PC地址
MEM_instr out [31:0] MEM阶段指令
MEM_A3 out [4:0]
MEM_WD out [31:0]
MEM_RES out [31:0]
MEM_RD2 out [31:0]
MEM_BD out
MEM_ExcCode out [4:0]

MEM

顶层

端口 In/Out? 位宽 功能
clk in
reset in
req in
MEM_PC in [31:0]
MEM_instr in [31:0]
MEM_WD in [31:0]
MEM_RES in [31:0]
MEM_RD2_forward in [31:0] WB转发的Read Data2
MEM_A3 in [4:0] MEM传递的A3寄存器地址
RD in [31:0] 从Memory中读出的数据
MEM_ExcCode in [4:0]
CP0_out in [31:0] CP0读出数据
MEM_WB_A3 out [4:0] MEM区传递接收写入数据的A3寄存器,传递至WB区
MEM_WB_WD out [31:0]
MEM_A2_NEW out [1:0] MEM\(T_{NEW}\)
MEM_BYTE_EN out [3:0] 写入MEM数据的按字节使能信号
MEM_WRITE_DATA out [31:0] 写入MEM,按字节重新排序的数据
MEM_DATA_ADDR out [31:0] 写入或读出的Memory地址
MEM_INST_ADDR out [31:0] 当load/store指令对应的PC地址
MEM_WB_ExcCode out [4:0]
CP0_enable out CP0写入数据信号
mfc0_rd out [4:0] mfc0/mtc0指定的寄存器rd
EXL_clr out EXL清空信号,由eret指令发出

MEMControl部件(共用)

端口 In/Out? 位宽 功能
instr in
MEM_WE out 选择是否写入Memory
MEM_Sel out 选择是否将Memory读出值向后传递(1:yes)
MEM_A2_NEW out MEM区\(T_{NEW}\)
MEM_PART out [1:0] 选择存入/读取Word,Half或者Byte
MEM_EXT_Control out [2:0] MEM_EXT部件控制信号
CP0_Sel out 读出数据来源选择CP0(由mfc0发出)
mfc0_rd out [4:0] mfc0/mtc0指定,输出指令对应的rd
EXL_clr out EXL清空信号,由eret指令发出

MEM信号及\(T_{NEW}\)

指令/信号 MEM_WE MEM_Sel MEM_A2_NEW MEM_PART MEM_EXT_Control
sw 1 0 0 memWord 3'bz
sh 1 0 0 memHalf 3'bz
sb 1 0 0 memByte 3'bz
lw 0 1 1 memWord |nonExt
lh 0 1 1 memHalf |signedHalfExt
lb 0 1 1 memByte |signedByteExt
else 0 0 0 none 3'bz

MEM_WB

端口 In/Out? 位宽 功能
clk in
reset in
req in
MEM_PC in [31;0]
MEM_instr in [31:0]
MEM_A3 in [4:0]
MEM_WD in [31:0]
WB_PC out [31:0]
WB_instr out [31:0]
WB_A3 out [4:0]
WB_WD out [31:0]

HAZARD_CTRL

端口 In/Out? 位宽 功能
clk in
reset in
ID阶段
ID_A1 in [4:0] ID阶段正在使用的A1寄存器
ID_A2 in [4:0] ID阶段正在使用的A2寄存器
ID_RD1 in [31:0] ID阶段寄存器堆读出的A1对应值
ID_RD2 in [31:0] ID阶段寄存器堆读出的A2对应值
ID_A1_USE in [1:0] \(T_{USE}\)
ID_A2_USE in [1:0] \(T_{USE}\)
ID_MD in ID区处理指令是否与乘除相关
EX阶段
EX_A1 in [4:0]
EX_A2 in [4:0]
EX_RD1 in [31:0] IE阶段A2对应值,由ID区的转发值得来
EX_RD2 in [31:0] IE阶段A2对应值,由ID区的转发值得来
EX_A1_USE in [1:0] \(T_{USE}\)
EX_A2_USE in [1:0] \(T_{USE}\)
EX_A3 in [4:0] EX传递的A3寄存器(rd)
EX_WD in [31:0] EX传递的Write Data
MULT_DIV_BUSY in 乘除模块忙碌信号
MULT_DIV_START in 乘除模块开始信号
MEM阶段
MEM_A2 in [4:0] MEM正在使用的A2
MEM_RD2 in [31:0] MEM的Read Data2,由EX传递而来
MEM_A2_NEW in [1:0] MEM的\(T_{NEW}\)
MEM_A3 in [4:0] MEM传递A3
MEM_WD in [31:0] MEM传递的Write Data
WB
WB_A3 in [4:0]
WB_WD in [31:0]
转发FORWARD
ID_RD1_forward out [31:0]
ID_RD2_forward out [31:0]
EX_RD1_forward out [31:0]
EX_RD2_forward out [31:0]
MEM_RD2_forward out [31:0]
暂停信号STALL
Enable_PC out PC使能信号
Enable_IF_ID out IF_ID流水寄存器使能信号
Enable_ID_EX out ID_EX流水寄存器使能信号
Flush_ID_EX out ID_EX流水寄存器刷新信号
Flush_EX_MEM out EX_MEM流水寄存器刷新信号

CPU

端口

端口 In/Out? 位宽 功能
clk in 时钟信号
reset in 同步复位信号
HW_Int in [5:0] 用于传递来自计时器和外部的中断信号
F区
i_inst_addr out [31:0] 需要进行取指操作的流水级 PC(一般为 F 级)
i_inst_rdata in [31:0] i_inst_addr 对应的 32 位指令
BRIDGE
m_data_addr out [31:0] BRIDGE待写入地址
m_data_rdata in [31:0] CPU_addr 对应的 32 位数据
m_data_wdata out [31:0] BRIDGE待写入数据
m_data_byteen out [3:0] BRIDGE字节使能信号
MEM区
m_inst_addr out [31:0] M 级 PC
WB区
w_grf_we out GRF 写使能信号
w_grf_addr out [31:0] GRF 中待写入寄存器编号
w_grf_wdata out [31:0] GRF 中待写入数据
w_inst_addr out [31:0] W 级 PC
macroscopic_pc out [31:0] 宏观PC

BRIDGE

端口

端口 In/Out? 位宽 功能
CPU内部传出数据
PR_addr in [31:0] 寄存器内部EX_MEM流水寄存器输出的store地址
PR_WD in [31:0] 寄存器内部EX_MEM流水寄存器输出的store数据
PR_byteen in [31:0] 寄存器字节使能信号
根据DEV_addr
从各部件获取数据
DEV_addr out [31:0] 将PR_addr[X:2]直接输出即可,X由N个设备中地址空间需求最大者决定
DM_RD in [31:0] MEM区DM的读出数据
TC0_RD in [31:0] 计数器0的读出数据
TC1_RD in [31:0] 计数器1的读出数据
对DEV_addr写入
(字节)数据使能信号
DM_byteen out [3:0] 字节使能信号
TC0_enable out TC0写入使能信号
TC1_enable out TC1写入使能信号
INT_byteen out [31:0] 中断发生器字节使能信号
load相关,将写入
寄存器的值传回CPU
PR_RD out [31:0] 输出到WB阶段,写入GRF的数据

地址图

条目 地址或地址范围 备注
数据存储器 0x0000_0000∼0x0000_2FFF
指令存储器 0x0000_3000∼0x0000_6FFF
PC 初始值 0x0000_30000x0000_3000
异常处理程序入口地址 0x0000_41800x0000_4180
计时器 0 寄存器地址 0x0000_7F00∼0x0000_7F0B 计时器 0 的 3 个寄存器
计时器 1 寄存器地址 0x0000_7F10∼0x0000_7F1B 计时器 1 的 3 个寄存器
中断发生器响应地址 0x0000_7F20∼0x0000_7F23

地址匹配方式

  • 设备基地址:分为高位低位
    • 基地址低位:位数由设备占用空间大小决定,也就是偏移地址的位数
    • 基地址高位:Bridge用于译码选择设备

CP0

寄存器

寄存器 编号 功能
SR 12 配置异常的功能。
Cause 13 记录异常发生的原因和情况。
EPC 14 记录异常处理结束后需要返回的 PC。
寄存器 功能域 位域 解释
SR(State Register) IM(Interrupt Mask) 15:10 分别对应六个外部中断,相应位置 1 表示允许中断,置 0 表示禁止中断。这是一个被动的功能,只能通过 mtc0 这个指令修改,通过修改这个功能域,我们可以屏蔽一些中断。
SR(State Register) EXL(Exception Level) 1 任何异常发生时置位,这会强制进入核心态(也就是进入异常处理程序)并禁止中断。
SR(State Register) IE(Interrupt Enable) 0 全局中断使能,该位置 1 表示允许中断,置 0 表示禁止中断。
Cause BD(Branch Delay) 31 当该位置 1 的时候,EPC 指向当前指令的前一条指令(一定为跳转),否则指向当前指令。
Cause IP(Interrupt Pending) 15:10 为 6 位待决的中断位,分别对应 6 个外部中断,相应位置 1 表示有中断,置 0 表示无中断,将会每个周期被修改一次,修改的内容来自计时器和外部中断。
Cause ExcCode 6:2 异常编码,记录当前发生的是什么异常。
EPC - - 记录异常处理结束后需要返回的 PC。

模块接口

端口 方向 位数 解释
clk IN 1 时钟信号。
reset IN 1 复位信号。
enable IN 1 写使能信号。
CP0_addr IN 5 寄存器地址。执行MTC0/MFCO指令时产生
CP0_in IN 32 CP0 写入数据。执行MTC0指令时产生
CP0_out OUT 32 CP0 读出数据。执行MFC0指令时产生,输出数据至 GPR
VPC IN 32 受害 PC。
BD_in IN 1 是否是延迟槽指令。
ExcCode_in IN 5 记录异常类型。
HW_int IN 6 输入中断信号。
EXL_clr IN 1 用来复位 EXL。
EPC_out OUT 32 EPC 的值。
Req OUT 1 进入处理程序请求。
macroscopic_pc OUT [31:0] 宏观PC

异常编码

异常与中断码 助记符与名称 指令与指令类型 描述 检测模块
0 Int (外部中断) 所有指令 中断请求,来源于计时器与外部中断。 \
4 AdEL (取指异常) 所有指令 PC 地址未字对齐。 IF
PC 地址超过 0x3000 ~ 0x6ffc IF
AdEL (取数异常) lw 取数地址未与 4 字节对齐。 MEM
lh 取数地址未与 2 字节对齐。 MEM
lh, lb 取 Timer 寄存器的值。 MEM
load 型指令 计算地址时加法溢出。 EX
load 型指令 取数地址超出 DM、Timer0、Timer1、中断发生器的范围。 MEM
5 AdES (存数异常) sw 存数地址未 4 字节对齐。 MEM
sh 存数地址未 2 字节对齐。 MEM
sh, sb 存 Timer 寄存器的值。 MEM
store 型指令 计算地址加法溢出。 EX
store 型指令 向计时器的 Count 寄存器存值。 MEM
store 型指令 存数地址超出 DM、Timer0、Timer1、中断发生器的范围。 MEM
8 Syscall (系统调用) syscall 系统调用。 ID
10 RI(未知指令) - 未知的指令码。 ID
12 Ov(溢出异常) add, addi, sub 算术溢出。 EX

阻塞矩阵

IF/ID当前指令 ID/EX EX/MEM MEM/WB
指令类型 源寄存器 \(T_{use}\) cal_r
1/rd)
cal_i
(1/rt)
load
(2/rt)
cal_r
(0/rd)
cal_i
(0/rt)
load
(1/rt)
cal_r
(0/rd)
cal_i
(0/rt)
load
(0/rt)
beq rs/rt 0 X X X X
cal_r rs_rt 1 X
cal_i rs 1 X
load rs(base) 1 X
store rs(base) 1 X
store rt 2

暂停实现

使用课程讲解的AT法,在流水线运行期间,ID区提供\(T_{USE}\),EX,MEM区提供\(T_{NEW}\),在冒险控制模块中采用以下判断逻辑:

1
2
3
4
assign STALL =  (ID_A1 == EX_A3 && ID_A1_USE < EX_NEW && EX_A3 != 0)  
|| (ID_A2 == EX_A3 && ID_A2_USE < EX_NEW && EX_A3 != 0)
|| (ID_A1 == MEM_A3 && ID_A1_USE < MEM_A2_NEW && MEM_A3 != 0)
|| (ID_A2 == MEM_A3 && ID_A2_USE < MEM_A2_NEW && MEM_A3 != 0);

STALL信号会控制三个行为:

  1. 暂停IF区的PC模块
  2. 暂停IF_ID间流水寄存器
  3. 刷新ID_EX间流水寄存器(等同于reset)
1
2
3
assign Enable_PC = !STALL;
assign Enable_IF_ID = !STALL;
assign Flush_ID_EX = STALL;

转发实现

转发有五条可能的数据通路:

  1. \(EX\_MEM\rightarrow ID\)
  2. \(MEM\_WB\rightarrow ID\)
  3. \(EX\_MEM\rightarrow EX\)
  4. \(MEM\_WB\rightarrow EX\)
  5. \(MEM\_WB\rightarrow MEM\)

这里以ID区的RD1转发数据逻辑为例:

1
2
3
4
assign ID_RD1_forward = (ID_A1 == 5'b0) ? 0 :
(ID_A1 == MEM_A3) ? MEM_WD :
(ID_A1 == WB_A3) ? WB_WD :
ID_RD1;

寄存器内部转发实现

1
2
3
// 考虑寄存器内部转发
assign RD1 = (A1 == A3 && A1 != 0 && !reset) ? WD : grf[A1];
assign RD2 = (A2 == A3 && A2 != 0 && !reset) ? WD : grf[A2];

测试方案

  1. Python自动生成测试mips文件
  2. Mars运行mips文件,生成正确结果和机器码
  3. iverilog运行CPU文件,生成测试结果
  4. Python比较两份答案

思考题

1、请查阅相关资料,说明鼠标和键盘的输入信号是如何被 CPU 知晓的?

当键盘或者鼠标按下按键时,设备会发出一个中断信号,中断信号经过中断控制器传到CPU,CPU根据不同的中断号执行不同的中断响应程序,然后进行相应的IO操作

2、请思考为什么我们的 CPU 处理中断异常必须是已经指定好的地址?如果你的 CPU 支持用户自定义入口地址,即处理中断异常的程序由用户提供,其还能提供我们所希望的功能吗?如果可以,请说明这样可能会出现什么问题?否则举例说明。(假设用户提供的中断处理程序合法)

统一的CPU处理中断异常地址能够实现软件的兼容.

会影响CPU的处理逻辑

3、为何与外设通信需要 Bridge?

让CPU访问不同外设只需要通过对应的地址,这种操作遵循了"高内聚,低耦合"的原则

4、请阅读官方提供的定时器源代码,阐述两种中断模式的异同,并分别针对每一种模式绘制状态移图。

当计数器倒计数为0时,计数器停止计数,Ctrl寄存器的计数使能自动变为0,并且中断信号时钟保持有效,直到屏蔽中断或重新开始计数

中断模式0

计数器模式1:

当计数器倒计数为0,自动读取PRESENT寄存器的值,然后重新开始倒计数,这种模式下中断信号只会产生一个中断周期

中断模式1

5、倘若中断信号流入的时候,在检测宏观 PC 的一级如果是一条空泡(你的 CPU 该级所有信息均为空)指令,此时会发生什么问题?在此例基础上请思考:在 P7 中,清空流水线产生的空泡指令应该保留原指令的哪些信息?

宏观PC突然变为0x0000_0000

保留原指令的PC信息

6、为什么 jalr 指令为什么不能写成 jalr $31, $31

jalr $31, $31指令的延迟槽内发生异常或者需要响应中断,那么在处理异常结束后会再次执行jalr $31, $31指令,这时的$31值已经被修改,会跳转到不正确的PC地址


P7-CPU设计文档
https://meteor041.git.io/2024/12/02/P7-CPU设计文档/
作者
meteor041
发布于
2024年12月2日
许可协议