CPU実験室

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

メモリ構成

DSP56Kシリーズはオリジナルのモトローラからfreescaleに移管された後、それがNXPに吸収されても脈々と継承され直系のDSP563xxはまだ現行品のようです

マニュアルを見ながらシステム構成を考えてみました。まずメモリですがプログラムメモリ空間が64kbyte、データメモリ空間が64kbyte×2(Xメモリ,Yメモリ)存在するようです

 

これらのメモリの一部はオンチップでSRAMとしてあるので外付け無しのシングルチップ動作もできます。メモリ構成はモードの切替えで選ぶことができ、構成として一番簡単なのはブート用のROMのみ外付けし電源ON、RESET解除時にROM内容を内蔵プログラムメモリに転送して起動するMODE1でいけそうです

ブート用ROMは8ビット幅(ROM1個)でよく、これはADSP2101のブート方法と同じです。内蔵プログラムSRAM200H×24bitなので、ブートROMの容量は最大600H×8bit2048(800H)×8bit構成の2716で十分収まってしまします

 

 

〇〇K新プロジェクト

486、トランスピュータも動作を確認したところで放置冷却状態ですが、またまた別の石に目移りしてます。

68k→32k→29kと来たのでここでいよいよ56k(DSP56001)に出番が回ってきました。でもよく見るとこれは「XSP56001」ですね。モトローラの品番で先頭をXに置換するのは正式出荷前のエンジニアリングサンプルらしいので・・XC68040とか・・はたして動作するんでしょうか

 

固定小数点24ビットDSPで性能、内部構成ともアナデバのADSP2Kシリーズとよく似ています。プログラム、データ用のRAM、すでに係数が書き込まれたROMが内蔵されブート用のROMだけ外付けすれば単体で起動可能です。

コーデックは外付けが必要ですがホストインターフェースを兼ねたパラレルI/Fや汎用シリアルI/Fも備えられていてワンボード化が容易そうです。

 

パッケージは13×13の88ピンセラミックPGAですがそのピン配置が独特。何でそうなるのかと。

ちょっとこんなPGAソケット見たことがありません。もちろん十分ピン数のあるソケットで使用しないコンタクトは放置か抜けばいいのですが。


モトローラは大ヒットMC68030でも同じようなことやっていてこちらは13×13の128ピンです。MC68030は数が出たせいかこの配置のソケットは時々見かけます

同じ13×13なんでこれを見つけて追加工でいけるかも

プログラム配信(2)

リンクの下位に伝達していくたびにヘッダを取り除く方式はTCP/IPプロトコルスタックと同様ですがいざコーディングしようとするといろいろ問題があります

・階層の数だけローダを付加するので深い階層に送るペイロードほどサイズ大きくなる

・階層によりローダに与えるメモリアドレス、レングスのパラメータが変わるので同じローダが使えない

そこでこれを改善してみました。リンク下位に送るペイロードとして実行中のローダ自身含めメモリの先頭番地からそっくり複製②してしまいます。こうすることでローダは1種1個のみ、各階層での操作も同じになりリンク階層の深さにも制限がなくなります

ただしこれにも欠点があり最下層のトランスピュータはさらに下位にトランスピュータがあることを期待してプログラム転送をしようとしますが、無いものからは応答が無いのでそこでハングアップしてしまいます。これの対策としては最下層の下にリンク入力に対して無条件にACK応答を返す模擬的なノード・・リンクターミネータとでも言うもの、例えばリンクアダプタIMSC011を置けば良さそうです

 

といってもすぐにハードは用意できるわけではないのでここではネットワークプロトコルに倣いTime to Live(TTL変数を用意してみました。ここには初期値として階層数n-1をセット、次の階層に複製されるとき1づつ減算するようにしておき、TTL=0となった階層ではさらに下位への転送は禁止するという仕組みです

これらを具体的にコーディングしたローダはこのようになっています

先頭部分に0x100のエリアを空けているのはユーザアプリケーションを先頭部分にリロケーションするための隙間です。これがないと転送処理BLKMOVが自分自身をデータ上書きして破壊してしまいます

このローダをTTL初期値=1としてtransputer1ボード上で実行させるとtransputer1transputer2の両方で同じユーザアプリケーション(LEDチカチカ)が実行されました。

ただしボードが2枚しかないのでn≧2での検証はできてません

 

プログラム配信

リンクの上位側にあるトランスピュータが下位のトランスピュータにプログラムを送信してブートさせることができましたが、さらに下位のリンクがある場合、最初に送信するプログラムにローダを含めて入れ子構造にしておかなければなりません

こうなると上位側のトランスピュータはプログラムの送信と管理に専念することになり主従関係が生まれてしまうということと、各層のトランスピュータが持つプログラムが異なってしまい「並列」という意味ではエレガントではありません

そこでこのような構造を考えてみました。各層のトランスピュータで共通で実行させたいアプリケーション(executable code)に転送したいレイヤーの数だけ同一のローダを先頭にくっつけておきます。これを先頭から実行①すると自身を除くコードを下位のトランスピュータへ転送②、その後アプリケーションのコードブロックを先頭番地に移動③させ改めて先頭から再実行④させます。

下位のトランスピュータでも同一の処理が行われますが下位レイヤーに転送されるたびヘッダにあるローダが1個ずつ減って行き、最下位では先頭番地から直にアプリケーションになるので結果的にすべてのレイヤーで同一のアプリケーションが実行されていることになります

ブート処理(3)

もうひとつPRGDLLというサブルーチンを作っておきました。これはリンク先のボードへバイナリコードを指定バイト分POKEコマンドを使って転送します。

これらを組み立てたブート処理の流れです。まず別途アセンブルしておいたアプリケーションプログラム:LEDチカチカのバイナリをベタでソースコードに埋め込んでおきます。その先頭アドレスAPL_CODEとバイト長104を引数にPRGDLLを呼ぶとリンク先ボードの0x00000000番地以降にアプリケーションのコードがセットされ、続いてBOOTを呼ぶとそのコードが実行されます

 

このコード全体をTransputer1上のモニタでロード実行させるとMSG0"LOAD"、MSG1"BOOT"の文字列を出力して直ちにモニタプロンプトに戻ってきますが、一切手を触れていないTransputer2上でLEDチカチカが実行されているのがわかります

 

ブート処理(2)

リンク先のボードをブートするコードはこうなります。

まず制御コード1バイト:BOOT_CMDの内容はジャンプコード(J 0x00000000)の長さ8バイトを示す0x08を送り、その後ジャンプコードの実体が続きます

では実際に動作させるユーザアプリケーションの方はというと。これは何でも良いのですがCPUが正常に動いていることがわかるようにパラレルLEDにインクリメントデータを出力してチカチカさせるものを用意しました。単純ループだとLEDの点滅が速すぎて動いているかわかりません。16bitカウントアップするwaitloopで時間稼ぎして目視できるチカチカとしました。

このコードはロードアドレスを0x00000000からとしているので、このままROMモニタで直接DLLしても動作します。

モニタから動作させる場合には既にモニタが起動しているので、内部/外部レジスタ等の初期化処理も行われていてユーザプログラムはその環境を継承しますが、リンク先で起動する場合はそれらの初期化処理を経ずにダイレクトに起動しようとします。

たとえばシリアル出力処理を挿入したら全然キャラクタ送出が行われず送信完了フラグ待ちでロックしてしまうのがなかなか理由がわからなかったのですが、これは単純にシリアルコントローラの初期化が行われていなかったからでした。ただしROMからブートしていなくてもメモリマップ上にROMは見えるのでROM内ルーチンを呼ぶことは可能です

ブート処理

リンク先ボードのメモリに読み書きができたので今度はそのボード上でプログラムの実行を指示する必要があります。

リセット後最初に受け取る制御コードが0x00のときはPOKE0x01のときはPEEKでしたが1より大きい(2以上)ときは続くコードを制御コードの数だけMemStart(=0x8000070番地)からセットして先頭から実行するとあります

ということはブートのために転送できるプログラムは255byte以下に制限されてしまう・・となりそうですが本当に実行させたいユーザプログラムの本体はPOKEコマンドでボード上の任意のアドレスにあらかじめ転送しておき(メモリ上限までサイズは制限なし)、ブート用プログラムはユーザプログラムの先頭番地に飛ぶだけのものにしておけばOKそうです

具体的なメモリマップはこのようにしました。

先ず①DLLではPOKEコマンドを使ってtransputer2ボード上の外付けメモリの先頭番地0x00000000からユーザプログラムを転送しておきます。次に②BOOT0x80000070番地から0x00000000番地にジャンプするコード列を転送、転送完了と同時に自動的にコード③JUMPが実行されてユーザプログラムの先頭に制御が移ります

もちろんユーザプログラムの格納場所をオンチップRAMにしておけば外付けRAMも必要なくなりCPUだけがびっしり並んだボードも実現できますが、プログラムが4kB以下に制限されることとリロケーションアドレスを0x00000000にしておけばROMモニタでロードするバイナリと共用できるメリットもあります

ブート処理を組み立てるためにまず「J 0x00000000」のコードをアセンブルしておきます。「0x27,0x2f,0x2f,0x2f,0x2f,0x2f,0x28,0x08」の8バイトのコードが得られました

一気に約2GBの空間を跳躍するのでオフセットが大きくなります