ソフトウェアベースの演算器(Soft)とハードウェアベースの演算器(Hard)の違いをメリットとデメリットが明確になるようにおしえてください。
Pipe.hs の execute() 関数内において使用されている fromRS1 について質問です。
fromRS1 自体は data ToPipe から makeLenses ''ToPipe でアクセッサとして生成されたものであることは把握しています。
この fromRS1 と命名された関数のfrom
が示す意図についてよく分かっていないので、どういう意味合いで使用されているのか設計者の意図を教えて下さい。
- data ToPipe の To はどこからどこへ向けたものなのか パイプラインステージの文脈に閉じたデータ型で、現在の段{フェッチ,デコード,実行,メモリアクセス,ライトバック}から次の段へ向けたToという意味でしょうか?
- fromRS1 を用いて execute() の関数内の文脈で何を読み取ろうとしているのか? 実行ステージでパイプの前段(デコードステージ)から渡されたレジスタセット1を取り出すという意味合いでしょうか?
Phind
はい、ご理解の通りです。fromRS1
はdata ToPipe
からmakeLenses ''ToPipe
によって生成されたアクセッサの一つであり、ToPipe
データ型の_fromRs1
フィールドにアクセスするための関数です。この命名規則はClashのmakeLenses
関数によって自動的に生成され、from
プレフィックスは通常、ある値を取得する(または参照する)操作を示します。ToPipe
データ型はパイプラインの各ステージ間でデータを転送するために使用されるデータ型であり、その名前「To」は「から(From)」という意味合いを持ちますが、このコンテキストでは「向けて(To)」という意味合いが強調されています。つまり、あるステージから次のステージへデータを「向けて」送ることを示しています。
-
data ToPipe
のTo
は、パイプラインの各ステージ間でデータを転送するためのデータ型であり、To
は「向けて」という意味合いを持っています。具体的には、あるステージから次のステージへデータを「向けて」送ることを示しています。例えば、フェッチステージからデコードステージへ、デコードステージから実行ステージへ、といったように、パイプラインの各ステージ間でデータが移動することを示しています。このTo
は、データが「どこからどこへ向けて」移動するのかを示しており、パイプラインのステージ間のデータフローを表現しています。 -
fromRS1
を使用してexecute()
関数内で読み取ろうとしているのは、実行ステージでパイプの前段(フェッチステージやデコードステージ)から渡されたレジスタセット1(rs1
)の値を取り出すことを意味しています。execute()
関数内でfromRS1
を使用することで、実行ステージで必要なレジスタの値を取得し、ALU(算術論理ユニット)などの演算に使用することができます。つまり、fromRS1
は、実行ステージで必要なレジスタの値を取得するために使用され、パイプラインの前のステージからrs1
の値を「から」取得して、現在のステージ(実行ステージ)で使用することを意味しています。
したがって、fromRS1
のfrom
は、データが「から」取得されることを示しており、ToPipe
のTo
はデータが「向けて」送られることを示しています。これらの命名規則は、パイプラインのデータフローを明確に示し、どのステージからどのステージへデータが移動するのかを理解するのに役立ちます。fromRS1
を使用することで、実行ステージでは、前のステージからrs1
レジスタの値を取得し、命令の実行に必要なデータを提供します。これは、パイプラインの各ステージ間でデータがどのように移動するのかを示すための一般的なパターンです。
このコード行は、rs1Data
の値を取得するために使用されています。具体的には、meRvfi.rvfiRs1Data
からrs1
レジスタの値を取得し、必要に応じてレジスタフォワーディングを適用しています。レジスタフォワーディングは、パイプラインのハザードを解消するために使用される技術で、依存関係があるレジスタの値を直接次のステージに転送することで、パイプラインのストールやバブルを防ぎます。ここでのregFwd
関数は、レジスタフォワーディングのロジックを実装しています。
レジスタフォワーディングに関する資料: https://www.am.ics.keio.ac.jp/arc/pipe2.pdf
rs1Data <- meRvfi.rvfiRs1Data <<~ regFwd exRs1 fromRs1 (control.meRegFwd) (control.wbRegFwd)
この行の各部分を詳しく見てみましょう:
-
meRvfi.rvfiRs1Data
: この部分は、メモリステージ(me
)のRISC-V Formal Verification Interface(Rvfi
)からrs1
レジスタの値を取得しようとしています。rvfiRs1Data
は、実行ステージで使用されるrs1
レジスタの値を保持しています。 -
<<~
: このLens演算子は、ClashのmeRvfi.rvfiRs1Data
の値をregFwd
関数の結果で更新します。<<~
演算子は、左辺の値を右辺の値で更新するために使用されます。 -
regFwd
: これはレジスタフォワーディングを行う関数で、引数としてexRs1
(実行ステージでのrs1
レジスタのアドレス)、fromRs1
(前のステージからrs1
の値)、control.meRegFwd
(メモリステージでのレジスタフォワーディング情報)、control.wbRegFwd
(ライトバックステージでのレジスタフォワーディング情報)を取ります。この関数は、フォワーディングが必要な場合に前のステージやライトバックステージからrs1
の値を取得し、必要なければmeRvfi.rvfiRs1Data
の値をそのまま使用します。 -
regFwd
関数の目的は、依存関係のあるレジスタの値を適切にフォワーディングすることで、パイプラインのストールを防ぎ、パフォーマンスを向上させることです。具体的には、rs1
レジスタの値がメモリステージまたはライトバックステージで更新される場合、その更新された値を実行ステージで直接使用できるようにします。これにより、パイプラインの次のサイクルでrs1
の値を待つ代わりに、現在のサイクルでその値を使用できるようになります。 -
exRs1
: 実行ステージでのrs1
レジスタのアドレスです。 -
fromRs1
: これはToPipe
データ型から_fromRs1
フィールドにアクセスするためのレンズ(またはアクセッサ)で、前のステージ(おそらくデコードステージ)からrs1
の値を取得します。 -
control.meRegFwd
とcontrol.wbRegFwd
: これらは、メモリステージとライトバックステージでのレジスタフォワーディング情報を保持しています。これらは、特定のレジスタが更新されたかどうか、そしてその値が何であるかを示します。
このコード行全体として、rs1Data
はmeRvfi.rvfiRs1Data
の値をregFwd
関数を使用して更新されます。regFwd
関数は、exRs1
(実行ステージでのrs1
レジスタのアドレス)、fromRs1
(前のステージからのrs1
の値)、およびcontrol.meRegFwd
とcontrol.wbRegFwd
(フォワーディング情報)を使用して、フォワーディングが必要な場合に適切な値をrs1Data
に設定します。フォワーディングが必要ない場合、meRvfi.rvfiRs1Data
の値がそのままrs1Data
に設定されます。これにより、パイプラインの効率が向上し、依存関係のある命令の間で待機することなく処理を続けることができます。
要約すると、この行は、rs1
レジスタの値を取得し、必要に応じてレジスタフォワーディングを適用して、実行ステージで使用するためにrs1Data
を設定しています。これは、パイプラインのパフォーマンスを最適化し、ハザードによる遅延を減らすために重要です。