尧图精选

CST导出SPICE模型txt转cir完整指南:从网表清洗到LTspice仿真验证

🕒 发布时间:2026/10/2 9:22:20 📁 来源:尧图网络
上周帮同事调一个高速连接器的信号完整性模型卡了整整一天。CST那边跑完仿真右键就把SPICE模型导了出来发过来一看是个txt文件。我们这边习惯用LTspice做接入后的快速验证第一反应是把后缀改成.cir结果一跑满屏都是红字。折腾到下午我打开那个txt逐行看才发现从txt到cir的路根本不是改一个后缀那么简单中间藏着不少文件格式和语法语义的门道。这篇内容适合谁你在用CST Studio Suite做无源结构连接器、滤波器、过孔、封装引线的高频仿真拿到了一堆SPICE模型的txt导出文件希望在LTspice、HSPICE或PSpice里直接跑仿真那这篇指南就是给你准备的。我会按实际处理顺序从CST导出SPICE模型的场景讲起再到txt文件内部结构、三种转换路线、转换后的仿真验证最后把我踩过的五类典型报错和排查链路完整写出来可以直接对照排查。1. 为什么需要txt到cir这一步CST导出SPICE模型的真实场景1.1 CST什么时候会导出SPICE模型很多刚接触CST的工程师有个误解以为CST的SPICE模型导出是在三维微波工作室里随便点两下就完成的。实际不是。我用的比较多的是CST的Design Studio设计工作室也就是CST专门做电路级协同仿真的环境。你在三维模块里把结构仿真完拿到的是S参数、场分布这些结果如果要进一步放到电路级仿真器里和驱动芯片、端接电阻、接收机一起做协同验证这时候才需要把无源结构的行为用SPICE模型表达出来。常见路径是这样的把三维仿真结果作为模块放进Design Studio的Schematic然后在结果输出端使用SPICE等效电路提取功能软件会对频响曲线做有理函数拟合最终生成一个由R、L、C和受控源构成的宽带SPICE模型。这个模型默认会落到工作目录里后缀可能是.txt、.dat有时候也是.sp。模型覆盖的频带、极点阶数、误差阈值等等参数在提取时都可以设置。不同版本CST的菜单入口略有差异但思路统一把频域行为变成可以在SPICE里求解的等效电路。还有一种情况是你手里没有现成的SPICE模型只有一个.s2p或者其他格式的S参数文件。这时候有些人会拿第三方工具去拟合但CST自己也能做。步骤上都是在Design Studio里加载S参数结果再执行SPICE模型提取。这也是从CST导出SPICE模型最常见的工作流。1.2 导出的txt和可仿真的cir到底差在哪我用一张表把这两者的核心差异列出来看完你就能理解为什么很多同事直接改后缀会失败。对比项CST导出的SPICE txt可直接运行的SPICE cir文件后缀.txt / .dat / .sp.cir顶层结构通常只有.SUBCKT/.ENDS子电路定义必须有标题行、元件、激励源、负载、分析指令、.END是否包含.END多数不包含因为它是个模型库文件仿真主文件必须包含是否包含激励/负载不包含那是调用方的事需要显式写上源和负载注释规范可能带时间戳、中文、全角符号建议只用*开头ASCII注释数值格式常见1.25E-12这种指数写法依赖具体仿真器LTspice基本兼容但也要检查节点命名可能有GND、n_1、net1这类节点名地节点必须是0节点名尽量只用字母数字这个表格反映了一个核心问题CST导出的txt本质上是一个子电路模型库文件它描述的是这个无源结构的等效电路长什么样但它不是一个可以直接运行的仿真工程文件。cir文件则应该是一份完整的、能独立求解的网表。所谓txt到cir就是把裸模型包装成一个带激励源、带负载、带分析指令、带结束语句的完整可执行文件。1.3 为什么直接改后缀行不通很多工程师的第一反应就是我直接重命名成.cir不就行了吗表面看文件后缀变了但SPICE类仿真器在解析时关注的不是后缀而是文件里的每一行指令。举个例子CST导出的txt通常以一堆*开头的注释行开始然后是一个.SUBCKT声明。你把后缀改成.cir打开 LTspice 一仿真它发现自己找不到任何激励源也没有负载更别说.TRAN、.AC这些分析指令。LTspice可能会报no analysis specified也可能直接忽略你的子电路因为根本没地方调用它。这不是文件坏了而是你给仿真器喂了一个零件库却没告诉它要把这个零件装在哪、加多大电压、看什么波形。另一个常见坑是隐藏字符。CST在Windows环境下导出txt文件可能是CRLF行尾、UTF-8 BOM编码有些版本甚至会在文件末尾带上不可见的控制字符。这些在记事本里完全看不见但LTspice、HSPICE这类解析器是非常严格的逐行逐字符处理一个BOM字符放在.SUBCKT前面轻则警告重则直接拒绝识别整个子电路。后面第5章我会专门讲这个坑。所以在动手转换之前必须先搞清楚CST导出的txt文件里到底写了什么。下一章我把内部结构逐行拆开讲。2. 摸清CST导出txt的内部结构读懂每一行网表2.1 一段典型的CST导出SPICE文本长什么样为了讲清楚结构我简化了一个真实模型。实际CST导出的文件可能比这个长几十倍规则是一致的不会变。下面这个例子模拟的是某个两端口无源结构提取出来的宽带SPICE模型* CST Studio Suite SPICE Model Export * Extract Time: 2025-01-12 14:32:06 * Original project: HDMI_Connector_CST .SUBCKT HDMI_PIN1 P1 P2 0 * node P1, P2, 0 C1 P1 n_1 1.2537E-12 C2 n_1 0 1.0329E-12 R1 n_1 n_2 45.6273 L1 P2 n_2 0.8325E-9 G1 P1 0 n_2 0 2.31524E-3 .ENDS HDMI_PIN1逐行看。第一行到第三行都是注释以*开头。第一行会注明这是CST Studio Suite的SPICE模型导出结果第二行是时间戳第三行是原始项目名。这些注释对人有用对仿真器来说直接忽略但前提是它们必须是合法的ASCII字符。第四行.SUBCKT HDMI_PIN1 P1 P2 0声明了一个名为HDMI_PIN1的子电路。P1、P2是对外端口0是全局地。这一行的最后一个节点通常就是参考地CST导出时一般会直接写成0但有些老版本会写成GND或者VSS这就要人工干预。接着是一些元件行。C1 P1 n_1 1.2537E-12表示一个1.2537皮法的电容跨接在P1和内部节点n_1之间。R1是45.6273欧姆的电阻L1是0.8325纳亨的电感。这些RLC元件组合起来模拟结构的寄生效应。G1 P1 0 n_2 0 2.31524E-3这一行是电压控制电流源。CST在拟合高频互连结构时非常依赖G元素因为耦合、串扰、传输系数等效应用纯RLC很难精确表达电压控制电流源可以很好地把某个节点的电压转成另一个节点上的电流。这也是CST宽带SPICE模型最核心的部分。最后一行.ENDS HDMI_PIN1结束子电路。注意这里没有.END没有V1没有.TRAN什么都没有。这就是我说它是个模型库文件的原因。2.2 数字格式、单位后缀与节点命名里的坑CST导出txt里的数值格式不同版本跨度很大。我见过三种1.2537E-12、1.2537e-012、0.8325E-9。前两种LTspice都能识别HSPICE也没问题但如果遇到1.2537D-12这种就要小心了。D在Fortran风格里代表双精度指数SPICE标准不认。如果你在文件里搜到D00、D-12这种最好的办法是用正则把所有D统一替换成E或者直接改写成带单位后缀的形式比如1.2537p。单位后缀这块最大的坑是M。在SPICE体系里后缀M代表毫milli不是兆mega。兆要用Meg。如果CST导出的txt里出现1M的电阻LTspice解析出来是1毫欧不是1兆欧量级直接差出9个数量级。后面我会专门讲这个换算导致的诡异现象。节点命名也要检查。CST喜欢生成n_1、net_27这类内部节点名大多数现代SPICE仿真器都支持下划线但个别老版本解析器遇到下划线就罢工。更麻烦的是如果节点名里出现#、这些特殊字符LTspice在解析时可能把后面一部分吃掉。所以我处理的时候都会用正则把#$[]这类非字母数字字符统一替换成下划线。还有一个所有SPICE仿真器都严格遵守的规则节点名0是全局地在SPICE里是独一无二的代表参考电位零点。任何连接到地的元件引脚要么直接接0要么通过显式的接地符号表示。CST如果导出GND这个节点名很多仿真器会把它当成普通网络名而不是地导致整个电路没有直流路径后面一仿真就是奇异矩阵报错。2.3 预处理先把脏文本洗干净我拿到CST导出的txt之后不会马上转格式而是先做三件预处理的事这都是实测下来避免踩坑的关键动作。第一用Notepad或者VS Code打开txt打开显示所有字符功能检查行尾符、BOM、零宽空格。一旦发现文件开头有EF BB BF这样的BOM字节另存为UTF-8无BOM格式如果行尾符是CRLF按需求统一成LF。有人觉得这是洁癖但SPICE解析器对不可见字符的容忍度极低一个小BOM就能让.SUBCKT整体失效。第二用正则搜索.SUBCKT和.ENDS检查它们是否成对出现、名字是否一致。最简单的办法是直接在编辑器里搜\.ENDS看它在文件里的个数和位置。如果.ENDS缺失大概率是导出时文件被截断或者复制时漏了行。第三把所有非ASCII字符清理掉。CST如果是在中文系统环境下导出的注释里经常混入全角冒号、中文括号这些字符在一些HSPICE旧版本里会直接导致解析报错。清理时注意只过滤注释行不要动.SUBCKT后的模型名和端口名。预处理干净之后才能进入正式的转换环节。下面这章我给你完整列出三种转换路线从手工到脚本按需选择。3. 实现txt到cir的三种实战路线3.1 手工包一层适合一次性修改的经典做法如果你手头只有一个模型又不想为了它专门维护脚本手工转换是最直接的。操作步骤如下。第一步用文本编辑器打开CST导出的txt复制里面的全部内容新建一个.cir文件粘贴进去。第二步确认.SUBCKT这一行是否正确端口顺序和地节点是否符合你的仿真需求。比如我用的是LTspice我会把.SUBCKT HDMI_PIN1 P1 P2 0保留成原样因为后面调用子电路时节点顺序必须和这一行一一对应。第三步在.SUBCKT之前补上一个标题行注意标题行不能以*开头要直接写文字比如HDMI_PIN1 Simulation这是SPICE文件第一行必须存在的标题行。第四步在文件末尾添加激励源、负载、分析指令和.END。一个完整的手工转换结果长这样HDMI_PIN1 Simulation .include HDMI_PIN1.txt VIN IN 0 PULSE(0 1 0 50p 50p 2n 4n) R1 IN P1 50 R2 P2 0 50 X1 P1 P2 0 HDMI_PIN1 .TRAN 10p 5n .PROBE .END这里我用了.include把原始txt文件包含进来而不是直接复制所有模型行。好处是原始txt保持不动出错时你随时能对比。X1这一行是调用名为HDMI_PIN1的子电路它的节点顺序P1 P2 0必须和.SUBCKT声明保持一致。R1 IN P1 50是源端50欧姆阻抗R2 P2 0 50是负载端50欧姆这样整个网络才有完整的信号通路和直流路径。手工转换适合偶发需求但要注意手动敲控制指令时最容易漏掉的就是.END前的.PROBE或者.PRINT。没写探针语句不代表仿真器不存波形但至少在很多SPICE变体里你拿不到想要的那个电压节点数据。我的习惯是宁可多写一行也不省。3.2 Python脚本批量转换一次处理几十个模型如果你的设计里有二十个过孔模型、八根差分线要转手工就不现实了。这种批量场景直接用Python脚本几分钟跑完。下面是我一直保存在本地的转换脚本针对CST导出的txt做了专门处理你直接把文件名改一改就能用import re from pathlib import Path src Path(cst_spice_model.txt) dst Path(cst_spice_model.cir) lines src.read_text(encodingutf-8).splitlines() # 1. 统一行尾处理SPICE续行符 merged [] for line in lines: stripped line.strip() if not stripped: continue if stripped.startswith() and merged: merged[-1] stripped.lstrip().strip() else: merged.append(stripped) # 2. 清洗节点名和非ASCII字符 cleaned [] for line in merged: if line.startswith(*): cleaned.append(line) continue line re.sub(r\bGND\b, 0, line, flagsre.IGNORECASE) line re.sub(r[#$\[\]], _, line) line re.sub(r[^\x00-\x7F], , line) cleaned.append(line) # 3. 检查并补全 .SUBCKT / .ENDS has_subckt any(l.upper().startswith(.SUBCKT) for l in cleaned) has_ends any(l.upper().startswith(.ENDS) for l in cleaned) if not has_subckt: cleaned.insert(0, .SUBCKT CST_MODEL P1 P2 0) if not has_ends: cleaned.append(.ENDS CST_MODEL) # 4. 写出模型文件这里刻意不加 .END因为它是子电路库文件 dst.write_text(\n.join(cleaned) \n, encodingutf-8) print(f[OK] {dst})脚本做了四件事把以开头的续行拼接成完整一行把GND统一替换成0把特殊字符和非ASCII字符清理掉检查.SUBCKT/.ENDS配对并自动补全。最后写出的文件是纯模型文件没有加.END因为还需要另一个仿真主文件去调用它。如果要连仿真主文件一起生成可以在脚本末尾再补一段按你的激励和分析需求拼接出sim.cir。脚本的价值不是省那一次两次手工而是保证所有模型都经过同一套清洗规则不会出现这个模型过了、另一个模型因为某个隐藏字符又挂了的情况。3.3 include方案模型文件和仿真文件分离第三种方案是我个人最推荐的工作模式尤其在模型还需要回传给别组工程师的时候。它的核心思路很简单CST导出的txt模型文件经过最小限度清洗后保存为.cir模型库文件仿真主文件单独写用.include把模型包含进来。结构上就像C语言里的头文件和源文件分离一样。目录结构可以这样组织C:/project/ models/HDMI_PIN1.cir sim/HDMI_PIN1_sim.cir模型文件只包含子电路定义和注释不包含激励、负载、分析指令。仿真主文件专门负责你要跑什么仿真、加多少激励、看哪个节点。这样做的好处有三点第一模型文件可以在多个仿真工程里复用第二修改激励参数时不用动模型第三如果LTspice报错你可以立刻定位是模型的问题还是仿真设置的问题排查范围小很多。仿真主文件示例HDMI_PIN1 Simulation .include ../models/HDMI_PIN1.cir VIN IN 0 PULSE(0 1 0 50p 50p 2n 4n) R1 IN P1 50 R2 P2 0 50 X1 P1 P2 0 HDMI_PIN1 .TRAN 10p 5n .END注意.include后面的路径我习惯用正斜杠Windows下LTspice也能正常解析。路径和文件名尽量不要有中文和空格否则解析器容易抽风。.SUBCKT后的模型名HDMI_PIN1必须和.include文件里的.SUBCKT HDMI_PIN1完全一致包括大小写。在SPICE里大小写敏感这个问题不同仿真器行为不一样最稳妥的方法是全部统一成大写。3.4 三种方案怎么选方案适用场景优点缺点手工包一层单个模型、应急验证零依赖改动直观容易漏控制语句不适合批量Python脚本几十个模型批量处理清洗规则一致可重复执行需要维护脚本和路径include分离模型复用、跨部门协作模型与仿真独立排查快对文件路径和命名要求高没有绝对的最好只有最适合当下场景的。我的做法是临时看看波形用手工包一层正式项目或要交付给其他团队用include分离一旦发现要转换的模型超过五个立刻写脚本。4. 转换完成后的电路仿真验证流程4.1 在LTspice中加载转换后的cir转换不是终点验证才是。把转好的cir文件用LTspice打开直接点Run如果能看到波形说明语法上基本通过了但这只代表能跑不代表跑对了。一定要做个完整的验证流程确认转换后的SPICE模型行为和CST原仿真的频响、时域特性一致。LTspice加载cir有两种方式。一种是用文字界面直接运行网表也就是你把cir文件拖进LTspice的schematic窗口它会弹出一个文本编辑器你点Simulate按钮就行。另一种是在原理图里通过.include指令和X元件引用子电路。如果你更喜欢画原理图就在原理图里放一个通用子电路符号把model name填成HDMI_PIN1然后把节点连线连到P1、P2和地上。我第一次用LTspice跑CST模型时遇到一个让我困惑很久的现象不加负载直接看端口电压波形正常加了负载之后波形幅度掉很多。后来想明白了CST的SPICE模型只是一个等效网络它本身不知道外面接了多少阻抗。你必须在外部把源端和负载端的参考阻抗加上它才能给出和矢量网络分析仪一致的响应。所以验证时一定不要省略R1和R2这两个50欧姆端接电阻。4.2 从AC分析里读出S参数的探针技巧很多工程师跑完AC分析之后不知道怎么看这个模型的S参数。其实在LTspice里只要在网表里做两个小动作就能把S11和S21直接画出来不需要额外工具。原理一句话讲清楚我们给输入端接理想电压源VIN AC 1串联50欧姆源阻抗R1输出端接50欧姆负载R2。在完全匹配的情况下输入节点的电压等于入射波加反射波的电压入射波幅度等于源电压的一半也就是0.5V。所以反射系数S11可以写成2 * V(IN) - 1输出端电压V(P2)等于入射波乘以传输系数再乘以0.5所以S21等于2 * V(P2)。在LTspice里用行为源B1来算这两个表达式V1 IN 0 AC 1 R1 IN P1 50 R2 P2 0 50 X1 P1 P2 0 HDMI_PIN1 B_S21 OUT21 0 V 2*V(P2) B_S11 OUT11 0 V 2*V(IN)-1 .AC DEC 100 100meg 10g .END这样在仿真结果里V(out21)就是S21的幅度和相位V(out11)就是S11单位都是线性值转成dB后就能和CST的S参数曲线直接叠加对比。我这个方法在多个模型上验证过和CST以及实测结果都能对得上误差主要来自模型本身的拟合精度而不是转换过程。4.3 和CST原始仿真结果对比拿到LTspice的AC结果后要把它和CST原始仿真结果放在同一张图里对比。我一般用Python的matplotlib同时读两个CSV一条画CST的S21一条画LTspice的S21。对比时重点看三个地方一是S21的过零点和谐振点位置偏差建议控制在5%以内二是通带内的纹波趋势方向要一致三是阻带衰减的斜率如果趋势都变了说明转换后的等效电路阶数不够或者模型本身拟合残差太大。频率点对比的同时还要跑一次时域验证。给输入端加一个阶跃或者脉冲源观察输出端的上升时间、振铃和过冲。时域波形容易暴露频域对比看不到的问题比如某个极点没有拟合好频域曲线肉眼看不出来时域上却可能出现明显振铃振荡。判断转换成功的标准不是两条曲线完全重合。宽带SPICE模型本质是对S参数的等效逼近一定会在某些频点上出现偏差尤其是靠近模型频带边沿的位置。我自己的工程经验是关键谐振点偏差在5%以内通带趋势一致时域阶跃响应无异常振荡就可以认为这次转换是成功的。如果偏差过大问题通常出在CST模型提取时的设置而不是txt转cir的过程中。5. 我踩过的坑转换过程中最常见的五类报错5.1 Missing .ENDS不是文件截断而是隐藏字符有一次同事把CST导出的txt转成cir后LTspice直接报Fatal Error: Missing .ENDS。当时第一反应是文件被截断了检查了半天发现文件字符数是完整的最后一行确有.ENDS。后来我用Notepad打开显示所有字符才看到文件末尾其实藏着一个UTF-8 BOM和一个零宽空格。解析器在读那行时实际内容被零宽空格隔断.ENDS没有被正确识别成子电路结束语句。排查链路是这样先看报错信息指向的行号在编辑器里跳到文件末尾打开显示所有字符找BOM、零宽空格、行尾符。解决方案很简单把所有不可见字符清除另存成UTF-8无BOM格式重新跑一次就好了。这个坑教会我任何从CST导出的txt第一步永远是预处理不是转格式。5.2 Subcircuit not found子电路名对不上Subcircuit not found这类报错绝大部分原因是调用处的模型名和.SUBCKT后面的模型名不一致。CST导出的子电路名可能很长比如HDMI_PIN1_model_V2你在X元件实例化时图省事写成了HDMI_PIN1_model那LTspice肯定找不到。排查方法是搜索.SUBCKT那一行复制完整的模型名再去检查所有X实例化行的最后一个字段是否一致。这里还要注意大小写CST导出的模型名有时是混合大小写而LTspice在某些版本里对子电路名是区分大小写的。我踩过一次HDMI_PIN1和hdmi_pin1对不上导致的报错。建议在所有文件里统一采用大写模型名省得后面自找麻烦。5.3 Singular matrix悬空节点和负值元件的锅跑时域仿真时报Singular matrix或no DC path to ground第一反应不是去调求解器而是回头查模型文件。SPICE在做直流工作点求解时要求每个节点至少有一条到地的直流通路。CST拟合出来的等效电路里受控源G常常充当信号通路但它本身未必提供直流路径尤其在端口之间只有电容耦合的情况下整条直流通路就是断的。排查方法先在每个外部端口上并联一个1G欧姆的大电阻到0跳过DC求解问题看能不能收敛。如果能收敛说明是直流路径缺失可以用一个合理的大电阻补上如果依然报奇异矩阵就要检查模型里是否有负值元件。CST拟合时为了扩展带宽可能生成负电容或负电感这在频域里合法但在时域里容易导致振荡或者矩阵奇异。你可以在转换脚本里加入对负值元件的警告一旦发现就打印出来。5.4 量级偏差单位后缀把兆当毫这个坑最隐蔽因为它不报错只是曲线整体偏移好几个数量级。我遇到过输出波形完全正常但S21插入损耗凭空多了30dB的情况最后抓着脚本翻半天才意识到模型里有个电阻写成了1M在LTspice里被解析成1毫欧而不是1兆欧。SPICE的规则是后缀M或m默认表示毫milli只有Meg才表示兆mega。这和我们很多工程软件里M表示兆的习惯完全相反。所以转换后务必用正则搜索一下有没有[0-9.]M($|[^A-Za-z])这种模式一旦发现把它替换成[数字]Meg。类似问题还有K好在SPICE对K的千比较宽容大小写都认但严谨起见我也会统一替换。5.5 中文注释带来的乱码与解析错误CST如果是以中文界面或者中文路径导出txt的注释行里很可能出现全角冒号、中文括号、以及一些非ASCII字符。LTspice对注释行的容忍度相对高但HSPICE等老牌仿真器对非ASCII字符很敏感轻则乱码重则该注释行的下一行解析失败。排查时看报错行号往前翻一行十有八九是注释行出了问题。解决方案我在预处理阶段就讲过用正则re.sub(r[^\x00-\x7F], , line)把所有非ASCII字符替换成空格。注意这个操作只对注释行做.SUBCKT后的模型名如果包含了特殊字符你不能简单替换建议手动改成纯ASCII的名字。最后聊一个我自己的习惯。CST导出后我不会立刻修改原始txt而是先复制一份再操作保留干干净净的原始备份。脚本转换也只在副本上跑绝不原地覆盖。这样一旦仿真器报错我能立刻回到源头对比判断问题到底是模型本身带来的还是转换过程中引入的语法错误。如果你只是临时验证用include方案会更稳妥模型文件和仿真文件分离排查问题的时候连备份都不用找。希望这篇把txt到cir的流程讲透了祝你们在CST和电路仿真器之间少折腾几个夜晚。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →