第一次接触dbGet命令时,我和大多数工程师一样,只是把它当作简单的数据库查询工具。直到某次项目签核前的深夜,面对堆积如山的物理验证报告,我偶然发现dbGet能直接提取金属层间距违规标记的坐标——这个发现彻底改变了我的工作方式。物理设计验证(Physical Verification)阶段最头疼的就是海量数据的快速定位,而dbGet用一行命令就能替代传统GUI界面里重复的点击操作。
举个例子,要检查时钟网络完整性,传统方法需要在布局布线工具中逐个查看时钟树节点。而用dbGet [dbGet top.nets.isCTSClock 1 -p].name -u可以直接列出所有CTS时钟网络,配合dbGet [dbGet top.insts.instTerms.name *clk* -p].pt甚至能批量输出时钟引脚坐标。这种效率提升在项目后期尤为明显,特别是当需要反复验证不同corner条件下的物理规则时。
在28nm以下工艺节点,物理单元的使用合规性直接影响芯片良率。我曾用dbGet [dbGet top.insts.cell.name *TAP* -p2].name扫描整个设计的阱接触单元分布,发现某些区域密度不足标准值的60%。更智能的用法是结合坐标过滤:先获取区块边界dbGet top.fPlan.box.size,再用-area参数限定查询范围,这样就能分区域统计物理单元覆盖率。
设计规则检查(DRC)往往在最后阶段才暴露问题。通过组合查询可以提前预警,比如检测固定位置的实例是否被意外移动:
tcl复制set fixed_insts [dbGet [dbGet top.insts.pStatus fixed -p].name]
foreach inst $fixed_insts {
set new_coord [dbGet [dbGet top.insts.name $inst -p].pt]
if {$new_coord != $original_coord} {
puts "违规移动:$inst 新坐标 $new_coord"
}
}
电源网络审计是签核前的必选项。这条命令链能一次性输出所有电源域的网络连接状态:
tcl复制dbGet top.fPlan.groups.pd.name | foreach pd {
set nets [dbGet [dbGet top.nets.powerDomain $pd -p].name]
set pins [llength [dbGet top.terms.supplyNet $pd -p]]
puts "$pd : 网络数 [llength $nets] 引脚数 $pins"
}
在先进工艺中,制造网格(mfgGrid)偏差会导致光刻问题。通过dbGet head.mfgGrid获取基准值后,可以用以下脚本验证所有金属层:
tcl复制set layers [dbGet [dbGet head.layers.type routing -p].name]
foreach layer $layers {
set pitch [dbGet [dbGet head.layers.name $layer -p].pitch]
if {[expr $pitch % $mfgGrid] != 0} {
puts "警告:$layer 间距 $pitch 不符合网格约束"
}
}
dbGet的强大之处在于嵌套查询。比如要分析时钟网络负载,可以这样获取所有触发器时钟端的电容值:
tcl复制set ff_pins [dbGet [dbGet top.insts.cell.isSequential 1 -p].instTerms.name *clk* -p]
dbGet [dbGet selected.instTerms.name $ff_pins -p].cap -u
这里的-p参数表示保留父对象关系,-u用于去重,避免重复计算同一单元的多个实例。
当处理大型设计时,直接dbGet top.insts.name可能返回数百万个实例。更高效的做法是分条件查询:
tcl复制# 先获取模块边界
set block_box [dbGet top.fPlan.box]
# 只查询左上象限的实例
dbGet top.insts.name -area [list [lindex $block_box 0] [lindex $block_box 1] \
[expr [lindex $block_box 0]+[lindex $block_box 2]/2] \
[expr [lindex $block_box 1]+[lindex $block_box 3]/2]]
dbGet返回的列表可以直接用Tcl处理。比如统计不同VT类型单元占比:
tcl复制set total [llength [dbGet top.insts.name]]
set ulvt [llength [dbGet top.insts.cell.name *ULVT* -p2]]
set lvt [llength [dbGet top.insts.cell.name *LVT* -p2]]
puts "ULVT占比:[expr {$ulvt*100.0/$total}]% LVT占比:[expr {$lvt*100.0/$total}]%"
在7nm项目中,我发现直接查询top.insts可能导致工具卡死。解决方案是分层次处理:
tcl复制foreach hier [dbGet top.children.name] {
set insts [dbGet $hier.insts.name]
# 处理子模块实例...
}
另外,善用-limit 1000参数限制单次返回数量,配合循环分批处理大数据集。
自动化查询需要双重验证。比如检查电源网络连接时,我会随机抽样:
tcl复制set sample [lindex [dbGet top.nets.isPwrOrGnd 1 -p].name 10]
dbGet [dbGet top.nets.name $sample -p].terms.name
然后手动在GUI中核对抽样结果,确保查询逻辑正确。
不是所有对象都包含查询的属性。稳健的脚本应该包含异常捕获:
tcl复制set cells [dbGet top.insts.cell.name -u]
foreach cell $cells {
if {[catch {dbGet [dbGet head.libCells.name $cell -p].size_x} size]} {
set size "N/A"
}
puts "$cell : $size"
}
建立个人查询模板能大幅提升效率。我的常用模板包括:
比如快速定位天线效应违例:
tcl复制set markers [dbGet top.markers.userType ANTENNA -p]
foreach marker $markers {
set viol_area [dbGet $marker.box]
set viol_net [dbQuery -area $viol_area -objType net]
puts "违例网络:$viol_net 坐标:$viol_area"
}