一个网页项目用 277,248 个 NAND 门搭了一台 16 位计算机。中央处理器、内存、操作系统和一个俄罗斯方块游戏全部跑在这些门上。页面可以一路缩放,从桌面看到单个 NAND 门,信号流动也看得见。它的做法是从一份固件二进制生成网表,交给仿真工作线程按单位延迟逐个门求值。这类演示的价值不在能玩游戏,在于把软件层完全看不见的故障变成了可见后果。
网表与仿真是怎么跑的
启动时先从固件二进制生成网表,再交给仿真工作线程执行。每个门一次求值,输入变化沿连线传播,屏幕上某个门的亮度反映它最近有没有翻转。缓存里放一个四千周期的环形记录。逻辑分析仪从里面取程序计数器、指令寄存器、地址总线和内存数据等信号,一次最多看 64 条网线。时钟有三条,一条晶振和两相时钟。按双相纪律,周期边界上三条线都是零。
子弹时间把一次周期拆成门延迟
单位延迟引擎没法显示真实门延时。项目的做法是录下一个周期,再按门延迟逐步回放,从驱动门追到接收门,一条一条连线看信号怎么走过去,还能显示当前边沿的关键路径。配合逻辑分析仪,一次取指或一次加法分布在多少个门步骤里,可以逐步数出来。这是仿真器里少见的粒度。
故障注入是真正的教学用具
故障实验室可以给任意门注入固定零、固定一,或者切断一个输入并接到零或一。项目自带几个预置故障,每个都附一句预测,再让人去看机器到底会怎样。一个视频存储体故障让屏幕中间四行不再更新,方块掉下去就消失,游戏逻辑照常运行,因为显示直接读像素锁存,读侧的故障不影响画面。算术部件第四位进位出错,位置、指针和分数全乱,系统很快崩溃,重启时内存自检直接报出地址。键盘寄存器某一位固定为一,左键读起来一直按着,而系统只在电平从低到高时算一次按键,于是左键彻底失效。去掉一相时钟,从锁存器不再打开,整机冻结。
独立审计兜底
演示类仿真最怕算错还看不出来。项目在界面一角挂了审计开关,用一套独立的求值器重放采样周期,一旦和主引擎结果不一致就变红。屏幕上的每个像素、每个门的输入输出和真值表都从网表实时读取,不是预渲染的动画。
它的参考价值在方法
课本上的单周期和多周期数据通路是理想化的。时序冲突、竞争冒险、故障传播要到了门级才看得见。这套实现的拆法可以直接借来做小型中央处理器可视化,网表加事件求值、周期级录制、门级回放、故障注入配独立审计。页面还用服务工作线程补了一层跨源隔离,拿到共享内存的资格,静态托管的站点没有那两个响应头也能跑。隔离加载失败时会退回非隔离模式,不会一直转圈。
常见问题
网页里跑门级仿真不会很慢吗?
求值放在工作线程里,主线程只负责渲染。屏幕上的信号来自采样,不是每门每周期重画。做演示和教学足够,做性能基准不行。
故障注入会影响保存的数据吗?
故障只改网表求值时的输入输出,加载的固件和日志不受影响。刷新页面就回到健康机器。
想自己做一个,最难的是哪一步?
渲染只占一小部分。真正的门槛是先把网表和固件对上,符号表和地址映射要能查到具体门,否则注入了一个故障也说不出它影响了什么。