1use std::collections::HashMap;
8use std::fmt;
9
10use crate::generic::MinDist;
11use crate::interval::Interval;
12use crate::point::Point;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum NodeType {
17 Steiner,
18 Terminal,
19 Source,
20}
21
22impl fmt::Display for NodeType {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 match self {
25 NodeType::Steiner => write!(f, "Steiner"),
26 NodeType::Terminal => write!(f, "Terminal"),
27 NodeType::Source => write!(f, "Source"),
28 }
29 }
30}
31
32#[derive(Debug, Clone)]
34pub struct RoutingNode {
35 pub id: String,
36 pub node_type: NodeType,
37 pub pt: Point<i32, i32>,
38 pub children: Vec<usize>,
39 pub parent: Option<usize>,
40 pub capacitance: f64,
41 pub delay: f64,
42 pub path_length: i32,
43}
44
45impl RoutingNode {
46 pub fn new(id: &str, node_type: NodeType, pt: Point<i32, i32>) -> Self {
47 RoutingNode {
48 id: id.to_string(),
49 node_type,
50 pt,
51 children: Vec::new(),
52 parent: None,
53 capacitance: 0.0,
54 delay: 0.0,
55 path_length: 0,
56 }
57 }
58
59 pub fn manhattan_distance(&self, other: &RoutingNode) -> i32 {
60 self.pt.min_dist_with(&other.pt) as i32
61 }
62}
63
64pub struct GlobalRoutingTree {
66 nodes: Vec<RoutingNode>,
67 node_map: HashMap<String, usize>,
68 source_idx: usize,
69 next_steiner_id: i32,
70 next_terminal_id: i32,
71 pub worst_wirelength: i32,
72}
73
74impl GlobalRoutingTree {
75 pub fn new(source_position: Point<i32, i32>) -> Self {
76 let source = RoutingNode::new("source", NodeType::Source, source_position);
77 let mut nodes = Vec::new();
78 let mut node_map = HashMap::new();
79 node_map.insert("source".to_string(), 0usize);
80 nodes.push(source);
81 GlobalRoutingTree {
82 nodes,
83 node_map,
84 source_idx: 0,
85 next_steiner_id: 1,
86 next_terminal_id: 1,
87 worst_wirelength: 0,
88 }
89 }
90
91 pub fn get_source(&self) -> &RoutingNode {
92 &self.nodes[self.source_idx]
93 }
94
95 pub fn get_source_mut(&mut self) -> &mut RoutingNode {
96 &mut self.nodes[self.source_idx]
97 }
98
99 fn add_node(&mut self, node: RoutingNode) -> usize {
100 let idx = self.nodes.len();
101 self.node_map.insert(node.id.clone(), idx);
102 self.nodes.push(node);
103 idx
104 }
105
106 fn _find_nearest_node(&self, point: Point<i32, i32>, exclude_id: Option<&str>) -> usize {
107 if self.nodes.len() <= 1 {
108 return self.source_idx;
109 }
110 let mut nearest = self.source_idx;
111 let mut min_dist = i32::MAX;
112 for (idx, node) in self.nodes.iter().enumerate() {
113 if let Some(ex) = exclude_id {
114 if node.id == ex {
115 continue;
116 }
117 }
118 let dist = node.pt.min_dist_with(&point) as i32;
119 if dist < min_dist {
120 min_dist = dist;
121 nearest = idx;
122 }
123 }
124 nearest
125 }
126
127 pub fn insert_steiner_node(
128 &mut self,
129 point: Point<i32, i32>,
130 parent_id: Option<&str>,
131 ) -> String {
132 let id = format!("steiner_{}", self.next_steiner_id);
133 self.next_steiner_id += 1;
134 let idx = self.add_node(RoutingNode::new(&id, NodeType::Steiner, point));
135
136 let parent_idx = match parent_id {
137 Some(pid) => *self.node_map.get(pid).expect("Parent node not found"),
138 None => self.source_idx,
139 };
140 self.nodes[idx].parent = Some(parent_idx);
141 self.nodes[parent_idx].children.push(idx);
142 id
143 }
144
145 pub fn insert_terminal_node(
146 &mut self,
147 point: Point<i32, i32>,
148 parent_id: Option<&str>,
149 ) -> String {
150 let id = format!("terminal_{}", self.next_terminal_id);
151 self.next_terminal_id += 1;
152 let idx = self.add_node(RoutingNode::new(&id, NodeType::Terminal, point));
153
154 let parent_idx = match parent_id {
155 Some(pid) => *self.node_map.get(pid).expect("Parent node not found"),
156 None => self._find_nearest_node(point, None),
157 };
158 self.nodes[idx].parent = Some(parent_idx);
159 self.nodes[parent_idx].children.push(idx);
160 id
161 }
162
163 fn _find_nearest_insertion_with_constraints(
164 &self,
165 pt: Point<i32, i32>,
166 _allowed_wirelength: i32,
167 _keepouts: &Option<Vec<Interval<i32>>>,
168 ) -> (Option<usize>, usize) {
169 let nearest = self._find_nearest_node(pt, None);
171 (None, nearest)
172 }
173
174 fn _insert_terminal_impl(
175 &mut self,
176 point: Point<i32, i32>,
177 allowed_wirelength: i32,
178 keepouts: Option<Vec<Interval<i32>>>,
179 ) {
180 let terminal_id = format!("terminal_{}", self.next_terminal_id);
181 self.next_terminal_id += 1;
182 let terminal_idx = self.add_node(RoutingNode::new(&terminal_id, NodeType::Terminal, point));
183
184 let (parent_node, nearest_node) =
185 self._find_nearest_insertion_with_constraints(point, allowed_wirelength, &keepouts);
186
187 let nearest_idx = nearest_node;
188 match parent_node {
189 None => {
190 self.nodes[terminal_idx].parent = Some(nearest_idx);
191 self.nodes[nearest_idx].children.push(terminal_idx);
192 let dist = self.nodes[nearest_idx].pt.min_dist_with(&point) as i32;
193 self.nodes[terminal_idx].path_length = self.nodes[nearest_idx].path_length + dist;
194 }
195 Some(parent_idx) => {
196 let steiner_id = format!("steiner_{}", self.next_steiner_id);
197 self.next_steiner_id += 1;
198 let nearest_pt = point; let steiner_idx =
200 self.add_node(RoutingNode::new(&steiner_id, NodeType::Steiner, nearest_pt));
201
202 self.nodes[parent_idx]
204 .children
205 .retain(|&c| c != nearest_idx);
206 self.nodes[nearest_idx].parent = None;
207
208 self.nodes[steiner_idx].parent = Some(parent_idx);
209 self.nodes[parent_idx].children.push(steiner_idx);
210
211 let dist_ps = self.nodes[parent_idx].pt.min_dist_with(&nearest_pt) as i32;
212 self.nodes[steiner_idx].path_length = self.nodes[parent_idx].path_length + dist_ps;
213
214 self.nodes[nearest_idx].parent = Some(steiner_idx);
215 self.nodes[steiner_idx].children.push(nearest_idx);
216
217 self.nodes[terminal_idx].parent = Some(steiner_idx);
218 self.nodes[steiner_idx].children.push(terminal_idx);
219
220 let dist_st = nearest_pt.min_dist_with(&point) as i32;
221 self.nodes[terminal_idx].path_length =
222 self.nodes[steiner_idx].path_length + dist_st;
223 }
224 }
225 }
226
227 pub fn insert_terminal_with_steiner(
228 &mut self,
229 point: Point<i32, i32>,
230 keepouts: Option<Vec<Interval<i32>>>,
231 ) {
232 self._insert_terminal_impl(point, i32::MAX, keepouts);
233 }
234
235 pub fn insert_terminal_with_constraints(
236 &mut self,
237 point: Point<i32, i32>,
238 allowed_wirelength: i32,
239 keepouts: Option<Vec<Interval<i32>>>,
240 ) {
241 self._insert_terminal_impl(point, allowed_wirelength, keepouts);
242 }
243
244 pub fn calculate_total_wirelength(&self) -> i32 {
245 let mut total = 0;
246 for node in &self.nodes {
247 if let Some(parent_idx) = node.parent {
248 total += self.nodes[parent_idx].manhattan_distance(node);
249 }
250 }
251 total
252 }
253
254 pub fn calculate_worst_wirelength(&self) -> i32 {
255 fn traverse(tree: &GlobalRoutingTree, idx: usize) -> i32 {
256 let node = &tree.nodes[idx];
257 let mut worst = 0;
258 for &child in &node.children {
259 let child_len = node.manhattan_distance(&tree.nodes[child]);
260 let child_path = traverse(tree, child);
261 worst = worst.max(child_len + child_path);
262 }
263 worst
264 }
265 traverse(self, self.source_idx)
266 }
267
268 pub fn find_path_to_source(&self, node_id: &str) -> Vec<&RoutingNode> {
269 let mut idx = *self.node_map.get(node_id).expect("Node not found");
270 let mut path = Vec::new();
271 loop {
272 path.push(&self.nodes[idx]);
273 match self.nodes[idx].parent {
274 Some(p) => idx = p,
275 None => break,
276 }
277 }
278 path.reverse();
279 path
280 }
281
282 pub fn get_all_terminals(&self) -> Vec<&RoutingNode> {
283 self.nodes
284 .iter()
285 .filter(|n| n.node_type == NodeType::Terminal)
286 .collect()
287 }
288
289 pub fn get_all_steiner_nodes(&self) -> Vec<&RoutingNode> {
290 self.nodes
291 .iter()
292 .filter(|n| n.node_type == NodeType::Steiner)
293 .collect()
294 }
295
296 pub fn get_tree_structure(&self) -> String {
297 fn fmt_node(tree: &GlobalRoutingTree, idx: usize, level: usize) -> String {
298 let node = &tree.nodes[idx];
299 let mut s = format!(
300 "{}{}({}, {})",
301 " ".repeat(level),
302 node.node_type,
303 node.id,
304 node.pt
305 );
306 s.push('\n');
307 for &child in &node.children {
308 s.push_str(&fmt_node(tree, child, level + 1));
309 }
310 s
311 }
312 fmt_node(self, self.source_idx, 0)
313 }
314
315 pub fn visualize_tree(&self) {
316 println!("Global Routing Tree Structure:");
317 println!("================================");
318 print!("{}", self.get_tree_structure());
319 println!("Total wirelength: {}", self.calculate_total_wirelength());
320 println!("Total nodes: {}", self.nodes.len());
321 println!("Terminals: {}", self.get_all_terminals().len());
322 println!("Steiner points: {}", self.get_all_steiner_nodes().len());
323 }
324
325 pub fn optimize_steiner_points(&mut self) {
326 let to_remove: Vec<usize> = self
327 .nodes
328 .iter()
329 .enumerate()
330 .filter(|(_, n)| {
331 n.node_type == NodeType::Steiner && n.children.len() == 1 && n.parent.is_some()
332 })
333 .map(|(i, _)| i)
334 .collect();
335
336 for idx in to_remove.into_iter().rev() {
337 let parent = self.nodes[idx].parent;
338 let child = self.nodes[idx].children[0];
339 if let Some(p) = parent {
340 self.nodes[p].children.retain(|&c| c != idx);
341 self.nodes[p].children.push(child);
342 }
343 self.nodes[child].parent = parent;
344 self.node_map.remove(&self.nodes[idx].id);
345 }
346 self.nodes.retain(|n| self.node_map.contains_key(&n.id));
347 self.remap_indices();
349 }
350
351 fn remap_indices(&mut self) {
352 let old_indices: Vec<usize> = (0..self.nodes.len()).collect();
353 let mut new_map = HashMap::new();
354 let mut new_nodes = Vec::new();
355 for node in self.nodes.drain(..) {
356 let new_idx = new_nodes.len();
357 new_map.insert(node.id.clone(), new_idx);
358 new_nodes.push(node);
359 }
360 self.nodes = new_nodes;
361 for node in &mut self.nodes {
362 if let Some(p) = node.parent {
363 if let Some(&old_p) = old_indices.get(p) {
364 node.parent = Some(old_p);
365 } else {
366 node.parent = None;
367 }
368 }
369 node.children = node
370 .children
371 .iter()
372 .filter_map(|c| old_indices.get(*c).copied())
373 .collect();
374 }
375 self.node_map = new_map;
376 }
377}
378
379pub struct GlobalRouter {
381 terminal_positions: Vec<Point<i32, i32>>,
382 tree: GlobalRoutingTree,
383 worst_wirelength: i32,
384 keepouts: Option<Vec<Interval<i32>>>,
385}
386
387impl GlobalRouter {
388 pub fn new(
389 source_pos: Point<i32, i32>,
390 terminal_positions: Vec<Point<i32, i32>>,
391 keepout_regions: Option<Vec<Interval<i32>>>,
392 ) -> Self {
393 let mut sorted = terminal_positions.clone();
394 sorted.sort_by(|a, b| {
395 let da = source_pos.min_dist_with(a) as i32;
396 let db = source_pos.min_dist_with(b) as i32;
397 da.cmp(&db)
398 });
399
400 let worst = if sorted.is_empty() {
401 0
402 } else {
403 source_pos.min_dist_with(&sorted[sorted.len() - 1]) as i32
404 };
405
406 GlobalRouter {
407 terminal_positions: sorted,
408 tree: GlobalRoutingTree::new(source_pos),
409 worst_wirelength: worst,
410 keepouts: keepout_regions,
411 }
412 }
413
414 pub fn route_simple(&mut self) {
415 for &terminal in &self.terminal_positions {
416 self.tree.insert_terminal_node(terminal, None);
417 }
418 }
419
420 pub fn route_with_steiners(&mut self) {
421 self.tree.worst_wirelength = self.worst_wirelength;
422 for &terminal in &self.terminal_positions {
423 self.tree
424 .insert_terminal_with_steiner(terminal, self.keepouts.clone());
425 }
426 }
427
428 pub fn route_with_constraints(&mut self, multiplier: f64) {
429 let allowed = (self.worst_wirelength as f64 * multiplier).round() as i32;
430 self.tree.worst_wirelength = self.worst_wirelength;
431 for &terminal in &self.terminal_positions {
432 self.tree
433 .insert_terminal_with_constraints(terminal, allowed, self.keepouts.clone());
434 }
435 }
436
437 pub fn get_tree(&self) -> &GlobalRoutingTree {
438 &self.tree
439 }
440}