circt/test/Dialect/FIRRTL/imconstprop.mlir

953 lines
41 KiB
MLIR

// RUN: circt-opt -pass-pipeline='builtin.module(firrtl.circuit(firrtl-imconstprop))' --split-input-file %s | FileCheck %s
firrtl.circuit "Test" {
// CHECK-LABEL: @PassThrough
// CHECK: (in %source: !firrtl.uint<1>, out %dest: !firrtl.uint<1>)
firrtl.module private @PassThrough(in %source: !firrtl.uint<1>, out %dest: !firrtl.uint<1>) {
// CHECK-NEXT: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%dontTouchWire = firrtl.wire sym @a1 : !firrtl.uint<1>
// CHECK-NEXT: %dontTouchWire = firrtl.wire
firrtl.matchingconnect %dontTouchWire, %source : !firrtl.uint<1>
// CHECK-NEXT: firrtl.matchingconnect %dontTouchWire, %c0_ui1
// CHECK-NEXT: firrtl.matchingconnect %dest, %dontTouchWire
firrtl.matchingconnect %dest, %dontTouchWire : !firrtl.uint<1>
// CHECK-NEXT: }
}
// CHECK-LABEL: @Test
firrtl.module @Test(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>,
out %result1: !firrtl.uint<1>,
out %result2: !firrtl.clock,
out %result3: !firrtl.uint<1>,
out %result4: !firrtl.uint<1>,
out %result5: !firrtl.uint<2>,
out %result6: !firrtl.uint<2>,
out %result7: !firrtl.uint<4>,
out %result8: !firrtl.uint<4>,
out %result9: !firrtl.uint<2>) {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%c0_ui2 = firrtl.constant 0 : !firrtl.uint<2>
%c0_ui4 = firrtl.constant 0 : !firrtl.uint<4>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
// Trivial wire constant propagation.
%someWire = firrtl.wire interesting_name : !firrtl.uint<1>
firrtl.matchingconnect %someWire, %c0_ui1 : !firrtl.uint<1>
// CHECK: %someWire = firrtl.wire
// CHECK: firrtl.matchingconnect %someWire, %c0_ui1
// CHECK: firrtl.matchingconnect %result1, %c0_ui1
firrtl.matchingconnect %result1, %someWire : !firrtl.uint<1>
// Trivial wire special constant propagation.
%c0_clock = firrtl.specialconstant 0 : !firrtl.clock
%clockWire = firrtl.wire interesting_name : !firrtl.clock
firrtl.matchingconnect %clockWire, %c0_clock : !firrtl.clock
// CHECK: %clockWire = firrtl.wire
// CHECK: firrtl.matchingconnect %clockWire, %c0_clock
// CHECK: firrtl.matchingconnect %result2, %c0_clock
firrtl.matchingconnect %result2, %clockWire : !firrtl.clock
// Not a constant.
%nonconstWire = firrtl.wire : !firrtl.uint<1>
firrtl.matchingconnect %nonconstWire, %c0_ui1 : !firrtl.uint<1>
firrtl.matchingconnect %nonconstWire, %c1_ui1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %result3, %nonconstWire
firrtl.matchingconnect %result3, %nonconstWire : !firrtl.uint<1>
// Constant propagation through instance.
%source, %dest = firrtl.instance "" sym @dm21 @PassThrough(in source: !firrtl.uint<1>, out dest: !firrtl.uint<1>)
// CHECK: firrtl.matchingconnect %inst_source, %c0_ui1
firrtl.matchingconnect %source, %c0_ui1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %result4, %inst_dest
firrtl.matchingconnect %result4, %dest : !firrtl.uint<1>
// Check connect extensions.
%extWire = firrtl.wire : !firrtl.uint<2>
firrtl.matchingconnect %extWire, %c0_ui2 : !firrtl.uint<2>
// Connects of invalid values should hurt.
%invalid = firrtl.invalidvalue : !firrtl.uint<2>
firrtl.matchingconnect %extWire, %invalid : !firrtl.uint<2>
// CHECK-NOT: firrtl.matchingconnect %result5, %c0_ui2
firrtl.matchingconnect %result5, %extWire: !firrtl.uint<2>
// Constant propagation through instance.
firrtl.instance ReadMem @ReadMem()
}
// Unused modules should NOT be completely dropped.
// https://github.com/llvm/circt/issues/1236
// CHECK-LABEL: @UnusedModule(in %source: !firrtl.uint<1>, out %dest: !firrtl.uint<1>)
firrtl.module private @UnusedModule(in %source: !firrtl.uint<1>, out %dest: !firrtl.uint<1>) {
// CHECK-NEXT: firrtl.matchingconnect %dest, %source
firrtl.matchingconnect %dest, %source : !firrtl.uint<1>
// CHECK-NEXT: }
}
// CHECK-LABEL: ReadMem
firrtl.module private @ReadMem() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<4>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%0 = firrtl.mem Undefined {depth = 16 : i64, name = "ReadMemory", portNames = ["read0"], readLatency = 1 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: sint<8>>
%1 = firrtl.subfield %0[data] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: sint<8>>
%2 = firrtl.subfield %0[addr] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: sint<8>>
firrtl.matchingconnect %2, %c0_ui1 : !firrtl.uint<4>
%3 = firrtl.subfield %0[en] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: sint<8>>
firrtl.matchingconnect %3, %c1_ui1 : !firrtl.uint<1>
%4 = firrtl.subfield %0[clk] : !firrtl.bundle<addr: uint<4>, en: uint<1>, clk: clock, data flip: sint<8>>
}
}
// -----
// CHECK-LABEL: firrtl.module @Issue1188
// https://github.com/llvm/circt/issues/1188
// Make sure that we handle recursion through muxes correctly.
firrtl.circuit "Issue1188" {
firrtl.module @Issue1188(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>, out %io_out: !firrtl.uint<6>, out %io_out3: !firrtl.uint<3>) {
%c1_ui6 = firrtl.constant 1 : !firrtl.uint<6>
%D0123456 = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<6>
%0 = firrtl.bits %D0123456 4 to 0 : (!firrtl.uint<6>) -> !firrtl.uint<5>
%1 = firrtl.bits %D0123456 5 to 5 : (!firrtl.uint<6>) -> !firrtl.uint<1>
%2 = firrtl.cat %0, %1 : (!firrtl.uint<5>, !firrtl.uint<1>) -> !firrtl.uint<6>
%3 = firrtl.bits %D0123456 4 to 4 : (!firrtl.uint<6>) -> !firrtl.uint<1>
%4 = firrtl.xor %2, %3 : (!firrtl.uint<6>, !firrtl.uint<1>) -> !firrtl.uint<6>
%5 = firrtl.bits %D0123456 1 to 1 : (!firrtl.uint<6>) -> !firrtl.uint<1>
%6 = firrtl.bits %D0123456 3 to 3 : (!firrtl.uint<6>) -> !firrtl.uint<1>
%7 = firrtl.cat %5, %6 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
%8 = firrtl.cat %7, %1 : (!firrtl.uint<2>, !firrtl.uint<1>) -> !firrtl.uint<3>
firrtl.matchingconnect %io_out, %D0123456 : !firrtl.uint<6>
firrtl.matchingconnect %io_out3, %8 : !firrtl.uint<3>
// CHECK: firrtl.mux(%reset, %c1_ui6, %4)
%9 = firrtl.mux(%reset, %c1_ui6, %4) : (!firrtl.uint<1>, !firrtl.uint<6>, !firrtl.uint<6>) -> !firrtl.uint<6>
firrtl.matchingconnect %D0123456, %9 : !firrtl.uint<6>
}
}
// -----
// DontTouch annotation should block constant propagation.
firrtl.circuit "testDontTouch" {
// CHECK-LABEL: firrtl.module private @blockProp
firrtl.module private @blockProp1(in %clock: !firrtl.clock,
in %a: !firrtl.uint<1> sym @dntSym, out %b: !firrtl.uint<1>){
//CHECK: %c = firrtl.reg
%c = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
firrtl.matchingconnect %c, %a : !firrtl.uint<1>
firrtl.matchingconnect %b, %c : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module private @allowProp
firrtl.module private @allowProp(in %clock: !firrtl.clock, in %a: !firrtl.uint<1>, out %b: !firrtl.uint<1>) {
// CHECK: [[CONST:%.+]] = firrtl.constant 1 : !firrtl.uint<1>
%c = firrtl.wire : !firrtl.uint<1>
firrtl.matchingconnect %c, %a : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, [[CONST]]
firrtl.matchingconnect %b, %c : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module private @blockProp3
firrtl.module private @blockProp3(in %clock: !firrtl.clock, in %a: !firrtl.uint<1> , out %b: !firrtl.uint<1>) {
//CHECK: %c = firrtl.reg
%c = firrtl.reg sym @s2 %clock : !firrtl.clock, !firrtl.uint<1>
firrtl.matchingconnect %c, %a : !firrtl.uint<1>
firrtl.matchingconnect %b, %c : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module @testDontTouch
firrtl.module @testDontTouch(in %clock: !firrtl.clock, out %a: !firrtl.uint<1>, out %a1: !firrtl.uint<1>, out %a2: !firrtl.uint<1>) {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%blockProp1_clock, %blockProp1_a, %blockProp1_b = firrtl.instance blockProp1 sym @a1 @blockProp1(in clock: !firrtl.clock, in a: !firrtl.uint<1>, out b: !firrtl.uint<1>)
%allowProp_clock, %allowProp_a, %allowProp_b = firrtl.instance allowProp sym @a2 @allowProp(in clock: !firrtl.clock, in a: !firrtl.uint<1>, out b: !firrtl.uint<1>)
%blockProp3_clock, %blockProp3_a, %blockProp3_b = firrtl.instance blockProp3 sym @a3 @blockProp3(in clock: !firrtl.clock, in a: !firrtl.uint<1>, out b: !firrtl.uint<1>)
firrtl.matchingconnect %blockProp1_clock, %clock : !firrtl.clock
firrtl.matchingconnect %allowProp_clock, %clock : !firrtl.clock
firrtl.matchingconnect %blockProp3_clock, %clock : !firrtl.clock
firrtl.matchingconnect %blockProp1_a, %c1_ui1 : !firrtl.uint<1>
firrtl.matchingconnect %allowProp_a, %c1_ui1 : !firrtl.uint<1>
firrtl.matchingconnect %blockProp3_a, %c1_ui1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %a, %blockProp1_b
firrtl.matchingconnect %a, %blockProp1_b : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %a1, %c
firrtl.matchingconnect %a1, %allowProp_b : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %a2, %blockProp3_b
firrtl.matchingconnect %a2, %blockProp3_b : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module @CheckNode
firrtl.module @CheckNode(out %x: !firrtl.uint<1>, out %y: !firrtl.uint<1>, out %z: !firrtl.uint<1>) {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
// CHECK-NOT: %d1 = firrtl.node
%d1 = firrtl.node droppable_name %c1_ui1 : !firrtl.uint<1>
// CHECK: %d2 = firrtl.node
%d2 = firrtl.node interesting_name %c1_ui1 : !firrtl.uint<1>
// CHECK: %d3 = firrtl.node
%d3 = firrtl.node sym @s2 %c1_ui1: !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %x, %c1_ui1
firrtl.matchingconnect %x, %d1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %y, %c1_ui1
firrtl.matchingconnect %y, %d2 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %z, %d3
firrtl.matchingconnect %z, %d3 : !firrtl.uint<1>
}
}
// -----
firrtl.circuit "OutPortTop" {
firrtl.module private @OutPortChild1(out %out: !firrtl.uint<1> sym @dntSym1) {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.matchingconnect %out, %c0_ui1 : !firrtl.uint<1>
}
firrtl.module private @OutPortChild2(out %out: !firrtl.uint<1>) {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.matchingconnect %out, %c0_ui1 : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module @OutPortTop
firrtl.module @OutPortTop(in %x: !firrtl.uint<1>, out %zc: !firrtl.uint<1>, out %zn: !firrtl.uint<1>) {
// CHECK: %c0_ui1 = firrtl.constant 0
%c_out = firrtl.instance c sym @a2 @OutPortChild1(out out: !firrtl.uint<1>)
%c_out_0 = firrtl.instance c sym @a1 @OutPortChild2(out out: !firrtl.uint<1>)
// CHECK: %0 = firrtl.and %x, %c_out
%0 = firrtl.and %x, %c_out : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
%1 = firrtl.and %x, %c_out_0 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %zn, %0
firrtl.matchingconnect %zn, %0 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %zc, %c0_ui1
firrtl.matchingconnect %zc, %1 : !firrtl.uint<1>
}
}
// -----
firrtl.circuit "InputPortTop" {
// CHECK-LABEL: firrtl.module private @InputPortChild2
firrtl.module private @InputPortChild2(in %in0: !firrtl.uint<1>, in %in1: !firrtl.uint<1>, out %out: !firrtl.uint<1>) {
// CHECK: = firrtl.constant 1
%0 = firrtl.and %in0, %in1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %out, %0 : !firrtl.uint<1>
}
// CHECK-LABEL: firrtl.module private @InputPortChild
firrtl.module private @InputPortChild(in %in0: !firrtl.uint<1>,
in %in1 : !firrtl.uint<1> sym @dntSym1, out %out: !firrtl.uint<1>) {
// CHECK: %0 = firrtl.and %in0, %in1
%0 = firrtl.and %in0, %in1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %out, %0 : !firrtl.uint<1>
}
firrtl.module @InputPortTop(in %x: !firrtl.uint<1>, out %z: !firrtl.uint<1>, out %z2: !firrtl.uint<1>) {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%c_in0, %c_in1, %c_out = firrtl.instance c @InputPortChild(in in0: !firrtl.uint<1>, in in1: !firrtl.uint<1>, out out: !firrtl.uint<1>)
%c2_in0, %c2_in1, %c2_out = firrtl.instance c2 @InputPortChild2(in in0: !firrtl.uint<1>, in in1: !firrtl.uint<1>, out out: !firrtl.uint<1>)
firrtl.matchingconnect %z, %c_out : !firrtl.uint<1>
firrtl.matchingconnect %c_in0, %x : !firrtl.uint<1>
firrtl.matchingconnect %c_in1, %c1_ui1 : !firrtl.uint<1>
firrtl.matchingconnect %z2, %c2_out : !firrtl.uint<1>
firrtl.matchingconnect %c2_in0, %x : !firrtl.uint<1>
firrtl.matchingconnect %c2_in1, %c1_ui1 : !firrtl.uint<1>
}
}
// -----
firrtl.circuit "InstanceOut" {
firrtl.extmodule private @Ext(in a: !firrtl.uint<1>)
// CHECK-LABEL: firrtl.module @InstanceOut
firrtl.module @InstanceOut(in %a: !firrtl.uint<1>, out %b: !firrtl.uint<1>) {
%ext_a = firrtl.instance ext @Ext(in a: !firrtl.uint<1>)
firrtl.matchingconnect %ext_a, %a : !firrtl.uint<1>
%w = firrtl.wire : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %w, %ext_a : !firrtl.uint<1>
firrtl.matchingconnect %w, %ext_a : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, %w : !firrtl.uint<1>
firrtl.matchingconnect %b, %w : !firrtl.uint<1>
}
}
// -----
firrtl.circuit "InstanceOut2" {
firrtl.module private @Ext(in %a: !firrtl.uint<1>) {
}
// CHECK-LABEL: firrtl.module @InstanceOut2
firrtl.module @InstanceOut2(in %a: !firrtl.uint<1>, out %b: !firrtl.uint<1>) {
%ext_a = firrtl.instance ext @Ext(in a: !firrtl.uint<1>)
firrtl.matchingconnect %ext_a, %a : !firrtl.uint<1>
%w = firrtl.wire : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %w, %ext_a : !firrtl.uint<1>
firrtl.matchingconnect %w, %ext_a : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, %w : !firrtl.uint<1>
firrtl.matchingconnect %b, %w : !firrtl.uint<1>
}
}
// -----
firrtl.circuit "invalidReg1" {
// CHECK-LABEL: @invalidReg1
firrtl.module @invalidReg1(in %clock: !firrtl.clock, out %a: !firrtl.uint<1>) {
%foobar = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
//CHECK: %0 = firrtl.not %foobar : (!firrtl.uint<1>) -> !firrtl.uint<1>
%0 = firrtl.not %foobar : (!firrtl.uint<1>) -> !firrtl.uint<1>
//CHECK: firrtl.matchingconnect %foobar, %0 : !firrtl.uint<1>
firrtl.matchingconnect %foobar, %0 : !firrtl.uint<1>
//CHECK: firrtl.matchingconnect %a, %foobar : !firrtl.uint<1>
firrtl.matchingconnect %a, %foobar : !firrtl.uint<1>
}
}
// -----
// This test is checking the behavior of a RegOp, "r", and a RegResetOp, "s",
// that are combinationally connected to themselves through simple and weird
// formulations. In all cases it should NOT be optimized away. For more discussion, see:
// - https://github.com/llvm/circt/issues/1465
// - https://github.com/llvm/circt/issues/1466
// - https://github.com/llvm/circt/issues/1478
//
// CHECK-LABEL: "Oscillators"
firrtl.circuit "Oscillators" {
// CHECK: firrtl.module private @Foo
firrtl.module private @Foo(in %clock: !firrtl.clock, in %reset: !firrtl.asyncreset, out %a: !firrtl.uint<1>) {
// CHECK: firrtl.reg
%r = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: firrtl.regreset
%s = firrtl.regreset %clock, %reset, %c0_ui1 : !firrtl.clock, !firrtl.asyncreset, !firrtl.uint<1>, !firrtl.uint<1>
%0 = firrtl.not %r : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %r, %0 : !firrtl.uint<1>
%1 = firrtl.not %s : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %s, %1 : !firrtl.uint<1>
%2 = firrtl.or %r, %s : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %a, %2 : !firrtl.uint<1>
}
// CHECK: firrtl.module private @Bar
firrtl.module private @Bar(in %clock: !firrtl.clock, in %reset: !firrtl.asyncreset, out %a: !firrtl.uint<1>) {
// CHECK: %r = firrtl.reg
%r = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: firrtl.regreset
%s = firrtl.regreset %clock, %reset, %c0_ui1 : !firrtl.clock, !firrtl.asyncreset, !firrtl.uint<1>, !firrtl.uint<1>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%0 = firrtl.xor %a, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %r, %0 : !firrtl.uint<1>
%1 = firrtl.xor %a, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %s, %1 : !firrtl.uint<1>
%2 = firrtl.or %r, %s : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %a, %2 : !firrtl.uint<1>
}
// CHECK: firrtl.module private @Baz
firrtl.module private @Baz(in %clock: !firrtl.clock, in %reset: !firrtl.asyncreset, out %a: !firrtl.uint<1>) {
// CHECK: firrtl.reg
%r = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: firrtl.regreset
%s = firrtl.regreset %clock, %reset, %c0_ui1 : !firrtl.clock, !firrtl.asyncreset, !firrtl.uint<1>, !firrtl.uint<1>
%0 = firrtl.not %a : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %r, %0 : !firrtl.uint<1>
%1 = firrtl.not %a : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %s, %1 : !firrtl.uint<1>
%2 = firrtl.or %r, %s : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %a, %2 : !firrtl.uint<1>
}
firrtl.extmodule @Ext(in a: !firrtl.uint<1>)
// CHECK: firrtl.module private @Qux
firrtl.module private @Qux(in %clock: !firrtl.clock, in %reset: !firrtl.asyncreset, out %a: !firrtl.uint<1>) {
%ext_a = firrtl.instance ext @Ext(in a: !firrtl.uint<1>)
// CHECK: firrtl.reg
%r = firrtl.reg %clock : !firrtl.clock, !firrtl.uint<1>
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: firrtl.regreset
%s = firrtl.regreset %clock, %reset, %c0_ui1 : !firrtl.clock, !firrtl.asyncreset, !firrtl.uint<1>, !firrtl.uint<1>
%0 = firrtl.not %ext_a : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %r, %0 : !firrtl.uint<1>
%1 = firrtl.not %ext_a : (!firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %s, %1 : !firrtl.uint<1>
%2 = firrtl.or %r, %s : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %ext_a, %2 : !firrtl.uint<1>
firrtl.matchingconnect %a, %ext_a : !firrtl.uint<1>
}
firrtl.module @Oscillators(in %clock: !firrtl.clock, in %reset: !firrtl.asyncreset, out %foo_a: !firrtl.uint<1>, out %bar_a: !firrtl.uint<1>, out %baz_a: !firrtl.uint<1>, out %qux_a: !firrtl.uint<1>) {
%foo_clock, %foo_reset, %foo_a_0 = firrtl.instance foo @Foo(in clock: !firrtl.clock, in reset: !firrtl.asyncreset, out a: !firrtl.uint<1>)
firrtl.matchingconnect %foo_clock, %clock : !firrtl.clock
firrtl.matchingconnect %foo_reset, %reset : !firrtl.asyncreset
firrtl.matchingconnect %foo_a, %foo_a_0 : !firrtl.uint<1>
%bar_clock, %bar_reset, %bar_a_1 = firrtl.instance bar @Bar (in clock: !firrtl.clock, in reset: !firrtl.asyncreset, out a: !firrtl.uint<1>)
firrtl.matchingconnect %bar_clock, %clock : !firrtl.clock
firrtl.matchingconnect %bar_reset, %reset : !firrtl.asyncreset
firrtl.matchingconnect %bar_a, %bar_a_1 : !firrtl.uint<1>
%baz_clock, %baz_reset, %baz_a_2 = firrtl.instance baz @Baz(in clock: !firrtl.clock, in reset: !firrtl.asyncreset, out a: !firrtl.uint<1>)
firrtl.matchingconnect %baz_clock, %clock : !firrtl.clock
firrtl.matchingconnect %baz_reset, %reset : !firrtl.asyncreset
firrtl.matchingconnect %baz_a, %baz_a_2 : !firrtl.uint<1>
%qux_clock, %qux_reset, %qux_a_3 = firrtl.instance qux @Qux(in clock: !firrtl.clock, in reset: !firrtl.asyncreset, out a: !firrtl.uint<1>)
firrtl.matchingconnect %qux_clock, %clock : !firrtl.clock
firrtl.matchingconnect %qux_reset, %reset : !firrtl.asyncreset
firrtl.matchingconnect %qux_a, %qux_a_3 : !firrtl.uint<1>
}
}
// -----
// 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
//
// CHECK-LABEL: firrtl.circuit "rhs_sink_output_used_as_wire"
firrtl.circuit "rhs_sink_output_used_as_wire" {
// CHECK: firrtl.module private @Bar
firrtl.module private @Bar(in %a: !firrtl.uint<1>, in %b: !firrtl.uint<1>, out %c: !firrtl.uint<1>, out %d: !firrtl.uint<1>) {
firrtl.matchingconnect %c, %b : !firrtl.uint<1>
%_c = firrtl.wire : !firrtl.uint<1>
// CHECK: firrtl.xor %a, %c
%0 = firrtl.xor %a, %c : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %_c, %0 : !firrtl.uint<1>
firrtl.matchingconnect %d, %_c : !firrtl.uint<1>
}
firrtl.module @rhs_sink_output_used_as_wire(in %a: !firrtl.uint<1>, in %b: !firrtl.uint<1>, out %c: !firrtl.uint<1>, out %d: !firrtl.uint<1>) {
%bar_a, %bar_b, %bar_c, %bar_d = firrtl.instance bar @Bar(in a: !firrtl.uint<1>, in b: !firrtl.uint<1>, out c: !firrtl.uint<1>, out d: !firrtl.uint<1>)
firrtl.matchingconnect %bar_a, %a : !firrtl.uint<1>
firrtl.matchingconnect %bar_b, %b : !firrtl.uint<1>
firrtl.matchingconnect %c, %bar_c : !firrtl.uint<1>
firrtl.matchingconnect %d, %bar_d : !firrtl.uint<1>
}
}
// -----
// issue 1793
// Ensure don't touch on output port is seen by instances
firrtl.circuit "dntOutput" {
// CHECK-LABEL: firrtl.module @dntOutput
// CHECK: %0 = firrtl.mux(%c, %int_b, %c2_ui3)
// CHECK-NEXT: firrtl.matchingconnect %b, %0
firrtl.module @dntOutput(out %b : !firrtl.uint<3>, in %c : !firrtl.uint<1>) {
%const = firrtl.constant 2 : !firrtl.uint<3>
%int_b = firrtl.instance int @foo(out b: !firrtl.uint<3>)
%m = firrtl.mux(%c, %int_b, %const) : (!firrtl.uint<1>, !firrtl.uint<3>, !firrtl.uint<3>) -> !firrtl.uint<3>
firrtl.matchingconnect %b, %m : !firrtl.uint<3>
}
firrtl.module private @foo(out %b: !firrtl.uint<3> sym @dntSym1) {
%const = firrtl.constant 1 : !firrtl.uint<3>
firrtl.matchingconnect %b, %const : !firrtl.uint<3>
}
}
// -----
// An annotation should block removal of a wire, but should not block constant
// folding.
//
// CHECK-LABEL: "AnnotationsBlockRemoval"
firrtl.circuit "AnnotationsBlockRemoval" {
firrtl.module @AnnotationsBlockRemoval(out %b: !firrtl.uint<1>) {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
// CHECK: %w = firrtl.wire
%w = firrtl.wire droppable_name {annotations = [{class = "foo"}]} : !firrtl.uint<1>
firrtl.matchingconnect %w, %c1_ui1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, %c1_ui1
firrtl.matchingconnect %b, %w : !firrtl.uint<1>
}
}
// -----
// CHECK-LABEL: "Issue3372"
firrtl.circuit "Issue3372" {
firrtl.module @Issue3372(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>, out %value: !firrtl.uint<1>) {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%other_zero = firrtl.instance other interesting_name @Other(out zero: !firrtl.uint<1>)
%shared = firrtl.regreset interesting_name %clock, %other_zero, %c1_ui1 : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1>, !firrtl.uint<1>
firrtl.matchingconnect %shared, %shared : !firrtl.uint<1>
%test = firrtl.wire interesting_name : !firrtl.uint<1>
firrtl.matchingconnect %test, %shared : !firrtl.uint<1>
firrtl.matchingconnect %value, %test : !firrtl.uint<1>
}
// CHECK: %other_zero = firrtl.instance other interesting_name @Other(out zero: !firrtl.uint<1>)
// CHECK: %test = firrtl.wire interesting_name : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %value, %test : !firrtl.uint<1>
firrtl.module private @Other(out %zero: !firrtl.uint<1>) {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.matchingconnect %zero, %c0_ui1 : !firrtl.uint<1>
}
}
// -----
// CHECK-LABEL: "SendThroughRef"
firrtl.circuit "SendThroughRef" {
firrtl.module private @Bar(out %_a: !firrtl.probe<uint<1>>) {
%zero = firrtl.constant 0 : !firrtl.uint<1>
%ref_zero = firrtl.ref.send %zero : !firrtl.uint<1>
firrtl.ref.define %_a, %ref_zero : !firrtl.probe<uint<1>>
}
// CHECK: firrtl.matchingconnect %a, %c0_ui1 : !firrtl.uint<1>
firrtl.module @SendThroughRef(out %a: !firrtl.uint<1>) {
%bar_a = firrtl.instance bar @Bar(out _a: !firrtl.probe<uint<1>>)
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
}
}
// -----
// CHECK-LABEL: "ForwardRef"
firrtl.circuit "ForwardRef" {
firrtl.module private @RefForward2(out %_a: !firrtl.probe<uint<1>>) {
%zero = firrtl.constant 0 : !firrtl.uint<1>
%ref_zero = firrtl.ref.send %zero : !firrtl.uint<1>
firrtl.ref.define %_a, %ref_zero : !firrtl.probe<uint<1>>
}
firrtl.module private @RefForward(out %_a: !firrtl.probe<uint<1>>) {
%fwd_2 = firrtl.instance fwd_2 @RefForward2(out _a: !firrtl.probe<uint<1>>)
firrtl.ref.define %_a, %fwd_2 : !firrtl.probe<uint<1>>
}
// CHECK: firrtl.matchingconnect %a, %c0_ui1 : !firrtl.uint<1>
firrtl.module @ForwardRef(out %a: !firrtl.uint<1>) {
%fwd_a = firrtl.instance fwd @RefForward(out _a: !firrtl.probe<uint<1>>)
%0 = firrtl.ref.resolve %fwd_a : !firrtl.probe<uint<1>>
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
}
}
// -----
// Don't prop through a rwprobe ref.
// CHECK-LABEL: "SendThroughRWProbe"
firrtl.circuit "SendThroughRWProbe" {
// CHECK-LABEL: firrtl.module private @Bar
firrtl.module private @Bar(out %rw: !firrtl.rwprobe<uint<1>>, out %out : !firrtl.uint<1>) {
%zero = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %[[N:.+]], %{{.+}} = firrtl.node
// CHECK-SAME: forceable
%n, %n_ref = firrtl.node %zero forceable : !firrtl.uint<1>
// CHECK: firrtl.node %[[N]]
%user = firrtl.node %n : !firrtl.uint<1>
firrtl.matchingconnect %out, %user : !firrtl.uint<1>
firrtl.ref.define %rw, %n_ref : !firrtl.rwprobe<uint<1>>
}
// CHECK: firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
firrtl.module @SendThroughRWProbe(out %a: !firrtl.uint<1>, out %out: !firrtl.uint<1>) {
%bar_rw, %bar_out = firrtl.instance bar @Bar(out rw: !firrtl.rwprobe<uint<1>>, out out: !firrtl.uint<1>)
firrtl.matchingconnect %out, %bar_out : !firrtl.uint<1>
%0 = firrtl.ref.resolve %bar_rw : !firrtl.rwprobe<uint<1>>
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
}
}
// -----
// Should not crash when there are properties.
// CHECK-LABEL: firrtl.circuit "Properties"
firrtl.circuit "Properties" {
firrtl.module @Properties(in %in : !firrtl.string, out %out : !firrtl.string) {
firrtl.propassign %out, %in : !firrtl.string
}
}
// -----
// Verbatim expressions should not be optimized away.
firrtl.circuit "Verbatim" {
firrtl.module @Verbatim() {
// CHECK: %[[v0:.+]] = firrtl.verbatim.expr
%0 = firrtl.verbatim.expr "random.something" : () -> !firrtl.uint<1>
// CHECK: %tap = firrtl.wire : !firrtl.uint<1>
%tap = firrtl.wire : !firrtl.uint<1>
%fizz = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<1>
firrtl.matchingconnect %fizz, %tap : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %tap, %[[v0]] : !firrtl.uint<1>
firrtl.matchingconnect %tap, %0 : !firrtl.uint<1>
// CHECK: firrtl.verbatim.wire "randomBar.b"
%1 = firrtl.verbatim.wire "randomBar.b" : () -> !firrtl.uint<1> {symbols = []}
// CHECK: %tap2 = firrtl.wire : !firrtl.uint<1>
%tap2 = firrtl.wire : !firrtl.uint<1>
firrtl.matchingconnect %tap2, %1 : !firrtl.uint<1>
}
}
// -----
// This test is only checking that IMCP doesn't generate invalid IR. IMCP needs
// to delete the matchingconnect instead of replacing its destination with an
// invalid value that will replace the register. For more information, see:
// - https://github.com/llvm/circt/issues/4498
//
// CHECK-LABEL: "Issue4498"
firrtl.circuit "Issue4498" {
firrtl.module @Issue4498(in %clock: !firrtl.clock) {
%a = firrtl.wire : !firrtl.uint<1>
%r = firrtl.reg interesting_name %clock : !firrtl.clock, !firrtl.uint<1>
firrtl.matchingconnect %r, %a : !firrtl.uint<1>
}
}
// -----
// An ordering dependnecy crept in with unwritten. Check that it's gone
// CHECK-LABEL: "Ordering"
firrtl.circuit "Ordering" {
firrtl.module public @Ordering(out %b: !firrtl.uint<1>) {
%0 = firrtl.wire : !firrtl.uint<1>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
firrtl.matchingconnect %0, %c1_ui1 : !firrtl.uint<1>
%1 = firrtl.xor %0, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<1>
firrtl.matchingconnect %b, %1 : !firrtl.uint<1>
}
// CHECK: firrtl.matchingconnect %b, %c0_ui1
}
// -----
// Checking that plusargs intrinsics are properly marked overdefined in IMCP,
// see:
// - https://github.com/llvm/circt/issues/5722
//
// CHECK-LABEL: "Issue5722Test"
firrtl.circuit "Issue5722Test" {
firrtl.module @Issue5722Test(out %a: !firrtl.uint<1>) {
%b = firrtl.wire : !firrtl.uint<1>
%0 = firrtl.int.plusargs.test "parg"
firrtl.matchingconnect %b, %0 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, %0
firrtl.matchingconnect %a, %b : !firrtl.uint<1>
}
}
// CHECK-LABEL: "Issue5722Value"
firrtl.circuit "Issue5722Value" {
firrtl.module @Issue5722Value(out %a: !firrtl.uint<1>, out %v: !firrtl.uint<32>) {
%b = firrtl.wire : !firrtl.uint<1>
%c = firrtl.wire : !firrtl.uint<32>
%0:2 = firrtl.int.plusargs.value "parg" : !firrtl.uint<32>
firrtl.matchingconnect %b, %0#0 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %b, %0#0
firrtl.matchingconnect %c, %0#1 : !firrtl.uint<32>
// CHECK: firrtl.matchingconnect %c, %0#1
firrtl.matchingconnect %a, %b : !firrtl.uint<1>
firrtl.matchingconnect %v, %c : !firrtl.uint<32>
}
}
// -----
// Check const prop of basic properties.
// CHECK-LABEL: "PropPassthruTest"
firrtl.circuit "PropPassthruTest" {
firrtl.module private @Passthru(in %intIn: !firrtl.integer,
out %intOut: !firrtl.integer,
in %boolIn: !firrtl.bool,
out %boolOut: !firrtl.bool,
in %strIn: !firrtl.string,
out %strOut: !firrtl.string) {
firrtl.propassign %intOut, %intIn : !firrtl.integer
firrtl.propassign %boolOut, %boolIn : !firrtl.bool
firrtl.propassign %strOut, %strIn : !firrtl.string
}
firrtl.module @PropPassthruTest(out %intOut: !firrtl.integer,
out %boolOut: !firrtl.bool,
out %strOut: !firrtl.string) {
// CHECK-DAG: %[[BOOL:.+]] = firrtl.bool true
// CHECK-DAG: %[[STRING:.+]] = firrtl.string "hello"
// CHECK-DAG: %[[INT:.+]] = firrtl.integer 123
%0 = firrtl.bool true
%1 = firrtl.string "hello"
%2 = firrtl.integer 123
%passthru_intIn, %passthru_intOut, %passthru_boolIn, %passthru_boolOut, %passthru_strIn, %passthru_strOut = firrtl.instance passthru @Passthru(in intIn: !firrtl.integer, out intOut: !firrtl.integer, in boolIn: !firrtl.bool, out boolOut: !firrtl.bool, in strIn: !firrtl.string, out strOut: !firrtl.string)
firrtl.propassign %passthru_intIn, %2 : !firrtl.integer
firrtl.propassign %passthru_strIn, %1 : !firrtl.string
firrtl.propassign %passthru_boolIn, %0 : !firrtl.bool
// CHECK-DAG: propassign %intOut, %[[INT]]
// CHECK-DAG: propassign %strOut, %[[STRING]]
// CHECK-DAG: propassign %boolOut, %[[BOOL]]
firrtl.propassign %intOut, %passthru_intOut : !firrtl.integer
firrtl.propassign %strOut, %passthru_strOut : !firrtl.string
firrtl.propassign %boolOut, %passthru_boolOut : !firrtl.bool
}
}
// -----
// Check assignments into object fields don't cause errors.
// CHECK-LABEL: "ObjectSubfieldConnect"
firrtl.circuit "ObjectSubfieldConnect" {
firrtl.class private @Test(in %in: !firrtl.integer) {
}
firrtl.module @ObjectSubfieldConnect(in %in: !firrtl.integer) {
%0 = firrtl.object @Test(in in: !firrtl.integer)
%1 = firrtl.object.subfield %0[in] : !firrtl.class<@Test(in in: !firrtl.integer)>
firrtl.propassign %1, %in : !firrtl.integer
}
}
// -----
// Check assignments of objects themselves are handled.
// CHECK-LABEL: "ObjectConnect"
firrtl.circuit "ObjectConnect" {
firrtl.class private @Test() {}
firrtl.module @Passthru(in %in : !firrtl.class<@Test()>,
out %out : !firrtl.class<@Test()>) {
firrtl.propassign %out, %in : !firrtl.class<@Test()>
}
firrtl.module @ObjectConnect(out %out : !firrtl.class<@Test()>) {
%c_in, %c_out = firrtl.instance c @Passthru(in in : !firrtl.class<@Test()>,
out out : !firrtl.class<@Test()>)
%obj = firrtl.object @Test()
firrtl.propassign %c_in, %obj : !firrtl.class<@Test()>
firrtl.propassign %out, %c_out : !firrtl.class<@Test()>
}
}
// -----
// Preserve forceable decl that is dead other than its rwprobe result.
// CHECK-LABEL: "KeepForceable"
firrtl.circuit "KeepForceable" {
firrtl.module @KeepForceable(out %a: !firrtl.rwprobe<uint<1>>) attributes {convention = #firrtl<convention scalarized>} {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%b_c = firrtl.wire : !firrtl.rwprobe<uint<1>>
%d, %d_ref = firrtl.wire forceable : !firrtl.uint<1>, !firrtl.rwprobe<uint<1>>
firrtl.matchingconnect %d, %c0_ui1 : !firrtl.uint<1>
// CHECK-COUNT-2: ref.define
firrtl.ref.define %b_c, %d_ref : !firrtl.rwprobe<uint<1>>
firrtl.ref.define %a, %b_c : !firrtl.rwprobe<uint<1>>
}
}
// -----
// Fix partly deleting non-hw dataflow.
// Issue #6076.
// CHECK-LABEL: "WireProbe"
firrtl.circuit "WireProbe" {
// CHECK: module @WireProbe
firrtl.module @WireProbe(out %p : !firrtl.probe<uint<5>>) {
// CHECK-NEXT: %[[ZERO:.+]] = firrtl.constant 0
// CHECK-NEXT: %[[REF:.+]] = firrtl.ref.send %[[ZERO]]
// CHECK-NEXT: firrtl.ref.define %p, %[[REF]]
// CHECK-NEXT: }
%x = firrtl.constant 0: !firrtl.uint<5>
%0 = firrtl.ref.send %x : !firrtl.uint<5>
%w = firrtl.wire interesting_name : !firrtl.probe<uint<5>>
firrtl.ref.define %w, %0: !firrtl.probe<uint<5>>
firrtl.ref.define %p, %w : !firrtl.probe<uint<5>>
}
}
// -----
// Also for properties that we const-prop.
// Drop connections to, and wires, that are not overdefined.
// CHECK-LABEL: firrtl.circuit "WireProp"
firrtl.circuit "WireProp" {
// CHECK-NOT: firrtl.wire
firrtl.module @WireProp(out %s : !firrtl.string) {
%x = firrtl.string "hello"
%w = firrtl.wire : !firrtl.string
%w2 = firrtl.wire : !firrtl.string
firrtl.propassign %w, %x: !firrtl.string
firrtl.propassign %w2, %w: !firrtl.string
firrtl.propassign %s, %w : !firrtl.string
}
}
// -----
// Check ability to const-prop through declarations (wires, nodes)
// with annotations, but keep them around.
firrtl.circuit "ConstPropAnno" {
firrtl.module @ConstPropAnno(out %val : !firrtl.uint<3>,
out %val2 : !firrtl.uint<3>) {
// CHECK: %[[ZERO:.+]] = firrtl.constant 0
%zero = firrtl.constant 0 : !firrtl.uint<3>
// CHECK: %w = firrtl.wire
%w = firrtl.wire {annotations = [{class = "circt.test"}]} : !firrtl.uint<3>
// CHECK-NOT: firrtl.wire
%w2 = firrtl.wire : !firrtl.uint<3>
firrtl.matchingconnect %w2, %zero : !firrtl.uint<3>
firrtl.matchingconnect %w, %w2 : !firrtl.uint<3>
firrtl.matchingconnect %val, %w : !firrtl.uint<3>
// CHECK: firrtl.node %[[ZERO]]
%n = firrtl.node %w2 {annotations = [{class = "circt.test"}]} : !firrtl.uint<3>
// CHECK-NOT: firrtl.wire
%w3 = firrtl.wire : !firrtl.uint<3>
firrtl.matchingconnect %w3, %n : !firrtl.uint<3>
firrtl.matchingconnect %val2, %w3 : !firrtl.uint<3>
}
}
// -----
// RefSubOp: preserve.
// CHECK-LABEL: "RefSubOp"
firrtl.circuit "RefSubOp" {
firrtl.extmodule private @Ext(out p : !firrtl.probe<vector<uint<32>, 31>>)
firrtl.module @RefSubOp(out %p : !firrtl.probe<uint<32>>) {
// CHECK: firrtl.wire
// CHECK: ref.sub
// CHECK-COUNT-2: firrtl.ref.define
%ext_vec_ref = firrtl.instance e @Ext(out p : !firrtl.probe<vector<uint<32>, 31>>)
%w = firrtl.wire { name = "tap" } : !firrtl.probe<uint<32>>
%ref = firrtl.ref.sub %ext_vec_ref[5] : !firrtl.probe<vector<uint<32>, 31>>
firrtl.ref.define %w, %ref : !firrtl.probe<uint<32>>
firrtl.ref.define %p, %w: !firrtl.probe<uint<32>>
}
}
// -----
// RefSubOp: prop.
// CHECK-LABEL: "RefSubOpPropagate"
firrtl.circuit "RefSubOpPropagate" {
firrtl.module private @Child(out %p : !firrtl.probe<vector<uint<32>, 2>>,
out %w0 : !firrtl.probe<uint<32>>,
out %w1 : !firrtl.probe<uint<32>>) {
// Vector initialized to 123, 321
%w = firrtl.wire : !firrtl.vector<uint<32>, 2>
%v0 = firrtl.subindex %w[0] : !firrtl.vector<uint<32>, 2>
%v1 = firrtl.subindex %w[1] : !firrtl.vector<uint<32>, 2>
%val0 = firrtl.constant 123 : !firrtl.uint<32>
%val1 = firrtl.constant 321 : !firrtl.uint<32>
firrtl.matchingconnect %v0, %val0 : !firrtl.uint<32>
firrtl.matchingconnect %v1, %val1 : !firrtl.uint<32>
// Send out probe of entire vector.
%vec_ref = firrtl.ref.send %w : !firrtl.vector<uint<32>, 2>
firrtl.ref.define %p, %vec_ref : !firrtl.probe<vector<uint<32>, 2>>
// Send out probe of individual elements.
%w0_ref = firrtl.ref.sub %vec_ref[0] : !firrtl.probe<vector<uint<32>, 2>>
%w1_ref = firrtl.ref.sub %vec_ref[1] : !firrtl.probe<vector<uint<32>, 2>>
firrtl.ref.define %w0, %w0_ref : !firrtl.probe<uint<32>>
firrtl.ref.define %w1, %w1_ref : !firrtl.probe<uint<32>>
}
// CHECK: module @RefSubOpPropagate
firrtl.module @RefSubOpPropagate(out %p : !firrtl.probe<uint<32>>,
out %w1_via_p : !firrtl.uint<32>,
out %w0 : !firrtl.uint<32>,
out %w1 : !firrtl.uint<32>) {
// Constant pool
// CHECK-DAG: %[[C123:.+]] = firrtl.constant 123
// CHECK-DAG: %[[C321:.+]] = firrtl.constant 321
// CHECK-DAG: %[[P321:.+]] = firrtl.ref.send %[[C321]]
// CHECK: firrtl.instance
%c_vec_ref, %c_w0, %c_w1 = firrtl.instance c @Child(out p : !firrtl.probe<vector<uint<32>, 2>>,
out w0 : !firrtl.probe<uint<32>>,
out w1 : !firrtl.probe<uint<32>>)
// 'p' should be probe of second element.
// CHECK-NEXT: firrtl.ref.define %p, %[[P321]]
%w = firrtl.wire : !firrtl.probe<uint<32>>
%ref = firrtl.ref.sub %c_vec_ref[1] : !firrtl.probe<vector<uint<32>, 2>>
firrtl.ref.define %w, %ref : !firrtl.probe<uint<32>>
firrtl.ref.define %p, %w: !firrtl.probe<uint<32>>
// CHECK-NEXT: firrtl.matchingconnect %w1_via_p, %[[C321]]
%p_read = firrtl.ref.resolve %ref : !firrtl.probe<uint<32>>
firrtl.matchingconnect %w1_via_p, %p_read : !firrtl.uint<32>
// CHECK-NEXT: firrtl.matchingconnect %w0, %[[C123]]
// CHECK-NEXT: firrtl.matchingconnect %w1, %[[C321]]
%w0_read = firrtl.ref.resolve %c_w0 : !firrtl.probe<uint<32>>
%w1_read = firrtl.ref.resolve %c_w1 : !firrtl.probe<uint<32>>
firrtl.matchingconnect %w0, %w0_read : !firrtl.uint<32>
firrtl.matchingconnect %w1, %w1_read : !firrtl.uint<32>
// CHECK-NEXT: }
}
}
// -----
// OMIR annotation should not block removal.
// - See: https://github.com/llvm/circt/issues/6199
//
// CHECK-LABEL: firrtl.circuit "OMIRRemoval"
firrtl.circuit "OMIRRemoval" {
firrtl.module @OMIRRemoval(
out %a: !firrtl.uint<1>,
out %b: !firrtl.uint<2>,
out %c: !firrtl.uint<3>,
out %d: !firrtl.uint<4>
) {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
%c3_ui2 = firrtl.constant 3 : !firrtl.uint<2>
%c7_ui3 = firrtl.constant 7 : !firrtl.uint<3>
%c15_ui4 = firrtl.constant 15 : !firrtl.uint<4>
// CHECK-NOT: %tmp_0
%tmp_0 = firrtl.node %c1_ui1 {
annotations = [
{
class = "freechips.rocketchip.objectmodel.OMIRTracker",
id = 0 : i64,
type = "OMReferenceTarget"
}
]} : !firrtl.uint<1>
firrtl.matchingconnect %a, %tmp_0 : !firrtl.uint<1>
// CHECK-NOT: %tmp_1
%tmp_1 = firrtl.node %c3_ui2 {
annotations = [
{
class = "freechips.rocketchip.objectmodel.OMIRTracker",
id = 1 : i64,
type = "OMMemberReferenceTarget"
}
]} : !firrtl.uint<2>
firrtl.matchingconnect %b, %tmp_1 : !firrtl.uint<2>
// CHECK-NOT: %tmp_2
%tmp_2 = firrtl.node %c7_ui3 {
annotations = [
{
class = "freechips.rocketchip.objectmodel.OMIRTracker",
id = 3 : i64,
type = "OMMemberInstanceTarget"
}
]} : !firrtl.uint<3>
firrtl.matchingconnect %c, %tmp_2 : !firrtl.uint<3>
// Adding one additional annotation will block removal.
//
// CHECK: %tmp_3
%tmp_3 = firrtl.node %c15_ui4 {
annotations = [
{
class = "freechips.rocketchip.objectmodel.OMIRTracker",
id = 4 : i64,
type = "OMReferenceTarget"
},
{
class = "circt.test"
}
]} : !firrtl.uint<4>
// CHECK-NEXT: firrtl.matchingconnect %d, %c15_ui4
firrtl.matchingconnect %d, %tmp_3 : !firrtl.uint<4>
}
}