在IC设计流程中,物理验证是确保芯片版图正确性的关键步骤。Calibre是业界广泛使用的物理验证工具,但其DRC和LVS的Runset文件路径管理却常常令人头疼。你是否也曾为手动设置 MGC_CALIBRE_DRC_RUNSET_FILE 和 MGC_CALIBRE_LVS_RUNSET_FILE 这类环境变量而感到繁琐?
今天就与大家分享一个实用的SKILL脚本,它能帮你快速加载和管理Calibre Runsets,通过图形化界面实现一键配置,有效提升版图验证环节的工作效率。
核心功能简介
这个SKILL脚本主要实现了以下三大功能,旨在简化工作流:
- 图形界面操作:通过直观的UI界面选择文件,告别记忆和手动输入冗长路径。
- 一键设置环境变量:自动设置
MGC_CALIBRE_DRC_RUNSET_FILE 和 MGC_CALIBRE_LVS_RUNSET_FILE 环境变量。
- 模板保存与加载:可将当前配置保存为模板文件,下次启动时自动加载,实现配置持久化。
建议将 skLoadCalibreRunsets() 函数绑定到Cadence Virtuoso的自定义菜单或工具栏中,以便随时快速调用。
代码解析与实现
主函数:skLoadCalibreRunsets()
这是脚本的入口函数,负责初始化UI并加载已有的模板配置。
procedure(skLoadCalibreRunsets()
let((out dataTable form)
; 生成表单
skLoadCalibreRunsetsFormGen()
; 加载模板文件
out = skLoadCalibreRunsets_loadTmpFile()
dataTable = out->data
form = skLoadCalibreRunsetsForm
; 如果模板文件中有数据,填充到表单中
when(dataTable
when(dataTable["drcRunset"]
form->drcRunset->value = dataTable["drcRunset"]
)
when(dataTable["lvsRunset"]
form->lvsRunset->value = dataTable["lvsRunset"]
)
form->tmpFile->value = out->file
)
; 显示表单
hiDisplayForm('skLoadCalibreRunsetsForm)
t
)
)
这个函数负责创建图形用户界面,包含了版图验证工作流中所需的全部交互组件。
;; 生成表单
procedure(skLoadCalibreRunsetsFormGen()
let((drcRunset drcRunsetBtn lvsRunset lvsRunsetBtn
tmpFile tmpFileBtn setRunsetsEnvBtn)
; 创建DRC Runset输入框和按钮
drcRunset = hiCreateStringField(
?name 'drcRunset
?prompt "DRC Runset"
?value ""
)
drcRunsetBtn = hiCreateButton(
?name 'drcRunsetBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'drcRunset \"**\" 'existingFile \"Select DRC Runset\")"
)
; 创建LVS Runset输入框和按钮
lvsRunset = hiCreateStringField(
?name 'lvsRunset
?prompt "LVS Runset"
?value ""
)
lvsRunsetBtn = hiCreateButton(
?name 'lvsRunsetBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'lvsRunset \"**\" 'existingFile \"Select LVS Runset\")"
)
; 创建模板文件输入框和按钮
tmpFile = hiCreateStringField(
?name 'tmpFile
?prompt "Template"
?value ""
)
tmpFileBtn = hiCreateButton(
?name 'tmpFileBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'tmpFile \"**\" 'existingFile \"Select Template File\")"
)
; 创建设置环境变量按钮
setRunsetsEnvBtn = hiCreateButton(
?name 'setRunsetsEnvBtn
?buttonText "Set Runsets"
?callback "skLoadCalibreRunsets_CB(hiGetCurrentForm() 0)"
)
; 创建表单
skLoadCalibreRunsetsForm = hiCreateAppForm(
?name 'skLoadCalibreRunsetsForm
?formTitle "Load Calibre Runsets"
?fields list(
list(drcRunset 0:0 530:30 75)
list(drcRunsetBtn 530:3 65:27 65)
list(lvsRunset 0:40 530:30 75)
list(lvsRunsetBtn 530:43 65:27 65)
list(tmpFile 0:80 530:30 75)
list(tmpFileBtn 530:83 65:27 65)
list(setRunsetsEnvBtn 30:120 530:30 65)
)
?buttonLayout 'Close
?minSize 600:200
?callback "printf(\"skMsg Info: skLoadCalibreRunsetsForm closed !\n\")"
)
skLoadCalibreRunsetsForm
)
)
界面包含:
- DRC Runset选择框:用于选择DRC(设计规则检查)规则文件。
- LVS Runset选择框:用于选择LVS(版图与原理图对比)规则文件。
- 模板文件选择框:用于保存当前配置或加载历史配置。
- Set Runsets按钮:点击后执行环境变量设置与模板保存操作。
回调函数:skLoadCalibreRunsets_CB()
这是“Set Runsets”按钮点击后的处理逻辑,核心任务是设置环境变量并保存配置。
procedure(skLoadCalibreRunsets_CB(form arg "rx")
prog((dir tmpFile dataTable saved)
case(arg
(0 ; 设置环境变量并保存模板
; 设置DRC Runset环境变量
if(isFile(form->drcRunset->value) then
setShellEnvVar("MGC_CALIBRE_DRC_RUNSET_FILE" form->drcRunset->value)
else
warn("DRC Runset file not found: %A.\n" form->drcRunset->value)
)
; 设置LVS Runset环境变量
if(isFile(form->lvsRunset->value) then
setShellEnvVar("MGC_CALIBRE_LVS_RUNSET_FILE" form->lvsRunset->value)
else
warn("LVS Runset file not found: %A.\n" form->lvsRunset->value)
)
; 保存模板文件
tmpFile = form->tmpFile->value
unless(isFile(tmpFile)
; 如果模板文件不存在,则使用默认路径
dir = sprintf(nil "%s/%s" getWorkingDir() "/.skKit/")
unless(isDir(dir)
createDir(dir)
)
tmpFile = sprintf(nil "%s/%s" dir "skRunsetsTmp.txt")
form->tmpFile->value = tmpFile
)
; 创建数据表并保存
dataTable = makeTable("dataTable" nil)
dataTable["drcRunset"] = form->drcRunset->value
dataTable["lvsRunset"] = form->lvsRunset->value
saved = writeTable(tmpFile dataTable)
if(saved then
printf("Template file saved to: %s.\n" tmpFile)
else
warn("Failed to save template file to: %s.\n" tmpFile)
)
)
(t
warn("Not supported arg - %A.\n" arg)
return(t)
)
)
return(t)
)
)
配置加载函数:skLoadCalibreRunsets_loadTmpFile()
此函数用于读取之前保存的模板文件,实现配置持久化,确保每次启动都能恢复工作现场。
procedure(skLoadCalibreRunsets_loadTmpFile(@optional dir(getWorkingDir()) fileName("skRunsetsTmp.txt") "t")
prog((dataTable tmpFile)
; 检查目录是否可读
unless(isReadable(dir)
warn("Directory no permissions to read: %s.\n" dir)
return(nil)
)
; 构建模板文件路径
tmpFile = simplifyFilename(sprintf(nil "%s/.skKit/%s" dir fileName))
; 检查模板文件是否存在
unless(isFile(tmpFile)
warn("Template file not existed: %s.\n" tmpFile)
return(nil)
)
; 读取模板文件
dataTable = makeTable("dataTable" nil)
readTable(tmpFile dataTable)
return(list(nil 'file tmpFile 'data dataTable))
)
)
使用方式
- 将下方提供的完整代码保存为
skLoadCalibreRunsets.il 文件。
- 在Cadence Virtuoso的CIW窗口或你的SKILL初始化文件中加载该脚本。
load("home/scripts/skLoadCalibreRunsets.il")
- 加载后,在CIW中输入
skLoadCalibreRunsets() 即可唤起图形化设置界面。
完整代码
以下为完整的SKILL脚本代码,你可以直接复制使用。
procedure(skLoadCalibreRunsets()
let((out dataTable form)
unless(boundp('skLoadCalibreRunsetsForm)
skLoadCalibreRunsetsFormGen()
)
out = skLoadCalibreRunsets_loadTmpFile()
dataTable = out->data
form = skLoadCalibreRunsetsForm
when(dataTable
when(dataTable["drcRunset"]
form->drcRunset->value = dataTable["drcRunset"]
)
when(dataTable["lvsRunset"]
form->lvsRunset->value = dataTable["lvsRunset"]
)
form->tmpFile->value = out->file
)
hiDisplayForm('skLoadCalibreRunsetsForm)
t
)
)
procedure(skLoadCalibreRunsetsFormGen()
let((drcRunset drcRunsetBtn lvsRunset lvsRunsetBtn
tmpFile tmpFileBtn setRunsetsEnvBtn)
;
drcRunset = hiCreateStringField(
?name 'drcRunset
?prompt "DRC Runset"
?value ""
)
drcRunsetBtn = hiCreateButton(
?name 'drcRunsetBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'drcRunset \"**\" 'existingFile \"Select DRC Runset\")"
)
lvsRunset = hiCreateStringField(
?name 'lvsRunset
?prompt "LVS Runset"
?value ""
)
lvsRunsetBtn = hiCreateButton(
?name 'lvsRunsetBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'lvsRunset \"**\" 'existingFile \"Select LVS Runset\")"
)
tmpFile = hiCreateStringField(
?name 'tmpFile
?prompt "Template"
?value ""
)
tmpFileBtn = hiCreateButton(
?name 'tmpFileBtn
?buttonText "Load.."
?callback "ddsFileBrowseCB(hiGetCurrentForm() 'tmpFile \"**\" 'existingFile \"Select Template File\")"
)
setRunsetsEnvBtn = hiCreateButton(
?name 'setRunsetsEnvBtn
?buttonText "Set Runsets"
?callback "skLoadCalibreRunsets_CB(hiGetCurrentForm() 0)"
)
skLoadCalibreRunsetsForm = hiCreateAppForm(
?name 'skLoadCalibreRunsetsForm
?formTitle "Load Calibre Runsets"
?fields list(
list(drcRunset 0:0 530:30 75)
list(drcRunsetBtn 530:3 65:27 65)
list(lvsRunset 0:40 530:30 75)
list(lvsRunsetBtn 530:43 65:27 65)
list(tmpFile 0:80 530:30 75)
list(tmpFileBtn 530:83 65:27 65)
list(setRunsetsEnvBtn 30:120 530:30 65)
)
?buttonLayout 'Close
?minSize 600:200
?callback "printf(\"skMsg Info: skLoadCalibreRunsetsForm closed !\n\")"
)
skLoadCalibreRunsetsForm
)
)
procedure(skLoadCalibreRunsets_CB(form arg "rx")
prog((dir tmpFile dataTable saved)
case(arg
(0
if(isFile(form->drcRunset->value) then
setShellEnvVar("MGC_CALIBRE_DRC_RUNSET_FILE" form->drcRunset->value)
else
warn("DRC Runset file not found: %A.\n" form->drcRunset->value)
)
if(isFile(form->lvsRunset->value) then
setShellEnvVar("MGC_CALIBRE_LVS_RUNSET_FILE" form->lvsRunset->value)
else
warn("LVS Runset file not found: %A.\n" form->lvsRunset->value)
)
;Save template file
tmpFile = form->tmpFile->value
unless(isFile(tmpFile)
dir = sprintf(nil "%s/%s" getWorkingDir() "/.skKit/")
unless(isDir(dir)
createDir(dir)
)
tmpFile = sprintf(nil "%s/%s" dir "skRunsetsTmp.txt")
form->tmpFile->value = tmpFile
)
dataTable = makeTable("dataTable" nil)
dataTable["drcRunset"] = form->drcRunset->value
dataTable["lvsRunset"] = form->lvsRunset->value
saved = writeTable(tmpFile dataTable)
if(saved then
printf("Template file saved to: %s.\n" tmpFile)
else
warn("Failed to save template file to: %s.\n" tmpFile)
)
)
(t
warn("Not supported arg - %A.\n" arg)
return(t)
)
)
return(t)
)
)
procedure(skLoadCalibreRunsets_loadTmpFile(@optional dir(getWorkingDir()) fileName("skRunsetsTmp.txt") "t")
prog((dataTable tmpFile)
unless(isReadable(dir)
warn("Directory no permissions to read: %s.\n" dir)
return(nil)
)
tmpFile = simplifyFilename(sprintf(nil "%s/.skKit/%s" dir fileName))
unless(isFile(tmpFile)
warn("Template file not existed: %s.\n" tmpFile)
return(nil)
)
dataTable = makeTable("dataTable" nil)
readTable(tmpFile dataTable)
return(list(nil 'file tmpFile 'data dataTable))
)
)
希望这个SKILL脚本能帮助各位IC设计工程师更高效地管理Calibre验证环境。如果你有更好的优化想法或使用中遇到了问题,欢迎在云栈社区的相应板块进行交流与探讨。