litex/runtime/
runtime_resolve_obj.rs1use crate::common::count_range_integer::{
2 count_closed_range_integer_endpoints, count_half_open_range_integer_endpoints,
3};
4use crate::prelude::*;
5use crate::verify::{compare_normalized_number_str_to_zero, NumberCompareResult};
6
7impl Runtime {
8 pub fn resolve_obj_to_number(&self, obj: &Obj) -> Option<Number> {
9 if let Some(number) = obj.evaluate_to_normalized_decimal_number() {
10 return Some(number);
11 }
12 let obj_key = obj.to_string();
13 if let Some(number) = self.get_object_equal_to_normalized_decimal_number(&obj_key) {
14 return Some(number);
15 }
16 None
17 }
18
19 pub fn resolve_obj_to_number_resolved(&self, obj: &Obj) -> Option<Number> {
20 self.resolve_obj_to_number(&self.resolve_obj(obj))
21 }
22
23 fn resolve_obj_try_fold_arithmetic(&self, result: Obj) -> Obj {
27 if let Some(calculated) = result.evaluate_to_normalized_decimal_number() {
28 return calculated.into();
29 }
30 if let Some(n) = self.resolve_obj_to_number(&result) {
31 return n.into();
32 }
33 result
34 }
35
36 pub fn resolve_obj(&self, obj: &Obj) -> Obj {
37 if let Some(number) = self.resolve_obj_to_number(obj) {
38 return number.into();
39 }
40 match obj {
41 Obj::Number(number) => number.clone().into(),
42 Obj::Add(add) => {
43 let result: Obj =
44 Add::new(self.resolve_obj(&add.left), self.resolve_obj(&add.right)).into();
45 self.resolve_obj_try_fold_arithmetic(result)
46 }
47 Obj::Sub(sub) => {
48 let result: Obj =
49 Sub::new(self.resolve_obj(&sub.left), self.resolve_obj(&sub.right)).into();
50 self.resolve_obj_try_fold_arithmetic(result)
51 }
52 Obj::Mul(mul) => {
53 let result: Obj =
54 Mul::new(self.resolve_obj(&mul.left), self.resolve_obj(&mul.right)).into();
55 self.resolve_obj_try_fold_arithmetic(result)
56 }
57 Obj::Mod(mod_obj) => {
58 let result: Obj = Mod::new(
59 self.resolve_obj(&mod_obj.left),
60 self.resolve_obj(&mod_obj.right),
61 )
62 .into();
63 self.resolve_obj_try_fold_arithmetic(result)
64 }
65 Obj::Pow(pow) => {
66 let result: Obj =
67 Pow::new(self.resolve_obj(&pow.base), self.resolve_obj(&pow.exponent)).into();
68 self.resolve_obj_try_fold_arithmetic(result)
69 }
70 Obj::Div(div) => {
71 let result: Obj =
72 Div::new(self.resolve_obj(&div.left), self.resolve_obj(&div.right)).into();
73 self.resolve_obj_try_fold_arithmetic(result)
74 }
75 Obj::Abs(a) => {
76 let result: Obj = Abs::new(self.resolve_obj(&a.arg)).into();
77 self.resolve_obj_try_fold_arithmetic(result)
78 }
79 Obj::Max(m) => {
80 let result: Obj =
81 Max::new(self.resolve_obj(&m.left), self.resolve_obj(&m.right)).into();
82 self.resolve_obj_try_fold_arithmetic(result)
83 }
84 Obj::Min(m) => {
85 let result: Obj =
86 Min::new(self.resolve_obj(&m.left), self.resolve_obj(&m.right)).into();
87 self.resolve_obj_try_fold_arithmetic(result)
88 }
89 Obj::Log(l) => {
90 let result: Obj =
91 Log::new(self.resolve_obj(&l.base), self.resolve_obj(&l.arg)).into();
92 self.resolve_obj_try_fold_arithmetic(result)
93 }
94 Obj::FiniteSeqSet(fs) => {
95 FiniteSeqSet::new(self.resolve_obj(&fs.set), self.resolve_obj(&fs.n)).into()
96 }
97 Obj::SeqSet(ss) => SeqSet::new(self.resolve_obj(&ss.set)).into(),
98 Obj::MatrixSet(ms) => MatrixSet::new(
99 self.resolve_obj(&ms.set),
100 self.resolve_obj(&ms.row_len),
101 self.resolve_obj(&ms.col_len),
102 )
103 .into(),
104 Obj::FiniteSeqListObj(list) => {
105 let objs: Vec<Obj> = list.objs.iter().map(|o| self.resolve_obj(o)).collect();
106 FiniteSeqListObj::new(objs).into()
107 }
108 Obj::MatrixListObj(matrix) => {
109 let rows: Vec<Vec<Obj>> = matrix
110 .rows
111 .iter()
112 .map(|row| row.iter().map(|o| self.resolve_obj(o)).collect())
113 .collect();
114 MatrixListObj::new(rows).into()
115 }
116 Obj::FnObj(fn_obj) => {
117 if let FnObjHead::AnonymousFnLiteral(anonymous_fn) = fn_obj.head.as_ref() {
118 if !fn_obj.body.is_empty() {
119 let mut args: Vec<Obj> = Vec::new();
120 for group in fn_obj.body.iter() {
121 for arg in group.iter() {
122 args.push((**arg).clone());
123 }
124 }
125 let param_defs = &anonymous_fn.body.params_def_with_set;
126 if args.len() == ParamGroupWithSet::number_of_params(param_defs) {
127 let param_to_arg_map =
128 ParamGroupWithSet::param_defs_and_args_to_param_to_arg_map(
129 param_defs, &args,
130 );
131 if let Ok(reduced) = self.inst_obj(
132 anonymous_fn.equal_to.as_ref(),
133 ¶m_to_arg_map,
134 ParamObjType::FnSet,
135 ) {
136 return self.resolve_obj(&reduced);
137 }
138 }
139 }
140 }
141 if fn_obj.body.len() == 1 && fn_obj.body[0].len() == 1 {
142 let head_key = fn_obj.head.to_string();
143 if let Some(list) = self.get_obj_equal_to_finite_seq_list(&head_key) {
144 let arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
145 if let Some(ix) = self.resolve_obj_to_number(&arg) {
146 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
147 if one_based >= 1 && one_based <= list.objs.len() {
148 return (*list.objs[one_based - 1]).clone();
149 }
150 }
151 }
152 }
153 }
154 if fn_obj.body.len() == 2 && fn_obj.body[0].len() == 1 && fn_obj.body[1].len() == 1
155 {
156 let head_key = fn_obj.head.to_string();
157 if let Some(mat) = self.get_obj_equal_to_matrix_list(&head_key) {
158 let r_arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
159 let c_arg = self.resolve_obj(fn_obj.body[1][0].as_ref());
160 if let (Some(rn), Some(cn)) = (
161 self.resolve_obj_to_number(&r_arg),
162 self.resolve_obj_to_number(&c_arg),
163 ) {
164 if let (Ok(r1), Ok(c1)) = (
165 rn.normalized_value.parse::<usize>(),
166 cn.normalized_value.parse::<usize>(),
167 ) {
168 if r1 >= 1
169 && r1 <= mat.rows.len()
170 && c1 >= 1
171 && c1 <= mat.rows[r1 - 1].len()
172 {
173 return (*mat.rows[r1 - 1][c1 - 1]).clone();
174 }
175 }
176 }
177 }
178 }
179 if fn_obj.body.len() == 1 && fn_obj.body[0].len() == 2 {
180 let head_key = fn_obj.head.to_string();
181 if let Some(mat) = self.get_obj_equal_to_matrix_list(&head_key) {
182 let r_arg = self.resolve_obj(fn_obj.body[0][0].as_ref());
183 let c_arg = self.resolve_obj(fn_obj.body[0][1].as_ref());
184 if let (Some(rn), Some(cn)) = (
185 self.resolve_obj_to_number(&r_arg),
186 self.resolve_obj_to_number(&c_arg),
187 ) {
188 if let (Ok(r1), Ok(c1)) = (
189 rn.normalized_value.parse::<usize>(),
190 cn.normalized_value.parse::<usize>(),
191 ) {
192 if r1 >= 1
193 && r1 <= mat.rows.len()
194 && c1 >= 1
195 && c1 <= mat.rows[r1 - 1].len()
196 {
197 return (*mat.rows[r1 - 1][c1 - 1]).clone();
198 }
199 }
200 }
201 }
202 }
203 if let Some(number) = self.resolve_obj_to_number(obj) {
204 number.into()
205 } else {
206 obj.clone()
207 }
208 }
209 Obj::Atom(AtomObj::Identifier(_)) | Obj::Atom(AtomObj::IdentifierWithMod(_)) => {
210 if let Some(number) = self.resolve_obj_to_number(obj) {
211 number.into()
212 } else {
213 obj.clone()
214 }
215 }
216 Obj::Count(count) => match &*count.set {
217 Obj::ListSet(list_set) => Number::new(list_set.list.len().to_string()).into(),
218 Obj::ClosedRange(cr) => {
219 if let (Some(a_num), Some(b_num)) = (
220 self.resolve_obj_to_number_resolved(cr.start.as_ref()),
221 self.resolve_obj_to_number_resolved(cr.end.as_ref()),
222 ) {
223 if let Some(n) = count_closed_range_integer_endpoints(&a_num, &b_num) {
224 return n.into();
225 }
226 }
227 obj.clone()
228 }
229 Obj::Range(r) => {
230 if let (Some(a_num), Some(b_num)) = (
231 self.resolve_obj_to_number_resolved(r.start.as_ref()),
232 self.resolve_obj_to_number_resolved(r.end.as_ref()),
233 ) {
234 if let Some(n) = count_half_open_range_integer_endpoints(&a_num, &b_num) {
235 return n.into();
236 }
237 }
238 obj.clone()
239 }
240 _ => obj.clone(),
241 },
242 Obj::TupleDim(dim) => match &*dim.arg {
243 Obj::Tuple(tuple) => Number::new(tuple.args.len().to_string()).into(),
244 _ => obj.clone(),
245 },
246 Obj::CartDim(cart_dim) => match &*cart_dim.set {
247 Obj::Cart(cart) => Number::new(cart.args.len().to_string()).into(),
248 _ => obj.clone(),
249 },
250 Obj::Proj(proj) => match &*proj.set {
251 Obj::Cart(cart) => {
252 let projection_index_number = self.resolve_obj_to_number(&proj.dim);
253 if let Some(projection_index_number) = projection_index_number {
254 let projection_index_parsed_result =
255 projection_index_number.normalized_value.parse::<usize>();
256 if let Ok(projection_index_one_based) = projection_index_parsed_result {
257 if projection_index_one_based >= 1
258 && projection_index_one_based <= cart.args.len()
259 {
260 return (*cart.args[projection_index_one_based - 1]).clone();
261 }
262 }
263 }
264 obj.clone()
265 }
266 _ => {
267 let known_cart_obj = self.get_object_equal_to_cart(&proj.set.to_string());
268 if let Some(known_cart_obj) = known_cart_obj {
269 let projection_index_number = self.resolve_obj_to_number(&proj.dim);
270 if let Some(projection_index_number) = projection_index_number {
271 let projection_index_parsed_result =
272 projection_index_number.normalized_value.parse::<usize>();
273 if let Ok(projection_index_one_based) = projection_index_parsed_result {
274 if projection_index_one_based >= 1
275 && projection_index_one_based <= known_cart_obj.args.len()
276 {
277 return (*known_cart_obj.args[projection_index_one_based - 1])
278 .clone();
279 }
280 }
281 }
282 }
283 obj.clone()
284 }
285 },
286 Obj::ObjAtIndex(obj_at_index) => match &*obj_at_index.obj {
287 Obj::Tuple(tuple) => {
288 let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
289 if let Some(tuple_index_number) = tuple_index_number {
290 let tuple_index_parsed_result =
291 tuple_index_number.normalized_value.parse::<usize>();
292 if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
293 if tuple_index_one_based >= 1
294 && tuple_index_one_based <= tuple.args.len()
295 {
296 return (*tuple.args[tuple_index_one_based - 1]).clone();
297 }
298 }
299 }
300 obj.clone()
301 }
302 Obj::FiniteSeqListObj(list) => {
303 let ix = self.resolve_obj_to_number(&obj_at_index.index);
304 if let Some(ix) = ix {
305 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
306 if one_based >= 1 && one_based <= list.objs.len() {
307 return (*list.objs[one_based - 1]).clone();
308 }
309 }
310 }
311 obj.clone()
312 }
313 _ => {
314 let known_tuple_obj =
315 self.get_obj_equal_to_tuple(&obj_at_index.obj.to_string());
316 if let Some(known_tuple_obj) = known_tuple_obj {
317 let tuple_index_number = self.resolve_obj_to_number(&obj_at_index.index);
318 if let Some(tuple_index_number) = tuple_index_number {
319 let tuple_index_parsed_result =
320 tuple_index_number.normalized_value.parse::<usize>();
321 if let Ok(tuple_index_one_based) = tuple_index_parsed_result {
322 if tuple_index_one_based >= 1
323 && tuple_index_one_based <= known_tuple_obj.args.len()
324 {
325 return (*known_tuple_obj.args[tuple_index_one_based - 1])
326 .clone();
327 }
328 }
329 }
330 }
331 if let Some(known_list) =
332 self.get_obj_equal_to_finite_seq_list(&obj_at_index.obj.to_string())
333 {
334 let ix = self.resolve_obj_to_number(&obj_at_index.index);
335 if let Some(ix) = ix {
336 if let Ok(one_based) = ix.normalized_value.parse::<usize>() {
337 if one_based >= 1 && one_based <= known_list.objs.len() {
338 return (*known_list.objs[one_based - 1]).clone();
339 }
340 }
341 }
342 }
343 obj.clone()
344 }
345 },
346 Obj::FamilyObj(f) => {
347 let params: Vec<Obj> = f.params.iter().map(|p| self.resolve_obj(p)).collect();
348 FamilyObj::new(f.name.clone(), params).into()
349 }
350 _ => obj.clone(),
351 }
352 }
353
354 pub(crate) fn obj_is_resolved_zero(&self, obj: &Obj) -> bool {
355 self.resolve_obj_to_number(obj)
356 .map(|n| {
357 matches!(
358 compare_normalized_number_str_to_zero(&n.normalized_value),
359 NumberCompareResult::Equal
360 )
361 })
362 .unwrap_or(false)
363 }
364
365 pub(crate) fn peel_mul_by_literal_neg_one(&self, obj: &Obj) -> Option<Obj> {
367 let Obj::Mul(m) = obj else {
368 return None;
369 };
370 if let Some(ln) = self.resolve_obj_to_number(m.left.as_ref()) {
371 if ln.normalized_value == "-1" {
372 return Some(m.right.as_ref().clone());
373 }
374 }
375 if let Some(rn) = self.resolve_obj_to_number(m.right.as_ref()) {
376 if rn.normalized_value == "-1" {
377 return Some(m.left.as_ref().clone());
378 }
379 }
380 None
381 }
382}