
パソコンを回路レベルで自作する (Intel x86 IA-32)
-
kaitou_ryaku
- 59255
- 219
- 323
- 292
~重要イベント一覧 (2019/06/22から)~
06/22 作成開始
06/29 32bit加算だけ実行する状態機械が完成
07/17 UARTの送信機を作る
07/18 8bit加算ができるようになる
07/19 ModRM, SIB周りのアドレシングを作り込む
07/20 加算命令がIntel x86の仕様を完全に再現
07/25 加算以外の命令を、一気に48個作る
08/13 Hello Worldが動いた (writeシステムコールの作成)
08/21 自作CPU上で自作OSが動いた
08/27 自作CPU上の自作OSにシェルを実装
09/21 自作CPU上の自作OS上でテトリスが動いた
2019/06/22 作成開始

パソコンを回路レベルで自作している。この土日で完成させたいけど、時間が厳しい。来週中に終われば御の字だな pic.twitter.com/aYDE1V7w1w
2019-06-22 18:19:51

FPGA詳しいマンが見れば「スイッチ8個をキーボードと称するのはどうなんだ?」とか「いやLED8個をディスプレイと呼ぶのはアカンやろ」とか総スカン喰らうこと必至だが、細かいことは気にすんな
2019-06-22 18:24:09
ハードウェア記述言語をやる際には、あらかじめ紙にブロック図を描いておくのが効率最強だと思う。もし「ノート出すのめんどいな。まぁ俺様の頭脳をもってすれば紙など不要よ」と思っていきなりコーディングし始めると、必ずどこかで配線の向きをミスって時間を溶かす。あと自分の絵が斜めすぎてやばい pic.twitter.com/ZNBKK5DJ4U
2019-06-23 00:24:07
2019/06/25 x86が可変長命令なので困る。僕が困るということは、Intelのおじさんも困ってるはずで、パイプラインの処理とかどうしてるのか心配になった。ツイッターの優秀な諸氏のおかげで疑問が解決した

Intelのx86 CPUのパイプライン処理の仕組みが謎すぎる。命令長がマジでバラバラだし、命令フェッチ→デコードまで済ませた後でないと次の命令の開始アドレスが分からないと思う。しかしあの命令セットでは、REP・ModRM・SBをデコードするのにかなり時間を取られる気がするし、パイプライン化不可能では
2019-06-25 22:30:40
今作ってるこれをパイプライン化しようと思って、5分ぐらい考えて、そもそもパイプライン化は不可能だと理解してしまった。浮動小数点周りの重い計算はパイプラインが効きそうだけど、他の命令をうまくやるのは無理だ (しかしIntelの中の人は気合と根性と努力で達成している) twitter.com/kaitou_ryaku/s…
2019-06-25 22:36:26
@kaitou_ryaku Skylakeだと16Byte/cycleでキューに乗せてPreDecodeと5-Way Decodeの2段構えでデコードしているようです en.wikichip.org/wiki/intel/mic…
2019-06-25 23:20:06
@kaitou_ryaku PreDecodeの中身がたぶんこのILDかと isus.jp/wp-content/upl… > 2.6.2 フロントエンドの概要 > 1 サイクルあたり最大 16 バイトのアライメントされた命令バイトを、命令キャッシュから命令長デコーダー (ILD) にフェッチします。
2019-06-25 23:56:50
@idxx 情報ありがとうございます!!この図が本質的ですね。命令の長さだけ、先に高速で特定してるのですね。 pic.twitter.com/uWf1Qa80ai
2019-06-26 21:45:13

この疑問が解決しました。新しめのx86-CPUでは、命令フェッチした直後に「命令長デコーダー」を動かして、命令長だけ高速で特定した後に、じっくりと命令の内容をデコードするっぽいです。割と安直な方法だった。 @idxx さん情報ありがとうございました twitter.com/kaitou_ryaku/s…
2019-06-26 21:51:582019/06/29 とりあえずDWORD(32bit)の加算命令
「ADD r/m ← reg」
のデコード・実行系を完成させる。CPUに命が宿った感。とはいえModRMやSIB周りのアドレシングは杜撰な設計で、BYTE (8bit)命令にも未対応。

などと先週末につぶやいたわけですが、今週ぼちぼちコードを書いてたので、「命令取得→デコード→メモリ読込→実効→メモリ書込→命令取得...」を繰り返すステートマシンは完成しました。とりあえずx86の0x01 (add reg/mem ← reg)の命令だけ実装した。ここまで来れば、あとは命令を増やすだけなのだ twitter.com/kaitou_ryaku/s…
2019-06-29 06:39:31
これまで自作したCPUを数えると、今回で10作目らしい。だいぶ作るコツを掴んだ気がする。何より重要なのは、命令フェッチからライトバックまで一周するステートマシンをさっさと完成させることだ。単純な命令1個のCPUを完動させる。あと、設計段階で構造体とインターフェイスの仕様はしっかり練るべき pic.twitter.com/wj5EINxRMY
2019-06-29 06:47:49

x86(IA-32)もどき自作CPUのオペコードの実装状況。セグメントレジスタは全て無視。Prefixも全て無視。PUSHAのようなメモリ書き込みが大量発生する命令もサポートしない。簡単にできるところだけやる twitter.com/kaitou_ryaku/s… pic.twitter.com/FOL4Z61dgI
2019-06-30 18:33:32
↑大量の命令が実装済みに見えるけど、実際は命令長をデコードしてるだけで、その先の処理は全くの未完成
2019/07/01 ここから5日ほど、テストベンチの設計をあれこれ考えていた。結局
「ROMの命令列を無理やり上書き→実行→結果を比較」
という比較テストを並列で動かしまくることにした。要するに結合テストだけ作る。この方式は動作が重いけど、CPU内部のステージ分割方式が変わってもテストベンチに変更が生じない。ステージ毎のテストは、一通りCPUが完成してからデバッグ目的で作ることにした(つまり先延ばしである)。

まだテストベンチを書いてないので、大量の細々したバグが潜んでいるはず。これを一挙に改善する秘策がある。とりあえず命令長だけassertするテストベンチを作るのだ。PCに眠ってる適当な32bit実行ファイルを逆アセンブルして、このCPUに食わせて、命令長が正しく解析できるか全自動でテストするつもり
2019-06-30 18:38:09
例えばCPUを自作する場合は * ALU内部moduleのUnitTest * 全体の結合テスト という2種類のテストをやりたくなる。前者はfork joinで済む。後者が少しトリッキーになる。例えば時刻0でのROMとレジスタを初期設定し、CPUを走らせて、時刻10でassert検証したい。これを何種類も並列実行したいとする(続く)
2019-07-06 16:43:35
今作ってるx86(IA-32)のコンピュータ、基本的な部分は全て完成してて、後は実行可能な命令セットをひたすら増やすだけの段階に到達した。テストベンチの書き方の良し悪しで開発効率がぜんぜん違う。ステートマシン部分は作りながら仕様がどんどん変わるけど、ALUはテスト駆動開発でやっていくべきかも twitter.com/kaitou_ryaku/s…
2019-07-06 22:02:49↑これはx86のデコーダーを作る際にしみじみ思う。もっと簡単な(MIPS等の)命令セットであれば、デコーダーは簡素だし、あまり「言語処理系」を作ってる気分にならないかも

根本的なところがコテコテのアナログ人間なので、x86のCPUを自作するときは家の壁に命令セット表を貼り、C言語コンパイラを自作するときは壁にBNFグラフを貼る。壁ポスターはキモいしダサいけど、なかなか馬鹿にできないぞ。作業効率が格段に上がるし、疲れた時にボーッと眺めることで色々理解が深まる pic.twitter.com/znN3NTFeJQ
2019-07-07 01:59:15
