第1章:网表基础回顾
各位同学好,我是老张。做逆向分析这么多年,我最大的体会就是——网表基础不牢,后面全白干。今天咱们先聊聊最基础的东西:标准单元库、网表层级结构、还有连接关系。
你可能会问:「这些东西我早就会了,还用学?」嗯,我当年也这么想。直到有一次,我接手一个别人做到一半的逆向项目,发现他把一个AOI22的引脚接反了,整个模块的功能分析全错。从那以后,我每次拿到网表,都会先花半小时确认基础结构。
1.1 标准单元库——逆向分析的「字母表」
标准单元库是什么?说白了,就是芯片设计里的「字母表」。就像你学英语要先认识26个字母一样,做网表逆向,你得先认识标准单元。
每个标准单元,本质上是一个预先设计好的逻辑功能块。比如反相器、与非门、或非门、触发器、锁存器……这些单元在物理上已经布好了晶体管,你只需要在网表里把它们「调用」出来,连上线就行。
我个人习惯把标准单元库分成三类:
- 组合逻辑单元:AND、OR、NAND、NOR、XOR、AOI(与或非)、OAI(或与非)等。这些单元的输出只取决于当前输入。
- 时序逻辑单元:DFF(D触发器)、LAT(锁存器)、SDFF(带扫描的D触发器)等。这些单元有记忆功能,输出还取决于时钟边沿。
- 特殊功能单元:时钟缓冲器、延迟单元、电平转换器、ISO(隔离单元)等。这些单元不改变逻辑功能,但影响时序和功耗。
重点提醒:逆向分析时,你看到的网表里每个实例(instance)都会引用一个标准单元。比如 U1 INV_X1,意思就是实例U1是一个驱动能力为1倍的反相器。这个「X1」代表驱动强度,在时序分析里非常关键。
我在项目中遇到过一件事:有个团队逆向一个老芯片,发现所有反相器都标的是INV_X4。他们以为芯片设计者故意用大驱动单元,后来才发现——是因为标准单元库版本不同,X4在老库里就是最小尺寸。你看,不了解库的细节,分析就会跑偏。
1.2 网表层级结构——从顶层到底层
一个真实的芯片网表,少则几百万门,多则上亿门。你不可能把所有门平铺开来看。所以,网表一定是分层的。
层级结构长什么样?我画个图你就明白了。
这张图展示了典型的网表层级:
- 顶层(TOP):芯片的顶层模块,包含所有IO端口。这是你逆向分析的入口。
- 模块(Module):功能子模块,比如一个SPI控制器、一个FIFO、一个加法器。模块可以嵌套。
- 实例(Instance):最底层的标准单元调用。每个实例对应一个具体的逻辑门或触发器。
实战技巧:拿到一个陌生网表,我习惯先看顶层有多少个IO端口。如果IO数量很少(比如几十个),那大概率是个小规模数字模块。如果IO有几百个,那可能是SoC级别的芯片。这个判断能帮你快速定位分析重点。
1.3 网表连接关系——线网、端口、引脚
网表的核心就三样东西:线网(net)、端口(port)、引脚(pin)。它们之间的关系,说白了就是「谁和谁连在一起」。
我举个例子,你一看就懂:
// 一个简单的网表片段
module TOP (clk, rst_n, data_in, data_out);
input clk, rst_n;
input [7:0] data_in;
output [7:0] data_out;
// 线网声明
wire [7:0] internal_bus;
wire clk_buf;
// 实例化
BUF_X1 U_clk_buf (.A(clk), .Z(clk_buf));
DFF_X1 U_reg[7:0] (.D(data_in), .Q(internal_bus), .CK(clk_buf), .RN(rst_n));
INV_X1 U_inv[7:0] (.A(internal_bus), .ZN(data_out));
endmodule
这里面包含了三种连接元素:
| 元素 | 含义 | 在代码中的体现 |
|---|---|---|
| 端口(Port) | 模块的对外接口 | input clk、output [7:0] data_out |
| 线网(Net) | 连接各实例的「导线」 | wire clk_buf、wire [7:0] internal_bus |
| 引脚(Pin) | 实例的输入输出接口 | .A(clk)、.Z(clk_buf)、.D(data_in) |
这里有个关键点,我当年踩过坑:线网名和引脚名是两码事。线网是物理连线,引脚是实例的接口。同一个线网可以连到多个实例的引脚上,但一个引脚只能连一个线网。
避坑指南:我曾经逆向一个网表,发现某个线网叫「n1234」,它同时连了10个DFF的时钟引脚。我一开始以为这是个普通信号,后来一查——它其实是时钟树上的一个缓冲输出。如果我没注意到这个线网扇出很大,时序分析就会完全错误。
1.4 连接关系的三种基本模式
在网表里,连接关系其实就三种模式。你记住这三种,后面分析路径就轻松了:
- 一对一连接:一个输出引脚连到一个输入引脚。比如反相器的输出直接连到下一个门的输入。这种最简单,路径清晰。
- 一对多连接(扇出):一个输出引脚连到多个输入引脚。比如时钟信号要驱动几百个触发器。这种在时序分析里要特别关注,因为负载大,延迟也大。
- 多对一连接(扇入):多个输出引脚连到同一个线网。这种情况在标准数字设计中很少见(因为会短路),但在三态总线里会出现。逆向分析时看到这种结构,要小心处理。
我个人习惯,拿到网表后先跑一个「扇出分析」。把所有扇出大于10的线网标出来,这些往往是时钟、复位、使能信号。它们就是关键路径的「嫌疑犯」。
1.5 小结
好了,这一章的内容就这些。总结一下:
- 标准单元库是网表的「字母表」,你得认识每个单元的符号和功能。
- 网表是分层的:顶层→模块→实例。逆向分析时,从顶层往下看,先抓大结构,再抠细节。
- 连接关系就三种元素:端口、线网、引脚。搞清楚谁连谁,路径就出来了。
下一章,咱们会正式进入关键路径提取。但在此之前,我建议你找个简单的网表,自己动手画一画它的层级树和连接图。纸上得来终觉浅,绝知此事要躬行。
公众号:蓝海资料掘金营,微信deep3321