1use crate::analysis::ProgramDependenceGraph;
10use crate::data_structures::{BitSet, WorkQueue};
11use crate::ir::hir::DisciplineAccess;
12use crate::ir::{
13 BranchId, IntegerExpressionId, NoiseSource, ParameterId, PortId, RealExpressionId, StatementId,
14 StringExpressionId, SystemFunctionCall, VariableId,
15};
16use crate::mir::{ExpressionId, Mir, StringExpression};
17use crate::mir::{IntegerExpression, RealExpression};
18use crate::ControlFlowGraph;
19use log::*;
20use std::collections::VecDeque;
21use std::iter::FromIterator;
22
23impl ControlFlowGraph {
24 pub fn backward_variable_slice(&mut self, var: VariableId, pdg: &ProgramDependenceGraph) {
25 let relevant_stmts = pdg.data_dependencies.assignments[var].clone();
26 self.backward_slice(relevant_stmts, BitSet::new_empty(StatementId::new(0)), pdg);
27 }
28
29 pub fn backward_variable_slice_assuming_input(
30 &mut self,
31 input: BitSet<StatementId>,
32 var: VariableId,
33 pdg: &ProgramDependenceGraph,
34 ) {
35 let relevant_stmts = pdg.data_dependencies.assignments[var].clone();
36 self.backward_slice(relevant_stmts, input, pdg);
37 }
38
39 pub fn backward_variable_slice_with_variables_as_input(
40 &mut self,
41 input: impl Iterator<Item = VariableId>,
42 var: VariableId,
43 pdg: &ProgramDependenceGraph,
44 ) {
45 let mut input_statements =
46 BitSet::new_empty(pdg.data_dependencies.stmt_use_def_chains.len_idx());
47 for var in input {
48 input_statements.union_with(&pdg.data_dependencies.assignments[var])
49 }
50 self.backward_variable_slice_assuming_input(input_statements, var, pdg)
51 }
52
53 pub fn backward_slice(
54 &mut self,
55 mut relevant_stmts: BitSet<StatementId>,
56 assumed_stmts: BitSet<StatementId>,
57 pdg: &ProgramDependenceGraph,
58 ) {
59 debug!(
60 "Computing backwardslice wit intput {} and output {}",
61 assumed_stmts,
62 relevant_stmts
63 );
64 let mut set = assumed_stmts;
66 set.grow(relevant_stmts.len_idx());
68 set.union(&relevant_stmts);
69 let mut stmt_work_queue = WorkQueue {
70 deque: VecDeque::from_iter(relevant_stmts.ones()),
72 set,
73 };
74
75 trace!(
76 "Backwardslice: Inital stmt work-list: {:?}",
77 stmt_work_queue
78 );
79
80 let mut bb_work_queue = WorkQueue::with_none(self.blocks.len_idx());
81
82
83 loop {
84 let mut done = true;
85
86 if let Some(stmt) = stmt_work_queue.take() {
87 relevant_stmts.insert(stmt);
88 for data_dependency in pdg.data_dependencies.stmt_use_def_chains[stmt].ones() {
89 stmt_work_queue.insert(data_dependency);
90 }
91
92 for control_dependency in pdg.control_dependencies[self
93 .containing_block(stmt)
94 .expect("Mallformed cfg statement owners")]
95 .ones()
96 {
97 bb_work_queue.insert(control_dependency);
98 }
99
100 trace!(
101 "Backwardslice: Inital stmt work-list after iteration {:?}",
102 stmt_work_queue
103 );
104 done = false;
105 }
106
107 if let Some(bb) = bb_work_queue.take() {
108 for data_dependency in pdg.data_dependencies.terminator_use_def_chains[bb].ones() {
109 stmt_work_queue.insert(data_dependency);
110 }
111
112 for control_dependency in pdg.control_dependencies[bb].ones() {
113 bb_work_queue.insert(control_dependency);
114 }
115
116 done = false;
117 }
118
119 if done {
120 break;
121 }
122 }
123
124 for bb in self.blocks.iter_mut() {
125 bb.statements.retain(|&stmt| relevant_stmts.contains(stmt))
126 }
127 }
128}
129
130impl Mir {
131 pub fn track_expression(
132 &self,
133 expr: ExpressionId,
134 dependency_handler: &mut impl DependencyHandler,
135 ) {
136 match expr {
137 ExpressionId::Real(expr) => self.track_real_expression(expr, dependency_handler),
138 ExpressionId::Integer(expr) => self.track_integer_expression(expr, dependency_handler),
139 ExpressionId::String(expr) => self.track_string_expression(expr, dependency_handler),
140 }
141 }
142
143 pub fn track_real_expression(
144 &self,
145 expr: RealExpressionId,
146 dependency_handler: &mut impl DependencyHandler,
147 ) {
148 match self[expr].contents {
149 RealExpression::Literal(_) => (),
150 RealExpression::VariableReference(var) => {
151 dependency_handler.handle_variable_reference(var);
152 }
153 RealExpression::ParameterReference(param) => {
154 dependency_handler.handle_parameter_reference(param)
155 }
156 RealExpression::Vt(temp) => {
157 dependency_handler.handle_system_function_call(SystemFunctionCall::Vt(temp))
158 }
159 RealExpression::SimParam(name, default) => dependency_handler
160 .handle_system_function_call(SystemFunctionCall::Simparam(name, default)),
161 RealExpression::Temperature => {
162 dependency_handler.handle_system_function_call(SystemFunctionCall::Temperature)
163 }
164
165 RealExpression::Noise(source, _) => match source {
166 NoiseSource::White(expr) => self.track_real_expression(expr, dependency_handler),
167 NoiseSource::Flicker(expr1, expr2) => {
168 self.track_real_expression(expr1, dependency_handler);
169 self.track_real_expression(expr2, dependency_handler);
170 }
171 NoiseSource::Table(_) | NoiseSource::TableLog(_) => todo!(),
172 },
173
174 RealExpression::BuiltInFunctionCall2p(_, arg1, arg2)
175 | RealExpression::BinaryOperator(arg1, _, arg2) => {
176 self.track_real_expression(arg1, dependency_handler);
177 self.track_real_expression(arg2, dependency_handler);
178 }
179
180 RealExpression::Condition(cond, _, val1, _, val2) => {
181 self.track_integer_expression(cond, dependency_handler);
182 self.track_real_expression(val1, dependency_handler);
183 self.track_real_expression(val2, dependency_handler);
184 }
185
186 RealExpression::BranchAccess(discipline, branch, order) => {
187 dependency_handler.handle_branch_reference(discipline, branch, order)
188 }
189
190 RealExpression::Negate(_, expr) | RealExpression::BuiltInFunctionCall1p(_, expr) => {
191 self.track_real_expression(expr, dependency_handler)
192 }
193 RealExpression::IntegerConversion(expr) => {
194 self.track_integer_expression(expr, dependency_handler)
195 }
196 }
197 }
198
199 pub fn track_integer_expression(
200 &self,
201 expr: IntegerExpressionId,
202 dependency_handler: &mut impl DependencyHandler,
203 ) {
204 match self[expr].contents {
205 IntegerExpression::Literal(_) => (),
206
207 IntegerExpression::VariableReference(var) => {
208 dependency_handler.handle_variable_reference(var);
209 }
210 IntegerExpression::ParameterReference(param) => {
211 dependency_handler.handle_parameter_reference(param)
212 }
213
214 IntegerExpression::NetReference(_) | IntegerExpression::PortReference(_) => {
215 todo!("digital")
216 }
217
218 IntegerExpression::FunctionCall(_, _) => todo!("Function calls"),
219
220 IntegerExpression::StringEq(arg1, arg2) | IntegerExpression::StringNEq(arg1, arg2) => {
221 self.track_string_expression(arg1, dependency_handler);
222 self.track_string_expression(arg2, dependency_handler);
223 }
224
225 IntegerExpression::RealComparison(arg1, _, arg2) => {
226 self.track_real_expression(arg1, dependency_handler);
227 self.track_real_expression(arg2, dependency_handler);
228 }
229
230 IntegerExpression::RealCast(expr) => {
231 self.track_real_expression(expr, dependency_handler);
232 }
233
234 IntegerExpression::UnaryOperator(_, expr) | IntegerExpression::Abs(expr) => {
235 self.track_integer_expression(expr, dependency_handler)
236 }
237
238 IntegerExpression::Max(arg1, arg2)
239 | IntegerExpression::Min(arg1, arg2)
240 | IntegerExpression::BinaryOperator(arg1, _, arg2)
241 | IntegerExpression::IntegerComparison(arg1, _, arg2) => {
242 self.track_integer_expression(arg1, dependency_handler);
243 self.track_integer_expression(arg2, dependency_handler);
244 }
245
246 IntegerExpression::Condition(cond, _, val1, _, val2) => {
247 self.track_integer_expression(cond, dependency_handler);
248 self.track_integer_expression(val1, dependency_handler);
249 self.track_integer_expression(val2, dependency_handler);
250 }
251 IntegerExpression::ParamGiven(param) => dependency_handler
252 .handle_system_function_call(SystemFunctionCall::ParameterGiven(param)),
253 IntegerExpression::PortConnected(port) => dependency_handler
254 .handle_system_function_call(SystemFunctionCall::PortConnected(port)),
255 }
256 }
257
258 pub fn track_string_expression(
259 &self,
260 expr: StringExpressionId,
261 dependency_handler: &mut impl DependencyHandler,
262 ) {
263 match self[expr].contents {
264 StringExpression::Literal(_) => (),
265 StringExpression::VariableReference(var) => {
266 dependency_handler.handle_variable_reference(var);
267 }
268 StringExpression::Condition(cond, _, val1, _, val2) => {
269 self.track_integer_expression(cond, dependency_handler);
270 self.track_string_expression(val1, dependency_handler);
271 self.track_string_expression(val2, dependency_handler);
272 }
273 StringExpression::ParameterReference(param) => {
274 dependency_handler.handle_parameter_reference(param)
275 }
276 StringExpression::SimParam(name) => dependency_handler
277 .handle_system_function_call(SystemFunctionCall::SimparamStr(name)),
278 }
279 }
280}
281
282pub trait DependencyHandler {
283 fn handle_variable_reference(&mut self, var: VariableId);
284 fn handle_parameter_reference(&mut self, param: ParameterId);
285 fn handle_branch_reference(&mut self, access: DisciplineAccess, branch: BranchId, order: u8);
286 fn handle_system_function_call(
287 &mut self,
288 call: SystemFunctionCall<RealExpressionId, StringExpressionId, PortId, ParameterId>,
289 );
290}
291
292impl DependencyHandler for () {
293 fn handle_variable_reference(&mut self, _: VariableId) {}
294
295 fn handle_parameter_reference(&mut self, _: ParameterId) {}
296
297 fn handle_branch_reference(&mut self, _: DisciplineAccess, _: BranchId, _: u8) {}
298
299 fn handle_system_function_call(
300 &mut self,
301 _: SystemFunctionCall<RealExpressionId, StringExpressionId, PortId, ParameterId>,
302 ) {
303 }
304}