HD64180Compact(その6)16bit乗算処理 [Z80]
今回使用している HD64180 では Z80 には無かった 8bit x 8bit の乗算命令が追加されています。参考としてデータシートの乗算命令に関する部分の抜粋を貼っておきます。8bit の乗算を 17 ステートで実行できるのでかなり高速です。
Z80 における 16bit の乗算の高速化検討に関しては「Z80での高速な乗算処理(その3)2バイト乗算への適用検討」の記事(以降、乗算高速化ページと記す)で書きましたが、HD64180 の 8bit 乗算命令を使った場合、どれくらい速くなるものか実験してみました。
HD64180 の 8bit 乗算命令を使って 16bit の乗算を実行するために乗算高速化ページにも書いている下記式のようなバイト分割法(と勝手に呼称)で行いました。
作成したソースコードを以下に示します。あまり最適化はしていませんが高速化のために固定のワークエリアは使用せずスタックを使用するようにしました。最適化してみました。
実機で測定した乗算時間の結果を下表にまとめました。HD64180 は 6MHz で評価に時間がかかりそうだったので乗算高速化ページの時よりループ回数を 1/4 に削減しています。表中の Minus square method(マイナス二乗法)等の乗算方式についての詳細は乗算高速化ページを参照してください。表中の比率(ratio)は速度比率なので実行時間比率の逆数で同一色内での比率になっています。中段の Z80 6Mhz の部分は上段の Z80 20MHz での測定値からクロック反比例で算出した推定値です。また、Z80 と HD64180 は両者ともメモリ wait は無い状態です。
★追記 2024/03/10 {
今までの乗算処理時間の計測は乗算処理以外に乗算処理に渡す引数の設定や引数によるループ処理の部分の処理時間も含めた時間を計測していました。しかし、HD64180 の MLT を使用した 16bit 乗算処理がかなりコンパクトになったことから乗算処理以外の処理の時間分を測定し、従来計測していた乗算処理時間から減算することで純粋に乗算処理にかかる時間で比較するようにしました。
}
意外だったのは Z80 ではノーマルな乗算法より速かった1バイトのマイナス二乗法を使ったバイト分割法による乗算が、ノーマルな乗算法より遅くなったことです。2byte 版のマイナス二乗法のデータを見ると Z80 での高速化は 1.35 倍 だったものが HD64180 では 1.24 倍に低下していますが、ノーマル手法よりは速いという結果でした。
また、Z80 と HD64180 の速度差としては HD64180 の方が 1.10 ~ 1.26 倍速いという結果でした。
元々の目的である MLT による高速化については「MLT を使用した 16bit の乗算処理はノーマル処理の 4.56 倍速い」という結果になりました。流石にハードウェアによる高速化なので速いですね。
それから今回の評価に直接的な関係はありませんが、Windows の DOS 窓で動作する CPM エミュレータがなんと HD64180 の乗算命令をもエミュれることが判りました。
最後に上記の速度比較表の元データとなる画面キャプチャーを貼っておきます。
★追記 2024/03/11
HD64180 の MLT を使った 16bit 乗算を変更し再測定
★追記 2024/03/21
6MHz 動作の HD64180 でアセンブラで記述したASCIIARTの実行時間が通常の乗算処理の7.3秒から3.5秒に短縮されました。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
HD64180 の8ビット乗算命令 |
|
|
Z80 における 16bit の乗算の高速化検討に関しては「Z80での高速な乗算処理(その3)2バイト乗算への適用検討」の記事(以降、乗算高速化ページと記す)で書きましたが、HD64180 の 8bit 乗算命令を使った場合、どれくらい速くなるものか実験してみました。
HD64180 の 8bit 乗算命令を使って 16bit の乗算を実行するために乗算高速化ページにも書いている下記式のようなバイト分割法(と勝手に呼称)で行いました。
(28*x1 + x0)*(28*y1 + y0) = 216*x1*y1 + 28*(x0*y1 + x1*y0) + x0*y0 |
---|
作成したソースコードを以下に示します。
HD64180 15bit 乗算処理(Z80アセンブラ) |
|
※2024/03/11 最適化で高速化 |
実機で測定した乗算時間の結果を下表にまとめました。HD64180 は 6MHz で評価に時間がかかりそうだったので乗算高速化ページの時よりループ回数を 1/4 に削減しています。表中の Minus square method(マイナス二乗法)等の乗算方式についての詳細は乗算高速化ページを参照してください。表中の比率(ratio)は速度比率なので実行時間比率の逆数で同一色内での比率になっています。中段の Z80 6Mhz の部分は上段の Z80 20MHz での測定値からクロック反比例で算出した推定値です。また、Z80 と HD64180 は両者ともメモリ wait は無い状態です。
★追記 2024/03/10 {
今までの乗算処理時間の計測は乗算処理以外に乗算処理に渡す引数の設定や引数によるループ処理の部分の処理時間も含めた時間を計測していました。しかし、HD64180 の MLT を使用した 16bit 乗算処理がかなりコンパクトになったことから乗算処理以外の処理の時間分を測定し、従来計測していた乗算処理時間から減算することで純粋に乗算処理にかかる時間で比較するようにしました。
}
16bit 乗算処理の速度比較表 |
|
意外だったのは Z80 ではノーマルな乗算法より速かった1バイトのマイナス二乗法を使ったバイト分割法による乗算が、ノーマルな乗算法より遅くなったことです。2byte 版のマイナス二乗法のデータを見ると Z80 での高速化は 1.35 倍 だったものが HD64180 では 1.24 倍に低下していますが、ノーマル手法よりは速いという結果でした。
また、Z80 と HD64180 の速度差としては HD64180 の方が 1.10 ~ 1.26 倍速いという結果でした。
元々の目的である MLT による高速化については「MLT を使用した 16bit の乗算処理はノーマル処理の 4.56 倍速い」という結果になりました。流石にハードウェアによる高速化なので速いですね。
それから今回の評価に直接的な関係はありませんが、Windows の DOS 窓で動作する CPM エミュレータがなんと HD64180 の乗算命令をもエミュれることが判りました。
最後に上記の速度比較表の元データとなる画面キャプチャーを貼っておきます。
16bit 乗算処理の時間計測画面(Z80 20MHz) |
|
16bit 乗算処理以外の処理の時間計測画面(Z80 20MHz) |
|
16bit 乗算処理の時間計測画面(HD64180 6MHz) |
|
16bit 乗算処理以外の処理の時間計測画面(HD64180 6MHz) |
|
★追記 2024/03/11
HD64180 の MLT を使った 16bit 乗算を変更し再測定
MLT 使用の 16bit 乗算処理の時間計測画面(HD64180 6MHz) |
|
★追記 2024/03/21
6MHz 動作の HD64180 でアセンブラで記述したASCIIARTの実行時間が通常の乗算処理の7.3秒から3.5秒に短縮されました。
HD64180と20ピンのPICを使った3チップ構成のボードで遊び中
— skyriver (@wcinp) March 13, 2024
64180で追加の8bit乗算を使った16bit乗算処理は最適化の結果、通常の乗算処理の4.56倍高速なり
64180 6MHzでアセンブラで記述したASCIIARTの実行時間は通常の乗算処理の7.3秒から3.5秒に短縮されたhttps://t.co/4U1k1Af2m3#HD64180Compact pic.twitter.com/9veKW5d2aN
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
HD64180Compact(その5)割込み動作の確認 [Z80]
前回の記事で書いたようにディバッグモニタを導入し、本記事の末尾に記載したように CP/M の起動までできました。そこで、当初の目的でもあった割込み対応について検討してみましたので記録しておきます。
初回の記事に書いたように今回の HD64180Compact では従来(Z80PicCompact)の IORQ 信号により WAIT 状態になることに対してマスクする機能を追加しています。この目的としては
a)については内部I/Oの場合、WAIT 信号は無視され WAIT 状態にならないので処理が止まらないことが判りました(実は弊害があり対処内容を後述します)。
b)は追加 I/O の実行前に IORQ による WAIT をマスクすればいいだけの話です。
c)について HD64180 内蔵のタイマを使った割込みで今回確認しましたので以下に記載します。
今回、割込み動作試験用に作成したタイマ0を使い割込みを発生させる試験プログラムのソースを以下に示します。ベクタ方式の割込みで割込み処理のアドレス指定方法は Z80 のモード2の割込みとほぼ同じです。割込み処理(INTTM0)ではタイマ0割込みのフラグをクリアするためのレジスタ読み込みとカウンタ用ワークの値を 200ms 毎にインクリメントしています。EnPic は IORQ により WAIT 状態になることを可能にするマクロです。
HD64180 の内部割込み及び外部の INT1、INT2 の割込みはベクタ方式の割込みとなります。参考としてデータシートのタイミングチャートが下図になります。割込み応答時に IORQ がアクティブにならないので上述のように WAIT 状態になる心配はありません。
ベクタ割込みの開始を捉えるためにトリガー条件として ST 立下りかつLIRがhighとした際のロジアナ波形例が下図になります。STは各命令の1バイト目のアクセス時にアクティブになるのでこれを目印にマーカーで区切り、実行している命令のニーモニックを図中に追記しました。
上記のタイマー割込み起動プログラムを起動後に GAME 言語で作成した下記のカウント値が変化した際に画面表示するプログラムを起動しました。
実行した際の画面キャプチャが下図です。"Cw30"と表示されていますが、これは PIC 側が未定義コマンドである 0x30 を受信したことを示しています。このように HD64180 内部レジスタへのアクセス時に発生する短い IORQ を PIC が稀に検出してエラーが発生しています。
今回の割込み動作試験で次の問題があることが判りました。
1項は上記の画面での"Cw30"の表示のことですが、PIC側で IORQ を検出する際、6回連続で IORQ がアクティブな場合に検出するように変更しました(4回チェックでは問題事象が発生したのでマージン込みで6回にした)。
2項についてはキー入力時に直接データ入力していたところをキー入力有無をステータスでチェック後、キー入力ありの場合にデータ入力するようにしました。
対処後のカウントチェック画面のキャプチャも貼っておきます。数十分継続してみましたが上記の問題事象は発生しませんでした。
以上、割込み動作試験での問題と対処について記載しましたが、これにより手持ちの Z80 ボードでは難しかった割込みを使った動作実験ができる環境ができました。
[補足]
CP/M が動作するようになるまでに発生した問題や対処などを以下にメモとして残しておきます。
初めに下の写真が今回作成した HD694180 と USB 機能を有する 20 ピンの PIC を使った手配線のボードです。
最初は SD 初期化での CMD0 コマンドに対しての応答が無い状態でした。これはハードウェアの問題で PIC 側が SD からの応答を読み取れず、SD から応答がまだ出ていないのに応答を受け取ってしまっている状態でした。
チップ抵抗を交換して応答が正常に受け取れるようになりました。
今回の HD64180Compact では今後機能追加し易いように SD の初期化を従来のように電源投入時ではなく、Z80 からの要求により実行するようにしました。このため、PIC 側の SD の初期化完了の際に Z80 側とのタイミング合せがうまく行かなくなってしまいました。原因は SD に送信するコマンド間の SDCS が非アクティブになる期間、Z80 側の WAIT が解除され処理が進むことだったので、初期化コマンド期間は連続して SDCS をアクティブにするように変更しました。結果として初期化を完了するまで Z80 が WAIT 状態のままなので双方のタイミングずれは発生しなくなりました。
初期化時のロジアナ波形を記録として貼っておきます。下図は初期化全体のロジアナ波形です。ほとんどの時間は CMD41(0x69)に対する Ok 応答(0x00)が来るまでリトライしている部分になります。
下図は CMD41(0x69)に対して Ng 応答を受けた部分のズームです。
下図は CMD41(0x69)に対して Ok 応答を受け取り、CMD58(0x7a)を発行して初期化を終了している部分です。
初めて CP/M が起動できた際の画面も記念に貼っておきます。但し、この時は HI-TECH C でのコンパイル時に固まり、不安定な要素が残存していました。
この時の CP/M の起動方法はディバッグモニタで BootLoader の Hex ファイルを読み込んで起動し、BootLoaderが SD から IPL を読み込み起動することで IPL がメモリ上に CP/M 本体をロードし BIOS の boot にジャンプすることで CP/M が起動されます。SD 自体は Z80PicCompact と同じものを使用していますが、MBASIC や BDS C は動きましたが HI-TECH C でのコンパイルで固まるのでまだ不安定要素がありました。
今回、HD64180は6MHz(USB用の12MHzからの流用)で動いていてBIOS部分はZ80の16MHzと20MHzで動作実績のあるものです。遅くなって動かなくなる部分は全く思い当たらないと思っていましたが原因はハードでした^^;
修正して安定に動作しHitech-Cのコンパイラも元気に動きました。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
初回の記事に書いたように今回の HD64180Compact では従来(Z80PicCompact)の IORQ 信号により WAIT 状態になることに対してマスクする機能を追加しています。この目的としては
- 内部I/O(レジスタ)アクセス時のWAIT防止
- 将来追加した外部I/Oアクセス時のWAIT防止
- 割込み時のIORQでのWAIT防止
a)については内部I/Oの場合、WAIT 信号は無視され WAIT 状態にならないので処理が止まらないことが判りました(実は弊害があり対処内容を後述します)。
b)は追加 I/O の実行前に IORQ による WAIT をマスクすればいいだけの話です。
c)について HD64180 内蔵のタイマを使った割込みで今回確認しましたので以下に記載します。
今回、割込み動作試験用に作成したタイマ0を使い割込みを発生させる試験プログラムのソースを以下に示します。ベクタ方式の割込みで割込み処理のアドレス指定方法は Z80 のモード2の割込みとほぼ同じです。割込み処理(INTTM0)ではタイマ0割込みのフラグをクリアするためのレジスタ読み込みとカウンタ用ワークの値を 200ms 毎にインクリメントしています。EnPic は IORQ により WAIT 状態になることを可能にするマクロです。
タイマ割込みソース(Z80アセンブラ) |
|
HD64180 の内部割込み及び外部の INT1、INT2 の割込みはベクタ方式の割込みとなります。参考としてデータシートのタイミングチャートが下図になります。割込み応答時に IORQ がアクティブにならないので上述のように WAIT 状態になる心配はありません。
ベクタ方式の割込みタイミング |
|
ベクタ割込みの開始を捉えるためにトリガー条件として ST 立下りかつLIRがhighとした際のロジアナ波形例が下図になります。STは各命令の1バイト目のアクセス時にアクティブになるのでこれを目印にマーカーで区切り、実行している命令のニーモニックを図中に追記しました。
タイマ割込み時のロジアナ波形例 |
|
上記のタイマー割込み起動プログラムを起動後に GAME 言語で作成した下記のカウント値が変化した際に画面表示するプログラムを起動しました。
カウント値チェックプログラム(GAME言語) |
---|
10 A=$00FE 20 D=A(0) 30 ;=D<>A(0) / D=A(0) ??=A ":" ??=D 40 #=30 |
実行した際の画面キャプチャが下図です。"Cw30"と表示されていますが、これは PIC 側が未定義コマンドである 0x30 を受信したことを示しています。このように HD64180 内部レジスタへのアクセス時に発生する短い IORQ を PIC が稀に検出してエラーが発生しています。
カウント値チェック結果 |
|
今回の割込み動作試験で次の問題があることが判りました。
- 内部レジスタのアクセスをPICが検出してしまう
- 入力待ちの際WAIT状態が継続し割込みが入らない
1項は上記の画面での"Cw30"の表示のことですが、PIC側で IORQ を検出する際、6回連続で IORQ がアクティブな場合に検出するように変更しました(4回チェックでは問題事象が発生したのでマージン込みで6回にした)。
2項についてはキー入力時に直接データ入力していたところをキー入力有無をステータスでチェック後、キー入力ありの場合にデータ入力するようにしました。
対処後のカウントチェック画面のキャプチャも貼っておきます。数十分継続してみましたが上記の問題事象は発生しませんでした。
カウント値チェック結果(対処後) |
|
以上、割込み動作試験での問題と対処について記載しましたが、これにより手持ちの Z80 ボードでは難しかった割込みを使った動作実験ができる環境ができました。
[補足]
CP/M が動作するようになるまでに発生した問題や対処などを以下にメモとして残しておきます。
初めに下の写真が今回作成した HD694180 と USB 機能を有する 20 ピンの PIC を使った手配線のボードです。
手配線の開発用ボード |
|
最初は SD 初期化での CMD0 コマンドに対しての応答が無い状態でした。これはハードウェアの問題で PIC 側が SD からの応答を読み取れず、SD から応答がまだ出ていないのに応答を受け取ってしまっている状態でした。
CMD0 への応答なし |
|
チップ抵抗を交換して応答が正常に受け取れるようになりました。
CMD0 と CMD8 への正常応答あり |
|
今回の HD64180Compact では今後機能追加し易いように SD の初期化を従来のように電源投入時ではなく、Z80 からの要求により実行するようにしました。このため、PIC 側の SD の初期化完了の際に Z80 側とのタイミング合せがうまく行かなくなってしまいました。原因は SD に送信するコマンド間の SDCS が非アクティブになる期間、Z80 側の WAIT が解除され処理が進むことだったので、初期化コマンド期間は連続して SDCS をアクティブにするように変更しました。結果として初期化を完了するまで Z80 が WAIT 状態のままなので双方のタイミングずれは発生しなくなりました。
初期化時のロジアナ波形を記録として貼っておきます。下図は初期化全体のロジアナ波形です。ほとんどの時間は CMD41(0x69)に対する Ok 応答(0x00)が来るまでリトライしている部分になります。
SD 初期化時のロジアナ波形例(全体) |
|
下図は CMD41(0x69)に対して Ng 応答を受けた部分のズームです。
SD 初期化時のロジアナ波形例(NG応答受信時) |
|
下図は CMD41(0x69)に対して Ok 応答を受け取り、CMD58(0x7a)を発行して初期化を終了している部分です。
SD 初期化時のロジアナ波形例(OK応答受信時) |
|
初めて CP/M が起動できた際の画面も記念に貼っておきます。但し、この時は HI-TECH C でのコンパイル時に固まり、不安定な要素が残存していました。
この時の CP/M の起動方法はディバッグモニタで BootLoader の Hex ファイルを読み込んで起動し、BootLoaderが SD から IPL を読み込み起動することで IPL がメモリ上に CP/M 本体をロードし BIOS の boot にジャンプすることで CP/M が起動されます。SD 自体は Z80PicCompact と同じものを使用していますが、MBASIC や BDS C は動きましたが HI-TECH C でのコンパイルで固まるのでまだ不安定要素がありました。
初の CP/M 起動画面 |
|
今回、HD64180は6MHz(USB用の12MHzからの流用)で動いていてBIOS部分はZ80の16MHzと20MHzで動作実績のあるものです。遅くなって動かなくなる部分は全く思い当たらないと思っていましたが原因はハードでした^^;
修正して安定に動作しHitech-Cのコンパイラも元気に動きました。
HI-TECH C でのコンパイル画面 |
|
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
HD64180Compact(その4)ディバッグモニタ [Z80]
前回の記事で書いたように手配線で製作した開発機がハード的には動いているようなのでディバッグモニタを入れることにしました。
GAME言語で自作した簡易モニタのGAMONを入れてみたところ、ブレークが動作しない場合があるので少し悩みましたが、Z80を使用したZ80PicCompactでも同様の現象が発生することが判り、GAMONを修正し正常動作を確認しました。ブレーク機能のディバッグにはブレーク機能が使えないので机上ディバッグですw。
ついでにHD64180でも使えるようにI/O入出力のコマンドのアドレスを16bit対応しました。「GAME言語で作った簡易モニタ」のページでアップデート版を公開しています。
HD64180関連の情報をネットで眺めていたところ、敏雪さんの「Softいろいろ」のページでHD64180用のモニタであるH18MONを見つけ、インストールしてみました。アセンブルには IR80.EXE 相当のアセンブラが必要なようなのですがネットでは見つけられなかったのでperlを使ってローカルのテンポラリラベルを自動変換する等してアセンブルしました。HD64180固有の命令は前回の記事で書いたマクロで対応しました。
コンソール入出力部分を変更しただけでは動かなかったのですが、メモリチェック部分を変更することで動作するようになりました(ROMでの運用を想定しているため、RAM上にロードした状態では動かなかった)。
起動画面のキャプチャが下図になります。今回作成したHD64180Compactではブート時にPICからロードされるHexLoaderを0xff00に配置していて、この領域をH18MONがデータ領域として使用しているので、GAMONを使ってロードしています。
上図のヘルプ表示にもあるようにH18MONは逆アセンブルやトレース機能もあり、このような高機能なモニタを公開されている作者に感謝致します。
ブレーク機能の試行として「メモリ上で実際に動くプログラム(その2)」の記事で書いたフラグの未使用ビット設定確認のソフトを実行した際の画面キャプチャが下図になります。Hexファイルは'^Z'で終端されている必要があるようです。実行結果として"Ok"が表示されているのでHD64180でもフラグの未使用ビットに値を設定できることが判ります。
因みにGAMONで同様にブレークした際の画面が下図です。
逆アセンブル機能はいいとしてトレース機能には食指が動きますが、暫くは手に馴染んだGAMONを使っていきたいと思います。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
GAME言語で自作した簡易モニタのGAMONを入れてみたところ、ブレークが動作しない場合があるので少し悩みましたが、Z80を使用したZ80PicCompactでも同様の現象が発生することが判り、GAMONを修正し正常動作を確認しました。ブレーク機能のディバッグにはブレーク機能が使えないので机上ディバッグですw。
ついでにHD64180でも使えるようにI/O入出力のコマンドのアドレスを16bit対応しました。「GAME言語で作った簡易モニタ」のページでアップデート版を公開しています。
HD64180関連の情報をネットで眺めていたところ、敏雪さんの「Softいろいろ」のページでHD64180用のモニタであるH18MONを見つけ、インストールしてみました。アセンブルには IR80.EXE 相当のアセンブラが必要なようなのですがネットでは見つけられなかったのでperlを使ってローカルのテンポラリラベルを自動変換する等してアセンブルしました。HD64180固有の命令は前回の記事で書いたマクロで対応しました。
コンソール入出力部分を変更しただけでは動かなかったのですが、メモリチェック部分を変更することで動作するようになりました(ROMでの運用を想定しているため、RAM上にロードした状態では動かなかった)。
起動画面のキャプチャが下図になります。今回作成したHD64180Compactではブート時にPICからロードされるHexLoaderを0xff00に配置していて、この領域をH18MONがデータ領域として使用しているので、GAMONを使ってロードしています。
H18MON起動画面 |
|
※2024/02/29 最新版に差し替え |
上図のヘルプ表示にもあるようにH18MONは逆アセンブルやトレース機能もあり、このような高機能なモニタを公開されている作者に感謝致します。
ブレーク機能の試行として「メモリ上で実際に動くプログラム(その2)」の記事で書いたフラグの未使用ビット設定確認のソフトを実行した際の画面キャプチャが下図になります。Hexファイルは'^Z'で終端されている必要があるようです。実行結果として"Ok"が表示されているのでHD64180でもフラグの未使用ビットに値を設定できることが判ります。
H18MONでのブレーク動作 |
|
※2024/02/29 最新版に差し替え |
因みにGAMONで同様にブレークした際の画面が下図です。
GAMOMでのブレーク動作 |
|
※2024/03/02 最新版に差し替え |
逆アセンブル機能はいいとしてトレース機能には食指が動きますが、暫くは手に馴染んだGAMONを使っていきたいと思います。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
HD64180Compact(その3)MBASICでASCIIART [Z80]
HD64180 と USB 機能を有する 20 ピンの PIC を使った 3 チップ構成のボードの開発の続編です。
前回の記事でジャンプ命令によるループができたことを書きましたが、後述するように Hello 表示と HexLoader も動いたので「CP/M-80でのBIOSエミュレートによるMBASICの起動」の記事で書いたように CP/M の BIOS をエミュレートして MBASIC を起動し ASCIIART を動かしてみました。
今回開発の HD64180Compact と類似の構成で Z80 を実装した Z80PicCompact との実行時間比較も行ってみました。
最初にソフト制御可能なメモリと I/O アクセス時の WAIT 設定を行わず(リセット直後の状態では WAIT ステート数がメモリ:3、IO:4)実行したところ(上表のNo2)かなり遅い結果でしたが、WAIT を最小の設定(メモリ:0、IO:1)にした結果(上表のNo3)、Z80PicCompact のクロックから比例計算した Z80 の速度の 1.15(=95.4x2/165.2)倍になり、ASCIIART.BAS の実行では HD64180 は Z80 より 1.15 倍速いことになります。尚、リフレッシュは禁止の設定にしています。HD64180 には 8bit の乗算命令もあるのでこれを活用できる場面では速度差が更に大きくなると思います。
WAIT を最小に設定して ASCIIART.BAS を実行した際の画面のキャプチャーが下図です。PIC に実装した BootROM 機能により Z80 側で HexLoader が起動し、その後 BIOS エミュと MBASIC の Hex ファイルを読み込ませています。
上記の比較表のエビデンスとして HD64180Compact(最大 WAIT)と Z80PicCompact での ASCIIART 実行時の画面キャプチャーも貼っておきます。
CP/M の BIOS エミュレートのソースも短いので貼っておきます。HD64180 の拡張命令は macro 定義して使いました。
[補足]
以降に Hello 表示の際のデータをメモとして記録しておきます。下記は Z80 側のソースです。EnPic で PIC が提供するサービスが有効になり、DisPic で無効になります。
下記が初めて Hello 表示した際の画面です^^
Z80PicCompact の環境を若干変更することで動作しました。
下図が Hello 表示時のロジアナ波形のサンプルです。1文字を PIC に送信するのに 60us 程度の時間がかかっています。突発的に時間がかかっている部分は PIC 側が USB 関連の処理をしているためだと思います。
下図は Puts をコールする部分を拡大したもので WR/ が2回アクティブになっている部分(マーカー:0)がスタックへのリターンアドレスの書込み部分です。
その後、毎回テストプログラムを PIC に書き込むのは面倒なので、PIC に HexLoader を書き込んだ状態で冒頭に書いた MBASIC と ASCIIART.BAS で実行速度の評価を行いました。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
前回の記事でジャンプ命令によるループができたことを書きましたが、後述するように Hello 表示と HexLoader も動いたので「CP/M-80でのBIOSエミュレートによるMBASICの起動」の記事で書いたように CP/M の BIOS をエミュレートして MBASIC を起動し ASCIIART を動かしてみました。
今回開発の HD64180Compact と類似の構成で Z80 を実装した Z80PicCompact との実行時間比較も行ってみました。
No. | machine environment | clock | time | ratio |
---|---|---|---|---|
1 | Z80PicCompact | 12MHz | 95.4s | 1.00 |
2 | HD64180Compac(maximal Wait) | 6MHz | 314.1s | 3.29 |
3 | HD64180Compact(minimal Wait) | 6MHz | 165.2s | 1.73 |
最初にソフト制御可能なメモリと I/O アクセス時の WAIT 設定を行わず(リセット直後の状態では WAIT ステート数がメモリ:3、IO:4)実行したところ(上表のNo2)かなり遅い結果でしたが、WAIT を最小の設定(メモリ:0、IO:1)にした結果(上表のNo3)、Z80PicCompact のクロックから比例計算した Z80 の速度の 1.15(=95.4x2/165.2)倍になり、ASCIIART.BAS の実行では HD64180 は Z80 より 1.15 倍速いことになります。尚、リフレッシュは禁止の設定にしています。HD64180 には 8bit の乗算命令もあるのでこれを活用できる場面では速度差が更に大きくなると思います。
WAIT を最小に設定して ASCIIART.BAS を実行した際の画面のキャプチャーが下図です。PIC に実装した BootROM 機能により Z80 側で HexLoader が起動し、その後 BIOS エミュと MBASIC の Hex ファイルを読み込ませています。
HD64180Compact での ASCIIART 実行画面( WAIT 最小設定時) |
|
上記の比較表のエビデンスとして HD64180Compact(最大 WAIT)と Z80PicCompact での ASCIIART 実行時の画面キャプチャーも貼っておきます。
HD64180Compact での ASCIIART 実行画面(WAIT 最大設定時) |
|
Z80PicCompact での ASCIIART 実行画面 |
|
CP/M の BIOS エミュレートのソースも短いので貼っておきます。HD64180 の拡張命令は macro 定義して使いました。
CP/M BIOS エミュレーター(Z80 アセンブラ) |
|
[補足]
以降に Hello 表示の際のデータをメモとして記録しておきます。下記は Z80 側のソースです。EnPic で PIC が提供するサービスが有効になり、DisPic で無効になります。
Hello 表示プログラム(Z80 アセンブラ) |
|
下記が初めて Hello 表示した際の画面です^^
Z80PicCompact の環境を若干変更することで動作しました。
Hello 表示画面 |
|
下図が Hello 表示時のロジアナ波形のサンプルです。1文字を PIC に送信するのに 60us 程度の時間がかかっています。突発的に時間がかかっている部分は PIC 側が USB 関連の処理をしているためだと思います。
Hello 表示時のロジアナ波形例 |
|
下図は Puts をコールする部分を拡大したもので WR/ が2回アクティブになっている部分(マーカー:0)がスタックへのリターンアドレスの書込み部分です。
ロジアナ波形の CALL 部の拡大図 |
|
その後、毎回テストプログラムを PIC に書き込むのは面倒なので、PIC に HexLoader を書き込んだ状態で冒頭に書いた MBASIC と ASCIIART.BAS で実行速度の評価を行いました。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
HD64180Compact(その2)開発機完成 [Z80]
前回の記事で書いた HD64180Compact の構想での開発用基板(以降、開発機と記す)が完成しました(下の写真)。自作のワイヤリングペンを使ってポリウレタン線で結線しています。
赤いフッククリップは PIC 書込み用の PICKit3 を接続するためのもので、接続用の PIC に被せるピン台を今回作りました。動作確認するのに必要最小限の信号を中央のピンソケットから取り出し、ロジアナに接続しています。下側で接続されているのは USB ケーブルでボードへ給電とパソコンとの通信(現時点では動作未確認)に使います。
共立エレショップさんから購入した新品の HD64B180R0P もあるのですがもったいないので以前、海外通販で購入した HD64180RP8 のリユース品を実装しています。メモリは CPU の上限の 512KB です。クロックは PIC 側の USB 用の 12MHz を流用しています(HD64180 は 6MHz 動作)。
開発機完成記念として結線チェック用の回路図も貼っておきます。動作モニタ用のトランジスタを使った LED 回路の部分は未結線ですが、動作確認後に結線する予定です。
実装した USB 機能付きの 20 ピンのPIC(PIC18F14K50)は BootROM と 通信/SPI インターフェースとして機能します。通信インターフェースはパソコンとは USB、HD64180 とはパラレル I/F で接続なので高速です。SPI は EEPROM もしくは SD カードに接続する予定です。Z80PicCompact 用のソフトをほぼそのまま持ってきて動作確認してみました。若干の変更は行ったものの最初の一歩であるジャンプ命令でのループ動作ができました。
実施手順はZ80PicCompact の時とほぼ同様で下記のようになります。
下図がジャンプループに成功した際のロジアナ波形例です。右端のウェイト無しで実行している部分がジャンプループです。1周期が 3us で 6MHz 動作なので遅い(JPは 9 ステート)感じですが、リセット直後の状態なのでソフト制御のウェイトがかかっているためだと思います。
★追記 2024/02/26 {
CPUは6MHz動作なので1クロックは(1/6)usでリセット直後は1回のメモリアクセスに3クロックのウェイトが入るので
3(=(1/6)*(9+3*3))us
となり下図の実測値と一致します。
}
尚、LIR/ は Z80 の M1 相当の信号でオペコードフェッチの際にアクティブになります。
★追記 2024/02/22 {
HD64180 には内蔵の I/O レジスタがあり、今回のブート時のメモリ書込みに使用する INI 命令で I/O アドレスを明示的に外部アドレスにするために初期化コードの末尾に C-reg の設定を追加しました。追加後のロジアナ波形例を貼っておきます。但し、他のロジアナ波形は追加前のままです。
}
以降に自分へのメモの意味も込めてジャンプループ実現までに発生した問題とその対処の概要を記録しておきます。
[補足]
メモリ設定データを HD64180 へ渡すために INIR 命令を使用していましたが、このコード自体は PIC がデータバスに出力しているので B-reg がゼロになっても繰り返されることから B-reg を設定していません。
しかし厳密にいうと B-reg がゼロになった場合とそれ以外の場合で実行ステート数が異なる(ゼロの場合が速い)ことから B-reg の影響を受けない INI 命令(ステート数は常に B-reg がゼロの場合と同じ)を使用することにしました。
ロジアナ波形例を下記に示します。INI の方が若干早くなったようにも見えますが次の INI では時間がかかっているようなので今回の処理ではウェイトが掛かっていることから処理時間はほぼ同じと言えそうです。
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
赤いフッククリップは PIC 書込み用の PICKit3 を接続するためのもので、接続用の PIC に被せるピン台を今回作りました。動作確認するのに必要最小限の信号を中央のピンソケットから取り出し、ロジアナに接続しています。下側で接続されているのは USB ケーブルでボードへ給電とパソコンとの通信(現時点では動作未確認)に使います。
共立エレショップさんから購入した新品の HD64B180R0P もあるのですがもったいないので以前、海外通販で購入した HD64180RP8 のリユース品を実装しています。メモリは CPU の上限の 512KB です。クロックは PIC 側の USB 用の 12MHz を流用しています(HD64180 は 6MHz 動作)。
完成した HD64180Compact の開発機 |
|
開発機完成記念として結線チェック用の回路図も貼っておきます。動作モニタ用のトランジスタを使った LED 回路の部分は未結線ですが、動作確認後に結線する予定です。
結線チェック用回路図 |
|
実装した USB 機能付きの 20 ピンのPIC(PIC18F14K50)は BootROM と 通信/SPI インターフェースとして機能します。通信インターフェースはパソコンとは USB、HD64180 とはパラレル I/F で接続なので高速です。SPI は EEPROM もしくは SD カードに接続する予定です。Z80PicCompact 用のソフトをほぼそのまま持ってきて動作確認してみました。若干の変更は行ったものの最初の一歩であるジャンプ命令でのループ動作ができました。
実施手順はZ80PicCompact の時とほぼ同様で下記のようになります。
- 初期化コード実行
PIC が下記のコードを HD64180 がフェッチするタイミングでデータバス上に出力し、HD64180 が実行します。LD HL,StartAdr XOR A OUT (00H),A ; set RTS0 to low OUT (36H),A ; set refresh disable LD C,0FFH ; set external I/O address
※2024/02/22 Creg設定を追加
- INI 命令でのメモリ書込み
PIC からデータバス上に INI 命令のオペコードを出力し、HD64180 が I/O リードするタイミングでメモリに設定するコードを出力する。これを繰り返すことで上記1項で HL レジスタに設定したメモリ上にジャンプ命令のコードを書き込む。今回は 0100H から C3H, 00H, 01H の3バイトのデータを書き込んだ。
- メモリ展開したコードへジャンプ
上記2項でメモリに設定したコードの開始アドレスへのジャンプ命令を PIC が出力し、HD64180 が実行する。
下図がジャンプループに成功した際のロジアナ波形例です。右端のウェイト無しで実行している部分がジャンプループです。1周期が 3us で 6MHz 動作なので遅い(JPは 9 ステート)感じですが、リセット直後の状態なのでソフト制御のウェイトがかかっているためだと思います。
★追記 2024/02/26 {
CPUは6MHz動作なので1クロックは(1/6)usでリセット直後は1回のメモリアクセスに3クロックのウェイトが入るので
3(=(1/6)*(9+3*3))us
となり下図の実測値と一致します。
}
尚、LIR/ は Z80 の M1 相当の信号でオペコードフェッチの際にアクティブになります。
ジャンプループ実行時のロジアナ波形例(サンプリング:32MHz) |
|
★追記 2024/02/22 {
HD64180 には内蔵の I/O レジスタがあり、今回のブート時のメモリ書込みに使用する INI 命令で I/O アドレスを明示的に外部アドレスにするために初期化コードの末尾に C-reg の設定を追加しました。追加後のロジアナ波形例を貼っておきます。但し、他のロジアナ波形は追加前のままです。
ジャンプループ実行時のロジアナ波形例(サンプリング:32MHz) |
|
以降に自分へのメモの意味も込めてジャンプループ実現までに発生した問題とその対処の概要を記録しておきます。
- IORQ 待ちで停止
[現象]
INIR 命令でメモリ設定時に IORQ/ が読み取りできず PIC 側の処理が停止した(下図)。
[原因と対処]
今回追加した IORQ を RTS0 でマスクする部分で、RTS0 のリセット後の値が High(マスク状態)だったので初期化コードに RTS0 をlow にする制御を追加した。
IORQ 待ちで停止
- INIR 後に停止
[現象]
実行コードをメモリに展開するための INIR 命令実行後 HD64180 が停止する。
[原因と対処]
INIR でコード出力後のウェイト解除時間が短すぎて HD64180 がウェイト解除にならないのでウェイト解除時間を長くした。
ウェイト解除ができない(赤カーソル部分)
- メモリ書込みで停止
[現象]
HD64180 が INIR で読み込んだデータをメモリに書き込み時にウェイトが解除されず、そのまま停止してしまう。
[原因と対処]
PIC 側が INIR に対してメモリに設定するデータを送った後、HD64180 がメモリ書込みできるように一定期間ウェイトを解除する。メモリライト直前のリフレッシュにより MREQ/ がアクティブになり、メモリライト用のウェイト解除が発動した為。対処として初期化コードにリフレッシュ禁止設定を追加した。
メモリライト直前のリフレッシュ動作(赤カーソル部分)
下図はリフレッシュ禁止設定後のロジアナ波形例で緑のカーソル部分が INIR の1回分の時間です。
リフレッシュ禁止後のロジアナ波形例
[補足]
メモリ設定データを HD64180 へ渡すために INIR 命令を使用していましたが、このコード自体は PIC がデータバスに出力しているので B-reg がゼロになっても繰り返されることから B-reg を設定していません。
しかし厳密にいうと B-reg がゼロになった場合とそれ以外の場合で実行ステート数が異なる(ゼロの場合が速い)ことから B-reg の影響を受けない INI 命令(ステート数は常に B-reg がゼロの場合と同じ)を使用することにしました。
ロジアナ波形例を下記に示します。INI の方が若干早くなったようにも見えますが次の INI では時間がかかっているようなので今回の処理ではウェイトが掛かっていることから処理時間はほぼ同じと言えそうです。
INIR から INI に変更後のロジアナ波形例(赤カーソル部分が INI 1回分) |
|
[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]