1use std::cell::RefCell;
7use std::collections::HashMap;
8use std::rc::Rc;
9
10use crate::generic::MinDist;
11use crate::interval::Interval;
12use crate::manhattan_arc::ManhattanArc;
13use crate::point::Point;
14
15#[derive(Debug, Clone)]
17pub struct Sink {
18 pub name: String,
19 pub position: Point<i32, i32>,
20 pub capacitance: f64,
21}
22
23impl Sink {
24 pub fn new(name: &str, position: Point<i32, i32>, capacitance: f64) -> Self {
25 Sink {
26 name: name.to_string(),
27 position,
28 capacitance,
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub struct TreeNode {
36 pub name: String,
37 pub position: Point<i32, i32>,
38 pub left: Option<Rc<RefCell<TreeNode>>>,
39 pub right: Option<Rc<RefCell<TreeNode>>>,
40 pub parent: Option<Rc<RefCell<TreeNode>>>,
41 pub wire_length: i32,
42 pub delay: f64,
43 pub capacitance: f64,
44 pub need_elongation: bool,
45}
46
47impl TreeNode {
48 pub fn new(name: &str, position: Point<i32, i32>) -> Self {
49 TreeNode {
50 name: name.to_string(),
51 position,
52 left: None,
53 right: None,
54 parent: None,
55 wire_length: 0,
56 delay: 0.0,
57 capacitance: 0.0,
58 need_elongation: false,
59 }
60 }
61
62 pub fn is_leaf(&self) -> bool {
63 self.left.is_none() && self.right.is_none()
64 }
65}
66
67pub trait DelayCalculator {
69 fn calculate_wire_delay(&self, length: i32, load_capacitance: f64) -> f64;
70 fn calculate_wire_delay_per_unit(&self, load_capacitance: f64) -> f64;
71 fn calculate_wire_capacitance(&self, length: i32) -> f64;
72 fn calculate_tapping_point(
73 &self,
74 node_left: &mut TreeNode,
75 node_right: &mut TreeNode,
76 distance: i32,
77 ) -> (i32, f64);
78}
79
80pub struct LinearDelayCalculator {
82 pub delay_per_unit: f64,
83 pub capacitance_per_unit: f64,
84}
85
86impl LinearDelayCalculator {
87 pub fn new(delay_per_unit: f64, capacitance_per_unit: f64) -> Self {
88 LinearDelayCalculator {
89 delay_per_unit,
90 capacitance_per_unit,
91 }
92 }
93}
94
95impl DelayCalculator for LinearDelayCalculator {
96 fn calculate_wire_delay(&self, length: i32, _load_capacitance: f64) -> f64 {
97 self.delay_per_unit * length as f64
98 }
99
100 fn calculate_wire_delay_per_unit(&self, _load_capacitance: f64) -> f64 {
101 self.delay_per_unit
102 }
103
104 fn calculate_wire_capacitance(&self, length: i32) -> f64 {
105 self.capacitance_per_unit * length as f64
106 }
107
108 fn calculate_tapping_point(
109 &self,
110 node_left: &mut TreeNode,
111 node_right: &mut TreeNode,
112 distance: i32,
113 ) -> (i32, f64) {
114 let skew = node_right.delay - node_left.delay;
115 let extend_left = ((skew / self.delay_per_unit + distance as f64) / 2.0).round() as i32;
116 let delay_left = node_left.delay + extend_left as f64 * self.delay_per_unit;
117
118 node_left.wire_length = extend_left;
119 node_right.wire_length = distance - extend_left;
120
121 let (extend_left, delay_left) = if extend_left < 0 {
122 node_left.wire_length = 0;
123 node_right.wire_length = distance - extend_left;
124 node_right.need_elongation = true;
125 (0, node_left.delay)
126 } else if extend_left > distance {
127 node_right.wire_length = 0;
128 node_left.wire_length = extend_left;
129 node_left.need_elongation = true;
130 (distance, node_right.delay)
131 } else {
132 (extend_left, delay_left)
133 };
134
135 (extend_left, delay_left)
136 }
137}
138
139pub struct ElmoreDelayCalculator {
141 pub unit_resistance: f64,
142 pub unit_capacitance: f64,
143}
144
145impl ElmoreDelayCalculator {
146 pub fn new(unit_resistance: f64, unit_capacitance: f64) -> Self {
147 ElmoreDelayCalculator {
148 unit_resistance,
149 unit_capacitance,
150 }
151 }
152}
153
154impl DelayCalculator for ElmoreDelayCalculator {
155 fn calculate_wire_delay(&self, length: i32, load_capacitance: f64) -> f64 {
156 let wire_resistance = self.unit_resistance * length as f64;
157 let wire_capacitance = self.unit_capacitance * length as f64;
158 wire_resistance * (wire_capacitance / 2.0 + load_capacitance)
159 }
160
161 fn calculate_wire_delay_per_unit(&self, load_capacitance: f64) -> f64 {
162 self.unit_resistance * (self.unit_capacitance / 2.0 + load_capacitance)
163 }
164
165 fn calculate_wire_capacitance(&self, length: i32) -> f64 {
166 self.unit_capacitance * length as f64
167 }
168
169 fn calculate_tapping_point(
170 &self,
171 node_left: &mut TreeNode,
172 node_right: &mut TreeNode,
173 distance: i32,
174 ) -> (i32, f64) {
175 let skew = node_right.delay - node_left.delay;
176 let r = distance as f64 * self.unit_resistance;
177 let c = distance as f64 * self.unit_capacitance;
178
179 let z = (skew + r * (node_right.capacitance + c / 2.0))
180 / (r * (c + node_right.capacitance + node_left.capacitance));
181
182 let extend_left = (z * distance as f64).round() as i32;
183 let r_left = extend_left as f64 * self.unit_resistance;
184 let c_left = extend_left as f64 * self.unit_capacitance;
185 let delay_left = node_left.delay + r_left * (c_left / 2.0 + node_left.capacitance);
186
187 node_left.wire_length = extend_left;
188 node_right.wire_length = distance - extend_left;
189
190 let (extend_left, delay_left) = if extend_left < 0 {
191 node_left.wire_length = 0;
192 node_right.wire_length = distance - extend_left;
193 node_right.need_elongation = true;
194 (0, node_left.delay)
195 } else if extend_left > distance {
196 node_right.wire_length = 0;
197 node_left.wire_length = extend_left;
198 node_left.need_elongation = true;
199 (distance, node_right.delay)
200 } else {
201 (extend_left, delay_left)
202 };
203
204 (extend_left, delay_left)
205 }
206}
207
208#[derive(Debug, Clone)]
210pub struct SkewAnalysis {
211 pub max_delay: f64,
212 pub min_delay: f64,
213 pub skew: f64,
214 pub sink_delays: Vec<f64>,
215 pub total_wirelength: i32,
216 pub delay_model: String,
217}
218
219#[derive(Debug, Clone)]
221pub struct TreeStatistics {
222 pub nodes: Vec<NodeInfo>,
223 pub wires: Vec<WireInfo>,
224 pub sinks: Vec<String>,
225 pub total_nodes: i32,
226 pub total_sinks: i32,
227 pub total_wires: i32,
228}
229
230#[derive(Debug, Clone)]
231pub struct NodeInfo {
232 pub name: String,
233 pub position: (i32, i32),
234 pub node_type: String,
235 pub delay: f64,
236 pub capacitance: f64,
237}
238
239#[derive(Debug, Clone)]
240pub struct WireInfo {
241 pub from_node: String,
242 pub to_node: String,
243 pub length: i32,
244 pub from_pos: (i32, i32),
245 pub to_pos: (i32, i32),
246}
247
248pub struct DMEAlgorithm {
250 sinks: Vec<Sink>,
251 delay_calculator: Box<dyn DelayCalculator>,
252 node_id: i32,
253}
254
255impl DMEAlgorithm {
256 pub fn new(sinks: Vec<Sink>, calculator: Box<dyn DelayCalculator>) -> Self {
257 assert!(!sinks.is_empty(), "No sinks provided");
258 DMEAlgorithm {
259 sinks,
260 delay_calculator: calculator,
261 node_id: 0,
262 }
263 }
264
265 pub fn build_clock_tree(&mut self) -> Rc<RefCell<TreeNode>> {
267 let nodes: Vec<Rc<RefCell<TreeNode>>> = self
268 .sinks
269 .iter()
270 .map(|s| {
271 let mut node = TreeNode::new(&s.name, s.position);
272 node.capacitance = s.capacitance;
273 Rc::new(RefCell::new(node))
274 })
275 .collect();
276
277 let merging_tree = self.build_merging_tree(&nodes, false);
278 let mut merging_segments = HashMap::new();
279 self.compute_merging_segment(Rc::clone(&merging_tree), &mut merging_segments);
280 self.embed_node(Rc::clone(&merging_tree), None, &merging_segments);
281 self.compute_delays(Rc::clone(&merging_tree), 0.0);
282 merging_tree
283 }
284
285 fn build_merging_tree(
286 &mut self,
287 nodes: &[Rc<RefCell<TreeNode>>],
288 vertical: bool,
289 ) -> Rc<RefCell<TreeNode>> {
290 if nodes.len() == 1 {
291 return Rc::clone(&nodes[0]);
292 }
293
294 let mut sorted = nodes.to_vec();
295 if vertical {
296 sorted.sort_by(|a, b| a.borrow().position.xcoord.cmp(&b.borrow().position.xcoord));
297 } else {
298 sorted.sort_by(|a, b| a.borrow().position.ycoord.cmp(&b.borrow().position.ycoord));
299 }
300
301 let mid = sorted.len() / 2;
302 let left_group: Vec<_> = sorted[..mid].to_vec();
303 let right_group: Vec<_> = sorted[mid..].to_vec();
304
305 let left_child = self.build_merging_tree(&left_group, !vertical);
306 let right_child = self.build_merging_tree(&right_group, !vertical);
307
308 let id = format!("n{}", self.node_id);
309 self.node_id += 1;
310 let pos = left_child.borrow().position;
311 let parent = Rc::new(RefCell::new(TreeNode::new(&id, pos)));
312 {
313 let mut p = parent.borrow_mut();
314 p.left = Some(Rc::clone(&left_child));
315 p.right = Some(Rc::clone(&right_child));
316 }
317 left_child.borrow_mut().parent = Some(Rc::clone(&parent));
318 right_child.borrow_mut().parent = Some(Rc::clone(&parent));
319
320 parent
321 }
322
323 fn compute_merging_segment(
324 &self,
325 node: Rc<RefCell<TreeNode>>,
326 segments: &mut HashMap<*const TreeNode, ManhattanArc<Interval<i32>>>,
327 ) -> ManhattanArc<Interval<i32>> {
328 let is_leaf = node.borrow().is_leaf();
329 let node_ptr: *const TreeNode = &*node.borrow();
330
331 if is_leaf {
332 let pos = node.borrow().position;
333 let ms1 = ManhattanArc::from_point(pos);
334 let ms = ManhattanArc::new(
335 Interval::new(ms1.xcoord(), ms1.xcoord()),
336 Interval::new(ms1.ycoord(), ms1.ycoord()),
337 );
338 segments.insert(node_ptr, ms);
339 return ms;
340 }
341
342 let left = node.borrow().left.as_ref().map(Rc::clone);
343 let right = node.borrow().right.as_ref().map(Rc::clone);
344 let left = left.expect("Internal node missing left child");
345 let right = right.expect("Internal node missing right child");
346
347 let left_ms = self.compute_merging_segment(Rc::clone(&left), segments);
348 let right_ms = self.compute_merging_segment(Rc::clone(&right), segments);
349
350 let distance = left_ms.min_dist_with(&right_ms) as i32;
351
352 let (extend_left, delay_left) = self.delay_calculator.calculate_tapping_point(
353 &mut left.borrow_mut(),
354 &mut right.borrow_mut(),
355 distance,
356 );
357 node.borrow_mut().delay = delay_left;
358
359 let merged_segment = left_ms.merge_with(&right_ms, extend_left);
360 segments.insert(node_ptr, merged_segment);
361
362 let wire_cap = self.delay_calculator.calculate_wire_capacitance(distance);
363 node.borrow_mut().capacitance =
364 left.borrow().capacitance + right.borrow().capacitance + wire_cap;
365
366 merged_segment
367 }
368
369 fn embed_node(
370 &self,
371 node: Rc<RefCell<TreeNode>>,
372 parent_segment: Option<&ManhattanArc<Interval<i32>>>,
373 segments: &HashMap<*const TreeNode, ManhattanArc<Interval<i32>>>,
374 ) {
375 let node_ptr: *const TreeNode = &*node.borrow();
376 let node_segment = segments
377 .get(&node_ptr)
378 .expect("Merging segment not found for node");
379
380 if parent_segment.is_none() {
381 let upper = Point::new(node_segment.impl_p.xcoord.ub, node_segment.impl_p.ycoord.ub);
383 node.borrow_mut().position = upper;
384 } else {
385 let parent_pos = node.borrow().parent.as_ref().map(|p| p.borrow().position);
386 if let Some(pp) = parent_pos {
387 let nearest = node_segment.nearest_point_to(&pp);
388 node.borrow_mut().position = nearest;
389 let dist = node.borrow().position.min_dist_with(&pp);
390 node.borrow_mut().wire_length = dist as i32;
391 }
392 }
393
394 let left = node.borrow().left.as_ref().map(Rc::clone);
395 let right = node.borrow().right.as_ref().map(Rc::clone);
396
397 if let Some(l) = left {
398 self.embed_node(l, Some(node_segment), segments);
399 }
400 if let Some(r) = right {
401 self.embed_node(r, Some(node_segment), segments);
402 }
403 }
404
405 fn compute_delays(&self, node: Rc<RefCell<TreeNode>>, parent_delay: f64) {
406 let has_parent = node.borrow().parent.is_some();
407 if has_parent {
408 let wire_delay = self
409 .delay_calculator
410 .calculate_wire_delay(node.borrow().wire_length, node.borrow().capacitance);
411 node.borrow_mut().delay = parent_delay + wire_delay;
412 } else {
413 node.borrow_mut().delay = 0.0;
414 }
415
416 let current_delay = node.borrow().delay;
417 let left = node.borrow().left.as_ref().map(Rc::clone);
418 let right = node.borrow().right.as_ref().map(Rc::clone);
419
420 if let Some(l) = left {
421 self.compute_delays(l, current_delay);
422 }
423 if let Some(r) = right {
424 self.compute_delays(r, current_delay);
425 }
426 }
427
428 pub fn analyze_skew(&self, root: Rc<RefCell<TreeNode>>) -> SkewAnalysis {
430 let mut sink_delays = Vec::new();
431 collect_sink_delays(&root, &mut sink_delays);
432
433 if sink_delays.is_empty() {
434 panic!("No sink delays collected");
435 }
436
437 let max_delay = sink_delays
438 .iter()
439 .cloned()
440 .fold(f64::NEG_INFINITY, f64::max);
441 let min_delay = sink_delays.iter().cloned().fold(f64::INFINITY, f64::min);
442 let skew = max_delay - min_delay;
443 let total_wl = total_wirelength(&root);
444 #[allow(clippy::incompatible_msrv)]
445 let delay_model = std::any::type_name_of_val(&*self.delay_calculator).to_string();
446
447 SkewAnalysis {
448 max_delay,
449 min_delay,
450 skew,
451 sink_delays,
452 total_wirelength: total_wl,
453 delay_model,
454 }
455 }
456}
457
458fn collect_sink_delays(node: &Rc<RefCell<TreeNode>>, sink_delays: &mut Vec<f64>) {
459 if node.borrow().is_leaf() {
460 sink_delays.push(node.borrow().delay);
461 }
462 let left = node.borrow().left.as_ref().map(Rc::clone);
463 let right = node.borrow().right.as_ref().map(Rc::clone);
464 if let Some(l) = left {
465 collect_sink_delays(&l, sink_delays);
466 }
467 if let Some(r) = right {
468 collect_sink_delays(&r, sink_delays);
469 }
470}
471
472fn total_wirelength(node: &Rc<RefCell<TreeNode>>) -> i32 {
473 let mut total = node.borrow().wire_length;
474 let left = node.borrow().left.as_ref().map(Rc::clone);
475 let right = node.borrow().right.as_ref().map(Rc::clone);
476 if let Some(l) = left {
477 total += total_wirelength(&l);
478 }
479 if let Some(r) = right {
480 total += total_wirelength(&r);
481 }
482 total
483}
484
485pub fn get_tree_statistics(root: Rc<RefCell<TreeNode>>) -> TreeStatistics {
487 let mut stats = TreeStatistics {
488 nodes: Vec::new(),
489 wires: Vec::new(),
490 sinks: Vec::new(),
491 total_nodes: 0,
492 total_sinks: 0,
493 total_wires: 0,
494 };
495 traverse_tree(&root, None, &mut stats);
496 stats.total_nodes = stats.nodes.len() as i32;
497 stats.total_sinks = stats.sinks.len() as i32;
498 stats.total_wires = stats.wires.len() as i32;
499 stats
500}
501
502fn traverse_tree(
503 node: &Rc<RefCell<TreeNode>>,
504 parent: Option<&Rc<RefCell<TreeNode>>>,
505 stats: &mut TreeStatistics,
506) {
507 let n = node.borrow();
508 stats.nodes.push(NodeInfo {
509 name: n.name.clone(),
510 position: (n.position.xcoord, n.position.ycoord),
511 node_type: if n.is_leaf() {
512 "sink".to_string()
513 } else {
514 "internal".to_string()
515 },
516 delay: n.delay,
517 capacitance: n.capacitance,
518 });
519
520 if n.is_leaf() {
521 stats.sinks.push(n.name.clone());
522 }
523
524 if let Some(p) = parent {
525 let pb = p.borrow();
526 stats.wires.push(WireInfo {
527 from_node: pb.name.clone(),
528 to_node: n.name.clone(),
529 length: n.wire_length,
530 from_pos: (pb.position.xcoord, pb.position.ycoord),
531 to_pos: (n.position.xcoord, n.position.ycoord),
532 });
533 }
534
535 let left = n.left.as_ref().map(Rc::clone);
536 let right = n.right.as_ref().map(Rc::clone);
537 drop(n);
538
539 if let Some(l) = left {
540 traverse_tree(&l, Some(node), stats);
541 }
542 if let Some(r) = right {
543 traverse_tree(&r, Some(node), stats);
544 }
545}