コンピュータとか

ハードウェアとかソフトウェアとかプログラミングとか

自作CPUを作る3.5 ~NandGameでやってみた番外編~

kouemuです。

またしてもf**k_3についてです。

なんとめちゃ簡単に作れました。

なのでOSを実行できるようにもしました。

 


目次

  1. 演算装置
  2. 命令装置
  3. CPU
  4. クロックのおすそ分け
  5. OSを実行できるCPU

 

1.演算装置

 

NandGameのスクリーンショット

演算装置

今回実装するものがあまりにも少なかったので演算装置をもとから一つにまとめました。
概要は前回までのものをご覧ください。

 


2.命令装置

 

NandGameのスクリーンショット

命令装置

こちらも同じくなのですが、接続がぐちゃぐちゃですね。

NANDの実行を「100」に設定していますがこれを「110」に設定すれば少し接続の量を減らせると思います。

またやらかしてましたね。

 


3.CPU

 

では早速CPUを見ていきましょう。

と言ってもあまりf**k_4と変わらないんですけどね...

NandGameのスクリーンショット

CPU

この通りです。

 

前回と違うのはEEPROMのアドレスセレクトの部分です!

ちゃんと直しましたよ!!(ドヤッ)

 


4.クロックのおすそ分け

 

ここではCPUを二つ搭載する際に、入力がごちゃごちゃにならないようにするためのものを作ります。

NandGameのスクリーンショット

クロック分割

仕様は、

・クロックをオンにしたときもし前回がどちらもオフなら片方をオンにする。

・クロックをオンにしたとき前回と反対の方をオンにする。

・クロックがオフなら両方オフにする。

となっております。

以下データシート

IN(前回の出力) OUT1 OUT2
0(0,0) 0 0
0(0,1) 0 0
0,(1,0) 0 0
0,(1,1) er er
1(0,0) 1 0
1(0,1) 1 0
1,(1,0) 0 1
1,(1,1) er er

 


5.OSを実行できるCPU

 

お待たせしました。

こちらがOSを実行できるCPUです。

NandGameのスクリーンショット

統合したCPU

なぜOSが実行できるのかというと、割り込み処理ができるためです。

(あ、出力にOS実行側のIを送信するのとそれぞれのiを送信するの忘れた)

 

今回はEEPROMを使用していますがROMだと書き込み上限があるので上の方にあるCPUのEEPROMはただのメモリだと思ってください。

 

あと、簡略化のために下の方にあるCPUのIに送信するためのアドレス「A」をbitごとに分けていますが本来は最大65,536本の線にできます。

 

ダブルクロックって書いてあるのはクロック分割です。この時はまだ間違いに気づいてませんでした。

 

で、割り込み処理のやり方ですが、OS側のCPUでIからメインメモリのデータを取得し、そのデータをもう一つのCPUの命令メモリに書き込みます。

 

クロックモードを制御するには、Aの0bit目とIの0bit目を1で送信すれば分割モードになります。

Aの0bit目を1で、Iの0bit目を0で送信すればOSモードになります。

アプリケーションの書き込みの時はOSモードにしましょう。

 

Aの1bit目と2bit目はそれぞれプログラムの書き込み、アドレスの変更となっています。

プログラムや変更先のプログラムメモリのアドレスはそれぞれIから出ています。

 

今中央のAND2つがありますがこれを3ANDに変えてクロックにも接続でもいいかもしれません。

 

忘れてる人向けに説明すると出力の「I」はDのデータです。

逆に入力の「I」もDにマウントされているのでDに入ります。

 

これで、OS側からアプリケーションを実行したり、強制終了させたり、接続の線を増やせばキー入力を行いながら書き込み処理なんかもできますね。

なんせこのCPU処理するためのコードが長くて大変なんですから...

 

以上になります。

続きは多分実際にCPUを作ると思うので時間がかかると思いますが書きます。

自作CPUを作る3 ~NandGameで設計をする2~

kouemuです。

 

回路を直せたので前回の続きを書きます!

 


目次

  1. 演算装置1
  2. 演算装置2
  3. 条件分岐
  4. 統合演算装置
  5. 命令装置
  6. CPU

 

1.演算装置1

 

NandGameのスクリーンショット

演算装置1

これは入力が命令の2bit目、1bit目、0bit目とデータ1とデータ2になっています。

 

もし命令がx000ならd1をビットシフトして0bit目を0にします。

もし命令がx001ならd1をビットシフトして0bit目を1にします。

※今気付いたけどここの判定ってxxx0かxxx1でよくない?

 

出力はもしx110ならd2を、そうでないならd1をビットシフトした値を出力します。

※後々判定するのでここの判定もxx1xでいいですね。

 

えーと...

画像の通りやってもいいし、入力の「3」を無くしてもいいですね。(直しとこう)

 


2.演算装置2

 

NandGameのスクリーンショット

演算装置2

これは入力が命令の2bit目、1bit目とデータ1とデータ2になっています。

 

もし命令がx10xならd1とd2をNANDしたものを出力します。

でなければd1を出力します。

 

...あれ?

なんか演算装置1と同じ動作してるやつがありますね?

多分どっかで使うのでしょう。

そうだよね?過去の自分??

 

でも演算装置1のやつを消せば回路がかなり小さくなりそう...

できた方は教えてください!(他力本願)

 


3.条件分岐

 

NandGameのスクリーンショット

条件分岐

これはかなり単純な装置ですね。

 

d1が0なら1をjに出力し、0でなければ0をjに出力します。

見やすさや考えやすさを重視した結果、d2をそのままadに出力することにしました。

これはジャンプする先のアドレスですね。

 


4.総合演算装置

 

NandGameのスクリーンショット

総合演算装置

これは、演算装置1・演算装置2・ジャンプを統合したものです。

命令


によって出力する装置を変更しています。

 

jは命令がジャンプ命令でis zeroに成功した場合1を返します。

これは条件分岐に組み込めばより見やすくなったかも...

 

どうしてこういうときに限って「あ、やっぱこうい

う回路の方が見やすい」とか「こっちの回路でやれば少ない回路で済む」とか思いつくんだろう...

 


5.命令装置

 

NandGameのスクリーンショット

命令装置

命令の種類によってm,r1,r0をd1,d2に割り当て、出力先も定義しています。

RAMの出力先アドレスは3bit目で判定しています。

特にそれ以外はやっていません。

 


 

6.CPU

NandGameのスクリーンショット

CPU

入力は右から、

・ROMの移動先アドレス(通常時は0にしておく)
※これはすぐに改良できます。ただ、バグが怖くて直せてないだけです。
・クロック信号
・ROMのアドレスを強制的に移動
・命令をプログラム
・4bitでプログラムする命令(アドレス移動するときは0にしておく)

です。

 

出力は自由にマウントしてください。

自分は見たいところすべてをマウントしてます。

 

2.5で話したf**k_3は外部のデバイスと通信をするため、その線を作ってもいいかもしれませんね。

 

ここで、はてなブログの仕様に気づきました。

シフト+エンターで通常の改行ができるんですね。

今までは段落改行しかできなかったので(html編集すればできるけどめんどくさい)今後は活用します。

 

 

はてなブログの仕様がわかったところで以上になります。

なにかミスがあった場合はご指摘ください。

その時に一緒に回路の最適化もします。

続きはまた後日書きます。

自作CPUを作る2.5 ~もう少し効率的なアーキテクチャ思いついた~

kouemuです。

 

こんかいは今まで作ってたCPUのf**kをもう少し効率的にしたf**k_3というものを思いついたので閑話としてやっていきます。

 

今回からは前回までのものをわかりやすくするためにf**k_4、今回のものをf**k_3と呼ぶことにします。

 


目次

  1. アーキテクチャの概要
  2. 命令セットとアセンブル言語
  3. コードの例

 

1.アーキテクチャの概要

 

f**k_3はf**k_4と似たような構成をしています。

できることは相変わらずNANDのみで、レジスタも2つです。

 

変わったことは入出力を限定的にしてより少ない命令セットでも同じようなことができるようにしました。

 

f**k_3は名前からわかる通り、3bitCPUです。

なので、f**k_4は16個の命令があるのに対してf**k_3はその半分の8つです。

 

マジでクソみたいなことになりそうでワクワクしますね(^^)♪

 


2.命令セットとアセンブル言語

 

ってことで早速表で見ていきましょう。

 

バイナリ アセンブリ 命令説明
000 A<0 Aをビットシフトして0ビット目を0にする
001 A<1 Aをビットシフトして0ビット目を1にする
010 A~D
(またはD~A)
AとDの値をこうかんする
011 M~D
(またはD~M)
RAMとDの値を交換する
100 D#M Dの値をDとRAMでNANDしたものにする
101 I=D Dの値をAのアドレスの接続デバイスに送信する
110 D=I Dの値をAのアドレスの接続デバイスから受信する
111 D:J Dが0ならAのアドレスの場所にジャンプする

AはレジスタAのことを指し、DはレジスタDを指し、MはRAMのことを指します。

RAMのアドレスはAの値を使用します。

Iは接続されているモニターやキーボードなどのIOデバイスを指します。

 

よくわかんない人はこちらへどうぞ!

 


3.コードの例

 

今回もすごいことになりましたね~

 

ってことでいろいろな機能を再現していきます!

以下のアセンブリ言語上記をご参照ください

順番は見にくいと思いますが上から参照できるようにしてあります。

 

/NOT M

A<1(x16)  
D~A  
A<0(x16) NOTしたいRAMアドレスを指定してください
D#M DにNOTを実行した値が入ります

 

RAMからDに上書きコピー(/D=M)

/NOT M コピーしたい値のあるRAMをNOTしてDに入れます
A<0(x16) 空いているRAMのアドレスを指定してください#1
D~M  
/NOT M #1>と同じアドレスのRAMをNOTしてDに入れます

 

DからRAMに上書きコピー(/M=D)

A<0(x16) コピー先のRAMアドレスを指定してください#1
D~M  
/D=M #1と同じアドレスを/D=Mします

 

D AND M

A<0(x16) ANDしたいRAMアドレスを指定してください
D#M  
A<0(x16) 空いているRAMアドレスを指定してください#1
D~M  
/NOT M #1と同じアドレスのRAMをNOTします

 

D OR M

A<0(x16) 空いているRAMアドレスを指定してください#1
D~M  
NOT M #1と同じアドレスのRAMをNOTします
A<0(x16) #1と同じRAMアドレスを指定してください
D~M  
/NOT M ORしたいアドレスのRAMをNOTします
A<0(x16) #1と同じRAMアドレスを指定してください
D#M DにORしたデータが格納されます

 

D XOR M

あーめんどくせぇ

M OR Dを空いてるRAMに保存#1
M#Dを実行#2
#1 AND #2を実行

 

D+M

何度も似たようなコード書いてるからマジでめんどくさい()

Dを空いているRAMに保存#1
MをあいているRAMに保存#2
#1 XOR #2をRAMに空いている保存#3(CP)
#1 AND #2を0でビットシフトしてRAMに空いている保存#4
#3 XOR #4をRAMに空いている保存#1
#3 AND #4を0でビットシフトしてRAMに空いている保存#2
もし#2が0なら#5にジャンプする
(CP)にジャンプする
D~M(#2)を実行する#5

 

 

以上になります。

閑話休題

続きはすぐ書きます()

自作CPUを作る2 ~NandGameで設計をする1~

kouemuです。

 

前回の続きです。

今回はNandGameというサイトを使用して実際のCPUをシミュレーションします。

長くなるので記事を2つに分けます。

頑張ってついてきてくださいね?

 


目次

  1. NandGameについて
  2. 設計を便利にするやつを作る
  3. CPUを作るためのパーツを作る

 

1.NandGameについて

 

NandGameとはリレーというものをつかって最終的にはCPUを作れるやつです。

自分の好きな回路を作れたり、指示にあった回路を作ってhackアーキテクチャCPUを作ったりできます。

NandGameでリレーを使ってNandを作る画像

NandGameでリレーを使ってNandを作る画像

 

ここで問題が発生しました。

以前に作ったf**kアーキテクチャCPUの回路が壊れていました。

なので今回は説明だけにして画像は次回に載せます。

(ちょくちょくあるんだよなぁこういうこと)

 

そういうのが嫌な人はSteamにこんなのがありますよ!

store.steampowered.com

 

こっちは金がかかります。

私はおとなしくNandGameやりますよ()

 

NandGameで設計するときはまず、ステージを解いてCPUを作るところまでやってからにしましょう。

あと、スマホでやると操作がほぼできないしバグるときあるからおすすめしません。

 

ちなみにプログラミングも学べます。

 


2.設計を便利にするやつを作る

 

ステージを解いてCPUが完成した人は次にカスタムコンポーネントを見てみましょう。

Create new componentってボタンだったっけな...

とりあえず目の前にあるボタンを押しましょう。

 

ここでどのような機能を追加するかは自由ですが、私は3つの線でANDを行うものとかANDを2つ搭載したやつとか6つの線でORしたりするやつを作りました。

 

ここは自分が「必要だ!」と思うものでいいので作っておくと便利です。

 


3.CPUを作るためのパーツを作る

 

ステージを解いてきた人はわかると思いますが、手順はそれと同じようになります。

演算装置を2種類作ってそれを統合してALUを作ってジャンプ用の条件分岐を作って命令装置を作ります。

今回作るものはデータを直接代入できないので制御装置を作る必要はありません。

詳しくは次回にやるんで許してください!

 

それと、ROMやメモリについてです。

ROMは今回、EEPROMを作成します。

そっちは壊れてないので写真をお見せします...

EEPROMの回路

EEPROMの回路

入力の左からプログラムするデータ(または任意ジャンプのアドレス)、オンにすることでプログラムできるやつ、オンにすることで任意ジャンプを実行、プログラム内でジャンプを実行するときのアドレス、オンにすることでプログラム内でジャンプを実行、クロックです。(最初のqは指に一番近かったキーがQだったからなので意味はありません)

bがオフになった時qの値が保存され、アドレスがインクリメントされます。clがオフになった時アドレスがインクリメントされます。

 

次にメモリについてです。

ステージでは統合していましたが都合が悪いのですべて個別に扱います。

写真無くてごめんねー...

 

 

以上になります。

続きは回路が直せたら書きます。

自作CPUを作る1 ~アーキテクチャを考える~

初めまして、kouemuと申します。

 

いきなりですがCPUを自作したいです。

今までに様々なCPUが作られてきました。例えば学習向けのhackや有名なintel,AMDなど...

そんな感じのものを自分でも作ってみようと思います。

そこでまず初めに「どの命令をすればどのような動作をするか」というのを考えます。

つまり、CPUアーキテクチャを考えようってことです。CPUアーキテクチャについては他の人とかが説明してると思うのでここでは詳しい説明を省きます。

 


目次

  1. CPUの概要
  2. 命令セット
  3. ロジックゲートについて
  4. アセンブリコード

 

1.CPUの概要

 

今回自作するCPUはhackという学習用CPUからインスピレーションを受けて作ったため「f**k」という名前にします。

名前の由来は命令がめんどくさいからです。

 

以下仕様です。

 

 

どうでしょうか?

これだけを見てもわかりにくいと思います。

なので次は命令の一覧を見ていきましょう。

 


2.命令セット

 

命令の数が8個となっていますが、実際には保存先のレジスタを選択するために1ビット使っているため実質16個です。

 

以下一覧です。

 

バイナリコード 命令の説明
x000 指定したレジスタをシフトして0ビット目を0にする
x001 指定したレジスタをシフトして0ビット目を1にする
x010 指定したレジスタの値をRAMの<指定していないレジスタの値>番目の値にする
x011 RAMの<指定していないレジスタの値>番目の値を指定したレジスタの値にする
x100 指定したレジスタの値を2つのレジスタの値同士でNANDしたものにする
x101 指定したレジスタの値を指定したレジスタの値とRAMの<指定していないレジスタの値>番目の値でNANDしたものにする
x110 指定したレジスタの値を指定していないレジスタの値にする
x111 指定したレジスタの値が0なら指定していないレジスタの値の命令にジャンプする

※バイナリコードの「x」はレジスタを指定するためのものです。

 

気になることがいくつかある人は続きを読みましょう!

これで「なるほど~」と思った人はこちらへどうぞ!

 


3.ロジックゲートについて

 

はい。

ここにいる人はおそらく「こんな命令セットでCPUが成り立つのか?」と疑問を持った人でしょう。

しかし、NANDゲートは万能ゲートと言われているんです。

なのでCPUは...NANDだけでつくれます!!!

 

つまりNANDさえあれば...他のロジックゲートは必要ないんです!!!

 

はい。

これがCPUの名前の由来でもあります。

ほんっっっっっっっっっっっっっっっとに長い命令を意味が判らなくなるまで与えなければいけません。

ね?クソみたいなCPUアーキテクチャでしょ?

 

以下に他のロジックゲートの再現方法を載せときます。

 

~NOT~

  1. データAとデータAをNANDする

~AND~

  1. データAとデータBをNANDする
  2. 1と1をNANDする

~OR~

  1. データAとデータAをNANDする
  2. データBとデータBをNANDする
  3. 1と2をNANDする

~XOR~

  1. データAとデータBをNANDする
  2. データAとデータAをNANDする
  3. データBとデータBをNANDする
  4. 2と3をNANDする
  5. 1と4をNANDする
  6. 5と5をNANDする

 


4.アセンブリコード

 

アセンブリコードがわからない人は無視で大丈夫です。

※簡単に言うと命令を文章に翻訳したやつだよ~(小声)

 

命令セットの一覧に追加しておきます

 

バイナリコード アセンブリコード 命令の説明
x000 (r)<0 レジスタの0ビット目を0にする
x001 (r)<1 レジスタの0ビット目を1にする
x010 (r)=M レジスタの値をRAMの値にする
x011 M=(r) RAMの値をレジスタの値にする
x100 (r)#(nr) レジスタ同士でNANDする
x101 (r)#M レジスタとRAMでNANDする
x110 (r)=(nr) レジスタの値をコピーしてくる
x111 (r):J 条件によってジャンプする

※バイナリコードの「x」はレジスタを指定するためのものです。
※(r)はAかBが入ります。選択するレジスタによって変わります。
※(nr)もAかBが入りますが(r)とは逆のものが入ります。
説明は一部省略しています

 

以上になります。

続きはまた書きます。