Commodore 64ハードウェアシミュレータ:チップやピンを壊し、結果を見る
The Commodore 64 hardware simulator: break chips and pins, see the results (github.com)
要約
Commodore 64のマザーボードをピンレベルでシミュレートする「c64-hw-sim」は、チップの足を外したり、ショートさせたり、ソケットから抜いたりすることで、ハードウェアの故障がどのように影響するかを視覚的に確認できるツールです。これにより、実機を破損させるリスクなく、C64の動作原理を深く学んだり、故障診断の手がかりを得たりすることができます。ただし、シミュレーション速度は実機より遅いです。
全文翻訳
Commodore 64
c64-hw-sim
c64-hw-simは、Commodore 64(ASSY 250407)とZX Spectrum 48K(ボードIssue 3B)のマザーボードをピンごとにシミュレートします。チップの足を浮かせたり、グランドや+5Vにショートさせたり、ソケットからチップを引き抜いたり、抵抗を開いたりすることができます。その後、マシンがどのように動作するかを観察します:モニターの映像、キーボード、ボード上のあらゆる信号です。
プログラムはボードのネットリスト(PCB上の電気的接続)と、各チップがピンでどのように振る舞うかを知っています。壊れたCommodore 64やSpectrumがどのように見えるかについては何も知りません。壊れた部品をシミュレートして画面がゴミでいっぱいになった場合、そのゴミは回路から計算されたものであり、誰かが期待されるものを知っていて選んだものではありません。
例を挙げましょう。電源投入前にC64のカラーRAMのピン17(A7)を浮かせると、マシンは起動し、正常に見えます。CPUは同じ間違ったアドレスで書き込み、VICは読み取るため、RAMは単にエイリアスされます。足を元に戻すと、書き込まれなかったカラーRAMの半分がランダムな色で表示されます。もう一度浮かせると、画面はきれいになります。実際の2114も同様の動作をします。
このプログラムでは、主に2つのことができます:
- Commodore 64とSpectrumが、実際のハードウェアを損傷するリスクなし(そしてほとんどのボードでは多くのチップがハンダ付けされており、ソケット式ではない)に再現するのが難しい方法で、より深いレベルでどのように動作するかを学びます。
- 壊れたC64やSpectrumを持っていて、何が壊れているかについての仮説がある場合、このプログラムでシミュレートし、手がかりを得て、最も論理的な順序でチップをハンダ吸い取りし、できるだけ少なくハンダ吸い取りできるようにします(ハンダ吸い取りは退屈なプロセスであり、毎回ボードを損傷するリスクがあります…)。一致する症状は手がかりであって証明ではありません:異なる故障が同じように見えることがあり、シミュレーションには限界があります(下記参照)。
高速なコンピューターであっても、このプログラムはこれらのマシンを実速でシミュレートするのに苦労することに注意してください。実際のC64は、Apple M3 Maxで31%、AMD Ryzen AI Max+ PRO 495(Gorgon Halo)で39%、Apple M5 Maxで48%の速度でシミュレートされます。ZX Spectrumは、同じコンピューターでそれぞれ23%、28%、34%の速度でシミュレートされます。これはプログラムの目標には問題ありませんが、注意してください:ゲームをプレイするためのエミュレータではありません。
なぜSpectrumはC64よりもシミュレートが遅いのでしょうか?ボードはよりシンプルなのに?それは時間分解能のためです。ULAは非常に低いレベルでシミュレートされるため、バスの競合はシミュレーションから自然に発生します。その信号は14MHzオシレータの半周期にタイミングが合っているため、ボード全体がシミュレートされた毎秒2800万回(C64は約600万回)で安定します。
[画像: BASICプログラム実行中にキャラクターROMを引き抜き、その後戻す]
上:クラシックなC64の10 PRINT CHR$(205.5+RND(1));:GOTO 10迷路が、キャラクターROM(U5)がソケットから引き抜かれ、その後戻されたときに実行されています。CPU、RAM、プログラムは動作し続けますが、文字の形状だけが失われます。これは修理業者によく知られています。スコープはROMソケットのデータラインD0にあります。ソケットが空のとき、VICが文字形状を取得するたびにバスはフローティング(点線部分)します。C64速度で表示されます。
Acknowledgements
私(antirez)はこのプログラムのアイデアを、Andre Weissflog(floooh)のチップ、6502、VIC-II、CIA、SIDなどのエミュレータを使用・観察しているときに得ました。これらはピンをインターフェースとして使用します。次のステップは、彼のコードを出発点として、このアプローチを論理的な極限まで推し進めることでした:C64の他のすべての部分、RAM、ROM、ロジックチップ、PLAなどのピンレベルモデルです。
チップコアはflooohのチップで、c64-llm(zlibライセンス)から取得しました。ボードはbwackのC64-250407-Replica-KiCad(CERN OHL)のものです。PLAの数式は、Mark SmithとMarko Mäkeläによって読み出された82S100のものです。
ZX Spectrumについては、Z80はflooohのもので、クロックのエッジで動作するように変更されています。ボードはliveboxandyのKiCadファイルIssue 3Bのもので、PABBのガーバー(CC0)から再描画されました。ULAモデルは、emu-russia/ulaプロジェクト(CC0)によってダイから復元された6C001のゲートネットリストに対してチェックされています。ROMはAmstradのもので、配布が許可されています。ZX Spectrum Diagnostics ROMはBrendan Alfordとその貢献者(LGPL)のものです。
Building
make
./c64-hw-sim [program.prg]
macOS、Linux(X11)、Windows(OpenGL)で動作します。Windowsでは、POSIXシェル(Git BashまたはMSYS2)からMinGW-w64 gccでビルドし(例:mingw32-make)、c64-hw-sim.exeを実行します。グラフィックライブラリ(sokol)とインターフェースライブラリ(nuklear)はthird_party/にあります。
Using it
ウィンドウには、ボード、モニター、コントロールパネル、オシロスコープが表示されます。コントロールパネル上部の2つのボタンでCommodore 64とZX Spectrum 48Kを切り替えます。実行中のマシンはオフになり、もう一方がオンになります。
ピンはロジックプローブのように状態を示します:赤はハイ、青はロー、黄色はパルス、グレーはフローティング、マゼンタは2つの出力が競合している状態です。ズームインすると、チップにリファレンス、アドレス範囲、ピン番号が表示されます。さらにズームインすると、ロジックチップにはゲート、それ以外のチップにはピン名が表示されます。ピンにカーソルを合わせると、それが何であるかがわかります(コネクタピンには機能が表示されます:「CN4.3 ATN (SERIAL)」)。
ピンをクリックするとオシロスコープに表示され、壊すことができます:フローティング、GNDへのショート、または+5Vへのショート。チップをクリックすると引き抜いたり、検査したりできます。抵抗、フェライトビーズ、クリスタルをクリックすると開くことができます。コントロールパネルには故障リストが表示され、それぞれに修理ボタンがあります。
インスペクタはチップをデータシートのように大きく描画します:ピンは番号付けされ色付けされ、ネットは外側に、ゲートは内側に配線されています。ワイヤーはそれに何が載っているかを示し、ゲートの出力はそのゲート自体が駆動しているものを示します。したがって、ネットをローに保つネットにハイを駆動しているゲートは一目でわかります。
開く(Ctrl+O、MacではCmd+O)とファイルブラウザが表示され、carts/から始まります。実行中のマシンが使用するフォルダとファイルが表示され、ヘッダーから各ファイルが何であるか、またはなぜ使用できないかがわかります。タイプしてリストを絞り込むか、パスを入力してEnterキーを押すと移動します。矢印キーとEnterキー、またはダブルクリックでファイルを開きます。バックスペースで上に移動します。Escで閉じます。最近使ったファイルはコントロールパネルに1クリックでアクセスできるようになり、ファイルウィンドウにドラッグ&ドロップすることもできます。
チップは役割名で示されるボックスです:
- RAM1からRAM8は4164 DRAMです。それぞれが各バイトの1ビットを保持します:RAMnはデータビットn-1を持ちます。
- VRAMは2114カラーRAMです。
- BASIC、KERNAL、CHARはROMです。
- PLAはアドレスデコーダです。
インスペクタでは、7406の出力マークはオープンコレクタトランジスタです:ラインをローにプルしている間は青、オフでプルアップが決まる間はグレーです。PLAについては、インスペクタはプロダクトタームをリストし、それらが真の間は点灯し、各入力はレベルで色付けされます:どのタームが何を選択し、どの入力がタームの発火を防いでいるかがわかります。
RESETはリセットカートリッジのように機能します:ユーザーポートの/RESETをGNDにショートさせます。それを保持するか、リセット状態でボードを見るために押し続けます。CPU、CIA、SIDはリセットされますが、リセットピンのないVICやRAMはリセットされません。Power cycleはC64の電源をオフにしてからオンに戻します。
プログラム(.prg)はロードされ、RUNされます。Shift+Enterでロードのみも可能です。ブラウザは、それがBASICかマシンコードか、そしてそのアドレスを示します。これらはDRAMチップに直接書き込まれるため、フリーザーカートリッジと同様です。これにより、壊れたボードでもロードが機能します。
カートリッジ(.crt)は拡張ポートに挿入されます(C64の電源はオフにしてからオンにします)。ブラウザはカートリッジの種類と名前を表示します。プレーンなものはサポートされており、8K、16K、Ultimax(診断カートリッジがこれです):Dead TestはKERNALを置き換え、デッドRAMまたはROMのボードで動作します。カートリッジは拡張ポートピンのみを駆動し、他はすべてボードのものです。ポートの接触不良はCN6ピンの故障です。
Dead Testは、そのマニュアルに従ってフラッシュコードを示します(U12、ビット7に1フラッシュ、U21、ビット0に最大8フラッシュ)。診断586220カートリッジの場合、テストハーネス、ユーザーポート、カセットポート、シリアルポート、両方のコントロールポート、キーボード(Sven Petersenによって構築されたCommodoreのオープンハードウェアコピー)をループバックするドングルを接続できます。これにより、正常なボードはすべてのテストに合格し、壊れた接触、チップ、またはクロックは、Commodoreのマニュアルが示す場所を示します。両方のカートリッジはcarts/にあります(これらはCommodoreのもので、carts/LICENSEを参照してください)。
キーボードは通常通りタイプしてください。ESCはRUN/STOP、PgUpはRESTORE、TABはCTRL、左ALTはC=です。
ZX Spectrum 48K
--machine zx48でSpectrumが起動し、コマンドラインでスナップショットまたはROMを指定した場合も同様です。
ボードはIssue 3Bです。チップは以下の通りです:
- ULAはFerranti 6C001です。映像を作成し、CPUクロックを生成し、下位RAMのRASとCASを駆動し、ポート0xFE(キーボード、ボーダー、MIC、EAR)を担当します。
- CPUはZ80A、ROMは23128です。
- LRAM0からLRAM7は下位16Kの4116 DRAMで、画面が表示されます。LRAMnはデータビットnを持ちます。
- URAM0からURAM7は上位32Kの4532です:片方の半分が不良な64Kチップです。隣接するリンクはボードにどちらの半分が良好かを示します。ここではTIチップが使用されています。
- MUXは74LS157アドレスマルチプレクサです。ORとNAND、74LS32と74LS00が、上位RAMを選択し、2つのRC遅延とともにそのRASとCASのタイミングを取ります。
- PALはLM1889ビデオモジュレータです。アナログであり、シミュレートされていない唯一のチップです:モニターはULAの映像を表示します。
CPUとULAは下位16Kを共有しており、これがSpectrumをピンレベルで興味深いものにしています。それらは抵抗の列の両側に位置しています:データバスには470オーム、マルチプレクサの後にはアドレスラインに330オームです。両方がバスを駆動するとき、各側は自身の値を見ます。CPUが下位16Kを必要とし、ULAが画面を取得するとき、ULAはCPUのクロックを停止します:有名なコンテンション(競合)です。ここでは、遅延テーブルによるのではなく、ULAがクロックピンを保持することによって発生します。シミュレートされたボードでは、遅延は実際のマシンから知られている6,5,4,3,2,1,0,0パターンに従います。最初の競合Tステートは、/INTが低下してから14337 Tステート後に発生します。エミュレータは、それ自身のフレーム開始から数えて、14335または14336に配置します。
キー:ESCはBREAK、TABはSYMBOL SHIFT、左SHIFTはCAPS SHIFTです。RESETはエッジコネクタの/RESETをGNDにショートさせます。開くは48Kスナップショット(.sna、.z80)をロードします:これらはC64プログラムのようにDRAMチップに直接書き込まれます。16K ROM(.rom)はROMカートリッジのようにエッジコネクタに挿入されます:/ROMCSをハイに保ち、内部ROMの代わりに応答します。ZX Spectrum Diagnostics ROMはcarts/にあります(LGPL)。正常なボードではテストに合格し、壊れたボードでは見つかったものを報告します。
電源は、その動作によってモデル化されています。7805は+5Vを生成します。DC-DCコンバータ(TR4、TR5、コイルT1)は+12Vを生成し、そのチャージポンプは-5Vを生成します。4116はすべてを必要とします:TR4、または-5VポンプのD12を壊すと、下位RAMが動作しなくなります。クリスタルX1がないと、クロックはまったく発生しません。
tests/zx-faults.shは一般的な13の故障を実行します。C64と同様に、各故障の期待される症状はシミュレータを実行する前に書き留められました。下位RAMチップがないと、ROMのRAMテストパターンが画面に表示され、上位RAMチップがないと16K Spectrumになります。tests/zx-diag.shは、正常なボードと不良RAMチップでDiagnostics ROMを実行します:マニュアルが示す場所で、失敗したデータビット(したがってチップ)を見つけます。
The ULA
ULAはエミュレータコアではありません:それはピンレベルのモデルであり、14MHzオシレータの分解能で動作します。各半周期で、/RAS、/CAS、アドレスピン、CPUクロック、/INT、ポート読み取り時にデータバスに置くもの、ピクセルの色を決定します。そのロジックとタイミングはダイから来ています:emu-russia/ulaプロジェクトは6C001のネットリスト、661個のNORゲートを復元しました。
tools/ulacheck.cはモデルを正確に保ちます。シミュレータは各半周期でULAが入力ピンで見たものをログに記録し(ZXHW_ULALOG=file)、チェッカーは同じ入力で661個のゲートを実行します。その後、各出力、各半周期、および各ピクセルの色を比較します。これはSpectrumの起動時、ROMのエディタ、およびボーダー色を可能な限り速く変更するBASICプログラムで実行されました。3つの文書化された簡略化があり、src/ula.cの先頭にリストされていますが、ボード上のチップには影響しません。それらを除けば、すべての出力とすべてのピクセルは同じです。ゲートはまた、新しいボーダー色は次の8ピクセル境界からのみ表示されるという詳細を教えてくれました。これは、属性と同じラッチを通過するためです。ネットリストはこのリポジトリにはありません。tools/ulacheck.cで取得場所が示されています。
The Z80
flooohのZ80は、呼び出しごとに1 Tステートを実行し、エミュレータに適したときにピンを出力します。ULAはより多くの情報が必要です:Tステートの右半分でアドレスと/MREQを調べてクロックを停止するかどうかを決定し、どちらのフェーズでもクロックを停止できます。そのため、chips/z80.hは現在、クロックの各エッジでステップされ、そのピンはZilogのタイミング図に従います。その命令、フラグ、タイミングは元のコアのものです。tests/z80にはテストがあります:すべての種類のバスサイクルのピン波形、およびZEXDOCとZEXALLです。chips/codegenにはコードジェネレータがあります。
Command line
./c64-hw-sim --headless 200 --text --shot out.png --fault U17:removed
これはウィンドウなしで4秒間(200フレーム)実行されます。モニター画像から読み取ったテキストを人間が読むように表示し、画像を保存します。故障はREF:whatまたはREF.PIN:whatと記述されます:
U17:removed U21.14:gnd U12.14:vcc U9.2:open CN6.B:open RP4:short
コマンドラインで与えられた.crtファイルは電源投入前に挿入され、--harnessは586220テストハーネスを接続します。
その他のオプション:
--at 150:U6.17:open --at 300:repairは、C64実行中に部品を壊したり修理したりします。RESET:pressedとRESET:releasedもここで機能します。--machine zx48はZX Spectrumを実行します。故障仕様はその参照を使用します(IC10:removed,D12:open,TI-3:open)。--netsは出力が競合したネットを報告します。C64HW_TYPE=$'PRINT 1+1\n'は起動後にテキストを入力します。ZXHW_ULALOG=file[:cycle]はULAのピンをtools/ulacheck.c用にログ記録します。ZXHW_CONTENTION=1は競合したTステートとその遅延をすべて表示します。ZXHW_TRACE=FROM:COUNTはTステートFROMからCOUNT Tステートまでの各半周期でバスを表示します。C64HW_CHECK=1は、すべてのKERNAL読み取りとすべてのVICフェッチを理想的なメモリマップに対してチェックします。--record 900:DIR --frames 90(グラフィカルモード)は、フレーム900から4エミュレートフレームごとにウィンドウを90回保存します。これが上記のGIFが作成された方法です。--inspect U8,--browse,--view X,Y,ZOOM,--mouse X,Y,--down X,Y@F,--up X,Y@F,--key NAME@F,--chars TEXT@F(グラフィカルモード)は、スクリーンショットやインターフェースのテストのために、インスペクタまたはファイルブラウザを開き、ボードビューをターゲットにし、UIフレームFでマウスをクリックし、キーを押します。
tests/faults.shは一般的な31の故障を実行します。各故障の期待される症状は、シミュレータを実行する前に書き留められました。
tests/diag.shは診断カートリッジを実行し、それらが報告する内容をマニュアルと比較します:DRAMごとのDead Testのフラッシュコード、ハーネス付きの正常なボードと故障時の586220。これには数分かかるため、開始時のみ実行されます。--flashes(ヘッドレス)はDead Testのフラッシュシリーズをカウントします。
How it works
tools/kicad2c.pyは、bwackの250407のKiCadレプリカをCテーブルに変換します:216個の部品、それらのパッド、249個のネットです。SpectrumのIssue 3Bについても同様です。
各ピンは、そのネットを強く、弱く(プルアップ)、電源ショート、またはまったく駆動しません。最も強い駆動が勝ちます。2つの等しい駆動が競合すると、コンテンションが発生し、ローが勝ちます。
誰も駆動しないネットは電荷を保持し、その後ドリフトします:
- TTL入力がロードする場合、マイクロ秒以内に約1.4Vにドリフトします。
- MOS入力のみが接続されている場合、数秒以内に0Vに向かってドリフトします。
MOS入力は、その電圧にいくらかのノイズを加えたものを自身の閾値と比較するため、フローティングラインは不安定に読み取られる可能性があります。
電源の故障はチップに依存します:
- VCCがないチップは動作しません。
- GNDがないチップは、出力がハイにフローティングします。
- CMOSチップは、ピンの保護ダイオードを通じて到達するファントム電源で動作し続けます。
ノイズはシードされており、実行は正確に繰り返すことができます。
src/parts.cはこれらの部品をピンレベルでモデル化します:
- グルーロジック;
- ROM;
- DRAM(/RASでロウアドレスを、/CASでカラムアドレスをラッチします);
- カラーRAM;
- PLA、その実際のロジック方程式付き。
6510、VIC-II、CIA、SIDはflooohのチップからのサイクルアキュレートコアで、いくつかの追加機能があります(ヘッダーにマークされています):CIAの時刻クロック、シリアルポート、/PCハンドシェイク、SIDのパドルレジスタ。src/board.cでは、各コアはピンのみを見るソケットに配置されています。各半サイクルは3つのステップで実行されます:ロウアドレス、次に/RASの低下、次に/CASの低下です。ボード全体は各ステップ後に安定します。
Spectrumでは、すべてがULAのオシレータによってタイミングが取られています:ボードは、CPU Tステートあたり8回、その半周期ごとに安定します。ULAがステップし、ボードが安定し、Z80がクロックのエッジ(もしあれば)を受け取ります。その後、メモリはストローブを認識し、ボードは再び安定します。
PLAN.mdはこれらの選択の背後にある理由を説明しています。
Limits
上記コンピューターでは、リアルタイムの3分の1から半分(Spectrumでは5分の1から3分の1)と遅いため、すべてのチップのすべてのピンがシミュレートされています。
フローティングと電源モデルは正しい形状をしていますが、その数値(閾値、ドリフト時間、クロストーク)は推測です。これらはsrc/sim.cの定数です。
これらのアナログ部品はシミュレートされていません:ビデオ出力、SIDフィルター、電源、ドットクロックPLL。Spectrumでは:ビデオモジュレータ、サウンド、テープ入力。それらのうち3つは、ロジックがそれらに依存するため、その動作によってモデル化されています:時刻クロックを駆動する mains からの50Hz、カセットモータードライバー、SIDのパドルA/Dコンバータ(1800pFコンデンサがパドルを介して充電される時間)。
チップ内の故障、例えば不良DRAMセルや遅い部品、2つのネット間のブリッジは計画されていますが、まだ実装されていません。