2015年07月14日の日記です


厄介なバグ  2015-07-14 16:47:55  業界記

ファイナルアーチの話の続きです。


完成間近になって、エージングが行われます。


エージングとは、長時間ほったらかしで止まらないことを確認する作業。

業務用ゲームって、1日中電源入っていますからね。止まるようではお話にならない。


…数日置いといたら止まりました。

画面真っ黒で、どこで止まったかもわからない。


数時間で止まるなら、まだ対策もできます。ビデオにとっておいたりして、止まる瞬間を捕まえられますから。

でも、「数日」というのが手におえない。


時間もないので、プログラマー全員で原因究明、となりました。


普段は僕は「他人の領域には手を出さない」ことにしているのですが、こういうときは別。

先輩方が作ったプログラムも、片っ端からチェックします。


しかし、情報が少なすぎてなかなか原因がわからない。


#他人の領域に手を出さないのは、大学の頃に読んだ新聞記事の影響。

 人の担当部分を見たら、バグの原因となりそうな処理があったので指摘したところ、相手のプライドを傷つけてしまい職場の人間関係にひびが…というような内容。

 そういうトラブルは起こしたくないので、基本的に人のプログラムは見ないことにしています。

 でも、バグ取りが「仕事」になれば、大義名分を得たことになるので他人の部分まで突っ込みます。




とにかく停止バグを捉えること、というので、一応ビデオも回しつつ、エージングを続けます。


すると、やっと停止の瞬間を捉えました。

デモ画面の途中、場面転換しようとした瞬間に停止しています。


メインプログラマー氏、その近辺の処理のプログラムを探し始めます。



それとは別に、ひたすらテストプレイも行われていました。

こちらでも、乱入したら停止した、という報告が。


えー、デモ画面と乱入した時では、全然違うことやってるよー。

全然違う個所なのに同じような停止バグを引き起こす。

原因のめどもつかず、一番厄介な状態です。




メインプログラマー氏は、自分のプログラムの何かがおかしいのだと考えて一生懸命チェックしています。

でも、僕としては、全然違う場所で同じようなバグが出るのだから、もっと深いルーチンがおかしいのではないか、と考えました。


でも、深いところにあるルーチンは、呼び出される頻度も高い。

なのにほとんど停止せず、ごくまれに停止するということは…



ヒントを求めて、ハードのバグなどの「追加仕様書」を片っ端から眺めます。

仕様書はプログラマーは全員手元にファイルを持っているのですが、後からの「追加」は、必要と思われるものだけがコピーされます。

完全版は、部内でファイルされたものが一冊あるだけ。



…怪しいものを発見しました。

追加仕様書に、サターンの CD用バッファから VRAM に向けて一定サイズ以上の DMA 転送を行ってはならない、という仕様がありました。


これ、ややこしい技術話ですが、面白いので書きます。


ST-V はサターンと同機能のボードです。

そして、サターンは3つのバスを持っていました


CPU のメインバス、VRAM やサウンドが接続された A バス、CD-ROM 等が接続された B バスです。


メインバスは、命令実行のために CPU に頻繁に使われます。

VRAM やサウンドは、画面や音楽の出力のため、画面出力回路に頻繁に使われます。

そして、CD-ROM などは低速デバイスなので、バスを占有しがちです。


これを1つのバスに混ぜていると、信号がぶつかり合って、頻繁に「待つ」ことになります。

なので、3つに分離した設計。


でも、3つのバスでのデータやり取りは必要ですから、System Control Unit (SCU)という LSI で接続されています。

SCU はバスの利用を引き受ける回路で、DMA 転送も担当していました。


DMA とは Direct Memory Access の意味で、CPU を使わずにメモリアクセスをすることです。

一般的に、ある程度のサイズの内容をコピーする機能(DMA 転送)として使われます。


DMA を使わないと VRAM にアクセスできない、という意味ではありません。

VRAM には CPU からアクセス可能なアドレスが割り振られ、直接操作することは可能でした。

それでないと、画面を作れませんから。


つまり、SCU は CPU バスに流れる信号を検知し、VRAM に流すべきであれば自動的に A バスに転送します。

しかし、そうでない場合は VDP と CPU のバスを切り離し、それぞれ頻繁にバスアクセスしても、問題を起こさないのです。

巧妙な設計でした。




ところで、CPU には RAM リフレッシュ機能がついています。

RAM はしばらくほおっておくと記憶内容を「忘れる」ので、それを防止する機能です。


命令しなくても、CPU が勝手に「古くなりそうな」RAM 内容を読出し、改めて書き込みます。

これで内容が「リフレッシュ」され、記憶が消えるのを防ぎます。


さて、本題。

SCU が DMA 転送を行っている間、SCU がバスを占有します。


A バス・B バス間の転送であれば CPU バスは無関係に思えますが、CPU からのアクセスは SCU がどのバスに流すべきか判断するため、アクセスが生じた時点で CPU も待たされることになります。


CPU は内蔵キャッシュがあるので、DMA 中も命令を読み込み、同時稼働することは可能でした。

…が、リフレッシュ機能は、外部アクセスを必要とします。



結果として、DMA 転送の時間、リフレッシュは待たされます。

余り期間が長いと、「消えそう」な RAM の読出しが間に合わず、実際消えてしまいます。


普通は十分に時間に余裕をもってリフレッシュするため、致命的にはなりません。

しかし、何百回に1回は、間に合わずに RAM が消えてしまうこともあります。


これが、追加仕様にあった「CD用バッファから VRAM に向けて一定サイズ以上の DMA 転送を行ってはならない」の真意でした。




追加仕様書の記述は「CD用バッファ」だったため、CD-ROM を使用しない ST-V では関係のない話、と思われていたようです。

この仕様は、誰も気にすることなく、部内のファイルに埋もれていました。


しかし、ST-V カートリッジも B バスに接続されるので、これは CD-ROM と同じ扱いです。

これが原因ではないかと考え、メインプログラマー氏に詳細を報告します。


ここで「禁止」されていたデータサイズは、CD-ROM を前提とするのであれば、あまり問題にならないサイズでした。

読み込みバッファ全部を使いきるようなサイズでの転送を行わないと、禁止事項に触れませんでしたから。


しかし、ST-V ではカートリッジを使い、このバッファよりずっと大きなメモリを転送できます。

そして、まさにそれをやっていました。VRAM 上のテクスチャを、全部一気に転送していたのです。


デモ中の画面転換シーン、乱入されたとき…停止した場所は、特に画面が急変するため、多くのテクスチャを送っているシーンでした。


メインプログラマー氏は、DMA 転送の指示を分割し、1回で転送していたのを 10回程度に分けるようにしました。

この程度であれば、速度の低下はほとんどありません。


そして、この後はエージングしてもバグは再発しませんでした。

どうやら、推察した通りの原因だったようです。



でも、こういうバグって、原因も「多分」だし、治ったかどうかも、確率問題だから確認しようがないんですよね。

締切も近かったので、本当にこれで正しいのか不安だった記憶があります。




同じテーマの日記(最近の一覧)

業界記

関連ページ

細かな話題

別年同日の日記

02年 お祝い

07年 最近のうちの子

10年 這えば立て 立てば歩めの…

13年 海水浴

16年 監視ユーザーの問題回避

19年 パスワードの管理方法(令和元年版)


申し訳ありませんが、現在意見投稿をできない状態にしています


戻る
トップページへ

-- share --

0000

-- follow --




- Reverse Link -