CPU実験が終わりました 〜コア係目線〜
タイトルの通り,遂に理情名物であるところの「CPU実験」が最終発表まで全て終わりました.この記事はその振り返り,という体のポエムになります.
追記にて学科同期によるCPU実験の記事をまとめたので,ぜひそちらも御覧ください.
目次
CPU実験とは?
CPU実験の正式名称は「プロセッサ・コンパイラ実験」で1,その内容は「CPU,コンパイラ等を自作して,如何に速く与えられたプログラム(通称「レイトレ」)を動かせるか競う」というものです.
とはいえ1人でコンパイラからCPUまで作るのは労力が洒落にならないので,3~4人ずつで班分けして以下の役割を分担します2.
上2つはハードウェア系,下3つはソフトウェア系です.そして今回僕が担当することになったのが,上で強調されている通り「コア係」でした.ということで,この記事では主にコア係の目線で話すことになります.
コア係とは?
コア係の説明で「CPUを実装する」と言いましたが,ブレッドボードなどで物理的に配線するわけではないですし,半田ごてを使ったりはしません3.
講義期間中,各班には「FPGA」という基盤が与えられます. FPGAは簡単に言うと「ユーザがプログラムを介して配線を構成できる基盤」で,より抽象度の高いレベルでユーザが配線を構成することができます.
このプログラムにはVerilog,SystemVerilogというハードウェア記述言語(HDL)を用います.プログラムのコンパイル,配線の最適化,基盤への書き込み等はvivadoという統合開発環境(IDE)を使います.
というわけでコア係の仕事は,より正確には「CPUをHDLで実装する」ことになります.
資料がない?
ただし諸々の資料や講義がある他の科目と異なり,CPU実験ではツールとFPGA以外は何も与えられません.参考資料も土台となるプログラムも皆無です4.そんな中でどうやってCPUを作るのかと言うと,
- 過去の講義を復習する
- 歴代のブログを漁る
- 公式ドキュメントなどを読んで,種々の機能の使い方を学ぶ
- 本などを読んでCPUの基本的な構成を学ぶ
などをすることになります.このブログの末尾に僕が参考にした資料をまとめました.これからCPU実験を体験する皆さんの力になれば幸いです.
ちなみにこの「何をすればいいか分からない」「公式ドキュメントを読まないといけない」といったところが「コア係はキツい」と言われる理由の3割くらいだと思っています.残り7割はハードウェア,vivado,verilog特有の非自明なバグと,それらのデバッグの困難さです.
全体のスケジュール
僕がコア係としてどのようなスケジュールで開発をしたのかを簡単にまとめました.興味のない方は結果まで飛ばして大丈夫です.
10月: 学習期
10月中はパタヘネを通読してコアの構造を学んだり,ALU・レジスタ・デコーダ等の基本モジュールを実装しました.
これだけなら良さそうに聞こえますが,実は実機に一度も触れていません. 結果として諸々の知見を聞き逃してしまったので,これからコア係をやる人は積極的に地下5に通うことをオススメします.
11月: 実装期
11月から腹を括って実機に触ることにしました.いよいよCPU実験開始です.
第1週: Lチカ
まず第1週にLチカをしました.先代の知見に圧倒的感謝(参考資料を参照).ついでに実装済みのALUとレジスタの動作確認もしました.
第2週: UART
第2週でUARTを実装しました.UART通信はAXI UART LiteというIPコアを使ったので,最初にそのドキュメントを読み込みました.
AXIの実装はハードウェア実験で実装したものをほとんど流用でき,バグを直してUART loopbackが動きました.I/O周りはバグを踏みやすい印象があったので怖かったですが,無事に乗り越えられて安心しました.
第3週前半: メモリ
第3週前半でメモリ周りを調べました.当初はAXIでメモリアクセスを行う予定でしたが,仕様が全然分からなかったのでBlock Memory Generatorのnativeインターフェースを使うことにしました.
これは偶然にも良い選択でした.というのも,メモリアクセスはUART通信と違ってかなり頻繁に行うため,AXIインターフェースでは遅すぎるのです.実際メモリアクセスは後に限界まで高速化することになります.
第3週後半: コア
第3週後半,いよいよコアのデバッグです.10月中に実装したものを試しに動かして見るも,流石にそう簡単には動きません.
そこで最初は「1から100を出力する」という簡単なプログラムから始めました.シミュレータ(vivado)とシミュレータ(ソフトウェア)を睨みながら,非想定の挙動を見つけて修正...を繰り返し,なんとか動かすことができました.それからさらにデバッグを重ね,遂に「再帰フィボナッチ」を動かすことができました.これでコアは概ね完成です.
ここまで早くデバッグが終わったのは,一重に優秀なシミュレータ(ソフトウェア)のおかげです.ちなみにどうやってデバッグするかというと,プログラムカウンタ・レジスタの中身がシミュレータ同士と一致しなくなった場所を二分探索です.地道な作業ですが,これが一番効果的だったりします.
第4週〜: 完動
その後FPUの方も完成し,僅かな修正によってレイトレを動かすことに成功しました.最後に謎の黒い線が出てしまい,どこの演算の精度不足が原因かを探るので四苦八苦した記憶があります.
12月~1月: 倦怠期
それからしばらくはCPU実験に触れませんでした.その理由を上げるとすれば,
- 11月の疲れが押し寄せてきた
- パイプラインの構想が詰めきれなかった
- 期末試験があった
等があります.特に期末試験の影響は大きく,次にCPU実験に触れたのは全ての試験が終わった1月後半からでした.
2月: ラストスパート
いよいよ最終月ということで,本格的に高速化に取り組み始めます.
2nd対応
最初にやったのが2ndアーキテクチャへの対応です.
班にもよりますが,うちの班は
の2段階にアーキテクチャが分かれていました. といってもCPUの構造が根幹から変わるような命令は追加されなかったため,コア係としてはデコーダを作り直すだけでほとんどは事足りました.
ちなみにこの裏でコンパイラ係はmincamlをScalaでフルスクラッチしていました.それでいて最終的な命令数は全体で恐らく最少なので,正に狂気です.
パイプライン化
次にいよいよパイプライン化を実装することにしました.
「パイプライン化はバグったら終わる」とずっと思っていたので,設計を極力詰めてから実装を始めるようにしました. 上の倦怠期の間も何もしていなかったわけではなく,パタヘネを読み直したり,回路図を描いて設計を整理したりしました.以下はその回路図です.
しかしやはりバグというのは存在するもので,またしてもシミュレータとにらめっこをすることになりました.特にパイプライン化は「今どの命令を実行しているのか」が分かりにくいため,慣れるまでデバッグにかなり手こずりました.
それでも徹夜でバグを潰し,結果として実行時間は半分以下になりました.この時点で動作周波数は20MHz,コンテストは200秒程度でした.
クロック分割
最後の大きな改善として,動作周波数を上げました. この作業でメインとなるのはFPU係で,FPUのクリティカルパスをクロック分割することで減らしてもらうことになります.
FPU係の努力の結果として,動作周波数は20MHzから180MHzまで上がりました.なぜかvivado上では最大周波数が130MHzだったのですが,最長のワイヤ線が本来あるはずのないものだったので試しに上げてみたら180MHzまで動きました.130MHz辺りでなぜか周波数が上がらなくなったら試してみるといいと思います.
最終結果,所感
最終的なスペックは以下のようになりました.
- 命令数: 10.82億
- 動作周波数: 180MHz
- コンテストの動作時間: 19.734sec
目標としていた20秒を割ることができました.しかし命令数的にコアがもっと頑張れば10秒前半が出てもおかしくないと思っていて,コア係としての力不足を感じました.
コア係をやって良かったか
最初の講義でコア係に立候補したのは完全に気まぐれでしたが,結果としてコア係になったのは正解だったと思います.その理由をいくつか挙げると,
- CPUの構成に対する学びがかなり大きかった
- 普段から地下6によく来るタイプなので向いていた
- 完動だけならそこまで大変な方ではない
などがあります.3つ目については,傍らから見た感じコンパイラ係の方が遥かに大変なように思いました.「労力」に対する「学べること」のコスパを考えると,コア係が一番かな,という印象です.
参考資料
Lチカまでの過程がかなり丁寧に書かれた神資料です.最初はこれを読んでvivadoの使い方を学ぶと良いです.
前セメスターで開講された「計算機構成論」の教科書です.日本語が怪しい箇所がままありますが,コアを実装する上で十分な内容が簡潔にまとまっています.
俗に「パタヘネ」と呼ばれる本です.厚さから威圧感を受けますが,平易な文章と豊富な図で,かなり詳しくコアの実装方針について書かれている良書です. 特にパイプラインの項は非常に参考になるので,実装前に一読することを強く推奨します. ちなみに下巻は余興とかやらない限りは読まなくて大丈夫です.
講義で使われるFPGAである,KCU105の公式ドキュメントです.制約ファイルを書くときに,ピンの名前を調べるために使いました.並列化とか余興をやろうとすると,さらに読む必要があるかもしれません.
UART通信を行う手段としてAXI UART LiteというIPコアを使う方法があるのですが,その公式ドキュメントです. これはChapter2までちゃんと読んだほうが良いです.非自明な仕様がそれなりにあります.
BRAMを使う上で用いた,Block Memory GeneratorというIPコアの公式ドキュメントです.しかし上の方にはプロトコルが存在せず,下の方の資料にありました.
追記: 同期によるCPU実験の記事
僕とは違う班ですが,コンパイラ係目線の記事です.
1ヶ月でLinuxを動かした余興班の記事です.何かもう,すごいです(語彙力).
-
厳密には,「プロセッサ実験」と「コンパイラ実験」という2つの講義が1つの科目として扱われている感じです.CPU実験に当たるのが「プロセッサ実験」で,「コンパイラ実験」では係に関わらず全員がコンパイラに触れることになります.↩
-
4人に対して係が5つありますが,大抵の班はアセンブラ係とシミュレータ係を1人が担うことになります.3人班はかなり大変です.↩
-
学科ガイダンスの資料を見るに,昔は物理レベルの配線をやっていたようです.恐ろしい….↩
-
「資料が何もない」というのは若干の誇張で,1つ前のセメスターで開講される「ハードウェア実験」「計算機構成論」の資料が参考になります.それでもCPU実験独自の資料がないのは事実で,多分「これまでの講義の知識を使ってね」というノリだと個人的に考えています.↩
-
上の注釈を参照.↩