4. Verilog网表读入与层次化设计展开

任务说明

本案例使用 OpenROAD 的 Tcl 接口读入一个 Verilog 网表,执行层次展开(flatten),并统计展开前后的实例(instance)、线网(net)和端口(port)数量。核心命令为 read_verilog、link_design、flatten,统计通过 get_cells、get_nets、get_ports 完成。

环境与依赖

  • OpenROAD 已编译并可在 PATH 中调用(openroad 命令可用)。
  • 一个含层次结构的 Verilog 网表文件,本案例提供最小可复现示例。

示例网表

保存为 top.v。顶层 top 例化两个 sub,sub 内部再例化一个 leaf,形成三层层次。

module leaf (input a, input b, output y);
  assign y = a & b;
endmodule

module sub (input a, input b, output y);
  leaf u_leaf (.a(a), .b(b), .y(y));
endmodule

module top (input clk, input a, input b, output y0, output y1);
  sub u_sub0 (.a(a), .b(b), .y(y0));
  sub u_sub1 (.a(a), .b(b), .y(y1));
endmodule

OpenROAD 脚本

保存为 run.tcl。脚本读入网表、链接设计、统计层次展开前的数量,执行 flatten 后再统计一次。

read_verilog top.v
link_design top

proc report_counts {tag} {
  set cells [llength [get_cells *]]
  set nets  [llength [get_nets *]]
  set ports [llength [get_ports *]]
  puts "\[$tag\] cells=$cells nets=$nets ports=$ports"
}

report_counts "before_flatten"
flatten
report_counts "after_flatten"

运行方式

openroad -no_init -exit run.tcl

验证方法与通过条件

  • 脚本正常退出,无 Tcl 报错。
  • 输出两行统计:before_flatten 与 after_flatten。
  • 展开前 cells 应包含层次实例(u_sub0、u_sub1、u_leaf 等),展开后层次被消除,cells 数量按叶子单元展开后重新计算。
  • 端口数量在展开前后保持一致(顶层端口不变),可作为一致性检查。

层次展开流程

top.v read_verilog link_design top 统计 before get_cells/nets/ports flatten 层次展开 统计 after 对比输出

常见问题

  • link_design 报找不到模块:确认 read_verilog 已成功读入且顶层模块名与 link_design 参数一致。
  • flatten 后 get_cells 数量变化不明显:检查网表是否确实存在多级例化;单层网表展开前后数量可能相同。
  • 端口数量异常:确认顶层模块端口声明完整,未被优化掉。