MIPS指令架构CPU设计文档

该博客围绕Verilog实现的流水线CPU展开。介绍了CPU设计方案,包括总体设计、关键模块定义及跳转、转发、暂停等重要机制;给出转发和暂停机制的测试方案及期望输出;还提出多个思考题,如乘除法部件设置原因、按字节访问内存优势等,并给出解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、CPU设计方案综述

(一)总体设计概述

本CPU为Verilog实现的流水线CPU,支持的指令集包含{LB、LBU、LH、LHU、LW、SB、SH、SW、ADD、ADDU、SUB、SUBU、MULT、MULTU、DIV、DIVU SLL、SRL、SRA、SLLV、SRLV、SRAV、AND、OR、XOR、NOR、ADDI、ADDIU、ANDI、ORI、XORI、LUI、SLT、SLTI、SLTIU、SLTU、BEQ、BNE、BLEZ、BGTZ、BLTZ、BGEZ、J、JAL、JALR、JR、MFHI、MFLO、MTHI、MTLO}。为了实现这些功能,CPU主要包含了mips、IM、PC、GRF、Controller、EXT、CMP、NPC、ALU、DM、regFD、regDE、regEM、regMW、Fw_Controller、Mult_Div、Load_select、CP0、Bridge等部件,其中,mips为顶层模块。

将这些部件分为F、D、E、M、W级模块,主要通过F级读取当前指令,进入D级输出各个模块的控制信号从而对各个模块进行相应控制并计算出下一指令地址,继而进入E级进行计算,通过M级、W级进行写入操作从而实现指令的功能。通过Fw_Controller模块,分析传入的各级寄存器编号以及指令类型,输出相应的转发控制信号和暂停控制信号。

(二)关键模块定义

1. PC

表1 PC模块接口

文件

模块接口定义

PC.v

module PC(

    input [31:0] NPC, //下一PC值

    input clk, //时钟信号

input reset, //同步复位信号

Input PCEn, //PC使能信号

    output reg [31:0] PC //当前PC值

    );

表2 IFU功能定义

序号

功能名称

功能描述

1

同步复位

当时钟信号处于上升沿且reset信号有效时,PC被设置为0x0000 3000

2

读取地址

根据PC寄存器中保存的值输出当前地址

3

冻结地址

当PC使能信号失效时,需要暂停,冻结当前地址

2. GRF

表3 GRF模块接口

文件

模块接口定义

GRF.v

module GRF(

    input clk,//时钟信号

    input reset,//同步复位信号

    input RegWrite,//写使能信号

    input [4:0] A1,//读寄存器地址1

    input [4:0] A2,//读寄存器地址2

    input [4:0] A3,//写寄存器地址

    input [31:0] WD,//写入数据

 input [31:0] PC,//当前地址

    output [31:0] RD1,//寄存器地址1的数据

    output [31:0] RD2 //寄存器地址2的数据

);

reg[31:0] register[31:0];

表4 GRF功能定义

序号

功能名称

功能描述

1

同步复位

当时钟信号处于上升沿且reset信号有效时,所有寄存器存储的数值清零

2

读数据

读出A1,A2地址对应寄存器中存储的数据到RD1,RD2

3

写数据

当RegWrite有效且时钟上升沿来临,将WD写入A3对应的寄存器中

3. Controller

表5 Controller模块接口

文件

模块接口定义

Controller.v

module Controller(

    input [5:0] op,//指令的[31:26]位,表明指令类型

    input [5:0] func,//指令的[5:0]位,表明R型指令的控制信号

    output reg [1:0]MemtoReg,//GRF写入数据选择信号

    output reg MemWrite,//DM写使能信号

    output reg Branch,//分支指令判断信号

 output reg if_jr,//jr指令判断信号

 output reg iF_j,//jal、j指令判断信号

    output reg ALUSrc,//ALU输入数据选择信号

    output reg [2:0] ALUControl,//ALU控制信号

    output reg [1:0]RegDst,//GRF写入寄存器选择信号

    output reg RegWrite,//GRF写使能信号

    output reg [1:0] ExpandSrc//立即数拓展方式选择信号

    );

表6 Controller功能定义

序号

功能名称

功能描述

1

产生控制信号

通过读入的op与func,产生对应指令的控制信号

4.ALU

表7 ALU模块接口

文件

模块接口定义

ALU.v

module ALU(

    input [31:0] A,//输入数据1

    input [31:0] B,//输入数据2

    input [2:0] ALUControl,//ALU控制信号

    output reg [31:0] ALUResult,//ALU计算结果

    );

表8 ALU功能定义

序号

功能名称

功能描述

1

A + B   //ALUControl=00

2

A - B   //ALUControl=01

3

A & B   //ALUControl=10

4

A | B   //ALUControl=11

5.DM

表9 DM模块接口

文件

模块接口定义

DM.v

module DM(

    input clk,//时钟信号

    input reset,//同步复位信号

 input MemWrite,//写使能信号

 input [31:0] PC,//当前地址

    input [31:0] Addr,//写入地址

    input [31:0] WD,//写入数据

    output [31:0] RD//输出数据

    );

表10 DM功能定义

序号

功能名称

功能描述

1

复位

当时钟信号处于上升沿且reset信号有效时,RAM中的数据都被设置为0x0000 0000

2

当时钟处于上升沿且写使能信号有效时,根据输入地址,把输入数据写入

3

根据输入的地址,输出对应地址的数据

6.EXT

表11 EXT模块接口

文件

模块接口定义

EXT.v

module EXT(

    input [15:0] imm16,//输入数据imm16

 input [1:0] ExpandSrc,//拓展选择信号

    output reg [31:0] EXTResult//输出数据

    );

表12 EXT功能定义

序号

功能名称

功能描述

1

符号拓展

当拓展选择信号为00时,将输入数据进行符号拓展

2

无符号拓展

当拓展选择信号为01时,将输入数据进行无符号拓展

3

转移至高位拓展

当拓展选择信号为10时,将输入数据转移至高位

7.IM

表13 IM模块接口

文件

模块接口定义

IM.v

module IM(

    input [31:0] PC,//当前地址

    output [31:0] instruction//当前地址对应指令

    );

表14 IM功能定义

序号

功能名称

功能描述

1

根据输入地址,读取当前指令

8.CMP

表15 CMP模块接口

文件

模块接口定义

CMP.v

module CMP(

    input [31:0] MFRSD,

    input [31:0] MFRTD,

    output reg Zero

    );

表16 CMP功能定义

序号

功能名称

功能描述

1

判断是否相等

判断输入的两个寄存器中的值是否相等

9.NPC

表17 NPC模块接口

文件

模块接口定义

NPC.v

module NPC(

    input [31:0] PC4_F,

 input [31:0] PC4_D,

    input [25:0] imm26,

    input Zero,

    input Branch,

 input if_j,

 input if_jr,

    input [31:0] MFRSD,

    output reg[31:0] NPC

);

wire [31:0] PC;

assign PC = PC4_F - 4;

表18 NPC功能定义

序号

功能名称

功能描述

1

判断下一条指令地址

根据输入的各个控制信号,判断下一条指令的地址。

若Branch信号和Zero信号都有效,beq跳转生效

NPC = PC4_D + {{14{imm26[15]}},imm26[15:0],2'b00};

若if_j信号有效,j或jal跳转生效

NPC = {PC[31:28],imm26[25:0],2'b00};

若if_jr信号有效,jr跳转生效

NPC = MFRSD;

若以上信号都未生效,NPC=PC+4;

10.regFD

表19 regFD模块接口

文件

模块接口定义

regFD.v

module regFD(

    input [31:0] Instr_F,

    input [31:0] PC4_F,

    input clk,

    input reset,

 input stall,

    output reg [31:0] Instr_D,

    output reg [31:0] PC4_D

    );

表20 regFD功能定义

序号

功能名称

功能描述

1

流水指令及地址

将F级读到的指令及地址流水至D级

2

暂停

若暂停信号stall信号生效,FD寄存器中的值冻结

3

复位

若复位信号生效,FD寄存器中的值归0

11.regDE

表21 regDE模块接口

文件

模块接口定义

regDE.v

module regDE(

    input clk,

    input reset,

 input stall,

    input [31:0] Instr_D,

 input [31:0] PC4_D,

    input RegWrite_D,

    input [1:0] MemtoReg_D,

    input MemWrite_D,

    input [1:0] RegDst_D,

    input ALUSrc_D,

    input [2:0] ALUControl_D,

    input [31:0] RD1_D,

    input [31:0] RD2_D,

    input [31:0] EXTResult_D,

    input [4:0] Rs_D,

    input [4:0] Rt_D,

    input [4:0] Rd_D,

    output reg [31:0] Instr_E,

    output reg [31:0] PC4_E,

    output reg RegWrite_E,

    output reg [1:0] MemtoReg_E,

    output reg MemWrite_E,

    output reg [1:0] RegDst_E,

    output reg ALUSrc_E,

    output reg [2:0] ALUControl_E,

    output reg [31:0] RD1_E,

    output reg [31:0] RD2_E,

    output reg [31:0] EXTResult_E,

    output reg [4:0] Rs_E,

    output reg [4:0] Rt_E,

    output reg [4:0] Rd_E

    );

表22 regDE功能定义

序号

功能名称

功能描述

1

流水指令及地址

将D级读到的指令及地址流水至E级

2

流水控制信号

将D级Controller输出的控制信号流水至E级

3

流水关键数据

将部分关键数据如GRF(转发)的数据,EXT拓展结果,指令中Rs,Rt,Rd的编号流水至E级

4

暂停

若暂停信号stall信号生效,FD寄存器中的值归0

5

复位

若复位信号生效,DED寄存器中的值归0

12.regEM

表23 regEM模块接口

文件

模块接口定义

regEM.v

module regEM(

    input clk,

 input reset,

    input [31:0] Instr_E,

    input [31:0] PC4_E,

    input RegWrite_E,

    input [1:0] MemtoReg_E,

    input MemWrite_E,

 input [4:0] A3_E,

 input [31:0] ALUResult_E,

 input [31:0] MFRTE,

    output reg [31:0] Instr_M,

    output reg [31:0] PC4_M,

    output reg RegWrite_M,

    output reg [1:0] MemtoReg_M,

    output reg MemWrite_M,

    output reg [31:0] ALUResult_M,

    output reg [4:0] A3_M,

    output reg [31:0] MFRTM

    );

表24 regEM功能定义

序号

功能名称

功能描述

1

流水指令及地址

将E级读到的指令及地址流水至M级

2

流水控制信号

将E级读到的控制信号流水至M级

3

流水关键数据

将部分关键数据如E级Rt转发后的值,ALU计算结果,E级指令所需写寄存器编号流水至M级

4

复位

若复位信号生效,EM寄存器中的值归0

13.regMW

表25 regMW模块接口

文件

模块接口定义

regMW.v

module regMW(

    input reset,

 input clk,

    input [31:0] Instr_M,

    input [31:0] PC4_M,

    input RegWrite_M,

    input [1:0] MemtoReg_M,

    input [31:0] ALUResult_M,

    input [4:0] A3_M,

    input [31:0] RD_M,

 output reg [31:0] Instr_W,

    output reg [31:0] PC4_W,

    output reg RegWrite_W,

    output reg [1:0] MemtoReg_W,

    output reg [31:0] ALUResult_W,

    output reg [4:0] A3_W,

    output reg [31:0] RD_W

    );

表26 regMW功能定义

序号

功能名称

功能描述

1

流水指令及地址

将M级读到的指令及地址流水至W级

2

流水控制信号

将M级读到的控制信号流水至W级

3

流水关键数据

将部分关键数据如M级写入DM的值,M级流水的ALU计算结果,M级指令所需写寄存器编号流水至M级

4

复位

若复位信号生效,MW寄存器中的值归0

14.F

表27 F模块接口

文件

模块接口定义

F.v

module F(

    input [31:0] NPC,

    input clk,

    input reset,

 input stall,

    output [31:0] Instr_F,

    output [31:0] PC4_F

    );

 wire [31:0] PC;

 assign PCEn = !stall;

表28 F功能定义

序号

功能名称

功能描述

1

流水指令及地址

将根据地址读到的指令及地址及地址流水至D级

2

暂停

若stall信号生效,冻结当前PC

4

复位

若复位信号生效,将PC复位至32’h00003000

15.D

表29 D模块接口

文件

模块接口定义

D.v

module D(

    input [31:0] Instr_F,

    input clk,

    input reset,

 input [31:0] PC4_F,

    input RegWrite_W,

    input [31:0] WD_W,

 input [31:0] WD_M,

    input [4:0] A3_W,

    input [31:0] PC4_W,

 input [31:0] PC4_E,

 input [31:0] PC4_M,

 input [2:0] ForwardRSD,

 input [2:0] ForwardRTD,

 input stall,

 input [31:0]ALUResult_M,

    output [31:0] Instr_D,

 output [31:0] PC4_D,

 output [31:0] NPC,

    output RegWrite_D,

    output [1:0] MemtoReg_D,

    output MemWrite_D,

    output [1:0] RegDst_D,

    output ALUSrc_D,

    output [2:0] ALUControl_D,

    output [31:0] RD1_D,

    output [31:0] RD2_D,

    output [31:0] EXTResult_D,

    output [4:0] Rs_D,

    output [4:0] Rt_D,

    output [4:0] Rd_D

);

assign Rs_D=Instr_D[`rs];

assign Rt_D=Instr_D[`rt];

assign Rd_D=Instr_D[`rd];

表30 D功能定义

序号

功能名称

功能描述

1

流水指令及地址

将D级读到的指令及地址流水至E级

2

流水控制信号

将Controller产生的控制信号流水至E级

3

流水关键数据

将部分关键数据流水至E级

4

计算下一个指令地址

通过NPC计算下一条指令地址

5

复位

若复位信号生效,FD寄存器中的值归0

6

暂停

若stall信号生效,使FD寄存器冻结

16.E

表31 E模块接口

文件

模块接口定义

E.v

module E(

    input clk,

    input reset,

    input [31:0] Instr_D,

 input [31:0] PC4_D,

    input RegWrite_D,

    input [1:0] MemtoReg_D,

    input MemWrite_D,

    input [1:0] RegDst_D,

    input ALUSrc_D,

    input [2:0] ALUControl_D,

    input [31:0] RD1_D,

    input [31:0] RD2_D,

    input [31:0] EXTResult_D,

    input [4:0] Rs_D,

    input [4:0] Rt_D,

    input [4:0] Rd_D,

 input [2:0] ForwardRSE,

 input [2:0] ForwardRTE,

 input [31:0] WD_M,

 input [31:0] WD_W,

 input stall,

    output [31:0] Instr_E,

    output [31:0] PC4_E,

    output RegWrite_E,

    output [1:0] MemtoReg_E,

    output MemWrite_E,

 output [4:0] A3_E,

 output [31:0] ALUResult_E,

 output [31:0] MFRTE,

 output flag_E,

 output [4:0]Rs_E,

 output [4:0]Rt_E

    );

表32 E功能定义

序号

功能名称

功能描述

1

流水指令及地址

将E级读到的指令及地址流水至M级

2

流水控制信号

将E级读到的控制信号流水至M级

3

流水关键数据

将部分关键数据流水至M级

4

计算指令结果

通过ALU计算部分指令的输出

5

复位

若复位信号生效,DE寄存器中的值归0

6

暂停

若stall信号生效,DE寄存器中的值归0

17.M

表33 M模块接口

文件

模块接口定义

M.v

module E(

    input clk,

    input reset,

    input [31:0] Instr_D,

 input [31:0] PC4_D,

    input RegWrite_D,

    input [1:0] MemtoReg_D,

    input MemWrite_D,

    input [1:0] RegDst_D,

    input ALUSrc_D,

    input [2:0] ALUControl_D,

    input [31:0] RD1_D,

    input [31:0] RD2_D,

    input [31:0] EXTResult_D,

    input [4:0] Rs_D,

    input [4:0] Rt_D,

    input [4:0] Rd_D,

 input [2:0] ForwardRSE,

 input [2:0] ForwardRTE,

 input [31:0] WD_M,

 input [31:0] WD_W,

 input stall,

    output [31:0] Instr_E,

    output [31:0] PC4_E,

    output RegWrite_E,

    output [1:0] MemtoReg_E,

    output MemWrite_E,

 output [4:0] A3_E,

 output [31:0] ALUResult_E,

 output [31:0] MFRTE,

 output flag_E,

 output [4:0]Rs_E,

 output [4:0]Rt_E

    );

表34 M功能定义

序号

功能名称

功能描述

1

流水指令及地址

将M级读到的指令及地址流水至W级

2

流水控制信号

将M级读到的控制信号流水至W级

3

流水关键数据

将部分关键数据流水至M级

4

复位

若复位信号生效,EM寄存器中的值归0,DM中的值归0

18.W

表35 W模块接口

文件

模块接口定义

M.v

module E(

    input clk,

    input reset,

    input [31:0] Instr_D,

 input [31:0] PC4_D,

    input RegWrite_D,

    input [1:0] MemtoReg_D,

    input MemWrite_D,

    input [1:0] RegDst_D,

    input ALUSrc_D,

    input [2:0] ALUControl_D,

    input [31:0] RD1_D,

    input [31:0] RD2_D,

    input [31:0] EXTResult_D,

    input [4:0] Rs_D,

    input [4:0] Rt_D,

    input [4:0] Rd_D,

 input [2:0] ForwardRSE,

 input [2:0] ForwardRTE,

 input [31:0] WD_M,

 input [31:0] WD_W,

 input stall,

    output [31:0] Instr_E,

    output [31:0] PC4_E,

    output RegWrite_E,

    output [1:0] MemtoReg_E,

    output MemWrite_E,

 output [4:0] A3_E,

 output [31:0] ALUResult_E,

 output [31:0] MFRTE,

 output flag_E,

 output [4:0]Rs_E,

 output [4:0]Rt_E

    );

表36 W功能定义

序号

功能名称

功能描述

1

写数据

将指令所需写数据传入GRF

2

复位

若复位信号生效,MW寄存器中的值归0

19.Mult_Div

表37 Mult_Div模块接口

文件

模块接口定义

Mult_Div.v

module Mult_Div(

    input clk,

    input reset,

    input [31:0] A,

    input [31:0] B,

    input start_E,

 input [3:0]MDOp_E,

    output reg Busy,

    output [31:0] HI,

    output [31:0] LO

    );

表38 Mult_Div功能定义

序号

功能名称

功能描述

1

进行乘除计算

将指令进行乘除计算并且将相应值保存至HI,LO

2

赋值

给HI,LO赋值

20.Load_seLect

表39 Load_seLect模块接口

文件

模块接口定义

Mult_Div.v

module Load_select(

    input [31:0] RD_W,

    input [31:0] Instr_W,

    input [31:0] ALUResult_W,

    output reg [31:0] RD_W_real

    );

表40 Load_stlect功能定义

序号

功能名称

功能描述

1

取内存值

根据当前指令及Addr,取处内存中值的相应位

21.CP0

表41 CP0模块接口

文件

模块接口定义

CP0.v

module CP0(

        input [4:0] A1,//rd读

input [4:0] A2,//rd写

input [31:0] DIn,

input [31:0] PC, //存入的epc

input [4:0] ExcCode, //中断异常类

input [5:0] HWInt, //6个中断

input We, //CP0写使能

input EXLSet, //中断 exl置1

input EXLClr, //eret exl置0

input clk,

input reset,

input BD, //延迟操指令受害标志

output IntReq, //输出中断请求

output [31:0] EPC,

output [31:0] Dout

    );

表42 CP0功能定义

序号

功能名称

功能描述

1

同步复位

当时钟信号处于上升沿且reset信号有效时,所有寄存器存储的数值清零

2

读数据

mfc0可以将CP0中寄存器存储的数据读出

3

写数据

mtc0可以向CP0寄存器写入数据

4

判断中断异常

判断中断异常的发生,产生中断请求的信号

5

返回地址

eret可以让cpu在处理完异常后返回epc

22.Bridge

表43 Bridge模块接口

文件

模块接口定义

Bridge.v

module Bridge(

    input [31:0] PrAddr,

 input PrWE,//timer写使能

 input [31:0] PrWD,//写入DEV的数据

 input [31:0] DEV0_RD,//DEV0的数据

    input [31:0] DEV1_RD,//DEV1的数据

    output [31:0] PrRD, //从DEV0/1读取的数据

    output [31:0] DEV_Addr,//写入地址

    output [31:0] DEV_WD,//写入DEV的数据

 output WeDEV0,//DEV0写使能

 output WeDEV1 //DEV1写使能

    );

表44 Bridge功能定义

序号

功能名称

功能描述

1

写/读 数据

作为CPU与timer的桥梁,向timer中写或读数据

23.mips

表45 mips模块接口

文件

模块接口定义

mips.v

module mips(

input clk,

   input reset,

input interrupt,

output [31:0] addr

    );

表46 mips功能定义

序号

功能名称

功能描述

1

复位

当复位信号有效时,将CPU复位

2

外部中断

当interrupt信号有效时,将CPU中断

3

输出当前宏观pc

输出当前宏观pc值

(三)重要机制实现方案

①:跳转

NPC模块和CMP模块协同工作支持b指令的跳转

CMP比较Rs和Rt寄存器中的值,以及比较0和Rs寄存器中的值,输出是大于小于等于0,或是否相等,进而通过NPC模块进行跳转。

NPC模块和Controller模快协同支持j,jal,jr,jalr的跳转

Controller模块通过读取指令判断指令是否为j,jal或jr,jalr,进而跳转至所需位置。

②:转发

Fw_Controller与D,E,M级模块协同工作以支持转发(未使用内部转发)

先分析当前级别(D,E,M)的指令是否立刻需要其所需寄存器的值,若需要,则判断所需寄存器编号与该指令前的指令中已产生新值但仍未写回GRF的的写入寄存器编号是否相等,若相等,进行转发。

而判断之前的指令是否已产生新值则需根据指令类型进行分析,在E,M,W级寄存器中通过分析指令的类型来判断当前是否产生新值,若已产生,flag_X(X为级数)为1.

图1 转发控制表

assign flag_E = Instr_E[`op]==`jal||Instr_E[`op]==`jalr;

assign flag_M=cal_r||cal_i||mf||j;

assign flag_W=cal_r||cal_i||mf||j||load;

assign ForwardRSD=(Rs_D==A3_E&&A3_E!=0&&flag_E)? 3'b001:

              (Rs_D==A3_M&&A3_M!=0&&flag_M)? 3'b010:

    (Rs_D==A3_W&&A3_W!=0&&flag_W)? 3'b011:0;  

assign ForwardRTD=(Rt_D==A3_E&&A3_E!=0&&flag_E)? 3'b001:

              (Rt_D==A3_M&&A3_M!=0&&flag_M)? 3'b010:

(Rt_D==A3_W&&A3_W!=0&&flag_W)? 3'b011:0;

assign ForwardRSE=(Rs_E==A3_M&&A3_M!=0&&flag_M)? 3'b010:

(Rs_E==A3_W&&A3_W!=0&&flag_W)? 3'b011:0;

assign ForwardRTE=(Rt_E==A3_M&&A3_M!=0&&flag_M)? 3'b010:

 (Rt_E==A3_W&&A3_W!=0&&flag_W)? 3'b011:0;

assign ForwardRTM=(Rt_M==A3_W&&A3_W!=0&&flag_W)? 3'b011:0;

assign MFRSD = (ForwardRSD==3'b001)?PC4_E+4:

                (ForwardRSD==3'b010)?WD_M:

 (ForwardRSD==3'b011)?WD_W:RD1;

assign MFRTD = (ForwardRTD==3'b001)?PC4_E+4:

                (ForwardRTD==3'b010)?WD_M:

 (ForwardRTD==3'b011)?WD_W:RD2;

assign MFRSE = (ForwardRSE==3'b010)?WD_M:

 (ForwardRSE==3'b011)?WD_W:RD1_E;

assign MFRTE = (ForwardRTE==3'b010)?WD_M:

 (ForwardRTE==3'b011)?WD_W:RD2_E;

assign WD = (ForwardRTM==3'b011)?WD_W:MFRTM;

③:暂停

Fw_Controller发出控制信号stall控制F,D,E级模块的暂停工作

分析D级指令还要过几个周期才需要使用寄存器的值(Tuse),对于该指令前的指令,分析还需过几个周期才能产生新值(Tnew),若Tnew>Tuse则需暂停。分析完本次实验所有指令的Tuse、Tnew后,对于D中指令以及前面的指令类型进行判断,若有Tnew>Tuse且所用寄存器编号相等,stall信号有效,控制各个流水寄存器进行暂停

图2 暂停控制表

assign stall_b = b_D&&((((Rs_D==A3_E)||(Rt_D==A3_E))&&(cal_r_E||cal_i_E||mf_E||load_E))||(((Rs_D==A3_M)||(Rt_D==A3_M))&&load_M));

assign stall_cal_r=cal_r_D&&((Rs_D==A3_E)||(Rt_D==A3_E))&&load_E;

assign stall_MD=MD_D&&((Rs_D==A3_E)||(Rt_D==A3_E))&&load_E;

assign stall_cal_i=cal_i_D&&Rs_D==A3_E&&load_E;

assign stall_mt=mt_D&&Rs_D==A3_E&&load_E;

assign stall_load=load_D&&Rs_D==A3_E&&load_E;

assign stall_store=store_D&&Rs_D==A3_E&&load_E;

assign stall_j = j_D&&(((Rs_D==A3_E)&&(cal_r_E||cal_i_E||mf_E||load_E))||((Rs_D==A3_M)&&load_M));

assign stall_ALLMD=ALLMD_D&&(Busy||MD_E);

assign stall = stall_b||stall_cal_r||stall_MD||stall_cal_i||stall_mt||stall_load||stall_store||stall_j||stall_ALLMD;

④:异常/异常

异常:根据所可能发生的异常,在cpu中进行判断,若发生异常将ExcCode修改为相应值,传入CP0中进行相应。

中断:向CPU输入HWInt信号,由interrupt、IRQ1、IRQ0组成,若该信号有位为1,则将CPU中断,各流水清空。

二、测试方案

1.转发机制测试

表48 转发情况

用例编号

当前指令

前序指令

冲突寄存器

冲突级别

1

b/jr/jalr

jal

rs

D

2

b/jr/jalr

cal_r

xxx

rs

D

3

b/jr/jalr

cal_i

xxx

rs

D

4

b/jr/jalr

jal

xxx

rs

D

5

b/jr/jalr

cal_r

xxx

xxx

rs

D

6

b/jr/jalr

cal_i

xxx

xxx

rs

D

7

b/jr/jalr

lw

xxx

xxx

rs

D

8

b/jr/jalr

jal

(延迟槽)

xxx

xxx

rs

D

9

b

jal

rt

D

10

b

cal_r

xxx

rt

D

11

b

cal_i

xxx

rt

D

12

b

jal

xxx

rt

D

13

b

cal_r

xxx

xxx

rt

D

14

b

cal_i

xxx

xxx

rt

D

15

b

lw

xxx

xxx

rt

D

16

b

jal

(延迟槽)

xxx

xxx

rt

D

17

cal_r,cal_i,load,store,mf

cal_r

xxx

rs

E

18

cal_r,cal_i,load,store,mf

cal_i

xxx

rs

E

19

cal_r,cal_i,load,store,mf

jal

xxx

rs

E

20

cal_r,cal_i,load,store,mf

cal_r

xxx

xxx

rs

E

21

cal_r,cal_i,load,store,mf

cal_i

xxx

xxx

rs

E

22

cal_r,cal_i,load,store,mf

lw

xxx

xxx

rs

E

23

cal_r,cal_i,load,store,mf

jal

(延迟槽)

xxx

xxx

rs

E

24

cal_r

cal_r

xxx

rt

E

25

cal_r

cal_i

xxx

rt

E

26

cal_r

jal

xxx

rt

E

27

cal_r

cal_r

xxx

xxx

rt

E

28

cal_r

cal_i

xxx

xxx

rt

E

29

cal_r

lw

xxx

xxx

rt

E

30

cal_r

jal

(延迟槽)

xxx

xxx

rt

M

31

store

cal_r

xxx

xxx

rt

M

32

store

cal_i

xxx

xxx

rt

M

33

store

lw

xxx

xxx

rt

M

34

store

jal

(延迟槽)

xxx

xxx

rt

M

1,9.jal后不接跳转或分支指令,故不需考虑

2,10.

ori $t1,$0,0x1234

addu $t2,$0,$t1

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00001234

@00003004: $10 <= 00001234

3,11.

ori $t1,$0,0x1234

ori $t2,$0,0x1234

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00001234

@00003004: $10 <= 00001234

4,12.

ori $t1,$0,0x300c

jal tag1

nop

addu $t1,$t1,$0

tag1:

beq $31,$t1,tag2

nop

addu $t1,$t1,$0

tag2:

期望输出:

@00003000: $ 9 <= 0000300c

@00003004: $31 <= 0000300c

5,13.

ori $t1,$0,0x1234

addu $t2,$0,$t1

nop

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00001234

@00003004: $10 <= 00001234

6,14.

ori $t1,$0,0x1234

ori $t2,$0,0x1234

nop

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

期望输出:

@00003000: $ 9 <= 00001234

@00003004: $10 <= 00001234

7.15

ori $t1,0x1234

sw $t1,0($0)

lw $t2,0($0)

nop

nop

beq $t1,$t2,tag

nop

addu $t1,$t1,$0

tag:

期望输出:

@00003000: $ 9 <= 00001234

@00003004: *00000000 <= 00001234

@00003008: $10 <= 00001234

8.16

ori $t1,$0,0x300c

jal tag1

nop

addu $t1,$t1,$0

tag1:

nop

beq $31,$t1,tag2

nop

addu $t1,$t1,$0

tag2:

期望输出:

@00003000: $ 9 <= 0000300c

@00003004: $31 <= 0000300c

17,18,24,25

ori $t1,$0,0x0010

ori $t2,$0,0x0020

ori $t3,$0,0x0004

addu $t4,$t1,$t2

nop

addu $t4,$t4,$t3 //t4=0034

nop

ori $t5,$t4,0x1234

subu $t4,$t4,$t3

nop

sw $t1,0($t4)

addu $t4,$t4,$t3

subu $t4,$t4,$t3

nop

lw $t2,0($t4)

期望输出:

@00003000: $ 9 <= 00001000

@00003004: $10 <= 00002000

@00003008: $11 <= 00000004

@0000300c: $12 <= 00003000

@00003014: $12 <= 00003004

@0000301c: $13 <= 00003234

@00003020: $12 <= 00003000

@00003000: $ 9 <= 00000010

@00003004: $10 <= 00000020

@00003008: $11 <= 00000004

@0000300c: $12 <= 00000030

@00003014: $12 <= 00000034

@0000301c: $13 <= 00001234

@00003020: $12 <= 00000030

@00003028: *00000030 <= 00000010

@0000302c: $12 <= 00000034

@00003030: $12 <= 00000030

@00003038: $10 <= 00000010

19.26

ori $t1,$0,4

jal tag1

nop

addu $t1,$t1,$t1

tag1:

addu $t2,$31,$t1

jal tag2

nop

addu $t1,$t1,$t1

tag2:

ori $t3,$31,0xff00

jal tag3

nop

addu $t1,$t1,$t1

tag3:

期望输出:

@00003000: $ 9 <= 00000004

@00003004: $31 <= 0000300c

@00003010: $10 <= 00003010

@00003014: $31 <= 0000301c

@00003020: $11 <= 0000ff1c

@00003024: $31 <= 0000302c

@00003000: $ 9 <= 00000004

@00003004: $31 <= 0000300c

@00003010: $10 <= 00003010

@00003014: $31 <= 0000301c

@00003020: $11 <= 0000ff1c

@00003024: $31 <= 0000302c

20,21,27,28.

ori $t1,$0,0x0010

ori $t2,$0,0x0020

ori $t3,$0,0x0004

addu $t4,$t1,$t2

nop

nop

addu $t4,$t4,$t3 //t4=0034

nop

nop

ori $t5,$t4,0x1234

subu $t4,$t4,$t3

nop

nop

sw $t1,0($t4)

addu $t4,$t4,$t3

subu $t4,$t4,$t3

nop

nop

lw $t2,0($t4)

期望输出:

@00003000: $ 9 <= 00001000

@00003004: $10 <= 00002000

@00003008: $11 <= 00000004

@0000300c: $12 <= 00003000

@00003014: $12 <= 00003004

@0000301c: $13 <= 00003234

@00003020: $12 <= 00003000

@00003000: $ 9 <= 00000010

@00003004: $10 <= 00000020

@00003008: $11 <= 00000004

@0000300c: $12 <= 00000030

@00003014: $12 <= 00000034

@0000301c: $13 <= 00001234

@00003020: $12 <= 00000030

@00003028: *00000030 <= 00000010

@0000302c: $12 <= 00000034

@00003030: $12 <= 00000030

@00003038: $10 <= 00000010

22,30.

ori $t1,$0,0x1234

sw $t1,0($1)

sw $t1,4($0)

lw $t2,0($0)

nop

nop

addu $t2,$t2,$t2

lw $t3,0($0)

nop

nop

ori $t3,$t3,0xfff0

lw $t4,0($0)

nop

nop

lw $t4,0($t4)

期望输出:

@00003000: $ 9 <= 00001234

@00003004: *00000000 <= 00001234

@00003008: *00000004 <= 00001234

@0000300c: $10 <= 00001234

@00003018: $10 <= 00002468

@0000301c: $11 <= 00001234

@00003028: $11 <= 0000fff4

@0000302c: $12 <= 00001234

@00003038: $12 <= 00000000

31,32,33,34

ori $t1,$0,0x1234

ori $t2,$0,0x0004

addu $t3,$t1,$t2

sw $t1,0($0)

lw $t4,0($0)

sw $t3,4($0)

nop

sw $t4,8($0)

jal tag

nop

addu $t1,$t1,$t1

tag:

nop

sw $31,12($0)

期望输出:

@00003000: $ 9 <= 00001234

@00003004: $10 <= 00000004

@00003008: $11 <= 00001238

@0000300c: *00000000 <= 00001234

@00003010: $12 <= 00001234

@00003014: *00000004 <= 00001238

@0000301c: *00000008 <= 00001234

@00003020: $31 <= 00003028

@00003030: *0000000c <= 00003028

2.暂停机制测试

用例编号

当前指令

前序指令

冲突寄存器

1

b

cal_r

rs/rt

2

b

cal_i

rs/rt

3

b

load

rs/rt

4

b

load

xxx

rs/rt

5

cal_r

load

rs

6

cal_i

load

rs

7

load

load

rs

8

store

load

rs

9

jr/jalr

cal_r

rs

10

jr/jalr

cal_i

rs

11

jr/jalr

load

rs

12

jr/jalr

load

xxx

rs

13

b

mf

rs/rt

14

jr/jalr

mf

rs

15

MD

load

rs/rt

16

ALLMD

busy/MD

/

测试代码:

1.

ori $t1,$0,0x3000

addu $t2,$t1,$zero

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00003000

@00003004: $10 <= 00003000

2.

ori $t1,$0,0x3000

ori $t2,$0,0x3000

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00003000

@00003004: $10 <= 00003000

3.

ori $t1,$0,0x3000

sw $t1,0($0)

lw $t2,0($0)

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00003000

@00003004: *00000000 <= 00003000

@00003008: $10 <= 00003000

4.

ori $t1,$0,0x3000

sw $t1,0($0)

lw $t2,0($0)

nop

beq $t1,$t2,tag

nop

addu $t3,$t1,$t2

tag:

期望输出:

@00003000: $ 9 <= 00003000

@00003004: *00000000 <= 00003000

@00003008: $10 <= 00003000

5.

ori $t1,$0,0x3000

sw $t1,0($0)

lw $t2,0($0)

addu $t3,$t1,$t2

期望输出:

@00003000: $ 9 <= 00003000

@00003004: *00000000 <= 00003000

@00003008: $10 <= 00003000

@0000300c: $11 <= 00006000

6.

ori $t1,$0,0x3000

sw $t1,0($0)

lw $t2,0($0)

ori $t3,$0,0x3000

期望输出:

ori $t1,$0,0x3000

sw $t1,0($0)

lw $t2,0($0)

ori $t3,$t2,0x3000

7.

ori $t1,$0,0x1000

sw $t1,0($0)

sw $t1,0($t1)

lw $t2,0($0)

lw $t3,0($t2)

期望输出:

@00003000: $ 9 <= 00001000

@00003004: *00000000 <= 00001000

@00003008: *00001000 <= 00001000

@0000300c: $10 <= 00001000

@00003010: $11 <= 00001000

8.

ori $t1,$0,0x1000

sw $t1,0($0)

lw $t2,0($0)

sw $t1,0($t2)

期望输出:

@00003000: $ 9 <= 00001000

@00003004: *00000000 <= 00001000

@00003008: $10 <= 00001000

@0000300c: *00001000 <= 00001000

9.

ori $t1,$0,0x3014

addu $t2,$t1,$0

jr $t2

nop

addu $t1,$t1,$0

addu $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 00003014

@00003004: $10 <= 00003014

@00003014: $ 9 <= 00006028

10.

ori $t1,$0,0x3014

ori $t2,$t1,0x0000

jr $t2

nop

addu $t1,$t1,$0

addu $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 00003014

@00003004: $10 <= 00003014

@00003014: $ 9 <= 00006028

11.

ori $t1,0x3018

sw $t1,0($0)

lw $t2,0($0)

jr $t2

nop

addu $t1,$t1,$0

addu $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 00003018

@00003004: *00000000 <= 00003018

@00003008: $10 <= 00003018

@00003018: $ 9 <= 00006030

12.

ori $t1,0x301c

sw $t1,0($0)

lw $t2,0($0)

nop

jr $t2

nop

addu $t1,$t1,$0

addu $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 0000301c

@00003004: *00000000 <= 0000301c

@00003008: $10 <= 0000301c

@0000301c: $ 9 <= 00006038

13.

addi $t1,$0,2

addi $t2,$t0,1

mult $t1,$t2

mflo $t3

beq $t1,$t3,flag

nop

add $t1,$t1,$t1

flag:

add $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 00000002

@00003004: $10 <= 00000001

@0000300c: $11 <= 00000002

@0000301c: $ 9 <= 00000004

14.

addi $t1,$0,1

addi $t2,$t0,0x301c

mult $t1,$t2

mflo $t3

jr $t3

nop

add $t1,$t1,$t1

flag:

add $t1,$t1,$t1

期望输出:

@00003000: $ 9 <= 00000001

@00003004: $10 <= 0000301c

@0000300c: $11 <= 0000301c

@0000301c: $ 9 <= 00000002

15.

addi $t1,$0,10

sw $t1,0($0)

lw $t2,0($0)

mult $t1,$t2

mflo $t3

期望输出:

@00003000: $ 9 <= 0000000a

@00003004: *00000000 <= 0000000a

@00003008: $10 <= 0000000a

@00003010: $11 <= 00000064

三、思考题

(一)为什么需要有单独的乘除法部件而不是整合进ALU?为何需要有独立的HI、LO寄存器?

因为MD类指令需要额外设置运算延迟,单独的乘除法部件更容易实现。同时MD指令计算结果为64位,而ALU的结果普遍都是32位,若仍要用ALU计算则要将ALU结果改为64位,那么就需要修改关于独立的HI、LO寄存器,违背了“高内聚,低耦合”的原则。

由于MD指令得到的结果为64位,将其分为两个32位寄存器来存储,对于乘法存储高32位和低32位,对于除法存储低余数和商,有了HI和LO方便获取MD指令计算后所需要的结果,也得以实现mf、mt指令。

(二)参照你对延迟槽的理解,试解释“乘除槽”

对于乘除模块,在进行MD指令的计算过程中,后续若有关于乘除指令,而乘除模块仍处于start或busy则需暂停。那么就可以类似延迟槽行为,在MD指令后接上与乘除无关的指令,充分利用CPU的性能。

(三)举例说明并分析何时按字节访问内存相对于按字访问内存性能上更有优势。(Hint: 考虑C语言中字符串的情况)

当对字符串进行处理时,一个字符占用一个字节,四个字符为一个字。若字符串中字符个数为5个,按字访存,需要2个字,8个字节,按字节访存,仅需要5个。可见按字访存会浪费内存空间。

(四)在本实验中你遇到了哪些不同指令类型组合产生的冲突?你又是如何解决的?相应的测试样例是什么样的?如果你是手动构造的样例,请说明构造策略,说明你的测试程序如何保证覆盖了所有需要测试的情况;如果你是完全随机生成的测试样例,请思考完全随机的测试程序有何不足之处;如果你在生成测试样例时采用了特殊的策略,比如构造连续数据冒险序列,请你描述一下你使用的策略如何结合了随机性达到强测的效果。

如上面第二大点中已列出冲突指令组合以及测试样例,通过Fw_Controller模块,分析传入的各级寄存器编号以及指令类型,输出相应的转发控制信号和暂停控制信号。

通过分析本次要求的各个指令,将会产生冲突的指令写入表格中,再一一列出样例进行测试,先写一条指令再在相应行数后写入一个会与这条指令所改变寄存器冲突的指令,构成冲突,再通过观察输出结果判断是否成功。

(五)为了对抗复杂性你采取了哪些抽象和规范手段?这些手段在译码和处理数据冲突的时候有什么样的特点与帮助?

采用宏定义,将各指令的op、func提前定义好,避免后续一堆数字不好分辨指令。同时利用模块Decoder将当前指令译码并分类,得到当前指令类型以进入Controller得到控制信号,避免了代码过长,并且在后续处理转发或暂停时可直接利用指令类型进行判断,不用将该类型所有指令列出,从而使得逻辑更清晰。并且在加入新指令时只需要将其归类便可直接处理好冲突。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值