ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

IC617下CDB转OA:cds.lib与Conversion Toolbox

IC617下CDB转OA:cds.lib与Conversion Toolbox

简介:面向仍在使用 IC514/IC617、需要把旧工艺库从 CDB 迁移到 OpenAccess 的 Cadence 模拟版图设计与 PDK 维护人员,这份 PDF 围绕 cdb2oa 数据转换展开,重点解决旧工艺库在新平台打开时提示 OA executable on CDB data、库无法正常加载等问题。压缩包仅含 1 个 PDF 文件,大小约 697KB,篇幅紧凑,便于随查随用;内容涉及 cdb2oa 命令行转换、Conversion Toolbox 与 CDB to OpenAccess Translator 的路径选择、Virtuoso 中 Library Path 的保存位置,以及转换后库的检查与验证思路,并梳理常见警告信息的成因与排查方向。已有 1557 人学习,说明该主题在实际项目中需求稳定。读者可据此理解 CDB 与 OA 的数据差异,掌握旧 PDK 库迁移的完整流程与易错点,减少因格式不兼容导致的反复试错,适合作为工艺库升级与版图环境搭建时的参考手册。

1. 从 IC514 到 IC617:CDB轉換為OA 不是改后缀,是换运行底座

把旧工艺库从 IC514 环境搬到 IC617 时,很多人第一反应是“库还在,路径也没改,顶多报个版本警告”。实际打开 Virtuoso 后,CIW 里直接刷出Warning: ddUpdateLibList: It appears that you are trying to run an OA executable on CDB data. Library 'demo035' contains 'prop.xx' which is CDB data.,库管理器里看着有库名,可 cellview 就是打不开。这个坑很常见:IC514 时代大量 PDK 是 CDB 数据,IC617 默认按 OA 运行,CDB 库不是改个后缀就能用。CDB轉換為OA 要动的是库的底层格式。适合手上还留着老 PDK、又必须在新 IC617 环境里复现的人;装不好不会立刻崩,但会在打开库、跑仿真、存版图时反复翻车。

2. 环境清单与版本确认:IC617、PDK、cds.lib 和 cdb2oa 的四个必查项

2.1 先确认 Virtuoso 是 IC617 且带 OA 运行库

转换前第一件事不是找 cdb2oa,而是确认你当前 shell 里启动的 Virtuoso 到底是哪一套。机器上同时装 IC514 和 IC617 的情况太常见了,.bashrc里PATH一抖,virtuoso&启起来的可能就是旧版本。旧版本能打开 CDB 库,你会误以为库没问题,等换到 IC617 才发现数据根本不兼容。常见做法是先看which virtuoso,再看安装目录和版本输出;不同安装包的版本参数不完全一样,-version不认就用安装目录名和启动日志确认。

# 确认当前 shell 实际调用的 virtuoso which virtuoso # 查看版本输出,不同安装包参数可能不同,认不出就看下一行 virtuoso -version 2>&1 | head -n 5 # 确认安装根目录,目录名通常能看出 IC617 这一代 echo "$CDS_INST_DIR"

which virtuoso决定你后面所有 GUI 操作到底跑在哪个版本上;$CDS_INST_DIR是安装根目录,切换环境时最容易漏掉。我一般会把这个结果记在转换笔记第一行,因为后面一旦报错,先回头核对“我刚才开的到底是 IC617 还是 IC514”。如果which指到旧路径,不要急着改系统环境,先在一个干净终端里显式sourceIC617 的环境脚本,再启动 Virtuoso。这样不会把整台机器的默认环境搞乱,也方便回滚。

环境对照可以先列成一张表,后面每一步都围着这几项转:

检查项应该是什么状态常见错误状态
Virtuoso 版本IC617 这一代实际启动的是 IC514
库格式CDB 待转 OA把 OA 库又转一遍
PDK 目录有cds.lib,库目录完整只拷了部分库,缺prop.xx
转换入口Conversion Toolbox 可用只找到旧脚本,参数不匹配
写权限工作目录和 PDK 副本可写直接改只读 PDK,转换中断

2.2 找到 PDK 的 cds.lib,不要拿错库文件

cdb2oa 转换时最关键的一个输入不是某个 cellview,而是cds.lib。这个文件告诉工具库名和库路径的对应关系,选错cds.lib,后面要么转出一个空库,要么把不相干的库一起拖进来。旧 PDK 目录里经常不止一个cds.lib:顶层有一个,子目录里可能还有示例工程带的,甚至有人手工复制过一份改过路径的。我的习惯是先find出候选,再用grep DEFINE看它到底定义了哪些库。

# 在 PDK 根目录下找 cds.lib,限制深度,避免翻进无关目录 find /path/to/pdk -maxdepth 3 -name cds.lib -print # 看候选 cds.lib 里定义了哪些库,确认库名和路径 grep -n "^DEFINE" /path/to/pdk/cds.lib

-maxdepth 3是为了别把整个磁盘翻一遍;grep "^DEFINE"只看库定义行,避免被注释和INCLUDE干扰。你要找的是那个能覆盖目标工艺库的cds.lib,不是随便一个示例工程的。常见做法是优先用 PDK 根目录下的那一份,如果它里面只有INCLUDE,再顺着INCLUDE指向的文件看。注意:如果cds.lib里的路径是相对路径,转换时工作目录一变就可能解析不到,后面第 3 章会把它保存到 home 下再检查。

提示:不要直接拿 IC514 工程目录里的cds.lib做转换输入,工程级cds.lib往往混进了设计库和临时库,转换工具会把不该转的库也列出来。

2.3 备份 PDK 与建立转换工作目录

转换本身会写文件,最怕的是直接在只读 PDK 或唯一一份 PDK 上操作。血泪经验是:先把整个 PDK 复制一份工作副本,所有转换输出先落在 home 下的工作目录,确认没问题再替换回 PDK。这样即使转换中断,原来的 CDB 库还在,不用到处找后悔药。复制前用du -sh看一眼大小,别把几个 GB 的库复制到空间不足的分区。

# 建立转换工作目录,所有输出先放这里 export CDB2OA_WORK="$HOME/cdb2oa_work" mkdir -p "$CDB2OA_WORK" # 复制一份 PDK 工作副本,保留原目录不动 cp -a /path/to/pdk "$CDB2OA_WORK/pdk_backup" # 看大小和权限,确认后续可写 du -sh "$CDB2OA_WORK/pdk_backup" ls -ld "$CDB2OA_WORK/pdk_backup"

cp -a保留权限和时间戳,后面排查“为什么转换工具说没权限”时有用;du -sh只是确认空间,不是必须。工作目录放在$HOME下有一个好处:Virtuoso 默认对 home 有写权限,转换工具输出到 home 时不容易被系统目录权限拦住。如果 PDK 很大,至少要把目标工艺库目录和它的cds.lib复制出来,不要只复制一个空壳。

2.4 检查 cdb2oa / Conversion Toolbox 是否可用

转换入口有两类:一类是 Virtuoso 菜单里的 Conversion Toolbox,另一类是命令行cdb2oa。项目正文走的是 GUI:启动 Conversion Toolbox,打开 CDB to OpenAccess Translator,选 PDK 里的cds.lib,然后等转换完成。命令行入口适合做小样本验证,但整库转换还是 GUI 更稳,因为它会把库级依赖一起处理。先确认命令是否存在,不存在的机器就直接走 GUI,不要硬凑命令。

# 看命令行入口是否在 PATH 中 which cdb2oa # 如果存在,先看帮助,确认参数含义 cdb2oa -help 2>&1 | head -n 40

which cdb2oa找不到不代表转换做不了,只说明当前 shell 没带这个入口;cdb2oa -help的输出才是本机参数准绳。摘要里常见的cdb2oa -i input.cdb -o output.oa更像单文件级示例,实际整库转换输出的是一个库目录,不是单个.oa文件。参数取舍上,我一般先用 GUI 跑通整库,再用命令行做单库复验;两者不要混着用,否则输出目录结构会对不上。

3. 转换前配置:在 home 下重建 Library Path 并保存 cds.lib

3.1 为什么要先在 home 下打开 virtuoso&

项目正文的第一步很朴素:在 home 下方打开virtuoso&,进入 Edit -> Library Path,File -> Save As,选择 home 目录保存。很多人会跳过这一步,直接开 Conversion Toolbox 选 PDK 里的cds.lib,结果转换工具读到的库路径和 Virtuoso 实际看到的不是同一套。先在 home 下启动 Virtuoso,是为了让当前会话的库搜索路径从 home 出发,保存出来的cds.lib路径干净、可控,不会混进旧工程的相对路径。

# 先回到 home,避免在 PDK 目录里启动后保存出相对路径 cd "$HOME" # 启动 IC617 的 Virtuoso,确认 CIW 能正常起来 virtuoso &

cd "$HOME"是关键,后面File -> Save As保存到 home 时,cds.lib里的路径更不容易写成相对路径;virtuoso &放后台启动,终端还能继续用。启动后先看 CIW 有没有一长串ddUpdateLibList警告,有警告不一定是坏事,它正好说明当前库还是 CDB 数据,后面转换就是冲它去的。如果 Virtuoso 根本起不来,先回去查第 2 章的版本和 license,不要在这里继续。

3.2 用 Library Path 编辑器保存一份干净 cds.lib

GUI 操作顺序按项目正文走:Virtuoso 启动后进入Edit -> Library Path,在编辑器里确认库路径列表,然后File -> Save As,选择 home 目录保存,点OK。保存出来的文件通常就是cds.lib,它是转换工具的输入,也是后面检查库名和路径的依据。这里不要手抖保存到 PDK 原目录,先把干净副本放 home,后面确认无误再决定要不要覆盖。

步骤清单可以按这个顺序走:

  1. 在 home 下启动virtuoso&,等 CIW 完全起来。
  2. 菜单Edit -> Library Path,看当前库路径列表。
  3. File -> Save As,路径选$HOME,文件名保持cds.lib。
  4. 点OK保存,回到终端确认文件存在。
  5. 用grep DEFINE检查库名和路径,别急着开转换工具。
# 确认 home 下已经生成 cds.lib ls -l "$HOME/cds.lib" # 看保存出来的库定义,重点看目标工艺库那一行 grep -n "^DEFINE" "$HOME/cds.lib"

ls -l看文件是否真的落盘,grep "^DEFINE"看库名和路径。保存出来的cds.lib里如果出现INCLUDE,要顺着看被包含文件里的DEFINE,转换工具最终认的是展开后的库列表。常见做法是先把目标工艺库那一行确认清楚,其他设计库可以先注释掉或留到后面再加,避免转换范围过大。

3.3 检查 cds.lib 里的 DEFINE 行和路径顺序

cds.lib的路径顺序会影响 Virtuoso 找库的优先级。旧 PDK 的cds.lib里经常有多个DEFINE指向不同版本的同名库,或者前面一个INCLUDE又把旧路径带回来。转换前要确认目标库只出现一次,路径指向你准备转换的那份 CDB 数据,而不是某个已经半转过的目录。

# cds.lib 里典型的库定义,库名和路径按实际替换 DEFINE demo035 /path/to/pdk/demo035 DEFINE demo035_oa /path/to/pdk/demo035_oa INCLUDE /path/to/pdk/other_libs.cds.lib

上面只是结构示例,DEFINE后面第一个字段是库名,第二个字段是库目录;INCLUDE会把另一份库列表带进来。检查时重点看三件事:目标库名有没有重复、路径是不是指向 CDB 数据、INCLUDE进来的文件里有没有把旧库又定义一遍。如果同名库出现两次,转换工具可能只处理其中一个,另一个留在cds.lib里继续报 CDB 警告。我的做法是先把不相关的DEFINE注释掉,转完再逐条加回来,缩小排错范围。

注意:改cds.lib前先复制一份cds.lib.bak,后面库打不开时可以直接对比,不用凭记忆回滚。

3.4 给转换工具准备可写目录

Conversion Toolbox 转换时会往输出目录写库文件,如果 home 下空间不够或者目录权限不对,转换会在中途停掉,留下半套数据。提前建好输出目录,确认当前用户可写,比转换失败后再查权限省事。项目正文里转换完成后是在 home 目录下看到转换好的流程库,说明输出默认落在 home;我一般会显式建一个$HOME/cdb2oa_out,把输出收拢,后面复制回 PDK 时不容易拿错。

# 建输出目录并确认可写 mkdir -p "$HOME/cdb2oa_out" touch "$HOME/cdb2oa_out/.write_test" && rm -f "$HOME/cdb2oa_out/.write_test" # 看 home 剩余空间,转换大库前至少留出足够余量 df -h "$HOME"

touch再删除只是快速验证写权限,df -h看空间余量。输出目录不要设在只读 PDK 里面,也不要设在网络盘上,转换过程中大量小文件写入,网络盘一抖就容易断。转换完成后先在输出目录里确认库目录结构,再执行复制替换,顺序不要反过来。

4. 执行 CDB 转 OA:Conversion Toolbox 的完整操作链

4.1 启动 Conversion Toolbox 并打开 CDB to OpenAccess Translator

环境确认完,回到 home 下启动 Virtuoso,然后在菜单里找 Conversion Toolbox。项目正文的路径是:启动 Conversion Toolbox,开启 CDB to OpenAccess Translator。不同安装包的菜单层级可能略有差异,但入口名称基本围绕Conversion Toolbox和CDB to OpenAccess Translator。打开后不要急着点开始,先确认工具窗口里选的输入文件是 home 下刚保存的那份cds.lib,不是 PDK 里旧的那份。

# 转换前再确认一次当前目录和 Virtuoso 版本 cd "$HOME" which virtuoso virtuoso &

cd "$HOME"保证 GUI 启动目录在 home,which virtuoso再确认一次没有切回旧版本。Conversion Toolbox 打开后,如果界面里库列表是空的,先检查cds.lib路径有没有选对;如果列表里出现一堆不相关设计库,回去第 3 章把cds.lib里的DEFINE收窄。转换工具不怕库少,怕的是库杂。

4.2 选择 PDK 里的 cds.lib 作为输入

项目正文写的是“路径选取 PDK 中的 cds.lib,然后 ok”。这里容易产生一个分歧:前面在 home 下保存了一份cds.lib,为什么这里又选 PDK 里的?我的处理是:home 下保存的那份用于确认库路径和库名,Conversion Toolbox 里选 PDK 的cds.lib作为转换输入,确保工具读到的是 PDK 原始库定义。两份文件如果内容一致,选哪份都能跑;如果不一致,以 PDK 里能覆盖目标库的那份为准,但转换前要用diff看一眼差异。

# 对比 home 下保存的 cds.lib 和 PDK 里的 cds.lib diff -u /path/to/pdk/cds.lib "$HOME/cds.lib" | head -n 60

diff -u输出差异,重点看DEFINE行和INCLUDE行。如果只是路径写法不同,问题不大;如果库名或库路径不同,先统一再转。转换工具窗口里选cds.lib后点OK,库列表会刷新,确认目标库在列表里且路径指向 CDB 数据,再开始转换。

4.3 等待转换完成并检查 home 下的输出库

点开始后不要反复点,转换过程会写大量文件,重复启动容易把输出目录写乱。项目正文说“等待转换完成”,然后在 home 目录下就能看到转换好的流程库。转换时间取决于库大小和磁盘速度,小库几分钟,大库可能更久。期间可以看输出目录里文件数量有没有增长,但不要手动往里复制文件。

# 转换过程中看输出目录是否在增长 watch -n 5 'du -sh "$HOME"/demo035* 2>/dev/null' # 转换结束后列出 home 下新出现的库目录 ls -ld "$HOME"/demo035* 2>/dev/null

watch只是观察,不是必须;ls -ld确认输出库目录的权限和时间戳。转换完成后重点看三处:库目录里有没有OA相关文件、原来 CDB 的prop.xx是否还在、库目录大小是否合理。如果输出目录只有一个空壳,或者大小明显不对,先别往 PDK 里复制,回去看转换日志。

4.4 把转换后的库替换回 PDK 的正确顺序

项目正文的顺序很明确:在 home 目录下看到转换好的流程库后,把它复制到原来的 PDK 里面,原来的先删掉后再复制进去。这个顺序不能反:先删原库再复制,中间一旦复制失败,原库就没了。我的做法是先重命名原库做备份,再把新库复制进去,确认 Virtuoso 能打开后再决定要不要删备份。这样即使新库有问题,改个名字就能回滚。

# 进入 PDK 目录,先备份原库,不要直接删 cd /path/to/pdk mv demo035 demo035.cdb.bak # 把 home 下转换好的库复制进 PDK cp -a "$HOME/demo035" /path/to/pdk/demo035 # 确认新库权限和目录结构 ls -ld /path/to/pdk/demo035 find /path/to/pdk/demo035 -maxdepth 1 -type f | head

mv做备份比rm -rf安全,cp -a保留权限。复制完成后不要马上删demo035.cdb.bak,先在 PDK 目录下启动virtuoso&,确认 Library Manager 能打开新库、关键 cellview 能进编辑,再考虑清理备份。项目正文最后一步是cd进入 PDK 文件夹,在 PDK 文件夹中打开virtuoso&,这一步就是验收启动环境。

4.5 命令行 cdb2oa 的备用路径与参数取舍

如果 GUI 入口找不到,或者要在脚本里做小样本复验,可以看命令行cdb2oa。摘要里给的写法是cdb2oa -i input.cdb -o output.oa,参数含义很直观:-i输入,-o输出。但整库转换和单文件转换不是一回事,实际参数以本机cdb2oa -help为准。我的取舍是:GUI 负责整库正式转换,命令行只做单库验证和批量检查,不拿命令行输出直接覆盖 PDK。

# 单文件/单库样本验证,参数以本机 help 为准 cdb2oa -i /path/to/input.cdb -o /path/to/output.oa # 转换后检查输出文件类型和大小 file /path/to/output.oa ls -lh /path/to/output.oa

-i和-o是最小参数组合,file看输出类型,ls -lh看大小是否合理。如果cdb2oa报参数不认,不要硬套网上的命令,直接跑cdb2oa -help看本机支持哪些选项。命令行输出如果是单文件,不能直接替代整库目录;整库替换还是走 4.4 的备份加复制流程。

5. 避坑与排查:cds.lib、权限和库覆盖的五个翻车点

5.1 转换后仍报 OA executable on CDB data

现象:转换完成,库也复制回 PDK,启动 Virtuoso 后 CIW 还是刷Warning: ddUpdateLibList: It appears that you are trying to run an OA executable on CDB data。原因通常不是转换没做,而是cds.lib还在指向旧 CDB 目录,或者 PDK 里同时存在新旧两份库,Virtuoso 先读到了旧的那份。解决顺序是先用grep找当前cds.lib里目标库的定义,再确认路径指向新库;如果路径没错,去库目录里看prop.xx是否还在,prop.xx是 CDB 数据特征文件,OA 库不应该靠它运行。

# 找当前会话使用的 cds.lib 里目标库定义 grep -R "DEFINE demo035" "$HOME/cds.lib" /path/to/pdk/cds.lib # 看库目录里是否还残留 CDB 特征文件 find /path/to/pdk/demo035 -name "prop.xx" -o -name "*.cdb" | head

grep -R把 home 和 PDK 两份cds.lib都查一遍,find查残留文件。如果cds.lib指回旧路径,改路径或注释旧DEFINE;如果新库目录里还有prop.xx,说明复制时把旧文件带进来了,清理后重新启动 Virtuoso。注意不要只改 GUI 里的 Library Path 不保存,下次启动又回到旧路径。

5.2 库复制进去后 Library Manager 看不到

现象:文件明明在 PDK 目录下,Library Manager 里就是没有目标库,或者库名是灰的。原因多半是cds.lib没有重新加载,或者新库目录权限不对,Virtuoso 读不进去。解决是先确认cds.lib里有DEFINE,再看目录权限和属主,最后在 Virtuoso 里重新加载库路径。不要急着重装,先看这三处。

# 确认库定义存在 grep -n "demo035" /path/to/pdk/cds.lib # 看库目录权限和属主 ls -ld /path/to/pdk/demo035 ls -l /path/to/pdk/demo035 | head

grep确认定义,ls -ld看目录权限。如果目录属主是别人、当前用户只读,Library Manager 可能能看到库名但打不开 cellview。常见做法是把库目录权限改成当前用户可读可写,或者用有权限的账号启动 Virtuoso。改权限前先确认不是共享 PDK 的只读区,别把团队公共目录改乱。

5.3 转换中途退出,输出目录只有半套数据

现象:Conversion Toolbox 跑到一半停了,home 下输出目录里只有部分库文件,库大小明显不对。原因可能是 home 空间不足、转换过程中终端被关、或者输出目录权限中断。解决是先把半成品目录改名留证,不要直接删;然后检查磁盘空间和权限,重新建干净输出目录再转。半成品最怕被当成成品复制进 PDK,后面查起来非常费劲。

# 把半成品改名留证 mv "$HOME/demo035" "$HOME/demo035.half.bak" # 看空间和权限再重转 df -h "$HOME" ls -ld "$HOME" "$HOME/cdb2oa_out"

mv留证,df -h看空间,ls -ld看权限。重新转换前把输出目录清干净,不要在半成品上叠加。转换时间长的库,建议在screen或tmux里跑,终端断了也不影响。

5.4 PDK 只读或权限不足导致转换失败

现象:转换工具报写入失败,或者复制回 PDK 时提示Permission denied。原因是你直接在只读 PDK 或公共 PDK 上操作。解决是把工作副本放到 home 下转换,输出也落 home,最后用有权限的账号做替换。不要为了省事给整个 PDK 加chmod -R 777,权限一乱,后面 Virtuoso 读库出问题更难查。

# 检查当前用户对 PDK 和目标目录的写权限 test -w /path/to/pdk && echo "PDK writable" || echo "PDK not writable" test -w "$HOME/cdb2oa_out" && echo "work writable" || echo "work not writable"

test -w只回答可写不可写,不改变权限。如果 PDK 不可写,就在 home 下完成转换,再让有权限的人复制;如果只是某个子目录不可写,确认是不是挂载成了只读。权限问题不要靠sudo硬压,先分清“转换写输出”和“替换回 PDK”是两件事。

5.5 旧库没删干净,库名冲突

现象:新库复制进去后,打开 cellview 还是旧数据,或者同一个库名在 Library Manager 里出现两个路径。原因通常是旧库目录还在,cds.lib里同名DEFINE没清理,Virtuoso 按顺序读到了旧库。解决是先把旧库改名备份,再检查cds.lib里同名定义,确保目标库只保留一条有效路径。

# 找同名库定义,确认没有重复 grep -n "DEFINE demo035" /path/to/pdk/cds.lib "$HOME/cds.lib" # 旧库改名备份,不要直接删 mv /path/to/pdk/demo035.old /path/to/pdk/demo035.old.bak 2>/dev/null

grep查重复定义,mv做备份。库名冲突时不要靠反复重启 Virtuoso 解决,先把路径顺序和同名定义理清。我一般会在cds.lib里只留一条目标库定义,其他旧路径注释掉,等验收通过再决定要不要恢复。

6. 装完怎么验证:在 IC617 里打开 OA 库并做一次可回滚验收

验证不要只看“转换完成”四个字。我的验收分三层:第一层,在 PDK 目录下cd进去启动virtuoso&,看 CIW 里还有没有ddUpdateLibList的 CDB 警告;第二层,Library Manager 里能找到目标库,库路径指向新目录,不是旧备份;第三层,随机点开几个关键 cellview,能进编辑、能看属性,最好再开一个版图或原理图样本。三层都过,才算跑通。

# 进入 PDK 目录启动 Virtuoso,按项目正文的最后一步走 cd /path/to/pdk virtuoso & # 启动后另开终端确认库目录和 cds.lib 指向 grep -n "DEFINE demo035" /path/to/pdk/cds.lib ls -ld /path/to/pdk/demo035

cd到 PDK 再启动,是为了复现真实使用场景;grep和ls -ld确认路径没有指回备份。验收表可以按下面几项打勾:

验收项通过标准不通过先看
CIW 警告不再刷 CDB data 警告cds.lib是否指回旧库
库可见性Library Manager 能看到目标库DEFINE和目录权限
cellview关键样本能打开、能编辑库是否只复制了一半
回滚旧库备份还在,改名可恢复备份是否被提前删除

我吃过一次亏:转换完太兴奋,直接把旧库删了,结果新库有一个子库没转全,回头找旧数据找不到,只能重装 PDK。从那以后我每次做 CDB 转 OA,都强制走一遍“备份改名、复制新库、三层验收、最后才清理备份”的顺序,不给自己的操作留后悔药。这份安装笔记和检查表我放在下载包里,拿到后先照着第 2 章的清单核对环境,再走第 4 章的转换链,别一上来就点转换。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进