Featured image of post P5_设计文档

P5_设计文档

verilog流水线CPU

P5_document

Hazard.v

inputexplain
Instr_IDID阶段的指令码
Instr_EXEX阶段的指令码
Instr_MAMA阶段的指令码
A3_EXEX阶段的寄存器写入地址
A3_MAMA阶段的寄存器写入地址

T_use表格(需求者)

指令位于ID级时,还需要多少个周期才必须要使用数据。

$T_{use}(rs)$$T_{use}(rt)$
add11
sub11
ori1
lw1
sw12
beq00
lui1
jal
jr0
nop
1
2
3
4
5
6
7
8
	wire [1:0] Tuse_rs = (add_ID | sub_ID | ori_ID | lw_ID | sw_ID | lui_ID)?2'b01:
								(beq_ID | jr_ID)? 2'b00:
								2'b11;
								
	wire [1:0] Tuse_rt = (add_ID | sub_ID)? 2'b01:
								(sw_ID)? 2'b10: 
								(beq_ID)? 2'b00:
								2'b11;

T_new表格(供给者)

T_new: 供给指令位于某个流水级时还需要多少个周期才可以计算出结果并存储到流水寄存器中。

早于需求指令进入流水线的供给者还需要多少cycle能够产生需求者需要的寄存器值。

Intsr功能部件(结果来源)EXMAWB
addALU1
subALU1
oriALU1
lwDM210
sw
beq
luiALU1
jalPC000
jr
nop
1
2
3
	wire [1:0] Tnew_EX = (add_EX | sub_EX | ori_EX | lui_EX)? 2'b01:
							(lw_EX)? 2'b10: 2'b00;
	wire [1:0] Tnew_MA = lw_MA?2'b01:2'b00;

rs策略矩阵

$T_{use} \textbackslash \space T_{new}$EXEXEXMAMAMAWBWBWB
ALUDMPCALUDMPCALUDMPC
120010000
0SSFFSFFFF
1FSFFFFFFF

rt策略矩阵

$T_{use} \textbackslash \space T_{new}$EXEXEXMAMAMAWBWBWB
ALUDMPCALUDMPCALUDMPC
120010000
0SSFFSFFFF
1FSFFFFFFF
2FFFFFFFFF

如何理解策略矩阵

  • 策略矩阵针对的是AT法中的Time部分,具体判断阻塞还是转发需要综合Adress部分
  • 对于ALU型指令,如add,只需要关注 $T_{new}$ 的ALU一列,其表示在当前流水级下,还有多少周期才能计算出结果并存入流水级寄存器。
1
2
3
4
5
6
	wire Stall_RS_EX = (Tuse_rs < Tnew_EX) & (A3_EX == RS_ID & RS_ID != 0);
	wire Stall_RS_MA = (Tuse_rs < Tnew_MA) & (A3_MA == RS_ID & RS_ID != 0);
	wire Stall_RT_EX = (Tuse_rt < Tnew_EX) & (A3_EX == RT_ID & RT_ID != 0);
	wire Stall_RT_MA = (Tuse_rt < Tnew_MA) & (A3_MA == RT_ID & RT_ID != 0);
	
	assign Stall = Stall_RS_EX | Stall_RS_MA | Stall_RT_EX | Stall_RT_MA;

Forward in mips.v

数据的供给者

  • EX_MA级流水线寄存器
1
2
3
	wire [31:0] forward_EX_MA = (RegWrite_MA && (Mem2Reg_MA == 2'b00))? ALU_C_MA:  
								(RegWrite_MA && (Mem2Reg_MA == 2'b10))? pc_add4_MA + 32'd4:
								32'h404;
  • MA_WB级流水线寄存器
1
2
3
4
5
	assign grf_WD = (Mem2Reg_WB == 2'b00) ? ALU_C_WB :
					(Mem2Reg_WB == 2'b01) ? dm_data_WB :
					(Mem2Reg_WB == 2'b10) ? pc_add4_WB + 32'd4 : 32'd0;
							 
	wire [31:0] forward_MA_WB = RegWrite_WB? grf_WD: 32'h405;

数据需求者

  • ID级
1
2
3
4
5
6
7
	wire [31:0] RD1_ID_valid =  ((RS_ID == A3_MA) && (A3_MA != 5'b0))? forward_EX_MA:
								((RS_ID == A3_WB) && (A3_WB != 5'b0))? forward_MA_WB:
								RD1_ID;
											
	wire [31:0] RD2_ID_valid =  ((RT_ID == A3_MA) && (A3_MA != 5'b0))? forward_EX_MA:
								((RT_ID == A3_WB) && (A3_WB != 5'b0))? forward_MA_WB:
								RD2_ID;
  • EX级
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
	//forward--select valid ALU_A and ALU_B
	wire [31:0] ALU_A_EX_valid = ((RS_EX == A3_MA) && (A3_MA != 5'b0))? forward_EX_MA:
								 ((RS_EX == A3_WB) && (A3_WB != 5'b0))? forward_MA_WB:
								 RD1_EX;
											
	wire [31:0] Grt_EX_valid =  ((RT_EX == A3_MA) && (A3_MA != 5'b0))? forward_EX_MA:
								((RT_EX == A3_WB) && (A3_WB != 5'b0))? forward_MA_WB:
								RD2_EX;//将目前正确的Grt值,流水到MA级供sw指令使用,也可供R-type-ALU指令使用
											
	wire [31:0] Grt_MA_valid; 
								
    wire [31:0] ALU_B_EX_valid = (ALUSrc_EX == 1'b0) ? Grt_EX_valid:
								 (ALUSrc_EX == 1'b1) ? ext32_EX : 32'b0;
  • MA级

    再一次获取转发数据,确保DM中的Grt值是正确的

1
wire [31:0] Grt_MA_valid_valid = ((RT_MA == A3_WB) && (A3_WB != 5'd0))? forward_MA_WB: Grt_MA_valid;

流水线寄存器

PCIF_IDID_EXEX_MAMA_WB
ennStallnStalltruefalsetrue
clrnullfalseStalltruefalse
RegDstExtOpjumpjumpSrcbranchbOpALUSrcALUOPMemWritels_typeMem2RegRegWrite
作用阶段EXIDIDIDIDIDEXEXMAMAWBWB
IF_ID
ID_EX1111111
EX_MA1111
MA_WB11

Stall Explain

ID级指令静止,EX级插入一个nop

  • PC不写入新数据
  • IF_ID寄存器不写入新数据
  • ID_EX寄存器清零,即插入nop(0x00000000)

Logic

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
module Stage_Reg(
		input clk,
		input reset,
		input en,
		input clr,
		input [31:0] data,
		output reg [31:0] data_out
    );
	 
	 initial begin
			data_out <= 0;
	 end
	 
	 always @(posedge clk) begin
		if (reset || clr) begin
			 data_out <= 0;
		end else begin
			if (en) begin
				data_out <= data;
			end
		end
	 end

信号解释

jumpSrc (2-bit)

jumpSrctype
2’b00branch
2’b01jump
2’b10jr
1
2
3
assign next_pc_ID = (jumpSrc_ID == 2'b00) ? branch_offset_ID:
                    (jumpSrc_ID == 2'b01) ? jumpExt32_ID:
                    (jumpSrc_ID == 2'b10) ? RD1_ID_valid: 32'h404; 

Mem2Reg (2-bit)

Mem2Regtype
2‘b00ALU
2’b01lw
2’b10link
1
2
3
assign grf_WD = (Mem2Reg_WB == 2'b00) ? ALU_C_WB :
				 (Mem2Reg_WB == 2'b01) ? dm_data_WB :
				 (Mem2Reg_WB == 2'b10) ? pc_add4_WB + 32'd4 : 32'd0;

RegDst (2-bit)

RegDsttype
2’b00无需写入寄存器的指令
2’b01R-type,写入rd寄存器
2’b10I-type,写入rt寄存器
2’b11link,写入$ra ($31)
1
2
3
4
5
assign A3_EX =  (RegDst_EX == 2'b00)? 5'b0: //null
                (RegDst_EX == 2'b01)? RD_EX:
				(RegDst_EX == 2'b10)? RT_EX:
                (RegDst_EX == 2'b11)? 5'h1f:
				5'b00000;

ALU (4-bit)

ALUtype
4’b0000add
4’b0001sub
4’b0010or
4’b0011lui
1
2
3
4
5
6
7
8
9
always @(*) begin
        case(F)
            `ADD:    C = A + B;
            `SUB:    C = A - B;
            `OR:     C = A | B;
            `SL16:   C = B << 16;
            default:C = 0;
        endcase
    end

测试方案

指令分类

R-type

  • ALU型指令(Grd <- Grs ? Grt)——(add、sub、or)
  • ALU型指令(Grd <- Grt ? shamt)——(sll、srl、sra)
  • 跳转型指令(PC <- Grs)——(jr)

I-type

  • ALU-Imm型指令(Grt <- Grs ? imm)——(ori、lui)
  • Memory-Store型指令(Memory[Grs + offset] <- Grt)——(sw、sb、sh)
  • Memory-load型指令(Grt <- Memory[Grs + offset])——(lw、lb、lbu、lh)
  • Branch型指令(Grs ? Grt,PC <- PC + 4 + offset)——(beq、bgez、bgtz、blez、bltz、bne)

J-type

  • J-link型指令 —— (jal)
  • 无条件Jump型指令
IF级ID级EX级MA级WB级
R-ALU读取数据(Grs、Grt)计算数据写入数据
R-jump读取数据并跳转
I-imm读取数据(Grt、imm)计算数据写入数据
I-store读取数据(Grs+offset、Grt)计算数据(地址)写入数据
I-load读取数据(Grs+offset、Grt)计算数据(地址)读取数据写入数据
I-branch读取数据(Grs、Grt)比较数据并跳转
J-link扩展数据并跳转传递跳转PC传递跳转PC写入pc+8

测试步骤

  1. 编写测试代码
    • 包括所有阻塞情况
    • 测试所有转发通路
    • 可利用课程组提供的分析工具对代码测试强度进行评估
  2. 将ISE输出与Mars输出比对
    • 可利用同学开发评测机进行快速比对
  3. 大量随机数据强测
 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
28
29
30
31
32
33
34
35
36
37
38
39
import random  
  
SUPPORTED_INSTRUCTIONS = [  
    "add", "sub", "and", "ori", "lui",  # arithmetic  
    "lw", "sw",  # storage  
    "beq", "bne",  # B-type  
    "j", "jal",  # jump  
    "nop"  
    # command jr will be generated according to the use of command jal  
]  
REGISTERS = [f"${i}" for i in range(32) if i != 1 and i < 26]  
  
  
def weighted_choice():  
    return random.choices(REGISTERS, weights=REGISTER_WEIGHTS, k=1)[0]  
  
  
def generate_random_instruction(half):  
    instruction = random.choice(SUPPORTED_INSTRUCTIONS)  
  
    if instruction in ["add", "sub", "and"]:  
        # add $t0, $t1, $t2 : op rd, rs, rt  
        rd = weighted_choice()  
        rs = weighted_choice()  
        rt = weighted_choice()  
        return f"{instruction} {rd}, {rs}, {rt}"  
  
    # other instructions...  
  
  
def main():  
    # parser...  
  
    high_weight_registers = random.sample(REGISTERS, 4)  
    # print(f"High weight registers: {high_weight_registers}")  
    global REGISTER_WEIGHTS  
    REGISTER_WEIGHTS = [4 if reg in high_weight_registers else 1 for reg in REGISTERS]  
  
    mips_code = generate_mips_code(args.num_instructions)

思考题

  1. 我们使用提前分支判断的方法尽早产生结果来减少因不确定而带来的开销,但实际上这种方法并非总能提高效率,请从流水线冒险的角度思考其原因并给出一个指令序列的例子。

提前分支判断会带增加阻塞的情况,从而降低效率

lw $1, 0($0) ori $2, $0, 514 beq $1, $2, label

对于上述代码,需要阻塞两次

  1. 因为延迟槽的存在,对于 jal 等需要将指令地址写入寄存器的指令,要写回 PC + 8,请思考为什么这样设计?

因为,jr返回时应该执行延迟槽后面的指令

  1. 我们要求所有转发数据都来源于流水寄存器而不能是功能部件(如 DM、ALU),请思考为什么?

减少组合逻辑与时序逻辑的组合,减少毛刺,使流水线分级更清晰

  1. 我们为什么要使用 GPR 内部转发?该如何实现?

解决结构冒险。由于流水线中grf的读写在不同级,所以当同时读和写grf时会出现结构冒险

assign RD1 = (A3!=0 & A1==A3 & WE) ? WD : grf[A1];
assign RD2 = (A3!=0 & A2==A3 & WE) ? WD : grf[A2];

  1. 我们转发时数据的需求者和供给者可能来源于哪些位置?共有哪些转发数据通路?

见上文

  1. 在课上测试时,我们需要你现场实现新的指令,对于这些新的指令,你可能需要在原有的数据通路上做哪些扩展或修改?提示:你可以对指令进行分类,思考每一类指令可能修改或扩展哪些位置。
  1. 添加控制信号
  2. 可能需要修改ALU
  3. 修改顶层模块,可能需要添加wire
  4. 可能需要修改阻塞逻辑
  1. 简要描述你的译码器架构,并思考该架构的优势以及不足。、

集中式译码。只需一次译码,然后流水各个信号。 优势:资源占用小,代码量小 不足:流水信号比较麻烦,添加控制信号时比较麻烦

  1. [P5 选做] 请详细描述你的测试方案及测试数据构造策略。

见测试方案

  1. [P5、P6 选做] 请评估我们给出的覆盖率分析模型的合理性,如有更好的方案,可一并提出。
Licensed under CC BY-NC-SA 4.0
最后更新于 Nov 14, 2024 00:11 UTC
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计