第 67 环 · 撤回即续聊(救回来后接着上次那句)
第 65/66 环把删错的那一场救回来了:目录项写活、名字格写回、清单重排,还念出「好,跑步计划回来了。」
可救回来的只是目录上的一场。删除时当前指针被清,片内 K/V 环里的上下文也早已被后来的会话覆盖——用户接着说「那明天呢」,AI 像第一次见面。名字回来了,记忆没回来。
这一环让撤回顺手把这一场重新开进场:归档里的 K/V 回到片内环,当前场指针接回去。下一句真的接着上次那句。
一条接力,不混语义。撤回引擎只认「垃圾记录 + 槽位目录」,开关场引擎才认「K/V 归档」。这一环不把两件事硬绑在一起,而是新增一条接力 rtl/resume_link.sv:
restored 单拍脉冲(不认 done 高电平,避免一次撤回被反复接力);cmd=1,会话号取撤回引擎解出来的那一场);npu.sess enter 完全同一条通路、同一份归档格式:目录查槽 → 归档引擎按时间序把 K/V 追加回环 → 当前场指针接上;不另造一套加载逻辑;mem_ok=1 表示真读回了旧上下文(空场也允许进场,但 mem_ok=0 必须如实报出),words=恢复的载荷字数,cur_sid/cur_valid=现在在场里;enter 失败如实置 err,不静默。忙闲没有缝。继电器的 busy 在 restored 那一拍之后立刻拉高,一直覆盖「等撤回收尾 + 进场」整段;npu.wait 不会在撤回完成、进场还没开始的那一拍把 NPU 看成空闲。
接口。会话开关场仍走同一扇门(sx_start/sx_cmd/sx_sid),继电器只是多一个请求主;新增只读探针接在 0x980 撤回页后面:UD_RESUME(0x9AC)、UD_MEMOK(0x9B0)、UD_KVW(0x9B4)、UD_CUR(0x9B8)、SCREEN42(0x9BC)、UD_RLERR(0x9C0)、UD_CURV(0x9C4)。ISA 一位没动,仍是 npu.undo。
单元仿真 tb_resume_link(开关场替身按拍忙闲):
cmd=1 / sid=0x92)→ 收下 ok=1 / mem_ok=1 / words=16 / cur_sid=0x92 / cur_valid=1;undo_ok=0)→ 一条 enter 都不发,err=1 如实报出;mem_ok=0)→ 照常进场,但 mem_ok=0 不假报;clear 把探针/状态归零。ISA 协同仿真 tb_isa_undo67(真整颗 SoC):三场 0x91/0x92/0x93,0x92 在槽 2、基址 0x80,里面存着合法的 4 条 K + 4 条 V(表头 SALT、摘要、16 字载荷)。程序 npu.forget 2 → npu.wait → npu.undo → npu.wait:
UD_MEMOK=1 / UD_KVW=16 / UD_CUR=0x0092,当前场有效;CONV_KVTOT=0x0404:层 0 与层 1 各 4 条,旧上下文真回到片内环(不是空场);npu.step token=1 layers=2 → CONV_KVTOT=0x0505:新一句是接着旧上下文长出来的,不是从 0 开始;SALT,目录项写活,程序走到 SCREEN=0x67,两次 npu.wait 都没冻死。回归:tb_undo_del66、tb_undo_del(第 65 环老契约)、tb_isa_undo66、tb_isa_undo、tb_min_soc64 全部复跑 RESULT=PASS;主通路 SCREEN=0xF905FD04 与第 25~66 环逐位一致(本环只在撤回尾部加一条进场接力,计算面一个字没动)。
只有一个对话窗口的手机,「撤回」不能只是把一行字塞回清单——用户要的是接着说。说「撤回」,AI 回「好,跑步计划回来了。」,然后用户接「那明天呢」,AI 记得上次聊到哪、明天指什么。名字回来、记忆也回来,这一场才算真的回来。
这一环把「续聊」也做进了接口契约:撤回引擎管「这一场回到清单」,继电器管「这一场回到对话」,两段各自可单测、又在一条 npu.undo 里闭合。OS 仍然不读垃圾记录、不搬 K/V、不发第二条指令——芯片把现场收好,也把话接上。
续聊先开口。这一环把上下文接回来了,可 AI 还在等用户先说话。下一环让撤回之后 AI 自己先接一句:名字念完,顺着上次那句直接说下去。