简介:这是一份面向半导体制造与离散事件系统研究者的 PDF 文献,聚焦晶圆生产线建模与仿真问题。内容以 Petri 网刻画生产线逻辑层,用 SimEvents 实现性能层仿真,并完整展示了针对包含 83 个机器组、265 台机器、210 道工序的 300mm 晶圆生产线的分层建模流程,包括机器层、机器组层和系统层的设计,以及多种调度方案的仿真结果对比。文中还体现了可重入制造系统对设备回流、机器故障、返工与次品等现实因素的建模考量,并通过共享库所实现自底向上的子网合并。包体为单文件 PDF,共 1 个文件,大小仅 222KB,便于快速下载与离线研读。该资源已有 107 人学习,适合需要了解 Petri 网与 SimEvents 结合方法、开展可重入制造系统建模或撰写相关参考文献的专业人士。
1. 晶圆生产线建模的硬骨头:可重入流与资源竞争
半导体晶圆生产线仿真的难点,从来不在设备多,而在可重入流——同一个晶圆批次会反复回到光刻、刻蚀等同一组设备,这使工序之间产生交叉等待和资源争夺。做产能分析与调度算法验证时,商业排产软件能画出工艺路径,却很难表达并发条件、批处理规则、设备故障之间的耦合关系。Petri网把这类结构性约束写成库所和变迁,SimEvents再把这些语义落成可运行的离散事件模型,建模和仿真在这里是一前一后的关系,不是二选一。“基于Petri网与SimEvents的半导体晶圆生产线建模与仿真”这类题目,也正是研究生数学建模里反复出现的组合。这篇文章面向的是要做产线级仿真、MES验证或调度评估的工程师,以及准备用同一套方法论参加建模竞赛的团队。
2. Petri网建模晶圆产线:库所、变迁与可重入流表达
2.1 离散事件系统为什么需要Petri网而不是甘特图
晶圆生产线是典型的离散事件动态系统:lot进入、工艺结束、设备故障、缓存占满,都发生在离散时间点上。甘特图能展示一段时间内的作业排程,但无法表达“多个事件同时具备发生条件”“一个资源被多个工序竞争”“某个工序完成后触发哪几条后续路径”这类结构性语义。Petri网把系统状态描述为库所中的token分布,事件由变迁表示;变迁是否使能,取决于所有前置库所的token数和弧权重。这个结构有两个直接好处:一是系统状态迁移可以被严格计算,活性、有界性、死锁都有明确判定方法;二是Petri网先回答“什么条件下会发生什么”,再往变迁上挂时间参数,时钟只是后加属性。我一般先做不带时间的Petri网结构分析,确认不存在结构性死锁,再进入仿真阶段;顺序反过来,排错成本会高得多。
2.2 最小可重入模型:wafer怎么“反复回到同一类设备”
用极简的“光刻→刻蚀→回流光刻”模型说明可重入流在Petri网里的表示。这个模型保留了晶圆产线最本质的结构:资源竞争加上再次进入同一缓存队列。
| 元素 | 产线含义 |
|---|---|
| p0 | 等待进入系统的wafer批次 |
| p1 | 等待光刻的缓存队列 |
| p2 | 光刻机可用(资源库所,初始1个token) |
| p3 | 等待刻蚀的缓存队列 |
| p4 | 刻蚀机可用(资源库所,初始1个token) |
| p5 | 再加工判定点 |
| p6 | 已完成、可出厂 |
变迁t1释放一个wafer进入系统;t2开始光刻,消耗p1和p2中的token;t3光刻完成,释放光刻机并把token送到p3;t4开始刻蚀;t5刻蚀完成,释放刻蚀机;t6a表示还需要再光刻,token回到p1;t6b表示工艺已满足要求,token进入p6。初始标记是p0有N个token,p2和p4各1个token。
可重入结构在这一模型里的表现是t6a:变迁直接把token送回p1,也就是光刻前缓存。Petri网不需要为可重入流发明特殊机制,它只是让token沿有向弧回到前面库所而已。真正的难点在于,这种回环造成光刻机被同一批次多次占用,系统产出率不等于各工序加工速率的简单最小值。结构画出来后,可以构造关联矩阵C,其中C[i,j] = W(t_j,p_i) - W(p_i,t_j),正值代表变迁向库所发放token,负值代表消耗。对关联矩阵做秩和零空间分析,能找出哪些库所是持续约束产出的资源回路,这比盯工艺流程图猜测可靠得多。这个矩阵计算在后面第5章还会用来做模型验证。
2.3 时间、随机性与色彩:从基本网到SPN和着色网
基本Petri网不带时间概念,产线仿真却必须处理时间,实际项目里一般会混合使用三类扩展。时间Petri网给变迁绑定固定延时,表达已知工艺时间;随机Petri网SPN让变迁延迟服从指数分布,表达设备故障、lot到达间隔这类无记忆过程;着色Petri网CPN给token附加数据属性,区分批次优先级、工艺版本、配方号。晶圆产线的建模实践里,通常用着色网定义批次属性,用时间网表达工艺时长,用SPN描述故障和到达。把混合模型转进SimEvents时要注意一个常见误区:SPN的指数分布假设是为了数学分析方便,不是物理定律。SimEvents允许服务时间用任意分布,没必要为了凑解析公式把所有时间都设成指数分布。统一指数分布跑出来的仿真,均值可能接近真实值,尾部却偏差很大——而晶圆线的交期恰恰盯着尾部看。
3. 从Petri网到SimEvents:把库所和变迁落成可仿真模块
3.1 元模型对应:Petri网的每个元素在SimEvents里是谁
SimEvents是基于实体的事件调度引擎,实体在模块网络里流动,这种世界观与Petri网中token在库所间的流动天然同构。但它不是一个Petri网仿真器,不能把PNML文件直接导进去运行,需要先完成一次语义映射。
| Petri网元素 | SimEvents模块 | 说明 |
|---|---|---|
| Place(普通缓存) | Queue | 容量对应库所容量,无界时设为inf |
| Place(资源) | Server的Capacity | 容量大于1表达多台并联设备 |
| Transition(立即) | Release Gate / Entity Output Switch | 由实体属性或事件条件决定是否继续放行 |
| Transition(延时) | Server的服务时间 | 处理时间即变迁延时 |
| Token | Entity | 可以是结构体,不只承载标量 |
| Arc | 信号连接线 | 资源占用/释放需额外用控制线表达 |
一个关键差异需要注意:Petri网中变迁的使能条件要看所有前置库所的token数量,而SimEvents里Server只要有输入实体就能开工。资源占用场景不能靠直接连线表达,要在Server的Capacity和占用机制里体现。见过一些模型把Petri网里的每个变迁直接映射成一个Server,资源库所不建,跑完后设备利用率虚高,问题就出在这次映射上。Queue也不等于库所:Queue里的实体只能进出一个端口,而库所里的token可能被多个变迁竞争;同一token下一步去哪,SimEvents里用Output Switch按实体属性分流来表达,和Petri网的弧权不是一回事。
3.2 搭一个最小闭环:光刻→刻蚀→回流
手动搭建步骤如下,建议先不做故障模型,跑通事件流之后再扩展。
- 从SimEvents库拖入Entity Generator,Entity data type设为结构体或uint16型batch id,Intergeneration Time选择Exponential,均值设5分钟。这个模块对应变迁t1,负责产生wafer实体。均值参数写在模型工作区里,后面脚本扫描时直接改这个变量。
- 拖入Queue作为p1光刻前缓存,容量设50。队列深度必须与Petri网库所容量一致,这是第一个要核对的地方。容量设小了会在高负荷下出现大量“已满拒收”,设大了掩盖掉真实瓶颈。
- 拖入Server,Capacity设2,代表两台光刻机并联;Service Time选择Uniform 8到12分钟。这个Server同时承担“开始光刻”和“光刻完成”两个变迁的功能,SimEvents把这两步并成了一个处理过程,没必要拆开。
- 刻蚀环节同样用Queue加Server,紧随光刻级联。刻蚀机的Capacity按实际设备数设置。
- 刻蚀之后放一个判定节点,常用做法是在Entity Output Switch上用实体属性判断路径。如果实体的rework属性为1,信号线直接连回光刻前Queue的输入,完成可重入流;如果为0,则连到Entity Terminator,完成出厂。这里的rework属性即CPN里的颜色。
运行前先做一个合理性测试:只用1个到达实体,沿整个回路走一遍,确认每站只服务一次,并确认回流路径能正确触发。这一步能滤掉大部分属性赋值错误。
3.3 批量处理与设备故障:绕不开的两种扩展
晶圆产线里有立式炉这类批处理设备,一次同时处理多个lot。SimEvents没有专门的“批设备”图标,常见做法是用Batch模块把多个实体合并成一个batch实体,经过Server后再用Separate模块拆回原实体。Batch的合并容量和触发规则需要与批次政策一致,例如“凑够4片或等待最长30分钟立即开工”对应Batch的两个条件参数。Batch合并之后,子实体属性如何合并不同版本行为不同,我这里会在Set Attribute里显式保存关键属性,Separate之后再写回,避免后续路径判断读不到原始字段。设备故障则用Server自带的Failure端口,接Time-Based Failure Generator,MTBF设300分钟,MTTR设20分钟,分布选指数。这样一个故障源只影响对应Server,不会污染到达过程等其他随机源。
4. 关键参数与MATLAB脚本:让SimEvents仿真结果可复现
4.1 参数表:先定边界,再定随机数
仿真参数没有一个放之四海皆准的默认值,但以下表格给出了从实际项目中整理出的常用起点。跑参数扫描之前,先把表中每一行确认一遍,再用代码批量实验。
| 参数 | 常用起点 | 说明 |
|---|---|---|
| 到达间隔 | 指数分布,均值3~7 min | 按lot release策略调整,预定投放用Fixed |
| 加工时间 | 均匀或三角分布 8~12 min | 光刻等关键设备用实测数据拟合 |
| 批大小 | 4~12 个lot | 与炉管容量和批次政策相关 |
| 缓存上限 | 20~100 | 必须与Petri网库所容量一致 |
| MTBF | 300 min,指数 | 故障频率低的设备可放宽到500以上 |
| MTTR | 20 min,指数 | 维修时长含等待时间,别只填维修手动作业时间 |
| 仿真时长 | 预热8h加统计40h | 长产线建议统计区间拉满一周 |
| 随机种子 | 每个随机源独立种子 | 不要全局共用一个随机流 |
我一般先把仿真时长设为预热8小时加统计40小时,先跑3个种子观察方差量级,再决定是增加到10个种子并行跑还是继续拉长仿真时间。如果模型要对照现场数据,到达率和加工时间必须用同一时段真实WIW数据,别拿行业平均值硬套。
4.2 用SimulationInput批量扫描关键参数
MATLAB脚本扫描到达率是最常见的用法,比手动改模型参数再点运行高效得多。下面是完整示例。
mdl = 'wafer_line_model'; intervals = [3, 5, 7]; % 平均到达间隔:3/5/7分钟 for i = 1:numel(intervals) simIn(i) = Simulink.SimulationInput(mdl); simIn(i) = simIn(i).setVariable('arrivalMean', intervals(i)); simIn(i) = simIn(i).setVariable('totalTime', 48*3600); end results = sim(simIn, 'ShowProgress', 'off'); % 逐个读取循环时间统计,去除预热区 for i = 1:numel(results) ct = results(i).logsout.get('cycleTime').Values.Data; ct = ct(ct > 0); % 剔除未完成的实体 fprintf('interval=%d: mean CT=%.1f min\n', ... intervals(i), mean(ct)/60); endSimulationInput比在循环里紧挨set_param接sim好在哪里?一是避免每次循环都改写模型和重新编译,二是可以和Parallel Computing Toolbox里的parsim配合,把多个工况分到不同worker并行跑。setVariable传入的变量名必须能在模型工作区或基础工作区找到,变量名拼错时模型会静默使用旧值,不报错但结果错误。logsout字段名取决于仿真时真正勾选记录的信号,所以脚本里cycleTime这个标签必须和模型里的信号名一致;不确定时可以先用logsout.getElementNames()打印已有信号名再照抄。
4.3 统计什么:cycle time、WIP、设备利用率的取舍
仿真输出至少要盯三个量:循环时间cycle time、在制品WIP和设备利用率。读取方法分别在Entity Scope、Queue的occupancy输出端和Server的utilization输出端。下面示例是一段常用的后处理代码。
ct = results(1).logsout.get('cycleTime').Values.Data; warmupSamples = 500; % 按仿真采样步长估算的预热样本数 ct(1:warmupSamples) = []; fprintf('95%% CT: [%.1f, %.1f] minutes\n', ... quantile(ct,0.025)/60, quantile(ct,0.975)/60);注意预热区长度不要用固定500,而应通过观察cycle time时间序列曲线何时进入稳态来决定。逐案对比方案时,用同一套随机种子集合跑完所有方案再比较,不同方案用不同随机流比出来的均值差可能是噪声而不是真实差异。
5. 从Petri网不变量到仿真发散排查:模型验证的最后一公里
5.1 仿真发散在SimEvents里的三个症状
离散事件仿真里的“发散”不是数值NaN,而是事件活动失控。常见三种现场:仿真时钟长时间卡在同一个时间点,事件不断触发但时间不前进,这通常来自零延迟自循环,比如两个Server间没有时间消耗直接连回输入;实体在某个Queue里堆积成山但下游利用率只有20%,多半是分流条件永远为假,实体全部进了死分支;某条路径的实体数量持续增长从不减少,属于实体被反复复制的“重生”型回路。
定位这类问题不要上来读代码,先打开Entity Scope看实体流向,确认是在哪个节点开始分叉或卡住。再在Output Switch的判定函数里加日志输出,把实体的属性值和到达时间打出来。多数情况下,问题不是随机性而是条件分支逻辑写错了。
5.2 用不变量检查提前发现结构性错误
跑仿真之前,先用Petri网关联矩阵做不变量检查。S-不变量对应token守恒的库所集合,T-不变量对应可重复发生的变迁序列。S-不变量为空说明系统里有只增不减的库所,存在实体泄漏;T-不变量为空说明没有可持续运行的循环序列,系统可能死锁。
% C = 关联矩阵,每行一个库所,每列一个变迁 C = [ -1 1 0 0 0 0 1 -1 0 0 0 0 0 -1 1 0 0 0 0 0 1 -1 0 0 0 0 0 -1 1 1 0 0 0 0 -1 -1 ]; % S-不变量:x'*C=0,列向量x表示库所权重集合 S_inv = null(C', 'rational'); % T-不变量:C*y=0,y是变迁发生次数向量 T_inv = null(C, 'rational'); disp('S invariants:'); disp(S_inv); disp('T invariants:'); disp(T_inv);这里C是示意矩阵,实际要用你自己模型的关联矩阵替换。运行前先确认关联矩阵每列元素之和为零,这意味着每个变迁的输入输出token守恒。这个基础检查常被忽略,可一旦不守恒,后续不变量计算全都失真。rational模式会输出有理数结果,方便核对权重是否为正整数。算出的不变量再去SimEvents模型里逐个对照对应库所集合的connection关系,能在仿真发散之前就拦掉结构性错误。
5.3 三个让结果可信的验证技巧
热启动。从空线启动仿真会先经历一段低WIP爬坡期,这段冷启动数据混进统计区间会把平均循环时间压低。我一般在0时刻用触发信号让生成器批量释放一批在制品,相当于预置合理WIP,再开始计时统计。
多运行多种子。同一参数组至少跑5个不同种子,输出均值的同时输出95%置信区间。晶圆产线仿真方差通常很大,两个方案的置信区间一旦重叠,就不应该下结论说方案A优于方案B。不少项目就是把“A比B好8%”的结论修正为“没有显著差异”,这一步直接影响决策质量。
解析极限对照。在无故障、缓存足够大的降阶场景下,Petri网模型会退化成排队网络,可以用M/M/c的循环时间公式算出解析近似值,再与SimEvents输出对比。偏差在5%以内说明事件逻辑基本可信,偏差大就要回去查资源占用和队列容量设置。先降阶验证再跑完整模型,是仿真项目控制风险的基本动作。
本文还有配套的精品资源,点击获取