未経験が読む「コンピュータシステムの理論と実装」#1

## はじめに
はじめまして、糸井と言います。
現在公務員からエンジニアへの転職活動の準備中の身です。
縁あって、ポートフォリオをレビューしていただいたエンジニアの方から「この本の勉強会を開くから来ない？」とお誘いをいただき、低レイヤーの勉強のために毎週一回参加させてもらっています。

まだ1章の演習中ですが、nand回路からnot, and, or, xor等の徐々に複雑な回路を実装していくのが、パズルのようでおもしろいです。

この記事では、本の第1章の終わりまでをスムーズに取り組めるよう、内容を書いていこうと思います。

手元にある本は初版第7刷になります。ページ数表記は適宜読み合わせてください。

## 「コンピュータシステムの理論と実装」とは
この本の愛称は、この記事のタグにもさせてもらっているNand2Tetrisだそうです。Nand回路からTetrisを作る…わかりやすいですね。
裏書きは以下のとおり

> コンピュータを理解するための最善の方法はゼロからコンピュータを作ることです。コンピュータの構成要素は、ハードウェア、ソフトウェア、コンパイラ、OSに大別できます。本書では、これらコンピュータの構成要素をひとつずつ組み立てます。具体的には、NANDという電子素子からスタートし、論理ゲート、加算器、CPUを設計します。そして、オペレーティングシステム、コンパイラ、バーチャルマシンなどを実装しコンピュータを完成させて、最後にその上でアプリケーション(テトリスなど)を動作させます。実行環境はJava(Mac、Windows、Linuxで動作)。

<b>自分でコンピュータを作る！</b>これに私は非常に興味をそそられました。

## もくじ
[1. シミュレータのインストール](#1-シミュレータのインストール)
[2. チップ実装の手順](#2-チップ実装の手順)
[3. VS Codeでシンタックスハイライト](#3-vs-codeでシンタックスハイライト)
[4. 1章の実装のヒント](#4-1章の実装のヒント)
[5. おわりに](#5-おわりに)

## 1. シミュレータのインストール
まずは<i>1.5 プロジェクト</i>まで読み進めてください。
<i>1.5 プロジェクト</i>の"手順"(P.25)まで来たら、手順に従ってハードウェアシミュレータをインストールします。
付録C(P.361)に従って"https://www.nand2tetris.org/software/nand2tetris.zip" からOSに合ったファイルをダウンロードしてインストールしてください。英語ですががんばってください！
私はMacでインストールしましたが、Macの場合"Setup Guide for Apple MacOS"にきちんと手順が書いてあります。

ちなみに、2022年３月にインストールしましたが、たしかにJavaは最新版でなければ動作しませんでした。
```
$ java -version
java version "1.8.0_321"
Java(TM) SE Runtime Environment (build 1.8.0_321-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.321-b07, mixed mode)
```
さらにちなみに、訳注のハードウェアシミュレータ・チュートリアルのURLは変わっています。
このページ↓の上から1/3あたり、"Software Tools"にあります。
https://www.nand2tetris.org/software
PDF↓
https://www.nand2tetris.org/_files/ugd/44046b_bfd91435260748439493a60a8044ade6.pdf

## 2. チップ実装の手順
#### ハードウェアシミュレータの起動
手順書通りインストールしていれば、下記のコマンドでシミュレータを起動できます。
```
~/Desktop/nand2tetris/tools/HardwareSimulator.sh &
```

#### コードを書く
エディターで該当チップの.hdlファイルを開き、実装します。
ハードウェアシミュレータではコードを書き換えられません。
シンタックスハイライトが当てられるプラグインを後ほど紹介するので、VS Codeはオススメです。

```
CHIP Not {
    IN in;
    OUT out;

    PARTS:
    // Put your code here:
    // ここに書く
}
```
「とりあえずどう書くのか例を見たい」という方のために、Notの回答例を置いておきます。

<details><summary>Notの回答例</summary><div>

```
CHIP Not {
    IN in;
    OUT out;

    PARTS:
    // Put your code here:
    Nand (a=in, b=in, out=out);
}
```


</div></details>

#### 回路のロード
左上のFileの下の[ICチップのようなアイコン]をクリックし、ロードする回路を選択します。
`Desktop/nand2tetris/projects/[1章なら 01]`
![loadChip.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633406/c8c3bb57-85da-35b4-a414-c10f55fa238b.gif)



#### テストのロード・実行
1. 回路をロードできたら、テストをロードします。
赤い旗の左隣の[羊皮紙のようなアイコン]をクリックし、回路と同名のテストをロードします。
2. [>>のようなアイコン]でテストします。ちなみに、その左の[>のアイコン]はステップ実行です。
3. ウィンドウ左下に`End of script - Comparison ended successfully`と出ればテストをパスしています。おめでとうございます🎉
![loadTest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633406/faf87038-a022-3480-0588-a63b50c2a817.gif)


## 3. VS Codeでシンタックスハイライト
VS Codeでシンタックスハイライトを当てるプラグイン
https://marketplace.visualstudio.com/items?itemName=loyio.Nand2Tetris-vscode
非常に見やすいのでオススメです。
![スクリーンショット 2022-04-30 21.40.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633406/b60c8d88-c605-e612-fd37-c63fd7cdea86.png)

あとは指定された回路を実装していきましょう！

## 4. 1章の実装のヒント
作る順番としては
Not
And
Or
Not16
And16
Or16
Or8Way
Xor
Mux
Mux16
Mux4way16
Mux8way16
DMux
DMux4Way
DMux8Way
の順がよいかと思います。

また、私がつまずいたものだけですが、考え方のヒントを残しておきます。
コード自体の答えが知りたい方は、GitHubに上がっているものを探してみてください。
参考にさせていただいた@y-meguro さんの記事にもGitHubリポジトリのURLがあります。

<details><summary>Not16</summary><div>
for文が使えない以上、地道に書くしかなさそうです。
</div></details>

<details><summary>Xor</summary><div>
細かい理屈は分からないままですが、実装すること自体はできました。<br>
P.5の図1-2を参考に、正準表現から実装しました。<br>
正準表現は、P.3ブール式を参考にすれば、Nand,Not,And,Orをどう組み合わせるかわかります。
</div></details>

<details><summary>Mux</summary><div>
Xorと同様、細かい理屈は分からないままですが、実装すること自体はできました。<br>
ポイントはやはり正準表現。ただし今度は入力が3つなので図1-2は使えません。
<details><summary>Muxさらにヒント</summary><div>
ベン図を描くと正準表現が分かりやすく書けます。
</div></details>
</div></details>

<details><summary>Mux4Way16（3行で実装するテクニック）</summary><div>
今まで作った１６ビットチップの中で便利なものがあります。<br>
ちなみに、多ビットの一括した入力出力の書き方は

```
(IN a[16], b[16], out[16];　の場合）
And16 (a=a, b=b, out=out);

(IN sel[2];　の場合）
sel = sel[0..1];
```
このように書けます。
</div></details>

<details><summary>DMux</summary><div>
入力２、出力２ですね。今までは入力:出力は1:1か2:1でした。<br>
どうやって出力を増やすかですね。
<details><summary>出力ピンの増やし方</summary><div>
Notのようにひとつのピンを複数回入力に使えば、出力を無限に増やせます。<br>
あとはどういうときに出力を0/1にするかです。
</div></details>

</div></details>


## 5. おわりに

今のところ一章までしか終わっていませんが、非常に楽しく学べています。

今後も章ごとに詰まったポイントをまとめていきますので、気長にお待ちいただけると幸いです。
お読みいただきありがとうございました！
<br>
<br>
##### 参考にさせていただいた記事

@y-meguro さん
「コンピュータシステムの理論と実装」をやりきりました
https://qiita.com/y-meguro/items/dc11c31cc2667aa20b3c

@Kendai さん
プログラミングを初めて半年の初心者がCPU ・コンパイラ・ OSを自作した話
https://qiita.com/Kendai/items/be5eb2d66d6b9138a9f2



<br>

##### 更新履歴
2022/05/10　Mux4Way16, DMuxのヒント追記
2022/05/23　2章以降に合わせ、タイトル変更