Phosphoric › 記事 › Phosphoric 2.0
Phosphoric 2.0:サイクル駆動のマシン — そして撤回する主張
私たちが言っていたことと、それがなぜ誤りだったか、V2 が何を変えたか、目に見えて何が変わるか — そして今も主張しないこと。
1.120.0-alpha まで、Phosphoric は自らを「cycle-accurate」と称していました。参照エミュレータがこの語に与える意味では、それは真実ではありませんでした。この記事は、何を撤回し、代わりに何を作り、主張がどこで止まるかを述べます。テストとオプションの名前はリポジトリのものです。
1. 私たちが言っていたこと、そしてなぜ誤りだったか
6502 コアは命令をひとまとまりで実行していました:バスアクセスは正しい順序で出力され、オペコードごとのサイクル合計も正しかったものの、内部サイクルは命令の最後に詰め物で帳尻を合わせ、NMOS のダミーアクセスは存在せず、割り込みは命令境界で受け付けられていました。VIA はまとまったサイクルを受け取り、ULA は 1 行を一度に描画し、PSG はオーディオのサンプリングレートで動いていました。
これは立派な水準です — 私たちはこれを N2「バスサイクル順序付き」と名付けました — が、「サイクル完全一致」ではありません。私たちはこの表現を撤回し、検証可能な尺度(docs/ACCURACY.md:N1 から N4、各レベルはそれを証明するテストに裏付けられる)と、ショーケース文書内の限定なしの「cycle-accurate」を拒否する自動ガード(make test-docs-claims)を書きました。そして V2 を作りました。
| レベル | 名称 | 運用上の定義 |
|---|---|---|
| N1 | 命令単位でカウント | オペコードごとのサイクル合計は正確;周辺機器は命令の後にまとめて進む。 |
| N2 | バスサイクル順序付き | 実際の各バスアクセスは命令内の正しいサイクルに落ちる;内部サイクルは命令の最後で帳尻合わせ;IRQ は命令境界。 |
| N3 | サイクル逐次 | マシンの進行単位はサイクル:1 サイクルに 1 つのバス動作(ダミーアクセス含む)、周辺機器は同期して進む;IRQ/NMI は最後から 2 番目のサイクル。 |
| N4 | サブサイクル(φ1/φ2) | サイクルが細分化され、ボードとバス間の setup/hold レースがモデル化される。 |
2. V2 が変えたこと
まずオラクル
コアに手を付ける前に、make test-cycle が SingleStepTests/65x02 のベクタ — オペコードあたり 10 000 ケース、サイクルごとの期待バストレース付き — を再生し、4 つの特性(最終状態、サイクル合計、バス部分列、完全なバス列)を別々に採点します。測定され公開された出発点:バス列完全一致 44.26 %。オラクルはさらにコアの論理的欠陥を 5 件明らかにし、着手前に修正されました。
マイクロシーケンス化されたコア
各命令は 1 サイクル 1 つのマイクロ操作の計画となり、それぞれが正確にそのバスアクセスを行います — ダミーアクセス(ゼロページインデックス、ページ跨ぎ、RMW の書き戻し、無効なスタック読み出し)を含めて。結果:2 440 000 ケースで 100.00 %。割り込みは最後から 2 番目のサイクルでサンプリングされ、CLI/SEI/PLP 後の I フラグ遅延と NMI による BRK の横取りが自然に得られます。両コアは同じ計算(フラグ、BCD、非公式オペコード)を共有し、シーケンスのみが異なります。旧コアは引き続き利用可能です(--cpu-legacy)。
マスタークロック
emu_cycle() はマシン全体を固定の順序で 1 サイクル進めます:CPU がバスアクセスを行い、周辺機器が 1 サイクル進み — 決してまとめてではなく —、次に ULA が同じサイクルのセルをフェッチします。これは Mike Brown がハードウェア上で測定した順序です;2.0.1 までは ULA が先で、各スプリットは 1 セル右にずれていました。メインループはもう何も計算しません:要求するだけです。
コンポーネント、ひとつずつ
- VIA 6522:サイクル単位で数える;Timer 1 は周期 N+2 を取り戻した(旧モデルは N:N=10 で 20 % の誤差)。
- ULA:ビームが読む瞬間に 1 サイクルあたり 6 ピクセルのセル 1 つをフェッチ — 行の途中の書き込みはまだ走査されていないセルにのみ届き、ラスタースプリットが可能になる。
- PSG AY-3-8910:クロック/8(125 kHz)で動き、出力は積分される — ナイキストを超えて設定されたトーンは折り返さず減衰;ずっと 2 倍遅かったエンベロープが正しい速度に;アナログ出力段は公式回路図から採取。
- WD1793:
LOST DATAと書き込み保護を通知。 - 信号レベルのカセット:フレームパリティは偶数ではなく奇数。
3. 目に見えて変わること
- ラスタースプリット:行の途中でインクやモードを変えるプログラムは、均一な行ではなくハードウェアが出す結果を得る。
- 音:正しい長さのエンベロープ、非常に高いトーンでの幽霊のような笛音が消え、中心化された信号(基板と同様に直流遮断)。
- IRQ:割り込みは実行中の命令の前には受け付けられない;
SEIは既に保留中の IRQ から次の命令を守らない。 - 破壊読み出しレジスタ:BASIC の
POKEを ACIA のデータレジスタに行うと1 バイト失われる。STA (zp),Yは書き込み前にダミー読み出しを行うため — エミュレータでも実機でも。Phosphoric はハードウェアより寛容でしたが、もうそうではありません。 - セーブステート:フレームの途中で取得した状態は止まった正確な場所から再開する(ビーム位置、タイマー、割り込みサンプル)。
4. 道中で学んだこと
2 つの欠陥は、方法を変えなければ決して見つからなかったでしょう。
PSG のエンベロープは「再計算により」適合と宣言されていました — 32 状態ではなく 16 状態を前提とした再計算です。誤った仮定は読み返しても見えず、信号を測定して初めて見えます。オーディオテストは今ではバイトを比較する代わりに周波数と長さを測定します。
2 つ目はさらに示唆的です。非分岐の分岐命令は、バスアクセスのないマイクロ操作の中で1 サイクル遅れて判断していました。CPU のカウンタは正しいままだったので、オラクルは 100 % グリーンでした。しかしマスタークロックは 1 回余計に呼ばれていました:ULA は CPU も VIA も経験していないサイクルを進んでいたのです — BASIC ROM 上でフレームあたり約 410 回、つまり画像とマシンの残りの間で毎秒 1 フレームのずれ。CPU しか見ないオラクルはマシンの同期を証明しません。それを明らかにしたのは、ラスター停止が正確に同じサイクルに落ちることを要求するセーブステートの決定性テストでした。
5. 言わないこと
「Phosphoric はサイクル完全一致である」— いいえ。FDC は依然として平坦なイメージ上の固定遅延で駆動されます(MFM ストリームなし、よって本当のバイト損失も CRC もなし)。一方、水平方向の基準はもう慣例ではありません:(測定された)ULA のカウンタは桁 0 をカウント 0 に置きます — しかしそのカウンタと CPU の絶対位相は、実機 ORIC では私たちがエミュレートしていない「VSYNC hack」でしか観測できません。VIA ワンショットの半サイクルは表現されていません。既定のカセット読み込みは選択として ROM パッチのままです:同じ内容を読み込み、サイクルは 2.4 分の 1。
許容される正確な表現と、その各行を反証しうるテストは docs/ACCURACY.md にあります。
6. コスト
サイクルへの移行は、参照マシンのフルスピードで、エミュレートされたフレームあたり 491 → 611 µs:20 ms 予算の 3 %。make test-bench は今では 5 % を超える超過を拒否します。
7. 2.0.0 以降
- 2.0.1 — WebAssembly ビルドを修復(macOS 移植以降壊れていた)、オンラインページを 2.0 で再構築。
- 2.0.2 — Mike Brown の Unofficial ULA Guide に基づきサイクル内の CPU/ULA 順序を修正:6502 が先にアクセスし、ULA が次に同じカウントをフェッチ;各ラスタースプリットは 1 セル(6 ピクセル)右にずれていた。「水平基準が未較正」という留保は解消。
- 2.0.3 — メインループを名前付きの段階に分割(1 296 → 126 行)、目に見える変更なし。
- 2.0.4 — LOCI 協調シミュレーション:F8 ボタンの所有者は 1 つ(協調シミュレートされたファームウェア)のみ;長押し = Mike Brown の診断 ROM。
テストスイート:60 スイート 1 208 テスト、100 % グリーン;タグでの自動リリース(Linux バイナリ、Windows zip);ブラウザ版をオンラインで公開。
出典とリンク
- Phosphoric リポジトリ: Codeberg · Framagit · GitHub
- 精度の尺度とコンポーネントごとの状況: docs/ACCURACY.md
- 元の技術ノート(フランス語): docs/articles/v2-cycle-stepped.md
- 6502 オラクル:SingleStepTests/65x02;Klaus Dormann の機能テスト。
- Mike Brown, ORIC 1/ATMOS Unofficial ULA Guide: oric.free.fr · oric.signal11.org.uk
- オンラインで試す:WebAssembly 版