KLayout PCell 介绍
一个”能改参数的圆”
假设要在版图里放五个半径不同的圆环:5、10、15、20、25 μm。最直接的做法是每个半径画一个单元,存成五份 GDS;改一次半径,就再画一份。用图形界面复制、改尺寸、再存一份,文件一多,版图库就变得又臃肿又难维护。
KLayout 给出的答案叫 PCell(parameterized cell,参数化单元):它不包含静态版图,而是由一段代码按照一组参数动态生成 [S1]。同样是圆环,PCell 的做法是”一份代码 + radius/width 参数”——参数变了,几何就跟着变。图 1 对比了这两种方式。
图 1:左边是静态单元——每个半径都是一份独立的 GDS 单元;右边是同一个 PCell 用不同 radius 参数动态生成。示意图为本平台自绘。
PCell 是什么
PCell 并不是一个新的文件格式,而是版图工具层的一种”生成器”机制。KLayout 从 0.22 版本开始支持 PCell [S1]。一个 PCell 由三部分组成:
- 描述文本:在单元树里显示的人类可读名称;
- 参数声明:半径、宽度、图层等参数的类型与默认值;
- 生产回调(produce):拿到参数后真正往单元里写几何的代码 [S1]。
使用方式和普通单元几乎一样:从库中选择 PCell,填写参数,然后像放普通单元一样放置、旋转、镜像、阵列 [S1][S2]。区别在于,普通单元的内容是”画好存好”的,PCell 的内容是”每次按参数算出来”的。
表 1:静态单元、生成脚本与 PCell 三种做法对比(作者整理,基于 KLayout 官方机制描述 S1、S2)。
| 做法 | 改参数的成本 | GDS 里的表现 | 适合场景 |
|---|---|---|---|
| 静态单元 | 每次手动重画或复制一份 | 每个版本都有一份几何 | 少量固定图形 |
| 生成脚本 | 改脚本参数重跑一遍 | 每次重新生成整批几何 | 一次性批量生成 |
| PCell | 改参数即时更新 | 几何快照 + 参数元信息 | 可交互复用的器件库 |
表 1 里”几何快照 + 参数元信息”是关键,我们下一节展开。
GDS 里没有 PCell:快照与元信息
很多刚接触 PCell 的人会以为”GDS 里能存 PCell”。严格说,GDSII 格式本身不支持 PCell 这种参数化概念 [S6][S9]。那 KLayout 是怎么保存 PCell 的?
KLayout 的做法是”快照 + 元信息”:写入 GDS 时,先用当前参数把几何算出来,把几何快照作为普通图形写进文件,再附加一份元信息,记录”这是哪个库的哪个 PCell、参数是什么”(GDS 中放在一个专用顶层单元里,OASIS 中放在 cell properties 里)[S6]。PCell 的代码本身不会写入文件——文件里保存的是几何快照和参数值 [S6]。
这个设计带来两个直接后果:
- 任何不认 PCell 的工具打开这个 GDS,看到的都是合法、完整的静态几何,不会报错——只是不能”改参数”而已 [S6];
- 用 KLayout 读回时,如果机器上装了对应的 PCell 库,它会重新连接成 PCell,参数面板继续可用;如果没装库,就退化为普通静态单元 [S6]。
我们用 KLayout 0.30.10 的 Python 包实测验证了后半句:一个写入了 PCell 的 GDS 文件,在未注册任何库的全新 Layout 中读回,pcell_names() 为空,单元作为静态单元存在 [S11]。图 2 把这个机制画了出来。也就是说,PCell 是”版图工具的功能”,不是”文件格式的功能”。
图 2:参数传给 PCell 代码动态生成几何;写入 GDS 时保存几何快照与参数元信息;读回时是否有对应库决定了能否恢复为 PCell。示意图为本平台自绘。
写一个最小 PCell:先看官方骨架
KLayout 提供 PCellDeclarationHelper 简化 PCell 声明,Ruby 与 Python 的写法几乎一致,Python 里的模块名是 pya [S5][S4]。下面是最小例子——一个由参数 p 决定大小的矩形:
1 | |
逐行看:
param("p", self.TypeInt, ...)声明一个整数参数p,同时自动生成self.p与self.set_p(...)访问器;类型为图层(TypeLayer)的参数还会额外生成self.l_layer,在produce_impl里直接得到图层索引 [S4];display_text_impl返回单元树里显示的文字;produce_impl是核心:用参数往self.cell里写几何 [S4]。
在 KLayout 0.30.10 的 Python 环境里实测:注册这个 PCell 后,用 layout.create_cell("MyPCell", {"p": 3, "l": pya.LayerInfo(2, 0)}) 实例化,写入 GDS,再读回——文件是合法的,2/0 层上有一个 300×600(DBU)的矩形。整个”注册 → 实例化 → 写 GDS → 读回”链路是通的 [S11]。
一个更实用的例子:环形 PCell
矩形只是骨架,光电子版图里更常见的是环、波导这类器件。下面的 RingPCell 把半径、波导宽度、图层和离散点数作为参数,用外圆减内圆生成环形:
1 | |
这里多了一个之前没见过的回调:coerce_parameters_impl。它的作用是”参数修正”——在界面按下 Apply 或实例化之前,把参数整理到一致、合法的状态(比如半径必须为正、环宽不能超过直径)[S4]。没有它,用户把 radius 填成负数,produce 就会生成怪形状甚至报错。
用同一份代码生成半径 5、10、15 μm 的三个环,写进 GDS 再渲染出来,就是图 3:

图 3:同一个 RingPCell 用不同 radius 参数生成的三个环(波导宽度 0.5 μm,64 点离散)。图片基于本文代码实际生成的 GDS 渲染,本平台自绘。
为了示例简洁,这里只生成环形本身,没有画总线波导;加总线波导只是再多插几个多边形的事。
注意一点:圆仍然是用 64 个点离散成多边形的——GDS 里没有真正的曲线。这和平台之前那篇《GDS里的圆弧为什么总是多边形》讨论的是同一个底层约束;PCell 解决的是”参数化复用”,而不是”曲线存储”。
guiding shapes:PCell 的”幽灵形状”
PCell 还有一个很特别的机制:guiding shapes(引导形状)。它是一类”幽灵形状”——不产生真实版图,但作为 PCell 实例的一部分存在,可以被正常编辑 [S1]。最常见的用法是手柄:一个点状 guiding shape,在移动模式下拖动它,就相当于修改了某个参数 [S1]。
最典型的例子是 Basic 库的 ROUND_PATH(圆角路径):它用一条路径作为输入形状,路径本身不输出,真正输出的是一条在拐角处按给定半径平滑过渡的新路径 [S1][S10]。改路径、拖拐点,圆角半径仍由数值参数控制。图形化的”画路径 → 拖拐点 → 得圆角波导”,就是 guiding shapes 的日常用法 [S2]。
从 Basic 库到 PDK:PCell 的生态
KLayout 自带 Basic 库,提供一批开箱即用的 PCell:TEXT、CIRCLE、DONUT(带孔的圆)、ELLIPSE、PIE、ARC、ROUND_PATH、ROUND_POLYGON、STROKED_BOX、STROKED_POLYGON [S10],见表 2。而且支持把已有图形直接”Convert To PCells”——画一个多边形,选中后转成 ROUND_POLYGON,就能继续用圆角半径参数调整它 [S10][S3]。
表 2:Basic 库提供的主要 PCell(S10)。
| PCell | 说明 |
|---|---|
| CIRCLE / ELLIPSE | 圆 / 椭圆,可选手柄定义尺寸,默认 64 个插值点 |
| DONUT | 带孔的圆(环),内、外半径两个手柄 |
| PIE / ARC | 圆环的一段(扇形 / 弧) |
| ROUND_PATH | 按半径平滑路径拐角的圆角路径 |
| ROUND_POLYGON | 圆角多边形 |
| STROKED_BOX / STROKED_POLYGON | 多边形或矩形的”描边”,可加圆角 |
在真实项目里,PCell 更多以 PDK(Process Design Kit,工艺设计套件) 的形式出现:工艺厂把自己的器件(波导、环、耦合器等)写成一套 PCell 库,设计者直接调用,改参数得到符合工艺规则的器件。硅光子领域有两个典型的开源例子:
- SiEPIC-Tools:一个基于 Python 的 KLayout 插件,为硅光子版图提供设计、验证与电路仿真能力,支持 GUI 与脚本两种方式,并配合 SiEPIC-EBeam-PDK 等 PDK 使用 [S8];
- gdsfactory:用
@gf.cell装饰器把普通 Python 函数变成参数化单元,官方文档直接说”cells 就是 PCell”,返回的 Component 可以注册进 PDK 统一调用 [S7]。
对写 PDK 的人来说,PCell 意味着器件库可以”一份代码、到处复用”;对用 PDK 的人来说,PCell 意味着”从库里拖器件、填参数”,而不是手动画每个器件。
局限与工程经验
PCell 不是万能的,几个工程上必须知道的限制:
- 代码不随文件走。GDS 里只有快照和参数,没有 PCell 代码 [S6]。把文件发给同事或送去流片,对方必须装了对应的库(或宏),否则只能看到静态几何、无法改参数。PDK 的分发本质上是在分发”代码”。
- 库会变。KLayout 的库单元在导入版图时保存一份副本,同时保留对库的引用;库内容更新后,重新加载版图会用新版本替换旧单元 [S2]。这对设计来说是”自动升级”,但也意味着库升级可能改变已有器件的几何——版本管理要跟上。
- 不适合复杂生成器。KLayout 作者的建议是:PCell 适合器件和小组件,不适合内存生成器这类计算量很大的生成器;PCell 代码只在需要时执行,但依然要保持轻量 [S6]。
- tape-out 前转静态。下游工具、工厂不一定装有你的 PCell 库。KLayout 提供”Convert Cell To Static”把 PCell 变成普通单元;代价是转换后失去参数控制,不能再调 [S3]。是否在交付前转静态、转多少层,是每个项目要定下的策略。
结论
PCell 是版图工具的”参数化生成”机制:一份代码加一组参数,动态生成几何,实例化与普通单元无异。它不改变 GDS 格式——文件里存的是几何快照和参数元信息,代码留在库里;正因为如此,”能改参数”依赖库,跨工具传递时会退化为静态几何。
理解这一点,再回头看 KLayout 里的 Basic 库、SiEPIC-Tools 和 gdsfactory,会清楚很多:它们本质上是同一件事的不同规模——把”重复画图”变成”一个函数 + 一组参数”。
参考资料
- [S1] About PCells(KLayout 官方文档)
- [S2] Creating A Cell Instance(KLayout 官方文档)
- [S3] PCell Operations(KLayout 官方文档)
- [S4] PCellDeclarationHelper API(KLayout API 文档)
- [S5] Using Python(KLayout 官方文档)
- [S6] general questions on Pcells(KLayout 作者论坛回复)
- [S7] PDK(gdsfactory 官方文档)
- [S8] SiEPIC-Tools(GitHub)
- [S9] Expert: Pcell and GDSII(Silvaco 应用笔记)
- [S10] About The Basic Library(KLayout 官方文档)
- [S11] klayout(PyPI)
