脚本化使用 Xschem 创建反相器:schematic 与 symbol 的完整流程
本教程通过 Tcl 直接生成 Xschem 文本文件,创建一个逻辑反相器 schematic,以及与它配对的层级 symbol。为了避免依赖未知 PDK 的引脚坐标,schematic 采用 SPICE 行为电压源表达反相逻辑,不冒充晶体管级 CMOS 实现。文末给出迁移到晶体管级设计的检查步骤。本文示例未在实际 Xschem 环境执行验证。
一、原理与输出文件
Xschem 官方手册说明了 .sch/.sym 文本格式;官方符号生成器教程展示了脚本输出 symbol 的方法。本例使用 tclsh 写文件,不通过鼠标操作,也不依赖未经核实的 GUI Tcl 命令。生成 inv.sch、inv.sym、top.sch 三个文件,同一目录保存。
- inv.sch:四个接口 A、Y、VDD、VSS,以及反相行为源。
- inv.sym:三角形加反相圆圈,四个显式电气引脚。
- top.sch:实例化 inv.sym,用于检查层级配对。
- 输出目录存在目标文件时拒绝覆盖。
二、完整 Tcl 生成器
保存为 generate_inv.tcl。代码中的花括号是 Tcl 语法,复制时应保留普通花括号。Xschem 的标准 devices 库必须能解析输入、输出和双向端口符号,以及 code_shown.sym。
set out ./inv_demo
file mkdir $out
foreach name {inv.sch inv.sym top.sch} {
if {[file exists [file join $out $name]]} {
error "Output exists: $name; use a new directory"
}
}
proc save_text {path text} {
set f [open $path w]
puts $f $text
close $f
}
save_text [file join $out inv.sch] {v {xschem version=3.4.5 file_version=1.2}
G {}
K {}
V {}
S {}
E {}
C {devices/ipin.sym} -100 0 0 0 {name=pA lab=A}
C {devices/opin.sym} 100 0 0 0 {name=pY lab=Y}
C {devices/iopin.sym} 0 -100 0 0 {name=pVDD lab=VDD}
C {devices/iopin.sym} 0 100 0 0 {name=pVSS lab=VSS}
C {devices/code_shown.sym} -180 180 0 0 {name=BEHAVIOR only_toplevel=false value="BINV Y VSS V=V(VDD,VSS)-V(A,VSS)"}
}
save_text [file join $out inv.sym] {v {xschem version=3.4.5 file_version=1.2}
G {}
K {type=subcircuit
format="@name @pinlist @symname"
template="name=X1"}
V {}
S {}
E {}
L 4 -30 -30 -30 30 {}
L 4 -30 -30 25 0 {}
L 4 -30 30 25 0 {}
A 4 30 0 5 0 360 {}
L 4 -60 0 -30 0 {}
L 4 35 0 60 0 {}
L 4 0 -50 0 -30 {}
L 4 0 30 0 50 {}
T {@name} -25 -65 0 0 0.2 0.2 {}
T {A} -55 -20 0 0 0.2 0.2 {}
T {Y} 45 -20 0 0 0.2 0.2 {}
T {VDD} 5 -50 0 0 0.15 0.15 {}
T {VSS} 5 35 0 0 0.15 0.15 {}
B 5 -62.5 -2.5 -57.5 2.5 {name=A dir=in}
B 5 57.5 -2.5 62.5 2.5 {name=Y dir=out}
B 5 -2.5 -52.5 2.5 -47.5 {name=VDD dir=inout}
B 5 -2.5 47.5 2.5 52.5 {name=VSS dir=inout}
}
save_text [file join $out top.sch] {v {xschem version=3.4.5 file_version=1.2}
G {}
K {}
V {}
S {}
E {}
C {inv.sym} 0 0 0 0 {name=X1}
}
puts "Generated inv.sch, inv.sym and top.sch in $out"三、运行与打开
tclsh generate_inv.tcl
cd inv_demo
xschem inv.sch
# 在另一个会话中检查 symbol 的层级实例
xschem top.sch检查三个文件都存在,然后打开 inv.sch 核对四个端口名称。打开 top.sch 后检查 X1 是否显示为反相器,并通过层级进入它对应的 inv.sch。若本地文件未找到,应先检查启动目录和 symbol 搜索路径;脚本不负责安装 Xschem、Tcl 或配置库。
四、理解 schematic 的实现
本例把 SPICE 行为源放在 code_shown.sym 的 value 中,并设置 only_toplevel=false,使它用于层级内实现。电气表达式为 V(Y,VSS)=V(VDD,VSS)-V(A,VSS)。当 VDD=1.8V、VSS=0V 时,A=0V 对应 Y=1.8V,A=1.8V 对应 Y=0V。
这是连续线性电压映射,不是具有阈值、延迟和饱和特性的真实 CMOS 反相器:输入超出供电范围时,输出也可超出范围;电源引脚只是表达式参考,不反映真实供电电流。该模型仅用于学习脚本生成与层级接口。
五、理解 symbol 的实现
L、A、T 分别用于线条、圆弧和文字;B 5 矩形定义电气引脚。反相圆圈本身不会产生电气反相功能。四个 B 5 引脚依次为 A、Y、VDD、VSS,中心坐标为 (-60,0)、(60,0)、(0,-50)、(0,50)。
K 区 type=subcircuit 表示存在对应 schematic 的层级块;format 使用 @name、@pinlist、@symname 生成子电路调用。inv.sym 与 inv.sch 使用相同基名,端口名称须一致。官方教程指出,pinlist 展开顺序取决于 symbol 的引脚顺序,不能仅凭图形左右位置推断。
六、先检查网表,再谈仿真
top.sch 中 X1 未接线,是层级查看用页面,不是完整 testbench。对它生成 SPICE 网表时应检查 inv 子电路内容、接口顺序和 BINV 行;不要直接将悬空顶层实例作为仿真电路。
.subckt inv A Y VDD VSS
BINV Y VSS V=V(VDD,VSS)-V(A,VSS)
.ends inv实际网表的大小写及端口排列以产物为准,X 调用的参数顺序必须匹配 .subckt 定义。确认 BINV 确实位于 inv 内部,没有被仅顶层输出规则过滤,并确认没有重复的子电路定义。
七、独立 ngspice testbench
下面手写网表先验证行为表达式。它没有自动使用生成的 Xschem 网表;后续应将其中 inv 定义替换为实际生成且已检查的子电路,才算端到端验证。
* Teaching model, not a transistor-level simulation
.subckt inv A Y VDD VSS
BINV Y VSS V=V(VDD,VSS)-V(A,VSS)
.ends inv
VDD VDD 0 1.8
VIN A 0 PULSE(0 1.8 1n 100p 100p 5n 10n)
X1 A Y VDD 0 inv
.tran 10p 30n
.control
run
plot v(A) v(Y)
.endc
.end保存后运行 ngspice tb_inv.cir。预期两个波形反相;本文没有实际运行,也不报告仿真通过或性能指标。
八、升级为晶体管级 CMOS schematic
保留 inv.sym 的四端口接口,将 inv.sch 中行为源替换为 PMOS、NMOS 和连线。连接目标如下:
- PMOS:D=Y,G=A,S=VDD,B=VDD。
- NMOS:D=Y,G=A,S=VSS,B=VSS。
- 删除行为源,避免 Y 被理想源和晶体管同时驱动。
- 从实际 PDK symbol 读取引脚中心,再计算实例坐标与导线端点。
- 核对工艺模型、W/L 参数单位、器件前缀及模型包含语句。
不能把一个 PDK 的坐标和 MOS 的 M 行格式照搬到另一个 PDK。实际器件可能使用 X 子电路调用,需以 symbol 的 format 为依据。完成后必须检查连接、端口顺序、工艺角落和负载,并做瞬态与直流验证。
九、工程化验收清单
- 文件生成可重复,重要文件不被静默覆盖。
- 本地 symbol 和标准端口库均能解析。
- 四个端口在 schematic 与 symbol 中一致。
- 层级能进入对应 schematic,网表定义和调用顺序一致。
- 行为模型与晶体管模型明确区分。
- 把版本、生成脚本、网表差异及仿真日志纳入回归。