自作CPU&自作コンパイラやってみた
はじめに
私は低レイヤの技術が好きで、特に自作する系の技術書は何冊か読んで手を動かしてみました。(自作 OS、自作 CPU、自作コンパイラ、、、)そんな中、ふと CPU を作り、その CPU 用のコンパイラを作り、アプリケーションを書いて、そのアプリケーションをコンパイルしたバイナリを CPU の上で動かしたら面白いんじゃないかと思い、実際にやってみました。実装は以下になります。
- CPU+アプリケーション:https://github.com/kkinos/zktc
- コンパイラ:https://github.com/kkinos/zktc-c-com
- アセンブラ:https://github.com/kkinos/zktc-asm
CPU
SystemVerilog で実装し FPGA 上で動かしました。特徴は以下です。
- 16 ビット、8 本の汎用レジスタ
- RISC
- マルチサイクル(1 命令 6~7 サイクル)
- パイプラインなし
- 割り込み対応
- I/O は UART、GPIO、LED
命令セットはオリジナルですが RV32I を参考にしました。RV32I からの変更点ですが、まず命令長が 16 ビットしかないので、オペランドレジスタの片方をディスティネーションレジスタにしています。命令長のことを考えるとスタックマシンやアキュムレータがあるような CPU でも良かったかなと思います。
また pop、push 命令を追加しています。pop、push 命令をはそれぞれ load、store 命令 と addi 命令で代替できますが、コンパイラをスタックマシンで考えていたので命令数を減らすために追加しました。
他にも addi 命令は便利な命令で、スタックポインタやフレームポインタの増減、定数のロードなどで使用するので、少しでも即値の幅を増やすために RV32I のように即値の符号拡張はせず、即値の減算のために subi 命令を追加しています。自作した CPU の命令一覧はこちらです。
この CPU で動かすアプリケーションとしてマルチタスクな OS のようなものを動かしたかったので、ソフトウェア割り込みも実装しました。
コンパイラ
有名な低レイヤを知りたい人のための C コンパイラ作成入門を参考にしつつ、Rust で実装しました。コンパイルする言語は C のサブセットを考えていましたが、思った以上に大変だったので、途中で C ライクなオリジナルな言語ということにしました。出力はアセンブリです。なのでアセンブラも実装しました。
以下の機能を実装しました。
- 四則演算、論理演算
- if、else、for、while
- ローカル変数、グローバル変数
- 関数定義、関数呼び出し
- 配列
- ポインタ
- 文字列リテラル
- 構造体
- コメント
- インラインアセンブラ
コンパイルは分割コンパイルではなく、必要な全てのファイルを一度に入力することにしました。そしてアセンブリで出力する時に適当にグローバル変数や関数などを配置し、それをアセンブラがシンボル解決して実行ファイルを生成します。つまりリンカがやることをコンパイラとアセンブラがやる形になっています。
アプリケーション
アプリケーションをメモリにロードする方法ですが、SystemVerilog には readmemh というファイルからデータを読み込み、配列に格納するという機能があります。これを使って、あらかじめメモリ用の配列の一部の領域にブートローダを格納しておき、CPU の起動時にその領域から実行を開始することで最初にブートローダが立ち上がるようにしました。ブートローダは以下のように立ち上がります。
load コマンドを実行すると UART を使用した XMODEM でのファイル転送が可能になり、Teraterm などを使ってアプリケーションを転送できます。その後 run コマンドでアプリケーションを実行します。この辺りは 「12 ステップで作る組み込み OS 自作入門」の KOZOS を参考にしました。
KOZOS を参考にしつつ、組み込み OS(ライブラリ OS?)を作ってみました。アプリケーションはこの OS の API を使って実装し、OS とアプリケーションを一緒にコンパイルして一つの実行ファイルになります。OS には以下の機能を簡単にですが実装しました。
- マルチタスク
- タスク間通信
- 割り込みハンドラ
- セマフォ
- メモリ管理
またアプリケーションとして以下を実装してみました。
- ハングマンゲーム(文字当てゲーム)
- マンデルブロ集合の描画
おわりに
CPU とその CPU 用のコンパイラを自作し、アプリケーションを書いてコンパイルして CPU 上で動かして遊んでみました。やり切るまでに時間はかかりましたが、長い間楽しめたとも言えるので良い趣味の開発かもしれません。低レイヤの自作系のものは一通りやってみたという人にとってはおすすめだと思うので、そのような人の参考になれば幸いです。
Discussion