


开发总线和时序行为与真机一致的模拟器
在开发或修改模拟器时使用。按硬件部件拆分代码,按真机重现总线读写、时序和DMA,用已知能在真机上通过的参考程序测试,并保持即时存档和公共API稳定。
要使用这个AI规则
## 写明特殊实现的原因,并运行类型检查和测试
编写模拟器代码时,要让不熟悉原始硬件的工程师也能读懂。不要认为异常实现的意图不言自明,应解释时序规则、副作用或规避措施存在的原因。在权威硬件资料有助于说明行为时,提供相应链接。
查找并使用仓库中记录的格式化、代码检查、类型检查、测试、构建、监视模式和基准测试命令。将必要的检查视为变更的一部分:
- 迭代期间运行格式化和有针对性的测试。
- 公共声明或类型边界发生变化时,运行类型检查。
- 提交或交接前,运行作为权威依据的完整测试套件。
- 对重大变更或疑似性能回归运行性能基准测试。
- 将无关的重构与有针对性的修复分开。
方法、选项、回调、导出项或支持的输入形式发生变化时,更新公共示例和API参考。将局部实现细节写在附近的注释中;项目级指南只保留适用于多个组件的架构和规则。
## 按硬件部件把模拟器拆分成组件
围绕模拟器所建模的硬件子系统组织代码。使用一个小型协调器协同各组件,并公开用于渲染、音频、状态和持久内存更新的回调。
将处理器、视频、音频、卡带或内存映射、程序加载、渲染辅助工具、控制器和序列化职责相互分离。为每个组件提供清晰的接口,并让组件自行管理其内部状态。
仅当硬件变体共享真实的基础行为,并只需覆盖特定映射或存储体切换规则时才使用继承。对独立子系统优先使用组合,并避免跨组件边界进行隐式访问。
定义统一的时间基准。即使按帧执行,每一帧内部仍需精确计算周期,而显示时序和调度仍由宿主应用程序负责。
通过所有有状态组件共同使用的对称序列化与恢复契约,集中处理存档状态转换。
## 连同虚读和虚写在内,按真机重现每次总线读写
将总线建模为有状态行为,而不是单纯的地址到数值查找。真实硬件可能会保留最近的值,从未映射或只写地址返回锁存数据,或者只驱动数值中的部分比特。
当不同硬件总线保留独立状态时,分别跟踪各自的锁存器。每次发生可观察的加载、写入、栈操作、操作码取指或中断向量读取时,都要更新相应锁存器。当设备只驱动数值的一部分时,应完全按照硬件行为,将这些比特与总线保留状态组合起来。
将虚读和虚写实现为真实的总线操作。即使程序从不使用返回值,它们仍可能更新锁存值并触发I/O副作用。
明确实现每种寻址模式的总线操作顺序:
- 索引寻址可能在修正页地址之前读取中间地址。
- 零页索引寻址可能在应用索引之前读取未索引的地址。
- 间接索引寻址可能在到达有效地址之前读取指针或中间地址。
- 即使没有跨页,存储指令和读-改-写指令也可能执行必需的虚访问。
- 读-改-写指令可能先将原值写回地址,再写入修改后的值。
当取指发生在栈操作之前或之后时,保留该指令特有的顺序。即使操作产生相同的最终寄存器值,改变顺序仍可能造成可在总线上观察到的错误。
## 在指令执行中途也让设备时间保持同步,并把DMA当作真实的总线周期
当模拟器以原子方式执行某个组件,而真实硬件中的各组件锁步推进时,指令执行期间访问寄存器可能会看到过期状态。应在该访问变得可观察的边界上纠正这一问题。
跟踪当前指令已完成的总线操作数量。在读写需要同步的设备寄存器之前,按照已执行操作对应的精确时钟比率推进该设备。随后进行帧级推进时,减去已经完成的工作,绝不能重复计算时间。
分别建模中断标志的生成与中断递送。屏蔽控制可能会阻止状态标志生成,而不仅仅是抑制外部中断信号。测试必须区分这两种行为。
将DMA表示为对真实总线周期的占用。传输可能改变当前总线值、延迟处理器进度,或改变输出取决于总线状态的指令结果。保留DMA、指令访问和设备副作用之间的顺序。
仅依据可靠资料和测试实现已有文档记录的非官方指令或边界情况指令。不要仅仅因为常见软件不使用它们,就简化其周期行为。
## 用已知能在真机上通过的参考程序测试模拟器
使用多层测试,每一层都承担不同目的:
- 单元测试验证初始化、指令语义、映射规则、内存镜像、状态转换和错误处理。
- 有针对性的回归测试固定帧缓冲区、音频样本、总线轨迹或其他确定性输出。
- 集成测试工具运行可信诊断程序,并比较详细的机器状态或错误代码。
- 硬件精度测试套件覆盖孤立的指令测试无法揭示的交互。
对于已知能在真实硬件上通过的成熟参考程序,应将其视为正确。责怪参考程序之前,先调查模拟器、测试工具、测试夹具和环境。
以明确而具体的理由记录可接受的失败。已知失败列表并不允许隐藏新的回归,也不允许扩大现有例外的范围。
当硬件可以观察中间访问时,同时测试最终值和操作顺序。每当规范更正或先前误分类的行为改变实现时,都要添加回归测试用例。
## 让即时存档能完整恢复,并在崩溃后停止运行
存档状态必须包含影响后续执行的每个组件,包括处理器、视频、音频、映射器、锁存器、中断和时序状态。必须验证序列化后再恢复能够重现执行,而不能只验证数据可以解析。
通过清晰的回调或存储边界公开持久内存,不要将核心与某一种宿主环境耦合。
将普通控制器保持为具有明确按钮转换和串行协议的简单状态机。通过专用API对特殊外设建模,保留它们各自的空间、时序或光检测行为。
发生无法恢复的执行异常后,设置明确的崩溃状态并阻止继续执行帧。恢复时必须使用已有文档说明的重置或程序重新加载,而不能从部分变更的状态继续执行。
保持可接受的程序输入和公共回调类型稳定。让公共类型声明与实现同步维护,使浏览器端和服务器端使用者看到相同的API契约。
## 生成文件只通过构建产生,并报告尚未测试的部分
通过批准的构建流程生成分发包、压缩文件、源映射和声明文件。不要直接编辑生成的输出。
验证项目声称支持的每一种运行时目标和模块格式。持续集成应运行与本地要求相同的格式化、代码检查、构建、类型检查和测试关卡。
更改硬件行为之前,查阅权威规范和可信实现说明。在相关操作附近记录不直观代码存在的原因,包括改变其顺序会产生的可观察后果。
审查最终差异,检查意外的生成文件编辑、过时的公共文档、未经测试的时序路径和无关整理。报告已运行的针对性检查、必要时的基准测试结果、已知失败,以及仍未验证的硬件路径。
