Appearance
附录 B:TDR 文件结构
NOTE
原文来源:Sentaurus Data Explorer User Guide, Version W-2024.09, Synopsys, Inc. PDF 源页码:附录 B,对应 PDF 第 124–125 页
TDR 文件概述
TDR(Technical Data Report)是 TCAD Sentaurus 工具链之间的标准数据交换格式。所有主要工具(SProcess、SMesh、SDevice、SVisual、SDE)都以 TDR 格式读写仿真数据。
为什么需要了解 TDR 结构?
在使用 TDX Tcl 接口编写脚本时,所有函数参数(geometry_index、region_index、state_index、dataset_index)都基于 TDR 的层次结构。理解结构是正确调用函数的前提。
层次结构图示
图:TDR 文件的五层嵌套结构。每一层都有独立的 TagGroup 可附加元数据。
层次结构总览
TDR 文件采用五层嵌套结构:
File / Collection
├── [TagGroup] ← 文件级元数据标签
│
├── Geometry 0 ← 第一个几何体(1D/2D/3D)
│ ├── [TagGroup] ← 几何体级元数据标签
│ │
│ ├── Region 0 ← 区域(材料区或接触区)
│ │ └── [TagGroup]
│ ├── Region 1
│ │ └── [TagGroup]
│ │
│ ├── State 0 ← 仿真状态(如某偏置点、某时间步)
│ │ ├── [TagGroup]
│ │ ├── Dataset 0 ← 某区域某物理量的数据集
│ │ │ └── [TagGroup]
│ │ ├── Dataset 1
│ │ └── Dataset N
│ │
│ └── State 1
│ └── ...
│
├── Geometry 1
│ └── ...
│
└── Geometry N
└── ...NOTE
每个层次都有独立的标签组(TagGroup),可以附加任意自定义元数据(见"标签系统"节)。
各层次详细说明
File / Collection(文件)
- 整个 TDR 文件是一个"集合"(Collection),可包含任意数量的几何体
- 文件本身有一个根级标签组,通常存储创建工具版本、仿真日期等全局元数据
访问方式(Tcl):
tcl
TdrFileOpen "mydevice.tdr"
set num_geom [TdrFileGetNumGeometry "mydevice.tdr"]
set root_tg [TdrFileGetTagGroup "mydevice.tdr"]Geometry(几何体)
特性:
| 属性 | 说明 |
|---|---|
| 维度 | 1D、2D 或 3D,同一文件中不同几何体可有不同维度 |
| 类型 | mixed_element(最常用)、tensor_rectilinear、tensor_xy 等 |
| 名称 | 字符串,如 "geometry_0" |
| 变换矩阵 | 3×3 旋转矩阵,用于坐标变换 |
| 偏移向量 | {x y z},用于几何体位移 |
典型内容:
- 一个 SDevice 仿真的
.tdr文件通常包含 1 个几何体(器件结构)和 若干状态(每个偏置点一个状态) - 一个合并多器件的文件可能包含多个几何体
访问方式(Tcl):
tcl
set gname [TdrGeometryGetName "mydevice.tdr" 0]
set gdim [TdrGeometryGetDimension "mydevice.tdr" 0]
set gtype [TdrGeometryGetType "mydevice.tdr" 0]Region(区域)
特性:
| 属性 | 说明 |
|---|---|
| 名称 | 字符串,对应 SDE/SProcess 中定义的区域名称 |
| 材料 | Sentaurus 材料名(如 "Silicon"、"SiO2"、"Aluminum") |
| 类型 | "bulk"(体区)、"contact"(接触)、"interface" 等 |
| 维度 | 与几何体维度一致,接触区通常低一维 |
注意:区域是网格结构的组成部分,不包含自己的网格节点——节点归属于几何体;数据集则归属于区域在特定状态下的值。
常见区域命名约定:
| 命名风格 | 示例 | 说明 |
|---|---|---|
| 材料名 | silicon, oxide, poly | 按材料命名 |
| 功能名 | channel, gate, source | 按器件功能命名 |
| SDE 默认名 | region_1, region_2 | SDE 自动生成 |
| 接触名 | Anode, Cathode, Gate | 接触区域 |
访问方式(Tcl):
tcl
set nr [TdrGeometryGetNumRegion "mydevice.tdr" 0]
for {set ir 0} {$ir < $nr} {incr ir} {
set rname [TdrRegionGetName "mydevice.tdr" 0 $ir]
set rmat [TdrRegionGetMaterial "mydevice.tdr" 0 $ir]
set rtype [TdrRegionGetType "mydevice.tdr" 0 $ir]
puts "Region $ir: $rname ($rmat, $rtype)"
}State(状态)
特性:
| 属性 | 说明 |
|---|---|
| 名称 | 字符串,如 "global"、"vg=0.5"、"t=1e-9" |
| 用途 | 存储某一特定仿真条件下的物理量快照 |
| 数量 | 同一几何体可有多个状态(如多个偏置点或多个时间步) |
典型的状态分布:
- 直流 IV 扫描:每个偏置点一个状态(如
Vg=0.0、Vg=0.1、...) - 瞬态仿真:每个时间步一个状态(如
t=0、t=1e-10、...) - 单次仿真:通常只有一个状态(通常命名为
"global"或与几何体同名)
访问方式(Tcl):
tcl
set ns [TdrGeometryGetNumState "mydevice.tdr" 0]
puts "Total states: $ns"
for {set is 0} {$is < $ns} {incr is} {
puts "State $is: [TdrStateGetName "mydevice.tdr" 0 $is]"
}Dataset(数据集)
特性:
| 属性 | 说明 |
|---|---|
| 名称 | 字符串,通常与物理量名相同(如 "ElectronConcentration") |
| 物理量(Quantity) | 标准化的物理量标识符,用于工具间对接 |
| 位置(Location) | 数据定义在哪种网格元素上(顶点、边、面、单元等) |
| 结构(Structure) | 标量、矢量或矩阵 |
| 单位 | 如 "cm^-3"、"V"、"A/cm^2" |
数据集与区域的关系:
一个物理量在所有区域中的值分别存储在各自区域下的独立数据集中。
例如,
ElectronConcentration在 silicon 区域和 poly 区域中各有一个数据集,通过region_index来区分。
常见物理量列表:
| 物理量名 | 说明 | 典型单位 |
|---|---|---|
ElectrostaticPotential | 静电势 | V |
ElectronConcentration | 电子浓度 | cm⁻³ |
HoleConcentration | 空穴浓度 | cm⁻³ |
DopingConcentration | 掺杂浓度(净) | cm⁻³ |
DonorConcentration | 施主掺杂浓度 | cm⁻³ |
AcceptorConcentration | 受主掺杂浓度 | cm⁻³ |
ElectricField | 电场强度(矢量) | V/cm |
CurrentDensity | 电流密度(矢量) | A/cm² |
LatticeTemperature | 晶格温度 | K |
eQuasiFermi | 电子准费米势 | V |
hQuasiFermi | 空穴准费米势 | V |
BandGap | 禁带宽度 | eV |
StressXX | 应力张量 XX 分量 | Pa |
OpticalIntensity | 光强度 | W/cm² |
访问方式(Tcl):
tcl
set nd [TdrRegionGetNumDataset "mydevice.tdr" 0 0 0] ;# 几何0,区域0,状态0
for {set id 0} {$id < $nd} {incr id} {
set dname [TdrDatasetGetName "mydevice.tdr" 0 0 0 $id]
set dqty [TdrDatasetGetQuantity "mydevice.tdr" 0 0 0 $id]
set dloc [TdrDatasetGetLocation "mydevice.tdr" 0 0 0 $id]
set dunit [TdrDatasetGetUnit "mydevice.tdr" 0 0 0 $id]
puts "Dataset $id: $dname ($dqty) @ $dloc [$dunit]"
}数据值(Data Value)布局
标量数据集(PerVertex)
对于定义在顶点上的标量量(如静电势、掺杂浓度),每个网格顶点对应一个数据值:
Dataset "ElectronConcentration" (Location: vertex, Structure: scalar)
├── Value 0 → 顶点 0 处的电子浓度
├── Value 1 → 顶点 1 处的电子浓度
├── ...
└── Value N → 顶点 N 处的电子浓度矢量数据集(PerVertex)
对于矢量量(如电场),每个顶点对应一个矢量:
Dataset "ElectricField" (Location: vertex, Structure: vector)
├── Value 0 → 顶点 0 处的电场
│ ├── Row 0 (Ex)
│ └── Row 1 (Ey) ← 2D 几何体
├── Value 1 → 顶点 1 处的电场
└── ...读取矢量分量:
tcl
set ni [TdrDataGetNumRow "mydevice.tdr" 0 0 0 $di $vi] ;# 应为 2(2D)或 3(3D)
for {set i 0} {$i < $ni} {incr i} {
set comp [TdrDataGetComponent "mydevice.tdr" 0 0 0 $di $vi $i]
puts "Component $i: $comp"
}标签系统(Tag Groups and Tags)
标签系统为 TDR 文件的各层次对象提供了可扩展的自定义元数据存储机制。
层次比喻
| 文件系统概念 | TDR 标签概念 |
|---|---|
| 目录 | Tag Group(标签组) |
| 文件 | Tag(标签) |
| 文件名 | Tag 名称 |
| 文件内容 | Tag 值 |
标签组可关联的对象
| 对象层次 | 访问函数 |
|---|---|
| File | TdrFileGetTagGroup |
| Geometry | TdrGeometryGetTagGroup |
| Region | TdrRegionGetTagGroup |
| State | TdrStateGetTagGroup |
| Dataset | TdrDatasetGetTagGroup |
标签的数据结构
结构类型
| 结构 | 说明 | 维度 |
|---|---|---|
"scalar" | 单值标量 | 1×1 |
"matrix" | 矩阵(行×列) | M×N |
"vector" | 矢量(特殊的 N×1 矩阵) | N×1 |
值类型
| 值类型 | 大小 | 备注 |
|---|---|---|
"bool" | 1 bit | TRUE/FALSE |
"int" | 32 bit | 整数 |
"int64" | 64 bit | 长整数 |
"float" | 32 bit | 单精度浮点 |
"double" | 64 bit | 双精度浮点 |
"complex_float" | 64 bit | 复数(单精度) |
"complex_double" | 128 bit | 复数(双精度) |
"string" | 可变 | 仅限 scalar 结构 |
标签使用示例
tcl
# 场景:在仿真结果中附加参数信息,便于后期批量处理
set f "n1_des.tdr"
TdrFileOpen $f
# 在文件级标签组下创建元数据子组
set root_tg [TdrFileGetTagGroup $f]
set meta_tg [TdrTagGroupCreate $root_tg "SimParameters"]
# 添加仿真参数标签
TdrTagCreateScalar $meta_tg "Vg_sweep_step" "double" "0.05"
TdrTagCreateScalar $meta_tg "Temperature_K" "double" "300.0"
TdrTagCreateScalar $meta_tg "ToolVersion" "string" "W-2024.09"
TdrTagCreateScalar $meta_tg "DeviceName" "string" "NMOS_28nm"
# 也可以在几何体级别添加标签
set geom_tg [TdrGeometryGetTagGroup $f 0]
set mesh_tg [TdrTagGroupCreate $geom_tg "MeshInfo"]
TdrTagCreateScalar $mesh_tg "NumVertices" "int" "6461"
TdrTagCreateScalar $mesh_tg "NumElements" "int" "12480"
TdrFileSave $f "n1_des_tagged.tdr"
TdrFileClose $f遍历标签组(递归)
tcl
proc DumpTagGroup {tg depth} {
set indent [string repeat " " $depth]
set nt [TdrTagGroupGetNumTag $tg]
set ntg [TdrTagGroupGetNumTagGroup $tg]
puts "${indent}TagGroup: '[TdrTagGroupGetName $tg]' ($nt tags, $ntg subgroups)"
# 遍历所有标签
for {set i 0} {$i < $nt} {incr i} {
set name [TdrTagGetName $tg $i]
set struct [TdrTagGetStructure $tg $i]
set type [TdrTagGetType $tg $i]
if {$struct eq "scalar"} {
set val [TdrTagGetValue $tg $i]
puts "${indent} Tag[$i]: $name = $val ($type)"
} else {
puts "${indent} Tag[$i]: $name (${struct}, $type)"
}
}
# 递归遍历子标签组
for {set i 0} {$i < $ntg} {incr i} {
set sub_tg [TdrTagGroupGetTagGroup $tg $i]
DumpTagGroup $sub_tg [expr $depth + 1]
}
}
set f "mydevice.tdr"
TdrFileOpen $f
DumpTagGroup [TdrFileGetTagGroup $f] 0
TdrFileClose $f索引规则与注意事项
基本规则
- 所有索引从 0 开始:第一个几何体 = 索引 0,第一个区域 = 索引 0
- 数量函数:使用
GetNum*函数确定上限,然后遍历0到N-1 - 删除操作:在循环中删除条目时,必须从高索引向低索引遍历(反向),否则删除后的重新索引会导致跳过某些条目或越界
反向遍历删除示例
tcl
# 错误做法(正向删除,会跳过条目)
# for {set i 0} {$i < $ns} {incr i} { TdrStateDelete $f 0 $i }
# 正确做法(反向删除)
set ns [TdrGeometryGetNumState $f 0]
for {set i [expr $ns - 1]} {$i >= 0} {incr i -1} {
if {[TdrStateGetName $f 0 $i] ne "keep_this_state"} {
TdrStateDelete $f 0 $i
}
}TDR 与 DF–ISE 的结构对应
从 DF–ISE 格式迁移到 TDR 时,结构对应关系如下:
| DF–ISE 概念 | TDR 对应 | 说明 |
|---|---|---|
.grd 文件(网格) | Geometry(几何体) + Region(区域) | 网格节点和拓扑结构 |
.dat 文件(数据) | State(状态)+ Dataset(数据集) | 物理量场值 |
.bnd 文件(边界) | Geometry(特殊类型) | 边界几何描述 |
.plt 文件(绘图) | Geometry(tensor_xy 类型) | XY 曲线数据 |
.ivl 文件(IV 曲线) | Geometry(tensor_xy 类型) | IV 特性曲线 |
本章小结
| 层次 | 索引参数 | 获取数量函数 | 典型用途 |
|---|---|---|---|
| File | (文件名) | TdrFileGetNumGeometry | 整个仿真集合 |
| Geometry | geom_idx | — | 一个器件结构 |
| Region | reg_idx | TdrGeometryGetNumRegion | 材料层/接触区 |
| State | state_idx | TdrGeometryGetNumState | 某一偏置点/时间步 |
| Dataset | dataset_idx | TdrRegionGetNumDataset | 某一物理量的场值 |
| Value | value_idx | TdrDatasetGetNumValue | 单个网格节点的值 |
TIP
在编写 Tcl 脚本之前,建议先用 tdx -info 命令在命令行查看文件结构,确认各层次的数量和名称,再编写脚本。