• 技术文章 >数据库 >mysql教程

    自己动手写CPU之第五阶段(2)OpenMIPS对数据相关问题的解决

    2016-06-07 15:20:23原创1284

    将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第16篇,我尽量每周四篇 5.2OpenMIPS 对数据相关问题的解决措施 OpenMIPS 处理器采用数据前推的方法来解决流水线数据相关问题。通过补充完善图 4-4 原始的数据流图,添加部分信号使得可以完成数

    将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第16篇,我尽量每周四篇


    5.2 OpenMIPS对数据相关问题的解决措施

    OpenMIPS处理器采用数据前推的方法来解决流水线数据相关问题。通过补充完善图4-4原始的数据流图,添加部分信号使得可以完成数据前推的工作,如图5-7所示。主要是将执行阶段的结果、访存阶段的结果前推到译码阶段,参与译码阶段选择运算源操作数的过程。


    5-8给出了为实现数据前推而对OpenMIPS系统结构所做的修改。有两个方面。

    1)将处于流水线执行阶段的指令的运算结果,包括:是否要写目的寄存器wreg_o、要写的目的寄存器地址wd_o、要写入目的寄存器的数据wdata_o等信息送到译码阶段,如图5-8中虚线所示。

    2)将处于流水线访存阶段的指令的运算结果,包括:是否要写目的寄存器wreg_o、要写的目的寄存器地址wd_o、要写入目的寄存器的数据wdata_o等信息送到译码阶段。


    为此,译码阶段的ID模块要增加如表5-1所示的接口。


    译码阶段的ID模块会依据送入的信息,进行综合判断,解决数据相关,给出最后要参与运算的操作数。ID模块的代码要做如下修改,其中主要修改部分使用加粗、斜体表示。修改后的代码位于本书光盘的Code\Chapter5_1目录下的id.v文件。

    module id(
    
    	......
    
    	//处于执行阶段的指令的运算结果
    	input wire			   ex_wreg_i,
    	input wire[`RegBus]		   ex_wdata_i,
    	input wire[`RegAddrBus]       ex_wd_i,
    	
    	//处于访存阶段的指令的运算结果
    	input wire		          mem_wreg_i,
    	input wire[`RegBus]           mem_wdata_i,
    	input wire[`RegAddrBus]       mem_wd_i,
    	
    ...... 	      
    	
    	//送到执行阶段的源操作数1、源操作数2
    	output reg[`RegBus]           reg1_o,
    	output reg[`RegBus]           reg2_o,
    	......
    );
    
           ......
    
           //给reg1_o赋值的过程增加了两种情况:
           //1、如果Regfile模块读端口1要读取的寄存器就是执行阶段要写的目的寄存器,
           //   那么直接把执行阶段的结果ex_wdata_i作为reg1_o的值;
           //2、如果Regfile模块读端口1要读取的寄存器就是访存阶段要写的目的寄存器,
           //   那么直接把访存阶段的结果mem_wdata_i作为reg1_o的值;
        	always @ (*) begin
    	  if(rst == `RstEnable) begin
    		reg1_o <= `ZeroWord;		
    	  end else if((reg1_read_o == 1'b1) && (ex_wreg_i == 1'b1) 
    			   && (ex_wd_i == reg1_addr_o)) begin
    		reg1_o <= ex_wdata_i; 
    	  end else if((reg1_read_o == 1'b1) && (mem_wreg_i == 1'b1) 
    		          && (mem_wd_i == reg1_addr_o)) begin
    		reg1_o <= mem_wdata_i; 			
    	  end else if(reg1_read_o == 1'b1) begin
    	  	reg1_o <= reg1_data_i;
    	  end else if(reg1_read_o == 1'b0) begin
    	  	reg1_o <= imm;
    	  end else begin
    	    reg1_o <= `ZeroWord;
    	  end
    	end
    
           //给reg2_o赋值的过程增加了两种情况:
           //1、如果Regfile模块读端口2要读取的寄存器就是执行阶段要写的目的寄存器,
           //   那么直接把执行阶段的结果ex_wdata_i作为reg2_o的值;
           //2、如果Regfile模块读端口2要读取的寄存器就是访存阶段要写的目的寄存器,
           //   那么直接把访存阶段的结果mem_wdata_i作为reg2_o的值;
    	always @ (*) begin
    	  if(rst == `RstEnable) begin
    		reg2_o <= `ZeroWord;
    	   end else if((reg2_read_o == 1'b1) && (ex_wreg_i == 1'b1) 
    			    && (ex_wd_i == reg2_addr_o)) begin
    		reg2_o <= ex_wdata_i; 
    	   end else if((reg2_read_o == 1'b1) && (mem_wreg_i == 1'b1) 
    			    && (mem_wd_i == reg2_addr_o)) begin
    		reg2_o <= mem_wdata_i;			
    	   end else if(reg2_read_o == 1'b1) begin
    	  	reg2_o <= reg2_data_i;
    	   end else if(reg2_read_o == 1'b0) begin
    	  	reg2_o <= imm;
    	   end else begin
    	       reg2_o <= `ZeroWord;
    	  end
    	end
    
    endmodule

    除了修改译码阶段ID模块的代码,还要修改顶层模块OpenMIPS对应的代码,在其中增加图5-8所示的连接关系。具体修改过程不在书中列出,读者可以参考本书附带光盘的Code\Chapter5_1目录下的openmips.v文件。(代码会在稍后上传)

    5.3 测试数据相关问题解决效果

    测试程序如下,其中存在5.1节讨论的RAW相关的三种情况,源文件是本书附带光盘Code\Chapter5_1\AsmTest目录下的inst_rom.S文件。

    .org 0x0
    .global _start
    .set noat
    _start:
       ori $1,$0,0x1100        # $1 = $0 | 0x1100 = 0x1100
       ori $1,$1,0x0020        # $1 = $1 | 0x0020 = 0x1120
       ori $1,$1,0x4400        # $1 = $1 | 0x4400 = 0x5520
       ori $1,$1,0x0044        # $1 = $1 | 0x0044 = 0x5564

    指令的注释给出了预期执行效果。将上述inst_rom.S文件,与第4章实现的Bin2Mem.exeMakefileram.ld这三个文件拷贝到Ubuntu虚拟机中的同一个目录下,打开终端,使用cd命令进入该目录,然后输入make all,即可得到能够用于ModelSim仿真的inst_rom.data文件。

    ModelSim中新建一个工程,添加本书附带光盘Code\Chapter5_1目录下的所有.v文件,然后可以编译。再复制上面得到的inst_rom.data文件到ModelSim工程的目录下,就可以进行仿真了。ModelSim中新建工程、仿真的详细步骤可以参考第2章。

    运行仿真,观察寄存器$1值的变化,如图5-9所示,$1的变化符合预期,所以修改后的OpenMIPS正确解决了数据相关问题。



    下一步将实现逻辑、移位、空指令,敬请关注!
    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    上一篇:Docker版本升级(从1.2.0升级到1.3.0) 下一篇:SQLSERVER监控复制并使用数据库邮件功能发告警邮件
    大前端线上培训班

    相关文章推荐

    • 一文讲解Mysql怎么根据ID值的顺序返回结果• 全面讲解MySQL8.0 For Windows的安装方法• MySQL中什么是索引?索引存储模型浅析• 聊聊mysql的cmake方式• 分析MySQL用户中的百分号%是否包含localhost?

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网