nand2tetris

一通り終えたので、感想などを書き残しておきたい。

1~5章は一週間かからずにやれたと思うけど、 6章から12章のソフトパートは、3週間くらいはかかったのではないかと思う。 (手が止まっていた期間もそこそこあるけれど。)

1章

この章ではNANDからNOT、AND、ORとか基本的な素子を作った。 大学のころ授業でやって気がするが、ド・モルガンのNOTを二つつけて変形するテクニックとか忘れていて、思い出して楽しめた。

2章

この章では全加算器までを作った。これは淡々と進めた。

3章

この章ではフリップフロップからレジスタ、そしてRAMを作った。

時間があるときにフリップフロップを物理的に作ってみたいなーと思っているので、そのうちやってみたい。 (水晶振動子とかも。)

4章

この章は、アセンブリ言語に慣れる章だった。 独自のアセンブリ言語の仕様をちゃんと読めばすぐ終わるのに、適当に読み飛ばしていたのでちょっと詰まった。

5章

この章は、CPUを組み立てる章。

これまでの章の内容をちゃんと理解できてないとCPUを作るのが難しいと感じた。自分は、2章で作ったALUの仕様をちゃんと理解してなかったり、4章で課題をこなす程度にしかアセンブラの仕様を読み込んでいなかったのが原因で、ちょっと詰まった。

逆にこの章でCPUを作り終えると、4章までの内容は大体理解できたな、と実感できる。

ハードはソフトと違って、各クロックで複数の処理を平行して実行して、必要な処理だけを選択して使うという実装になるのが感覚的にわかって面白かった。

6章

この章では、アセンブリ言語機械語に変換するアセンブラを作る。 忘れかけていたRustを思い出しながら書いたので、基本のパーサを書くあたりでも苦労した。

7章

この章では、VMとして作ったCPU上で動作するスタックマシンを作る。

popの実装のときに、値の入れ替えが必要になったけど、レジスタ2つしかなくて無理では?となってちょっと詰まった。 RAMの固定アドレスをレジスタR5-R12として扱うので、ここがレジスタ代わりに使えることに気づければ、あとはコツコツやればできた。 過去にもなんどかアセンブラを書いたことはあるのだが、スタックのpushとpopを実装するのは初めてだったので、結構新鮮だった。

ずっとJVMで仕事してきたのに、あまりVM自体については考えたことがなかったので、今回の実装を通して多少でも理解できたのは大きな収穫かもしれない。

8章

制御構文は簡単に実装できるし、関数フレームの作り方も疑似コードが示されているので、こつこつやればできた。レジスタは3つあれば大体なんとかなる。

9章

この章は、詰まってから読み返せばいいので、流し読みして終わり。12章の課題を一部先に実装してもよいかもしれない。

10章

コードから構文木を生成する。 公式のテストを通せればよいわけではなく、ちゃんと木構造を作らないといけない。 構文木の生成自体が別に難しいというよりも、 コンパイラをさほど慣れていないRustで書いてしまったせいで、Rustの使いこなしで結構苦労したりもした。

本書はかなり上長に構文木を構築するけれども、ほとんどのキーワードは除外した方が楽なので、後で手を入れた。

11章

10章で生成した構文木をもとに、VMのコードを生成する。 なかなかどこから手を付けるかピンと来ずに苦労したが、JackCompilerが吐き出すVMコードを見ればわかった。 ここで、VMで実装したthisとthatの意味を理解した。thisはともかく、thatがなぜ必要なのかわかってなかった。

12章

OSとして、動的なメモリ確保や、基本的な描画などをJack言語で実装する。

12章はこれまでの章とは違ってアルゴリズムが示されているので、Jack言語で実装するだけである。 とはいえ、Jack言語の演算子は一文字のみなので、2文字の演算子が使えなかったりとか不自由した。あとは、アドレス指定してデータ操作する方法もわからず迷子になったりはした。 いっそ言語を拡張しようかと思ったが、面倒なので結局やってない。

演算子の順序や、種類を増やしたり、制御構文を拡張したりといったことは、やればできると思う。 (が、まぁ、やり方もだいたいわかることに時間を使うのもなぁという気分になったので。。。)

全体を通して。

いろいろ物足りなさがあるけれども、コンパクトに一通り学べる教材だと感じた。

これまでもリアルタイムシェーダー、コンパイラ、OSなど、それぞれ個別にもう少し踏み込んだ内容を扱う教材で学んできたが、 今回のハードからOSまで一貫して実装してみるというのは、ほかに代えがたい内容だと感じた。

手だけでなく頭も動かして、結構悩んだり、再設計しなおしたりもしたので、理解が深まったと思う。 特にVM周りの仕様は、最初疑問だったことが、後の章で納得できることも多く、勉強になった。

ただ、テストスクリプトや期待する出力は事前に示されているので、 本当に自力で実装するのと比べるとずいぶん楽をさせてもらったような気はする。

CPUの設計から自分でやってみれば、本当の意味で理解が深まるのかもしれない。そのうちやってみたい。

これまでにやってみた自作

参考まで。

  • 大学4回のころに、リアルタイムシェーダーを実装したけど記事に残してない。

ma38su.hatenablog.com

ma38su.hatenablog.com

ma38su.hatenablog.com

ma38su.hatenablog.com

ma38su.hatenablog.com

記事にしてなかったが、Ray Tracing in One Weekend Seriesもやった。 raytracing.github.io

ma38su.hatenablog.com