4. Recipe引擎运行时架构

Recipe引擎的运行时架构决定了配方从“静态文本”变成“设备动作”的全过程。它要同时解决四个问题:配方怎么被执行(解释还是编译)、执行到一半的数据放在哪里(上下文)、当前处于什么阶段(状态机)、多腔体多配方同时跑时谁先用资源(并发与互斥)。这四者不是并列的四个模块,而是层层嵌套:调度器决定“谁跑”,状态机决定“跑到哪”,上下文保存“跑过的痕迹”,执行器决定“每一步怎么落地”。

解释执行与编译执行的取舍

解释执行是逐条读取配方步骤,边解析边下发。例如配方中一行 SET PRESSURE 5.0 mTorr,解释器在运行时才把字符串解析成“参数=PRESSURE、目标值=5.0、单位=mTorr”,再映射到设备点位。它的优点是灵活:改一行配方立即生效,适合调试期和频繁变更的工艺。缺点是每步都有解析开销,且错误往往在执行到该步时才暴露。

编译执行则先把整份配方翻译成中间表示(IR)或字节码,例如把步骤序列编译成一张带跳转地址的指令表,运行时只做“取指—执行”。这样单步开销低、可提前做静态检查(如单位一致性、步骤跳转目标是否存在、超时是否缺失)。代价是编译产物需要缓存与失效管理:配方一改,缓存必须失效重编。

工程上常见的是混合模式:配方首次加载时编译成IR并缓存,运行时按IR执行;遇到需要动态计算的表达式(如根据前序测量值调整时间)时,保留一个解释执行的小型求值器。判断依据可以简化为:变更频率高、步骤少、调试阶段用解释;量产稳定、步骤多、节拍敏感用编译。

Recipe运行时架构:执行、上下文、状态机与调度 并发调度层 配方队列 资源互斥锁 腔体分配器 优先级仲裁 状态机层 IDLE RUNNING PAUSED ABORTED DONE 执行上下文 步骤指针 / PC 局部变量表 测量值快照 超时/重试计数 执行器 解释器(逐条解析) IR执行器(编译产物) 设备点位映射 / 单位换算

执行上下文管理

上下文是配方执行期间的“随身背包”。它至少包含:程序计数器(当前执行到第几步)、局部变量表(如 step_time = 30s、target_temp = 250C)、测量值快照(前序步骤采集到的膜厚、温度)、超时与重试计数、以及资源句柄(当前占用的腔体ID、气体阀门ID)。

上下文管理的关键是生命周期与隔离。每个Recipe实例创建时分配独立上下文,执行结束或中止后释放。并发场景下,上下文必须按实例隔离,不能共用全局变量,否则两个配方同时写同一个变量会互相污染。实现上常用线程局部存储或显式传入上下文对象。对于需要跨步骤传递的数据,例如“第3步测得的厚度决定第5步的刻蚀时间”,应写入上下文的命名槽位,而不是依赖全局状态。

一个实用的检查点是:当配方被暂停再恢复时,上下文必须完整还原,包括步骤指针和局部变量。如果恢复后从第一步重新开始,说明上下文没有持久化,这是常见的实现缺陷。

状态机设计

Recipe执行过程适合用有限状态机建模。典型状态包括:IDLE(空闲)、RUNNING(执行中)、PAUSED(暂停)、ABORTED(中止)、DONE(完成)。状态迁移由事件驱动:START 从IDLE到RUNNING,PAUSE 从RUNNING到PAUSED,RESUME 从PAUSED回RUNNING,ABORT 从任意活动状态到ABORTED,COMPLETE 从RUNNING到DONE。

设计要点有三。第一,非法迁移必须被拒绝,例如DONE状态不能再收到PAUSE。第二,每个状态要有明确的进入动作和退出动作:进入RUNNING时启动超时计时器,退出RUNNING时停止计时器。第三,状态机要与上下文联动:进入PAUSED时保存上下文快照,恢复时加载。这样即使设备断电,只要快照落盘,也能恢复到暂停点。

并发Recipe调度与资源互斥控制

一台设备通常有多个腔体、多路气体、共享的机械手和真空泵。并发调度的目标是:在满足资源约束的前提下,让多个Recipe尽可能并行,提高产能。资源互斥控制则保证同一资源在同一时刻只被一个Recipe占用。

实现上,每个可独占资源对应一个互斥锁或信号量。Recipe在执行到需要某资源的步骤时,先申请锁,获得后才下发动作,步骤结束后释放。例如腔体A的锁被Recipe1持有,Recipe2若也需要腔体A,则进入等待队列。调度器按优先级和等待时间决定谁先获得。

一个典型的调度策略是:高优先级配方插队,但同优先级按FIFO。同时要避免死锁:如果Recipe1持有腔体A等气体阀,Recipe2持有气体阀等腔体A,就会互相等待。解决办法是统一资源申请顺序,或使用超时回退——申请超时后释放已持有资源并重试。

下面给出一个简化的资源互斥配置示例,用于说明调度器如何描述资源与约束:

resources:
  - id: chamber_A
    type: exclusive
    capacity: 1
  - id: gas_valve_N2
    type: exclusive
    capacity: 1
  - id: robot_arm
    type: exclusive
    capacity: 1

recipes:
  - id: RCP_ETCH_01
    priority: 10
    steps:
      - {action: acquire, resource: chamber_A}
      - {action: set, param: PRESSURE, value: 5.0, unit: mTorr}
      - {action: acquire, resource: gas_valve_N2}
      - {action: wait, duration: 30s}
      - {action: release, resource: gas_valve_N2}
      - {action: release, resource: chamber_A}

在这个示例中,acquire 和 release 成对出现,调度器据此判断资源占用。如果某步骤缺少release,资源将一直被占用,后续配方无法执行。因此,静态检查应验证每个acquire都有对应的release路径,包括异常分支。

调试并发问题时,优先观察资源锁的持有者和等待队列。常见现象是某个配方卡在acquire步骤,日志显示“waiting for chamber_A”,说明锁未释放或释放路径未执行。

综合来看,运行时架构的四个部分需要协同设计:调度器决定并发度,状态机保证执行阶段可控,上下文保证数据可追溯,执行器决定单步开销。解释与编译的选择影响执行器,而资源互斥影响调度器。实际工程中,建议先用解释执行快速跑通流程,再对稳定配方编译优化;上下文和状态机从第一版就按实例隔离和可恢复设计,避免后期重构。