LoongArch CPU设计实验_实践任务8:阻塞技术解决相关引发的冲突

LoongArch CPU设计实验_实践任务8:阻塞技术解决相关引发的冲突

声明

由于未能成功配置Loongarch交叉编译工具,本实验使用的是exp压缩包(压缩包下载链接见文尾参考资料)。

实验要求

本实践任务要求在实践任务7实现的CPU基础上完成以下工作:

  1. 加入适当的逻辑处理寄存器写后读数据相关引发的流水线冲突(本任务中只要求使用阻塞技术)。
  2. 运行exp8对应的func,要求成功通过仿真和上板验证。

请参照第2.3.1节中介绍的方式获取本次实践任务所需的实验开发环境。具体的实验环境仍位于 mycpu_env/ 目录下,且仍使用soc_bram/子目录。
在这里插入图片描述

流水线冲突分析

前提:单发射静态流水线。

  • 控制相关引发的流水线冲突,因为五级流水线的译码阶段能够完成所有跳转指令的处理,并产生前递数据,因此不会因为控制相关导致冲突。
  • 结构相关引发的流水线冲突,因为五级流水线各级间有严格的握手逐级互锁,因此当某一级阻塞时所有流水线都可以停止。
  • 寄存器写后读引发的冲突,可能某条指令A处于ID阶段时,指令B处于EXE阶段,且B的目的寄存器为A的源寄存器。此时B指令还没来得及将新值写回寄存器,A就读取了旧的寄存器值。
    • 读后写,因为读取的是最新的数据,读取刚写入的新值不会冲突。
    • 写后写,因为写和写之间互不影响,单发射同一时间只能有一条指令写寄存器,不会冲突。

关于跳转指令

⭐重点在于使用br_taken信号让FS和DS都阻塞一个时钟周期,并在此周期内更新next_pcinst的内容,从而达到跳过jmp指令后的那一条指令的目的。
⭐需要注意的是,bnebeq指令,在这两条指令因为等待源寄存器更新而阻塞在DS时,需要将br_taken信号也阻塞(赋值为0),因为此时跳转指令相关计算未完成。

代码修改

寄存器号传递

EXE_stage:		
	output [ 4:0] es_to_ds_dest,  //执行级目的操作数寄存器号
	assign es_to_ds_dest = dest & {5{es_valid}}; 
	
MEM_stage:
	output [ 4:0] ms_to_ds_dest  //访存级目的操作数寄存器号
	assign ms_to_ds_dest = ms_dest & {5{ms_valid}};
	
WB_stage:	
	output [ 4:0] ws_to_ds_dest    //写回级目的操作数寄存器号
	assign ws_to_ds_dest = ws_dest & {5{ws_valid}};
	
ID_stage:
    input   [4:0]   es_to_ds_dest,
    input   [4:0]   ms_to_ds_dest,
    input   [4:0]   ws_to_ds_dest

阻塞信号产生

// IF stage
assign fs_ready_go    = ~br_taken;   // if taken is valid, if stage block

always @(posedge clk) begin
    if (reset) begin
        fs_pc <= 32'h1bfffffc;     //trick: to make nextpc be 0x1c000000 during reset 
    end
    else if (to_fs_valid && (fs_allowin || br_taken)) begin
        // if taken is valid, to skip the delay slot instruction, next_pc should be the instruction after the jump inst
        fs_pc <= nextpc;
    end
end

// if taken is valid and if stage is block, get the instruction after the jump inst
assign inst_sram_en    = to_fs_valid && (fs_allowin || br_taken);
ID_stage:
wire inst_no_dest;
wire src_no_rj;
wire src_no_rk;
wire src_no_rd;
wire rj_wait;
wire rk_wait;
wire rd_wait;
wire no_wait;

// taken signal need to be block too!!!!
assign br_taken = (   inst_beq  &&  rj_eq_rd
                   || inst_bne  && !rj_eq_rd
                   || inst_jirl
                   || inst_bl
                   || inst_b
                )  && ds_valid & no_wait;
                
assign inst_no_dest = inst_st_w | inst_b | inst_beq | inst_bne;

assign src_no_rj    = inst_b | inst_bl | inst_lu12i_w;
assign src_no_rk    = inst_slli_w | inst_srli_w | inst_srai_w | inst_addi_w | inst_ld_w | inst_st_w | inst_jirl | 
                      inst_b | inst_bl | inst_beq | inst_bne | inst_lu12i_w;
assign src_no_rd    = ~inst_st_w & ~inst_beq & ~inst_bne;

assign rj_wait = ~src_no_rj && (rj != 5'b00000) && ((rj == es_to_ds_dest) || (rj == ms_to_ds_dest) || (rj == ws_to_ds_dest));
assign rk_wait = ~src_no_rk && (rk != 5'b00000) && ((rk == es_to_ds_dest) || (rk == ms_to_ds_dest) || (rk == ws_to_ds_dest));
assign rd_wait = ~src_no_rd && (rd != 5'b00000) && ((rd == es_to_ds_dest) || (rd == ms_to_ds_dest) || (rd == ws_to_ds_dest));

assign no_wait = ~rj_wait & ~rk_wait & ~rd_wait;

转移计算未完成

DS为jmp指令,ES为Load指令。

IF_stage:
	wire         br_stall;
	wire         pre_if_ready_go;
	assign {br_stall, br_taken, br_target} = br_bus;
	// pre-IF stage
	assign to_fs_valid  = ~reset && pre_if_ready_go;
	assign pre_if_ready_go = ~br_stall;
	// if taken is valid and if stage is block, get the instruction after the jump inst
	assign inst_sram_en    = to_fs_valid && (fs_allowin || br_taken) && pre_if_ready_go;

ID_stage:
	input           es_to_ds_load_op;
	wire br_stall;
	wire load_stall;
	// es is load and ds is jmp(taken)
	assign br_stall   = load_stall & br_taken & ds_valid;
	assign load_stall = es_to_ds_load_op & (((rj == es_to_ds_dest) & rj_wait) |
	                                        ((rk == es_to_ds_dest) & rk_wait) |
	                                        ((rd == es_to_ds_dest) & rd_wait)); 
	assign br_bus       = {br_stall,br_taken,br_target};

EXE_stage:
	output        es_to_ds_load_op;

mycpu.h:
	`define BR_BUS_WD       34   //修改

Testbench

测试通过
在这里插入图片描述

参考资料

[1] CPU设计实战(汪文祥)第四章
[2] LoongArch CPU设计实验_实践任务8
[3] CDP_EDE_local
[4] 龙芯架构32位精简版参考手册
[5] exp实验发布包下载地址
[6] Loongarch个人赛指令集

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值