SimAlpha : C++で記述した もうひとつのAlphaプロセッサシミュレータ 電気通信大学 大学院情報システム学研究科 吉瀬謙二 本多弘樹 弓場 敏嗣 2002-08-23 SWoPP 2002 発表資料 1 はじめに アーキテクチャの研究、教育のツールとして様々なプロセッサ シミュレータが利用されている。 定番の SimpleScalarは、高速なシミュレーションが目的の一つ であり、変更が容易なコード記述にはなっていない。 シンプルで理解しやすく、変更が容易なコード記述を第一の条 件として、Alphaプロセッサシミュレータ SimAlpha Version 1.0 を 構築した。 本発表では SimAlpha の高いコード可読性を示すために、変更 を加えていないC++の本物のコードを示しながら、その実装内 部の説明を試みる。 利用列として、SPEC CINT95とCINT2000の理想的な命令レベ ル並列性を測定した結果を報告する。 2 SimAlpha Version 1.0 の設計方針 可読性と拡張性 もう一つの実装 世の中のコードが可読性を考慮している訳ではない。 シンプルで理解しやすく、変更が容易なコード記述を第一の条件と してゼロから記述した。 グローバル変数、goto文、条件付きコンパイルを利用していない。 インクルードファイルを含むソースはC++で約2800行と少ない。 SPEC CINT95 と CINT2000 のバイナリをシミュレートできる。 SimpleScalar の置換えをねらうのではなく、もう一つの実装を示す。 利用者が多くの選択肢の中から、適切なツールを選べる利点は大 きい。 機能レベルシミュレータ(クロックレベルではない) アウトオブオーダ実行の性能評価シミュレータを考慮した記述 次の版において、性能評価シミュレータを提供予定 3 機能レベル(命令レベル)シミュレータ Functional simulation Performance modeling SimpleScalar では sim-safe, sim-fast 動作検証 命令の実行頻度 (Instruction Mix) 命令レベルで測定した分岐予測のヒット率 命令レベルで測定したキャッシュシステムのヒット率 理想的な命令レベル並列性 Logic design Circuit design Layout design Figure 1. Typical flow in microprocessor design process. Interaction between the process steps refines the performance model throughout the process. (IEEE Computer, February 2002, p 30) 4 SimAlpha のファイル構成 Line Word 340 73 356 871 73 201 368 271 187 179 15 562 2968 193 1570 2948 199 626 1173 811 647 491 49 1234 3496 2727 12909 8178 Byte Filename 17992 1556 13174 21347 1882 5286 11142 7751 4505 4412 417 14871 COPYING Makefile README.txt arithmetic.cc chip.cc debug.cc define.h etc.cc instruction.cc memory.cc sim.cc syscall.cc ソースコードとヘッダファイ ルの合計C++で2727行と非 常に少ない。 GNU GENERAL PUBLIC LICENSE Version 2 arithmetic.cc 871行は加算 や減算などの命令実行の記 述で、理解は容易 syscall.cc 562行はシステム コールの実装 これらを除いた核の部分は 1300行程度 104335 total 71613 total *.cc *.h 5 SimAlpha の実行と動作検証 Intel Linux 上で動作 SimpleScalar を用いた動作検証 1命令実行する度に、SimpleScalar と SimAlpha の全てのアーキ テクチャステートを比較し、一致することを確認 SPEC CINT95と CINT2000を用いて動作検証 シミュレーション動作速度 sim-safe (SimpleScalar) の3倍の時間を必要とする。 シミュレーション開発の時間を短縮できれば、3倍程度の速度差 は問題にならない範囲 独自形式の実行イメージファイルを入力 Alphaバイナリと入力パラメータを用いて構築 6 SimAlpha の実行イメージファイル 独自形式の実行イメージ /* SimAlpha 1.0 Image File */ ファイルを採用した。 /*** Registers ***/ テキストファイルの前半にレ /@reg 16 0000000000000003 ジスタの内容を列挙する。 /@reg 17 000000011ff97008 後半でメモリの内容を列挙 /@reg 29 0000000140023e90 する。 /@reg 30 000000011ff97000 テキスト形式、容量の大き /@pc 32 0000000120007d80 いもので4MB程度 /*** Memory ***/ ELF,COFF といった実行ファ @11ff97000 00000003 イル形式やローダの知識が @11ff97008 1ff97138 必要ない。 @11ff9700c 00000001 初心者に優しい。 7 SimAlpha のソフトウェアアーキテクチャ コードの高い可読性を示すために、変更を加えていないC++の本 物のコードを示しながら、SimAlpha の実装内部の説明を試みる。 メイン関数で生成されるオブジェクトchipのコンストラクタが、7つ のオブジェクトを生成する。 simple_chip chip instruction p system_manager sys architecture_state as system_config sc memory_system mem evaluation_result e SimAlpha Version 1.0 における7つのオブジェクトの参照関係 8 SimAlpha のメイン関数 : sim.cc int main(int argc, char **argv){ if(argc==1) usage(); char *p = argv[argc-1]; /* program name */ char **opt = argv; /* options */ simple_chip *chip = new simple_chip(p, opt); while(chip->step()); delete chip; return 0; } 実行例 SimAlpha -e10000 -v100 aout.txt option program name シンプルな記述 グローバル変数を利用していない。 9 SimAlpha のメイン関数 : sim.cc 2つの実行イメージを作成する例 int main(int argc, char **argv){ if(argc==1) usage(); char *p = argv[argc-1]; /* program name */ char **opt = argv; /* options */ simple_chip *chipA = new simple_chip(p, opt); simple_chip *chipB = new simple_chip(p, opt); while(chipA->step() || chipB->step()); delete chipA; delete chipB; return 0; } 10 simple_chip のコンストラクタ simple_chip::simple_chip(char *prog, char **opt){ sc = new system_config(prog, opt); e = new evaluation_result; as = new architecture_state(sc, e); mem = new memory_system(sc, e); deb = new debug(as, mem, sc, e); sys = new system_manager(as, mem, sc, e); p = new instruction(as, mem, sys, sc, e); } instruction p system_manager sys architecture_state as system_config sc memory_system mem evaluation_result e simple_chip で作られる6つのオブジェクトの参照関係 11 データオブジェクトとアーキテクチャステートの定義 class data_t{ uint64_t value; public: int cmov; uint64_t ld(); int st(uint64_t); int init(uint64_t); }; SimAlpha の利用するデータはメモリを 含め 左に示す data_t型のオブジェク トにより表現する。 データ値以外の特性を持たせることが できる。様々なデータを収集できる。 class architecture_state{ public: data_t pc; /* program counter */ data_t r[32]; /* general purpose regs */ data_t f[32]; /* floating point regs */ architecture_state(system_config *, evaluation_result *); }; data_t型の配列 によりレジスタファ イルを構成する。 整数レジスタ、浮 動小数点レジスタ、 プログラムカウン タによりアーキテ クチャステートを 定義 12 1つの命令を処理する関数 step のコード int simple_chip::step(){ p->Fetch(&as->pc); /* p->Slot(); /* p->Rename(); /* p->Issue(); /* p->RegisterRead(); /* p->Execute(&as->pc); /* p->Memory(); /* p->WriteBack(); pipeline pipeline pipeline pipeline pipeline pipeline pipeline stage stage stage stage stage stage stage 0 1 2 3 4 5 6 */ */ */ */ */ */ */ /* split a conditional move,see README.txt */ execute_cmovb(p, as); e->retired_inst++; house_keeper(sys, sc, e, deb); return sys->running; } Alpha 21264 の命令パイプラインを参考にして処理を分割した。 13 SimAlpha Version 1.0 のソフトウェアアーキテクチャ simple_chip -> step() は、instruction の8つの関数を呼び出 すことにより1命令を処理する。 instruction の8つの関数は、必要に応じてアーキテクチャス テートを参照・更新する。 重要な役割を果たすクラスinstructionの定義とコードを説明 する。 architecture_state simple_chip -> step() instruction Fetch Slot Ren Issue RR Ex Mem Wb architecture_state architecture_state, simple_chip -> step, instruction の関係 14 クラス instruction の定義 class instruction{ evaluation_result architecture_state system_manager memory_system INST_TYPE ir; int Op; int RA; int RB; int RC; int ST; int LD; int LA; int BR; int Ai; int Bi; int Af; int Bf; int WF; int WB; data_t Npc; data_t Imm; data_t Adr; data_t Rav; data_t Rbv; data_t Rcv; /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* *e; *as; *sys; *mem; 32bit instruction code Opcode field Ra field of the inst Rb field of the inst Rc field of the inst store inst ? load inst ? load address inst ? branch inst ? Rav is immediate ? Rbv is immediate ? Rav from floating-reg ? Rbv from floating-reg ? Write to the f-reg ? Writeback reg index Update PC or PC + 4 immediate load & store address Ra Rb Rc */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ public: int Fetch(data_t *); int Fetch(data_t *, INST_TYPE); int Slot(); int Rename(); int Issue(); int RegisterRead(); int Execute(data_t *); int Memory(); int WriteBack(); INST_TYPE get_ir(); int data_ld(data_t *, data_t *); int data_st(data_t *, data_t *); instruction(architecture_state *, memory_system *, system_manager *, system_config *, evaluation_result *); }; 15 命令フェッチステージのコード int instruction::Fetch(data_t *pc){ mem->ld_inst(pc, &ir); Npc.init(pc->ld() + 4); return 0; } メモリ上の PC のアドレスから4バイトの命令を フェッチし、変数 ir に格納する。 PC の値に4を加え、更新された PC を生成する。 16 スロットステージ(デコード)のコード int instruction::Slot(){ Op = (ir>>26) & 0x3F; RA = (ir>>21) & 0x1F; RB = (ir>>16) & 0x1F; RC = (ir ) & 0x1F; WF = ((Op&MSK2)==0x14 || (Op&MSK2)==0x20); LA = (Op==0x08 || Op==0x09); LD = (Op==0x0a || Op==0x0b || Op==0x0c || (Op&MSK2)==0x20 || (Op&MSK2)==0x28); ST = (Op==0x0d || Op==0x0e || Op==0x0f || (Op&MSK2)==0x24 || (Op&MSK2)==0x2c); BR = ((Op&MSK4)==0x30); WB = (LD || (Op&MSK2)==0x08 || Op==0x1a || Op==0x30 || Op==0x34) ? RA : ((Op&MSK3)==0x10 || Op==0x1c) ? RC : 31; Af = (Op==0x15 || Op==0x16 || Op==0x17 || Op==0x1c || (Op&MSK2)==0x24 || (Op&MSK3)==0x30); Bf = ((Op&MSK2)==0x14); Ai = (Op==0x08 || Op==0x09 || LD); Bi = (BR || (Op&MSK2)==0x10 && (ir & BIT12)); フェッチした命令 ir を デコードする。 Verilog-HDL を意識し た記述。 /** For the CMOV Split Code (CMOV1) **/ if(cmov_ir_create(ir)){ RB = RC; Bi = 0; } return 0; } 17 発行ステージ(即値計算)のコード int instruction::Issue(){ DATA_TYPE Lit, D16, D21, tmp, d21e, d16e; d21e = ((ir & MASK21) | EXTND21) << 2; d16e = (ir & MASK16) | EXTND16; Lit = (ir>>13) & 0xFF; D21 = (ir & BIT20) ? d21e : (ir&MASK21)<<2; D16 = (ir & BIT15) ? d16e : (ir&MASK16); if(Op==0x09) D16 = (D16 << 16); } tmp = (LA||LD||ST) ? D16 : (BR) ? D21 : Lit; Imm.init(tmp); return 0; 即値 Imm を計算 命令により以下から選択 8ビットの Lit 21ビットの符号拡張 16ビットの符号拡張 18 レジスタリードステージのコード int instruction::RegisterRead(){ Rav = Ai ? Imm : Af ? as->f[RA] : as->r[RA]; Rbv = Bi ? Imm : Bf ? as->f[RB] : as->r[RB]; return 0; } デコードしたフラグに従って整数レジスタ、浮動小 数点レジスタ、即値のどれかを入力オペランドとし て Rav, Rbv に格納する。 19 実行ステージのコード Rcv の値を計算 ロードストア命令のためにメモ リ参照アドレス Adr を計算 分岐命令では、分岐先アドレ ス Tpc を計算 int instruction::Execute(data_t *Tpc){ /*** Update Rcv ***/ if(BR || Op==OP_JSR){ Rcv=Npc; } else if(!LD){ ALU(ir, &Rav, &Rbv, &Rcv); } /*** Update Adr ***/ Adr.init(0); if(LD || ST){ ALU(ir, &Imm, &Rbv, &Adr); } /*** Update Tpc ***/ *Tpc = Npc; if(Op==OP_JSR){ *Tpc = Rbv; Tpc->st(Tpc->ld() & ~3ull); } if(BR){ BRU(ir, &Rav, &Rbv, &Npc, Tpc); } return 0; } 20 メモリアクセスとライトバックのコード ストア命令は Rav の内容をア ドレス Adr にストア ロード命令はアドレス Adr の 内容を Rcv にロード int instruction::Memory(){ if(ST) data_st(&Adr, &Rav); if(LD) data_ld(&Adr, &Rcv); return 0; } int instruction::WriteBack(){ if(Op==OP_PAL){ PAL命令の場合には、それを sys->execute_pal(this); 実行する関数をコール } Rcv の値をレジスタファイルに ライトバック if(!WF && WB!=31) as->r[WB] = Rcv; if( WF && WB!=31) as->f[WB] = Rcv; return 0; } 21 SimAlpha Version 1.0 のソフトウェアアーキテクチャ Line 871 73 201 368 271 187 179 15 562 Word 2948 199 626 1173 811 647 491 49 1234 Byte 21347 1882 5286 11142 7751 4505 4412 417 14871 architecture_state Filename arithmetic.cc chip.cc debug.cc define.h etc.cc instruction.cc memory.cc sim.cc syscall.cc 説明済み ほぼ説明済み 説明済み 説明済み simple_chip -> step() instruction Fetch Slot Ren Issue RR Ex Mem Wb architecture_state 22 SimAlpha の利用例 理想的な命令レベル並列性 (Oracle IPC) 制御依存関係や資源競合を解消し、データ依存関 係のみを制約として得られる並列性を測定 それぞれのデータについて、データフローグラフの 高さに相当する rank を計算 測定した結果を報告 拡張性を示す例 OP OP OP Rank = 1 Rank = 1 OP Rank = 2 Rank = 1 OP Oracle IPC = 6/4 = 1.5 Rank = 3 OP Max Rank = 4 23 ランクの計算方法 ランク値を保存する変数を data_t型に追加 class data_t{ uint64_t value; データが生成される時点で、ランク値を計算 public: 全ての命令のコストを1として計算 int cmov; uint32_t rank; 追加したコードはわずか26行 uint64_t ld(); データが生成される時点でランク値の最大値を計算 int st(uint64_t); ランク値の最大値と実行命令数から並列性を計算 int init(uint64_t); }; Rav Rbv Imm Rbv Rav Imm Rbv data_t型の拡張 OP add Adr Rcv mem add Adr mem Rcv (a) Arithmetic (a) (b) (c) (b) Load (c) Store rank(Rcv) = max(rank(Rav), rank(Rbv)) + latency(OP) rank(Rcv) = rank(Rbv) + latency(add) + latency(mem) rank = max(rank(Rav), rank(Rbv) + latency(add)) 命令タイプ毎の ランクの計算方法 24 12 09 4.m 9.g 88 o ks i 12 12 m 9.c 6.g om cc pr es s 13 13 0.li 2.i jp 13 eg 14 4.pe 7.v rl or t 16 ex 4.g z 17 ip 5.v 17 pr 6.g 18 cc 1 18 .mc 6.c f 19 raf 7.p ty ar s 25 er 25 2.e 3.p on er lbm 25 k 25 4.ga 5.v p o 25 rtex 6.b z 30 ip2 0.t wo lf Oracle IPC 理想的な命令レベル並列性の測定結果 120 107 60 41.8 40 20 20 10.5 108 100 80 64.2 56.6 53.1 43.3 47.1 32 49.7 43.6 30.9 32.1 25.1 16.9 29.3 21.9 8.4 0 25 おわりに プロセッサアーキテクチャ研究とプロセッサ教育における 利用を目的として、プロセッサシミュレータ SimAlpha Version 1.0 を構築した。 実際のC++のコードを示しながらソフトウェアアーキテク チャを明らかにした。 利用例として、理想的な命令レベル並列性を測定する方 法とSPEC CINT95, CINT 2000の測定結果を示した。 もうひとつのAlphaプロセッサシミュレータとして、プロセッ サ研究の選択肢の一つ 謝辞 SimAlpha の初期のバージョンをテストし、貴重なコメントやパッチを頂 いた飯塚大介氏に深く感謝致します。 26 SimAlpha のダウンロード SimAlpha Version 1.0 のダウンロード Version 1.0 のソースコードと、理想的な命令レベル並列性を得る ために変更を加えたソースコードは次のURLからダウンロードで きる。 http://www.yuba.is.uec.ac.jp/~kis/SimAlpha/ SimAlpha Version 1.0 に関する記述 吉瀬謙二, 本多弘樹, 弓場敏嗣: SimAlpha: シンプルで理解しやすいコード記述を目指した Alpha プロセッサシミュレータ, Technical Report UEC-IS-2002-2, 電気通信大学 大学院情報システム学研究科 (July 2002). 27
© Copyright 2025 ExpyDoc