SSブログ

HD6303で電大版TINY BASIC(3) [6801]

8ビットマイコン基板の時のHD6303基板は色々ミスがあってパターンカット&ジャンパー飛ばしでデバッグしていたのだが、結局新規に起こしなおした。たぶん最初の基板も動くとは思う。最終確認していないけど。
これはHD6301/6303の64pinシュリンクパッケージのXあるいはY用で、今手元にはこれだけ。
種類はもちろん、数的にももう少しあったと思う。

HD6301XY.jpg

左上からHD6303XP,HD63A03XP,HD63B01X0P,HD63X03X0P
右上からHD63701X0P,HD63B701X0P,HD6301Y0P,HD63C03YP
HD63B01X0Pはマスク品でたぶんなんらかのファームウェアが入っているはず。

その中からHD63C03Yを使って電大版Tiny BASICを動かしたいと思う。

SYC-6303Y_1.jpg

I/Oコネクタはまだ付けていない。
このボード、MREQではなくEをそのまま出しているのでメモリボード側でジャンパ切り替えて対応。

SYC-6303Y_2.jpg

ソースの変更点は
(1)ピン数増えているので内蔵I/Oも増えていて、その分ゼロページのI/Oレジスタ占有量も増えているので、またメモリのマッピングを多少変更する必要がある。
(2)増えた分のI/Oレジスタは継ぎ足しで既存の分の機能はほぼ変わらないので、SCI等のソース変更はなし。
(3)I/O追加に伴う割込増加分と、未定義命令トラップが追加されている分ベクタが増えているが使わなければこれも同じでOK。アドレス下位方向に追加なので、念のため新規割込もダミールーチンへJMP。
(4)XとYではI/Oも多少違うのだが、Yの方が上位互換とみなせるのでYの固有機能を使わなければ同じで構わない。もちろん、Xからの固有機能も使っていない。

USB-シリアル変換、クロック生成を行っているPICも変更。
(5)MC6801および40pinまでのHD6301はSCIを外部クロックで使用する場合、ボーレートの8倍入力だったが、HD6301X(Y)はなぜか16倍に変更されているので16倍クロック出力に変更。
(6)HD63C01を使うので3MHz動作のためにシステムクロックも12MHzに。
実際には12.6MHz程だからCPUクロックは3.15MHzで多少オーバークロック。

それら小変更で難なく動作。

前回と同じベンチマークプログラムを動かしてみた。

bench_result_20181113_1.jpg

タイムは824カウントだから約8.2秒。
前回は約0.8MHz動作で32.9秒だったので、ほぼクロック通り4倍動作となっている。
ちなみに6801向けに演算にDレジスタ使ったバージョンです。

モトローラ6800伝説

モトローラ6800伝説

  • 作者: 鈴木哲哉
  • 出版社/メーカー: ラトルズ
  • 発売日: 2017/12/16
  • メディア: 単行本(ソフトカバー)



モトローラ 6800伝説

モトローラ 6800伝説

  • 出版社/メーカー: ラトルズ
  • 発売日: 2018/02/23
  • メディア: Kindle版



nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

HD6303で電大版TINY BASIC(2) [6801]

HD6303で電大版Tiny BASICの続きです。
MC6801系にちょっとオプティマイズしてみます。

MC6800は8080に比べてきれいなアーキテクチャだと言われ、確かにそうだとは思うが、当時のモトローラは8bitマイコンなんてこの程度で充分と思ったのか、それとも当時の半導体技術ではこれが精一杯なのか、機能が絞り込まれていて使いにくい。
具体的には8bitCPUだからというわけだろうが、8bit単位でしか演算できない。これはまだ個人的には許容できるが、インデックスレジスタをスタックに操作できないというのは結構使いにくいところに感じる。
MC6801になってその辺が解消され、ACCAとACCBを連結して16bitのACCDとして扱えたり、インデックスレジスタXをスタックへPUSH/PULできるようになり、扱いやすさがぐんとあがり、その後6809につながっていく事になる。

そういうわけで電大版Tiny BASICをMC6801向けにカスタマイズしていく。
(1)16bit演算に変更
BASICの扱う数値データは16bitの整数なので、MC6800ではACCAとACCBを下位、上位としてそれぞれ演算しているのはACCDで可能な限りまとめて行うようにする。
(2)16bitデータ転送の変更
これも(1)と基本的に同じで、アキュムレータに対するロード/ストアも可能ならDレジスタとして一括で転送
(3)インデックスレジスタのスタック退避
これも一応変更を考えたが、単純に退避するだけの目的の場合退避先がゼロページの場合はPULで同ステータス数、PUSHで+1となってしまい、パフォーマンス的な効果が薄いのでそのままにする。

参考までに加算命令のダイレクトアドレッシングとインデックスアドレッシングのクロック数を記しておく。

DIRECTINDEX
ADDA(B)
3
4
ADDD
4
5

これだけみれば1クロックの差しかないが、16bit計算だと8bit計算を2回することになるので、ある程度のパフォーマンスアップを期待できるのでは?と思う。

さて、(1)(2)の変更で特に(1)に関して問題となることがあり、TinyBasicはACCAを下位バイト、ACCBを上位バイトとしているが、MC6801のDレジスタはACCAが上位バイト、ACCBが下位バイトと逆であること。下位バイトだけ、上位バイトだけというケースや、80系がそうであるようにアキュムレータというばAということで、とりあえずAで処理しそれをそのまま下位バイトにという処理もあり、とにかくDにしてしまえ!というわけにいかず、ソースのいたるところでACCAとACCBを入れ替えて行く必要がある。
さらに、一見Dレジスタは16bitのアキュムレータとしてACCA(B)と同様に扱えそうで、ローテート命令がないなど一部制約があり、そういう場合は処理はそのままだが上位下位の扱いが逆になっているので、それだけは入れ替えとなる。
ちなみに加算処理の場合だと、

ADDJSRPOP
INX
INX
ADD3ADDA1,X
ADCB0,X
STAXSTAA1,X
STAB0,X
E7RTS

これが

ADDJSRPOP
INX
INX
ADD3ADDD0,X
STAXSTD0,X
E7RTS

こうなる。
加減算は単純に置き換えるだけですむが、乗除算はそうはいかない。
以上を踏まえて変更していき、なんとかそれっぽく動作したので簡単なベンチマークをとってみた。

CPUHD6303
動作クロック0.8MHz


同じ基板、同じCPU、クロック発生用のPICも同じでROMだけ入れ替え。
前回書いたとおり、このシステムは内蔵タイマを使って10ms間隔で割込を掛け、TinyBASICの変数Tをカウントアップさせている。
ベンチマークソフトは最初にT=0で初期化しておき、主要処理終了後にTの値を表示させる単純なもの。
ベンチマーク用のBASICプログラムソースはこれです。

bench_src_20181111_1.jpg

単純な四則演算を繰り返すだけ。
10msが3301カウントなので、約33秒です。
MC6800版と移植したものの結果がこれです。

bench_result_20181111_1.jpg

MC6801向けにDレジスタを使用したバージョンの結果がこれです。

bench_result_20181111_2.jpg

3292カウントだから約32.9秒。
何回か繰り返し実行してだいたい同じで、その差約0.1秒。
若干速くなっているが、インタープリタはソースを読んで解析していくのがやはりメインなのか、処理中の演算処理の割合が低いのだろうな?という事でしょう。

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

HD6303で電大版TINY BASIC [6801]

引き続き68系。
最初に作った基板HD6301/6303ボード。
ワンチップモードでのみ動作確認までだったが、実はその後外部ROM/RAM実装でLILBUGモニタの動作確認までOK。
すっかり間が空いてどこまで書いたかも忘れている。
CPUはHD6303Rに。オーバークロックでも動作するのだが、供給クロックを3MHzに。つまり動作クロックは0.75MHz。
実際は3.2MHzほどでているので0.8MHz動作。
こんな感じです。

SYC-6801_HD6303R.jpg

このボードに前回MC6802ボードに搭載した電大版TINY BASICを入れる。
オリジナルソースをベースとせず、MC6802ボード用に変更したソースをベースにした。
元々MC6800系のBASICだから、MC6802ボードでは割込使用送受信関係ではまったとはいえ、それ以外は比較的簡単に移植できたがMC6801系は色々と変更部分がでてくる。
8bitの6800系はゼロページエリアが重要で、電大版Tiny BASICもワークエリアはゼロページが前提になっているが、

・ワンチップマイコンであるMC6801系はそのゼロページにペリフェラルI/Oのレジスタ群が存在する。
・せっかく搭載したLILBUGなのでそれベースにTINY BASICを動かすつもりだが、LILBUGはMIKBUGと比較して機能が豊富な分ワークエリアも多くとる。
・実は送受信関係のバッファ操作のためのワークもゼロページにとってしまっている。
・I/OレジスタとLILBUGのワークの除いて、BASIC用の変数A~Zのアドレス($82~52バイト)を固定して確保する必要がある。

I/Oレジスタ($0~固定)とLILBUG、独自ワークエリアとTINY BASICのワーク全てあわせて256バイトに収めること自体は可能だが、TINY BASICは特定のワーク変数からの相対位置をみていたりヘタに動かせない部分がある。
そういった制約の中で色々配置を換えて移植してみた。

ベースは前回のMC6802のものでゼロページ以外のメモリ配置はほぼ同じ。モニタがMIKBUGからLILBUGになったぐらい。
実はFORループ処理用のスタックが$0100になっており、つまりFORスタックはゼロページなのだが、これはMC6802ボードへの移植時にゼロページ外に出している。

今回はソースリストでのラベルBUFFER部分をゼロページ外に出すことにした。
これはキーボードから入力された文字を一時的にためていくところ。領域も比較的大きいので外に出す意味は大きい。
ただし、この部分が一番ワークの相対位置関係が決まってヘタに動かせない部分でもある。
このワーク部分のオリジナルソースを抜粋

ORG$1A
BUFEND RMB 2
BUFFERRMB 80
EXSTK EQU *
EXSP RMB 2
RMB52


ORGからBUFENDまでは色々ワーク変数があり、さらにBUFENDからBUFFERまでは別のワーク変数が4バイト存在するが省略。
ワークエリアが$1Aから始まっているのはA~Zの変数領域が$82からになるようにするため。

BUFENDにはBUFFERに入力された最後尾のアドレスが入る。
EXSPは計算等に使うスタック。変数のアドレスをEXSPが示す領域にプッシュ/ポップして計算処理をする。
実際はスタックに入れてプッシュ/ポップではなくインデクスレジスタに入れて、だが。
EXSPの初期値には自身のアドレスであるEXSTKが入る。
位置関係が固定されている最初のポイントがここで、スタックオーバーの判定にBUFENDと比較される。ようするにEXSPがバッファラスト(BUFEND)まできたらスタックオーバー。
その部分

LDXEXSP
DEX
DEX
CPX BUFEND
BEQ ERR180

これが下限チェックで上限チェックはこちら

LDXEXSP
CPX#EXSTK
BEQERR180


ちにみに最大入力判定をBUFFER+70としているので、計算スタックの最小は10バイトと想定している模様。
この部分を確保したスタック領域の先頭、末尾か?で行うように変更。

EXSPの次の52バイトが変数A~Zの領域で$0082~の固定領域となっている。
入力行解析時、それが変数なら1bit左シフトし(Aなら$41→$82)変数アドレスを設定しているが、実は上位アドレスとしてBUFENDの中の値を設定している。
その部分の抜粋

TSTVBSRSKB8
CMPA#$40
BEQARRAY
CMPA#'A
BCSNOTV
CMPA#'Z
BHINOTV
ASLA
LDABBUFEND
INX
RTS


アキュムレータAには文字コードが入っていて1bit左シフト下値が変数の下位アドレス。
アキュムレータBにBUFEND、つまりバッファ使用領域最後尾、n文字入力していたらアドレスBUFFER+nの上位を入れている。
これより変数領域はBUFFERと同じ上位アドレスで下位が$82からの52バイト、かつBUFFERの領域が256バイト境界をまたがないなら構わないことになる。
実際、「マイコンてづくり塾」のΛ-1の電大版TINY BASICは、BUFFERからまとめて$E400に配置している。
ただ本のソースリストは

F400 BUFFER RMB 80
EXSTK EQU*
F450 EXSP RMB2
F452 RMB 52

となっていて、
これはリストのタイプミスなのか、それとも本当にそうしてしまっているのか、変数領域は$F482からになっていないし、にもかかわらず変数のアドレス算出はアルファベットの文字コードをASLAとオリジナルのまま。もっとも、$F4xxの領域はそれら以外に使ってないので、プログラムの想定通りではないが問題なく動くだろうとは思う。

話が少しそれたが、変数領域はゼロページのままにしておくので、BUFENDの値を入れずに固定値0を設定するように変更(CLRB)。

大きな変更は以上。
一部ワークエリアをゼロページ外に移したので、相対ジャンプが範囲外になってしまう所等を修正。
結局、一番動かしにくいワーク領域を移動させてしまったが、以上の修正で動作OK。

修正ではないがMC6801のタイマも動かしていて、約10ms周期で割込を掛けているがついでに変数Tをカウントアップするようにしてみた。
何かのベンチマークテスト用。

あと、これはMC6802版からだがBASICだけでなくモニタも含めて、改行をLFに統一。
オリジナルは入力の改行判定はCR。改行出力はCR+LFを送信している。

MC6802ボード用に修正した時点からそうだが、シリアルの送受信キューはともに256バイトと余裕たっぷりにとっているし、スタック領域変更ついでに多めにとったし、限られたリソースでBASICを動かすというTINY BASICの趣旨には反しているけども、今だからできる贅沢かな?
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

MC6802CPUボード [6802]

またちょっと間が空いて、今回は元に戻って68系の話。
MC6802のCPUボードを起こしました。

SYC-6802_1.jpg

MC6802とACIA(MC6850)のボード。
例によってPICでシリアル-USB変換、CPUクロック、ボーレート供給、リセットを任せているが、これはZ80のものと全く同じもの。
CPU用のクロックは6MHz。MC6802は4分周されるので1.5MHz動作。シリアルボーレートは9600bpsで、クロック供給はACIA側で16分周するものとして9600×16=153.6K。
一応今までのものと同じように電源はCPUボードからも通信用USBと電源用のUSBと選択できるようにしたが、ベースのボードからスマフォ充電用のACアダプタで電源供給。
ベースボードにCPUボードとメモリボードをさして動かしている状態がこちら。

SYC-6802_2.jpg

メモリボードはZ80で使用したものと同じもの。ただしZ80と違って下位アドレスがRAM、上位アドレスがROM。
メモリボードのバス7番ピンは80系のMREQと68系のEを切り替えるようにしてたのだが、メモリマップドI/Oの68系では結局の所I/Oアドレスの時にメモリアクセスを禁止しなければいけないので、CPUボード側でMREQとIORQを生成するようにした。
回路図はこちら。

SYC-6802_3.jpg

動作確認用として68系定番モニタMIKBUGと電大版TinyBASICを用意。
この電大版TinyBASICを動作させるのに手間取ったのが間が空いた理由。

そのままでは動かないので修正を施す。

・MIKBUG修正点

(1)いわゆるコンソール入出力をACIAに変更。
MIKBUGはパラレルI/OであるPIA(MC6820/21)を使ってシリアル通信を行っているのを、ACIAでのシリアル通信変更。
ついでに送受信とも割込で行う事にする。

(2)コンソールは当時のテレタイプライターが前提になっているのでその部分を修正。
テレタイプライタの制御部分、最後に$FFを連続して送ったり、文字列終端がEOTだったりといった部分を削除。

(3)アドレス配置を変更
これは普通にこちらのメモリマップにあわせるだけ。

MKIBUGの動作はわりとすんなりOK。
リセット後にブートメッセージを表示させるようにしてみたら、最初の4~5文字が化けるのはご愛敬(笑)

・TinyBASIC修正点

次に電大版TinyBASIC。ネットにあったソースをベースにさせてもらった。
一応、昔「マイコン手づくり塾」という本に掲載されたソースを打ち込んだものもあるが、あれはメモリ配置も含めけっこう手が入っているのでオリジナルに近いものからの方がいいかな?という判断。

(!)MIKBUG前提部分の修正
MIKBUGも同時に移植しているのでそのままでいいはずだけれども、ACIAでしかも送受信割込を使った独自の入出力に変更したこともあり変更。

(2)テレタイプライタ制御部分の修正
これもMIKBUGを使う事が前提になっていることもあって、テレタイプライタ用の制御コードが色々入っている。LOADとSAVE代わりでもあるLISTはSTXで始まり、ETXで終了であるとか。
LIST出力時は別段問題ないと思われるが(TeraTermの場合)、LOADでSTX待たれても困るので。
ただしLOADの動作確認はしていないので、ちゃんと動くかは未確認。

(3)アドレス配置の変更
これもこちらのメモリマップにあわせて変更。
ただし、変数A~Zのメモリ配置はゼロページの特定領域決め打ちになっていたりするので、影響少ない範囲で最小限に。
ちなみに「マイコン手づくり塾」のTinyBASICは、その変数領域もゼロページ外に変更してたりする。

そうやって変更を加えたのだが、起動はするがうまく動作しない。
で、変更部分のチェックからはじめて、ベースにさせてもらったソースと自分で打ち込んだソース、打ち込み元の本のソースリストを見比べて修正していったがやはりダメ。
ただ、動作現象的にTinyBASICのワークアリアを侵食してしまっているか、スタックが崩れているかかな?と思いながらソースを順に追っていたところ、スタックポインタをインデックスレジスタ代わりに使っているのを所々発見。
あぁなるほど、送受信に割込を使っているからスタックにワークエリアを設定している時に割込がかかるとアウトになる模様。
スタックポインタ操作前に割込禁止。一連の処理終了後に割込許可を入れたら無事動作しました。



nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。