ここで話を戻して、図3.4では構造的ハザードを解消するためにレジスタファイル2を追加しているが、レジスタファイル1のリードポート数を3ポートに増やすのとどちらが良いかを考えてみよう。

ADD演算の場合、二つのオペランドを読み、加算結果をそのサイクルの終わりにレジスタファイルに書き込むという動作なので、レジスタファイル1は、2R 1Wの構成が必要である。これをシングルエンド方式で作ると、ビット線は3本、ワード線も3本であり、面積は9単位である。そして、レジスタファイル2は、ストアデータの読み出しと独立して、レジスタファイル1への書込みと同時に、同じデータを書き込む必要があるので、2ポートが必要となる。これもシングルエンド方式で作ると面積は4単位となり、全体の合計面積は9+4=13単位となる。

一方、3R 1Wのレジスタファイルをシングルエンド方式で作ると、ビット線が4本、ワード線も4本であり、16単位の面積を必要とする。ということで、3R 1Wの単一のレジスタファイルを作るよりも2R 1Wと1R 1Wに分割して作る方が有利である。

なお、1R 1Wを3個使用すると面積は12単位であり、この簡易計算では2R 1Wと1R 1Wの合計よりも小さいが、前に述べたように、ポート数が少ない領域では面積の増加は二乗則よりも緩やかなので、どちらが得かは、詳細に検討する必要があろう。

これまでに説明してきたプロセサでは、レジスタファイルへの書き込みは1サイクルに1回できれば良いというマイクロアーキテクチャであるが、最近のマイクロプロセサでは、複数の演算器を持ち、同一サイクルに複数の演算結果をレジスタファイルに書き込んだり、演算結果と合わせて、LD命令でメモリから読み出したデータのレジスタファイルへの格納を並行して行ったりすることが必要になってきている。

このようなレジスタファイルでは、次の図3.10のように、複数の書き込みポートを持つ必要がある。図3.9で赤で示したN10~12の部分とD in2、Write Wordline2の2本の線が書き込み第二の書き込みポートのために追加された部分である。

図3.10:2R 2Wレジスタファイルの記憶セル回路

Readポートを増やす場合は、例えば、2R 1Wのレジスタファイルを2個用いて両方に同じデータを書き込むことにより、4R 1Wのレジスタファイルとして使用することができるが、複数のWriteポートを必要とする場合は、このように分割することはできず、1個で必要な数のWriteポートを持つ図3.8や図3.10のような回路を使う必要がある。

いずれにしても、レジスタファイルのポート数が多くなると、面積が増えるだけでなく、ReadやWriteのスピードも遅くなり、クロック周波数を高くすることが難しくなる。従って、マイクロアーキテクチャを考える上において、レジスタファイルのポート数の増加による並列実行性能の向上と面積やクロックに対するコスト増は重要なトレードオフである。

データハザードとコントロールハザード

これまでに述べたように、構造的ハザードは資源の増強により解消することが可能であるが、より本質的なのはデータの依存性によって生じるデータハザードである。図3.11の例では、ADD命令の一方のオペランドが直前のLD命令でメモリから読まれるデータである場合は、第4サイクルの終わりにならないとLD命令の結果が得られないので4サイクル目にADD演算を行うことはできない。このようにデータの依存性がある場合には、図3.11のようにパイプラインストールが必要となる。

図3.11:データハザードによるパイプラインストールの発生

この例では、4サイクルには2番目のADD命令の演算の実行はできず、データハザードによるストールが発生する。そして、5、6、7サイクル目のストールは、演算器の競合による構造的ハザードにより発生しているものである。

もう一つの本質的なハザードとして、分岐命令のようなプログラムカウンタを変更する命令が存在する場合に発生するコントロールハザードがある。命令をアドレス順に実行するのではなく、レジスタに格納されたアドレスの命令に分岐する場合は、次の図3.12のように、レジスタの内容を演算器経由でプログラムカウンタに書き込む。これにより、次の命令フェッチは分岐先のアドレスから行われることになる。

図3.12:分岐命令の処理

分岐命令の分岐先アドレスがプログラムカウンタに転送され、次の命令フェッチに使用可能になるのは、図3.13に示すように、3サイクル目の終わりであり、2サイクル目、3サイクル目にフェッチした命令はプログラム上、実行されない命令であり、キャンセルしなければならない。

図3.13:分岐命令によるコントロールハザード

従って、分岐(BR)命令に続くADD命令の開始は、2サイクル遅延されることになる。

これまで見てきたように、パイプライン処理は、1サイクルあたり1命令の処理を可能にするテクニックであり、各命令の処理を順次に行うナイーブな方式に較べて大幅に性能を向上することができるが、構造的ハザード、データハザード、コントロールハザードにより命令を処理できないストールサイクル(バブル)が発生する。従って、マイクロアーキテクチャ設計としては、ストールサイクルを減らし、高い命令処理性能の達成と、それに必要なハードウェア資源の最適なトレードオフを見つけ出すことが重要になる。