一个基于图神经网络(GNN)的标准单元布局预测框架:直接从综合后的 Verilog 网表学习预测单元的**(x, y, 朝向)**坐标,从而替代或加速传统迭代式的 placement 流程。
本仓库只跟踪源码、配置、结果数据与文档。
data/(数据集)、log/(各阶段日志)、output/(除results.csv/results.jsonl外的运行产物)以及 ABC 编译产物等生成内容均不入库,详见.gitignore。
流水线集成了内置的 ABC fork(含物理感知映射命令)、OpenROAD 与 DREAMPlace 来生成训练数据,并使用一个 level-aware 的消息传递 GNN 预测每个单元的 (x, y, orient),最终写回 DEF 文件。
核心思路。把门级网表视为一张有向图(PI / PO / INV / AND / NAND / OR / NOR / XOR / XNOR / BUF),逐层(PI→PO 与 PO→PI)运行 GNN 消息传递,把每个 cell 回归到它的目标位置。在 DREAMPlace 放置好的电路集上训练后,模型能在毫秒级产出一份初始的 placed DEF,跳过 global-placement 的大部分迭代。
PhysicalAwareSynthesis/
├── src/ # GNN 训练与数据准备
│ ├── main.py # 入口:训练 / 验证 / 生成 DEF
│ ├── model.py # LevelAwareGNNModel(GCN/SAGE/GAT/MPNN backbone)
│ ├── train_eval.py # Trainer、MAE / MSE / MAPE / SMAPE / Acc 等指标
│ ├── data_gen.py # Verilog → PyG Data、RWPE、归一化、缓存
│ ├── data_augmentation.py # 随机 AIG 生成、DreamPlace / GiFt 配置生成器
│ ├── utils/parser.py # Verilog 解析器、节点类型词表、level 计算
│ ├── visualize/ # Loss / RMSD / HPWL 等可视化脚本
│ └── gt_models/ # 参考 GNN baseline(GraphGPS、NodeFormer、DiFFormer 等)
│
├── run/ # 运行脚本(详见「如何运行」)
│ ├── run_full_pipeline.sh # ★ 主入口:端到端(综合→floorplan→放置→训练)
│ ├── runsyns.sh # 阶段① ABC 综合映射:AIG → Verilog
│ ├── rename_modules.sh # 阶段② module <name> → module top
│ ├── runfloorplan.sh # 阶段③ OpenROAD floorplan:Verilog → DEF
│ ├── runplacement.sh # 阶段④ DREAMPlace 放置:DEF → placed DEF + JSON
│ ├── run_gift_init.sh # 阶段⑤(可选)GiFt 放置初始化
│ ├── run_route_minimal.sh # 阶段⑥(可选)单设计 OpenROAD 布线
│ ├── prepare_placement_jsons.py# 辅助:生成 DreamPlace JSON 变体
│ ├── gen_pin_config.py # 辅助:LEF → pin-geometry JSON
│ ├── batch_process.py # 评估:批量 HPWL / delay
│ ├── compare_train_memory.py # 评估:训练显存对比
│ ├── run_multigpu.sh # 训练:torchrun 多卡启动
│ ├── debug_abc.sh # 调试:交互式 ABC 自检
│ └── ablation_study.sh # 实验:消融研究
│
├── scripts/
│ ├── tclscript/ # OpenROAD floorplan / route 流程
│ ├── dreamplace_script/ # 每个设计的 DREAMPlace JSON 配置(基准)
│ ├── dreamplace_script_variants/ # 由 prepare_placement_jsons.py 生成的变体
│ ├── dreamplace_script_addition/ # 新设计的自动生成配置
│ ├── dreamplace_script4experiment/ # 实验用配置集
│ ├── gift_script*/ # GiFt 配置集
│ ├── extract_pin_pos.py # LEF → pin-geometry JSON
│ └── test_script/ # 冒烟测试网表
│
├── abc/ # Berkeley ABC 的 fork(含物理感知命令)
│ └── README.md # 介绍 read_physical、pfmap、pwmap、read_pin_config
│
├── lib/ # Sky130 + ASAP7 的 LEF / Liberty 文件
│
├── docs/ # 文档与论文
│ └── Physical_Aware___ICCAD.pdf
│
├── result/ # 最终数值、HPWL / delay JSON(图表 PNG/PDF 不入库)
├── output/ # 汇总实验结果(results.csv / results.jsonl)
│
└── README.md
生成物不入库:
data/(数据集)、log/、logs/、logs_gift4experiment/(日志)、output/models/与output/ablation_*/(运行产物)、release_packages/(打包)、ABC 编译产物等均被.gitignore忽略,需要时由流水线重新生成。
由 utils/parser.py 解析网表:
- 节点 = net(信号)。每个 net 继承驱动它的门类型(
INPUT、INV、AND…)。原始输出端被补成独立的OUTPUT节点。 - 边 =
(driver_net, driven_net)。扫描每个门实例,把所有 input port 与 output port 配对得到。 - Level = 从任意 PI 到最深可达 PO 的拓扑深度(
compute_levels),用来驱动 GNN 的逐层传播。 - 位置编码 = 无向图上长度 16 的 Random-Walk PE(
AddRandomWalkPE,小图有手动 fallback)。 - 目标 = DREAMPlace 输出的
.gp.json中的(x, y, orient),按每个电路归一化到[0, 1](推理时用缓存的min_vals/ranges反归一化)。 - 缓存 = 处理后的图按电路缓存在
<circuit>/processed_data.pt,并汇总到data/processed_data/all_circuits_data.pt。缓存版本由processing_version字段跟踪。
LevelAwareGNNModel 是一个双向、按 level 调度的 GNN:
- 输入 = 节点类型 one-hot ⊕ 在 PI/PO 节点注入的
(x, y, orient)⊕ 可选的入/出度 ⊕ 可选的 RWPE / ID 嵌入。 - Backbone = GCN、SAGE、GAT 或自定义 MPNN;
forward(PI → PO)与backward(PO → PI)使用共享参数的实例。 - Level 调度 = 只用指向 level
l节点的边来更新 levell的节点。按≈ 2·√max_level分段推进,每段用torch.utils.checkpoint控制峰值显存。 - 输出 MLP = 两层 head,回归每个节点的
(x_norm, y_norm, orient_logit)。朝向用sigmoid(.) > 0.5解码为N或FS。
- Loss = 对
(x, y, orient)的MAE/MSE加权和,叠加可选的 HPWL(边 L1)与 density(方差)辅助 loss(--hpwl_weight、--density_weight)。 - 多卡:
torch.nn.parallel.DistributedDataParallel(用run/run_multigpu.sh启动);同时也支持单卡 / CPU。 - 通过 METIS 对超大电路做 sub-graph 切分(
--use_subgraph_sampling),避免 OOM。 - 在线数据增强:随机旋转 / 翻转 placement 目标(
--augment)。 - 可选特征:随机游走位置编码(
--use_pos_emb)、唯一 ID 嵌入(--use_id_emb)、入/出度(--use_degree)。 - 结果按
(fraction, seed)追加到output/results.csv和output/results.jsonl,并记录峰值 / 末端 CUDA 显存。 - 模式:完整训练、纯验证(
--val_only --load_model <ckpt>)、DEF 生成(--val_to_def --load_model <ckpt>)。
在上游 ABC 的基础上新增物理感知命令:
| 命令 | 用途 |
|---|---|
read_physical <json> |
从 JSON 读取每个单元的坐标和朝向。 |
read_pin_config <json> |
读入库的 pin 几何信息,用于朝向感知的线长估算。 |
pfmap |
标准单元映射,目标最大化线长最小化(最大线长最短)。 |
pwmap |
标准单元映射,目标总线长最小化。 |
映射由 run/batch_process.py 和 run/debug_abc.sh 驱动,使用 lib/ 中的 Sky130 liberty / LEF。
随机 AIGs → [ABC fork:AIG → 映射后的 Verilog]
→ 把 `module <name>` 改名为 `module top`
→ [OpenROAD:floorplan → DEF]
→ [DREAMPlace:global + detail 放置 → DEF + JSON]
→ [GNN 训练:python3 src/main.py --epochs 300]
每个阶段都有对应的启动脚本(runsyns.sh、rename_modules.sh、runfloorplan.sh、runplacement.sh)。
本仓库假定运行在 Ubuntu 类 Linux 环境,并配有支持 CUDA 的 GPU。外部工具不在仓库内,需自行安装/编译。
# 1. 克隆
git clone git@github.com:zhoujy22/PhysicalAwareSynthesis.git
cd PhysicalAwareSynthesis
# 2. Python 依赖(建议;按需安装)
pip install torch torchvision torch-geometric tqdm numpy
# 可视化可选:matplotlib、pandas
# 3. 编译 ABC fork
cd abc && make -j$(nproc)
cd ..
# 4. 配置外部工具路径:编辑 run/config.sh,把其中的占位路径
# (/path/to/DREAMPlace/...、/path/to/OpenROAD/... 等)改成你的安装位置。
# 也可运行时用环境变量覆盖,例如:
# OPENROAD_BIN=/opt/openroad/build/bin/openroad bash run/runfloorplan.shlib/ 下的 PDK 文件(Sky130 HD、ASAP7)足以跑完整流程。
run/ 下的脚本按角色分四类:主入口、流水线阶段、训练/推理、评估/辅助。日常只需跑主入口;手动复现则按阶段顺序执行。
- 编译 ABC fork:
cd abc && make -j$(nproc) && cd .. - 在
run/config.sh里把 DREAMPlace / OpenROAD / GiFt 的占位路径(/path/to/...)改成你的安装位置;所有run/*.sh都会 source 它。也可运行时用环境变量覆盖。 - 准备电路数据:AIG 文件放
data/<name>.aig,或把网表放到data/sysdata/<name>/。
bash run/run_full_pipeline.sh [N] # N = 要生成的新电路数,默认 10按顺序自动执行:综合 → 重命名模块 → floorplan → 生成放置配置 → 放置 → 训练 GNN(300 epochs)。最终在 data/experiment_data/ 得到每个电路的 placed DEF + JSON,并在 output/results.csv / output/results.jsonl 记录训练指标。
完整流水线共 6 个阶段,按序执行:
| 步骤 | 命令 | 输入 → 输出 |
|---|---|---|
| ① 综合映射 | bash run/runsyns.sh |
AIG → 映射后 Verilog |
| ② 重命名模块 | bash run/rename_modules.sh |
module <name> → module top |
| ③ Floorplan | bash run/runfloorplan.sh |
Verilog → placed DEF(OpenROAD) |
| ④ 放置 | bash run/runplacement.sh [--parallel N] |
DEF → .gp.def + .gp.json(DREAMPlace) |
| ⑤ GiFt 初始化(可选) | bash run/run_gift_init.sh |
用 GiFt 做放置初始化 |
| ⑥ 布线(可选) | bash run/run_route_minimal.sh --design <d> --verilog <f> --def <f> --lef-tech <f> --lef-std <f> --lib <f> |
placed DEF → routed DEF + DRC / TNS / WNS 报告 |
runplacement.sh会自动先调用prepare_placement_jsons.py生成 JSON 变体;批量布线多个设计用run_batch_route.sh(编辑脚本里的TARGETS列表)。
python3 src/main.py \
--fractions 0.9 \
--seeds 0 \
--epochs 300 \
--hidden 256 --layers 5 \
--gnn_type gcn \
--use_pos_emb \
--output_dir output/run_quickstartbash run/run_multigpu.sh # 按需调整脚本里的 torchrun 配置python3 src/main.py \
--val_only \
--load_model output/models/<your_ckpt>.pt \
--fractions 0.9 --seeds 0python3 src/main.py \
--val_to_def \
--load_model output/models/<your_ckpt>.pt \
--output_dir output/run_inference
# 会在每个电路目录下写出 <circuit>_pseudo.def。| 脚本 | 作用 |
|---|---|
run/batch_process.py |
批量评估 placement 质量(HPWL / capacitance / delay)→ result/experiment_results*.json |
run/compare_train_memory.py |
对比训练显存 |
run/prepare_placement_jsons.py |
生成每个设计的 DreamPlace JSON 变体 |
run/gen_pin_config.py |
从 LEF 生成 pin-geometry JSON |
run/debug_abc.sh |
交互式 ABC 自检 |
run/ablation_study.sh |
一键跑 6 组消融实验 |
| 任务 | 命令 |
|---|---|
| 生成随机 AIG | python3 src/data_augmentation.py gen_aigs --num 50 |
| 生成 DREAMPlace JSON | python3 src/data_augmentation.py gen_configs --sysdata data/experiment_data |
| 生成 GiFt JSON | python3 src/data_augmentation.py gen_gift --sysdata data/experiment_data |
| 画训练曲线 | python3 src/visualize/plot_training_log.py |
output/results.csv/output/results.jsonl— 每次运行的指标(x、y、orient上的 MAE / MSE / MAPE / SMAPE / Acc,以及最佳 epoch、train/val 数量、总时长、单 epoch 平均时长、峰值 / 末端 CUDA 显存)。output/models/— 设置了--save_model后保存的 checkpoint(不入库,本地生成)。result/experiment_results*.json— 下游的 HPWL / capacitance / delay,每个设计、每种 mapping 变体一组数。result/*.png、result/*.pdf— 图表(训练 loss、RMSD、HPWL、delay、capacitance 等)。
- 默认设备是
cuda:0(如可用)。想强制 CPU,加--device cpu(GNN 阶段会很慢)。 - GNN 训练的是按电路归一化后的
(x, y, orient);反归一化使用Data对象上缓存的min_vals/ranges。 - DREAMPlace / OpenROAD / GiFt 的二进制不在仓库内,只保留了驱动它们的 JSON 配置。请按你的安装位置修改
run/config.sh里的路径(或运行时用环境变量覆盖)。 abc/是 Berkeley ABC 的 fork;只有 fork 特有的命令记录在abc/README.md,上游行为保持不变。- 缓存失效由
src/data_gen.py中的PROCESSING_VERSION控制;如果改了图构造逻辑,记得把这个版本号往上提。