CUGR Global Routing 算法设计文档
项目概述
CUGR (Chinese University of Hong Kong Global Routing) 是一个详细布线驱动的3D全局路由器,由香港中文大学Young教授团队开发。与传统以线长和资源溢出为质量指标的全局路由器不同,CUGR的解质量完全由最终详细布线结果决定。
核心特性
- 概率成本模型:基于使用情况的资源建模
-
- 3D模式路由:结合2D模式路由和层分配的优化技术
-
- 多级迷宫路由:利用两级路由策略
-
- 补丁技术 :添加有用的布线引导以改善详细布线路径性
参考论文:Jinwei Liu et al., "CUGR: Detailed-Routability-Driven 3D Global Routing with Probabilistic Resource Model", DAC 2020
- 补丁技术 :添加有用的布线引导以改善详细布线路径性
1. 系统架构
┌─────────────────────────────────────────────────────────────┐
│ Global Routing Flow │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Input │───▶│ Database │───▶│ Router │ │
│ │ (LEF/DEF) │ │ Init │ │ (RRR) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ GrRouteGrid │◀──▶│SingleNet │ │
│ │ (Cost Model)│ │ Router │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │Congestion │ │ MazeRoute │ │
│ │ Map │ │ (Dijkstra) │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Output │◀───│GenGuide │ │
│ │ (.guide) │ │ (Patch) │ │
│ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
代码模块结构
| 模块 | 文件 | 功能 |
|---|---|---|
| 数据库 | db/Database.cpp, gr_db/GrDatabase.cpp |
网格图、网络信息、资源管理 |
| 单网络路由 | single_net/InitRoute.cpp, MazeRoute.cpp |
FLUTE、模式路由、迷宫路由 |
| 多网络路由 | multi_net/Router.cpp, Scheduler.cpp |
RRR迭代、调度、并行处理 |
| 成本模型 | gr_db/GrRouteGrid.cpp, CongestionMap.cpp |
概率成本、历史成本 |
2. 核心数据结构
2.1 全局路由网格 (GrRouteGrid)
cpp
class GrRouteGrid {
// 资源使用记录
vector<vector<vector<UsageT>>> routedWireMap; // [layer][gridline][cp]
vector<vector<vector<std::pair<int, DBU>>>> fixedMetalMap; // [layer][gridline][cp]
vector<vector<vector<double>>> histWireUsageMap; // 历史使用
vector<vector<vector<UsageT>>> routedViaMap; // [layer][x][y]
// 成本参数
double unitViaMultiplier = 1.0; // Via单位成本乘数
double logisticSlope = 2.0; // Logistic函数斜率
double wireCapDiscount = 1.0; // 线容量折扣
double viaCapDiscount = 1.0; // Via容量折扣
};
```
### 2.2 网络表示 (GrNet)
```cpp
class GrNet {
db::Net dbNet; // 设计数据库中的网络
vector<vector<gr::GrBox>> pinAccessBoxes; // 引脚访问盒
vector<vector<gr::GrBox>> wireRouteGuides; // 线布线引导
vector<gr::GrBox> viaRouteGuides; // Via布线引导
vector<shared_ptr<gr::GrSteiner>> gridTopo; // 网格拓扑树
};
```
### 2.3 网格图 (GridGraph)
```cpp
class GridGraph {
vector<vector<int>> conn; // 连接关系 [vertex][direction]
vector<vector<db::CostT>> edgeCost; // 边成本
vector<gr::PointOnLayer> vertexToPoint; // 顶点到网格点映射
vector<vector<int>> pinToVertex; // 引脚到顶点映射
};
```
---
## 3. 算法原理
### 3.1 概率成本模型
#### 3.1.1 Wire成本计算
```cpp
db::CostT getWireCost(const GrEdge& edge) const {
return getWireDistCost(edge) + getWireShortCost(edge);
}
```
**距离成本**:
WireDistCost = Manhattan distance
**短路成本(Logistic模型)**:
demand = fixed_usage + wire_usage + 1 + sqrt(via_num) * unit_sqrt_via_usage
capacity = num_tracks * wire_cap_discount
WireShortCost = expected_overflow_length / (1 + exp(-slope * (demand - capacity)))
* unit_short_cost
* ```
3.1.2 Via成本计算
cpp
db::CostT getViaCost(const GrPoint& via) const {
return database.getUnitViaCost() * (unitViaMultiplier + getViaShortCost(via));
}
```
**Via短路成本**:
ViaShortCost = Σ(1 / (1 + exp(-slope * (incell_used - incell_area))))
for side in [current_layer, upper_layer]
```
3.2 3D模式路由
3.2.1 FLUTE树生成
使用FLUTE算法生成初始Steiner树:
cpp
void InitRoute::runFlute() {
// 1. 获取网络中心
// 2. 选择最佳引脚盒(优先无违规)
// 3. 构建位置到引脚映射
// 4. 调用FLUTE生成Steiner树
Tree flutetree = flute(degree, xs, ys, ACCURACY);
// 5. 构建路由节点和连接关系
for (branch : flutetree.branches) {
RouteNode node(branch.x, branch.y);
routeNodes[node.idx] = node;
}
}
```
#### 3.2.2 边移动优化 (Edge Shifting)
优化Steiner树边位置以减少拥塞:
For each Steiner-Steiner edge:
-
计算安全移动范围(邻边交叉区域)
-
- 评估每个候选位置的总成本
-
- 移动到最小成本位置
-
- 合并重叠节点
-
```
3.2.3 模式路由
cpp
void InitRoute::patternRoute() {
for (edge : routeEdges) {
// 1. 计算退出成本(考虑via成本)
for (layer : all_layers) {
exitCosts[layer] = calcExitCost(fromNode, layer);
}
// 2. L型模式路由
if (fromNode.x == toNode.x || fromNode.y == toNode.y) {
// 直线:无拐点
routeStraight(edge);
} else {
// L型:一个拐点
routeLShape(edge);
}
}
}
```
**L型路由**:
For each to_layer:
bend_point = (fromNode.x, toNode.y) or (toNode.x, fromNode.y)
min_cost = INF
For each from_layer:
if (from_layer.dir == to_layer.dir) continue
cost = exitCosts[from_layer] +
wire_cost(from_layer, bend) +
via_cost(from_layer, to_layer, bend) +
wire_cost(to_layer, bend, toNode)
if (cost < min_cost):
best_from_layer = from_layer
```
3.3 迷宫路由
3.3.1 网格图构建
CoarseGridGraphBuilder(RRR阶段):
1. 粗化网格:cellWidth × cellHeight 个网格点合并为一个粗化点
2. 2. 添加层间连接(via)
3. 3. 添加层内连接(wire)
4. 4. 计算基于拥塞图的边成本
5. ```
**GuideGridGraphBuilder**(补丁阶段):
- 按方向切割引导区域
-
- 为每个引导区域创建顶点
-
- 添加引导间连接(via)
-
- 添加引导内连接(wire)
10.```
- 添加引导内连接(wire)
3.3.2 Dijkstra算法
cpp
db::RouteStatus MazeRoute::route(int startPin) {
// 使用优先队列(最小堆)
priority_queue<Solution> solQueue;
// 初始化:从起始引脚开始
for (vertex : graph.getVertices(startPin)) {
solQueue.push(Solution(0, vertex, nullptr));
}
while (pins_to_connect > 0) {
// Dijkstra主循环
while (!solQueue.empty()) {
cur = solQueue.top(); solQueue.pop();
// 到达引脚?
if (isPin(cur.vertex)) {
connectPin(cur);
break;
}
// 剪枝:已有更优解
if (cur.cost > vertexCosts[cur.vertex]) continue;
// 扩展邻居
for (direction : [UP, DOWN, LEFT, RIGHT]) {
if (graph.hasEdge(cur.vertex, direction)) {
next = graph.getEdgeEndPoint(cur.vertex, direction);
new_cost = cur.cost + graph.getEdgeCost(cur.vertex, direction);
solQueue.push(Solution(new_cost, next, cur));
}
}
}
}
}
```
---
## 4. 算法流程
### 4.1 主流程 (main.cpp)
┌────────────────────────────────────────────────────────────┐
│ 1. 读取输入文件 (LEF/DEF) │
│ - 构建设计数据库 │
│ - 解析层、引脚、网络信息 │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 2. 初始化全局路由数据库 │
│ - 构建网格图 (GCellGrid) │
│ - 标记固定金属 │
│ - 初始化资源使用 │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 3. Rip-up and Reroute (RRR) 迭代 │
│ For iter = 0 to rrrIterLimit-1: │
│ a. 获取需要路由的网络列表 │
│ b. 更新成本(历史成本 + 容量成本) │
│ c. 撕销违规网络 │
│ d. 路由网络 │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 4. 后处理 │
│ - 生成补丁引导 │
│ - 优化布线路径 │
└────────────────────────────────────────────────────────────┘
↓
┌────────────────────────────────────────────────────────────┐
│ 5. 输出结果 │
│ - 写入.guide文件 │
│ - 打印统计信息 │
└────────────────────────────────────────────────────────────┘
```
4.2 RRR迭代流程 (Router::run)
cpp
for (iter = 0; iter < rrrIterLimit; iter++) {
// 1. 获取需要路由的网络
vector<int> netsToRoute = getNetsToRoute();
if (netsToRoute.empty()) break;
// 2. 网络排序(按包围盒半周长)
sortNets(netsToRoute);
// 3. 更新成本
if (iter > 0) {
addHistCost(); // 添加历史成本
fadeHistCost(); // 衰减历史成本
setUnitViaMultiplier(max(100/pow(5, iter-1), 4.0));
setLogisticSlope(initSlope * pow(2, iter));
}
// 4. 撤销违规网络
if (iter > 0) {
ripup(netsToRoute);
congMap.init(cellWidth, cellHeight);
}
// 5. 路由网络
routeApprx(netsToRoute);
}
```
### 4.3 单网络路由流程
#### 4.3.1 初始路由 (iter == 0)
┌─────────────────────────────────────────────┐
│ 1. FLUTE生成Steiner树 │
│ - 构建路由节点 │
│ - 建立连接关系 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 边移动优化 (Edge Shifting) │
│ - 迭代移动Steiner点到最优位置 │
│ - 合并重叠节点 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 模式路由 (Pattern Routing) │
│ - 计算每层退出/进入成本 │
│ - L型/Z型布线 │
│ - 层分配优化 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 4. 构建拓扑树 │
│ - 生成GrSteiner树 │
│ - 移除冗余节点 │
└─────────────────────────────────────────────┘
```
4.3.2 迷宫路由 (iter > 0)
┌─────────────────────────────────────────────┐
│ 1. 构建粗化网格图 │
│ - 合并相邻网格单元 │
│ - 基于拥塞图计算边成本 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 2. 迷宫路由 (Dijkstra) │
│ - 逐个连接引脚 │
│ - 优先队列扩展 │
│ - 成本剪枝 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 3. 回溯构建路径 │
│ - 从终点回溯到起点 │
│ - 构建Steiner树 │
│ - 合并路径节点 │
└─────────────────────────────────────────────┘
```
### 4.4 拥塞管理
#### 4.4.1 拥塞图初始化
```cpp
void CongestionMap::init(int x_crsn_scale, int y_crsn_scale) {
// 1. 构建资源使用映射
for (layer, x, y):
rsrcMap[layer][x][y] = getCellUsage(layer, x, y);
// 2. 计算粗化边成本
for (edge in coarse_edges):
crsnEdgeCostMap[edge] = calcCrsnEdgeCost(u, v);
// 3. 计算粗化via成本
for (point in coarse_points):
crsnViaCostMap[point] = calcCrsnViaCost(point);
}
```
#### 4.4.2 拥塞图更新
```cpp
void CongestionMap::update(const GrNet& net) {
// 1. 收集受影响的网格点
for (guide in net.wireRouteGuides):
enlarge_guide(guide); // 扩大更新范围
collect_points(guide);
// 2. 更新受影响的边和via成本
for (point in affected_points):
updateViaCostMap(point);
updateWireCostMap(point);
}
```
---
## 5. 关键算法细节
### 5.1 历史成本机制
**添加历史成本**:
```cpp
void addHistCost() {
for (edge in all_edges):
if (hasVio(edge)):
histWireUsageMap[edge] += 1.0;
}
```
**衰减历史成本**:
```cpp
void fadeHistCost() {
for (edge in all_edges):
histWireUsageMap[edge] *= rrrFadeCoeff; // 默认0.9
}
```
**效果**:违规边在后续迭代中成本增加,引导其他网络避开。
### 5.2 并行路由调度
```cpp
vector<vector<int>> getBatches(vector<SingleNetRouter>& routers) {
// 1. 为每个网络计算临时包围盒
for (router in routers):
bbox = computeBoundingBox(router);
router.temp_guides.push_back(bbox);
// 2. 调度:找出可并行路由的网络批次
Scheduler scheduler(routers);
batches = scheduler.schedule(); // 基于包围盒重叠
return batches;
}
```
**调度原则**:包围盒不相交的网络可并行路由。
### 5.3 补丁引导生成
```cpp
void genPatchGuides() {
// 添加额外的布线引导以改善详细布线路径性
for (wire in existing_wires):
// 在拥挤区域附近添加替代路径
if (isCongested(wire)):
patch = findAlternativePath(wire);
addPatchGuide(patch);
}
```
---
## 6. 成本参数调整
### 6.1 迭代间参数调整
```cpp
void updateCost() {
if (iter > 0) {
// Via成本指数增长(减少via使用)
setUnitViaMultiplier(max(100 / pow(5, iter-1), 4.0));
// Logistic斜率指数增长(松弛容量约束)
setLogisticSlope(initSlope * pow(2, iter));
}
// 违规成本线性增长
if (rrrIterLimit > 1) {
step = (1.0 - rrrInitVioCostDiscount) / (rrrIterLimit - 1);
setUnitVioCost(rrrInitVioCostDiscount + step * iter);
}
}
```
### 6.2 默认参数
| 参数 | 默认值 | 说明 |
|------|--------|------|
| `rrrIterLimit` | 3 | RRR迭代次数 |
| `rrrInitVioCostDiscount` | 0.8 | 初始违规成本折扣 |
| `rrrFadeCoeff` | 0.9 | 历史成本衰减系数 |
| `initLogisticSlope` | 2.0 | 初始Logistic斜率 |
| `edgeShiftingIter` | 5 | 边移动迭代次数 |
| `unitSqrtViaUsage` | 1.5 | Via使用平方根系数 |
| `wireCapDiscount` | 1.0 | 线容量折扣 |
| `viaCapDiscount` | 1.0 | Via容量折扣 |
---
## 7. 算法复杂度分析
| 阶段 | 时间复杂度 | 说明 |
|------|-----------|------|
| 数据库初始化 | O(N + M) | N=网格数, M=固定金属数 |
| FLUTE | O(d log d) | d=网络度数 |
| 边移动 | O(E × I × S) | E=边数, I=迭代数, S=搜索范围 |
| 模式路由 | O(E × L²) | L=层数 |
| 迷宫路由 | O(V log V + E) | V=顶点数, E=边数 |
| RRR迭代 | O(K × (V log V + E)) | K=迭代次数 |
| 总体 | O(K × N × V log V) | N=网络数 |
---
## 8. 示例图示

**图示说明**:
- 不同颜色代表不同网络
- - 矩形框表示布线引导区域
- - 水平/垂直线遵循层方向约束
---
## 9. 总结
CUGR全局路由器的核心创新点:
1. **详细布线驱动**:成本模型直接反映详细布线的可行性
2. 2. **概率资源模型**:使用Logistic函数平滑容量约束
3. 3. **3D模式路由**:同时优化2D布线和层分配
4. 4. **多级策略**:初始快速布线 + 迭代优化
5. 5. **历史成本**:学习式避免拥塞区域
6. 6. **并行化**:多线程加速大规模网络路由
这些技术的结合使得CUGR在ICCAD/ISPD竞赛中取得了优异的成绩。