mirror of https://github.com/llvm/circt.git
783 lines
42 KiB
MLIR
783 lines
42 KiB
MLIR
// RUN: circt-opt %s --firrtl-lower-xmr -split-input-file | FileCheck %s
|
|
|
|
// Test for same module lowering
|
|
// CHECK-LABEL: firrtl.circuit "xmr"
|
|
firrtl.circuit "xmr" {
|
|
// CHECK-DAG: @xmr::@[[wSym:[a-zA-Z0-9]+]]
|
|
// CHECK: firrtl.module @xmr(out %o: !firrtl.uint<2>)
|
|
firrtl.module @xmr(out %o: !firrtl.uint<2>) {
|
|
%w = firrtl.wire : !firrtl.uint<2>
|
|
%1 = firrtl.ref.send %w : !firrtl.uint<2>
|
|
%x = firrtl.ref.resolve %1 : !firrtl.probe<uint<2>>
|
|
// CHECK-NOT: firrtl.ref.resolve
|
|
firrtl.matchingconnect %o, %x : !firrtl.uint<2>
|
|
// CHECK: %w = firrtl.wire : !firrtl.uint<2>
|
|
// CHECK: %w_probe = firrtl.node sym @[[wSym]] interesting_name %w : !firrtl.uint<2>
|
|
// CHECK-NEXT: %[[#xmr:]] = firrtl.xmr.deref @xmrPath : !firrtl.uint<2>
|
|
// CHECK: firrtl.matchingconnect %o, %[[#xmr]] : !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test the correct xmr path is generated
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]]
|
|
// CHECK-SAME: [@Top::@bar, @Bar::@barXMR, @XmrSrcMod::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
firrtl.module @XmrSrcMod(out %_a: !firrtl.probe<uint<1>>) {
|
|
// CHECK: firrtl.module @XmrSrcMod() {
|
|
%zero = firrtl.constant 0 : !firrtl.uint<1>
|
|
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
|
|
// CHECK: %0 = firrtl.node sym @[[xmrSym]] %c0_ui1 : !firrtl.uint<1>
|
|
%1 = firrtl.ref.send %zero : !firrtl.uint<1>
|
|
firrtl.ref.define %_a, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<1>>) {
|
|
%xmr = firrtl.instance bar sym @barXMR @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @barXMR @XmrSrcMod()
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar_a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @bar @Bar()
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path]] : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %a, %[[#xmr]] : !firrtl.uint<1>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test 0-width xmrs are handled
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
firrtl.module @Top() {
|
|
%t_bar_a, %t_bar_b = firrtl.instance t @TopPriv(out bar_a : !firrtl.probe<uint<0>>, out bar_b : !firrtl.probe<vector<uint<0>,10>>)
|
|
|
|
%a = firrtl.wire : !firrtl.uint<0>
|
|
%0 = firrtl.ref.resolve %t_bar_a : !firrtl.probe<uint<0>>
|
|
// CHECK: %[[c0_ui0:.+]] = firrtl.constant 0 : !firrtl.uint<0>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<0>
|
|
// CHECK: firrtl.matchingconnect %a, %[[c0_ui0]] : !firrtl.uint<0>
|
|
%b = firrtl.wire : !firrtl.vector<uint<0>,10>
|
|
%1 = firrtl.ref.resolve %t_bar_b : !firrtl.probe<vector<uint<0>,10>>
|
|
firrtl.matchingconnect %b, %1 : !firrtl.vector<uint<0>,10>
|
|
// CHECK: %[[c0_ui0_0:.+]] = firrtl.constant 0 : !firrtl.uint<0>
|
|
// CHECK: %[[v2:.+]] = firrtl.bitcast %[[c0_ui0_0]] : (!firrtl.uint<0>) -> !firrtl.vector<uint<0>, 10>
|
|
// CHECK: firrtl.matchingconnect %b, %[[v2]] : !firrtl.vector<uint<0>, 10>
|
|
}
|
|
// CHECK: TopPriv()
|
|
firrtl.module private @TopPriv(out %bar_a : !firrtl.probe<uint<0>>, out %bar_b : !firrtl.probe<vector<uint<0>,10>>) {
|
|
%zw = firrtl.wire : !firrtl.uint<0>
|
|
%zw_ref = firrtl.ref.send %zw : !firrtl.uint<0>
|
|
%zw_vec = firrtl.wire : !firrtl.vector<uint<0>,10>
|
|
%zw_vec_ref = firrtl.ref.send %zw_vec : !firrtl.vector<uint<0>,10>
|
|
firrtl.ref.define %bar_a, %zw_ref : !firrtl.probe<uint<0>>
|
|
firrtl.ref.define %bar_b, %zw_vec_ref : !firrtl.probe<vector<uint<0>,10>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test the correct xmr path to port is generated
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]] [@Top::@bar, @Bar::@barXMR, @XmrSrcMod::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
firrtl.module @XmrSrcMod(in %pa: !firrtl.uint<1>, out %_a: !firrtl.probe<uint<1>>) {
|
|
// CHECK: firrtl.module @XmrSrcMod(in %pa: !firrtl.uint<1>) {
|
|
// CHECK-NEXT: firrtl.node sym @[[xmrSym]]
|
|
%1 = firrtl.ref.send %pa : !firrtl.uint<1>
|
|
firrtl.ref.define %_a, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<1>>) {
|
|
%pa, %xmr = firrtl.instance bar sym @barXMR @XmrSrcMod(in pa: !firrtl.uint<1>, out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: %bar_pa = firrtl.instance bar sym @barXMR @XmrSrcMod(in pa: !firrtl.uint<1>)
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar_a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @bar @Bar()
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path]] : !firrtl.uint<1>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %a, %[[#xmr]]
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test for multiple readers and multiple instances
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
// CHECK-DAG: hw.hierpath private @[[path_0:[a-zA-Z0-9_]+]] [@Foo::@fooXMR, @XmrSrcMod::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
// CHECK-DAG: hw.hierpath private @[[path_1:[a-zA-Z0-9_]+]] [@Bar::@barXMR, @XmrSrcMod::@[[xmrSym]]]
|
|
// CHECK-DAG: hw.hierpath private @[[path_2:[a-zA-Z0-9_]+]] [@Top::@bar, @Bar::@barXMR, @XmrSrcMod::@[[xmrSym]]]
|
|
// CHECK-DAG: hw.hierpath private @[[path_3:[a-zA-Z0-9_]+]] [@Top::@foo, @Foo::@fooXMR, @XmrSrcMod::@[[xmrSym]]]
|
|
// CHECK-DAG: hw.hierpath private @[[path_4:[a-zA-Z0-9_]+]] [@Top::@xmr, @XmrSrcMod::@[[xmrSym]]]
|
|
firrtl.module @XmrSrcMod(out %_a: !firrtl.probe<uint<1>>) {
|
|
// CHECK: firrtl.module @XmrSrcMod() {
|
|
%zero = firrtl.constant 0 : !firrtl.uint<1>
|
|
// CHECK: %c0_ui1 = firrtl.constant 0
|
|
// CHECK: %0 = firrtl.node sym @[[xmrSym]] %c0_ui1 : !firrtl.uint<1>
|
|
%1 = firrtl.ref.send %zero : !firrtl.uint<1>
|
|
firrtl.ref.define %_a, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Foo(out %_a: !firrtl.probe<uint<1>>) {
|
|
%xmr = firrtl.instance bar sym @fooXMR @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @fooXMR @XmrSrcMod()
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
%0 = firrtl.ref.resolve %xmr : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path_0]]
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK: firrtl.matchingconnect %a, %[[#xmr]]
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<1>>) {
|
|
%xmr = firrtl.instance bar sym @barXMR @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @barXMR @XmrSrcMod()
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
%0 = firrtl.ref.resolve %xmr : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path_1]]
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK: firrtl.matchingconnect %a, %[[#xmr]]
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar_a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<1>>)
|
|
%foo_a = firrtl.instance foo sym @foo @Foo(out _a: !firrtl.probe<uint<1>>)
|
|
%xmr_a = firrtl.instance xmr sym @xmr @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @bar @Bar()
|
|
// CHECK: firrtl.instance foo sym @foo @Foo()
|
|
// CHECK: firrtl.instance xmr sym @xmr @XmrSrcMod()
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
%b = firrtl.wire : !firrtl.uint<1>
|
|
%c = firrtl.wire : !firrtl.uint<1>
|
|
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr_2:]] = firrtl.xmr.deref @[[path_2]]
|
|
%1 = firrtl.ref.resolve %foo_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr_3:]] = firrtl.xmr.deref @[[path_3]]
|
|
%2 = firrtl.ref.resolve %xmr_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr_4:]] = firrtl.xmr.deref @[[path_4]]
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %a, %[[#xmr_2]]
|
|
firrtl.matchingconnect %b, %1 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %b, %[[#xmr_3]]
|
|
firrtl.matchingconnect %c, %2 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %c, %[[#xmr_4]]
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]] [@Top::@[[TOP_XMR_SYM:.+]], @DUTModule::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
// CHECK-LABEL: firrtl.module private @DUTModule
|
|
// CHECK-SAME: (in %clock: !firrtl.clock, in %io_addr: !firrtl.uint<3>, in %io_dataIn: !firrtl.uint<8>, in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>)
|
|
firrtl.module private @DUTModule(in %clock: !firrtl.clock, in %io_addr: !firrtl.uint<3>, in %io_dataIn: !firrtl.uint<8>, in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>, out %_gen_memTap: !firrtl.probe<vector<uint<8>, 8>>) attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} {
|
|
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
|
|
%rf_memTap, %rf_read, %rf_write = firrtl.mem Undefined {depth = 8 : i64, name = "rf", portNames = ["memTap", "read", "write"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.probe<vector<uint<8>, 8>>, !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>, !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
// CHECK: %rf_read, %rf_write = firrtl.mem sym @[[xmrSym]] Undefined {depth = 8 : i64, name = "rf", portNames = ["read", "write"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>, !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%0 = firrtl.subfield %rf_read[addr] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%1 = firrtl.subfield %rf_read[en] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%2 = firrtl.subfield %rf_read[clk] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%3 = firrtl.subfield %rf_read[data] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data flip: uint<8>>
|
|
%4 = firrtl.subfield %rf_write[addr] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%5 = firrtl.subfield %rf_write[en] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%6 = firrtl.subfield %rf_write[clk] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%7 = firrtl.subfield %rf_write[data] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%8 = firrtl.subfield %rf_write[mask] : !firrtl.bundle<addr: uint<3>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
firrtl.matchingconnect %0, %io_addr : !firrtl.uint<3>
|
|
firrtl.matchingconnect %1, %c1_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %2, %clock : !firrtl.clock
|
|
firrtl.matchingconnect %io_dataOut, %3 : !firrtl.uint<8>
|
|
firrtl.matchingconnect %4, %io_addr : !firrtl.uint<3>
|
|
firrtl.matchingconnect %5, %io_wen : !firrtl.uint<1>
|
|
firrtl.matchingconnect %6, %clock : !firrtl.clock
|
|
firrtl.matchingconnect %8, %c1_ui1 : !firrtl.uint<1>
|
|
firrtl.matchingconnect %7, %io_dataIn : !firrtl.uint<8>
|
|
firrtl.ref.define %_gen_memTap, %rf_memTap : !firrtl.probe<vector<uint<8>, 8>>
|
|
}
|
|
// CHECK: firrtl.module @Top
|
|
firrtl.module @Top(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>, in %io_addr: !firrtl.uint<3>, in %io_dataIn: !firrtl.uint<8>, in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>) {
|
|
// CHECK: firrtl.instance dut sym @[[TOP_XMR_SYM]] @DUTModule
|
|
%dut_clock, %dut_io_addr, %dut_io_dataIn, %dut_io_wen, %dut_io_dataOut, %dut__gen_memTap = firrtl.instance dut @DUTModule(in clock: !firrtl.clock, in io_addr: !firrtl.uint<3>, in io_dataIn: !firrtl.uint<8>, in io_wen: !firrtl.uint<1>, out io_dataOut: !firrtl.uint<8>, out _gen_memTap: !firrtl.probe<vector<uint<8>, 8>>)
|
|
%0 = firrtl.ref.resolve %dut__gen_memTap : !firrtl.probe<vector<uint<8>, 8>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path]], ".Memory"
|
|
firrtl.matchingconnect %dut_clock, %clock : !firrtl.clock
|
|
%memTap_0 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_1 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_2 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_3 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_4 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_5 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_6 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_7 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
firrtl.matchingconnect %io_dataOut, %dut_io_dataOut : !firrtl.uint<8>
|
|
firrtl.matchingconnect %dut_io_wen, %io_wen : !firrtl.uint<1>
|
|
firrtl.matchingconnect %dut_io_dataIn, %io_dataIn : !firrtl.uint<8>
|
|
firrtl.matchingconnect %dut_io_addr, %io_addr : !firrtl.uint<3>
|
|
%1 = firrtl.subindex %0[0] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_0:]] = firrtl.subindex %[[#xmr]][0]
|
|
firrtl.matchingconnect %memTap_0, %1 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_0, %[[#cast_0]] : !firrtl.uint<8>
|
|
%2 = firrtl.subindex %0[1] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_1:]] = firrtl.subindex %[[#xmr]][1]
|
|
firrtl.matchingconnect %memTap_1, %2 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_1, %[[#cast_1]] : !firrtl.uint<8>
|
|
%3 = firrtl.subindex %0[2] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_2:]] = firrtl.subindex %[[#xmr]][2]
|
|
firrtl.matchingconnect %memTap_2, %3 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_2, %[[#cast_2]] : !firrtl.uint<8>
|
|
%4 = firrtl.subindex %0[3] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_3:]] = firrtl.subindex %[[#xmr]][3]
|
|
firrtl.matchingconnect %memTap_3, %4 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_3, %[[#cast_3]] : !firrtl.uint<8>
|
|
%5 = firrtl.subindex %0[4] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_4:]] = firrtl.subindex %[[#xmr]][4]
|
|
firrtl.matchingconnect %memTap_4, %5 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_4, %[[#cast_4]] : !firrtl.uint<8>
|
|
%6 = firrtl.subindex %0[5] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_5:]] = firrtl.subindex %[[#xmr]][5]
|
|
firrtl.matchingconnect %memTap_5, %6 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_5, %[[#cast_5]] : !firrtl.uint<8>
|
|
%7 = firrtl.subindex %0[6] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_6:]] = firrtl.subindex %[[#xmr]][6]
|
|
firrtl.matchingconnect %memTap_6, %7 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_6, %[[#cast_6]] : !firrtl.uint<8>
|
|
%8 = firrtl.subindex %0[7] : !firrtl.vector<uint<8>, 8>
|
|
// CHECK: %[[#cast_7:]] = firrtl.subindex %[[#xmr]][7]
|
|
firrtl.matchingconnect %memTap_7, %8 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_7, %[[#cast_7]] : !firrtl.uint<8>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]] [@Top::@[[TOP_XMR_SYM:.+]], @DUTModule::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
// CHECK-LABEL: firrtl.module private @DUTModule
|
|
// CHECK-SAME: in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>)
|
|
firrtl.module private @DUTModule(in %clock: !firrtl.clock, in %io_addr: !firrtl.uint<3>, in %io_dataIn: !firrtl.uint<8>, in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>, out %_gen_memTap_0: !firrtl.probe<uint<8>>, out %_gen_memTap_1: !firrtl.probe<uint<8>>) attributes {annotations = [{class = "sifive.enterprise.firrtl.MarkDUTAnnotation"}]} {
|
|
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
|
|
%rf_memTap, %rf_read, %rf_write = firrtl.mem Undefined {depth = 2 : i64, name = "rf", portNames = ["memTap", "read", "write"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.probe<vector<uint<8>, 2>>, !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<8>>, !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
// CHECK: %rf_read, %rf_write = firrtl.mem sym @[[xmrSym]] Undefined {depth = 2 : i64, name = "rf", portNames = ["read", "write"], prefix = "foo_", readLatency = 0 : i32, writeLatency = 1 : i32} : !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data flip: uint<8>>, !firrtl.bundle<addr: uint<1>, en: uint<1>, clk: clock, data: uint<8>, mask: uint<1>>
|
|
%9 = firrtl.ref.sub %rf_memTap[0] : !firrtl.probe<vector<uint<8>, 2>>
|
|
firrtl.ref.define %_gen_memTap_0, %9 : !firrtl.probe<uint<8>>
|
|
%10 = firrtl.ref.sub %rf_memTap[1] : !firrtl.probe<vector<uint<8>, 2>>
|
|
firrtl.ref.define %_gen_memTap_1, %10 : !firrtl.probe<uint<8>>
|
|
}
|
|
firrtl.module @Top(in %clock: !firrtl.clock, in %reset: !firrtl.uint<1>, in %io_addr: !firrtl.uint<3>, in %io_dataIn: !firrtl.uint<8>, in %io_wen: !firrtl.uint<1>, out %io_dataOut: !firrtl.uint<8>) {
|
|
// CHECK: firrtl.instance dut sym @[[TOP_XMR_SYM]] @DUTModule
|
|
%dut_clock, %dut_io_addr, %dut_io_dataIn, %dut_io_wen, %dut_io_dataOut, %dut__gen_memTap_0, %dut__gen_memTap_1 = firrtl.instance dut @DUTModule(in clock: !firrtl.clock, in io_addr: !firrtl.uint<3>, in io_dataIn: !firrtl.uint<8>, in io_wen: !firrtl.uint<1>, out io_dataOut: !firrtl.uint<8>, out _gen_memTap_0: !firrtl.probe<uint<8>>, out _gen_memTap_1: !firrtl.probe<uint<8>>)
|
|
%0 = firrtl.ref.resolve %dut__gen_memTap_0 : !firrtl.probe<uint<8>>
|
|
// CHECK: %[[#xmr_0:]] = firrtl.xmr.deref @[[path]], ".Memory[0]"
|
|
%1 = firrtl.ref.resolve %dut__gen_memTap_1 : !firrtl.probe<uint<8>>
|
|
// CHECK: %[[#xmr_1:]] = firrtl.xmr.deref @[[path]], ".Memory[1]"
|
|
firrtl.matchingconnect %dut_clock, %clock : !firrtl.clock
|
|
%memTap_0 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
%memTap_1 = firrtl.wire {annotations = [{class = "firrtl.transforms.DontTouchAnnotation"}]} : !firrtl.uint<8>
|
|
firrtl.matchingconnect %memTap_0, %0 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_0, %[[#xmr_0]]
|
|
firrtl.matchingconnect %memTap_1, %1 : !firrtl.uint<8>
|
|
// CHECK: firrtl.matchingconnect %memTap_1, %[[#xmr_1]]
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test lowering of internal path into a module
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]] [@Top::@bar, @Bar::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
firrtl.module @XmrSrcMod(out %_a: !firrtl.probe<uint<1>>) {
|
|
// CHECK: firrtl.module @XmrSrcMod() {
|
|
// CHECK-NEXT: }
|
|
%z = firrtl.verbatim.expr "internal.path" : () -> !firrtl.uint<1>
|
|
%1 = firrtl.ref.send %z : !firrtl.uint<1>
|
|
firrtl.ref.define %_a, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<1>>) {
|
|
%xmr = firrtl.instance bar sym @barXMR @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @barXMR @XmrSrcMod()
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar_a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @bar @Bar()
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path]], ".internal.path"
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %a, %[[#xmr]]
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test lowering of internal path into a module
|
|
// CHECK-LABEL: firrtl.circuit "Top" {
|
|
firrtl.circuit "Top" {
|
|
// CHECK: hw.hierpath private @[[path:[a-zA-Z0-9_]+]] [@Top::@bar, @Bar::@barXMR, @XmrSrcMod::@[[xmrSym:[a-zA-Z0-9_]+]]]
|
|
firrtl.module @XmrSrcMod(out %_a: !firrtl.probe<uint<1>>) {
|
|
// CHECK: firrtl.module @XmrSrcMod() {
|
|
// CHECK{LITERAL}: firrtl.verbatim.expr "internal.path" : () -> !firrtl.uint<1> {symbols = [@XmrSrcMod]}
|
|
// CHECK: = firrtl.node sym @[[xmrSym]] %[[internal:.+]] : !firrtl.uint<1>
|
|
%z = firrtl.verbatim.expr "internal.path" : () -> !firrtl.uint<1> {symbols = [@XmrSrcMod]}
|
|
%1 = firrtl.ref.send %z : !firrtl.uint<1>
|
|
firrtl.ref.define %_a, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<1>>) {
|
|
%xmr = firrtl.instance bar sym @barXMR @XmrSrcMod(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @barXMR @XmrSrcMod()
|
|
firrtl.ref.define %_a, %xmr : !firrtl.probe<uint<1>>
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar_a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<1>>)
|
|
// CHECK: firrtl.instance bar sym @bar @Bar()
|
|
%a = firrtl.wire : !firrtl.uint<1>
|
|
%0 = firrtl.ref.resolve %bar_a : !firrtl.probe<uint<1>>
|
|
// CHECK: %[[#xmr:]] = firrtl.xmr.deref @[[path]]
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<1>
|
|
// CHECK-NEXT: firrtl.matchingconnect %a, %[[#xmr]]
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// Test correct lowering of 0-width ports
|
|
firrtl.circuit "Top" {
|
|
firrtl.module @XmrSrcMod(in %pa: !firrtl.uint<0>, out %_a: !firrtl.probe<uint<0>>) {
|
|
// CHECK-LABEL: firrtl.module @XmrSrcMod(in %pa: !firrtl.uint<0>)
|
|
%0 = firrtl.ref.send %pa : !firrtl.uint<0>
|
|
firrtl.ref.define %_a, %0 : !firrtl.probe<uint<0>>
|
|
}
|
|
firrtl.module @Bar(out %_a: !firrtl.probe<uint<0>>) {
|
|
%bar_pa, %bar__a = firrtl.instance bar sym @barXMR @XmrSrcMod(in pa: !firrtl.uint<0>, out _a: !firrtl.probe<uint<0>>)
|
|
firrtl.ref.define %_a, %bar__a : !firrtl.probe<uint<0>>
|
|
}
|
|
firrtl.module @Top() {
|
|
%bar__a = firrtl.instance bar sym @bar @Bar(out _a: !firrtl.probe<uint<0>>)
|
|
%a = firrtl.wire : !firrtl.uint<0>
|
|
%0 = firrtl.ref.resolve %bar__a : !firrtl.probe<uint<0>>
|
|
firrtl.matchingconnect %a, %0 : !firrtl.uint<0>
|
|
// CHECK: %c0_ui0 = firrtl.constant 0 : !firrtl.uint<0>
|
|
// CHECK: firrtl.matchingconnect %a, %c0_ui0 : !firrtl.uint<0>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Test lowering of XMR to instance port (result).
|
|
// https://github.com/llvm/circt/issues/4559
|
|
|
|
// CHECK-LABEL: Issue4559
|
|
firrtl.circuit "Issue4559" {
|
|
// CHECK: hw.hierpath private @xmrPath [@Issue4559::@[[SYM:.+]]]
|
|
firrtl.extmodule @Source(out sourceport: !firrtl.uint<1>)
|
|
firrtl.module @Issue4559() {
|
|
// CHECK: %[[PORT:.+]] = firrtl.instance source @Source
|
|
// CHECK-NEXT: %[[NODE:.+]] = firrtl.node sym @[[SYM]] interesting_name %[[PORT]]
|
|
// CHECK-NEXT: = firrtl.xmr.deref @xmrPath
|
|
%port = firrtl.instance source @Source(out sourceport: !firrtl.uint<1>)
|
|
%port_ref = firrtl.ref.send %port : !firrtl.uint<1>
|
|
%port_val = firrtl.ref.resolve %port_ref : !firrtl.probe<uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check read-only XMR of a rwprobe.
|
|
|
|
// CHECK-LABEL: firrtl.circuit "ReadForceable"
|
|
firrtl.circuit "ReadForceable" {
|
|
// CHECK: hw.hierpath private @xmrPath [@ReadForceable::@[[wSym:.+]]]
|
|
// CHECK: firrtl.module @ReadForceable(out %o: !firrtl.uint<2>)
|
|
firrtl.module @ReadForceable(out %o: !firrtl.uint<2>) {
|
|
%w, %w_ref = firrtl.wire forceable : !firrtl.uint<2>, !firrtl.rwprobe<uint<2>>
|
|
%x = firrtl.ref.resolve %w_ref : !firrtl.rwprobe<uint<2>>
|
|
// CHECK-NOT: firrtl.ref.resolve
|
|
firrtl.matchingconnect %o, %x : !firrtl.uint<2>
|
|
// CHECK: %w, %w_ref = firrtl.wire sym @[[wSym]] forceable : !firrtl.uint<2>, !firrtl.rwprobe<uint<2>>
|
|
// CHECK-NEXT: %[[#xmr:]] = firrtl.xmr.deref @xmrPath : !firrtl.uint<2>
|
|
// CHECK: firrtl.matchingconnect %o, %[[#xmr]] : !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check resolution through a ref cast.
|
|
|
|
// CHECK-LABEL: firrtl.circuit "RefCast"
|
|
firrtl.circuit "RefCast" {
|
|
// CHECK: hw.hierpath private @xmrPath [@RefCast::@[[wSym:.+]]]
|
|
// CHECK-LABEL: firrtl.module @RefCast(out %o: !firrtl.uint<2>)
|
|
firrtl.module @RefCast(out %o: !firrtl.uint<2>) {
|
|
%w, %w_ref = firrtl.wire forceable : !firrtl.uint<2>, !firrtl.rwprobe<uint<2>>
|
|
%w_ro = firrtl.ref.cast %w_ref : (!firrtl.rwprobe<uint<2>>) -> !firrtl.probe<uint<2>>
|
|
%x = firrtl.ref.resolve %w_ro : !firrtl.probe<uint<2>>
|
|
firrtl.matchingconnect %o, %x : !firrtl.uint<2>
|
|
// CHECK-NEXT: %w, %w_ref = firrtl.wire sym @[[wSym]] forceable : !firrtl.uint<2>, !firrtl.rwprobe<uint<2>>
|
|
// CHECK-NEXT: %[[#xmr:]] = firrtl.xmr.deref @xmrPath : !firrtl.uint<2>
|
|
// CHECK-NEXT: firrtl.matchingconnect %o, %[[#xmr]] : !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
|
|
// CHECK-LABEL: firrtl.circuit "ForceRelease"
|
|
firrtl.circuit "ForceRelease" {
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@ForceRelease::@[[INST_SYM:.+]], @RefMe::@[[TARGET_SYM:.+]]]
|
|
// CHECK: firrtl.module private @RefMe() {
|
|
firrtl.module private @RefMe(out %p: !firrtl.rwprobe<uint<4>>) {
|
|
// CHECK-NEXT: %x, %x_ref = firrtl.wire sym @[[TARGET_SYM]] forceable : !firrtl.uint<4>, !firrtl.rwprobe<uint<4>>
|
|
%x, %x_ref = firrtl.wire forceable : !firrtl.uint<4>, !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: }
|
|
firrtl.ref.define %p, %x_ref : !firrtl.rwprobe<uint<4>>
|
|
}
|
|
// CHECK-LABEL: firrtl.module @ForceRelease
|
|
firrtl.module @ForceRelease(in %c: !firrtl.uint<1>, in %clock: !firrtl.clock, in %x: !firrtl.uint<4>) {
|
|
// CHECK-NEXT: firrtl.instance r sym @[[INST_SYM]] @RefMe()
|
|
%r_p = firrtl.instance r @RefMe(out p: !firrtl.rwprobe<uint<4>>)
|
|
// CHECK-NEXT: %[[REF1:.+]] = firrtl.xmr.ref @[[XMRPATH]] : !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: firrtl.ref.force %clock, %c, %[[REF1]], %x : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>, !firrtl.uint<4>
|
|
firrtl.ref.force %clock, %c, %r_p, %x : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>, !firrtl.uint<4>
|
|
// CHECK-NEXT: %[[REF2:.+]] = firrtl.xmr.ref @[[XMRPATH]] : !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: firrtl.ref.force_initial %c, %[[REF2]], %x : !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>, !firrtl.uint<4>
|
|
firrtl.ref.force_initial %c, %r_p, %x : !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>, !firrtl.uint<4>
|
|
// CHECK-NEXT: %[[REF3:.+]] = firrtl.xmr.ref @[[XMRPATH]] : !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: firrtl.ref.release %clock, %c, %[[REF3]] : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>
|
|
firrtl.ref.release %clock, %c, %r_p : !firrtl.clock, !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: %[[REF4:.+]] = firrtl.xmr.ref @[[XMRPATH]] : !firrtl.rwprobe<uint<4>>
|
|
// CHECK-NEXT: firrtl.ref.release_initial %c, %[[REF4]] : !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>
|
|
firrtl.ref.release_initial %c, %r_p : !firrtl.uint<1>, !firrtl.rwprobe<uint<4>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check tracking of public output refs as sv.macro.decl and sv.macro.def
|
|
|
|
// CHECK-LABEL: firrtl.circuit "Top"
|
|
firrtl.circuit "Top" {
|
|
// CHECK: sv.macro.decl @ref_Top_a
|
|
// CHECK-NEXT: sv.macro.decl @ref_Top_b
|
|
// CHECK-NEXT: sv.macro.decl @ref_Top_c
|
|
// CHECK-NEXT: sv.macro.decl @ref_Top_d
|
|
// CHECK-NOT: sv.macro.decl @ref_Top_e
|
|
// CHECK: hw.hierpath private @[[XMR5:.+]] [@Foo::@[[FOO_X_SYM:.+]]]
|
|
// CHECK: sv.macro.decl @ref_Foo_x
|
|
// CHECK-NEXT: sv.macro.decl @ref_Foo_y
|
|
// CHECK: hw.hierpath private @[[XMR1:.*]] [@Top::@[[TOP_W_SYM:.+]]]
|
|
// CHECK: hw.hierpath private @[[XMR2:.*]] [@Top::@foo, @Foo::@[[FOO_X_SYM]]]
|
|
// CHECK: hw.hierpath private @[[XMR3:.*]] [@Top::@foo]
|
|
// CHECK: hw.hierpath private @[[XMR4:.*]] [@Top::@{{.+}}]
|
|
|
|
// CHECK: emit.file "ref_Top.sv" {
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_Top_a "{{0}}"
|
|
// CHECK-SAME: ([@[[XMR1]]])
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_Top_b "{{0}}"
|
|
// CHECK-SAME: ([@[[XMR2]]])
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_Top_c "{{0}}.internal.path"
|
|
// CHECK-SAME: ([@[[XMR3]]])
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_Top_d "{{0}}"
|
|
// CHECK-SAME: ([@[[XMR4]]])
|
|
|
|
// CHECK-LABEL: firrtl.module @Top()
|
|
firrtl.module @Top(out %a: !firrtl.probe<uint<1>>,
|
|
out %b: !firrtl.probe<uint<1>>,
|
|
out %c: !firrtl.probe<uint<1>>,
|
|
out %d: !firrtl.probe<uint<1>>) {
|
|
%w = firrtl.wire sym @w : !firrtl.uint<1>
|
|
// CHECK: firrtl.node sym @[[TOP_W_SYM]] interesting_name %w
|
|
%0 = firrtl.ref.send %w : !firrtl.uint<1>
|
|
firrtl.ref.define %a, %0 : !firrtl.probe<uint<1>>
|
|
|
|
%x, %y = firrtl.instance foo sym @foo @Foo(out x: !firrtl.probe<uint<1>>, out y: !firrtl.probe<uint<1>>)
|
|
firrtl.ref.define %b, %x : !firrtl.probe<uint<1>>
|
|
firrtl.ref.define %c, %y : !firrtl.probe<uint<1>>
|
|
|
|
%constant = firrtl.constant 0 : !firrtl.uint<1>
|
|
%1 = firrtl.ref.send %constant : !firrtl.uint<1>
|
|
firrtl.ref.define %d, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
|
|
// CHECK: emit.file "ref_Foo.sv" {
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_Foo_x "{{0}}"
|
|
// CHECK-SAME: ([@[[XMR5]]])
|
|
// CHECK-NEXT: sv.macro.def @ref_Foo_y "internal.path"
|
|
// CHECK-NOT: ([
|
|
|
|
// CHECK-LABEL: firrtl.module @Foo()
|
|
firrtl.module @Foo(out %x: !firrtl.probe<uint<1>>, out %y: !firrtl.probe<uint<1>>) {
|
|
%w = firrtl.wire sym @x : !firrtl.uint<1>
|
|
// CHECK: firrtl.node sym @[[FOO_X_SYM]] interesting_name %w
|
|
%0 = firrtl.ref.send %w : !firrtl.uint<1>
|
|
firrtl.ref.define %x, %0 : !firrtl.probe<uint<1>>
|
|
|
|
%z = firrtl.verbatim.expr "internal.path" : () -> !firrtl.uint<1>
|
|
%1 = firrtl.ref.send %z : !firrtl.uint<1>
|
|
firrtl.ref.define %y, %1 : !firrtl.probe<uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check resolving XMR's to internalPaths
|
|
|
|
// CHECK-LABEL: firrtl.circuit "InternalPaths"
|
|
firrtl.circuit "InternalPaths" {
|
|
firrtl.extmodule private @RefExtMore(in in: !firrtl.uint<1>,
|
|
out r: !firrtl.probe<uint<1>>,
|
|
out data: !firrtl.uint<3>,
|
|
out r2: !firrtl.probe<vector<bundle<a: uint<3>>, 3>>) attributes {convention = #firrtl<convention scalarized>, internalPaths = [#firrtl.internalpath, #firrtl.internalpath<"path.to.internal.signal">, #firrtl.internalpath, #firrtl.internalpath<"in">]}
|
|
// CHECK: hw.hierpath private @xmrPath [@InternalPaths::@[[EXT_SYM:.+]]]
|
|
// CHECK: module public @InternalPaths(
|
|
firrtl.module public @InternalPaths(in %in: !firrtl.uint<1>) {
|
|
// CHECK: firrtl.instance ext sym @[[EXT_SYM]] @RefExtMore
|
|
%ext_in, %ext_r, %ext_data, %ext_r2 =
|
|
firrtl.instance ext @RefExtMore(in in: !firrtl.uint<1>,
|
|
out r: !firrtl.probe<uint<1>>,
|
|
out data: !firrtl.uint<3>,
|
|
out r2: !firrtl.probe<vector<bundle<a: uint<3>>, 3>>)
|
|
firrtl.matchingconnect %ext_in, %in : !firrtl.uint<1>
|
|
|
|
// CHECK: %[[XMR_R:.+]] = firrtl.xmr.deref @xmrPath, ".path.to.internal.signal" : !firrtl.uint<1>
|
|
// CHECK: %node_r = firrtl.node %[[XMR_R]]
|
|
%read_r = firrtl.ref.resolve %ext_r : !firrtl.probe<uint<1>>
|
|
%node_r = firrtl.node %read_r : !firrtl.uint<1>
|
|
// CHECK: %[[XMR_R2:.+]] = firrtl.xmr.deref @xmrPath, ".in" : !firrtl.vector<bundle<a: uint<3>>, 3>
|
|
// CHECK: %node_r2 = firrtl.node %[[XMR_R2]]
|
|
%read_r2 = firrtl.ref.resolve %ext_r2 : !firrtl.probe<vector<bundle<a: uint<3>>, 3>>
|
|
%node_r2 = firrtl.node %read_r2 : !firrtl.vector<bundle<a: uint<3>>, 3>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check resolving XMR's to use macro ABI.
|
|
|
|
// CHECK-LABEL: firrtl.circuit "RefABI"
|
|
firrtl.circuit "RefABI" {
|
|
firrtl.extmodule private @RefExtMore(in in: !firrtl.uint<1>,
|
|
out r: !firrtl.probe<uint<1>>,
|
|
out data: !firrtl.uint<3>,
|
|
out r2: !firrtl.probe<vector<bundle<a: uint<3>>, 3>>) attributes {convention = #firrtl<convention scalarized>}
|
|
// CHECK: hw.hierpath private @xmrPath [@RefABI::@[[XMR_SYM:.+]]]
|
|
// CHECK: module public @RefABI(
|
|
firrtl.module public @RefABI(in %in: !firrtl.uint<1>) {
|
|
%ext_in, %ext_r, %ext_data, %ext_r2 =
|
|
// CHECK: firrtl.instance ext sym @[[XMR_SYM]] @RefExtMore
|
|
firrtl.instance ext @RefExtMore(in in: !firrtl.uint<1>,
|
|
out r: !firrtl.probe<uint<1>>,
|
|
out data: !firrtl.uint<3>,
|
|
out r2: !firrtl.probe<vector<bundle<a: uint<3>>, 3>>)
|
|
firrtl.matchingconnect %ext_in, %in : !firrtl.uint<1>
|
|
|
|
// CHECK: %[[XMR_R:.+]] = firrtl.xmr.deref @xmrPath, ".`ref_RefExtMore_r" : !firrtl.uint<1>
|
|
// CHECK: %node_r = firrtl.node %[[XMR_R]]
|
|
%read_r = firrtl.ref.resolve %ext_r : !firrtl.probe<uint<1>>
|
|
%node_r = firrtl.node %read_r : !firrtl.uint<1>
|
|
// CHECK: %[[XMR_R2:.+]] = firrtl.xmr.deref @xmrPath, ".`ref_RefExtMore_r2" : !firrtl.vector<bundle<a: uint<3>>, 3>
|
|
// CHECK: %node_r2 = firrtl.node %[[XMR_R2]]
|
|
%read_r2 = firrtl.ref.resolve %ext_r2 : !firrtl.probe<vector<bundle<a: uint<3>>, 3>>
|
|
%node_r2 = firrtl.node %read_r2 : !firrtl.vector<bundle<a: uint<3>>, 3>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check handling of basic ref.sub.
|
|
|
|
// CHECK-LABEL: circuit "BasicRefSub"
|
|
firrtl.circuit "BasicRefSub" {
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@BasicRefSub::@[[C_SYM:[^,]+]], @Child::@[[REF_SYM:[^,]+]]]
|
|
// CHECK-LABEL: firrtl.module private @Child
|
|
// CHECK-SAME: in %in: !firrtl.bundle<a: uint<1>, b: uint<2>>)
|
|
firrtl.module private @Child(in %in : !firrtl.bundle<a: uint<1>, b: uint<2>>, out %out : !firrtl.probe<uint<2>>) {
|
|
// CHECK-NEXT: firrtl.node sym @[[REF_SYM]] interesting_name %in
|
|
%ref = firrtl.ref.send %in : !firrtl.bundle<a: uint<1>, b: uint<2>>
|
|
%sub = firrtl.ref.sub %ref[1] : !firrtl.probe<bundle<a: uint<1>, b: uint<2>>>
|
|
firrtl.ref.define %out, %sub : !firrtl.probe<uint<2>>
|
|
}
|
|
// CHECK-LABEL: module @BasicRefSub(
|
|
firrtl.module @BasicRefSub(in %in : !firrtl.bundle<a: uint<1>, b: uint<2>>, out %out : !firrtl.uint<2>) {
|
|
// CHECK: firrtl.instance c sym @[[C_SYM]]
|
|
%c_in, %c_out = firrtl.instance c @Child(in in : !firrtl.bundle<a: uint<1>, b: uint<2>>, out out : !firrtl.probe<uint<2>>)
|
|
firrtl.matchingconnect %c_in, %in : !firrtl.bundle<a: uint<1>, b: uint<2>>
|
|
// CHECK: firrtl.xmr.deref @[[XMRPATH]], ".b"
|
|
%res = firrtl.ref.resolve %c_out : !firrtl.probe<uint<2>>
|
|
firrtl.matchingconnect %out, %res : !firrtl.uint<2>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check rwprobe, forceable, ABI
|
|
|
|
// CHECK-LABEL: circuit "RWProbe_field"
|
|
firrtl.circuit "RWProbe_field" {
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@RWProbe_field::@[[SYM:[^,]+]]]
|
|
// CHECK-NEXT: sv.macro.decl @ref_RWProbe_field_rw
|
|
// e.g., "n[0]"
|
|
// CHECK-NEXT: sv.macro.decl @ref_RWProbe_field_rw_narrow
|
|
// e.g., "n[0].a"
|
|
|
|
// CHECK: emit.file "ref_RWProbe_field.sv" {
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_RWProbe_field_rw "{{0}}[0]"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_RWProbe_field_rw_narrow "{{0}}[0].a"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
firrtl.module @RWProbe_field(in %x: !firrtl.vector<bundle<a: uint<1>>, 2>, out %rw: !firrtl.rwprobe<bundle<a: uint<1>>>, out %rw_narrow : !firrtl.rwprobe<uint<1>>) {
|
|
%n, %n_ref = firrtl.node %x forceable : !firrtl.vector<bundle<a: uint<1>>, 2>
|
|
%0 = firrtl.ref.sub %n_ref[0] : !firrtl.rwprobe<vector<bundle<a: uint<1>>, 2>>
|
|
firrtl.ref.define %rw, %0 : !firrtl.rwprobe<bundle<a: uint<1>>>
|
|
%1 = firrtl.ref.sub %0[0] : !firrtl.rwprobe<bundle<a: uint<1>>>
|
|
firrtl.ref.define %rw_narrow, %1 : !firrtl.rwprobe<uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check ref.sub handling through layers, combining with import/export ABI (if aggs preserved?).
|
|
|
|
// CHECK-LABEL: circuit "RefSubLayers"
|
|
firrtl.circuit "RefSubLayers" {
|
|
firrtl.extmodule @ExtRef(out out: !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<2>, b: uint<1>>, 2>>>)
|
|
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@RefSubLayers::@[[TOP_SYM:[^,]+]], @Mid::@[[MID_SYM:[^,]+]], @Leaf::@[[LEAF_SYM:.+]]]
|
|
// CHECK-NEXT: sv.macro.decl @ref_RefSubLayers_rw
|
|
// CHECK: emit.file "ref_RefSubLayers.sv" {
|
|
// CHECK-NEXT{LITERAL}: sv.macro.def @ref_RefSubLayers_rw "{{0}}.`ref_ExtRef_out.b[1].a"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
firrtl.module @RefSubLayers(out %rw : !firrtl.probe<uint<2>>) {
|
|
%ref = firrtl.instance m @Mid(out rw: !firrtl.probe<bundle<a: uint<2>, b: uint<1>>>)
|
|
%sub = firrtl.ref.sub %ref[0] : !firrtl.probe<bundle<a: uint<2>, b: uint<1>>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<uint<2>>
|
|
}
|
|
firrtl.module private @Mid(out %rw : !firrtl.probe<bundle<a: uint<2>, b: uint<1>>>) {
|
|
%ref = firrtl.instance l @Leaf(out rw: !firrtl.probe<vector<bundle<a: uint<2>, b: uint<1>>, 2>>)
|
|
%sub = firrtl.ref.sub %ref[1] : !firrtl.probe<vector<bundle<a: uint<2>, b: uint<1>>, 2>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<bundle<a: uint<2>, b: uint<1>>>
|
|
}
|
|
|
|
firrtl.module private @Leaf(out %rw : !firrtl.probe<vector<bundle<a: uint<2>, b: uint<1>>, 2>>) {
|
|
%ref = firrtl.instance ext @ExtRef(out out: !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<2>, b: uint<1>>, 2>>>)
|
|
%sub = firrtl.ref.sub %ref[1] : !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<2>, b: uint<1>>, 2>>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<vector<bundle<a: uint<2>, b: uint<1>>, 2>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check dropping force/etc. ops that target zero-width references.
|
|
// Ensure no symbol added, so can be dropped in LowerToHW.
|
|
|
|
// CHECK-LABEL: circuit "DropForceOp"
|
|
firrtl.circuit "DropForceOp" {
|
|
firrtl.module @DropForceOp() {
|
|
// CHECK: firrtl.wire
|
|
// CHECK-NOT: sym
|
|
// CHECK-NEXT: }
|
|
%c0_ui0 = firrtl.constant 0 : !firrtl.uint<0>
|
|
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
|
|
%x, %x_ref = firrtl.wire forceable : !firrtl.uint<0>, !firrtl.rwprobe<uint<0>>
|
|
firrtl.ref.force_initial %c1_ui1, %x_ref, %c0_ui0 : !firrtl.uint<1>, !firrtl.rwprobe<uint<0>>, !firrtl.uint<0>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check dropping zero-width and interaction with ABI/across layers.
|
|
|
|
// CHECK-LABEL: circuit "RefSubZeroWidth"
|
|
firrtl.circuit "RefSubZeroWidth" {
|
|
// CHECK-NOT: probe<
|
|
firrtl.extmodule @ExtRef(out out: !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<0>, b: uint<1>>, 2>>>)
|
|
firrtl.module @RefSubZeroWidth(out %rw : !firrtl.probe<uint<0>>) {
|
|
%ref = firrtl.instance m @Mid(out rw: !firrtl.probe<bundle<a: uint<0>, b: uint<1>>>)
|
|
%sub = firrtl.ref.sub %ref[0] : !firrtl.probe<bundle<a: uint<0>, b: uint<1>>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<uint<0>>
|
|
}
|
|
firrtl.module private @Mid(out %rw : !firrtl.probe<bundle<a: uint<0>, b: uint<1>>>) {
|
|
%ref = firrtl.instance l @Leaf(out rw: !firrtl.probe<vector<bundle<a: uint<0>, b: uint<1>>, 2>>)
|
|
%sub = firrtl.ref.sub %ref[1] : !firrtl.probe<vector<bundle<a: uint<0>, b: uint<1>>, 2>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<bundle<a: uint<0>, b: uint<1>>>
|
|
}
|
|
|
|
firrtl.module private @Leaf(out %rw : !firrtl.probe<vector<bundle<a: uint<0>, b: uint<1>>, 2>>) {
|
|
%ref = firrtl.instance ext @ExtRef(out out: !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<0>, b: uint<1>>, 2>>>)
|
|
%sub = firrtl.ref.sub %ref[1] : !firrtl.probe<bundle<a: uint<1>, b: vector<bundle<a: uint<0>, b: uint<1>>, 2>>>
|
|
firrtl.ref.define %rw, %sub : !firrtl.probe<vector<bundle<a: uint<0>, b: uint<1>>, 2>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Check resolving through rwprobe ops, particularly when pointing to specific field.
|
|
// CHECK-LABEL: circuit "RWProbePort"
|
|
|
|
firrtl.circuit "RWProbePort" {
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@RWProbePort::@target]
|
|
// CHECK{LITERAL}: sv.macro.def @ref_RWProbePort_p "{{0}}"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
// CHECK: module @RWProbePort(
|
|
// CHECK-NOT: firrtl.ref.rwprobe
|
|
// CHECK-NEXT: }
|
|
firrtl.module @RWProbePort(in %in: !firrtl.vector<uint<1>, 2> sym [<@target,2,public>], out %p: !firrtl.rwprobe<uint<1>>) {
|
|
%0 = firrtl.ref.rwprobe <@RWProbePort::@target> : !firrtl.rwprobe<uint<1>>
|
|
firrtl.ref.define %p, %0 : !firrtl.rwprobe<uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Test resolving through output ports through points that aren't handled by unification.
|
|
// (ref.sub).
|
|
|
|
// CHECK-LABEL: circuit "RefSubOutputPort"
|
|
firrtl.circuit "RefSubOutputPort" {
|
|
// CHECK: hw.hierpath private @[[XMRPATH:.+]] [@RefSubOutputPort::@[[CHILD_SYM:.+]], @Child::@[[WIRE_SYM:.+]]]
|
|
|
|
// CHECK: firrtl.module private @Child
|
|
// CHECK-NEXT: firrtl.wire sym @[[WIRE_SYM]] forceable
|
|
firrtl.module private @Child(out %bore_1: !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>) {
|
|
%b, %b_ref = firrtl.wire forceable : !firrtl.bundle<x: vector<uint<1>, 2>>, !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>
|
|
firrtl.ref.define %bore_1, %b_ref : !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>
|
|
}
|
|
// CHECK: emit.file "ref_RefSubOutputPort.sv" {
|
|
// CHECK: sv.macro.def @ref_RefSubOutputPort_outVec
|
|
// CHECK-SAME{LITERAL}: "{{0}}.x"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
// CHECK: sv.macro.def @ref_RefSubOutputPort_outElem
|
|
// CHECK-SAME{LITERAL}: "{{0}}.x[1]"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
// CHECK: sv.macro.def @ref_RefSubOutputPort_outElemDirect
|
|
// CHECK-SAME{LITERAL}: "{{0}}.x[1]"
|
|
// CHECK-SAME: ([@[[XMRPATH]]])
|
|
// CHECK: firrtl.module @RefSubOutputPort
|
|
firrtl.module @RefSubOutputPort(out %outRWBundleProbe: !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>,
|
|
out %outVec: !firrtl.rwprobe<vector<uint<1>, 2>>,
|
|
out %outElem: !firrtl.rwprobe<uint<1>>,
|
|
out %outElemDirect: !firrtl.rwprobe<uint<1>>) attributes {convention = #firrtl<convention scalarized>} {
|
|
%0 = firrtl.ref.sub %outVec[1] : !firrtl.rwprobe<vector<uint<1>, 2>>
|
|
%1 = firrtl.ref.sub %outRWBundleProbe[0] : !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>
|
|
%2 = firrtl.ref.sub %1[1] : !firrtl.rwprobe<vector<uint<1>, 2>>
|
|
// CHECK-NEXT: instance child sym @[[CHILD_SYM]] @Child
|
|
// CHECK-NEXT: }
|
|
%child_bore_1 = firrtl.instance child @Child(out bore_1: !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>)
|
|
firrtl.ref.define %outRWBundleProbe, %child_bore_1 : !firrtl.rwprobe<bundle<x: vector<uint<1>, 2>>>
|
|
firrtl.ref.define %outElemDirect, %2 : !firrtl.rwprobe<uint<1>>
|
|
firrtl.ref.define %outVec, %1 : !firrtl.rwprobe<vector<uint<1>, 2>>
|
|
firrtl.ref.define %outElem, %0 : !firrtl.rwprobe<uint<1>>
|
|
}
|
|
}
|
|
|
|
// -----
|
|
// Test that wires of refs are resolved through and deleted.
|
|
|
|
// CHECK-LABEL: "WireProbe"
|
|
firrtl.circuit "WireProbe" {
|
|
// CHECK: hierpath {{.*}} [@WireProbe::@[[SYM:[^ ]+]]]
|
|
// CHECK: @WireProbe(in %x: !firrtl.uint<5>) {
|
|
// CHECK-NEXT: firrtl.node sym @[[SYM]]
|
|
// CHECK-NEXT: }
|
|
firrtl.module @WireProbe(in %x: !firrtl.uint<5>, out %p: !firrtl.probe<uint<5>>) {
|
|
// CHECK-NOT: firrtl.wire
|
|
%0 = firrtl.ref.send %x : !firrtl.uint<5>
|
|
%w = firrtl.wire : !firrtl.probe<uint<5>>
|
|
firrtl.ref.define %w, %0 : !firrtl.probe<uint<5>>
|
|
firrtl.ref.define %p, %w : !firrtl.probe<uint<5>>
|
|
}
|
|
}
|