libreda_sta/
cone_propagation.rs1use std::{borrow::Borrow, sync::atomic::Ordering};
9
10use libreda_db::traits::{NetlistBaseMT, NetlistIds};
11use petgraph::{
12 data::DataMap,
13 stable_graph::NodeIndex,
14 visit::{EdgeRef, GraphBase, IntoEdgesDirected},
15};
16
17use crate::{
18 timing_graph::{EdgeData, GraphEdgeType, NodeData, TimingGraph},
19 traits::ConstraintBase,
20};
21
22use pargraph::{
23 executors::multi_thread::MultiThreadExecutor, local_view::LocalGraphView,
24 worklists::biglock_fifo::FifoWorklist, worklists::WorklistPush, ReadonlyOperator,
25};
26
27pub(crate) fn propagate_cones<Netlist, CellModel>(
36 g: &TimingGraph<Netlist, CellModel>,
37 frontier: impl Iterator<Item = NodeIndex>,
38 generation: u32,
39) where
40 Netlist: NetlistBaseMT,
41 CellModel: ConstraintBase,
42{
43 let operator = ConePropagationOp { generation };
44
45 let executor = MultiThreadExecutor::new();
46
47 let worklist =
48 FifoWorklist::new_with_local_queues(frontier.map(WorkItem::new_forward).collect());
49 executor.run_readonly(worklist, operator, &g.arc_graph);
50}
51
52#[derive(Clone, Copy, PartialEq, Eq, Debug)]
53pub(crate) enum PropagationDirection {
54 Forward,
55 Backward,
56}
57
58#[derive(Clone)]
59pub(crate) struct ConePropagationOp {
60 pub generation: u32,
61}
62
63#[derive(Clone, Copy, Debug)]
65pub(crate) struct WorkItem<N> {
66 node: N,
67 dir: PropagationDirection,
68}
69
70impl<N> WorkItem<N> {
71 pub fn new_forward(n: N) -> Self {
72 Self {
73 node: n,
74 dir: PropagationDirection::Forward,
75 }
76 }
77 fn new_backward(n: N) -> Self {
78 Self {
79 node: n,
80 dir: PropagationDirection::Backward,
81 }
82 }
83}
84
85impl<N> Borrow<N> for WorkItem<N> {
86 fn borrow(&self) -> &N {
87 &self.node
88 }
89}
90
91impl<G, N, D> ReadonlyOperator<G> for ConePropagationOp
92where
93 N: NetlistIds,
94 D: ConstraintBase,
95 G: GraphBase
96 + IntoEdgesDirected
97 + DataMap<NodeWeight = NodeData<N, D>, EdgeWeight = EdgeData<D>>,
98{
99 type WorkItem = WorkItem<G::NodeId>;
100
101 fn op(
102 &self,
103 work_item: Self::WorkItem,
104 local_view: LocalGraphView<&G>,
105 mut worklist: impl WorklistPush<Self::WorkItem>,
106 ) {
107 let local_view = &local_view;
108 let active_node = local_view.active_node();
109
110 let next_neighbors = |direction: PropagationDirection| {
112 let dir = match direction {
113 PropagationDirection::Forward => petgraph::Direction::Outgoing,
114 PropagationDirection::Backward => petgraph::Direction::Incoming,
115 };
116
117 local_view
118 .edges_directed(active_node, dir)
119 .map(move |e| match direction {
120 PropagationDirection::Forward => (e.target(), e.weight().edge_type),
121 PropagationDirection::Backward => (e.source(), e.weight().edge_type),
122 })
123 };
124
125 let local_data = local_view.node_weight(active_node).unwrap();
126
127 if work_item.dir == PropagationDirection::Forward {
128 let is_forward_visited = local_data
129 .generation_forward
130 .swap(self.generation, Ordering::Relaxed)
131 == self.generation;
132
133 if !is_forward_visited {
137 local_data.backward_dependencies.increment_unresolved();
139
140 for (n, edge_type) in next_neighbors(PropagationDirection::Forward) {
141 let data = local_view.node_weight(n).unwrap();
142
143 match edge_type {
145 GraphEdgeType::Delay | GraphEdgeType::Virtual => {
146 data.forward_dependencies.increment_unresolved();
147 }
148 GraphEdgeType::Constraint => {
149 data.backward_dependencies.increment_unresolved();
150 }
151 }
152
153 worklist.push(WorkItem::new_forward(n));
154 }
155 }
156 }
157
158 let is_backward_visited = local_data
159 .generation_backward
160 .swap(self.generation, Ordering::Relaxed)
161 == self.generation;
162
163 if is_backward_visited {
164 return;
166 }
167
168 for (n, edge_type) in next_neighbors(PropagationDirection::Backward) {
170 let data = local_view.node_weight(n).unwrap();
171
172 match edge_type {
174 GraphEdgeType::Delay | GraphEdgeType::Virtual => {
175 data.backward_dependencies.increment_unresolved();
176 }
177 GraphEdgeType::Constraint => {}
178 }
179
180 worklist.push(WorkItem::new_backward(n));
181 }
182 }
183}