Recti 1.2.4
Loading...
Searching...
No Matches
dme_algorithm.hpp
Go to the documentation of this file.
1
5#pragma once
6
7#include <cstddef>
8#include <memory>
9#include <optional>
10#include <stdexcept>
11#include <string>
12#include <unordered_map>
13#include <utility>
14#include <vector>
15
16#include "manhattan_arc.hpp"
17#include "point.hpp"
18
19namespace recti {
20
21 // Forward declarations
22 class Tree;
23
31 using NodeIdx = std::size_t;
32
40 class Sink {
41 public:
42 std::string name;
45
52 constexpr Sink(const std::string& name, const Point<int>& position,
53 double capacitance = 1.0)
55 };
56
65 class TreeNode {
66 public:
67 std::string name;
69 NodeIdx left = SIZE_MAX;
70 NodeIdx right = SIZE_MAX;
71 NodeIdx parent = SIZE_MAX;
72 int wire_length = 0;
73 double delay = 0.0;
74 double capacitance = 0.0;
76 = false;
77
83 TreeNode(const std::string& name, const Point<int>& position)
85
90 bool is_leaf() const { return left == SIZE_MAX && right == SIZE_MAX; }
91 };
92
102 class Tree {
103 private:
104 std::vector<TreeNode> nodes;
105
106 public:
108 NodeIdx root = SIZE_MAX;
109
110 Tree() = default;
111
118 NodeIdx idx = nodes.size();
119 nodes.push_back(std::move(node));
120 return idx;
121 }
122
126 const TreeNode& get(NodeIdx idx) const { return nodes.at(idx); }
127
131 TreeNode& get_mut(NodeIdx idx) { return nodes.at(idx); }
132
139 std::pair<TreeNode&, TreeNode&> get_pair_mut(NodeIdx a, NodeIdx b) {
140 return {nodes.at(a), nodes.at(b)};
141 }
142
144 std::size_t size() const { return nodes.size(); }
145
147 bool empty() const { return nodes.empty(); }
148 };
149
167
180 public:
181 DelayCalculator() = default;
186 virtual ~DelayCalculator() = default;
187
194 virtual double calculate_wire_delay(int length, double load_capacitance) const = 0;
195
201 virtual double calculate_wire_delay_per_unit(double load_capacitance) const = 0;
202
208 virtual double calculate_wire_capacitance(int length) const = 0;
209
229 virtual TappingResult calculate_tapping_point(int distance, double left_delay,
230 double right_delay, double left_capacitance,
231 double right_capacitance) const
232 = 0;
233 };
234
244 private:
245 double delay_per_unit;
246 double capacitance_per_unit;
247
248 public:
249 LinearDelayCalculator(double delay_per_unit = 1.0, double capacitance_per_unit = 1.0)
250 : delay_per_unit(delay_per_unit), capacitance_per_unit(capacitance_per_unit) {}
251
252 double calculate_wire_delay(int length, double /* load_capacitance */) const override {
253 return delay_per_unit * static_cast<double>(length);
254 }
255
256 double calculate_wire_delay_per_unit(double /* load_capacitance */) const override {
257 return delay_per_unit;
258 }
259
260 double calculate_wire_capacitance(int length) const override {
261 return capacitance_per_unit * static_cast<double>(length);
262 }
263
275 TappingResult calculate_tapping_point(int distance, double left_delay, double right_delay,
276 double /* left_capacitance */,
277 double /* right_capacitance */) const override;
278 };
279
290 private:
291 double unit_resistance;
292 double unit_capacitance;
293
294 public:
295 ElmoreDelayCalculator(double unit_resistance = 1.0, double unit_capacitance = 1.0)
296 : unit_resistance(unit_resistance), unit_capacitance(unit_capacitance) {}
297
298 double calculate_wire_delay(int length, double load_capacitance) const override {
299 double wire_resistance = unit_resistance * length;
300 double wire_capacitance = unit_capacitance * length;
301 return wire_resistance * (wire_capacitance / 2 + load_capacitance);
302 }
303
304 double calculate_wire_delay_per_unit(double load_capacitance) const override {
305 return unit_resistance * (unit_capacitance / 2 + load_capacitance);
306 }
307
308 double calculate_wire_capacitance(int length) const override {
309 return unit_capacitance * length;
310 }
311
325 TappingResult calculate_tapping_point(int distance, double left_delay, double right_delay,
326 double left_capacitance,
327 double right_capacitance) const override;
328 };
329
335 double max_delay;
336 double min_delay;
337 double skew;
338 std::vector<double> sink_delays;
340 std::string
342 };
343
349 struct NodeInfo {
350 std::string name;
351 std::pair<int, int> position;
352 std::string type;
353 double delay;
354 double capacitance;
355 };
356
357 struct WireInfo {
358 std::string from_node;
359 std::string to_node;
360 int length;
361 std::pair<int, int> from_pos;
362 std::pair<int, int> to_pos;
363 };
364
365 std::vector<NodeInfo> nodes;
366 std::vector<WireInfo> wires;
367 std::vector<std::string> sinks;
368 int total_nodes = 0;
369 int total_sinks = 0;
370 int total_wires = 0;
371 };
372
389 private:
390 std::vector<Sink> sinks;
391 std::unique_ptr<DelayCalculator> delay_calculator;
392 int node_id = 0;
393 Tree tree;
394 std::optional<Point<int>> source;
395
396 public:
403 DMEAlgorithm(const std::vector<Sink>& sinks, std::unique_ptr<DelayCalculator> calculator)
404 : sinks(sinks), delay_calculator(std::move(calculator)) {
405 if (this->sinks.empty()) {
406 throw std::invalid_argument("No sinks provided");
407 }
408 }
409
417 DMEAlgorithm(const std::vector<Sink>& sinks, std::unique_ptr<DelayCalculator> calculator,
418 Point<int> source_position)
419 : sinks(sinks), delay_calculator(std::move(calculator)), source(source_position) {
420 if (this->sinks.empty()) {
421 throw std::invalid_argument("No sinks provided");
422 }
423 }
424
434
436 const Tree& get_tree() const { return tree; }
437
439 Tree& get_tree_mut() { return tree; }
440
452
453 private:
465 NodeIdx build_merging_tree(const std::vector<NodeIdx>& node_ids, bool vertical);
466
476 ManhattanArc<Interval<int>, Interval<int>> _compute_merging_segment(
477 NodeIdx node, std::unordered_map<NodeIdx, ManhattanArc<Interval<int>, Interval<int>>>&
478 merging_segments);
479
483 std::unordered_map<NodeIdx, ManhattanArc<Interval<int>, Interval<int>>>
484 compute_merging_segments(NodeIdx root);
485
493 void _embed_node(
494 NodeIdx node, const ManhattanArc<Interval<int>, Interval<int>>* parent_segment,
495 const std::unordered_map<NodeIdx, ManhattanArc<Interval<int>, Interval<int>>>&
496 merging_segments);
497
503 NodeIdx embed_tree(
504 NodeIdx merging_tree_root,
505 const std::unordered_map<NodeIdx, ManhattanArc<Interval<int>, Interval<int>>>&
506 merging_segments);
507
511 void _compute_delays(NodeIdx node, double parent_delay);
512
516 void compute_tree_parameters(NodeIdx root);
517
522 int total_wirelength(NodeIdx root) const;
523 };
524
534
543 extern void example_dme_usage();
544
545} // namespace recti
Implements the Deferred Merge Embedding (DME) algorithm for clock tree synthesis.
Definition dme_algorithm.hpp:388
DMEAlgorithm(const std::vector< Sink > &sinks, std::unique_ptr< DelayCalculator > calculator, Point< int > source_position)
Constructs a DMEAlgorithm with a specified clock source position.
Definition dme_algorithm.hpp:417
DMEAlgorithm(const std::vector< Sink > &sinks, std::unique_ptr< DelayCalculator > calculator)
Constructs a DMEAlgorithm object.
Definition dme_algorithm.hpp:403
SkewAnalysis analyze_skew(NodeIdx root) const
Analyzes clock skew of the constructed tree.
Tree & get_tree_mut()
Returns a mutable reference to the internal tree arena.
Definition dme_algorithm.hpp:439
const Tree & get_tree() const
Returns a const reference to the internal tree arena.
Definition dme_algorithm.hpp:436
NodeIdx build_clock_tree()
Builds the clock tree for the given sinks.
Abstract base class for delay calculation models.
Definition dme_algorithm.hpp:179
virtual ~DelayCalculator()=default
DelayCalculator & operator=(DelayCalculator &&)=default
DelayCalculator(DelayCalculator &&)=default
virtual double calculate_wire_capacitance(int length) const =0
Calculates the capacitance of a wire segment.
virtual TappingResult calculate_tapping_point(int distance, double left_delay, double right_delay, double left_capacitance, double right_capacitance) const =0
Determines the optimal tapping point for merging two subtrees to achieve prescribed skew.
DelayCalculator(const DelayCalculator &)=default
virtual double calculate_wire_delay_per_unit(double load_capacitance) const =0
Calculates the delay per unit length of a wire.
virtual double calculate_wire_delay(int length, double load_capacitance) const =0
Calculates the delay of a wire segment.
DelayCalculator & operator=(const DelayCalculator &)=default
Implements the Elmore delay model for RC trees.
Definition dme_algorithm.hpp:289
ElmoreDelayCalculator(double unit_resistance=1.0, double unit_capacitance=1.0)
Definition dme_algorithm.hpp:295
TappingResult calculate_tapping_point(int distance, double left_delay, double right_delay, double left_capacitance, double right_capacitance) const override
Elmore-model tapping point.
double calculate_wire_delay_per_unit(double load_capacitance) const override
Calculates the delay per unit length of a wire.
Definition dme_algorithm.hpp:304
double calculate_wire_delay(int length, double load_capacitance) const override
Calculates the delay of a wire segment.
Definition dme_algorithm.hpp:298
double calculate_wire_capacitance(int length) const override
Calculates the capacitance of a wire segment.
Definition dme_algorithm.hpp:308
Interval.
Definition interval.hpp:23
Implements a simple linear delay model.
Definition dme_algorithm.hpp:243
TappingResult calculate_tapping_point(int distance, double left_delay, double right_delay, double, double) const override
Linear-model tapping point.
double calculate_wire_delay(int length, double) const override
Calculates the delay of a wire segment.
Definition dme_algorithm.hpp:252
LinearDelayCalculator(double delay_per_unit=1.0, double capacitance_per_unit=1.0)
Definition dme_algorithm.hpp:249
double calculate_wire_capacitance(int length) const override
Calculates the capacitance of a wire segment.
Definition dme_algorithm.hpp:260
double calculate_wire_delay_per_unit(double) const override
Calculates the delay per unit length of a wire.
Definition dme_algorithm.hpp:256
Merging Object (for deferred-merge embedding (DME) algorithm)
Definition manhattan_arc.hpp:41
Point.
Definition point.hpp:30
Represents a clock sink in the clock tree network.
Definition dme_algorithm.hpp:40
std::string name
Definition dme_algorithm.hpp:42
constexpr Sink(const std::string &name, const Point< int > &position, double capacitance=1.0)
Constructs a new Sink object.
Definition dme_algorithm.hpp:52
Point< int > position
Definition dme_algorithm.hpp:43
double capacitance
Definition dme_algorithm.hpp:44
A node in the clock tree, stored in a Tree arena.
Definition dme_algorithm.hpp:65
NodeIdx parent
Index of the parent (or SIZE_MAX)
Definition dme_algorithm.hpp:71
std::string name
Definition dme_algorithm.hpp:67
NodeIdx left
Index of the left child (or SIZE_MAX)
Definition dme_algorithm.hpp:69
double capacitance
Total downstream capacitance seen from this node.
Definition dme_algorithm.hpp:74
Point< int > position
Definition dme_algorithm.hpp:68
TreeNode(const std::string &name, const Point< int > &position)
Constructs a new TreeNode.
Definition dme_algorithm.hpp:83
NodeIdx right
Index of the right child (or SIZE_MAX)
Definition dme_algorithm.hpp:70
bool need_elongation
Flag indicating if a branch needed elongation for skew balancing.
Definition dme_algorithm.hpp:76
bool is_leaf() const
Checks if the node is a leaf (a sink).
Definition dme_algorithm.hpp:90
double delay
Accumulated delay from the clock source to this node.
Definition dme_algorithm.hpp:73
int wire_length
Length of the wire connecting this node to its parent.
Definition dme_algorithm.hpp:72
Arena-allocated tree of TreeNodes.
Definition dme_algorithm.hpp:102
std::size_t size() const
Number of nodes in the arena.
Definition dme_algorithm.hpp:144
bool empty() const
True when the arena holds no nodes.
Definition dme_algorithm.hpp:147
std::pair< TreeNode &, TreeNode & > get_pair_mut(NodeIdx a, NodeIdx b)
Simultaneously returns mutable references to two distinct nodes.
Definition dme_algorithm.hpp:139
Tree()=default
NodeIdx add(TreeNode node)
Adds a node to the arena and returns its index.
Definition dme_algorithm.hpp:117
const TreeNode & get(NodeIdx idx) const
Returns a const reference to the node at the given index.
Definition dme_algorithm.hpp:126
NodeIdx root
Definition dme_algorithm.hpp:108
TreeNode & get_mut(NodeIdx idx)
Returns a mutable reference to the node at the given index.
Definition dme_algorithm.hpp:131
ManhattanArc template class for the DME algorithm merging segments.
Definition svg_utils.hpp:12
std::size_t NodeIdx
Node index type used throughout the DME algorithm.
Definition dme_algorithm.hpp:31
void example_dme_usage()
Example usage function demonstrating the DME algorithm with different delay models.
TreeStatistics get_tree_statistics(const Tree &tree, NodeIdx root)
Extracts detailed statistics from a constructed clock tree.
2D Point template class supporting intervals, arithmetic, and geometric queries.
Stores the results of the clock skew analysis for a clock tree.
Definition dme_algorithm.hpp:334
double min_delay
The minimum delay from the clock source to any sink.
Definition dme_algorithm.hpp:336
double skew
The difference between max_delay and min_delay.
Definition dme_algorithm.hpp:337
double max_delay
The maximum delay from the clock source to any sink.
Definition dme_algorithm.hpp:335
int total_wirelength
The sum of all wire lengths in the clock tree.
Definition dme_algorithm.hpp:339
std::string delay_model
The name of the delay model used (e.g. "LinearDelayCalculator").
Definition dme_algorithm.hpp:341
std::vector< double > sink_delays
A list of delays to each individual sink.
Definition dme_algorithm.hpp:338
Result of a tapping-point calculation.
Definition dme_algorithm.hpp:159
int raw_extend_left
Definition dme_algorithm.hpp:163
double delay_left
Definition dme_algorithm.hpp:165
int extend_left
Definition dme_algorithm.hpp:161
Definition dme_algorithm.hpp:349
std::pair< int, int > position
(x, y) coordinates.
Definition dme_algorithm.hpp:351
std::string name
Name of the node.
Definition dme_algorithm.hpp:350
std::string type
Type: "sink" or "internal".
Definition dme_algorithm.hpp:352
double capacitance
Downstream capacitance.
Definition dme_algorithm.hpp:354
double delay
Accumulated delay.
Definition dme_algorithm.hpp:353
Definition dme_algorithm.hpp:357
std::pair< int, int > to_pos
Destination (x, y).
Definition dme_algorithm.hpp:362
std::pair< int, int > from_pos
Source (x, y).
Definition dme_algorithm.hpp:361
std::string from_node
Source node name.
Definition dme_algorithm.hpp:358
std::string to_node
Destination node name.
Definition dme_algorithm.hpp:359
int length
Wire length.
Definition dme_algorithm.hpp:360
Provides detailed statistics about the generated clock tree.
Definition dme_algorithm.hpp:348
int total_wires
Definition dme_algorithm.hpp:370
int total_nodes
Definition dme_algorithm.hpp:368
std::vector< std::string > sinks
Definition dme_algorithm.hpp:367
std::vector< NodeInfo > nodes
Definition dme_algorithm.hpp:365
int total_sinks
Definition dme_algorithm.hpp:369
std::vector< WireInfo > wires
Definition dme_algorithm.hpp:366