第 71 环 · 开机问候也认人(清单里的名字都验归属)
第 70 环把「续聊开口」这条入口堵住了:接回一场之前先验名字归属,归属不对就不叫名字。可手机开机还有另一条入口——开机问候念清单。第 58 环的问候合成器自己走一遍活清单(0x1C0),逐条取槽号、读名字格,把名字排进第一句。
它读名字时只看槽,不看人。槽一旦被回收再分配,旧名字还留在格子里,开机第一句就会把别人的名字叫给这一场听。第 70 环修的是「接回之后」,这一环把「开机第一句」也补齐:清单里每一个名字,都要先验归属。
名字念出口之前,多读一格归属。boot_greet 的念清单路径在收到清单条目(槽号 + sid)之后,不再直接去读名字格,而是先发一拍同步读 OWNER_BASE = 0x280 + 槽号:
nver++;nspoken,nskip++,直接翻下一条清单;接口。新增只读探针 BG_NVER(0xE74,归属验过几场)、BG_NSKIP(0xE70,归属对不上跳过几场),屏摘要 SCREEN47(0xAE4);前 70 圈地址映射一字不改,ISA 一位没动(仍 npu.boot)。名字格布局(6 字/槽)与归属表(1 字/槽)都沿用第 56/70 环,不新开存储。
单元仿真 tb_boot_greet71(真同步 SRAM 行为模型):
0xA1/0xA2/0xA3)→ 三个名字按清单顺序念全:nsp=3 / ver=3 / skip=0,64 字节 / 16 字逐位;0xAA,条目 0xA2)→ 跳过它,念「记一笔、家里的事,还有一场。」nsp=2 / ver=2 / skip=1 / left=1;ver=0 / skip=3 / named=0;all_names=0 的单名问候路径逐位不变;clear 把 nver/nskip 一并归零。ISA 协同仿真 tb_isa_greet71(真整颗 SoC):目录三场 0xA1(slot0) / 0xA2(slot1) / 0xA3(slot2);三格名字都写着字,但槽 1 的归属是 0xAA(上一任留下来的)。开机前 BG_ALL=1,一条 npu.boot 跑完恢复、清单、问候:
0x1E0 =「记一笔、家里的事,还有一场。」64 字节 / 11 字逐位相同;BG_NVER=2 / BG_NSKIP=1 / BG_NSPOKE=2 / BG_TOTAL=3 / BG_LEFT=1 / BG_NAMED=1,全由硬件自报;SCREEN47 = 0x00122140(skip 1 | ver 2 | spoken 2 | left 1 | bytes 64),SCREEN=0x71;一次 npu.wait 没冻死。回归:tb_boot_greet(第 53 环按场数)、tb_boot_greet58(第 58 环念清单,补上归属格后断言照旧)、tb_boot_greet71、tb_min_soc58(OS 层真 boot 念清单)、tb_min_soc64、tb_isa_resume69、tb_isa_resume70、tb_resume_speak70 共 8 项 RESULT=PASS;tb_min_soc64 主通路 SCREEN=0xF905FD04 与第 25~70 环逐位一致(计算面一个字没动)。
只有一个对话窗口的手机,开机第一句话就是它的「人味」。记得住几场对话还不够,得叫对人——名字不是这一场的,就宁可少念一个,也不把别人的名字塞进这一场。
这也是软硬协同的分寸:清单在内存里,归属表在内存里,比对在硬件里;核不查表、不比对、不拼字,开机那一条 npu.boot 就把该叫的名字叫准了。
单名问候也验归属。清单路径已经逐个验归属,可 all_names=0 时的「单名问候」仍按槽读名字。下一环把恢复那一场的名字也验一遍:槽换过人,就不叫旧名字。