第三章 网表解析与预处理:从原始数据到可分析结构

说实话,网表解析这一步,看着简单,做起来全是坑。

我刚开始做硬件安全分析那会儿,拿到一个几十万门的网表文件,直接往工具里一丢,结果解析出来全是乱码。后来才明白——网表这东西,不同工具、不同工艺库,格式差异大得离谱。你想想看,一个综合工具吐出来的网表,跟另一个工具吐出来的,连端口命名规则都可能不一样。

所以这一章,咱们就聊聊怎么把那些「原始」的网表,变成我们能用的、标准化的数据结构。

3.1 网表解析工具的选择

做网表解析,工具选对了,事半功倍。我个人习惯用两套工具搭配着来。

3.1.1 Yosys:开源界的利器

Yosys 是我最常用的开源综合工具,它不仅能做综合,还能做网表解析和转换。它的优势在于:

  • 支持多种输入格式:Verilog、EDIF、BLIF 都能吃
  • 内部表示统一:解析后都转成 RTLIL 格式,方便后续处理
  • 脚本化操作:用 Tcl 或 Python 接口,自动化程度高

举个例子,用 Yosys 读入一个 Verilog 网表:

# 读入设计文件
read_verilog top_module.v
# 层次化展开
flatten
# 输出统计信息
stat
# 写出处理后的网表
write_verilog -noattr processed_netlist.v

我在项目中遇到过一个问题:某个第三方 IP 的网表里,用了很多 Synopsys 特有的 `$sdf_*` 系统函数。Yosys 默认不认识这些,直接报错。后来我加了个 `-lib` 参数,把标准单元库的 Verilog 模型也读进去,才搞定。

小技巧:用 Yosys 解析大型网表时,记得加 `-noopt` 参数。不然它默认会做优化,把一些冗余逻辑给优化掉,反而破坏了安全分析需要的原始结构。

3.1.2 Synopsys 工具链:工业级的选择

如果你在芯片公司工作,大概率会用到 Synopsys 的工具链。DC(Design Compiler)和 Formality 都能导出网表,而且格式更规范。

Synopsys 工具生成的网表,通常有这些特点:

  • 命名规则统一:`U_*` 表示标准单元,`I_*` 表示实例
  • 包含时序信息:`.lib` 库文件里有时序弧数据
  • 支持 SDC 约束:时序约束文件可以直接关联

不过,Synopsys 的网表也有个麻烦——它喜欢用 `\` 转义特殊字符。比如 `\reg[0] ` 这种写法,解析的时候要特别处理。

注意:Synopsys 网表中的 `\` 转义字符,在 Linux 和 Windows 下的处理方式不同。我吃过这个亏——在 Windows 上解析好好的脚本,放到 Linux 服务器上就跑不起来了。后来统一用 Python 的 `re` 模块做预处理,才彻底解决。

3.2 网表标准化处理

不同工具吐出来的网表,就像不同方言——意思一样,说法不同。标准化处理,就是把它们翻译成「普通话」。

3.2.1 端口映射标准化

我见过最离谱的端口命名:同一个时钟信号,在顶层叫 `clk`,在子模块叫 `clock`,在综合后的网表里叫 `CK`。这要是直接分析,肯定乱套。

标准化的做法是:

  1. 建立端口映射表:把不同命名统一成标准名称
  2. 信号类型标注:区分时钟、复位、数据、控制信号
  3. 方向性确认:明确每个端口的输入/输出/双向属性
# 端口映射示例
port_mapping = {
    'clk': 'CLOCK',
    'clock': 'CLOCK',
    'CK': 'CLOCK',
    'rst_n': 'RESET_N',
    'reset': 'RESET_N',
    'RST': 'RESET_N'
}

3.2.2 层次化展开

网表通常有层次结构——顶层模块调用子模块,子模块再调用标准单元。做安全分析时,我建议把层次全部展开,变成扁平网表。

为什么?因为安全漏洞往往藏在跨层次的连接里。你想想看,一个 Trojan 可能藏在某个子模块里,通过顶层信号触发。不展开,根本发现不了。

Yosys 的 flatten 命令就是干这个的:

# 展开所有层次
flatten
# 查看展开后的模块
hierarchy -check
# 重命名所有内部信号
rename -hide path
核心要点:层次化展开后,所有信号名都变成了扁平路径。比如 `top.sub1.reg_out` 会变成 `top_sub1_reg_out`。这样虽然名字长了点,但分析起来一目了然。

3.2.3 标准单元库对齐

不同工艺库的标准单元,名字和功能可能不同。比如:

功能 台积电 28nm 中芯国际 55nm 华虹 130nm
D触发器 DFFQ_X1 DFFR_1 DFF_1
二输入与非门 NAND2_X1 ND2_1 NAND2_1
反相器 INV_X1 INV_1 INV_1

标准化时,需要建立一个「功能到单元名」的映射表。我一般用 JSON 文件维护:

{
    "DFF": ["DFFQ_X1", "DFFR_1", "DFF_1"],
    "NAND2": ["NAND2_X1", "ND2_1", "NAND2_1"],
    "INV": ["INV_X1", "INV_1", "INV_1"]
}

3.3 网表数据结构的构建

解析和标准化都做完了,接下来就是构建数据结构。这一步决定了后续分析的效率和准确性。

3.3.1 图结构:网表的本质

网表本质上就是个有向图——标准单元是节点,连线是边。我习惯用邻接表来存储:

class NetlistGraph:
    def __init__(self):
        self.nodes = {}      # 节点:标准单元
        self.edges = []      # 边:连线
        self.inputs = []     # 输入端口
        self.outputs = []    # 输出端口
        self.registers = []  # 寄存器列表
    
    def add_cell(self, name, cell_type, ports):
        self.nodes[name] = {
            'type': cell_type,
            'ports': ports,
            'fanin': [],
            'fanout': []
        }

为什么要用图结构?因为安全分析本质上就是图分析。比如:

  • 路径分析:从输入到输出的所有路径
  • 扇入扇出分析:某个信号影响了多少后续逻辑
  • 环路检测:组合逻辑环路往往是漏洞的温床

3.3.2 信号追踪表

除了图结构,我还会建一个信号追踪表。这个表记录了每个信号的「前世今生」:

信号名 源单元 源端口 目标单元 目标端口 信号类型
net_123 U_AND2_1 Z U_DFF_1 D data
clk_tree BUF_1 Z U_DFF_1 CK clock

有了这个表,追踪一个信号从产生到消费的完整路径,就变得非常直观。

经验之谈:信号追踪表最好用数据库存,比如 SQLite。我早期用 CSV 文件,结果网表一大了(几十万行),查询速度慢得让人崩溃。换成 SQLite 后,加个索引,查询速度提升了上百倍。

3.3.3 时序弧信息

做安全分析,光有结构信息不够,还得有时序信息。比如:

  • 建立时间:数据必须在时钟沿前稳定
  • 保持时间:数据必须在时钟沿后保持
  • 传播延迟:信号从输入到输出的延迟

这些信息在 .lib 文件里都有。我一般会解析 .lib 文件,提取出每个标准单元的时序弧:

# 时序弧示例
cell DFFQ_X1 {
    pin D {
        timing() {
            related_pin : CK;
            timing_type : setup_rising;
            rise_constraint("0.1:0.2:0.3");
        }
    }
}

有了时序弧信息,就能做更深入的分析。比如检查是否存在「建立时间违规」——这往往是硬件木马利用的漏洞点。

3.4 知识体系总览

说了这么多,我画个图帮你理清思路:

网表解析与预处理知识体系 原始网表输入 标准单元库 时序约束文件 网表解析工具 Yosys(开源) | Synopsys DC/Formality(商业) 网表标准化处理 端口映射标准化 → 层次化展开 → 标准单元库对齐 统一命名规则 | 扁平化结构 | 功能映射 网表数据结构构建 图结构(节点+边) | 信号追踪表 | 时序弧信息 邻接表存储 | SQLite索引 | .lib时序解析 输出:标准化的可分析网表

这张图把整个流程串起来了。从原始输入开始,经过工具解析、标准化处理,最后构建成可分析的数据结构。每一步都有坑,但每一步也都有对应的解决方案。

嗯,网表解析和预处理这块,说白了就是「磨刀不误砍柴工」。前期把数据结构搭好了,后面的安全分析才能又快又准。我见过太多人急着做分析,结果网表都没解析对,分析出来的结果全是错的——那才是真正的浪费时间。

一句话总结:网表解析不是简单的「读文件」,而是要把不同来源、不同格式的网表,统一成标准化的图结构,为后续的安全漏洞挖掘打好基础。

公众号:蓝海资料掘金营,微信deep3321