第一百四十四章 寄存器
JTAG 通了之后,孟思远坐到了工位前。
这是他的主场。
他打开 OpenOCD,打开一个 Python 脚本,在命令行里输入第一条寄存器读取指令——读取芯片 ID 寄存器,这是每一块芯片最基础的标识,地址固定,值固定,用来确认 JTAG 访问的基本路径是通的。
回显出现了:「0x1F001A03」
「芯片 ID 寄存器,」孟思远说,「读回来了,值是 0x1F001A03。」他转头看向方宇明,「预期值?」
方宇明从旁边的文件夹里抽出一张打印的寄存器映射表,找到芯片 ID 那行,「0x1F001A03,」他说,「对的。」
「第一条,通,」孟思远说,在 checklist 上划掉一行。
接下来是一长串寄存器读写测试。
孟思远一条一条往下走:读配置寄存器,读状态寄存器,写控制字段,再读回来确认写入是否生效,读中断标志,清中断,再读。
大多数都是顺利的。芯片 ID 对,版本号对,大多数的配置寄存器读写一致,控制字段写入之后读回来的值和写入的值匹配。

B207 里安静了很长一段时间,只有 PC 风扇的声音和偶尔的键盘声。
到了下午三点多,孟思远读到一个地址的时候,停了一下。
「这条,」他说,「读回来的值不对。」
是一个状态寄存器,记录 KV-cache buffer 的初始化状态。
预期值是 0x00000000——芯片刚上电,buffer 未初始化,所有位应该是 0;但读回来的是 0x00000040,第六位被置了 1。
「第六位是什么?」颜天磊过来看。
孟思远翻开寄存器说明,「buffer ready flag,」他说,「这一位是 1 意味着系统认为 KV-cache buffer 已经 ready 了。但我们还没有执行任何初始化流程,它不应该是 ready 的。」
「它自己初始化了?」贺志明问。
「不应该,」方宇明说,他走过来,在屏幕前站了一会儿,「这个寄存器的复位值,」他说,「在设计里是多少?」

颜天磊已经翻到了对应的 RTL 文件,「复位值是 0x00000040,」他说,停了一下,「……第六位在复位时是 1。」
「所以,」孟思远说,「是复位值就是这样的,不是芯片异常,是我们的 checklist 写错了?」
「可能是我写的预期值有问题,」孟思远说,「我当时以为复位值全是 0。」
他们把这块 RTL 翻出来重新看了一遍。
RTL 里,那个寄存器的定义是这样的:上电复位之后,buffer ready flag 默认置 1,代表「buffer 可以接受初始化命令」,而不是「buffer 已经完成初始化」。换句话说,这个 flag 是一个「准备好被初始化」的状态标志,而不是「已经初始化」的状态标志。
「命名有点歧义,」颜天磊说,「buffer ready 通常让人以为是已经 ready 了,但在这里的含义是「ready to be initialized」。」
「这个地方,」方宇明说,「手册里应该写得更清楚。」他停了一下,「不是 bug,是文档问题。但这是我们第一次在真实芯片上碰到这个,如果不是读到这个值,可能不会注意到。」
孟思远修改了 checklist 里的预期值,从 0x00000000 改成 0x00000040,然后在旁边加了一个注释:「buffer ready flag = 1 at reset,含义为「ready to accept init commands」,非异常。」
「改好了,」他说,「继续下一条。」

下午四点半,孟思远把第三层的寄存器读写测试做完了。
最终结果:共测试了 47 条寄存器访问路径,46 条完全符合预期,1 条(KV-cache 状态寄存器第六位)因 checklist 预期值有误导致初始误判,修正后符合 RTL 定义。
他把这份结果整理成一页文档,发给了方宇明。
方宇明看完,「第三层通了,」他说,「明天做第四层——内存初始化。」
杜磊在这期间去把内核电压的问题查了一下。
他换了一个 LDO 上的外部调节电阻,把阻值从标准值往上微调,内核电压从 0.984V 回到了 1.001V。
「问题在哪?」贺志明问。
「LDO 的负载调整率,」杜磊说,「空板测试时没有芯片负载,电压是准的;芯片装上来之后,内核电流变大了大约 150mA,LDO 的输出电压稍微往下掉了 16mV。通过微调外部电阻可以补偿掉。」
「这属于板子设计的问题,」颜天磊说,「还是芯片功耗比预期高了?」

「两个原因都有一点,」杜磊说,「LDO 的设计可以更保守一些,用调整率更低的型号;芯片的静态功耗比后仿真的预计值高了大约 12%,在可以接受的范围里。」
那天晚上,陆衍把这一天发生的事发给了豆包——芯片到货,BGA 焊接,第一次上电,JTAG 通了,寄存器读写基本都过了,一个状态寄存器的预期值写错了但不是 bug,电压低了一点点但已经修正。
豆包:「第三层通过——寄存器读写。现在 bringup checklist 的 7 层中,已经完成了:上电序列、JTAG 连通性、寄存器读写。明天开始第四层:LPDDR4 内存初始化,这是相对复杂的一步,需要通过 JEDEC 规定的初始化时序初始化片外 LPDDR4,然后写入测试数据并读回验证。」
陆衍:「那个状态寄存器的事,方宇明说不是 bug,是文档问题。」
豆包:「对。但这是真实芯片上第一次发现的——在仿真里,仿真工程师通常知道复位值,不会犯这个错误。在 bringup 里,有一类问题就是这样的:不是芯片有问题,是人对芯片的理解有误,真实芯片帮你发现了。」
陆衍:「所以 bringup 是在发现人对芯片理解的误差。」
豆包:「也是在验证芯片和人对它的描述之间有没有误差。两个方向同时在发生。」
B207 的灯关了,砺火一号在验证板上,在黑暗里,等待明天的第四层。