CPU実験室

誰も見向きもしない古いCPUをいじって動かしてみようというプロジェクトです

ウェイト調整

16bit幅のBCR(Bus Control Resister)の4bitづつにXDATA,YDATA,プログラム領域、ペリフェラル領域に0~15の値を与えることでDSPに外付けした各メモリ空間にそれぞれウェイトが設定できます。

 

BCRを設定してから最小ループを回すテストプログラムを実行させてみます

 

最大ウェイトwait=15の時、これはリセット後BCRのデフォルト値($FFFF)なので最初のこの結果と同様、アドレスバスは1.16MHzでトグルします

ch1:/RD、ch2:アドレスバスA0

 

ここでBCR=$0000に設定して各メモリをノーウェイト最高速でアクセスできるようにするとトグル周波数は9.8MHzまで上昇しました。DSPクロックは19.66MHzなので2クロック/インストラクションで動作していることになります

なお、DSPの内蔵プログラムRAM($0000~$01FF)にロードされたコードはBCRの設定によらずノーウェイトで動作するようです

モニタ完成

各コマンドにはアドレス引数を持てるようにし、Pコマンド(プログラムロード)にタイムアウト脱出、ロードサイズ表示など追加してコマンド作り込みが完了、これをROMに焼き込み電源ONで高機能モニタが起動しました

 

コードサイズは706word、コマンドバッファなどワークメモリはXDATA領域に18word使用します。なおDSP56001のスタックは16段×2バンクをハードウェアでチップに内蔵しているため外付けRAMを圧迫しません

 

SOJパッケージのSRAMを実装するとき半田ごてでかなりゴリゴリやってしまったのでショートとか破損してないか気がかりだったのですが、各メモリ領域にデータロード/ダンプしてみるとちゃんと読み書きできているようです

モード変更

高機能化した修正版モニタのめどが付いてきてサイズも高々1kwordくらいになりそうなのでメモリ配置を再検討しました。

いままではDSPMODE3(Development Mode)で起動していましたがこれをMODE2(Normal Expanded Mode)にしました。こうすることでリセットベクタが$E000に移動します。するとモニタを含んだROM領域を$E000~$FFFFの8kwordに押し込むことができ、残り$0000~$DFFFの56kwordをユーザRAMに開放できます。さらに割込みベクタは$0001以降に残るので先頭部分がRAMだと割込みサービスの記述もできるようになります。

モード切替は基板上のジャンパポスト、メモリマップの変更はGALの書き換えでプログラム空間は以下のようになりました。

なおMODE2にするとオンチップのプログラムRAMが$0000-$01FFに見えるようになり外付けRAMとオーバーライドしますがこの領域でで小さいプログラムを動かしてみると外部への制御信号/PS、/RD、/WRは一切アクティブにならず、アドレスバスすら全く変化しません。つまりアクセスは内部メモリを優先しており外部バスのデコードにそれを考慮する必要はない、ということがわかりました。もちろん内部RAMと外部RAMはシームレスにつながり変な隙間もできません

同じようにデータ空間でも内蔵RAM/ROMや内蔵ペリフェラルとの被りを気にしなくていいのでGALのロジックは非常に単純化しました

 

データテーブル

拡張バイトにデータが残っているとCMP A,Bが常に負になるので引数$A~$Fが+$30足した”:;<=>?”になったということです

修正は簡単で24bitレジスタを56bitアキュームレータAにコピーした時に無条件に拡張バイトA2を0クリアするだけです。再度ダンプしてみると表示は正常になりました

得られた24bitデータを固定小数点Q23フォーマットとしてグラフにプロットするときれいなサインカーブになっています。離散FFTのために用意されていますがDDSやFM音源にも応用できそうです

一方、XDATA領域の$100~$1FFには音声のダイナミックレンジ圧縮のための変換テーブルROMが用意されています。前半がμ-law、後半がA-lawアルゴリズム用で同様にプロットするとμ-lawは逆対数特性になっていることがわかります。A-lawは一部符号化しているのでぐちゃぐちゃですが1対1写像になっています

 

HEX変換(2)

プログラム領域のメモリダンプがうまくいったのでメモリを直接参照している1行 MOVE P:(R0),X0MOVE X:(R0),X0MOVE Y:(R0),X0に変えるだけでたちまちXDATAダンプ、YDATAダンプのメニューを追加できました。

YDATAメモリの$100~$1FFの256ワードには工場出荷時書込み済のオンチップROMがアサインされていて1周期分のサイン波データが埋込まれているとされています。この部分をダンプしてみると、

・・確かにそれっぽい値が表示されます。ですが何故か後半部分から文字化けが混ざってきています。1桁単位の変換(0...15→0...F)のHEX1ルーチンは正しく動作しているはずなのですが。

24bitデータがマイナス(最上位bit=1)のとき起きるようなのでシミュレータsim56000で化けるときの入力値でHEX6ルーチン全体でのレジスタの挙動を見てみました。その結果わかったのが

24bitレジスタを56bitアキュームレータにコピーするとき、仮想的な小数点に合わせて左詰めD47-D24へロードされる(←ここまでは既知)のはいいとして同時に拡張バイト(D55..D48)へ自動的に符号拡張する、とあります

このあとアキュームレータにロジカルなマスクをかけて必要なビットパタンを切り出しても拡張ビットに「符号のゴミ」が残ってしまいHEX1ルーチンの中の比較処理CMP A,Bに影響を与えてしまったようです

 

HEX変換

原始モニタのコーディングができたのでこれをROMに焼き電源ONで起動するようにしました。これでテストプログラムをSRAM領域にDLLしては即試行できるので開発効率が飛躍的に向上します。まずは原始モニタ自身のコードをロードしてこれに機能拡張していくことにします。

最初にやりたいのはメモリダンプ機能で、これがあれば実行させるコードがメモリ上に正しく配置されていることを確認できます。いろいろなCPUで繰返し作ってきたレジデント型モニタで共通で出てくるBIN→HEX変換ルーチンはこのようになりました。24bitデータをHEX6桁に変換しますがDSP特有の命令:REP #nnをつかってハードウェア的にオーバヘッドなしで繰返しを記述できます

sim56000シミュレータでいくつかの数値が正しくHEX文字列に変換されるのを確かめてからモニタに組み込み、プログラム空間にある自分自身のコードをダンプしてみた例です

正しくHEX変換されているようです

 

 

 

 

シリアルワード受信

即値アドレッシングしている部分に「演算子を付けてロングワードであることを明示。入力されたコードをコマンドコード「P」「G」と比較して分岐する部分も同様に修正しこれでシリアル入出力とI/Fが一致してコマンド入力、分岐ができるようになりました

メインループはこれでいいのですが、実際に送られてきたデータをプログラムメモリに書き込むPLOADルーチンも修正が必要です

シリアルは8bit-1byte単位で受信されますがDSP56001はワードマシンなのでインデックスアドレスを1つ進めると24bit-3byte進んでしまいます。そのため1byteデータ3個を受信して左シフトして24bitレジスタに押し込めば良いのですが、ここはハードウェアでうまい仕組みがあり8bit受信レジスタSRXが上位(D23..D16)、中位(D15..D8)、下位(D7..D0)にエイリアスで見えます

 

なので1byte受信するたび24bit幅で3回読取ってORすれば1ワードデータが揃います。下位/中位/上位の順で送られてくるとして修正したPLOADルーチンはこうなりました