Source Code Explanation: main.cpp

This document provides a line-by-line explanation of the main.cpp file in both English and Chinese.
本文档提供了 main.cpp 文件的中英双语逐行解释。


1. Includes and Namespaces (引入与命名空间)

1: #include <fstream>
2: #include <iostream>
3: #include <sstream>
4: #include <string>
5: #include <vector>
6: 
7: using namespace std;

2. Utility Templates (实用模板函数)

9: /*
10:  * Swaps the values of two variables.
11:  */
12: template <typename T>
13: void my_swap(T& a, T& b)
14: {
15:     T tmp = a;
16:     a = b;
17:     b = tmp;
18: }
20: /*
21:  * In-place reverses the elements of a vector within the range [first, last).
22:  */
23: template <typename T>
24: void my_reverse(vector<T>& v, int first, int last)
25: {
26:     --last;
27:     while (first < last) {
28:         my_swap(v[first], v[last]);
29:         ++first;
30:         --last;
31:     }
32: }
34: /*
35:  * In-place reverses the entire vector.
36:  */
37: template <typename T>
38: void my_reverse_all(vector<T>& v)
39: {
40:     my_reverse(v, 0, static_cast<int>(v.size()));
41: }

3. Data Structures (数据结构)

45: /*
46:  * Manages a set of points based on a 2D boolean array to check grid coordinate occupancy in O(1) time.
47:  */
48: struct PointSet {
49:     int n;
50:     vector<vector<bool> > used;
51: 
52:     explicit PointSet(int grid_n)
53:         : n(grid_n), used(grid_n, vector<bool>(grid_n, false)) {}
54: 
55:     bool insert(int x, int y)
56:     {
57:         if (used[y][x]) return false;
58:         used[y][x] = true;
59:         return true;
60:     }
61: };
64: struct Point {
65:     int x;
66:     int y;
67:     Point() : x(0), y(0) {}
68:     Point(int x_, int y_) : x(x_), y(y_) {}
69:     bool operator==(const Point& o) const
70:     {
71:         return x == o.x && y == o.y;
72:     }
73: };
76: struct Net {
77:     int   id;
78:     Point source;
79:     Point sink;
80:     Net() : id(0) {}
81: };
83: struct Problem {
84:     int                n;
85:     vector<Point> obstructions;
86:     vector<Net>   nets;
87:     Problem() : n(0) {}
88: };
90: struct WaveRecord {
91:     int                level;
92:     vector<Point> cells;
93:     WaveRecord() : level(0) {}
94: };
96: struct NetRoute {
97:     bool                    success;
98:     vector<Point>      path;
99:     vector<WaveRecord> waves;
100:    NetRoute() : success(false) {}
101: };
103: struct RouteAttempt {
104:     vector<NetRoute> net_routes;
105:     int                   routed_count;
106:     int                   total_wirelength;
107:     vector<int>      order;
108:     RouteAttempt() : routed_count(0), total_wirelength(0) {}
109: };

4. Constants and Utilities (常量与辅助函数)

111: const int FREE        = -1;
112: const int OBSTRUCTION = -2;
113: const int TERMINAL    = -3;
115: /*
116:  * Trims leading and trailing whitespace characters (including spaces, tabs, and newlines) from a string.
117:  */
118: string trim(const string& s)
119: {
120:     const size_t first = s.find_first_not_of(" \t\r\n");
121:     if (first == string::npos) return "";
122:     const size_t last = s.find_last_not_of(" \t\r\n");
123:     return s.substr(first, last - first + 1);
124: }
126: /*
127:  * Checks if the given coordinate (x, y) is within the boundaries of the n x n grid.
128:  */
129: bool in_bounds_n(int x, int y, int n)
130: {
131:     return x >= 0 && y >= 0 && x < n && y < n;
132: }

5. Input Parsing (输入解析)

137: bool read_netlist(const string& filename, Problem& prob)
138: {
139:     ifstream input(filename.c_str());
140:     if (!input) {
141:         cerr << "Error: Cannot open netlist: " << filename << '\n';
142:         return false;
143:     }
145:     string line;
146:     bool size_read = false;
147:     int  net_id    = 0;
148:     int  line_no   = 0;
150:     while (getline(input, line)) {
151:         ++line_no;
152:         size_t comment = line.find("//");
153:         if (comment != string::npos) line = line.substr(0, comment);
154:         line = trim(line);
155:         if (line.empty()) continue;
156: 
157:         istringstream iss(line);
159:         if (!size_read) {
160:             if (!(iss >> prob.n) || prob.n <= 0) {
161:                 cerr << "Error: Invalid grid size on line " << line_no << '\n';
162:                 return false;
163:             }
164:             string extra;
165:             if (iss >> extra) {
166:                 cerr << "Error: Unexpected token '" << extra << "' in: " << line << '\n';
167:                 return false;
168:             }
169:             size_read = true;
170:             continue;
171:         }
173:         string kw;
174:         iss >> kw;
175: 
176:         if (kw == "obstruction") {
177:             Point q;
178:             if (!(iss >> q.x >> q.y)) {
179:                 cerr << "Error: Malformed obstruction: " << line << '\n';
180:                 return false;
181:             }
182:             string extra;
183:             if (iss >> extra) { ... return false; }
184:             prob.obstructions.push_back(q);
189:         } else if (kw == "net") {
190:             Net net;
191:             net.id = net_id++;
192:             if (!(iss >> net.source.x >> net.source.y >> net.sink.x >> net.sink.y)) {
193:                 cerr << "Error: Malformed net: " << line << '\n';
194:                 return false;
195:             }
196:             string extra;
197:             if (iss >> extra) { ... return false; }
198:             prob.nets.push_back(net);
203:         } else {
204:             cerr << "Error: Unknown keyword '" << kw << "' on line " << line_no << '\n';
205:             return false;
206:         }
207:     }
209:     if (!size_read) { ... }
213:     if (prob.nets.empty()) { ... }
218:     PointSet obs_set(prob.n);
219:     for (size_t i = 0; i < prob.obstructions.size(); ++i) {
220:         const Point& q = prob.obstructions[i];
221:         if (!in_bounds_n(q.x, q.y, prob.n)) { ... return false; }
225:         if (!obs_set.insert(q.x, q.y)) { ... return false; }
229:     }
231:     PointSet term_set(prob.n);
232:     for (size_t i = 0; i < prob.nets.size(); ++i) {
233:         const Net& net = prob.nets[i];
234:         if (!in_bounds_n(net.source.x, net.source.y, prob.n) ||
235:                 !in_bounds_n(net.sink.x,   net.sink.y,   prob.n)) { ... return false; }
239:         if (net.source == net.sink) { ... return false; }
243:         const Point terminals[2] = { net.source, net.sink };
244:         for (int t = 0; t < 2; ++t) {
245:             if (!term_set.insert(terminals[t].x, terminals[t].y)) { ... return false; }
249:         }
250:     }
251:     return true;
252: }

6. Core Algorithm: Lee-Moore Router (核心算法)

259: NetRoute lee_route(const Problem& p,
260:                    const Net& net,
261:                    const vector<vector<int> >& occupied)
262: {
263:     static const int dx[4] = {1, -1, 0, 0};
264:     static const int dy[4] = {0, 0, 1, -1};
265: 
266:     vector<vector<int> >   labels(p.n, vector<int>(p.n, -1));
267:     vector<vector<Point> > parent(p.n, vector<Point>(p.n, Point(-1, -1)));
269:     vector<Point> current_wave;
270:     current_wave.push_back(net.source);
271:     labels[net.source.y][net.source.x] = 0;
273:     NetRoute result;
274:     WaveRecord wr0;
275:     wr0.level = 0;
276:     wr0.cells = current_wave;
277:     result.waves.push_back(wr0);
279:     bool path_exists = false;
280:     int  level       = 1;
281: 
282:     while (!current_wave.empty() && !path_exists) {
283:         vector<Point> next_wave;
285:         for (size_t ci = 0; ci < current_wave.size() && !path_exists; ++ci) {
286:             const Point& cur = current_wave[ci];
287: 
288:             for (int d = 0; d < 4; ++d) {
289:                 Point nb(cur.x + dx[d], cur.y + dy[d]);
291:                 if (!in_bounds_n(nb.x, nb.y, p.n)) continue;
292:                 if (labels[nb.y][nb.x] != -1)       continue;
294:                 const bool own_pin = (nb == net.source || nb == net.sink);
295:                 if (occupied[nb.y][nb.x] != FREE && !own_pin) continue;
297:                 labels[nb.y][nb.x] = level;
298:                 parent[nb.y][nb.x] = cur;
299:                 next_wave.push_back(nb);
300: 
301:                 if (nb == net.sink) {
302:                     path_exists = true;
303:                     break;
304:                 }
305:             }
306:         }
308:         if (!next_wave.empty()) {
309:             WaveRecord wr;
310:             wr.level = level;
311:             wr.cells = next_wave;
312:             result.waves.push_back(wr);
313:         }
314:         current_wave = next_wave;
315:         ++level;
316:     }
318:     if (!path_exists) return result;
319: 
320:     Point cur = net.sink;
321:     while (!(cur == net.source)) {
322:         result.path.push_back(cur);
323:         cur = parent[cur.y][cur.x];
324:     }
325:     result.path.push_back(net.source);
326: 
327:     my_reverse_all(result.path);
328:     result.success = true;
329:     return result;
330: }

7. Multi-Net Sequence Routing (多网络顺序布线)

336: vector<vector<int> > make_initial_occupancy(const Problem& p)
337: {
338:     vector<vector<int> > occ(p.n, vector<int>(p.n, FREE));
339:     for (size_t i = 0; i < p.obstructions.size(); ++i)
340:         occ[p.obstructions[i].y][p.obstructions[i].x] = OBSTRUCTION;
341:     for (size_t i = 0; i < p.nets.size(); ++i) {
342:         occ[p.nets[i].source.y][p.nets[i].source.x] = TERMINAL;
343:         occ[p.nets[i].sink.y  ][p.nets[i].sink.x  ] = TERMINAL;
344:     }
345:     return occ;
346: }
352: RouteAttempt route_in_order(const Problem& p, const vector<int>& order)
353: {
354:     vector<vector<int> > occ = make_initial_occupancy(p);
355:     RouteAttempt result;
356:     result.net_routes.resize(p.nets.size());
357:     result.order = order;
359:     for (size_t oi = 0; oi < order.size(); ++oi) {
360:         int        idx = order[oi];
361:         const Net& net = p.nets[static_cast<size_t>(idx)];
362:         NetRoute   route = lee_route(p, net, occ);
364:         if (route.success) {
365:             ++result.routed_count;
366:             result.total_wirelength += static_cast<int>(route.path.size()) - 1;
367:             for (size_t pi = 0; pi < route.path.size(); ++pi) {
368:                 const Point& q = route.path[pi];
369:                 if (!(q == net.source) && !(q == net.sink))
370:                     occ[q.y][q.x] = idx;
371:             }
372:         }
373:         result.net_routes[static_cast<size_t>(idx)] = route;
374:     }
375:     return result;
376: }

8. Retry Strategy Manager (重试策略管理器)

382: bool better(const RouteAttempt& a, const RouteAttempt& b)
383: {
384:     if (a.routed_count != b.routed_count) return a.routed_count > b.routed_count;
385:     return a.total_wirelength < b.total_wirelength;
386: }
396: RouteAttempt route_with_retries(const Problem& p)
397: {
398:     const int N = static_cast<int>(p.nets.size());
399: 
400:     vector<int> order(static_cast<size_t>(N));
401:     for (int i = 0; i < N; ++i)
402:         order[static_cast<size_t>(i)] = i;
403: 
404:     RouteAttempt best = route_in_order(p, order);
405:     if (best.routed_count == N) return best;
407:     int max_retries = N;
408:     for (int retry = 0; retry < max_retries; ++retry) {
409:         int failed_net = -1;
410:         for (int i = 0; i < N; ++i) {
411:             if (!best.net_routes[static_cast<size_t>(i)].success) {
412:                 failed_net = i;
413:                 break;
414:             }
415:         }
416:         if (failed_net == -1) break;
418:         /* Move failed_net to the front of the order */
419:         vector<int> new_order;
420:         new_order.push_back(failed_net);
421:         for (size_t i = 0; i < order.size(); ++i) {
422:             if (order[i] != failed_net) {
423:                 new_order.push_back(order[i]);
424:             }
425:         }
426:         order = new_order;
428:         RouteAttempt attempt = route_in_order(p, order);
429:         if (better(attempt, best)) {
430:             best = attempt;
431:         }
432:         if (best.routed_count == N) break;
433:     }
434:     return best;
435: }

9. Output Formatting (输出格式化)

441: void write_result(const Problem& p, const RouteAttempt& result)
442: {
443:     cout << "grid " << p.n << '\n';
444:     for (size_t i = 0; i < p.obstructions.size(); ++i)
445:         cout << "obstruction " << p.obstructions[i].x << ' ' << p.obstructions[i].y << '\n';
446: 
447:     cout << "order";
448:     for (size_t i = 0; i < result.order.size(); ++i) cout << ' ' << result.order[i];
449:     cout << '\n';
451:     for (size_t i = 0; i < p.nets.size(); ++i) {
452:         const Net&      net   = p.nets[i];
453:         const NetRoute& route = result.net_routes[i];
454: 
455:         cout << "net " << net.id ...
476:     cout << "summary " << result.routed_count << ' ' << p.nets.size()
477:          << ' ' << result.total_wirelength << '\n';
478: }

10. Main Entry Point (主函数入口)

483: int main(int argc, char* argv[])
484: {
485:     if (argc != 2) {
486:         cerr << "Usage: " << argv[0] << " <netlist>\n";
487:         return 1;
488:     }
489:     const string in_file = argv[1];
491:     Problem prob;
492:     if (!read_netlist(in_file, prob)) {
493:         return 1;
494:     }
497:     const RouteAttempt result = route_with_retries(prob);
498:     write_result(prob, result);
501:     cerr << "\n--- Run Info ---\n";
502:     cerr << "Routed " << result.routed_count << " of " << prob.nets.size() << " nets.\n";
503:     cerr << "Total wirelength: " << result.total_wirelength << "\n";
504:     cerr << "Selected order:";
505:     for (size_t i = 0; i < result.order.size(); ++i)
506:         cerr << ' ' << result.order[i];
507:     cerr << "\n";
508: 
509:     return 0;
510: }