Posts Tagged with "Design"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on February 23, 2022 #465

EIT処理

通常の命令処理以外の処理、例外(Exception)、割り込み(Interrupt)、トラップ(割り出し、Trap)を総称してEIT処理と称します。 パイプラインの各ステージで検出されるEITを以下に示します。

  • <PC>: 奇数命令アドレスジャンプ例外
  • <IF>: 命令フェッチアドレス例外、デバッグトラップ
  • <ID>: 無効命令例外、ゼロ除算例外(命令が除算かつdivisorソースレジスタの内容がゼロ)
  • <EX>: 無し
  • <MA>: メモリアクセスアドレス例外、デバッグトラップ
  • <WB>: 無し

割り込みはいずれのパイプラインステージで検出されるか、保留します。 さて、各ステージでEITが検出されると、前後の命令最大4命令でEITが検出されることになり、後続命令のEITが時間的に先に検出されることになります。これを処理すると命令の前後関係が逆転するために、EITを検出するパイプラインステージを揃えることを考えます。

この中で最も時間的に遅いのが、<MA>であるため、割り込みもここで検出することにします。パイプラインストリーム中に検出されたEITは全てパイプラインレジスタで<MA>まで保留し、ここで優先度を判定し、弱い順にEIT要因をスタックに格納します。従って、EITハンドラは優先度の高い順から実行し、弱い順にハンドラ実行することになります。

例外とトラップ、割り込みの違い

EITはいずれも命令ストリームの途中で起きる例外事象ですが、以下のような違いがあります。

  • E(xception): 当該命令は取り消される。具体的には<MA>で起こる場合はメモリに対する書き込みを無効化する。その他の場合は<WB>において書き込みを無効化(パイプラインキャンセル)する。
  • I(nterrupt): 当該命令の後に割り込みハンドラに分岐するので、当該命令は実行する。
  • T(rap): 当該命令の後にトラップハンドラに分岐するので、当該命令は実行する。

左矢前のブログ 次のブログ右矢

posted by sakurai on February 22, 2022 #464

分岐命令

一般的な5段パイプラインを解説してきましたが、具体的なプロセッサを対象にして検討します。対象は何でも良いので、ここではRISC-Vとします。その理由は命令セットがオープンであり、誰でも自由に使用することができるためです。

さて、前述の分岐命令は一般的にフラグを見て分岐判定を先行して行うRISCプロセッサでした。前の命令の<EX>で演算後にフラグを立て、その結果で次の分岐命令のデコードである<ID>終了時には分岐命令であり、かつ分岐条件が成立しているため、バブルは1$\tau$となります。

しかしながら、RISC-VのISAからの引用の図464.1を見ると、RISC-Vの条件分岐命令はレジスタをテストして、その結果で分岐するため、バブルは2$\tau$となります。そのため、前稿のフラグベースのアーキテクチャよりもこのアーキテクチャのほうが分岐レイテンシが長くなり、性能が悪いことになります。

図%%.1
図464.1 beq命令

図%%.2
図464.2 パイプライン図

それにもかかわらず、RISC-Vにおいて条件フラグを廃したのは、スーパスカラ化を考えると条件フラグの資源競合が起きやすくなるためだと思われます。


左矢前のブログ 次のブログ右矢

posted by sakurai on February 21, 2022 #463

キャンセル

パイプラインウエイトと並んで重要な制御がパイプラインキャンセルです。パイプライン中に例外的な事象が起き、そのパイプラインストリームを無効化します。これは前稿で述べたバブルと同様に、あるステージを無効化(Valid信号=false)することで実現します。パイプライン中をinvalidが流れ、最後に<WB>においてレジスタに書き込まないことで実現します。<MA>においてはinvalidである場合にはメモリアクセスFSMは起動しません。

分岐キャンセル

分岐の場合の具体例を示します。分岐先及び非分岐先(+4)を投機的に計算しておくことで、相対分岐の高速化を図ります。これは分岐命令をデコードした時点で既に前の命令で演算フラグが確定しているものとしています。

図%%.1
図463.1 パイプライン図

1の命令が相対分岐であったとき、<ID>において命令をデコードと並行して相対分岐だと思って分岐先を計算します。タイミングとしては3の命令の<PC>と同一です。その命令の最後に相対分岐かどうかが確定し、かつ条件分岐の成立が確定するので、PC選択のマルチプレクサにおいて、分岐先を選択します。同時に後続命令である2のパイプラインストリームにinvalidを流し、パイプラインキャンセルを実行します。

図%%.2
図463.2 パイプライン図


左矢前のブログ 次のブログ右矢

posted by sakurai on February 17, 2022 #462

マルチサイクル演算ウエイト

続いてマルチサイクル演算ウエイトです。例えば<EX>が4サイクル必要となる乗算等の命令となります。

これはパイプラインストリームの増殖が無いので、通常のウエイト同様、<EX>でウエイトが発生すると、同一サイクル中に後続の命令ステージを全て停止し、かつ下段のパイプラインを無効化します。

図%%.1
図462.1 パイプライン図

図462.2は図462.1をパイプラインステージ順に並び替えたもので、パイプラインウエイトとそれに対応するバブルを見ることができます。

図%%.2
図462.2 パイプライン図

具体的には<EX>で起動するFSMを実装します。


左矢前のブログ 次のブログ右矢

posted by sakurai on February 16, 2022 #461

マルチサイクル命令ウエイト

前稿ではマルチサイクル命令ウエイトをご紹介しましたが、パイプライン図を示します。これは例えばRead Modify Write等のように、1命令が1サイクルで終わらない複数ストリームを使用する命令で、いわばCISC命令です。ロード命令、演算命令、ストア命令のRISC命令を並べて実行しないのは、RISC命令だとその間に割り込みが入り、アトミック性が保たれないためです。

図%%.1
図461.1 パイプライン図

黄色は内部的に増殖したサイクルです。

図461.2は図461.1をステージで並び替えたもので、通常のウエイトではパイプライン下段にバブルが発生しますが、マルチサイクル命令ウエイトは例外的に、内部的に命令を発生(増殖)させパイプラインを埋めるので、バブルは発生しません。

図%%.2
図461.2 パイプライン図

黄色は内部的に増殖したサイクルです。具体的には<ID>で起動するFSMにより実装します。これはRISC-Vにはないかもしれませんが、EIT処理やMMUミスによるテーブルウォークは、これを用いて実装する可能性があります。

左矢前のブログ 次のブログ右矢

posted by sakurai on February 15, 2022 #460

レジスタ干渉ハザード

レジスタ干渉によるハザードは2種類あります。前稿でも触れたWARハザードとロードユースハザードです。

  • WARハザード: 前の演算命令のデスティネーションレジスタが後続の命令のソースレジスタと同じ場合にレジスタ干渉ハザードが起きます。しかしながら、レジスタ番号マッチ機構によりバイパスさせ、実質ノーウエイト=ゼロペナルティでパイプライン実行可能です。バイパスパスは<EX>出力⇒<EX>入力です。

図%%.1
図460.1 パイプライン図

図%%.2
図460.1 パイプライン図

ロードユーズハザード

  • ロードユーズハザード: 前のロード命令のデスティネーションレジスタが後続の命令のソースレジスタと同じ場合にロードユーズハザードが起きます。この場合待ち合わせのために1ウェイトが必要であり、かつレジスタ番号マッチ機構によりバイパスさせます。バイパスパスは<MA>出力⇒<EX>入力です。

図%%.3
図460.1 パイプライン図

図%%.4
図460.1 パイプライン図


左矢前のブログ 次のブログ右矢

posted by sakurai on February 14, 2022 #459

パイプラインウエイトの種別

前稿ではパイプラインウエイトの原因を2種類説明しました。ここでステージ毎のパイプラインウエイトの原因をまとめます。

  • <PC>: PCの計算にウエイトがかかることは、下段からのウエイトを除きありません。
  • <IF>: 命令をメモリからフェッチする際にメモリレイテンシ-1のウエイトが加算されます。これを命令フェッチウエイトと分類します。
  • <ID>: 命令デコードにウエイトがかかることはありません。ただしマルチサイクル命令という例外があるので、次項で述べます。
  • <EX>: 演算にウエイトがかかる場合はマルチサイクル命令です。上記マルチサイクル命令とはパイプライン制御法が異なるので、併せて次項で述べます。
  • <MA>: オペランドメモリのリードライトの際にメモリレイテンシ-1のウエイトが加算されます。これをメモリアクセスウエイトと分類します。
  • <WB>: レジスタライトに対してウエイトがかかることはありません。

マルチサイクル命令

前記のように<ID>と<EX>ではマルチサイクル命令ウエイトが発生する可能性があります。

  • <ID>: マルチサイクル命令ウエイトと分類します。命令デコードでのマルチサイクル命令は、上段へのウエイト伝搬はパイプラインウエイトと同様、即時に伝えます。一方、下段への無効化を流す操作は行いません。これはあたかも<ID>において命令が内部的に命令ストリームが増殖し、パイプラインを埋めるためです。具体的にはメモリに対するリードモディファイライトがあります。このためには<ID>で動作するステートマシンを起動する必要があります。アーキテクチャにより、無い場合もあります。その理由はCISCっぽい命令となるためです。
  • <EX>: マルチサイクル演算ウエイトと分類します。演算にウエイトがかかる場合はマルチサイクル命令ですが、マルチサイクル命令ウエイトと異なり、内部的にパイプラインが増殖することはないため、通常のウエイト制御と同じパイプライン制御を行います。例えば乗算命令に関して32bit×32bitの乗算器を用意すると面積が大きくなるので、32bit×8bitの乗算器を4サイクル回す場合等です。

左矢前のブログ 次のブログ右矢

posted by sakurai on February 11, 2022 #458

命令フェッチウエイト

次に命令フェッチ時に2ウエイトがかかった場合のタイミングを示します。

図%%.1
図458.1 パイプライン図

命令1の<IF>にウエイトが入ると、後続命令を直ちに止める必要があるため、前稿と同様、ウエイト信号は即時に上ステージに伝える(下向き矢印)ように制御します。

図458.2はそれを並べ替えたものです。メリットは図458.1では省略されているパイプラインバブルが見えることです。濃いグレーは初期の無効フラグであり、パイプラインバブルは薄いグレーで示しています。

図%%.2
図458.2 パイプライン図

パイプラインウエイトは上段に向かって即時(同一サイクル内)に流す(上向き矢印)だけでなく、下段に向かってバブルを発生します(右下斜矢印)。下段へは即時ではなくパイプラインに沿って流します。

実装は<IF>で起動するFSMにより実装します。例えば命令キャッシュをFSMで構成すると、キャッシュヒット時は1サイクルで結果が返りますが、キャッシュミス時は複数サイクルのFSMにより、命令がフェッチされます。


左矢前のブログ 次のブログ右矢

posted by sakurai on February 10, 2022 #457

パイプラインウエイト

パイプラインの設計も佳境となるのがパイプラインハザードであり、それを実行するのがパイプラインウエイト制御です。本来ウエイトさせるべきタイミングでウエイトされないと、「パイプラインステージが滑る」バグとなります。

パイプラインステージ制御には原則があり、パイプラインステージは増殖してはいけません。パイプラインステージを止める場合は、その出力の更新を止めることでサイクルを繰り返す制御を行い、かつ、後段には無効信号を流す必要があります。

つまり、パイプラインステージ制御信号にはValid信号が必要です。一方パイプラインデータ信号にはValid信号は不要です。パイプラインで無効データが流れても、最後の<WB>で書き込まなければ問題ないためです。

メモリアクセスウエイト

次にロードストア命令の<MA>でのウエイトの場合を示します。

通常のパイプライン図を457.1に示します。命令の実行順に、縦に命令を1, 2, ..., 6と並べています。横軸は時間軸で、箱の中にステージ名が書かれています。命令処理を命令流すなわち、命令ストリームあるいはパイプラインストリームと呼ぶこともあります。

図%%.1
図457.1 パイプライン図

図457.1は例えば命令1のメモリアクセスステージ<MA>でメモリウエイトが2サイクル入った場合の例です。命令1の<MA>にウエイトが入ると、後続命令を直ちに止める必要があるため、ウエイト信号は即時に上ステージに伝える(下向き矢印)ように制御します。

図457.1をパイプラインステージ順に並べ替えたものが図457.2です。図457.1と同様に横軸は時間軸です。箱の中には命令の順番の番号が入っています。こちらのほうが有利なのは、図457.1では省略されているパイプラインバブルが見えることです。バブルは薄いグレーで示しています。初期の無効状態は濃いグレーで示しています。

図%%.2
図457.2 パイプライン図

パイプラインウエイトは上段に向かって即時(同一サイクル内)に流す(上向き矢印)だけでなく、下段に向かってバブルを発生します(右下斜め矢印)。下段へは即時ではなくパイプラインに沿って流します。バブルとは、具体的にはパイプラインのValid信号をインバリデート(無効, false)にすることです。

例えば1の命令が<MA>でウエイトする場合(5クロック目)、パイプラインを下段方向に止めるのではなく、下段は止めずにその代わり無効信号を流します。これは重要なパイプライン制御のテクニックであり、下段も止めてしまうと、誤ったインターロック(お互いに止めあうこと)が発生することがあります。

余談ですが、20?年前に課内でパイプライン制御を説明したとき、先輩のTさんと後輩のK君は「全部止めたらいいんじゃないか」と言いましたが、上記の理由からそれは誤っています。

実装は<MA>で起動するFSMにより実装します。例えばデータキャッシュをFSMで構成すると、キャッシュヒット時は1サイクルでデータが返りますが、キャッシュミス時は複数サイクルのFSMによりデータがフェッチされます。


左矢前のブログ 次のブログ右矢

posted by sakurai on February 9, 2022 #456

レジスタフォワーディング

レジスタフォワーディングは単にフォワーディング、またはバイパスと呼ばれることがあります。これは前述のRAWハザードのペナルティ(無駄時間、バブル)を軽減もしくは無化するためのものです。

以下のような命令ストリームがあった時、

1: <PC><IF><ID><EX><MA><WB>
2:         <PC><IF><ID><EX><MA><WB>
3:                  <PC><IF><ID><EX><MA><WB>
4:                           <PC><IF><ID><EX><MA><WB>
5:                                   <PC><IF><ID><EX><MA><WB>

1:のデスティネーションレジスタは<WB>ステージで書き込まれますが、直後の2の命令ストリームの<ID>で読もうとすると、5の命令のタイミングまでウエイトしなければなりません。つまり2、3、4の命令実行時間の$3\tau$が無駄になります。

これを高速化するのがレジスタフォワーディングで、2の命令デコード時に先行命令のデスティネーションレジスタ番号と自分の命令のソースレジスタ番号の比較を行います。この時同じレジスタであれば、デスティネーションレジスタから読み出すのではなく、演算器の出力をレジスタの結果とみなします。1の命令の<EX>の出力確定は2の命令の<ID>のレジスタ読み出しと同一タイミングなので、レジスタフォワーディング制御としては<EX>の出力を<EX>の入力にフィードバックします。

このバイパス機構を設けることで、本来$3\tau$のバブルが発生するところをバブル無しとなり、RAWハザードを解消することができます。

機構的にはソースレジスタとデスティネーションレジスタの番号をパイプラインで流し、番号が前後の命令で一致するかを見る比較器を設け、一致した場合は命令コードが示すレジスタの内容ではなく、演算器の出力パスをマルチプレクサで選択します。


左矢前のブログ 次のブログ右矢


ページ: