250 likes | 483 Views
データハザードとその解決法. 慶應義塾大学 理工学部 天野. PICO のパイプライン構造. RFPC. WB. IF. RF. EX. a. 2. regc. rega. +. ALU. IFPC. regb. c. b. Imm. wadr. IFIR. RFIR. Data Memory. Instruction Memory. パイプラインハザード. パイプライン動作を阻害するもの 構造( Structural) ハザード 各ステージで共有資源がある場合に生じる
E N D
データハザードとその解決法 慶應義塾大学 理工学部 天野
PICOのパイプライン構造 RFPC WB IF RF EX a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
パイプラインハザード • パイプライン動作を阻害するもの • 構造(Structural) ハザード • 各ステージで共有資源がある場合に生じる • 資源を複製すれば解決可能→コストと性能のトレードオフの問題 • データハザード • パイプライン中で並列に実行される複数の命令間のデータの依存性に起因するハザード • 先行命令の結果が書き込まれる前に後続命令がデータを読んでしまう • 制御(Control)ハザード • 分岐命令に起因するハザード • 次に実行する命令がわからなくなる
メモリを共有する場合の構造ハザード RFPC WB IF RF EX a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR 統合 Memory
構造ハザードによるパイプラインストール ステージ 1 ステージ 2 ステージ 3 ステージ 4 LD/ST命令 ステージ 1 ステージ 2 ステージ 3 ステージ 4 ステージ 1 ステージ 2 ステージ 3 ステージ 4 命令フェッチができない ステージ 1 ステージ 2 ステージ 3 ステージ 4 ステージ 1 ステージ 2 ステージ 3 ステージ 4 ストールするパイプラインのCPI = 理想CPI + ダメージの確率×ダメージサイクル
データハザード • 先行命令が書き込む前に後続命令がレジスタファイルからデータを読み込んでしまう。 • RAW(Read After Write)ハザード • WAR(Write After Read)ハザード • WAW(Write After Write)ハザードもあるが今回は関係ない • ストールすると性能低下が大きい • 解決するにはフォワーディングを用いる
ADDI r3,#2 LD r3,(r1) LDLI r1,#0 RFPC IF RF EX WB a 2 regc rega + 0 ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ST (r1),r3 ADDI r3,#2 LD r3,(r1) LDLI r1,#0 RFPC IF RF EX WB a 2 regc rega 0 + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ST (r1),r3 ADDI r3,#2 LD r3,(r1) RFPC IF RF EX WB a 2 regc rega U + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
パイプラインストール LDLI r1,#0 LD r3,(r1) NOP NOP RFPC IF RF EX WB a 2 regc rega 0 + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
NOP LD r3,(r1) NOP NOP RFPC IF RF EX WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
レジスタファイルのフォワーディング RFPC EX IF RF WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ストールサイクルの減少 NOP LD r3,(r1) LDLI r1,#0 NOP RFPC IF RF EX WB a 2 regc rega 0 + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ALUからのフォワーディング RFPC EX IF RF WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ADDI r3,#2 LD r3,(r1) LDLI r1,#0 RFPC EX IF RF WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ST (r1),r3 ADDI r3,#2 LD r3,(r1) LDLI r1,#0 RFPC EX IF RF WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
ST (r1),r3 ADDI r3,#2 LD r3,(r1) RFPC EX IF RF WB a 2 regc rega + ALU IFPC regb c b Imm. wadr IFIR RFIR Data Memory Instruction Memory
今回のverilog記述 ppico16_test.v テストベンチ memory.v メモリ ppico16.v CPU if_stage.v 命令フェッチ rf_stage.v レジスタフェッチ ex_stagef.v (ex_stage.v) 実行 変更はrf_stage, ex_stageのみ 変更 変更 変更
rf_stage.v1 レジスタファイル周辺 wire [DataBus-1:0] dout1; // Register File Output for Source A (Rd) wire [DataBus-1:0] fout1; // Forwarding Source A wire [DataBus-1:0] dout2; // Register File Output for Source B (Rs) wire [DataBus-1:0] fout2; // Forwarding Source B wire [RegNum-1:0] proc_dest, foll_dest; // Destination registers wire [RegNum-1:0] proc_src, foll_src; // Source registers assign foll_dest = ifir[10:8]; assign proc_dest = reg_ir[10:8]; assign foll_src = ifir[7:5]; assign proc_src = reg_ir[7:5]; regfile regfile ( .clk( clk ),.adrA( foll_dest ), .adrB( foll_src), .adrC( rwadr ), .inc( c ),.outa( dout1 ), .outb( dout2 ),.rwe( rwe ) ); // Outputs assign rfir = reg_ir; assign rfpc = reg_pc; assign a = reg_a; assign b = reg_b; assign imm = reg_im; assign fout1 = rwen & (proc_dest == foll_dest) ? result : dout1; assign fout2 = rwen & (proc_dest == foll_src) ? result : dout2;
rf_stage.v 2 レジスタセット always @( posedge clk ) begin if ( reset_ == Enable_ ) begin reg_ir <= NULL; reg_pc <= NULL; reg_a <= NULL; reg_b <= NULL; end else begin reg_ir <= ifir; reg_pc <= ifpc; reg_a <= fout1; reg_b <= fout2; reg_im <= {{8{ifir[7]}},ifir[7:0]}; end end
レジスタファイル本体 module regfile (clk, adrA, adrB, adrC, inc, outa, outb, rwe); `include "pico.h" input clk; input [RegNum-1:0] adrA, adrB, adrC; input [DataBus-1:0] inc; output [DataBus-1:0] outa, outb; input rwe; reg [DataBus-1:0] rfile [0:7]; assign outa = (adrA==adrC) & rwe ? inc : rfile[adrA]; assign outb = (adrB==adrC) & rwe ? inc : rfile[adrB]; always @(posedge clk) if (rwe) rfile[adrC] <= inc; endmodule
ex_stage.v 入出力 module ex_stage (clk,reset_,rfir,rfim,a,b,ddatain,rfpc,c,ddataout, address,rwadr,dmwe,rwe,pcset); `include "pico.h" input clk; input reset_; input [DataBus-1:0] rfir; // IR ( RF stage output ) input [DataBus-1:0] rfim; // Immediate Data input [DataBus-1:0] a; // Source Data A input [DataBus-1:0] b; // Source Data B input [DataBus-1:0] ddatain; // Read Data from D-Memory input [DataBus-1:0] rfpc; // PC (RF stage output ) output [DataBus-1:0] c; // Operation Result output [DataBus-1:0] result; // Operation Result output [DataBus-1:0] ddataout; // Write Data to D-Memory output [AddrBus-1:0] address; // Address for D-Memory access output [RegNum-1:0] rwadr; // Destination Register No output dmwe; // D-Memory Write Enable output rwe; // Register Write Enable output rwen; output pcset; // PC branch address set
ex_stage.v ALU周辺中間信号線 // Intermediate wires assign alu_ina = (op == BNEZ) | (op == BEQZ) ? rfpc: a; assign alu_inb = // Sign extended immediate ( rfir[15:13] == 3‘b001 ) | (op == BEQZ) | (op == BNEZ) | (op == LDLI) ? rfim: (op == ROP) ? b: (op == LDHI) ? {rfir[7:0],8'b0}: // LDHI {8'b0,rfir[7:0]}; // Sign unextended immediate assign aluope = // Braches (op == BEQZ) | (op == BNEZ) ? ADDOP: (op == LDLI) | (op == LDHI) ? THB: // LDLI, LDHI (op == ROP) ? rfir[2:0]: rfir[13:11]; assign rwen = // Disable when Braches or ST (op == BEQZ) | (op == BNEZ) | ((op == ROP) & (op2 == ST)) | ((op == ROP) & (op2 == NOP)) ? Disable : Enable; assign result = // when LD datain ((op == ROP) & (op2 == LD)) ? ddatain : aluout; assign pcsett = ( op == BEQZ )& (a==16'h0000) | ( op == BNEZ )& (a!=16'h0000) ; 信号を外に出すだけ
ppico.v ステージ間接続 assign iaddr = ifpc; // Fetch Addr to Instruction Memory if_stage if_stage ( .clk( clk ), .reset_( reset_ ), .idata( idata ), .pcset( pcset ), .badr( c ), .ifpc( ifpc ), .ifir( ifir ) ); rf_stage rf_stage ( .clk( clk ), .reset_( reset_ ), .ifir( ifir ), .ifpc( ifpc ), .rwe( rwe ), .rwen(rwen), .c( c ), .result(result), .rwadr( rwadr ), .rfpc( rfpc ), .rfir( rfir ), .a( a ), .b( b ), .imm( imm ) ); ex_stage ex_stage ( .clk( clk ) .reset_( reset_ ),.rfir( rfir ), .a( a ), .b( b ), .rfim( imm ), .ddatain( ddatain ), .rfpc(rfpc), .c( c ), .result(result), .ddataout( ddataout ), .address( daddr ), .rwadr( rwadr ), .dmwe( dmwe ), .rwe( rwe ), .rwen(rwen), .pcset(pcset) );
演習 • fowardingをやらない場合、以下の仮定でCPIがどうなるか計算せよ • 理想のCPIは1 • 先行命令の結果を次の命令が利用する可能性が70% • 分岐命令の影響については無視