スコアボードによるアウトオブオーダ実行
このようなアウトオブオーダ実行の歴史は、実はかなり古く、1963年に登場した当時のスパコンである「CDC6600」で採用されていた。CDC6600は4つの浮動小数点演算パイプライン、5つのメモリアクセスパイプライン、7つの整数計算パイプラインを備えており、 単純にプログラム順に命令を発行するだけでは、とてもこれらの合計16本の実行パイプラインを効率的に動かすことは出来ない。そこで、浮動小数点演算やメモリアクセスなどの実行時間の長い命令の実行中に、依存関係の無い命令は並列的に実行してしまう「スコアボード(Scoreboard)」と呼ぶマイクロアーキテクチャにより、この問題を解決している。
CDC6600のマイクロアーキテクチャでは、各実行パイプは共通レジスタファイルから入力オペランドを読み込み、処理を行って、その結果を共通レジスタファイルに書き戻す構造であるが、各実行パイプはレジスタファイルにそれぞれ専用のリードポートとライトポートを持っており、オペランドの読出しと結果の格納に関しては構造ハザードは発生しない構造になっている。
なお、このシリーズの125回、126回のマルチポートレジスタのところで説明したように、ポート数の大きいレジスタファイルは配線が多くチップ面積を食うのであるが、CDC6600の時代には配線は本物の電線で、配線は高価なトランジスタを使う論理回路よりずっと安価であったので、当時のテクノロジでは超多数ポートのレジスタファイルは効率の良いマイクロアーキテクチャであった。
そして、スコアボード方式での命令の実行は、
- Issue
- Read Operands
- Execute
- Write Back
の4ステージで行われる。ただし、ここで言う4ステージは論理的なステージであり、浮動小数点演算やメモリアクセスなどでは、Executeステージはパイプラインとしては多くのパイプステージに分かれているのが普通である。
そして、スコアボードと呼ぶ集中型の制御回路を用いて、次のように処理を行う。
"1"のIssueステージでは、その命令が必要とする実行パイプが使用可能であり、結果を格納するレジスタに対して先行する命令が書き込みを行わない(WAWハザードが無い)場合には、その命令を実行パイプに送る。
"2"のRead Operandsステージではその命令の入力オペランドをレジスタファイルから読み込む。スコアボードは、入力オペランドのレジスタに書き込みを行う先行命令が無い(RAWハザードでない)ことを確認してレジスタからデータを読み、実行パイプラインに渡す。
"3"のExecuteステージではすべての入力オペランドを受け取ると、処理を開始する。そして処理の終了をスコアボードに通知する。
"4"のWrite Backステージでは、スコアボードは、その命令の処理終了が通知されており、かつ、その結果を書き込むレジスタを読む先行命令がない(WARハザードでない)ことを確認して、処理結果をレジスタに書き込む。
つまり、スコアボードは、IssueステージでWAWハザードがある場合は命令の発行をストールしてハザードを解消し、Read Operandsステージで先行命令の結果が得られていない場合はオペランドの読み出しをストールしてRAWハザードを解消している。そして、Write Backステージで、先行する命令がそのレジスタの結果を読む必要がある場合は、その読み出しを待ち合わせてから書き込みを行うことで、WARハザードを解消している。そして、これらのハザードの解消のためのストールが必要無い命令は、ストールした命令を追い越して実行して行く。