巣鴨でトゲ抜き
巣鴨というと「とげぬき地蔵」を思い浮かべる。 そして、なぜか毒蝮三太夫も一緒に頭に浮かぶ。 トゲは漢字で「刺」とか「棘」とか書くらしい。 今まで書いたこともないし、 いきなり出てきたら読みもあやふやだ。
唐突ではあるが、今月のインタフェースをちょっとみてみよう。
特集は「ゼロから作るOS」とあり、まぁこちらの専門分野だ。
Interface 2023年7月号
「IEEE で標準規格になった。」2018 年と書いてある。 知らなかった。で、どういう標準規格のだろうか? どこを参照したらいいのだろう?
記事とIEEEの関連性が(現時点では)不明だが(読みながら書いてるんでね)、 その先を進めよう。
Windows の NT Kernel について記述がある。あ、竹岡さんのコラムだった。 RISC-V には PMP というのがあるのか。 勉強になる。
第1章は RTOS の話だ。そういえば 1980 年代にインタフェースの記事を 読んで RTOS を勉強したのを思い出した。当時はタスクなんて言葉を使ってた。
いまもタスクなのか。
第2章で IEEE に準拠するという話が出てくる。 IEEE 2050-2018 は日本の TRON をベースにしているらしい。
あれ〜 tk_cre_tsk? まじかよ。T-Kernel じゃん。
余談だけど、T-Kernel の提唱者はどうも PC-9801 のモニターを 雛形にしてものを作ろうとしているようだ。
そして、ARM のレジスタの使い方(コンベンション)を無視して 作られている(サンプル実装?)
シーラカンスのような仕様と実装はやめてほしい。
イベント・フラグとセマフォかよ。 セマフォはともかく、なんでイベント・フラグなんていう 退行した API 使わなきゃならんのよ。
POSIX には(pthreadには)ちゃんとした cond_wait に代表される 条件変数での制御が規定されている!!!
これもう30年前の話で、決着ついてるはずなのに、、、
この感じだと IEEE はロビー活動の結果であって、 技術的に素晴らしいから採用されたわけじゃなさそうだぞ (現時点の感想です)。
RTOS でバグの少ない見通しのよいプログラムを書くには
この2つが大事だ。
とりわけ、初期化処理に代表される 「順序性のあるものの」 切り分け、切り出しは重要。
典型的な初期化処理では順序性がある。例えば、
1 → 2 → 3 → 4 → 5
これをイベント・フラグとかで実装しちゃうと case 文使ったりして混乱してしまう。 ソースが汚くなる。
本来、順序性があって、一本道なのを わざわざ case 文で分断してしまう。
もちろん、case 文を上から実行していくんだよという 風に書くことも出来る。
kaffe のソースは(昔読んだんだけど)、そうなっていて 感心した。そういう書き方も出来るんだなぁと。
技量があれば case 文を使ってもきれいに書くことは出来る。
しかし、複数の人が関わり、メンテナンスする RTOS の アプリに case 文を入れると、 日本のソフトウェア業界の悪しき文化、 古いソースのコメント化と謎の担当者名+日付のコメントと あいまってどんどん汚くなってくる。
最初から cond_wait を使いましょう。
cond_wait は semaphore と mutex の組み合わせでかけるので、 RTOS で最初に実装する関数は cond_wait だ。
これ、たぶん30年くらい前からの(私の)定番。
iTRON 系の OS が来たら、semaphore と mutex で cond_wait つくって アプリケーションではフラグとかメッセージとか使わない。
cond_wait 使えば普通のプログラムになるんだよ!!
次に重要なのが「優先度の高い処理を明確にすること」。
RTOS いれても、全部同じ優先度にしたら、ポーリングと変わらないからね。
これ、理解してもらえなかったお客もいる。トホホ。
RTOS でアプリを組むから リアルタイムなアプリケーションになる のではなく、、、
RTOS 上で正しく優先順位をつけたタスクに分割するように 設計して記述するから、 リアルタイムなアプリケーションになるのよ。
よく見る間違いに、フラグやメッセージで管理してタスク分けして 制御順があやふやになってくると delay 入れたりして調整。 みたいなプログラム。
当たり前だけど、だめだから。
結論
mutex や semaphore は単体だと すれ違いも起こしやすく 使いづらい。
そのために POSIX では cond_wait を規定していて 使いやすいインタフェースを用意している。
順序制御は cond_wait 一択で OK!! イベント・フラグなんて使うな!!
(メッセージボックスは私も使うときがある。 ネットワーク系と相性がいいから)
30年前のバグを誘発しやすい API !!
その先読んでないから(読む気がなくなった)。 ちゃんとしたリカバリーがされているのかもしれないが。
現時点では(先読んでないからね)、だめすぎて相当がっかり。
相当過激な意見だから、他の専門家(TさんとかIさんとか)の意見ももらって チェックしたい。 (このページを勝手に参照するのは不可。ちゃんと口頭で説明したい)
プログラミング学園も読んでおこう。 宇宙の数式 いい記事な気がする(深く読んでない。読むだけの知識がない)。 最初から読みたいから pdf でまとめほしいよ。
Forth と RISC-V
本当はこっちをメインで書きたかったんだけど もう力尽き気味だよ。
CPU をつくりたいならまず Forth を検討しましょう。
Verilog でも書けますし、 Synthesijer でも Polyphony でも書けます。
FPGA の初学者にはとくに HLS(High-level synthesis) で書くことをおすすめします。
私は以前、がんばってパタヘネをみながら VHDL で 独自CPUを 作ろうと思ったのですが、あっさり断念しました。 パイプラインとか複雑すぎ。
パタヘネとかみるとパイプライン化しないまでも こんな絵が出てくるよね。
高位合成で書けばパイプライン考えなくて済みます。
パイプラインを考えなくていいのか? それでいいのかという本質的な問題はある。
Polyphony で書けば Python で次のように書けます(抜粋です)。 簡単!!
if opcode <= 30:
if opcode == 0: # nop
pass
elif opcode == 1: # lit
ip += 1
stack.push(memory[ip])
elif opcode == 2: # dup
stack.push(stack.top)
elif opcode == 3: # drop
stack.pop()
elif opcode == 4: # swap
stack.swap()
elif opcode == 5: # push
address.push(stack.pop())
elif opcode == 6: # pop
stack.push(address.pop())
CPU が出来たら今度はソフトウェアです。
qiita に素晴らしい記事が上がっています。機械語手書きから言語処理系をブートストラップする
これみながらアプリの環境を作れば、コンパイラとかアセンブラとか必要ありません。
Forth をつくる!! 是非、みなさんもトライしてみましょう!!
いやいや Forth 今更作ってどうする。 という人は RISC-V でしょう。
これも Polyphony で Python 言語でかけちゃいますよ!!
if opcode == 0x63:
if funct3 == 0:
if self.get_reg_v(rs1) == self.get_reg_v(rs2):
self.pc += int32__31__7_30_25_11_8x2
elif funct3 == 1:
if self.get_reg_v(rs1) != self.get_reg_v(rs2):
self.pc += int32__31__7_30_25_11_8x2
elif funct3 == 4:
if self.get_reg_v(rs1) < self.get_reg_v(rs2):
self.pc += int32__31__7_30_25_11_8x2
elif funct3 == 5:
if self.get_reg_v(rs1) > self.get_reg_v(rs2):
self.pc += int32__31__7_30_25_11_8x2
elif funct3 == 6:
if cmp_32u(self.get_reg_v(rs1), self.get_reg_v(rs2)) == 1:
self.pc += int32__31__7_30_25_11_8x2
elif funct3 == 7:
if cmp_32u(self.get_reg_v(rs1), self.get_reg_v(rs2)) == -1:
self.pc += int32__31__7_30_25_11_8x2
else:
illegal_op = True
基本的な構造は Forth も RISC-V も同じです。 Python の if elif else のカタマリ。
その書き方どうなの?という気がしなくもないですが、 とにかく簡単に出来るからおすすめ。
ただし、スピードは出ません。Toy CPU です。
RISC-V を試すなら gowin の FPGA は候補の一つになると思います。
なんといっても安い!!
そして、RISC-V もついてくる。
CPU を作ったことにはならないかもしれませんが、 Gowin + RISC-V の環境で周辺機器を作ると CPU 周りの理解が深まりますね。
詳しくはこちら(CMでした。まぁCMしてもべつに収入にはなりませんが)2022年12月号 別冊付録2500円ボードで始めるFPGA開発
CPU に興味がある人だったら次の分野も興味ありそうですね。
であれば、ぜひ Lisp と Forth は押さえておきましょう。特に Lisp。
幾つかの大学で(多くが国公立)CPU実習なるものの講義があります。 私の記憶では東大が始めたと記憶してます。 iTRON の成功の一環ですね。 これがあるから今の日本に多くの優秀な技術者が育っている。
コンピュータ哲学
もうほとんどギブアップですが(書くの疲れてきた)、、、
「CPU演習」と似たような講義に関する資料は 1990 年代のはじめから あります。
この辺がその走りじゃないですかね? MIT の教科書だったらしい。 Turbo Pascal だからオワコンですが。 SICP もその一つかな。やさしいコンピュータ科学
この手の本は今やいっぱい出ていて、 最近でも日本の著者で OS と CPU 作る的な本が複数ある。
詳しく紹介したいところですが、 もう力尽きたのでこのへんで終了。