日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自己动手写CPU(2)流水线数据相关问题

發布時間:2023/12/19 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自己动手写CPU(2)流水线数据相关问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

自己動手寫CPU(2)流水線數據相關問題

問題定義

流水線中經常有一些被稱為“相關”的情況發生,它使得指令序列中下一條指令無法按照設計的時鐘周期執行,這些“相關”會降低流水線的性能。流水線中的相關分為以下三種類型。

  • 結構相關:指的是在指令執行的過程中,由于硬件資源滿足不了指令執行的要求,發生硬件資源沖突而產生的相關。比如:指令和數據都共享一個存儲器,在某個時鐘周期,流水線既要完成某條指令對存儲器中數據的訪問操作,又要完成后續的取指令操作,這樣就會發生存儲器訪問沖突,產生結構相關。
  • 數據相關:指的是在流水線中執行的幾條指令中,一條指令依賴于前面指令的執行結果。
  • 控制相關:指的是流水線中的分支指令或者其他需要改寫PC的指令造成的相關。
  • 本節重點分析數據相關的問題,流水線數據相關又分為三種情況:RAW、WAR、WAW

    • RAW,即 Read After Write,假設指令j是在指令i后面執行的指令,RAW表示指令i將數據寫入寄存器后,指令j才能從這個寄存器讀取數據。如果指令j在指令i寫入寄存器前嘗試讀出該寄存器的內容,將得到不正確的數據。
    • WAR,即 Write After Read,假設指令j是在指令i后面執行的指令,WAR表示指令i讀出數據后,指令j才能寫這個寄存器。如果指令j在指令i讀出數據前就寫該寄存器,將使得指令i讀出的數據不正確。
    • WAW,即 Write After Write,假設指令j是在指令i后面執行的指令,WAW表示指令i將數據寫入寄存器后,指令j才能將數據寫入這個寄存器。如果指令j在指令i之前寫該寄存器,將使得該寄存器的值不是最新值。

    對我們之前建立的原始OpenMIPS五級流水線而言,只有在流水線回寫階段才會寫寄存器,因此不存在WAW相關;又因為只能在流水線譯碼階段讀寄存器、回寫階段寫寄存器,不存在WAR相關;所以OpenMIPS的流水線只存在RAW相關。RAW相關有三種情況:

    1、相鄰指令間存在數據相關

    ori $1,$0,0x1100 ori $2,$1,0x0020

    2、相隔1條指令的指令間存在數據相關

    ori $1,$0,0x1100 ori $3,$0,0xffff ori $2,$1,0x0020

    3、相隔2條指令的指令間存在數據相關

    ori $1,$0,0x1100 ori $3,$0,0xffff ori $4,$0,0xffff ori $2,$1,0x0020

    上述所說的相隔兩條指令存在數據相關的問題已經在之前設計的Regfile模塊中得到了解決,此處不再贅述;

    對于相鄰指令間存在數據相關、相隔1條指令的指令間存在數據相關這兩種情況,有三種解決方法。

  • 插入暫停周期:當檢測到相關時,在流水線中插入一些暫停周期;
  • 編譯器調度:編譯器檢測到相關后,可以改變部分指令的執行順序;
  • 數據前推:將計算結果從其產生處直接送到其他指令需要處或所有需要的功能單元處,避免流水線暫停;
  • 解決方案

    我們采用數據前推的方式解決流水線數據相關問題。完善后的數據流圖如下所示,主要是將執行階段的結果、訪存階段的結果前推到譯碼階段,參與譯碼階段選擇運算源操作數的過程。

    主要的修改在兩個方面:

  • 將處于流水線執行階段的指令的運算結果,包括:是否要寫目的寄存器wreg_o、要寫的目的寄存器地址wd_o、要寫入目的寄存器的數據wdata_o等信息送到譯碼階段。
  • 將處于流水線訪存階段的指令的運算結果,包括:是否要寫目的寄存器wreg_o、要寫的目的寄存器地址 wd o、要寫入目的寄存器的數據wdata_o等信息送到譯碼階段。
  • 測試結果

    用如下的匯編代碼進行程序的測試

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

    指令的注釋給出了預期的執行效果,我們首先用上章的項目工程進行測試,波形圖如下:

    由圖可見,譯碼階段的reg1_o有X階段,這是由于讀reg1_o時,第一條指令還未進行到reg1的回寫階段,所以第二和第三條指令讀取reg1的值時為X,當第四條指令讀取reg1時,第一條指令處于回寫階段,這種沖突我們在之前的Regfile里解決過了,所以第四條指令才能讀到reg1的值。可見由于數據間沖突,指令的結果不正確,我們要對譯碼模塊做適當修改。

    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 //給reg1_o賦值的過程增加了兩種情況 //1.如果Regfile模塊讀端口1要讀取的寄存器就是執行階段要寫的目的寄存器, //那么直接把執行階段的結果ex_data_i作為reg1_o的值 //2.如果Regfile模塊讀端口1要讀取的寄存器就是訪存階段要寫的目的寄存器, //那么直接把訪存階段的結果mem_data_i作為reg1_o的值 always @(*) beginif(rst == `RstEnable) beginreg1_o = `ZeroWord;endelse if((reg1_read_o == `ReadEnable) && (ex_wreg_i == `WriteEnable) && (ex_wd_i == reg1_addr_o))beginreg1_o = ex_wdata_i;endelse if((reg1_read_o == `ReadEnable) && (mem_wreg_i == `WriteEnable) && (mem_wd_i == reg1_addr_o)) beginreg1_o = mem_wdata_i;endelse if(reg1_read_o == `ReadEnable) beginreg1_o = reg1_data_i;endelse if(reg1_read_o == `ReadDisable) beginreg1_o = imm;endelse beginreg1_o = `ZeroWord;end end//確定進行運算的操作數2 //給reg2_o賦值的過程與reg1_o同理 always @(*) beginif(rst == `RstEnable) beginreg2_o = `ZeroWord;endelse if((reg2_read_o == `ReadEnable) && (ex_wreg_i == `WriteEnable) && (ex_wd_i == reg2_addr_o))beginreg2_o = ex_wdata_i;endelse if((reg2_read_o == `ReadEnable) && (mem_wreg_i == `WriteEnable) && (mem_wd_i == reg2_addr_o)) beginreg2_o = mem_wdata_i;endelse if(reg2_read_o == `ReadEnable) beginreg2_o = reg2_data_i;endelse if(reg2_read_o == `ReadDisable) beginreg2_o = imm;endelse beginreg2_o = `ZeroWord;end endendmodule

    其中執行階段判斷的優先級比訪存階段高的原因是執行階段在流水線中比訪存階段靠前,寫入寄存器的值也是最新的值,所以體現在if上優先級就高于訪存階段。再修改頂層模塊OpenMIPS對應的代碼,增加連線關系即可,修改后的代碼跑出的波形圖如下圖所示:

    由上圖可見,reg1的值與預期一致,解決了數據沖突的問題。寫入寄存器的值也是最新的值,所以體現在if上優先級就高于訪存階段。再修改頂層模塊OpenMIPS對應的代碼,增加連線關系即可,修改后的代碼跑出的波形圖如下圖所示:

    由上圖可見,reg1的值與預期一致,解決了數據沖突的問題。

    項目鏈接

    總結

    以上是生活随笔為你收集整理的自己动手写CPU(2)流水线数据相关问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。