1use std::collections::HashMap;
2
3use spade_common::id_tracker::ExprID;
4
5use crate::{Entity, MirInput, Register, Statement, ValueName};
6
7macro_rules! check {
8 ($cond:expr) => {
9 if !($cond) {
10 return false;
11 }
12 };
13}
14
15pub struct VarMap {
18 pub expr_map: HashMap<ExprID, ExprID>,
19 pub expr_map_rev: HashMap<ExprID, ExprID>,
20 pub name_map: HashMap<u64, u64>,
21 pub name_map_rev: HashMap<u64, u64>,
22}
23
24impl Default for VarMap {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl VarMap {
31 pub fn new() -> Self {
32 Self {
33 expr_map: HashMap::new(),
34 expr_map_rev: HashMap::new(),
35 name_map: HashMap::new(),
36 name_map_rev: HashMap::new(),
37 }
38 }
39
40 pub fn map_expr(&mut self, lhs: ExprID, rhs: ExprID) {
41 self.expr_map.insert(lhs, rhs);
42 self.expr_map_rev.insert(rhs, lhs);
43 }
44
45 pub fn map_name(&mut self, lhs: u64, rhs: u64) {
46 self.name_map.insert(lhs, rhs);
47 self.name_map_rev.insert(rhs, lhs);
48 }
49
50 fn try_update_name(&mut self, lhs: &ValueName, rhs: &ValueName) -> Result<(), ()> {
51 match (lhs, rhs) {
53 (ValueName::Named(i1, n1, _), ValueName::Named(i2, n2, _)) => {
54 if n1 != n2 {
55 Err(())
56 } else {
57 self.map_name(*i1, *i2);
58 Ok(())
59 }
60 }
61 (ValueName::Expr(i1), ValueName::Expr(i2)) => {
62 self.map_expr(*i1, *i2);
63 Ok(())
64 }
65 _ => Err(()),
66 }
67 }
68
69 fn compare_name(
70 &self,
71 (lhs_id, lhs_name): (&u64, &str),
72 (rhs_id, rhs_name): (&u64, &str),
73 ) -> bool {
74 if lhs_name != rhs_name {
75 return false;
76 }
77
78 self.name_map
79 .get(lhs_id)
80 .map(|v| rhs_id == v)
81 .unwrap_or(false)
82 }
83
84 fn compare_exprs(&self, lhs: ExprID, rhs: ExprID) -> bool {
85 self.expr_map.get(&lhs).map(|v| v == &rhs).unwrap_or(false)
86 }
87
88 pub fn compare_vals(&self, lhs: &ValueName, rhs: &ValueName) -> bool {
89 match (lhs, rhs) {
90 (ValueName::Named(i1, n1, _), ValueName::Named(i2, n2, _)) => {
91 self.compare_name((i1, n1), (i2, n2))
92 }
93 (ValueName::Expr(i1), ValueName::Expr(i2)) => self.compare_exprs(*i1, *i2),
94 _ => false,
95 }
96 }
97}
98
99fn compare_statements(s1: &Statement, s2: &Statement, var_map: &mut VarMap) -> bool {
101 macro_rules! check_name {
102 ($lhs:expr, $rhs:expr) => {
103 if !var_map.compare_vals($lhs, $rhs) {
104 return false;
105 }
106 };
107 }
108 match (s1, s2) {
109 (Statement::Binding(b1), Statement::Binding(b2)) => {
110 if b1.ty != b2.ty {
113 return false;
114 }
115 if b1.operator != b2.operator {
116 return false;
117 }
118 if b1.operands.len() != b2.operands.len() {
119 return false;
120 }
121 for (n1, n2) in b1.operands.iter().zip(b2.operands.iter()) {
123 check_name!(n1, n2)
124 }
125
126 true
127 }
128 (Statement::Register(r1), Statement::Register(r2)) => {
129 let Register {
130 name: _,
131 ty: ty1,
132 clock: clock1,
133 reset: reset1,
134 initial: initial1,
135 value: value1,
136 loc: _,
137 traced: _,
138 } = &r1;
139 let Register {
140 name: _,
141 ty: ty2,
142 clock: clock2,
143 reset: reset2,
144 initial: initial2,
145 value: value2,
146 loc: _,
147 traced: _,
148 } = &r2;
149 if ty1 != ty2 {
150 return false;
151 }
152
153 check_name!(value1, value2);
154 check_name!(clock1, clock2);
155
156 match (reset1, reset2) {
157 (Some((t1, v1)), Some((t2, v2))) => {
158 check_name!(t1, t2);
159 check_name!(v1, v2);
160 }
161 (None, None) => {}
162 _ => return false,
163 }
164
165 match (initial1, initial2) {
166 (Some(l), Some(r)) => {
167 if l != r {
168 return false;
169 }
170 }
171 (None, None) => {}
172 _ => return false,
173 }
174
175 true
176 }
177 (Statement::Constant(_, t1, v1), Statement::Constant(_, t2, v2)) => {
178 if t1 != t2 {
179 return false;
180 }
181 if v1 != v2 {
182 return false;
183 }
184 true
185 }
186 (Statement::Assert(v1), Statement::Assert(v2)) => {
187 check_name!(v1, v2);
188 true
189 }
190 (
191 Statement::Set {
192 target: tl,
193 value: vl,
194 },
195 Statement::Set {
196 target: tr,
197 value: vr,
198 },
199 ) => {
200 check_name!(tl, tr);
201 check_name!(vl, vr);
202 true
203 }
204 (
205 Statement::WalTrace {
206 name: n1,
207 val: v1,
208 suffix: s1,
209 ty: ty1,
210 },
211 Statement::WalTrace {
212 name: n2,
213 val: v2,
214 suffix: s2,
215 ty: ty2,
216 },
217 ) => {
218 check_name!(n1, n2);
219 check_name!(v1, v2);
220 if s1 != s2 {
221 return false;
222 }
223 if ty1 != ty2 {
224 return false;
225 }
226 true
227 }
228 _ => false,
229 }
230}
231
232fn populate_var_map(
233 stmts1: &[Statement],
234 stmts2: &[Statement],
235 var_map: &mut VarMap,
236) -> Result<(), ()> {
237 stmts1
240 .iter()
241 .zip(stmts2.iter())
242 .try_for_each(|(s1, s2)| match (s1, s2) {
243 (Statement::Binding(b1), Statement::Binding(b2)) => {
244 var_map.try_update_name(&b1.name, &b2.name)
245 }
246 (Statement::Register(r1), Statement::Register(r2)) => {
247 var_map.try_update_name(&r1.name, &r2.name)
248 }
249 (Statement::Constant(e1, _, _), Statement::Constant(e2, _, _)) => {
250 var_map.try_update_name(&ValueName::Expr(*e1), &ValueName::Expr(*e2))
251 }
252 (Statement::WalTrace { .. }, Statement::WalTrace { .. }) => Ok(()),
253 (Statement::Assert(_), Statement::Assert(_)) => Ok(()),
254 (Statement::Set { .. }, Statement::Set { .. }) => Ok(()),
255 _ => Err(()),
256 })
257}
258
259pub fn compare_entity(e1: &Entity, e2: &Entity, var_map: &mut VarMap) -> bool {
260 check!(e1.name == e2.name);
261 check!(e1.output_type == e2.output_type);
262
263 for (
264 MirInput {
265 name: n1,
266 val_name: vn1,
267 ty: t1,
268 no_mangle: nm1,
269 },
270 MirInput {
271 name: n2,
272 val_name: vn2,
273 ty: t2,
274 no_mangle: nm2,
275 },
276 ) in e1.inputs.iter().zip(e2.inputs.iter())
277 {
278 check!(nm1 == nm2);
279 check!(n1 == n2);
280 check!(var_map.try_update_name(vn1, vn2).is_ok());
281 check!(t1 == t2);
282 }
283
284 if populate_var_map(&e1.statements, &e2.statements, var_map).is_err() {
285 return false;
286 }
287
288 for (s1, s2) in e1.statements.iter().zip(e2.statements.iter()) {
289 check!(compare_statements(s1, s2, var_map))
290 }
291 check!(e1.statements.len() == e2.statements.len());
292
293 check!(var_map.compare_vals(&e1.output, &e2.output));
294
295 true
296}
297
298#[cfg(test)]
299mod statement_comparison_tests {
300 use super::*;
301
302 use crate::{statement, types::Type, ConstantValue};
303
304 use crate as spade_mir;
305
306 #[test]
307 fn identical_bindings_update_expr_map() {
308 let mut map = VarMap::new();
309
310 map.map_expr(ExprID(1), ExprID(2));
311 map.map_name(2, 3);
312
313 let lhs = statement!(e(0); Type::int(5); Add; e(1), n(2, "test"));
314 let rhs = statement!(e(3); Type::int(5); Add; e(2), n(3, "test"));
315
316 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
317 assert!(compare_statements(&lhs, &rhs, &mut map));
318
319 assert!(map.compare_exprs(ExprID(0), ExprID(3)))
320 }
321
322 #[test]
323 fn identical_bindings_update_name_map() {
324 let mut map = VarMap::new();
325
326 map.map_expr(ExprID(1), ExprID(2));
327 map.map_name(2, 3);
328
329 let lhs = statement!(n(0, "a"); Type::int(5); Add; e(1), n(2, "test"));
330 let rhs = statement!(n(3, "a"); Type::int(5); Add; e(2), n(3, "test"));
331
332 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
333 assert!(compare_statements(&lhs, &rhs, &mut map));
334
335 assert!(map.compare_name((&0, "a"), (&3, "a")))
336 }
337
338 #[test]
339 fn identical_bindings_with_differing_string_name_diff() {
340 let mut map = VarMap::new();
341
342 map.map_expr(ExprID(1), ExprID(2));
343 map.map_name(2, 3);
344
345 let lhs = statement!(n(0, "a"); Type::int(5); Add; e(1), n(2, "test"));
346 let rhs = statement!(n(3, "b"); Type::int(5); Add; e(2), n(3, "test"));
347
348 assert!(populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).is_err());
349 }
350
351 #[test]
352 fn bindings_with_mismatched_types_are_different() {
353 let mut map = VarMap::new();
354
355 map.map_expr(ExprID(1), ExprID(1));
356 map.map_expr(ExprID(2), ExprID(2));
357
358 let lhs = statement!(e(0); Type::int(5); Add; e(1), e(2));
359 let rhs = statement!(e(3); Type::int(4); Add; e(1), e(2));
360
361 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
362
363 assert!(!compare_statements(&lhs, &rhs, &mut map));
364 }
365
366 #[test]
367 fn bindings_with_mismatched_operators_are_different() {
368 let mut map = VarMap::new();
369
370 map.map_expr(ExprID(1), ExprID(1));
371 map.map_expr(ExprID(2), ExprID(2));
372
373 let lhs = statement!(e(0); Type::int(5); Add; e(1), e(2));
374 let rhs = statement!(e(3); Type::int(5); Select; e(1), e(2));
375
376 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
377
378 assert!(!compare_statements(&lhs, &rhs, &mut map));
379 }
380
381 #[test]
382 fn bindings_with_mismatched_operands_are_different() {
383 let mut map = VarMap::new();
384
385 map.map_expr(ExprID(1), ExprID(1));
386 map.map_expr(ExprID(2), ExprID(2));
387
388 let lhs = statement!(e(0); Type::int(5); Add; e(2), e(1));
389 let rhs = statement!(e(3); Type::int(5); Add; e(1), e(2));
390
391 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
392
393 assert!(!compare_statements(&lhs, &rhs, &mut map));
394 }
395
396 #[test]
397 fn bindings_with_unmapped_names_are_different() {
398 let mut map = VarMap::new();
399
400 map.map_expr(ExprID(1), ExprID(1));
401 map.map_expr(ExprID(2), ExprID(2));
402
403 let lhs = statement!(e(0); Type::int(5); Add; e(2), e(1));
404 let rhs = statement!(e(3); Type::int(5); Add; e(1), e(3));
405
406 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
407
408 assert!(!compare_statements(&lhs, &rhs, &mut map));
409 }
410
411 #[test]
413 fn identical_registers_with_reset_do_not_diff() {
414 let mut map = VarMap::new();
415
416 map.map_expr(ExprID(1), ExprID(1));
417 map.map_expr(ExprID(2), ExprID(2));
418 map.map_expr(ExprID(3), ExprID(3));
419 map.map_expr(ExprID(4), ExprID(4));
420
421 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
422 let rhs = statement!(reg e(5); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
423
424 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
425
426 assert!(compare_statements(&lhs, &rhs, &mut map));
427 }
428
429 #[test]
430 fn identical_registers_with_reset_do_not_diff_and_update_names() {
431 let mut map = VarMap::new();
432
433 map.map_expr(ExprID(1), ExprID(1));
434 map.map_expr(ExprID(2), ExprID(2));
435 map.map_expr(ExprID(3), ExprID(3));
436 map.map_expr(ExprID(4), ExprID(4));
437
438 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
439 let rhs = statement!(reg e(5); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
440
441 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
442
443 assert!(compare_statements(&lhs, &rhs, &mut map));
444
445 assert!(map.compare_exprs(ExprID(0), ExprID(5)));
446 }
447
448 #[test]
449 fn identical_registers_update_name_table() {
450 let mut map = VarMap::new();
451
452 map.map_expr(ExprID(1), ExprID(1));
453 map.map_expr(ExprID(2), ExprID(2));
454 map.map_expr(ExprID(3), ExprID(3));
455 map.map_expr(ExprID(4), ExprID(4));
456
457 let lhs = statement!(reg n(0, "test"); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
458 let rhs = statement!(reg n(5, "test"); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
459
460 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
461
462 assert!(compare_statements(&lhs, &rhs, &mut map));
463
464 assert!(map.compare_name((&0, "test"), (&5, "test")));
465 }
466
467 #[test]
468 fn mismatched_register_clocks_causes_a_diff() {
469 let mut map = VarMap::new();
470
471 map.map_expr(ExprID(1), ExprID(1));
472 map.map_expr(ExprID(2), ExprID(2));
473 map.map_expr(ExprID(3), ExprID(3));
474 map.map_expr(ExprID(4), ExprID(4));
475
476 let lhs = statement!(reg e(0); Type::int(5); clock(e(3)); reset(e(3), e(4)); e(1));
477 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
478
479 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
480
481 assert!(!compare_statements(&lhs, &rhs, &mut map));
482 }
483
484 #[test]
485 fn mismatched_register_reset_trig_causes_a_diff() {
486 let mut map = VarMap::new();
487
488 map.map_expr(ExprID(1), ExprID(1));
489 map.map_expr(ExprID(2), ExprID(2));
490 map.map_expr(ExprID(3), ExprID(3));
491 map.map_expr(ExprID(4), ExprID(4));
492
493 let lhs = statement!(reg e(0); Type::int(5); clock(e(3)); reset(e(3), e(4)); e(1));
494 let rhs = statement!(reg e(0); Type::int(5); clock(e(3)); reset(e(2), e(4)); e(1));
495
496 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
497
498 assert!(!compare_statements(&lhs, &rhs, &mut map));
499 }
500
501 #[test]
502 fn mismatched_register_value_causes_diff() {
503 let mut map = VarMap::new();
504
505 map.map_expr(ExprID(1), ExprID(1));
506 map.map_expr(ExprID(2), ExprID(2));
507 map.map_expr(ExprID(3), ExprID(3));
508 map.map_expr(ExprID(4), ExprID(4));
509
510 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
511 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(5)); e(1));
512
513 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
514
515 assert!(!compare_statements(&lhs, &rhs, &mut map));
516 }
517
518 #[test]
519 fn identical_registers_with_mismatched_value_diff() {
520 let mut map = VarMap::new();
521
522 map.map_expr(ExprID(1), ExprID(1));
523 map.map_expr(ExprID(2), ExprID(2));
524 map.map_expr(ExprID(3), ExprID(3));
525 map.map_expr(ExprID(4), ExprID(4));
526
527 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
528 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(2));
529
530 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
531
532 assert!(!compare_statements(&lhs, &rhs, &mut map));
533 }
534
535 #[test]
536 fn identical_registers_with_mismatched_initial_diff() {
537 let mut map = VarMap::new();
538
539 map.map_expr(ExprID(1), ExprID(1));
540 map.map_expr(ExprID(2), ExprID(2));
541 map.map_expr(ExprID(3), ExprID(3));
542 map.map_expr(ExprID(4), ExprID(4));
543
544 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)) initial(vec![statement!(e(0); Type::Bool; Alias; e(3))]); e(1));
545 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)) initial(vec![statement!(e(0); Type::Bool; Alias; e(2))]); e(1));
546
547 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
548
549 assert!(!compare_statements(&lhs, &rhs, &mut map));
550 }
551
552 #[test]
553 fn identical_registers_with_initial_is_different_from_without() {
554 let mut map = VarMap::new();
555
556 map.map_expr(ExprID(1), ExprID(1));
557 map.map_expr(ExprID(2), ExprID(2));
558 map.map_expr(ExprID(3), ExprID(3));
559 map.map_expr(ExprID(4), ExprID(4));
560
561 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
562 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)) initial(vec![statement!(e(0); Type::Bool; Alias; e(2))]); e(1));
563
564 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
565
566 assert!(!compare_statements(&lhs, &rhs, &mut map));
567 }
568
569 #[test]
570 fn missing_register_causes_a_diff() {
571 let mut map = VarMap::new();
572
573 map.map_expr(ExprID(1), ExprID(1));
574 map.map_expr(ExprID(2), ExprID(2));
575 map.map_expr(ExprID(3), ExprID(3));
576 map.map_expr(ExprID(4), ExprID(4));
577
578 let lhs = statement!(reg e(0); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
579 let rhs = statement!(reg e(0); Type::int(5); clock(e(2)); e(1));
580
581 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
582
583 assert!(!compare_statements(&lhs, &rhs, &mut map));
584 }
585
586 #[test]
587 fn mismatched_types_causes_register_diff() {
588 let mut map = VarMap::new();
589
590 map.map_expr(ExprID(1), ExprID(1));
591 map.map_expr(ExprID(2), ExprID(2));
592 map.map_expr(ExprID(3), ExprID(3));
593 map.map_expr(ExprID(4), ExprID(4));
594
595 let lhs = statement!(reg e(0); Type::int(6); clock(e(2)); reset(e(3), e(4)); e(1));
596 let rhs = statement!(reg e(5); Type::int(5); clock(e(2)); reset(e(3), e(4)); e(1));
597
598 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
599
600 assert!(!compare_statements(&lhs, &rhs, &mut map));
601 }
602
603 #[test]
606 fn identical_constants_match() {
607 let mut map = VarMap::new();
608
609 let lhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
610 let rhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
611
612 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
613
614 assert!(compare_statements(&lhs, &rhs, &mut map));
615 }
616
617 #[test]
618 fn identical_constants_update_expressions() {
619 let mut map = VarMap::new();
620
621 let lhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
622 let rhs = statement!(const 1; Type::int(5); ConstantValue::int(10));
623
624 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
625
626 assert!(compare_statements(&lhs, &rhs, &mut map));
627
628 assert!(map.compare_exprs(ExprID(0), ExprID(1)));
629 }
630
631 #[test]
632 fn constant_type_mismatch_diff() {
633 let mut map = VarMap::new();
634
635 let lhs = statement!(const 0; Type::int(6); ConstantValue::int(10));
636 let rhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
637
638 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
639
640 assert!(!compare_statements(&lhs, &rhs, &mut map));
641 }
642
643 #[test]
644 fn constant_value_mismatch_diff() {
645 let mut map = VarMap::new();
646
647 let lhs = statement!(const 0; Type::int(5); ConstantValue::int(11));
648 let rhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
649
650 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
651
652 assert!(!compare_statements(&lhs, &rhs, &mut map));
653 }
654
655 #[test]
656 fn constant_value_type_mismatch_diff() {
657 let mut map = VarMap::new();
658
659 let lhs = statement!(const 0; Type::int(5); ConstantValue::Bool(false));
660 let rhs = statement!(const 0; Type::int(5); ConstantValue::int(10));
661
662 populate_var_map(&vec![lhs.clone()], &vec![rhs.clone()], &mut map).unwrap();
663
664 assert!(!compare_statements(&lhs, &rhs, &mut map));
665 }
666}
667
668#[cfg(test)]
669mod entity_comparison_tests {
670 use super::*;
671
672 use crate as spade_mir;
673 use crate::{entity, Type};
674
675 #[test]
676 fn identical_entities_have_no_diff() {
677 let mut var_map = VarMap::new();
678 var_map.map_name(1, 1);
679 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
680 } => n(1, "value"));
681 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
682 } => n(1, "value"));
683
684 assert!(compare_entity(&lhs, &rhs, &mut var_map));
685 }
686
687 #[test]
688 fn names_are_mapped_for_inputs() {
689 let mut var_map = VarMap::new();
690 var_map.map_name(1, 1);
691
692 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
693 } => n(1, "value"));
694 let rhs = entity!("pong"; ("_i_clk", n(2, "clk"), Type::Bool) -> Type::int(6); {
695 } => n(1, "value"));
696
697 assert!(compare_entity(&lhs, &rhs, &mut var_map));
698
699 assert!(var_map.compare_name((&0, "clk"), (&2, "clk")));
700 }
701
702 #[test]
703 fn mismatched_name_causes_diff() {
704 let mut var_map = VarMap::new();
705 var_map.map_name(1, 1);
706
707 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
708 } => n(1, "value"));
709 let rhs = entity!("not_pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
710 } => n(1, "value"));
711
712 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
713 }
714
715 #[test]
716 fn input_types_must_match() {
717 let mut var_map = VarMap::new();
718 var_map.map_name(1, 1);
719
720 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
721 } => n(1, "value"));
722 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::int(6)) -> Type::int(6); {
723 } => n(1, "value"));
724
725 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
726 }
727
728 #[test]
729 fn input_name_mismatch() {
730 let mut var_map = VarMap::new();
731 var_map.map_name(1, 1);
732
733 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
734 } => n(1, "value"));
735 let rhs = entity!("pong"; ("_i_not_clk", n(0, "clk"), Type::int(6)) -> Type::int(6); {
736 } => n(1, "value"));
737
738 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
739 }
740
741 #[test]
742 fn input_value_name_mismatch() {
743 let mut var_map = VarMap::new();
744 var_map.map_name(1, 1);
745
746 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
747 } => n(1, "value"));
748 let rhs = entity!("pong"; ("_i_clk", n(0, "not_clk"), Type::int(6)) -> Type::int(6); {
749 } => n(1, "value"));
750
751 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
752 }
753
754 #[test]
755 fn output_type_mismatch_causes_diff() {
756 let mut var_map = VarMap::new();
757 var_map.map_name(1, 1);
758
759 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(7); {
760 } => n(1, "value"));
761 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
762 } => n(1, "value"));
763
764 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
765 }
766
767 #[test]
768 fn output_name_mismatches_are_caught() {
769 let mut var_map = VarMap::new();
770 var_map.map_name(1, 1);
771
772 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
773 } => e(1));
774 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
775 } => e(2));
776
777 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
778 }
779
780 #[test]
781 fn mismatched_statements_cause_diff() {
782 let mut var_map = VarMap::new();
783 var_map.map_name(1, 1);
784
785 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
786 (e(0); Type::int(6); Add; n(1, "value"))
787 } => n(1, "value"));
788 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
789 (e(0); Type::int(7); Add; n(1, "value"))
790 } => n(1, "value"));
791
792 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
793 }
794
795 #[test]
796 fn mismatched_statement_counts_diff() {
797 let mut var_map = VarMap::new();
798 var_map.map_name(1, 1);
799
800 let lhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
801 (e(0); Type::int(6); Add; n(1, "value"));
802 (e(0); Type::int(6); Add; n(1, "value"))
803 } => n(1, "value"));
804 let rhs = entity!("pong"; ("_i_clk", n(0, "clk"), Type::Bool) -> Type::int(6); {
805 (e(0); Type::int(6); Add; n(1, "value"))
806 } => n(1, "value"));
807
808 assert!(!compare_entity(&lhs, &rhs, &mut var_map));
809 }
810}