FANCOMI Ad-Tech Blog

株式会社ファンコミュニケーションズ nend・新規事業のエンジニア・技術ブログ

CPU作りました

2月から3月までの二ヶ月間インターンをさせていただきましたko_tamuraです.
私自身は計算機科学の専攻ですが,計算機アーキテクチャに興味があって研究も特定用途向けプロセッサの開発をしてます.
今回F@Nさんとご縁があって,CPUを作りましたので,そのまとめをしたいと思います.

参加の経緯

サポーターズの逆求人イベントでF@Nの方とお話し,ぜひインターンシップに参加したいと考えました.
普通のインターンシップだと業務体験みたいな感じで,与えられたテーマに学生は取り組むという形になると思います.
F@Nのインターンシップでは自由になんでも開発してよい,しかもF@Nの事業に関係なくてもよいという寛大な心と懐の広さに惹かれました.

インターンの目的

だいたい次のつもりで参加してました.
・計算機の知識を深める
・F@Nの方が何やってるか,雰囲気だけでも知る

以上の2つはおおむね達成できた気がします.

私自身は知識を身につけるだけで満足するタイプの人間ですが,工学分野では開発と理論はきっても切り離せない関係にあります.開発を通じてより知識を深めるという普通の企業の開発とは逆の目的でやってました.

やったこと

CPU作りました.
具体的には主に次の本にならって学びながら作りました.
gihyo.jp
XilinxというFPGAベンダの開発環境Plan Aheadを使ってCPUと,それを動かすために必要なシステムをVerilog HDL(回路を記述できる言語)を使って開発しました.

FPGAについて

FPGAってなんぞや?という人のために,簡単に説明します.FPGA (field-programmable gate array)は,書き換え可能な論理デバイスです.普通のASIC(application specific integrated circuit)のような回路は焼付けたら変更は不可能ですが,これはレジスタ(フリップフロップ)と演算器によって構成される単位から構成されており,その単位同士の配線をユーザが切り替えることで任意の回路を構成できるというアーキテクチャをしています.

従来はその設計柔軟性から制御系の産業でテスト的に使われることが多かったのですが,半導体の性能向上によって情報処理分野でも使われることが増えました.

処理の高速化やコスト削減のためにマイクロソフトのBing検索エンジンに使われた事例があります.また,クラウドでもAWSが提供するF1インスタンスを利用すれば,FPGAによる高速化の恩恵を享受できるソリューションを構成できます.しかも今では高位合成という,高級言語から回路を生成する技術も生まれ,トップダウン的なFPGA開発ができるため,興味があればぜひグーグルに聞いてみてください.

構成モジュール

全体構成

f:id:fan_ko_tamura:20180328144215p:plain

クロックソース

ICはクロックに同期した処理を実行した方が都合が良いので,評価ボードに備わるクロックジェネレータから入力します.
非同期設計にするとデータアクセスのタイミング設計がとても難しなります(同期回路でもクロックとデータ信号の遅延差を考慮せねばなりませんが).

CPU

いわずもがなです.
32bit RISCプロセッサを構成しました.詳しくは後述します.

SPM(スクラッチパッドメモリ)

キャッシュメモリのような役割を果たしますが,これは主記憶装置とは接続されず,プロセッサ側からのみのアクセスに利用できます.
PS3などで利用されていたセルプロセッサではSPMが搭載されているものがありましたが,メインストリームにはなれませんでした.

バス

各モジュールをつなぐ部分です.
バスは各モジュールがいつ使うかという管理機構が複雑でした.
関係ないけどバスって移動手段のバスと同じ語ですよね.Busはラテン語のomnibus(すべての人のための)という意味らしいので,このバスはすべてのモジュールのためのものとなります.

UART

UARTという規格でUSBを通じて外部の機器と通信できます.
外部から機械語の入力をこのシステムに与えればCPUが動く,みたいな用途を想定しています.

タイマ

時間を計ります.
ハイデガーによると存在は時間を根拠にしています.

ROM

記憶領域です.
ROMはFPGAベンダが提供しているIPコア(APIみたいなものです)を使って評価ボード上に搭載されているROMにアクセスができます.



プロセッサの構成

計算機の構成は大きく分けてCISC(Complex Instruction Set Computer)とRISC(Reduced Instruction Set Computer)の2パターンあります.
両者の大きな違いは命令長の長さです.

従来の計算機は命令長の長いCISCで,CPUが実行する命令が長いとデコードに時間がかかり,また並列処理に向きません.消費電力も大きいです.
実際にユーザが計算機で使う命令は単純な命令の組み合わせで実現できることがほとんどなので,命令長を短くして,それを並列に行ってスループットをあげよう,という思想から生まれたのがRISCアーキテクチャでした.
RISCでは命令パイプライン(命令を実行するライン工みたいなイメージです)によってレイテンシを隠蔽し,スループットの向上を実現しています.また,これによってレジスタ間の伝達遅延を抑えられるため,動作周波数が向上できます.
最もよく使われている命令パイプラインアーキテクチャは次の5つのステージで構成されます.

  1. Instruction Fetch: 命令をメモリから取り出す
  2. Instruction Decode: 命令を解釈して,演算に備える
  3. EXecute: 演算を実行する
  4. MEMory access:メモリのロード,ストアを行う
  5. Write Back:CPUレジスタにデータを書き込む

f:id:fan_ko_tamura:20180330152401p:plain

しかし,様々な要因によって図に示すような理想の動作ができません.
次に示すパイプラインハザードが発生した時には,何もしない命令を途中にはさんで処理の整合性を保つ必要があります.

IFとMEMが同じタイミングで発生し,伝送路が競合する場合

命令キャッシュとデータキャッシュを分ければ解決できます.ハードウェア的に領域を分けるということです.

EXの演算結果がレジスタに書きこまれない間に参照される場合

キャッシュレジスタを用意し,そこに演算結果を書き込んで参照すればよいですね.
賢いコンパイラならコードをなるべく依存関係がない順番にアセンブルしてくれます.

分岐命令により,順次実行されてきた命令が破棄される場合

( ˘•ω•˘ ).。oஇ



私自身は今回フォワーディング(EXの結果を直接次の命令で参照すること)を実装しました.
参考した本でも実装例があり,たぶん上記の中でこれが一番楽です.

こちらに実際Verilogで記述したコードがあるので,もし良ければご参照ください.https://github.com/flublight/my_CPU_with_SPARTAN3
自分で書いたコードとテキストのサンプルコードがごちゃまぜなので読むに耐えない感じになっています.

プログラマ的にRISCを知っておくと何がいいか

インテルのCPUも内部的にはRISCアーキテクチャを採用しているため,RISCの知識があるとより高速なプログラムを書けるかもしれません.
たとえば分岐命令を少なくすれば,上述のとおりパイプラインハザードを防ぐことができます.
更には,コンパイラや命令セットの知識があれば,パイプラインハザードを防ぐ効果的なプログラムが書けるようになります(しかし,その場合たいてい可読性が犠牲になります).高速性が必要となるソリューションでは,このような知識がかなり重要になります.

しかし,もっと早くするには,FPGAを使った専用回路を構成することが必要になると思います.

動作確認

をしたかったのですが時間の都合上できませんでした.
また現状ではデバッグが不十分なので十中八九動作しないと思います.
また,ロジックが正常であってもタイミング制約を与えてないので,もしかしたら動作しないかもしれません.10MHzの低速動作のため,遅延猶予は十分あるので杞憂かもしれませんが.
また,入出力機構はUARTしかないため,電気的な信号劣化の可能性は低いと信じています.

開発のまとめ

やったこと

  1. FPGA上にCPUと周辺回路を作った.
  2. CPUは32bitRISCプロセッサで,フォワーディング機能を持つ

できなかった(から後にやるべき)こと

  1. デバックちゃんとやる(めんどくさい)
  2. UART通信が正常にできるか実機確認する
  3. 機械語を送って動作するか確かめる

つらかったこと

  1. 配線がめんどう
  2. デバッグがめんどう
  3. 社内プロキシにはじかれる
  4. FPGA開発ツール探し(使ったFPGAが古かったので,それにあうバージョンを探す必要があった)

インターンの感想

かなりスケールの大きいデジタル回路を1から設計し実装したのは初めてだったので,システム全体の把握や,波形シミュレーションを使ったデバッグが大変でした.
機能の十分な検証にはあと数週間くらいかかりそうです(テスト項目をちゃんと作ったりしたら数ヶ月かかると思います).
しかし,計算機の内部の細かい仕様がわかり,実際にプロセッサを実装するのに必要な論理設計がなんとなくでも理解できたのは大きな収穫でした.

また,F@Nで働いている方の隣で開発ができて,働いている方々の実態がある程度わかりました.みなさん自由に,リラックスした環境で開発できるはすごく良いところだと感じました.また,社員の方にランチに連れて行っていただいたり,卓球の部活動に参加できたりと楽しい時間が過ごすことができて嬉しかったです.

最後に

二ヶ月間たいへんお世話になりました.
在学中にこのような貴重な体験ができて本当に良かったです.
本ブログは半分くらい計算機アーキテクチャのお勉強的な中身になってしまいましたが,エンジニアの方々の教養にでもなれば幸いです.
お世話になった方々はもちろんですが,事業とは関係ない開発を受け入れていただいたF@Nの懐の広さに改めて感謝いたします.ありがとうございました.