Doom 在一颗 FPGA 上跑起来,本身不稀奇。稀奇的是,这次管住硬件的不是一套新写的 x86 指令级 RTL,而是一份恢复、反汇编出来的 80386 原始微码。

z386 现在能启动 DOS 6 和 DOS 7,能运行 DOS/4GW、DOS/32A 这类保护模式程序,也能跑 Doom、Cannon Fodder 等游戏。它不是 Intel 官方开源 80386,也不是完整复刻的 80386。更准确的说法是:一个第三方开源项目,用原始 386 微码做控制核心,在现代 FPGA 上搭出了一颗可运行真实软件的 386 级 CPU。

我更在意的不是它快不快,而是它把一个老问题推到了可验证状态:恢复出来的 386 微码,到底能不能离开论文、die shot 和反汇编文本,重新驱动一套真实硬件。

z386 做成了什么:让旧微码重新发号施令

z386 使用的是 37 位宽、2560 项的恢复版 80386 微码 ROM。项目的路线不是逐条指令写 RTL,而是尽量重建微码当年期待看到的内部机器。

这点很关键。

普通 x86 软核更像“我知道 ADD、MOV、IRET 应该做什么,于是我写逻辑去实现它”。z386 更像“这份老微码会在某个周期拉某些控制信号,所以我要把寄存器、ALU、总线、异常路径和前端做得能接住它”。

它保留了不少 386 风格的结构:16 字节预取队列、解码 PLA、微码 sequencer、32 项分页 TLB、保护 PLA,以及 16KB 四路组相联统一 L1 cache。

对复古计算和 x86 微架构研究者来说,这比“又一个能跑 DOS 的软核”更有用。因为它给了一个可动手样本:你可以看真实 DOS 负载怎样穿过预取、解码、保护、分页和缓存路径,而不只是看指令语义。

做 FPGA 软核或 SoC 教学的人,也可以把它当成研究材料,而不是马上替换现有内核。更现实的动作是:拉源码、看微码接口、跑已知 DOS 程序、记录异常和兼容性边界。它现在更适合验证问题,不适合当稳定产品内核。

它为什么难:386 不是“会执行几条指令”就够了

80386 的麻烦不在 ADD。难点在前端、保护模式、分页和时序。

x86 指令长度可变。前缀、0F 扩展 opcode、ModR/M、SIB、位移、立即数会混在一条字节流里。解码器不能等指令排好队再慢慢看,它要边取边判断边界。

z386 用预取队列、控制 PLA 和入口 PLA,把字节流整理成微码能消费的 decoded record。这里做错,后面的微码入口就会错。

保护模式和分页更像分水岭。386 要处理段基址、段界限、特权级、选择子校验、TLB、页表遍历、Accessed/Dirty 位更新和精确异常。很多错误不会立刻暴露,可能只是在某个 DOS 扩展器或游戏场景里崩掉。

这也是 z386 和普通指令级实现的区别。微码很短、很密,默认底层硬件按特定节奏给出内部信号。少一个等待周期,错一个保护判断,都会让“原始微码”失去意义。

所以 z386 的难点不是把 386 指令表抄完,而是把微码背后的隐形机器补回来。形可不泥,神不能丢。

现实位置:它能跑,但还不是完美 386

性能上,z386 没有压过 ao486。现有数据更适合说明它的工程位置:规模更小,频率接近,但真实负载帧率落后。

项目z386ao486怎么看
代码量约 8K 行约 17.6K 行z386 更像微码重建研究项目
ALUT18K21Kz386 面积略低
FPGA 频率85MHz90MHz接近,不占优
Doom 原版16.5 FPS21.0 FPSao486 更快
3DBench34 FPS43 FPSz386 仍落后

项目当前大致相当于带高速缓存的 70MHz 386,或低端 486。它的频率高于历史 386,但 CPI 更差。换句话说,时钟上去了,单条指令并没有更省。

这也解释了为什么不该把它写成“386 复活并超越 486”。现在的 z386 更像一台研究用显微镜:能把原始微码、前端、保护、分页和缓存放到同一块 FPGA 上观察。

接下来最该看的不是 Doom 多几帧,而是几个更硬的变量:

观察点为什么重要
复杂保护模式程序能暴露段保护、分页和异常路径的问题
精确异常关系到 DOS 扩展器和调试类程序能不能稳定运行
PLA 行为决定解码和保护检查是否接近原芯片预期
缓存策略影响性能,也影响和历史 386 系统的差异
兼容性测试范围决定它是演示项目,还是可复用研究平台

对开发者来说,合适的姿势是观望兼容性边界,而不是按跑分下结论。ao486 仍是更成熟的 486 级软核参照;z386 的独特价值在“原始微码驱动硬件”这条路线上。

这条路不容易快。它先要证明自己足够像,才谈得上足够稳。