mirror of https://github.com/llvm/circt.git
276 lines
13 KiB
MLIR
276 lines
13 KiB
MLIR
// RUN: circt-opt -pass-pipeline='builtin.module(firrtl.circuit(firrtl-imconstprop))' --split-input-file %s | FileCheck %s
|
|
|
|
// This contains a lot of tests which should be caught by IMCP.
|
|
// For now, we are checking that the aggregates don't cause the pass to error out.
|
|
|
|
firrtl.circuit "VectorPropagation1" {
|
|
// CHECK-LABEL: @VectorPropagation1
|
|
firrtl.module @VectorPropagation1(out %b: !firrtl.uint<1>) {
|
|
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
|
|
%tmp = firrtl.wire : !firrtl.vector<uint<1>, 2>
|
|
%0 = firrtl.subindex %tmp[0] : !firrtl.vector<uint<1>, 2>
|
|
%1 = firrtl.subindex %tmp[1] : !firrtl.vector<uint<1>, 2>
|
|
%2 = firrtl.xor %0, %1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
firrtl.matchingconnect %0, %c1_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %1, %c1_ui1 : !firrtl.uint<1>
|
|
// CHECK: firrtl.matchingconnect %b, %c0_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %b, %2 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "VectorPropagation2" {
|
|
// CHECK-LABEL: @VectorPropagation2
|
|
firrtl.module @VectorPropagation2(out %b1: !firrtl.uint<6>, out %b2: !firrtl.uint<6>, out %b3: !firrtl.uint<6>) {
|
|
|
|
// tmp1[0][0] <= 1
|
|
// tmp1[0][1] <= 2
|
|
// tmp1[1][0] <= 4
|
|
// tmp1[1][1] <= 8
|
|
// tmp1[2][0] <= 16
|
|
// tmp1[2][1] <= 32
|
|
|
|
// b1 <= tmp[0][0] xor tmp1[1][0] = 5
|
|
// b2 <= tmp[2][1] xor tmp1[0][1] = 34
|
|
// b3 <= tmp[1][1] xor tmp1[2][0] = 24
|
|
|
|
%c32_ui6 = firrtl.constant 32 : !firrtl.uint<6>
|
|
%c16_ui6 = firrtl.constant 16 : !firrtl.uint<6>
|
|
%c8_ui6 = firrtl.constant 8 : !firrtl.uint<6>
|
|
%c4_ui6 = firrtl.constant 4 : !firrtl.uint<6>
|
|
%c2_ui6 = firrtl.constant 2 : !firrtl.uint<6>
|
|
%c1_ui6 = firrtl.constant 1 : !firrtl.uint<6>
|
|
%tmp = firrtl.wire : !firrtl.vector<vector<uint<6>, 2>, 3>
|
|
%0 = firrtl.subindex %tmp[0] : !firrtl.vector<vector<uint<6>, 2>, 3>
|
|
%1 = firrtl.subindex %0[0] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %1, %c1_ui6 : !firrtl.uint<6>
|
|
%2 = firrtl.subindex %0[1] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %2, %c2_ui6 : !firrtl.uint<6>
|
|
%3 = firrtl.subindex %tmp[1] : !firrtl.vector<vector<uint<6>, 2>, 3>
|
|
%4 = firrtl.subindex %3[0] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %4, %c4_ui6 : !firrtl.uint<6>
|
|
%5 = firrtl.subindex %3[1] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %5, %c8_ui6 : !firrtl.uint<6>
|
|
%6 = firrtl.subindex %tmp[2] : !firrtl.vector<vector<uint<6>, 2>, 3>
|
|
%7 = firrtl.subindex %6[0] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %7, %c16_ui6 : !firrtl.uint<6>
|
|
%8 = firrtl.subindex %6[1] : !firrtl.vector<uint<6>, 2>
|
|
firrtl.matchingconnect %8, %c32_ui6 : !firrtl.uint<6>
|
|
%9 = firrtl.xor %1, %4 : (!firrtl.uint<6>, !firrtl.uint<6>) -> !firrtl.uint<6>
|
|
firrtl.matchingconnect %b1, %9 : !firrtl.uint<6>
|
|
%10 = firrtl.xor %8, %2 : (!firrtl.uint<6>, !firrtl.uint<6>) -> !firrtl.uint<6>
|
|
firrtl.matchingconnect %b2, %10 : !firrtl.uint<6>
|
|
%11 = firrtl.xor %7, %5 : (!firrtl.uint<6>, !firrtl.uint<6>) -> !firrtl.uint<6>
|
|
firrtl.matchingconnect %b3, %11 : !firrtl.uint<6>
|
|
// CHECK: firrtl.matchingconnect %b1, %c5_ui6 : !firrtl.uint<6>
|
|
// CHECK-NEXT: firrtl.matchingconnect %b2, %c34_ui6 : !firrtl.uint<6>
|
|
// CHECK-NEXT: firrtl.matchingconnect %b3, %c24_ui6 : !firrtl.uint<6>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "BundlePropagation1" {
|
|
// CHECK-LABEL: @BundlePropagation1
|
|
firrtl.module @BundlePropagation1(out %result: !firrtl.uint<3>) {
|
|
%tmp = firrtl.wire : !firrtl.bundle<a: uint<3>, b: uint<3>, c: uint<3>>
|
|
%c1_ui3 = firrtl.constant 1 : !firrtl.uint<3>
|
|
%c2_ui3 = firrtl.constant 2 : !firrtl.uint<3>
|
|
%c4_ui3 = firrtl.constant 4 : !firrtl.uint<3>
|
|
%0 = firrtl.subfield %tmp[a] : !firrtl.bundle<a: uint<3>, b: uint<3>, c: uint<3>>
|
|
%1 = firrtl.subfield %tmp[b] : !firrtl.bundle<a: uint<3>, b: uint<3>, c: uint<3>>
|
|
%2 = firrtl.subfield %tmp[c] : !firrtl.bundle<a: uint<3>, b: uint<3>, c: uint<3>>
|
|
firrtl.matchingconnect %0, %c1_ui3 : !firrtl.uint<3>
|
|
firrtl.matchingconnect %1, %c2_ui3 : !firrtl.uint<3>
|
|
firrtl.matchingconnect %2, %c4_ui3 : !firrtl.uint<3>
|
|
%3 = firrtl.xor %0, %1 : (!firrtl.uint<3>, !firrtl.uint<3>) -> !firrtl.uint<3>
|
|
%4 = firrtl.xor %3, %2 : (!firrtl.uint<3>, !firrtl.uint<3>) -> !firrtl.uint<3>
|
|
firrtl.matchingconnect %result, %4 : !firrtl.uint<3>
|
|
// CHECK: firrtl.matchingconnect %result, %c7_ui3 : !firrtl.uint<3>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "DontTouchAggregate" {
|
|
firrtl.module @DontTouchAggregate(in %clock: !firrtl.clock, out %out1: !firrtl.uint<1>, out %out2: !firrtl.uint<1>) {
|
|
%init = firrtl.wire sym @dntSym: !firrtl.vector<uint<1>, 2>
|
|
%0 = firrtl.subindex %init[0] : !firrtl.vector<uint<1>, 2>
|
|
%1 = firrtl.subindex %init[1] : !firrtl.vector<uint<1>, 2>
|
|
%true = firrtl.constant 1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %0, %true : !firrtl.uint<1>
|
|
firrtl.matchingconnect %1, %true : !firrtl.uint<1>
|
|
|
|
// CHECK: firrtl.matchingconnect %out1, %0 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %out2, %1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %out1, %0 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %out2, %1 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Following tests are ported from normal imconstprop tests.
|
|
|
|
firrtl.circuit "OutPortTop" {
|
|
// Check that we don't propagate througth it.
|
|
firrtl.module @OutPortChild(out %out: !firrtl.vector<uint<1>, 2> sym @dntSym)
|
|
{
|
|
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
|
|
%0 = firrtl.subindex %out[0] : !firrtl.vector<uint<1>, 2>
|
|
%1 = firrtl.subindex %out[1] : !firrtl.vector<uint<1>, 2>
|
|
firrtl.matchingconnect %0, %c0_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %1, %c0_ui1 : !firrtl.uint<1>
|
|
}
|
|
// CHECK-LABEL: firrtl.module @OutPortTop
|
|
firrtl.module @OutPortTop(out %out1: !firrtl.uint<1>, out %out2: !firrtl.uint<1>) {
|
|
%c_out = firrtl.instance c @OutPortChild(out out: !firrtl.vector<uint<1>, 2>)
|
|
%0 = firrtl.subindex %c_out[0] : !firrtl.vector<uint<1>, 2>
|
|
%1 = firrtl.subindex %c_out[1] : !firrtl.vector<uint<1>, 2>
|
|
firrtl.matchingconnect %out1, %0 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %out2, %1 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "InputPortTop" {
|
|
// CHECK-LABEL: firrtl.module private @InputPortChild2
|
|
firrtl.module private @InputPortChild2(in %in0: !firrtl.bundle<v: uint<1>>, in %in1: !firrtl.bundle<v: uint<1>>, out %out: !firrtl.bundle<v: uint<1>>) {
|
|
// CHECK: firrtl.and %0, %c1_ui1
|
|
%0 = firrtl.subfield %in1[v] : !firrtl.bundle<v: uint<1>>
|
|
%1 = firrtl.subfield %in0[v] : !firrtl.bundle<v: uint<1>>
|
|
%2 = firrtl.subfield %out[v] : !firrtl.bundle<v: uint<1>>
|
|
%3 = firrtl.and %1, %0 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
firrtl.matchingconnect %2, %3 : !firrtl.uint<1>
|
|
}
|
|
// CHECK-LABEL: firrtl.module private @InputPortChild
|
|
firrtl.module private @InputPortChild(in %in0: !firrtl.bundle<v: uint<1>>,
|
|
in %in1: !firrtl.bundle<v: uint<1>> sym @dntSym,
|
|
out %out: !firrtl.bundle<v: uint<1>>)
|
|
{
|
|
// CHECK: firrtl.and %1, %0
|
|
%0 = firrtl.subfield %in1[v] : !firrtl.bundle<v: uint<1>>
|
|
%1 = firrtl.subfield %in0[v] : !firrtl.bundle<v: uint<1>>
|
|
%2 = firrtl.subfield %out[v] : !firrtl.bundle<v: uint<1>>
|
|
%3 = firrtl.and %1, %0 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
firrtl.matchingconnect %2, %3 : !firrtl.uint<1>
|
|
}
|
|
|
|
// CHECK-LABEL: firrtl.module @InputPortTop
|
|
firrtl.module @InputPortTop(in %x: !firrtl.bundle<v: uint<1>>, out %z: !firrtl.bundle<v: uint<1>>, out %z2: !firrtl.bundle<v: uint<1>>) {
|
|
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
|
|
%0 = firrtl.subfield %z2[v] : !firrtl.bundle<v: uint<1>>
|
|
%1 = firrtl.subfield %x[v] : !firrtl.bundle<v: uint<1>>
|
|
%2 = firrtl.subfield %z[v] : !firrtl.bundle<v: uint<1>>
|
|
%c_in0, %c_in1, %c_out = firrtl.instance c @InputPortChild(in in0: !firrtl.bundle<v: uint<1>>, in in1: !firrtl.bundle<v: uint<1>>, out out: !firrtl.bundle<v: uint<1>>)
|
|
%3 = firrtl.subfield %c_in1[v] : !firrtl.bundle<v: uint<1>>
|
|
%4 = firrtl.subfield %c_in0[v] : !firrtl.bundle<v: uint<1>>
|
|
%5 = firrtl.subfield %c_out[v] : !firrtl.bundle<v: uint<1>>
|
|
%c2_in0, %c2_in1, %c2_out = firrtl.instance c2 @InputPortChild2(in in0: !firrtl.bundle<v: uint<1>>, in in1: !firrtl.bundle<v: uint<1>>, out out: !firrtl.bundle<v: uint<1>>)
|
|
%6 = firrtl.subfield %c2_in1[v] : !firrtl.bundle<v: uint<1>>
|
|
%7 = firrtl.subfield %c2_in0[v] : !firrtl.bundle<v: uint<1>>
|
|
%8 = firrtl.subfield %c2_out[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %2, %5 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %4, %1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %3, %c1_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %0, %8 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %7, %1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %6, %c1_ui1 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: firrtl.circuit "rhs_sink_output_used_as_wire"
|
|
// This test checks that an output port sink, used as a RHS of a connect, is not
|
|
// optimized away. This is similar to the oscillator tests above, but more
|
|
// reduced. See:
|
|
// - https://github.com/llvm/circt/issues/1488
|
|
//
|
|
firrtl.circuit "rhs_sink_output_used_as_wire" {
|
|
// CHECK-LABEL: firrtl.module private @Bar
|
|
firrtl.module private @Bar(in %a: !firrtl.bundle<v: uint<1>>, in %b: !firrtl.bundle<v: uint<1>>, out %c: !firrtl.bundle<v: uint<1>>, out %d: !firrtl.bundle<v: uint<1>>) {
|
|
%0 = firrtl.subfield %d[v] : !firrtl.bundle<v: uint<1>>
|
|
%1 = firrtl.subfield %a[v] : !firrtl.bundle<v: uint<1>>
|
|
%2 = firrtl.subfield %b[v] : !firrtl.bundle<v: uint<1>>
|
|
%3 = firrtl.subfield %c[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %3, %2 : !firrtl.uint<1>
|
|
%_c = firrtl.wire : !firrtl.bundle<v: uint<1>>
|
|
%4 = firrtl.subfield %_c[v] : !firrtl.bundle<v: uint<1>>
|
|
%5 = firrtl.xor %1, %3 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
|
|
firrtl.matchingconnect %4, %5 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %0, %4 : !firrtl.uint<1>
|
|
}
|
|
|
|
// CHECK-LABEL: firrtl.module @rhs_sink_output_used_as_wire
|
|
firrtl.module @rhs_sink_output_used_as_wire(in %a: !firrtl.bundle<v: uint<1>>, in %b: !firrtl.bundle<v: uint<1>>, out %c: !firrtl.bundle<v: uint<1>>, out %d: !firrtl.bundle<v: uint<1>>) {
|
|
%bar_a, %bar_b, %bar_c, %bar_d = firrtl.instance bar @Bar(in a: !firrtl.bundle<v: uint<1>>, in b: !firrtl.bundle<v: uint<1>>, out c: !firrtl.bundle<v: uint<1>>, out d: !firrtl.bundle<v: uint<1>>)
|
|
%0 = firrtl.subfield %a[v] : !firrtl.bundle<v: uint<1>>
|
|
%1 = firrtl.subfield %bar_a[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %1, %0 : !firrtl.uint<1>
|
|
%2 = firrtl.subfield %b[v] : !firrtl.bundle<v: uint<1>>
|
|
%3 = firrtl.subfield %bar_b[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %3, %2 : !firrtl.uint<1>
|
|
%4 = firrtl.subfield %bar_c[v] : !firrtl.bundle<v: uint<1>>
|
|
%5 = firrtl.subfield %c[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %5, %4 : !firrtl.uint<1>
|
|
%6 = firrtl.subfield %bar_d[v] : !firrtl.bundle<v: uint<1>>
|
|
%7 = firrtl.subfield %d[v] : !firrtl.bundle<v: uint<1>>
|
|
firrtl.matchingconnect %7, %6 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
firrtl.circuit "dntOutput" {
|
|
// CHECK-LABEL: firrtl.module @dntOutput
|
|
// CHECK: %[[INT_B_V:.+]] = firrtl.subfield %int_b[v] : !firrtl.bundle<v: uint<3>>
|
|
// CHECK-NEXT: %[[MUX:.+]] = firrtl.mux(%c, %[[INT_B_V]], %c2_ui3)
|
|
firrtl.module @dntOutput(out %b: !firrtl.bundle<v: uint<3>>, in %c: !firrtl.uint<1>) {
|
|
%c2_ui3 = firrtl.constant 2 : !firrtl.uint<3>
|
|
%0 = firrtl.subfield %b[v] : !firrtl.bundle<v: uint<3>>
|
|
%int_b = firrtl.instance int @foo(out b: !firrtl.bundle<v: uint<3>>)
|
|
%1 = firrtl.subfield %int_b[v] : !firrtl.bundle<v: uint<3>>
|
|
%2 = firrtl.mux(%c, %1, %c2_ui3) : (!firrtl.uint<1>, !firrtl.uint<3>, !firrtl.uint<3>) -> !firrtl.uint<3>
|
|
firrtl.matchingconnect %0, %2 : !firrtl.uint<3>
|
|
}
|
|
firrtl.module private @foo(out %b: !firrtl.bundle<v: uint<3>> sym @dntSym1){
|
|
%c1_ui3 = firrtl.constant 1 : !firrtl.uint<3>
|
|
%0 = firrtl.subfield %b[v] : !firrtl.bundle<v: uint<3>>
|
|
firrtl.matchingconnect %0, %c1_ui3 : !firrtl.uint<3>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "Issue4369" {
|
|
// CHECK-LABEL: firrtl.module private @Bar
|
|
firrtl.module private @Bar(in %in: !firrtl.vector<uint<1>, 1>, out %out: !firrtl.uint<1>) {
|
|
%0 = firrtl.subindex %in[0] : !firrtl.vector<uint<1>, 1>
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
// CHECK: firrtl.matchingconnect %a, %0
|
|
// CHECK-NEXT: firrtl.matchingconnect %out, %a
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %out, %a : !firrtl.uint<1>
|
|
}
|
|
firrtl.module @Issue4369(in %a_0: !firrtl.uint<1>, out %b: !firrtl.uint<1>) {
|
|
%bar_in, %bar_out = firrtl.instance bar @Bar(in in: !firrtl.vector<uint<1>, 1>, out out: !firrtl.uint<1>)
|
|
%0 = firrtl.subindex %bar_in[0] : !firrtl.vector<uint<1>, 1>
|
|
firrtl.matchingconnect %0, %a_0 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %b, %bar_out : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
firrtl.circuit "AggregateConstant" {
|
|
// CHECK-LABEL: AggregateConstant
|
|
firrtl.module @AggregateConstant(out %out: !firrtl.uint<1>) {
|
|
%0 = firrtl.aggregateconstant [0 : ui1, 1 : ui1] : !firrtl.vector<uint<1>, 2>
|
|
%w = firrtl.wire : !firrtl.vector<uint<1>, 2>
|
|
%1 = firrtl.subindex %w[1] : !firrtl.vector<uint<1>, 2>
|
|
firrtl.matchingconnect %out, %1 : !firrtl.uint<1>
|
|
// CHECK: firrtl.matchingconnect %out, %c1_ui1
|
|
firrtl.matchingconnect %w, %0 : !firrtl.vector<uint<1>, 2>
|
|
}
|
|
}
|