两年前,我们在逻辑门级别从零设计了一颗定制CPU,并在FPGA上成功运行了Doom——这个视频获得了数百万播放。说实话,我自己至今仍觉得难以置信。
这颗CPU最初只能跑一些简单程序,比如Pong和曼德博集合,内存仅有不到1MB。而完整版Doom的关卡文件需要14MB,还需要额外空间来运行程序。更大的障碍是速度:现代PC运行Doom毫不费力,但我们的CPU却力不从心。
背景:BRAM的局限与DDR3的挑战
早期设计依赖FPGA内置的BRAM(块存储器),它的优势是延迟固定为1个时钟周期,接口简单,恰好可以融入流水线,无需额外的停顿机制。但BRAM容量太小,根本装不下Doom。
DDR3内存则完全是另一种脾性:延迟不固定、总线宽度大、速度远低于BRAM。如果每次内存访问都直接发送到DDR3,CPU会慢如爬行。解决方案是缓存——把程序当前活跃的区域暂存在BRAM中,理论上可以让DDR3的额外延迟几乎消失。
流水线与缓存的设计
新版CPU采用标准的5级流水线:指令获取、解码、寄存器读取、执行、写回。关键是内存操作被抽象成统一接口,简化了核心流水线。
指令获取阶段要处理重定向(跳转指令)比原来复杂得多。BRAM时代,内存延迟固定,收到跳转信号后下一个周期就能取新地址。但DDR3可能有请求正在途中飞着,必须先标记那个响应无效,再请求正确地址。
寄存器读取阶段也做了重要改进。旧版本使用组合逻辑直接读寄存器,拖慢了关键路径;新版本把读取流水线化,增加1个周期延迟但缩短了关键路径。同时用寄存器使用图(RUM)替代原来内部追踪最后几次写操作的方式——RUM是个32位映射表,追踪每个寄存器是否正在被占用,自然适配不同长度的流水线。
真正的难点在缓存。由于DDR3每30~60个周期才返回2个数据字,远达不到流水线理想的每周期1次访问,我们需要I缓存和D缓存分别服务取指和访存阶段,两者独立运作。它们都基于BRAM实现,本质上是把热点数据从慢速DDR3预取到快速BRAM中。
有了内存集成方案,同步加速的流水线设计才成为可能,这颗自研CPU终于能运行完整的商业游戏了。
编注:材料为技术博客长文,侧重CPU架构设计与缓存机制的技术细节,未涉及项目商业化计划或团队融资背景。