ブログの練習

ブログを書く練習です。
最近はレトロな計算機(電卓、マイコン、パソコンなど)
に関することを書き始めました。

Intel 4004 (その12) VTLインタプリタを作ってみる

2023-03-12 11:36:51 | マイコン(4004)

4004用のVTLインタプリタを書いてみました。当初はMITS_Altair_680_Very_Tiny_Language_VTL-2_Manual.PDFに載っている6800版のオリジナルのソースか、白石孝次氏による8080への移植版(「マイクロBASICインタプリタの製作」, 月刊ASCII, 1978年2月(エンサイクロペディアASCII vol.1収録))を参考にして移植ベースで作るつもりだったのですが、どちらもサブルーチンを多段に呼びまくりなコードで、PCのスタックが4段しかない(サブルーチンを3段までしか呼べない)4004では同じ構造のまま移植するのは無理そうだったので、多少参考にする程度でゼロから書くことにしました。
とはいえ、数式を評価するルーチンが再帰的な呼出しになり、データRAMにスタック領域を用意してそこにレジスタやPCを積めるような仕組みを作ることになったので、最終的には多段呼び出しも可能になったのですが。
とりあえず動けばいいと思って書いたもので、かなり汚いプログラムなのですが、せっかくなのでGitHubで公開しました。内部レジスタ(P0~P7)の使い方など、直した方がいい点が多々ありますが、下手にリファクタリングして動かなくなるのもいやなのでこれ以上手を加えるのはやめます。これを直すくらいなら、もう一度ゼロから書き直す方が良さそう。

GitHub - ryomuk/VTL4004: VTL Interpreter for 4004 Evaluation Board

GitHub - ryomuk/VTL4004: VTL Interpreter for 4004 Evaluation Board

VTL Interpreter for 4004 Evaluation Board. Contribute to ryomuk/VTL4004 development by creating an account on GitHub.

GitHub

 


プログラムを書くにあたり、いくつか準備をしました。まず1つ目は、前のブログ(Intel 4004 (その11) メモリ周りを改築する)に書いたメモリの拡張に関することです。物理メモリは00H~0FDHの254byte x 16バンクという、256byteごとに2byteの読み出しルーチンが書かれていて使いにくい空間なので、12bitのアドレスBA98.7654.3210を、BANK=3210、ADD=7654.BA98に変換してアクセスするルーチンを用意して、000H~0FDFHの論理空間に見せるようにしました。vtl.asmの LD_P1_PM12REG16P0, LD_PM12REG16P0_P1 がそのルーチンです。メモリ1byte読み出すのに30命令近く、実行時間で約300μ秒かかるということになってしまいましたが、これでメモリがかなり使い易くなりました。このメモリにはVTLのプログラムテキストを格納します。
プログラム領域のメモリはアクセスが遅いので、演算用の変数はデータレジスタに格納します。4002は4bit x 16キャラクターのレジスタを4つ(計32 byte)持っており、RAM0~3で計128 byteあります。
RAM0とRAM1にA~Zとシステム変数、RAM2にシステム変数や作業用変数、RAM3をスタック領域として使用することにしました。
当初のハードウェアでは入手性やコストの観点から4002-1(1個$8)を4つ使って、CMRAM0とCMRAM1に2個づつ継げていたのですが、4002-1を2つと4002-2(1個$20)を2つを同じライン(CMRAM0)に接続する方がCMRAMのラインを0に固定でき、アクセス毎に発生するDCL命令を省略できるのでそのようにしました。
eBayで注文したところ、最初4002-2ではなく4002-1が送られてきたのですが、店に連絡したらすぐに4002-2を再送してくれて返品も不要という対応をしてもらえて事なきを得ました。ICもちゃんとした新品で動作も良好。HIFIICというストアは信頼できそうです。
RAM3のスタック領域に内部レジスタをPUSH/POPするためルーチンと、変数をPUSH/POPするルーチンを用意しました。8bit CPUでは1命令で実行できるPUSH/POPですが、これにも30命令以上かかります。しかもレジスタ毎に別のルーチンをマクロで展開して作ったため、メモリもかなり食ってしまいました。このあたりは改善の余地がありそうです。
スタックを利用して返り先をスタックに積むようにすれば3段しか使えないJMSの代わりに、JUN命令でサブルーチンが実現できます。返るときにはvtl.asmのRETURN_P2を呼びます。12bitのアドレスに間接ジャンプする命令は無いので、8bitのラベルを使って間接ジャンプで飛んだ先で12bitにジャンプするという2段ジャンプのリターンになっています。
以上が主な準備です。

実装したインタプリタの仕様の表をここに書こうと思ったのですが、このブログで表を書く方法がわからなかったのでやめました。GitHubのREADME.mdをご覧下さい。表に従って順に解説していきます。
プログラムサイズはモニターと合わせて約3.5KBになりました。8bit CPU版に比べると3~4倍でしょうか。8bitの値を操作するのにも複数の命令が必要なので仕方ありません。
オリジナルのVTLの変数の値域は0~65535ですが、マンデルブロ集合を計算したいので2の補数で-32768~32767とすることにしました。加算と減算ルーチンは変更無しで使えます。除算は正負を判断して絶対値の除算を行い符号を補正するという計算になります。乗算も除算と同様のことをやる必要があるかと思ったのですが、下位16bitだけ使うのであれば何もしなくていいようで、正数の乗算ルーチンのまま変更無しで動きました。これに伴い、行番号が1~32766となっています。
16進の数値が扱える方が何かとうれしいので、0で始まる数値は16進数として扱えるようにしました。出力も??=で16進4桁、?$=で16進2桁で表示するようにしました。
通常のPRINT(?=e, ?=STR)、改行抑止(;)、入力(A=?)、文字入出力(A=$, $=e)、GOTO(#=)、GOSUB(!=)、LIST(0)等々はオリジナルのVTLと同じです。
オリジナルのVTLではIF文は無く、#=(A=B)*100のようにGOTO先の行番号を比較演算子の結果との乗算で代用するという手法が使われていたようなのですが、乗算は計算コストが大きいのでIF文(;=)を実装しました。;=0 の後は次の行にスキップするのでコメント文の代用に使えます。なのでコメント文の実装はサボりました。
演算子に優先順位は無く、左から右に評価しますが、括弧内を先に評価する機能はさすがに実装しました。上の方に書いたJUN命令とスタックを使ったサブルーチンコールで数式の値計算(EVAL_EXPRESSION_PMINDEX_REG16P1)と因子の値計算(GETFACTOR_PMINDEX_REG16P1)の再帰呼出しをしています。
行の編集機能(挿入、削除等)はサボりました。真面目に実装すると結構メモリを食いそうなので。最初から行番号昇順のプログラムが入力されることを前提にします。

あと、配列とPEEK、POKEあたりを実装したかったのですが、マンデルブロ集合の計算に使わないので後回しになっています。

こちらが動作の様子です。


約2週間ほどかかってどうにか動くものが完成し、目標にしていたマンデルブロ集合の計算が出来ました。時間は2時間54分13秒。今回は速度は頑張りどころではないので完走できたことで満足です。

プログラムはこんな感じ。基本的に以前にF8用に書いた整数BASIC用のプログラムと同じです。不等号">"がVTLでは">="の意味であるということらしいので、比較文の数値がちょっと違います。

10 F=50
20 Y=-12
30 X=-39
40 C=X*229/100
50 D=Y*416/100
60 A=C
70 B=D
80 I=0
90 Q=B/F S=B-(Q*F)
100 T=((A*A)-(B*B))/F+C
110 B=2*((A*Q)+(A*S/F))+D
120 A=T
130 P=A/F Q=B/F
140 ;=((P*P)+(Q*Q))>5 #=180
150 I=I+1 ;=I<16 #=90
160 ?=" ";
170 #=200
180 ;=I>10 I=I+7
190 $=48+I
200 ;=X<39 X=X+1 #=40
210 ?=""
220 ;=Y<12 Y=Y+1 #=30


消費電力はシステム全体(表示用VFDは除く)で270mA前後とそれほど多くありませんでした。

発熱も4002が50度ぐらいになっている程度、CPUはあまり発熱していませんね。


最後に、試しに手動でコンパイルして変数アクセスや演算ルーチンを直接叩くようにして実行した結果です。55分56秒。実行時間は約1/3ぐらいに短縮しました。1桁くらい速くなるかと思っていたのですが、思ったほどは速くなりませんでした。構文解析や制御よりも演算自体に時間がかかっているということですね。


コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« Intel 4004 (その11) メモリ... | トップ | Intel 4004 (その13) 8080エ... »
最新の画像もっと見る

コメントを投稿

マイコン(4004)」カテゴリの最新記事