Skip to content

Instantly share code, notes, and snippets.

@tonosaman
Created June 25, 2024 08:04
Show Gist options
  • Save tonosaman/70a50986d097cd323480d39aa77c25f6 to your computer and use it in GitHub Desktop.
Save tonosaman/70a50986d097cd323480d39aa77c25f6 to your computer and use it in GitHub Desktop.
Lion Clash - Code Tour

『単一サイクル遅延』となるように注意してClash上で実現する必要があるのでしょうか? Lionコアで『単一サイクル遅延』を実現している具体的な記述箇所をおしえてください。

ソフトウェアベースの演算器(Soft)とハードウェアベースの演算器(Hard)の違いをメリットとデメリットが明確になるようにおしえてください。


Pipe.hs の execute() 関数内において使用されている fromRS1 について質問です。 fromRS1 自体は data ToPipe から makeLenses ''ToPipe でアクセッサとして生成されたものであることは把握しています。 この fromRS1 と命名された関数のfromが示す意図についてよく分かっていないので、どういう意味合いで使用されているのか設計者の意図を教えて下さい。

  • data ToPipe の To はどこからどこへ向けたものなのか パイプラインステージの文脈に閉じたデータ型で、現在の段{フェッチ,デコード,実行,メモリアクセス,ライトバック}から次の段へ向けたToという意味でしょうか?
  • fromRS1 を用いて execute() の関数内の文脈で何を読み取ろうとしているのか? 実行ステージでパイプの前段(デコードステージ)から渡されたレジスタセット1を取り出すという意味合いでしょうか?

Phind

はい、ご理解の通りです。fromRS1data ToPipeからmakeLenses ''ToPipeによって生成されたアクセッサの一つであり、ToPipeデータ型の_fromRs1フィールドにアクセスするための関数です。この命名規則はClashのmakeLenses関数によって自動的に生成され、fromプレフィックスは通常、ある値を取得する(または参照する)操作を示します。ToPipeデータ型はパイプラインの各ステージ間でデータを転送するために使用されるデータ型であり、その名前「To」は「から(From)」という意味合いを持ちますが、このコンテキストでは「向けて(To)」という意味合いが強調されています。つまり、あるステージから次のステージへデータを「向けて」送ることを示しています。

  • data ToPipeToは、パイプラインの各ステージ間でデータを転送するためのデータ型であり、Toは「向けて」という意味合いを持っています。具体的には、あるステージから次のステージへデータを「向けて」送ることを示しています。例えば、フェッチステージからデコードステージへ、デコードステージから実行ステージへ、といったように、パイプラインの各ステージ間でデータが移動することを示しています。このToは、データが「どこからどこへ向けて」移動するのかを示しており、パイプラインのステージ間のデータフローを表現しています。

  • fromRS1を使用してexecute()関数内で読み取ろうとしているのは、実行ステージでパイプの前段(フェッチステージやデコードステージ)から渡されたレジスタセット1(rs1)の値を取り出すことを意味しています。execute()関数内でfromRS1を使用することで、実行ステージで必要なレジスタの値を取得し、ALU(算術論理ユニット)などの演算に使用することができます。つまり、fromRS1は、実行ステージで必要なレジスタの値を取得するために使用され、パイプラインの前のステージからrs1の値を「から」取得して、現在のステージ(実行ステージ)で使用することを意味しています。

したがって、fromRS1fromは、データが「から」取得されることを示しており、ToPipeToはデータが「向けて」送られることを示しています。これらの命名規則は、パイプラインのデータフローを明確に示し、どのステージからどのステージへデータが移動するのかを理解するのに役立ちます。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.meRegFwdcontrol.wbRegFwd: これらは、メモリステージとライトバックステージでのレジスタフォワーディング情報を保持しています。これらは、特定のレジスタが更新されたかどうか、そしてその値が何であるかを示します。

このコード行全体として、rs1DatameRvfi.rvfiRs1Dataの値をregFwd関数を使用して更新されます。regFwd関数は、exRs1(実行ステージでのrs1レジスタのアドレス)、fromRs1(前のステージからのrs1の値)、およびcontrol.meRegFwdcontrol.wbRegFwd(フォワーディング情報)を使用して、フォワーディングが必要な場合に適切な値をrs1Dataに設定します。フォワーディングが必要ない場合、meRvfi.rvfiRs1Dataの値がそのままrs1Dataに設定されます。これにより、パイプラインの効率が向上し、依存関係のある命令の間で待機することなく処理を続けることができます。

要約すると、この行は、rs1レジスタの値を取得し、必要に応じてレジスタフォワーディングを適用して、実行ステージで使用するためにrs1Dataを設定しています。これは、パイプラインのパフォーマンスを最適化し、ハザードによる遅延を減らすために重要です。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment