首页/新闻资讯/正文详情

GDS版图从入门到精通:层次结构、生成流程与-uniquifycellnames避坑指南

发布时间:2026/9/25 4:57:55 来源:云帆数科 栏目:资讯中心
GDS版图从入门到精通:层次结构、生成流程与-uniquifycellnames避坑指南
1. GDS版图到底是什么从一个真实踩坑案例说起如果你在芯片设计行业待过哪怕只是刚入行的新人一定听过“GDS”这个词。招聘JD里写“熟悉GDS版图”同事聊天说“GDS什么时候tapeout”老板问“GDS给foundry了吗”。但真要问一句“GDS版图到底是什么”很多人第一反应是“就是版图文件呗”再往下追问就含糊了。我当年也是这样直到有一次在项目里踩了个大坑才真正把GDS这个东西搞明白。那次的情况是这样的一个数字后端的项目子block单独跑DRC的时候干干净净一条违规都没有。但是到了top层把子block拼进来之后DRC报告里突然冒出一堆M3、M4的space违规而且报的位置全在子block内部。当时第一反应是“不可能啊子block明明过了DRC的”。查了半天最后在top写GDS的时候加了一个-uniquifycellnames的option这些DRC就全消失了。这个经历让我意识到GDS版图远不止是“一个文件”那么简单它背后涉及到单元命名、层次结构、工具行为等一系列底层逻辑。所以这篇文章我想从一个从业者的角度把GDS版图这个东西彻底讲清楚。不管你是刚入行的版图新手还是做数字后端的工程师或者是对芯片设计流程好奇的硬件爱好者看完之后应该都能对GDS有一个立体的认知。我会从GDS的本质讲起然后拆解它的文件结构、生成流程、常见坑点最后把那个-uniquifycellnames的原理彻底讲透。这些都是实打实的项目经验不是教科书上的概念堆砌。2. GDS的本质它到底存了什么2.1 GDS不是“图片”而是制造指令的载体很多人第一次接触GDS会觉得它就是一个版图的“截图”或者“图纸”。这个理解不能说错但太浅了。GDS的全称是Graphic Data System最早是Calma公司在上世纪70年代定义的一种数据格式后来演变成GDSII也就是第二代标准。现在行业里说的GDS基本上指的就是GDSII。它的本质是什么简单说GDS是一个二进制文件里面用层次化的方式描述了芯片每一层掩模上的几何图形。这些几何图形包括多边形、矩形、路径、文本标注等等。foundry拿到这个文件之后会把它转换成掩模制造设备能识别的格式然后一层一层地把图形刻到硅片上。你可以把GDS理解成一份“施工图纸”但它不是给人看的而是给机器看的。人看版图用的是Virtuoso、KLayout这些EDA工具工具把GDS解析之后渲染成可视化的图形。但GDS文件本身打开来看就是一堆二进制数据直接看是看不懂的。这里有一个关键点GDS里存储的是几何图形不是电路逻辑。它不关心你这个图形是NMOS还是PMOS不关心你这里是电源线还是信号线它只记录“在某一层上有一个什么形状的多边形坐标是多少”。至于这个图形代表什么那是设计者赋予它的意义。2.2 GDSII的文件结构拆解要真正理解GDS得知道它内部是怎么组织的。GDSII文件采用了一种类似“记录流”的结构整个文件由一系列记录组成每条记录有固定的格式。核心的结构单元包括以下几个层次Library一个GDS文件就是一个Library里面可以包含多个Cell。Library层面会定义单位比如用户单位是1微米数据库单位是0.001微米这个比例很关键搞错了会导致整个版图尺寸偏差。CellCell是GDS里的基本单元可以理解为一个“模块”或者“元件”。一个Cell里面可以包含几何图形也可以引用其他Cell。这就是GDS的层次化结构。SREFStructure Reference就是对一个Cell的引用。比如你在top层里放了10个反相器不需要把反相器的图形复制10遍只需要用10个SREF指向同一个反相器Cell就行。AREFArray Reference是SREF的数组形式用来描述规则排列的重复单元比如存储器阵列。Boundary多边形边界用来描述一个封闭的几何图形。Path路径用来描述走线。Text文本标注。Layer层号每个几何图形都归属于某一层比如M1层、M2层、Poly层等等。这种层次化结构是GDS最核心的设计。它的好处是文件体积小、修改方便。你改一个底层Cell所有引用它的地方都会跟着变。但坏处也很明显层次结构如果管理不好就会出现各种意想不到的问题后面讲的那个DRC案例就是典型的层次结构引发的坑。2.3 GDS与其他版图格式的区别行业里除了GDS还有几种常见的版图格式容易搞混这里简单对比一下格式全称特点典型用途GDSIIGraphic Data System II二进制层次化行业标准流片交付、IP交换OASISOpen Artwork System Interchange Standard二进制压缩率更高支持更大文件先进工艺流片CIFCaltech Intermediate Form文本格式可读早期教学、简单设计DEFDesign Exchange Format文本格式侧重布局信息数字后端布局交换LEFLibrary Exchange Format文本格式描述Cell抽象数字后端库交换GDSII至今仍然是使用最广泛的版图交换格式尤其是在成熟工艺节点。先进工艺因为版图数据量太大越来越多地转向OASIS但GDS仍然是绕不开的基础。很多foundry同时接受GDS和OASIS但IP交付通常还是以GDS为主。3. GDS版图是怎么生成的从RTL到最终文件3.1 数字后端流程中的GDS生成对于数字芯片来说GDS的生成是后端设计流程的最后一环。整个流程大致是这样的综合RTL代码经过综合工具变成门级网表。布局规划确定芯片的die size、IO位置、macro摆放。标准单元摆放把标准单元放到row上。时钟树综合插入时钟缓冲器平衡时钟偏差。布线用金属层把各个单元连接起来。时序签核检查setup/hold是否满足。物理验证跑DRC、LVS。GDS导出把最终的版图数据写成GDS文件。在GDS导出这一步工具会把标准单元的GDS、macro的GDS、以及布线产生的金属图形合并到一起生成一个完整的顶层GDS。这个过程叫做“stream out”或者“write GDS”。这里有一个容易忽略的点标准单元的GDS和网表是分开的。后端工具在布局布线阶段用的是LEF文件抽象视图只包含pin的位置和blockage信息不包含完整的几何图形。只有在写GDS的时候工具才会去调用标准单元的完整GDS把它们拼进来。所以如果标准单元库的GDS有问题布局阶段是发现不了的只有到GDS导出之后跑DRC才会暴露。3.2 模拟版图流程中的GDS生成模拟版图的流程和数字后端完全不同。模拟版图工程师是手工画版图的用Virtuoso或者KLayout这样的工具一个管子一个管子地画。流程大致是原理图设计先有电路图确定器件尺寸和连接关系。版图绘制根据原理图手工绘制版图考虑匹配、寄生、隔离等因素。DRC/LVS验证检查设计规则和版图与原理图的一致性。寄生参数提取提取版图中的寄生电阻电容反标回原理图做后仿。GDS导出验证通过后导出GDS。模拟版图的GDS通常层次结构比较简单因为大部分是手工绘制的。但如果是复杂的模拟IP比如ADC、PLL也会有层次化设计底层模块复用的情况很常见。3.3 GDS导出时的关键参数写GDS的时候工具会提供很多option这些option直接影响最终文件的内容。常见的包括-uniquifycellnames这个就是本文开头案例里提到的关键option后面会详细讲。-merge把多个GDS文件合并成一个。-hier保持层次化结构导出。-flatten把所有层次打平导出成一个扁平的GDS。-map层号映射文件把内部层号映射到foundry要求的层号。-units指定单位和精度。这些option的选择会直接影响GDS文件的大小、可读性、以及后续验证的结果。比如-flatten会让文件变得很大但可以避免层次结构带来的问题-hier保持层次结构文件小但需要小心处理单元命名冲突。4. 那个-uniquifycellnames到底做了什么4.1 问题的现象回顾回到开头那个案例。子block单独跑DRC没问题top层拼进来之后子block内部出现M3、M4的space违规。加-uniquifycellnames之后问题消失。这个现象看起来很神奇但原理其实不复杂。先说现象的本质DRC工具在top层跑验证的时候看到的版图和子block单独跑的时候不一样。为什么不一样因为top层里可能有两个不同的子block它们内部有同名的Cell但内容不同。DRC工具在解析的时候把这两个同名Cell当成同一个了导致图形合并出错产生了虚假的space违规。4.2 单元命名冲突是怎么产生的在GDS的层次化结构里每个Cell有一个名字。正常情况下不同的Cell应该有不同的名字。但实际项目中命名冲突很常见原因有几种第一种情况不同来源的IP用了相同的Cell名。比如你从A供应商买了一个IP里面有个Cell叫“INV_X1”从B供应商买了另一个IP里面也有个Cell叫“INV_X1”。这两个INV_X1的内容可能完全不同但名字一样。当它们被集成到同一个top层时就冲突了。第二种情况同一个IP在不同层次被修改过。比如你在子block里改了一个Cell但没有改名字。top层引用这个子block的时候如果工具没有正确处理就可能把修改前和修改后的版本搞混。第三种情况工具自动生成的Cell名重复。有些工具在优化过程中会生成一些临时Cell命名规则可能不够唯一导致冲突。4.3 uniquifycellnames的工作原理-uniquifycellnames这个option的作用就是在写GDS的时候给每个Cell生成一个全局唯一的名字。具体做法通常是给Cell名加上前缀或后缀比如加上所在block的名字或者加上一个递增的编号。这样一来原来同名的两个Cell就变成了两个不同名的CellDRC工具在解析的时候就不会把它们混在一起了。子block内部的图形保持原样不会因为同名Cell的合并而产生虚假的space违规。用一个生活化的类比假设有两个班都有个学生叫“张伟”老师点名的时候如果只喊“张伟”两个人可能都站起来。但如果喊“一班张伟”和“二班张伟”就不会搞混了。-uniquifycellnames做的就是这件事给每个Cell加上“班级前缀”。4.4 为什么子block单独跑没问题子block单独跑DRC的时候它的GDS里只有自己的Cell不存在同名冲突的问题。所以DRC结果是干净的。但到了top层多个子block的GDS合并在一起同名Cell冲突就出现了。DRC工具在解析合并后的GDS时可能把两个同名Cell的图形叠加在一起导致原本不相邻的金属线看起来像是靠得太近从而报出space违规。这也解释了为什么违规出现在“子block内部”——因为冲突的Cell就在子block内部图形叠加之后子block内部的金属线间距看起来变小了。4.5 实操建议与注意事项在实际项目中处理这类问题的经验是写GDS之前先检查Cell命名。可以用工具或者脚本统计一下整个设计里有没有重名的Cell。如果有提前处理。养成加-uniquifycellnames的习惯。虽然它会稍微增加文件体积但能避免很多层次结构引发的问题。尤其是top层集成多个IP的时候这个option几乎是必加的。不要随便用-flatten。虽然打平能彻底避免命名冲突但文件会变得巨大而且丢失层次信息后续debug很困难。如果foundry对Cell命名有要求比如不允许某些特殊字符要提前确认。uniquify之后的Cell名可能会包含一些特殊字符需要确保符合要求。注意-uniquifycellnames不是万能的。如果两个Cell的内容确实不同但名字相同uniquify能解决冲突但如果两个Cell内容相同名字也相同uniquify会生成两个内容相同的Cell虽然不会导致DRC问题但会增加文件体积。所以最好的做法还是从源头上规范Cell命名。5. GDS版图在实际项目中的典型应用场景5.1 流片交付GDS是最终交付物芯片设计流程的终点就是tapeout而tapeout的核心交付物就是GDS。foundry拿到GDS之后会做一系列处理格式转换、掩模准备、光刻模拟等等。最终生成掩模版用来制造芯片。GDS交付的时候通常还需要附带一些其他文件比如层号映射表说明GDS里每一层对应掩模的哪一层。DRC/LVS报告证明版图符合foundry的设计规则。天线检查报告检查是否有天线效应违规。密度检查报告检查各层金属密度是否在允许范围内。这些文件一起构成tapeout package缺一不可。5.2 IP交付GDS是IP的核心资产在IP交易中GDS是核心交付物之一。一个模拟IP比如PLL或者ADC买家拿到的不只是原理图更重要的是GDS版图。因为版图直接决定了IP的性能寄生参数、匹配特性都体现在版图里。IP交付的GDS通常需要经过“硬化”处理也就是把版图固定下来不能再修改。同时会提供LEF抽象视图、Verilog行为模型、Liberty时序模型等方便买家在数字流程中集成。5.3 MPW与Full MaskGDS的使用差异MPWMulti Project Wafer和Full Mask是两种不同的流片方式对GDS的要求也不同。MPW是把多个项目拼在一个掩模上共享流片成本。每个项目提供自己的GDSfoundry把它们拼在一起。这种情况下GDS的层次结构和命名规范特别重要因为多个项目合并时很容易出现命名冲突。前面讲的-uniquifycellnames在MPW场景下尤其关键。Full Mask是一个项目独占一套掩模成本高但灵活。GDS的处理相对简单不需要和其他项目合并命名冲突的风险小很多。5.4 芯片封装设计中的GDS封装设计也会用到GDS。芯片的bump、RDL重分布层这些结构需要在封装基板上对应位置有相应的焊盘。封装工程师会参考芯片的GDS来确定bump的位置和尺寸。有些先进封装比如2.5D、3D封装芯片和interposer之间的连接需要精确对齐GDS的坐标精度就非常重要。单位和原点如果搞错了封装对不上整个项目就废了。6. GDS版图常见问题与排查技巧6.1 DRC违规排查从top到block的定位方法DRC违规是GDS相关最常见的问题。排查的时候我通常按这个顺序来确认违规位置DRC报告里会给出坐标先在版图工具里定位到具体位置。判断是真实违规还是虚假违规如果违规出现在子block内部但子block单独跑没问题大概率是层次结构问题。检查Cell命名统计整个设计里有没有重名Cell。尝试uniquify重新写GDS加上-uniquifycellnames再跑DRC。如果还有问题尝试flatten打平之后跑DRC如果违规消失说明确实是层次结构问题。这个流程能解决大部分GDS相关的DRC问题。6.2 LVS不匹配的常见原因LVS是版图与原理图一致性检查。GDS相关的LVS问题通常有这几个原因层号映射错误GDS里的层号和LVS规则文件里的层号对不上导致工具认不出器件。Cell被错误打平打平之后器件识别出错。文本层丢失LVS需要文本层来识别pin和器件如果GDS导出时文本层没带上LVS会失败。单元命名冲突和DRC类似同名Cell冲突可能导致LVS把不同器件混在一起。排查LVS问题的时候先确认层号映射再检查文本层最后看Cell命名。6.3 GDS文件过大怎么办GDS文件过大是先进工艺的常见问题。一个7nm的芯片GDS可能几十GB甚至上百GB。处理大文件的经验用OASIS替代GDSOASIS压缩率更高文件能小很多。保持层次化不要随便flatten层次化能大幅减小文件。删除不必要的层有些层在流片时不需要可以删掉。用工具做压缩有些EDA工具提供GDS压缩功能。6.4 常见问题速查表问题现象可能原因排查方法解决方案子block DRC干净top报违规Cell命名冲突统计重名Cell加-uniquifycellnamesLVS器件识别错误层号映射错误检查map文件修正层号映射GDS文件异常大层次被打平检查导出option改用-hier导出封装对不上单位或原点错误检查units设置统一单位和原点文本层丢失导出时未包含检查GDS层列表重新导出包含文本层DRC报虚假违规图形叠加对比单独跑和top跑uniquify或flatten6.5 独家避坑经验说几个我在项目里踩过的坑都是教科书上不会写的第一个坑单位搞错。有一次项目GDS导出的时候单位设成了1纳米但foundry期望的是1微米。结果整个版图小了1000倍foundry那边直接拒收。后来查了半天才发现是units设置的问题。所以每次导出GDS第一件事就是确认单位。第二个坑层号映射漏了一层。有个项目DRC一直报某个层缺失查了很久才发现是map文件里漏了一层的映射。GDS里明明有这层图形但映射之后变成了默认层DRC规则检查不到。这种问题很隐蔽因为GDS本身看起来是正常的。第三个坑uniquify之后Cell名太长。有些工具uniquify的时候会把整个层次路径拼到Cell名里导致Cell名特别长。foundry那边有名字长度限制超了会报错。所以uniquify之后要检查一下Cell名长度必要时用缩写或者哈希值。第四个坑flatten之后LVS过不了。有一次为了解DRC问题把GDS打平了DRC确实过了但LVS死活过不了。原因是打平之后器件的识别出了问题工具认不出哪些图形构成一个管子。后来还是回到层次化用uniquify解决。这些坑的共同教训是GDS导出不是点一下按钮就完事每个option都要想清楚为什么这么设。尤其是top层集成的时候多花十分钟检查能省后面几天的debug时间。7. 从GDS看芯片设计的数据管理7.1 版本管理GDS的迭代与追溯GDS文件是二进制不像代码那样能用git做diff。但GDS的版本管理同样重要。一个项目从初版到tapeoutGDS可能迭代几十次。每次迭代改了什么必须记录清楚。常见的做法是每次导出GDS都打tag记录版本号、日期、修改内容。保留关键版本的GDS比如DRC clean的版本、tapeout的版本。用脚本做GDS对比有些工具能对比两个GDS的差异找出改了哪些图形。7.2 数据安全GDS的保密与权限GDS是芯片设计的核心资产保密性非常重要。尤其是IP供应商的GDS泄露出去损失巨大。常见的安全措施包括文件加密GDS文件可以加密只有授权用户能打开。访问权限控制只有相关工程师能访问GDS服务器。水印在GDS里嵌入不可见的标识追踪泄露源。NDA约束和foundry、合作伙伴签保密协议。7.3 跨团队协作GDS的交接规范大项目里GDS往往涉及多个团队数字后端、模拟版图、IP团队、封装团队。GDS的交接必须有规范否则很容易出问题。交接清单通常包括GDS文件本身层号映射表单位和精度说明DRC/LVS报告版本说明和修改记录联系人信息交接的时候接收方要做的第一件事是验证GDS的完整性能不能打开、层号对不对、单位对不对、DRC能不能过。这些确认了才算交接完成。8. 写在最后GDS版图这个东西入门容易精通难。表面上它就是一个文件格式但背后涉及到层次结构管理、工具行为、命名规范、数据安全等一系列问题。我见过太多项目因为GDS导出时的一个option没设对导致流片延期甚至失败。如果你刚入行我的建议是不要只把GDS当成一个“导出按钮”的结果。每次导出的时候花点时间看看工具的输出日志确认Cell数量、层号、单位这些基本信息。遇到DRC或LVS问题的时候先想想是不是GDS层次结构的问题。这些习惯养成了能帮你避开很多坑。如果你已经有一定经验可以深入研究一下GDSII的文件格式规范自己写脚本解析GDS统计Cell命名、检查层号映射、对比版本差异。这些技能在实际项目中非常有用尤其是处理大文件和多项目集成的时候。芯片设计是一个容错率很低的行业GDS作为最终交付物承载了整个设计团队几个月甚至几年的心血。把GDS搞明白是对自己工作的负责也是对项目成功的保障。

相关推荐

Atlas 300V Pro部署YOLO全流程实战:从ONNX转换到推理优化
Atlas 300V Pro部署YOLO全流程实战:从ONNX转换到推理优化

前阵子有个朋友拿着热搜词“atlas部署yolo”来问我,说是不是随便找台Atlas 300V插上去就能把YOLO跑起来。我第一反应是问他:“你说的Atlas 300V是运算加速卡吗?”,他愣了半天,说这不就是显卡吗,插上去驱动装… · 2026/9/25 4:57:55

红米12C刷机变砖?NV数据损坏的底层修复与备份指南
红米12C刷机变砖?NV数据损坏的底层修复与备份指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:57:55

I2C通信协议深度解析:开漏输出、时序与多主仲裁实战
I2C通信协议深度解析:开漏输出、时序与多主仲裁实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:57:49

ESPnet 日语电视语音 ASR 实战:LaboroTVSpeech 配方(egs2/laborotv/asr1)的数据、训练、解码与流式推理全解析
ESPnet 日语电视语音 ASR 实战:LaboroTVSpeech 配方(egs2/laborotv/asr1)的数据、训练、解码与流式推理全解析

人工智能语音音频深度学习NLP 【免费下载链接】espnet End-to-End Speech Processing Toolkit 项目地址: https://gitcode.com/gh_mirrors/es/espnet 点击查看 免费下载 本篇技术指南以 ESPnet 仓库中 egs2/laborotv/asr1 配方为核心,完整解析如何在大型… · 2026/9/25 5:35:26

Sentry2视觉传感器巡线小车实战:色块检测+线条检测完整玩法
Sentry2视觉传感器巡线小车实战:色块检测+线条检测完整玩法

Sentry2视觉传感器巡线小车实战:色块检测线条检测完整玩法 【免费下载链接】CupCode_Sentry模块 源师兄扩展项目: sentry摄像头 | 由源师兄组织创建 项目地址: https://gitcode.com/yuanshixiong/sentry-system 源师兄 CupCode_Sentry 模块为 Sentry2 视觉传… · 2026/9/25 5:35:14

ClawHub 发布者搜索缺陷复现与句柄前缀检索修复验证
ClawHub 发布者搜索缺陷复现与句柄前缀检索修复验证

后端前端AI 技能AI 插件搜索引擎 【免费下载链接】clawhub Skill Plugin Registry for OpenClaw 项目地址: https://gitcode.com/gh_mirrors/mo/clawhub 点击查看 免费下载 listPublicPage 是 ClawHub(OpenClaw 的 Skill Plugin Registry)… · 2026/9/25 5:35:14

Cyrus SASL 2.1.21源码编译与认证服务部署实践
Cyrus SASL 2.1.21源码编译与认证服务部署实践

简介:Cyrus SASL 2.1.21 是一套面向邮件服务场景的开源认证与安全层库,主要服务于 Postfix 等 MTA 的运维人员、邮件系统管理员以及需要对接 SMTP/IMAP/POP3 认证的开发者。它内置 PLAIN、CRAM-MD5、DIGEST-MD5 等多种安全机制,可有效防范中间… · 2026/9/25 5:35:14

PTA 7-32 交换实数整数部分:C语言浮点数精度与类型转换避坑指南
PTA 7-32 交换实数整数部分:C语言浮点数精度与类型转换避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 5:35:14

医疗支架涂层技术解析与成本优化策略
医疗支架涂层技术解析与成本优化策略

1. 医疗支架涂层行业现状与核心需求2026年的医疗支架涂层加工领域正面临技术迭代的关键期。随着介入治疗普及率提升,国内每年冠状动脉支架植入量已突破150万例,对涂层技术提出了更高要求。目前主流涂层类型包括:药物洗脱涂层(DES&… · 2026/9/25 5:35:14

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码