ngspice can't find model 报错:MOS 实例缺 .model 模型卡的硬错误与修复
更新时间:2026-11-11。长尾排查篇,属于 EDA 报错排查系列,汇总入口见 开源 EDA 报错排查导航。网表里画了 MOS 管、跑起来却先冒两条
can't find model警告,紧接着工作点求解中断退出,这是 ngspice 新手最常踩的网表错误之一。本文用一个 CMOS 反相器最小工程,把警告、硬错误、批处理追加报错和修复后的直流扫描整条链路跑透。
首屏答案:两条 MOS 实例语句 m1 ... pmos、m2 ... nmos 的第五个字段是模型名,但网表里没有同名的 .model pmos ... 与 .model nmos ... 模型卡,ngspice 读网表时先挂 can't find model 警告,工作点求解阶段没有器件方程可用,便抛出 could not find a valid modelname 硬错误,进程以退出码 1 中止。修复是补上带 level=1 与工艺参数的两张模型卡,复跑退出码为 0,直流扫描打印出完整的反相器电压传输特性。
这张流程卡对应本文的叙事顺序:先区分警告与硬错误各发生在什么阶段,再顺着 M 语句的字段约定找到缺失的模型卡,最后用直流扫描数据确认修复闭环。看到警告就停手补卡,比等求解中断再回头查省一轮迭代。
本文要回答的问题
- 网表里有 MOS 实例却没有
.model模型卡时,ngspice-47 的完整报错原文是什么,退出码是多少? - M 元件语句的五个字段分别是什么,为什么第五个字段必须在网表里有同名模型卡?
can't find model只是警告,为什么后面还会升级成could not find a valid modelname硬错误?- 补上模型卡后,怎样用 DC sweep 的输出数据确认反相器功能恢复正常?
一、完整报错原文
最小工程是一个 CMOS 反相器:PMOS 上拉、NMOS 下拉,两个栅极并接输入 in,漏极并接输出 out。出问题的 inverter_bad.cir 只有实例、没有模型卡,全文如下:
CMOS inverter without model cards
Vdd vdd 0 DC 1.8
Vin in 0 DC 0.9
M1 out in vdd vdd pmos W=2u L=0.18u
M2 out in 0 0 nmos W=1u L=0.18u
.op
.end执行 ngspice -b inverter_bad.cir 跑批处理仿真,下面是日志原样摘录,未作任何润色:
$ ngspice -b inverter_bad.cir
warning, can't find model 'pmos' from line
m1 out in vdd vdd pmos w=2u l=0.18u
warning, can't find model 'nmos' from line
m2 out in 0 0 nmos w=1u l=0.18u
Note: No compatibility mode selected!
Circuit: cmos inverter without model cards
Error on line 4 or its substitute:
m1 out in vdd vdd pmos w=2u l=0.18u
could not find a valid modelname
Simulation interrupted due to error!
Error: incomplete or empty netlist
or no ".plot", ".print", or ".fourier" lines in batch mode;
no simulations run!
exit code: 1读这段输出要抓住三层。第一层是读网表阶段的两条 can't find model 警告,分别点名 pmos 和 nmos,并原样回贴触发警告的实例行。第二层是工作点求解阶段的硬错误:Error on line 4 ... could not find a valid modelname,求解器为 M1 取器件方程时发现模型名无效,仿真当场中断。第三层是批处理模式特有的追加报错——仿真没跑起来,没有任何 .plot/.print 输出,ngspice 再报一次 incomplete or empty netlist ... no simulations run,最终退出码为 1。三条信息是同一根因的连锁反应,不要当成三个独立问题分头修。
二、工具与版本
本次实验在 macOS 本机以批处理方式完成,工具版本与日志头部一致:ngspice-47,编译进 KLU 稀疏求解器,可执行文件位于 /usr/local/bin/ngspice,统一用 ngspice -b <网表文件> 调用。
版本先固定,是因为模型查找的诊断措辞随 ngspice 版本演进过。本文的警告原文、硬错误句式与退出码只对 ngspice-47 这个构建负责;换到其他大版本应保留当次完整输出再对照。求解器如何用模型方程列方程组、做牛顿迭代,背景原理见 SPICE 电路仿真器:它在解什么方程。
三、根本原因:M 语句第五字段是模型名,模型卡必须先注册
3.1 MOS 实例与模型卡是「引用」与「定义」的关系
SPICE 网表里,以 M 开头的一行是 MOS 管实例,字段约定是固定的:
M<name> <漏极> <栅极> <源极> <衬底> <模型名> <几何与参数>
M1 out in vdd vdd pmos W=2u L=0.18u前四个节点字段描述管子怎么接进电路,第五个字段 pmos 不是器件类型声明,而是模型名引用——告诉仿真器本管的电气行为到名为 pmos 的模型卡上取。模型卡是一条独立的 .model 语句,给出器件类型、模型级别(level)和阈值电压等工艺参数,例如 .model pmos pmos (level=1 vto=-0.45 ...)。实例回答「有几个管、怎么接」,模型卡回答「这种管按什么方程导电」,两者靠名字关联。下图画出这条查找链,红色节点就是本例断掉的环节。
图中蓝色是两条实例引用,红色是模型注册表里的空缺,绿色是模型卡正常时才能供给的器件方程。ngspice 读网表时先把 .model 语句登记进注册表,再逐行解析实例;名字查不到就挂 can't find model 警告。警告不阻止网表解析,电路标题、节点信息照常打印;但求解器一旦需要这只管子的电流方程,缺失就无法绕过,于是升级成硬错误。同属「引用了未加载定义」家族的还有子电路调用缺 .subckt,机制对照见 ngspice subckt 未定义报错排查。
3.2 三种常见触发方式
根因都是名字对不上,具体写法有三种:
- 只写实例不写模型卡:本例情形,抄电路时漏掉了工艺模型段落。
- 模型名拼写不一致:实例写
pmos,模型卡却叫.model pm或.model PMOS;名字区分大小写,差一个字符就是查无此卡。 - 工艺库没有 include:模型卡写在厂家工艺文件里,网表却缺
.include "process.lib"或路径不对,注册表同样为空。
四、排查清单:先对名字,再查 include,最后看卡体
图中蓝色是信息收集动作,灰色是判定节点,红色是硬失败分支,橙色是两条「定义存在但接不上」的分支,绿色是本例走的补卡分支。落地排查按四步走:
- 收集实例模型名:
grep -i '^m' 网表列出所有 MOS 行,摘出第五字段去重,本例得到pmos、nmos两个待核对名字。 - 扫描模型卡与 include:
grep -i '^\.model'看本地定义,grep -i '^\.include'确认工艺库是否加载,库文件还要打开核实目标名字确有定义。 - 逐字对拼写:名字大小写敏感,实例、模型卡、库调用三处必须完全一致。
- 按分支选动作:完全缺卡就补
.model,卡在库里就修 include 路径,名字不符就统一命名后复跑。
五、修复代码与复跑确认
修复后的 inverter_fixed.cir 在网表顶部补两张 level=1 模型卡,并把激励从单点工作点改成 0 到 1.8V 的直流扫描,让结果自己证明反相器功能恢复:
CMOS inverter with level 1 model cards
.model nmos nmos (level=1 vto=0.45 gamma=0.4 phi=0.7)
.model pmos pmos (level=1 vto=-0.45 gamma=0.4 phi=0.7)
Vdd vdd 0 DC 1.8
Vin in 0 DC 0
M1 out in vdd vdd pmos W=2u L=0.18u
M2 out in 0 0 nmos W=1u L=0.18u
.dc Vin 0 1.8 0.3
.print dc v(in) v(out)
.end两张卡的第一个名字是模型名,与 M 语句第五字段一一对应;第二个 nmos/pmos 是器件类型关键字;level=1 选用经典平方律模型,vto 给出阈值电压(NMOS 正、PMOS 负),gamma 与 phi 是体效应参数。一次 bash run.sh 顺序跑出坏网表报错与修复后扫描两段记录,坏路径的终端实录如下:
修复后的直流扫描段同样取自同一份运行日志,七个扫描点的输出原样摘录:
把扫描结果整理成表,反相器的电压传输特性(VTC)一目了然:
| 扫描点 | Vin(V) | v(out)(V) | 区间判读 |
|---|---|---|---|
| 0 | 0.0 | 1.800000 | 输入低,PMOS 导通,输出满摆幅高 |
| 1 | 0.3 | 1.800000 | 仍在低电平区,输出保持高 |
| 2 | 0.6 | 1.792462 | NMOS 开始微导,输出略降 |
| 3 | 0.9 | 1.668198 | 进入翻转区前半段 |
| 4 | 1.2 | 3.060033e-02 | 翻转区后半段,输出已接近地 |
| 5 | 1.5 | 1.539998e-08 | 输入高,NMOS 导通,输出 effectively 0 |
| 6 | 1.8 | 1.206666e-08 | 满摆幅低电平 |
修复闭环有三处证据要一起读。其一,警告与硬错误全部消失,退出码为 0,两个模型名都在注册表里找到了定义。其二,七个扫描点全部算出数值,.dc 分析走完全程,不再有 no simulations run 的追加报错。其三,数据形态符合反相器的物理预期:输入 0 到 0.6V 时输出钉在 1.8V,0.9V 到 1.2V 之间输出从 1.668V 骤降到 0.03V,这就是电压传输特性的翻转区,1.5V 以上输出降到纳伏量级,等价于逻辑 0。如果补卡后仍不收敛,问题就从「缺定义」转移到模型参数与数值求解层面,排查方法回到 SPICE 仿真器的收敛性章节。
实验环境
- 机器/系统:macOS 本机,ngspice 批处理模式(
ngspice -b),无图形界面 - 工具版本:ngspice-47(KLU 稀疏求解器),可执行文件
/usr/local/bin/ngspice - 日期:2026-11-11
- 完整命令:在实验目录执行
bash run.sh;脚本先跑ngspice -b inverter_bad.cir复现缺模型卡的警告与硬错误,再跑ngspice -b inverter_fixed.cir截取直流扫描表段,各打印退出码。
代码获取
完整网表与复现脚本位于公开仓:https://github.com/derekzhuo/geek-doc.cn/tree/main/experiments/ts-ngspice-model-card-missing,含 inverter_bad.cir、inverter_fixed.cir 与 run.sh。本机装好 ngspice 后,在该目录执行以下命令即可原样复现两段运行:
bash run.sh这一篇在知识体系里的位置
本篇属于 开源 EDA 报错排查导航 的开源仿真分支,回答「实例引用的模型名为什么必须有同名模型卡、警告怎样升级成硬错误」。同家族的子电路侧问题见 ngspice subckt 未定义报错排查,两篇对照可建立网表「引用与定义分离」的心智模型;补卡之后的器件方程、牛顿迭代与不收敛救援见 SPICE 电路仿真器:它在解什么方程、不收敛怎么救。三篇覆盖 ngspice 仿真「定义缺失、调用缺失、数值求解」三个故障面。
总结
ngspice can't find model 报错的本质是 MOS 实例与模型卡之间的名字关联断裂:M 语句第五字段是模型名引用,网表里必须存在同名 .model 定义,或通过 .include 加载工艺库。ngspice-47 在读网表阶段先挂 can't find model 警告,工作点求解时因取不到器件方程升级为 could not find a valid modelname 硬错误,批处理模式再追加 no simulations run 并以退出码 1 中止。排查按「收集实例模型名、扫描 .model 与 .include、逐字对拼写、按分支补卡或修包含」四步走;本例补上 level=1 的两张模型卡后复跑退出码为 0,DC sweep 七个扫描点给出完整的反相器电压传输特性,翻转区落在 0.9V 到 1.2V 之间。