|
11 |
RISC-Vプロセッサの設計 (36) |
6段のパイプラインをFIFOでつなぐ(Step 1)
RISC-V パイプラインプロセッサ 設計方針の設計順序に沿って、実装を始めました。Step 1では、まだ命令の中身は何も実行しません。6つの段を段間FIFOでつなぎ、命令が正しいタイミングで流れ、止まり、捨てられることだけを確かめます。
やったこと
- <PC> <IF> <ID> <EX> <MA> <WB>の6段を、それぞれ1つのruleで書きました。段間はmkPipelineFIFOで、<PC>→<IF>だけはlastを持つmkPipeQ(PCの箱)です。
- 段の間を流れるのは、段ごとの構造体です。中身はpc、epoch、命令です。validもMaybeもありません。
- 分岐はまだ作っていないので、仮にjalだけを「成立する分岐」として扱います。<EX>がjalを見つけるとexEpochを反転し、redirectに分岐先を書きます。後ろの誤った命令は、epochによるキャンセル制御のとおりに捨てられます。
- 検証のために、テストベンチから任意の段を任意のサイクルで止められるようにしました。止めた段のruleは、そのサイクルに発火しません。
Konataで見る
各段のruleが、Kanata形式のログを出します。命令の通し番号、どのサイクルにどの段にいたか、最後まで流れたか捨てられたか、を記録します。これをKonataで開くと、パイプラインの動きが図で見えます。
次の表は、サイクル4に<EX>を止めた場合です。表には、ログから作った命令×サイクルの図をそのまま写しました。灰色は誤った経路の命令、ピンクは捨てたサイクルです。
| 命令 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 80000000 addi | PC | IF | ID | EX | MA | WB | |||||||
| 80000004 addi | PC | IF | ID | EX | EX | MA | WB | ||||||
| 80000008 jal | PC | IF | ID | ID | EX | MA | WB | ||||||
| 8000000c | PC | IF | IF | ID | |||||||||
| 80000010 | PC | IF | |||||||||||
| 80000018 addi | PC | IF | ID | EX | MA | WB | |||||||
| 8000001c addi | PC | IF | ID | EX | MA | WB |
サイクル4に<EX>が止まると、その上流の<ID>、<IF>、<PC>も同じサイクルに止まります。wait信号はどこにも書いていません。下流が止まると段間FIFOが満杯になり、上流のruleが発火しなくなるだけです。サイクル6にjalが<EX>を通ると、後ろにいた2命令は同じサイクルに捨てられます。同じサイクルに<PC>が分岐先(80000018)を選ぶので、無駄になるのはこの2命令だけです。
どう確かめたか
プロセッサとは別に、Pythonでパイプラインのモデルを書きました。モデルの規則は設計方針と同じです。
- 下流が同じサイクルにdeqすれば、上流はenqできる。
- ruleは<WB>から<PC>の順に動く。
- epochが古い命令は、止めていても捨てる。
モデルは、同じ命令列と同じ止め方から、期待されるKanataログを作ります。これをプロセッサのログと1行ずつ比べました。名前を付けた10通りの止め方に加えて、各段をランダムに止めるテストを300通り流し、bsimとVerilatorの両方で全部一致しました。
できたこと
段間FIFOだけで、waitの伝搬と分岐の取り消しが設計どおりに動くことを確かめました。wait信号やバブルを1つも書かずに、タイミングは従来のレジスタ+wait方式と同じになっています。以後のStepでは、この骨格に部品を足していきます。