|
| 1 | +// RUN: circt-opt %s --comb-simplify-tt | FileCheck %s |
| 2 | + |
| 3 | +// CHECK-LABEL: @truth_table_constant_true |
| 4 | +hw.module @truth_table_constant_true(in %a: i1, in %b: i1, out out: i1) { |
| 5 | + // Truth table that is always true (all ones) |
| 6 | + // CHECK-NEXT: [[TRUE:%.+]] = hw.constant true |
| 7 | + // CHECK-NEXT: hw.output [[TRUE]] |
| 8 | + %0 = comb.truth_table %a, %b -> [true, true, true, true] |
| 9 | + hw.output %0 : i1 |
| 10 | +} |
| 11 | + |
| 12 | +// CHECK-LABEL: @truth_table_constant_false |
| 13 | +hw.module @truth_table_constant_false(in %a: i1, in %b: i1, out out: i1) { |
| 14 | + // Truth table that is always false (all zeros) |
| 15 | + // CHECK-NEXT: [[FALSE:%.+]] = hw.constant false |
| 16 | + // CHECK-NEXT: hw.output [[FALSE]] |
| 17 | + %0 = comb.truth_table %a, %b -> [false, false, false, false] |
| 18 | + hw.output %0 : i1 |
| 19 | +} |
| 20 | + |
| 21 | +// CHECK-LABEL: @truth_table_identity |
| 22 | +hw.module @truth_table_identity(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 23 | + // Truth table that depends only on %a |
| 24 | + // Pattern: [0,0,0,0,1,1,1,1] means output follows first input |
| 25 | + // CHECK-NEXT: hw.output %a |
| 26 | + %0 = comb.truth_table %a, %b, %c -> [false, false, false, false, true, true, true, true] |
| 27 | + hw.output %0 : i1 |
| 28 | +} |
| 29 | + |
| 30 | +// CHECK-LABEL: @truth_table_inverted |
| 31 | +hw.module @truth_table_inverted(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 32 | + // Truth table that depends only on %a (inverted) |
| 33 | + // Pattern: [1,1,1,1,0,0,0,0] means output is NOT of first input |
| 34 | + // Should simplify to single-input truth table for negation |
| 35 | + // CHECK-NEXT: [[NOT:%.+]] = comb.truth_table %a -> [true, false] |
| 36 | + // CHECK-NEXT: hw.output [[NOT]] |
| 37 | + %0 = comb.truth_table %a, %b, %c -> [true, true, true, true, false, false, false, false] |
| 38 | + hw.output %0 : i1 |
| 39 | +} |
| 40 | + |
| 41 | +// CHECK-LABEL: @truth_table_middle_input_identity |
| 42 | +hw.module @truth_table_middle_input_identity(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 43 | + // Truth table that depends only on %b (middle input, identity) |
| 44 | + // Pattern: [0,0,1,1,0,0,1,1] means output follows second input |
| 45 | + // CHECK-NEXT: hw.output %b |
| 46 | + %0 = comb.truth_table %a, %b, %c -> [false, false, true, true, false, false, true, true] |
| 47 | + hw.output %0 : i1 |
| 48 | +} |
| 49 | + |
| 50 | +// CHECK-LABEL: @truth_table_middle_input_inverted |
| 51 | +hw.module @truth_table_middle_input_inverted(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 52 | + // Truth table that depends only on %b (middle input, inverted) |
| 53 | + // Pattern: [1,1,0,0,1,1,0,0] means output is NOT of second input |
| 54 | + // Should simplify to single-input truth table for negation |
| 55 | + // CHECK-NEXT: [[NOT:%.+]] = comb.truth_table %b -> [true, false] |
| 56 | + // CHECK-NEXT: hw.output [[NOT]] |
| 57 | + %0 = comb.truth_table %a, %b, %c -> [true, true, false, false, true, true, false, false] |
| 58 | + hw.output %0 : i1 |
| 59 | +} |
| 60 | + |
| 61 | +// CHECK-LABEL: @truth_table_last_input_identity |
| 62 | +hw.module @truth_table_last_input_identity(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 63 | + // Truth table that depends only on %c (last input, identity) |
| 64 | + // Pattern: [0,1,0,1,0,1,0,1] means output follows third input |
| 65 | + // CHECK-NEXT: hw.output %c |
| 66 | + %0 = comb.truth_table %a, %b, %c -> [false, true, false, true, false, true, false, true] |
| 67 | + hw.output %0 : i1 |
| 68 | +} |
| 69 | + |
| 70 | +// CHECK-LABEL: @truth_table_last_input_inverted |
| 71 | +hw.module @truth_table_last_input_inverted(in %a: i1, in %b: i1, in %c: i1, out out: i1) { |
| 72 | + // Truth table that depends only on %c (last input, inverted) |
| 73 | + // Pattern: [1,0,1,0,1,0,1,0] means output is NOT of third input |
| 74 | + // Should simplify to single-input truth table for negation |
| 75 | + // CHECK-NEXT: [[NOT:%.+]] = comb.truth_table %c -> [true, false] |
| 76 | + // CHECK-NEXT: hw.output [[NOT]] |
| 77 | + %0 = comb.truth_table %a, %b, %c -> [true, false, true, false, true, false, true, false] |
| 78 | + hw.output %0 : i1 |
| 79 | +} |
| 80 | + |
| 81 | +// CHECK-LABEL: @truth_table_two_input_non_foldable |
| 82 | +hw.module @truth_table_two_input_non_foldable(in %a: i1, in %b: i1, out out: i1) { |
| 83 | + // Truth table depends on both inputs, Should not be canonicalized |
| 84 | + // CHECK-NEXT: %0 = comb.truth_table %a, %b -> [false, false, false, true] |
| 85 | + // CHECK-NEXT: hw.output %0 |
| 86 | + %0 = comb.truth_table %a, %b -> [false, false, false, true] |
| 87 | + hw.output %0 : i1 |
| 88 | +} |
| 89 | + |
| 90 | +// CHECK-LABEL: @truth_table_with_extract_operations |
| 91 | +hw.module @truth_table_with_extract_operations(in %c: i3, out out: i1) { |
| 92 | + // Truth table depends only on first input (%2 = LSB of %c) |
| 93 | + // CHECK: [[TMP:%.+]] = comb.extract %c from 0 |
| 94 | + // CHECK: hw.output [[TMP]] |
| 95 | + %0 = comb.extract %c from 2 : (i3) -> i1 |
| 96 | + %1 = comb.extract %c from 1 : (i3) -> i1 |
| 97 | + %2 = comb.extract %c from 0 : (i3) -> i1 |
| 98 | + %3 = comb.truth_table %2, %0, %1 -> [false, false, false, false, true, true, true, true] |
| 99 | + hw.output %3 : i1 |
| 100 | +} |
0 commit comments