T0 · 语言一览
RNL 语言的样貌
下方语法遵循语言标准 0.3:共 46 个关键字;按标准例句编写时,每条语句读起来就像流畅的自然语言,且同样可以用中文编写。工具链的运行库已完整实现所有关键字。0.x 各版本之间不承诺兼容性,但工具仍可读取 0.2 的文件。
一条语句的剖析
同一条语句的三种写法
自由文本仅供人类阅读,因此同一条语句可以只写精简记号,也可以写成英文或中文的标准例句。机器读取到的内容完全一致,且工具可在不同写法之间双向转换。
若要使用中文写法,请在文件开头的头段记录中加载代称包 rnl-zh:
引用记号
一眼区分哪些属于网表、哪些属于 RNL。
网表中的元件仅引用,绝不创建新元件网络网表中的节点端子按端子名,或按序号如 #M1:1(从 1 开始)本层子电路的端口由 .subckt 定义;单独一个 # 代表该子电路本身本层级的名称每个层级内仅绑定一次,且仅在该层级可见定义符号、样式、普通定义或集合;向子层级继承定义中的角色套用时由实际对象填入;在符号定义中,单独一个 ? 代表使用该符号绘制的元件点坐标“_”表示该轴交由求解器决定;%j = (10, 10) 为具名点集合有序集合;放入另一个集合时会展开一层,而 {{…}} 则保持为单一成员总线带有下标范围的一组网络或元件,例如 #XI<3:0>子对象例如以 key 命名的标签管道将前一段的结果传递给后一段;=> %x 可为其命名语句的常见形态
将 M1 置于 (10, 20)。也可仅指定单一坐标轴,如 @PLACE(x=10);另一轴交由求解器决定。
花括号表示一组有序对象:M1 与 M2 具有相同的 y 坐标。
紧跟在对象后面的括号标明该对象填入定义的哪个角色;“and”与“are treated”为自由文本。
为该语句生成的对象命名,后续即可引用 %g0(例如指定其位置);写在末尾的 => %g0 效果相同。
每段将结果传递给下一段:先指定位置,再进行左右镜像。
一条记录,内部语句以分号分隔。记录头会作用于内部的每一条语句:author 记录作者,priority 设置默认优先级(AS 与 ATTACH 除外,它们仅在记录的优先级为 disabled 时才继承它)。
关键字家族
46 个关键字分为九大家族。点击任一关键字即可查看其用途、标准例句与中文写法。
五种布局约束
所有布局意图最终均归结为这五种关系:前四种作用于 x 或 y 坐标,第五种作用于朝向。仅指定坐标轴的约束不限定方向;指定如 "left-to-right" 的方向才会固定先后顺序。
对齐(Align):y 坐标相同,排成同一行。
顺序(Order):沿 x 轴严格排列。仅指定坐标轴时,正序与倒序均符合;写 "left-to-right" 才会固定方向。
等距(Distribute):相邻成员之间的间距相等,例如使尾管居中。
距离(Distance):B 在 A 右侧至少 3 格;若方向写 "x" 则不分左右先后。
朝向关系(Orientation relation):B 为 A 的左右镜像;至于两者各自朝向哪一边,则由求解器决定。
单个电路层级如何生效
读取完整个层级后,会按九个固定阶段依次处理。因此名称可以先使用后定义,出错的语句也仅影响自身;由规则生成的对象(例如标准包自动补上的接地符号)同样会获得符号与位置。
语言导览九个可动手操作的小节:句子与中文写法、定义、标准包默认行为、集合与筛选、导线、文字、朝向、优先级以及头段记录。T1 · 句子与写法
语句读作事实:记号、标准例句、中文写法
机器只读取记号:以 # & % $ 开头的引用、以 @ 开头的关键字、括号内的参数、花括号、分号与 =>。记号之间的词均为自由文本,可写可不写。标准例句为每个关键字配好了固定用词,使同类语句在各处读起来一致;中文代称包则能将相同的句子转为中文。
- 机器读取内容
- 语义解读
标准例句的编写原则
- 陈述事实,而非下达指令每条语句描述的是图面上成立的事实,而非要执行的操作。对象为主语,关键字为谓语或名词,参数为其数值;中间仅加入 is、are、has、there is(或中文的“是、位于、有、按……排列”)等连接词。
- 不夸大语义不写 must、only、“必须”等超出语句本身语义的字眼:人类读者会当真,但机器会直接忽略。
- 补充说明朝向码或坐标轴后面可加上“, i.e., …”(或中文“,即……”),以白话说明其含义:
#M2 @ORIENT("MX"), i.e., flipped upside down。 - 自由文本可包含的字符在括号之外,除了 @ # & % $ ? " ; = { } ( ) [ ] < > 以外的任何字符(包含中文与标点符号)均可写在记号之间;每个 @ 前面则必须留有一个空格。
四个常见笔误
写在自由文本中的引用依然会被视为引用,而漏写前缀的名称则会被当成自由文本。
自由文本中的 M3 与元件 #M3 同名;是否漏写了前缀?
M3 没有加上 #,因此被视为自由文本:这条语句只会对齐 M1 与 M2。
无任何提示:这条语句完全合法。
即使写在“说明”里,#M2 依然是一个对象:PLACE 接收到两个对象并分别放置,导致 M2 也被放到 x = 0。单纯的注释请写在 /* */ 中。
引用后面紧跟着 . 与名称:端子应使用 :,此处的 .d 会被当成自由文本。
这条语句指代的是 M1 本身而非其漏极;CURRENT 仅接受端子,因此整条语句失效。请改写为 #M1:d。
引用后面紧跟着 !:包含该字符的名称必须加上双引号,例如 &"vdd!"。
未加双引号时,会被解析为网络 vdd 加上自由文本“!”,而本层级并没有名为 vdd 的网络。
完整文件示例
介绍页中的五管 OTA,展示第二步时的完整文件。切换为中文写法时,头段记录多了一行 @USE-ALIASES;其余每一条语句均与英文写法一一对应。
T2 · 定义
AS 说明“是什么”;ATTACH 说明“添上什么”
普通定义(@DEFINE)包含角色、参数与定义体。使用 AS 或 ATTACH 套用定义时,会生成一个“用例(usage)”对象,可供命名与筛选。差分对、镜像对称、接地与端口标签均是由此机制生成,而它们的定义都位于标准包中。
前面的对象共同构成该结构。定义写在最后,对象按角色填入:M1 填入 in_p,M2 填入 in_n。
将前面的定义添到后面的对象上。定义写在最前:在网络 vss 上添一个接地符号;它仅供显示而存在,不产生电气连接。
“是什么”与“怎么画”
$CURRENT_MIRROR 的定义体为空:套用它仅记录“这是一个电流镜”,不会改变画法。$MIRRORED 的定义体内含约束;套用时会将角色替换为实际对象,并将约束展开至本层级。$DIFFERENTIAL_PAIR 则两者兼备:既记录差分对语义,其定义体也将尾管置于差分对中央下方。标准包定义体中的约束优先级一律为 low:作者编写的事实优先,且可对用例套用 PRIORITY 将其关闭。
自定义一个定义
在定义体中,角色写作 ?a,参数写作 ?gap。套用时将参数写在 AS 的括号内;未指定时使用默认值。拖动滑块改变 gap,观察文件与图面如何同步变化。
min=?gap 代表最小间距:求解器可以排得更开;此图展示的是最紧凑的排法。
标准包中的定义
RNL 语言本身并不认识差分对。下方这些均是标准包用 RNL 编写的普通定义,点击任一项即可查看其写法。文件中若有同名定义,将会遮蔽它们。
T3 · 标准包默认行为
即使什么都不写,依然能绘出原理图
标准包本身就是一份 RNL 文件,内含默认符号、样式、定义与补位规则。它在每个文件之前加载,因此文件中编写的任何内容都能覆盖它;各包的内容请见标准包图库。下方的共射放大级起初仅有原始网表;依次切换两个预设,加上三行 RNL,观察标准包自动补位的内容(灰色部分)如何随之变化。
默认符号
在 SPICE 网表中,先按元件名首字母、再按模型类型选定符号;在 Spectre 网表中,则按 master 与模型类型选定。文件中编写的 SET-SYMBOL 排在后面,因此会覆盖这些默认符号。
| 元件 | 符号 | 端子 |
|---|---|---|
R* C* L* | $RESISTOR $CAPACITOR $INDUCTOR | p n |
V* I* | $VOLTAGE_SOURCE $CURRENT_SOURCE | p n |
D* | $DIODE | a k |
E* G* | $VCVS_4TERM $VCCS_4TERM | p n cp cn |
M* | $NMOS_4TERM;类型 pmos $PMOS_4TERM | d g s b |
Q* | $NPN;类型 pnp $PNP | c b e |
F、H、B、S、W、J、T、U 等其余元件的符号及各符号的外观,请见标准包图库。
补位规则(节选)
标准包本身即用 RNL 写成。它通过几个集合为文件预留了扩展口:只要向集合中添加或移除成员,补位行为就会随之调整。
T4 · 集合与筛选
集合在嵌套时展开一层;筛选即是规则
花括号用来书写有序集合。在集合中引用另一个集合时,会将其成员展开并入;若要将其保持为单一成员,只需再套一层花括号。筛选出的对象同样构成集合,且筛选会在所在层级及下方每个层级各求值一次。
展开一层,还是保持为单一成员
设 %s1 = {#M1 #M2} 且 %s2 = {#M3 #M4}。在我们的大语言模型编写基准测试中,约有 15 次运行本想表达右侧的写法,却写成了左侧的形式。点击“换一种排法”,查看两种写法各自允许哪些排列方式。
成员:M1 M2 M3 M4
四个元件逐个排序:仅允许 M1 M2 M3 M4 或完全倒序。
成员:{M1 M2} {M3 M4}
两组之间按各自的中心排序;每组内部的先后顺序则不限。
按条件筛选
筛选(Selection)会从指定范围中按条件挑出对象:范围为 # 时,即为整个层级;范围为网络时,即为连接在该网络上的对象。点击任一语句以查看其筛选结果。
每个层级各求一次
规则按定义对待:写在顶层时,会在顶层及下方每个子电路中各求值一次,且每次仅检查该层级内的对象。若加上 recursive=false,则仅在编写该规则的层级生效。
T5 · 导线
唯有共用同一个点对象,导线才会相接
WIRE 接受一个网络与一串有序的点(每个点可为端子或点对象)。网络名仅作为标注,实际电气连接依然由网表定义。绘制出的导线是否相接,完全取决于它们是否共用同一个点对象或端子。
六种走线模式
点列表中的每个点均会依次经过;相邻两点之间的路径走法则由 mode 决定。除了 auto 之外,每种模式均为查看器严格遵循的几何规则。点击图面任意位置可移动终点。
总线、分接与叠画
网表本身没有总线概念:总线只是将多个网络画成一根粗线的画法。单根导线与总线共用一个点即构成“分接(tap)”。叠画(BUNDLE)则将一组元件绘制为单一符号,其引脚代表各成员的同名端子。
若不想手写走线路径,可使用 &D<1> @ROUTE 将整个网络交由求解器处理:分叉、路径与交汇圆点均由求解器决定。
T6 · 文字
附着在对象上的文字是标签;附着在点上的是标注
TEXT 附着的对象决定了三件事:${…} 读取谁的属性、文字默认摆放的位置,以及指定 key 时它成为谁的子对象。文字自身的位置则是独立的,可通过 PLACE 或 dx、dy 设置。
文字标记语法
文字标记采用大语言模型熟悉的一小部分 LaTeX 语法。上下标必须加上花括号,因此 g_m 会原样显示;${…} 会读取文字所附着对象的属性(此处为 M1 的 W=2u L=0.5u)。遇到未知命令时会原样显示并给出警告,该段文字依然有效。
T7 · 朝向
x 向右、y 向上;共八种朝向码
坐标采用 y 轴向上的网格单位,与 Virtuoso 一致。朝向变换以符号的原点为中心:引脚位置与出线方向会随之改变,但引脚所对应的端子不变。仅接受下方八种朝向码;R90 为逆时针旋转,而 MYR90 与 MXR90 则是先镜像翻转再旋转。
朝向关系
ORIENT-RELATION 不固定绝对朝向,仅固定两者之间的相对关系:B 的朝向为 A 的朝向再套用指定变换。$MIRRORED 使用的正是 "MY":无论 A 如何旋转,B 永远是它的左右镜像。
T8 · 优先级
冲突并非错误:先按优先级,再按先后顺序
每项几何事实均具有优先级:disabled、low、normal(默认)或 high。系统按优先级从高到低(同一优先级内后写者优先)逐条处理事实;每项事实只要不与已保留的事实矛盾即予以保留。一条 PLACE 包含 x 与 y 两项事实,可各自丢弃;由用例展开出的事实,在语句顺序中位于创建该用例的语句处。
三条记录如何协同运作
编写语义与约束,默认为 normal。可随时修改。
输出坐标与导线,优先级为 high。每次求解时整段替换;以 hash 记录求解时的输入。
手动修改追加在后面,优先级同样为 high:同一优先级内后写者生效,因此会覆盖求解器结果。
当输入变更导致 hash 不再匹配时,旧结果仍可照常显示;查看器仅建议重新求解,不会报错。下次运行求解时,编辑器写入的 high 坐标会被视为固定位置,其余部分则随之调整。
T9 · 头段记录
头段记录:语言版本、代称包、器件端子名
头段记录为可选项;若有编写,必须是文件的第一条记录且位于所有子电路之外,至多一条。它一律按标准拼写读取,不识别代称。若未编写,工具会按默认语言版本读取,并在保存文件时自动补上头段记录。
PDK 器件的端子名
网表中未定义的子电路(例如来自 PDK 的 sky130_fd_pr__nfet_01v8)没有已知的端子名,因此其端子只能按位置下标引用(例如 :1)。@DEVICE 可声明其端子名,并通过名称与模型的通配模式匹配元件。
E · 综合示例
几个完整的小示例
左侧为文件内容,右侧为绘制结果。将光标悬停在某一行上,可查看它控制图面中的哪个部分;反过来将光标悬停在图面元件上,也会标出相关的语句行。