仿真请求变成任务包后,再交给固定 runner。跑完只列成果,确认后再回传,避免一句话变成本机命令。
windows-bot-memory/simulation-bridge
实验课最容易出现一种“看起来很顺手”的需求:把电路文件、Verilog 源码或题目截图发给本地助手,然后让它直接跑仿真、画波形、把结果回传。
这个需求本身合理。问题在于中间少了一层:自然语言不该直接变成命令。
我在本地助手里做仿真桥接时,最后把链路拆成了几个硬步骤:聊天请求先变成任务包,任务包只能交给固定 runner,runner 写出结构化成果清单,成果回传再走独立确认。这样系统响应慢一点,但权限和责任清楚很多。
先落成任务包
使用任务包,主要是为了把这次执行计划固定下来。
一条“帮我跑这个滤波器的 AC 和瞬态响应”的请求,不能在确认后重新解释成另一条命令。它应该先被转成一个结构化 spec,里面只保留这些内容:
{ "task_type": "spice_simulation", "engine": "hspice", "project": "analog", "input_files": ["received_files/example.cir"], "analyses": ["ac", "tran"], "outputs": ["run_summary", "measurements", "plot_png"], "requires_confirmation": true}这里最麻烦的通常是那些被刻意删掉的入口:没有 command、没有 shell、没有工作目录、没有任意参数数组,也不能让模型指定可执行程序。
任务包只描述“我要做哪类仿真、输入来自哪里、希望产出什么”。至于怎么调用工具,由系统内置 runner 决定。
固定 runner 比任意命令可靠
Vivado、HSPICE、LTspice 都是复杂工具。最省事的接法,是让模型拼一条命令行。不过这会很快失控:路径、参数、环境变量、输出文件、临时目录、超时、失败归因都会散在自然语言和命令字符串里。
固定 runner 的做法更笨,也更适合长期维护。
Vivado runner 只接受源码或安全解包后的源码包,先扫描模块,再决定是否缺 top 或 testbench。有明确入口时,才按固定阶段完成编译、elaboration 和仿真,并导出波形成果。
HSPICE runner 只处理受控网表和分析类型,负责收集测量表、日志、波形图和失败摘要。参数扫描、.alter、测量失败这些细节,也由 runner 归类。
LTspice runner 只处理允许的电路文件,拒绝混合在一个网表里的不合理分析组合,失败时从日志里抽摘要,而不是把整段原始输出扔回聊天。
这样做的好处是,模型负责理解意图,runner 按固定流程执行。两者之间只有任务包,不共享自由命令入口。
输入和输出要分区
实验自动化里,文件目录比想象中重要。
输入只能来自固定接收区或受控本地任务区。任务执行时,把需要的输入复制进当前任务包的 inputs/,后续 runner 只看这份副本。这样即使原始文件后来被替换,任务包仍然能解释自己当时跑了什么。
输出也不能散落。每个任务包至少应该有:
task-request.json:确认时冻结的 spec。run-summary.md:给人看的摘要。runner-result.json:给系统看的执行结果。status-events.jsonl:阶段事件。artifacts.json:可回传成果清单。inputs/:本次执行使用的输入副本。
这套结构看起来啰嗦,但它能解决一个很实际的问题:仿真失败时,用户需要知道失败在哪个阶段;仿真成功时,系统需要知道哪些成果适合默认回传,哪些只留在本地等待点名。
成果回传是第二个动作
跑完仿真不等于应该立刻把所有文件发出去。
波形 PNG、摘要 Markdown、测量表通常可以默认候选;大型 raw、WDB、VCD、完整日志、源码包就要更谨慎。它们可能很大,也可能包含过多环境信息。
所以任务完成后,更倾向于生成一张成果清单:每个文件有类型、大小、默认是否回传、跳过原因。后续要上传或发送时,再单独确认一次。
这条限制很有用。确认“在本机跑仿真”和确认“把成果发到外部会话”,不是同一个授权。
失败要给阶段
仿真系统最糟糕的输出,是只丢回来一句“失败”。
对用户来说,缺 testbench、编译失败、license 不可用、模型库缺失、测量表达式失败、波形解析失败,是完全不同的问题。一个好的 runner 至少要把失败落到阶段上:
packet_createdrunner_startedrunner_finishedartifacts_ready如果卡在编译,就别假装是波形问题。如果测量失败但仿真跑完了,也别把整次任务说成“不可用”。阶段事件和摘要文件能让用户快速判断下一步该补题干、补模型、补 testbench,还是只需要调整输出要求。
图片题先做分析,别假装已完成
课程题里还有一种麻烦输入:截图、扫描件、DOCX 里的嵌入图片。
这种题很适合先生成 problem-analysis.md,而不是直接跑仿真。分析文件可以记录题目识别结果、已知参数、缺失信息、公式路线、手算计划和仿真计划。
如果参数齐全,可以生成一个初始网表或 testbench 草稿,并标成可运行候选。如果题干缺模型、时钟、器件参数或完整端口定义,就应该明确返回 needs_info。这比“猜一个电路然后跑出一张图”可靠得多。
图片理解不是仿真完成。它只是把非结构化题目推进到结构化任务包的一步。
本地桥接也要保持轻量
这套设计不需要在服务器上跑重任务。服务器只适合做提醒、状态和轻量页面;依赖 Windows 工具、许可证、GUI 或大成果处理的仿真,留在本地。
本地桥接层也不该变成一个通用远程执行服务。它可以提供健康检查、只读状态、创建计划、归档输入、生成确认请求、调用固定 runner。它不需要提供“执行任意命令”的接口。
一旦系统有了固定 job type 和确认 TTL,就能把自然语言入口限制在几个可审计动作里:计划、确认、执行、列成果、回传。
现在的判断
聊天里跑仿真,最后要防住两件事:工具权限过大,自然语言解释空间过大。
一个稳一点的实验自动化链路,应该满足这些条件:
- 请求先冻结成任务包。
- 输入只来自固定接收区或受控任务区。
- spec 不能包含自由命令字段。
- 执行只能走 Vivado、HSPICE、LTspice 这类固定 runner。
- 每个阶段写事件,失败要归因。
- 成果清单区分默认回传和本地保留。
- 外部回传要和本地执行分开确认。
- 图片题先分析,信息不足就返回缺口。
这样做之后,助手依然能节省大量重复劳动:建任务、跑仿真、收波形、汇总测量、整理报告片段。
但它不会因为一句“帮我跑一下”就获得整台机器的自由命令入口。对实验自动化来说,这条限制比多支持一个仿真参数更重要。
继续读