PICOのパイプライン化 慶應義塾大学 理工学部 天野 PICOの構成(前期の図を若干変更) aluout regc outc MUX MUX pc op com ir op2 op 110 ALU 001 alubin Expander MUX ‘2’ op2 dest idata src regb aluain MUX rega adrA adrB regfile ddataout MUX iadr Instruction Memory we_ dadr Data Memory ddatain パイプライン処理の設計 • 大きな処理を一定の同じ大きさの小さな段階(ス テージ)に分解 • それぞれのステージにそれぞれの処理装置を設け る • 順にデータを流してやり、自分の処理が終わったら すぐ次のステージに渡す • 流れ作業と基本は同じ • ステージ数をSとすると、理想の場合は性能はS倍 – ステージの処理量が均等でないと、最も重いものに律速 される – ステージ間の受け渡しで大概ロスがある パイプライン処理 組合せ回路 ステージ 1 ステージ 2 ステージ 3 ステージ 4 時間 ステージステージステージステージ 2 3 4 1 ステージステージステージステージ 2 3 4 1 ステージステージステージステージ 2 3 4 1 ステージステージステージステージ 2 3 4 1 流れ作業(パイプライン処理) vs 多人数による並列処理 • S人居れば最大S倍、これは同じ • 流れ作業は、各人がそのステージの処理だけでき れば良い ⇔並列処理は、すべての人が全作業を する能力がなければならない • 流れ作業は、各人がそのステージの処理をするの に必要な工具(リソース)を持てば良い⇔並列処理 は、すべての人がすべての工具、場所を持つ必要 がある • このため、日常的な作業効率向上、工場のオート メーションなどもまずは流れ作業を導入する 状態遷移→ステージ 結果を書き込む命令 それ以外:分岐、STなど IF irに命令を フェッチ RF レジスタ 読み出し PC←PC+2 EX WB 演算実行 結果の格納 飛び先セット メモリからの読み 書き込み パイプライン化されていない設計が良くできていれば、それぞれの状態は 遅延時間がほぼ均等に分割されているはず。このため、状態をそのまま パイプラインのステージに割り当ててしまうのが基本的な設計手法 PICOのパイプライン構造 IF RF RFPC WB EX a 2 regc ALU + rega IFPC regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory LDLI r1,#1 IF RF RFPC EX WB a 2 regc ALU + rega IFPC regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory LDLI r2,#2 LDLI r1,#1 IF RF RFPC EX WB a 2 regc ALU + rega IFPC regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory LDLI r3,#3 LDLI r2,#2 IF RF LDLI r1,#1 RFPC EX WB a 2 ALU + rega IFPC 1 regc regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory ADD r1,#2 LDLI r3,#3 IF RF LDLI r2,#2 RFPC LDLI r1,#1 EX WB a 2 ALU + rega IFPC 2 regc regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory 1 ADD r2,r2 ADD r1,#2 IF RF LDLI r3,#3 RFPC LDLI r2,#2 EX WB a 2 ALU + rega IFPC 3 regc regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory 2 ADD r2,r2 IF RF ADD r1,#2 RFPC LDLI r3,#3 EX WB a 2 ALU + rega IFPC 3 regc regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory 3 ADD r2,r2 IF RF RFPC ADD r1,#2 EX WB a 2 ALU + rega IFPC 4 regc regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory 3 ADD r2,r2 IF RF RFPC EX WB a 2 regc ALU + rega IFPC regb c b IFIR Instruction Memory Imm. wadr RFIR Data Memory 4 今回のverilog記述 ppico16_test.v テストベンチ memory.v メモリ ppico16.v CPU 合成対象 if_stage.v 命令フェッチ rf_stage.v レジスタフェッチ ex_stagef.v (ex_stage.v) 実行 パイプライン化はしてある Data Hazard, Control Hazardの除去はしてない →これは来週 if_stage.v module if_stage ( clk, reset_, idata, pcset, badr, ifpc, ifir); `include "pico.h" input clk, reset_; input [DataBus-1:0] idata; // Data from I-Cache input pcset; // Branch Taken Signal input [AddrBus-1:0] badr; // Branch Addr output [AddrBus-1:0] ifpc; // PC ( IFstage output ) output [DataBus-1:0] ifir; // IR ( IFstage output ) reg [AddrBus-1:0] pc; reg [DataBus-1:0] ir; assignifpc = pc; assignifir = ir; always @( posedge clk ) begin if ( reset_ == Enable_ ) begin pc <= NULL; ir <= NULL; pcsetが1ならば分岐先ア end else begin ドレスのセット ir <= idata; if( pcset == Enable ) begin そうでなければ+2 pc <= badr; end (バイトアドレスなので) else begin pc <= ifpc + 2; end end end pico.h コードの定義 parameter Enable = 1'b1; parameter Disable = 1'b0; parameter Enable_ = 1'b0; parameter Disable_ = 1'b1; parameter AddrBus = 16; parameter DataBus = 16; parameter ComNum = 3; parameter RegNum = 3; parameter StateNum = 4; parameter MemSize = 32768; parameter Opcode = 5; parameter NULL = 16'h0000; parameter ROP = 5'b00000; parameter LDLI = 5'b11100; parameter LDHI = 5'b11101; parameter BNEZ = 5'b01001; parameter BEQZ = 5'b01010; parameter JMP = 5'b01111; parameter LD = 5'b01000; parameter ST = 5'b01001; parameter NOP = 5'b00000; parameter THA = 3'b000; parameter THB = 3'b001; parameter ANDOP = 3'b010; parameter OROP = 3'b011; parameter SLOP = 3'b100; parameter SROP = 3'b101; parameter ADDOP = 3'b110; parameter SUBOP = 3'b111; rf_stage.v 1 入出力と定義 module rf_stage ( clk, reset_, ifir, ifpc, rwe, c, rwadr, rfpc, rfir, a, b, imm ); `include "pico.h" input clk; input reset_; input [DataBus-1:0] ifir; // IR ( IF stage output ) input [AddrBus-1:0] ifpc; // PC ( IF state output ) input rwe; // Register Write Enable (c) input [DataBus-1:0] c; // Destination Data input [RegNum-1:0] rwadr; // Destination Register No output [DataBus-1:0] rfpc; // PC ( RFstage output ) output [DataBus-1:0] rfir; // IR ( RFstage output ) output [DataBus-1:0] a; // Source Data A output [DataBus-1:0] b; // Source Data B output [DataBus-1:0] imm; // Immediate Data // Pipeline Registers reg [DataBus-1:0] reg_a; reg [DataBus-1:0] reg_b; reg [DataBus-1:0] reg_im; reg [DataBus-1:0] reg_ir; reg [AddrBus-1:0] reg_pc; // Outputs assignrfir = reg_ir; assignrfpc = reg_pc; assigna = reg_a; assignb = reg_b; assignimm = reg_im; rf_stage.v 2 レジスタファイルとレジスタセット // Register File wire [DataBus-1:0] dout1; // Register File Output for Source A (Rd) wire [DataBus-1:0] dout2; // Register File Output for Source B (Rs) regfile regfile ( // See regfile.v .clk( clk ), .adrA( ifir[10:8] ), // Read Address for Source A .adrB( ifir[7:5] ), // Read Address for Source B .adrC( rwadr ), // Write Address .inc( c ), // Write Data .outa( dout1 ), .outb( dout2 ), .rwe( rwe ) // Write Enable ); 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 <= dout1; reg_b <= dout2; reg_im <= {{8{ifir[7]}},ifir[7:0]}; end end endmodule レジスタファイル本体 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 = rfile[adrA]; assign outb = rfile[adrB]; always @(posedge clk) if (rwe) rfile[adrC] <= inc; endmodule データ入力用Cポートを独立 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] input [DataBus-1:0] input [DataBus-1:0] input [DataBus-1:0] input [DataBus-1:0] input [DataBus-1:0] rfir; rfim; a; b; ddatain; rfpc; output [DataBus-1:0] output [DataBus-1:0] output [AddrBus-1:0] output [RegNum-1:0] output dmwe; output rwe; output pcset; c; // Operation Result ddataout; // Write Data to D-Memory address; // Address for D-Memory access rwadr; // Destination Register No // D-Memory Write Enable // Register Write Enable // PC branch address set // IR ( RF stage output ) // Immediate Data // Source Data A // Source Data B // Read Data from D-Memory // PC (RF stage output ) ex_stage.v レジスタと簡単な論理部の接続 // Pipeline Registers reg reg reg reg [DataBus-1:0] [RegNum-1:0] reg_rwe; pcsetr; // Temporary Wire wire [DataBus-1:0] wire [ComNum-1:0] wire [DataBus-1:0] wire [DataBus-1:0] wire rwen; wire pcsett; wire [Opcode-1:0] op, op2; wire [RegNum-1:0] dest; reg_c; reg_rwadr; aluout; // ALU Output aluope; // ALU Operation alu_ina, alu_inb;// Temporary Wire for ALU Source B result; // Temporary Wire for results // Output assign rwadr = reg_rwadr; assign rwe = reg_rwe; assign c = reg_c; assign pcset = pcsetr; assign address = (op ==ROP) & (op2 == ST)? a : b; assign ddataout = b; assign op = rfir[15:11]; assign dest = rfir[10:8]; assign op2 = rfir[4:0]; assign dmwe = ( op == ROP )& (op2 == ST) ? Enable : Disable; ex_stage.v ALU // ALU operation assignaluout = alu ( alu_ina, alu_inb, aluope ); // ALU ( ThrohghA, ThrohghB, And, Or, ShiftLeft, ShiftRight, Add, Sub ) function [DataBus-1:0] alu ; input [DataBus-1:0] a, b; input [ComNum-1:0] com; case(com) THA: alu = a ; THB: alu = b ; ANDOP: alu = a & b; OROP: alu = a | b; SLOP: alu = a << b[3:0]; SROP: alu = a >> b[3:0]; ADDOP: alu = a + b; SUBOP: alu = a - b; endcase endfunction 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) ; ex_stagef.v functionの利用 // Intermediate wires assign alu_ina = (op == BNEZ) | (op == BEQZ) ? rfpc: a; function [DataBus-1:0] aluinb; input [Opcode-1:0] ope; input [7:0] imm; input [DataBus-1:0] rfim, b; if(ope[4:2]==3'b001) aluinb = rfim; else case(ope) BEQZ, BNEZ, LDLI : aluinb = rfim; ROP: aluinb = b; LDHI: aluinb = {imm,8'b0}; default: aluinb = {8'b0,imm}; endcase endfunction assign alu_inb = aluinb(op,rfir[7:0],rfim,b); function [ComNum-1:0] aluope; input [Opcode-1:0] ope; input [ComNum-1:0] func; case (ope) BEQZ, BNEZ : aluope = ADDOP; LDLI, LDHI : aluope = THB; ROP: aluope = func; default: aluope = ope[ComNum-1:0]; endcase endfunction assign alu_ope = aluope(op,op2[ComNum-1:0]); 複雑な記述をfunction文で 置き換える 簡単なものは今ま で通り ex_stage.v レジスタのセット always @ ( posedge clk or negedge reset_ ) begin if ( reset_ == Enable_ ) begin reg_c <= NULL; reg_rwadr <= NULL; reg_rwe <= Disable; pcsetr <= Disable; end else begin // See Figure reg_c <= result; reg_rwadr <= dest; reg_rwe <= rwen; pcsetr <= pcsett; end end ppico.v 入出力と接続信号線 module ppico16 ( clk, reset_, idata, ddatain, iaddr, daddr, ddataout, dmwe ); `include "pico.h" input clk, reset_; input [DataBus-1:0] idata; // Instruction Data from I-Memory input [DataBus-1:0] ddatain; // Read Data from D-Memory output [AddrBus-1:0] iaddr; // Instruction Addr to I-Memory output [AddrBus-1:0] daddr; // Data Addr to D-Memory output [DataBus-1:0] ddataout; // Write Data to D-Memory output dmwe; // D-Memory Write Enable // IF & RF stage wire pcset; // Branch Taken Signal wire [AddrBus-1:0] ifpc; // PC ( IFstage output ) wire [DataBus-1:0] ifir; // IR ( IFstage output ) // RF stage wire rwe; // Register Write Enable wire rwen; // RWE for Next Clock Cycle // RF & EX stage wire [DataBus-1:0] a; // Source Data A wire [DataBus-1:0] b; // Source Data B wire [DataBus-1:0] c; // Destination Data wire [DataBus-1:0] imm; // Immediate Data wire [ComNum-1:0] rwadr; // Destination Register No wire [DataBus-1:0] rfir; // IR ( RFstage output ) wire [AddrBus-1:0] rfpc; // PC ( RFstage output ) ppico.v ステージ間接続 assign iaddr = ifpc; Memory // Fetch Addr to Instruction 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 ), .c( c ), .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 ), .ddataout( ddataout ), .address( daddr ), .rwadr( rwadr ), .dmwe( dmwe ), .rwe( rwe ), .pcset(pcset) ); test.prg 11100_001_00000001 11100_010_00000010 11100_011_00000011 00110_001_00000010 00000_010_010_00110 00000_000_00000000 00000_000_00000000 00000_000_00000000 00000_000_00000000 00000_000_00000000 // LDLI r1,#1 // LDLI r2,#2 // LDLI r3,#3 // ADDI r1#2 // ADD r2,r2 // NOP // NOP // NOP // NOP // NOP ikarus verilog で実行してgtkwaveで波形を見てみよう 演習 • LDHI2 rd,#X rdの上位8ビットにXをセットし、下位8ビットは rdのままにする命令を付け加えてみよ。
© Copyright 2024 ExpyDoc