Nand to Tetrisとは
Nand to Tetrisとは、NAND回路だけを与えられた状況から自力で各種論理ゲート、ALU、CPUを作り、さらにコンパイラ、OSを自作してコンピュータアーキテクチャの全体像を身につける講座です。自分で1から(Nandゲートから)最終的にはPongとよばれるゲームを動かすまでを自作することができます。
講座のやり方
公式サイトにて課題や授業のスライド、6章までは本の内容も公開されており、課題に必要なデータやシュミレータはこの公式サイトからダウンロードします。
私は本を購入せずにCourseraにて講義を受けつつ、課題を進めました。Courseraでは無料もしくは有料(月7千円程度)のどちらかを選択でき、有料の場合は講座の全ての課題を完了すると修了証がもらえます。私は前半を有料講座で、後半を無料講座で受講しました。無料講座の場合には課題の提出を行わないため課題の自動採点がありません。しかし、公式サイトで配布されているアプリにて(おそらく)同様のテストが可能であるため、支障は感じませんでした。サーティフィケイトが欲しいかどうかで決めて良いかと思います。
公式サイト
日本語版書籍
Coursera
自身のモチベーション
コンピュータアーキテクチャについて学びたい気持ちは前からあり、有名なCPUの作り方も読んでみたのですが(大変良い本です)、CPUと自分が普段書いているコードのつながりまで理解するには足りず、また私は情報科の出身ではないためにコンピュータサイエンスの知識が不足しているのではという不安感がありました。ちょうど転職の境目で時間にも余裕ができたため、前々から楽しそうだなと気になっていたNandtoTetrisをやってみることにしました。
私は現在13章あるうちの11章を終えたところですが、ハードウェアを作成し、コンパイラの作成まで完了しました。この後はOSの作成が残っているものの、NANDゲートから自作言語を自分のコンパイラでバイナリに変換し、実行させるところまで自分の手でコードを書き上げることができ、充実感と達成感をめちゃくちゃ感じています。笑
前半 ハードウェア
1章から5章ではNandゲートが与えられ、そこからコンピュータの実装までを行います。実際にハードウェアを用意するのは大変なので、HDLと呼ばれるハードウェア記述言語での実装となります。
以下のような形で実装するハードウェアの概要が示され、実際にレジスタやALUのどの出力をどの入力に繋げるかは自分で考える必要があります。
基本情報技術者を取った際に、プログラムはすべて二進法の世界であること学んでいたのですが、いまいちピンときていませんでした。この講義を通じて実際に機械語(バイナリ)の命令の入力を受けて計算結果を出力する(例:1111110111011000 → MD=M+1)CPUを組み立てることで、今まで魔法のように感じていた計算やジャンプ命令がどのように行われているのかを学ぶことができました。
なお平日に講義を視聴、休日にコーディングという形で進めて前半を終えるのにおおよそ1ヶ月ほどかかりました。
後半 ソフトウェア
後半では、コンパイル・VM・アセンブラまでを好きな言語で実装していきます。ここからはある程度のプログラミング知識が求められますが、オブジェクト指向の言語を触ったことがあれば問題ないかと思います。
いつも触っている言語がどのように機械語に翻訳されるのかを自分で実装できるため、非常に楽しくやりがいがあります。が、前半に比べて手応えが強くなり、かなり時間がかかりました。特に関数呼び出しの実装(スタックに引数や必要な変数、また関数実行後の戻り先命令のアドレスを保存し、関数実行後には関数実行直前の環境を復元できるようにする)にやや手こずり、フィボナッチ関数が再帰で呼び出せたときには達成感がすごかったです。
実装に必要な情報や偽コードは授業やスライドで説明されているものの、単純にそれを反映させるだけでは動かない箇所もあり、きちんとした理解が求められる構造になっており、非常に良くできた教材だと感動しました。
ポインタへの苦手意識があったのですが、アセンブラを作るにはひたすらポインタを利用する必要があるため、だいぶポインタの理解が進みました。
印象に残っているのはレジスタを追加で使用せずにスタックからPopする方法(みたい人はこちら)、めちゃくちゃ賢いな、、と思ったし、それ以上にもっと複雑で効率的なレジスタの管理が現在のCPUでは使われているのかと思うと、本当にありがたい。
やってよかったと感じること
まず、自分が普段利用しているコードがどのように解釈され、実行されていくのかを実装を通して(苦労しながら)知ることができるので、コンピュータアーキテクチャを築いてきた数多の偉大な先人たちへの感謝の気持ちが生まれました。コンパイルエラーにはありがとうを言わなければいけない。
仕事上でコードを書く際にも、関数の呼び出しやスコープが実行時にどのように制御されているのかをイメージできるようになったため、自信と納得感を持ってコーディングできるようになりました。また何かしらのエラーが出た際にも、今まではOS以下の領域はブラックボックスと感じ、デバグに時間がかかっていましたが、Nand2Tetrisをやった後では例え自分が知らないエラーであっても、エラー文を読めばプログラムを実行するまでのどのタイミングでエラーが起きたのかを想像できるようになったため、エラーの内容を進んで理解しようと思えるようになりました。ただ圧倒的にデバグやコードを書くのが早くなったかと言うと、そんなことはないかな。笑
コンピュータがどのようにプログラムを実行するのかと言う全体像を身につけたことで、書くコードが良くなったと言うよりも、メンタルモデルや自信の向上に大きく貢献してくれたように思います。
不足している?と言われるところ
現代のコンピュータアーキテクチャにおける2つの非常に重要な概念は、パイプライン化とメモリ階層ですが、どちらもテキストにはほとんど含まれていません
-TeachYourselfCS-JP
現代で実際に利用されているCPUやコンパイラはこの授業で取り扱ったものよりも非常に複雑かつ効率的であるため、一応授業の中でも授業用の言語や使用と現在の技術の違いについて簡単には触れられているものの、この授業だけでは理解するにはかなり不足していると感じました。あくまでも全体像を実感として身につけるためのものであり、全体像を身につけることこそが非常に意義深く、またここから興味の方向に応じて深掘りしていくと良いのかなと思います。なおNand2Tetrisを終えた後にパタヘネ本を読むとかなり理解しやすく、現状のアーキテクチャについても触れられるため、基礎をしっかり理解した後に知識の幅を広げるのに非常におすすめです。
次にやりたいこと
- パタヘネ本が積読(Kindleで買ったから積まれてないけど)になっているので、得た知識で読み進めたい
→読みすすめ中、おすすめ - コンパイラ楽しいのでもっとやりたい
- 次はインタプリタでもいいなあ
- OSも作ってみたいよね
- CPUの気持ちに近づく
さいごに
高水準言語で書いたプログラムがCPUで実行されるまでに何が起きているのかを知りたい初心者には確実におすすめできる教材です。課題やテストが非常に良くできているため、課題をすすめるのが非常に楽しいです。かなり時間がかかってしまう(私の場合は働きながらで2ヶ月程度)のが難点ではありますが、自分で実装したことがあるという経験は自信にも繋がり、周辺分野をより深く学んでいく際にも役立つと思うので、ぜひチャレンジしてみてはいかがでしょうか。