circt/test/Dialect/FIRRTL/lower-layers.mlir

770 lines
32 KiB
MLIR

// RUN: circt-opt -firrtl-lower-layers -split-input-file %s | FileCheck %s
firrtl.circuit "Test" {
firrtl.module @Test() {}
firrtl.layer @A bind {
firrtl.layer @B bind {
firrtl.layer @C bind {}
}
}
firrtl.layer @B bind {}
firrtl.extmodule @Foo(out o : !firrtl.probe<uint<1>, @A>)
//===--------------------------------------------------------------------===//
// Removal of Probe Colors
//===--------------------------------------------------------------------===//
// CHECK-LABEL: @ColoredPorts(out %o: !firrtl.probe<uint<1>>)
firrtl.module @ColoredPorts(out %o: !firrtl.probe<uint<1>, @A>) {}
// CHECK-LABEL: @ExtColoredPorts(out o: !firrtl.probe<uint<1>>)
firrtl.extmodule @ExtColoredPorts(out o: !firrtl.probe<uint<1>, @A>)
// CHECK-LABEL: @ColoredPortsOnInstances
firrtl.module @ColoredPortsOnInstances() {
// CHECK: %foo_o = firrtl.instance foo @ColoredPorts(out o: !firrtl.probe<uint<1>>)
%foo_o = firrtl.instance foo @ColoredPorts(out o: !firrtl.probe<uint<1>, @A>)
}
// CHECK-LABEL: @ColoredThings
firrtl.module @ColoredThings() {
// CHECK: %0 = firrtl.wire : !firrtl.probe<bundle<f: uint<1>>>
%0 = firrtl.wire : !firrtl.probe<bundle<f: uint<1>>, @A>
// CHECK: %1 = firrtl.ref.sub %0[0] : !firrtl.probe<bundle<f: uint<1>>>
%1 = firrtl.ref.sub %0[0] : !firrtl.probe<bundle<f: uint<1>>, @A>
// CHECK-NOT: firrtl.ref.cast
%2 = firrtl.ref.cast %1 : (!firrtl.probe<uint<1>, @A>) -> !firrtl.probe<uint<1>, @A::@B>
}
// CHECK-LABEL: @ColoredThingUnderWhen
firrtl.module @ColoredThingUnderWhen(in %b : !firrtl.uint<1>) {
// CHECK: firrtl.when %b : !firrtl.uint<1>
firrtl.when %b : !firrtl.uint<1> {
// CHECK: %0 = firrtl.wire : !firrtl.probe<bundle<f: uint<1>>>
%0 = firrtl.wire : !firrtl.probe<bundle<f: uint<1>>, @A>
// CHECK: %1 = firrtl.ref.sub %0[0] : !firrtl.probe<bundle<f: uint<1>>>
%1 = firrtl.ref.sub %0[0] : !firrtl.probe<bundle<f: uint<1>>, @A>
// CHECK-NOT: firrtl.ref.cast
%2 = firrtl.ref.cast %1 : (!firrtl.probe<uint<1>, @A>) -> !firrtl.probe<uint<1>, @A::@B>
}
}
//===--------------------------------------------------------------------===//
// Removal of Enabled Layers
//===--------------------------------------------------------------------===//
// CHECK-LABEL: @EnabledLayers() {
firrtl.module @EnabledLayers() attributes {layers = [@A]} {}
// CHECK-LABEL: @EnabledLayersOnInstance()
firrtl.module @EnabledLayersOnInstance() attributes {layers = [@A]} {
// CHECK: firrtl.instance enabledLayers @EnabledLayers()
firrtl.instance enabledLayers {layers = [@A]} @EnabledLayers()
}
//===--------------------------------------------------------------------===//
// Removal of Layerblocks and Layers
//===--------------------------------------------------------------------===//
// CHECK-NOT: firrtl.layer @GoodbyeCruelWorld
firrtl.layer @GoodbyeCruelWorld bind {}
// CHECK-LABEL @WithLayerBlock
firrtl.module @WithLayerBlock() {
// CHECK-NOT firrtl.layerblock @GoodbyeCruelWorld
firrtl.layerblock @GoodbyeCruelWorld {
}
}
//===--------------------------------------------------------------------===//
// Capture
//===--------------------------------------------------------------------===//
// CHECK: firrtl.module private @[[A:.+]](in %[[x:.+]]: !firrtl.uint<1>, in %[[y:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.add %[[x]], %[[y]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
// CHECK: }
// CHECK: firrtl.module @CaptureHardware() {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
// CHECK: %[[p:.+]], %[[q:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: firrtl.matchingconnect %[[q]], %c1_ui1 : !firrtl.uint<1>
// CHECK: firrtl.matchingconnect %[[p]], %c0_ui1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @CaptureHardware() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
firrtl.layerblock @A {
%0 = firrtl.add %c0_ui1, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
}
}
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>) {
// CHECK: %x = firrtl.node %[[p]] : !firrtl.uint<1>
// CHECK: }
// CHECK: firrtl.module @CapturePort(in %in: !firrtl.uint<1>) {
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: firrtl.matchingconnect %[[p]], %in : !firrtl.uint<1>
// CHECK: }
firrtl.module @CapturePort(in %in: !firrtl.uint<1>){
firrtl.layerblock @A {
%x = firrtl.node %in : !firrtl.uint<1>
}
}
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>)
// CHECK: %w = firrtl.wire : !firrtl.uint<1>
// CHECK: firrtl.connect %w, %[[p]] : !firrtl.uint<1>
// CHECK: }
// CHECK: firrtl.module @CaptureHardwareViaConnect() {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: firrtl.matchingconnect %[[p]], %c0_ui1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @CaptureHardwareViaConnect() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.layerblock @A {
%w = firrtl.wire : !firrtl.uint<1>
firrtl.connect %w, %c0_ui1 : !firrtl.uint<1>, !firrtl.uint<1>
}
}
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.ref.send %[[p]] : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @CaptureProbeSrc() {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %w = firrtl.wire : !firrtl.uint<1>
// CHECK: %0 = firrtl.ref.send %w : !firrtl.uint<1>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[p]], %1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @CaptureProbeSrc() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%w = firrtl.wire : !firrtl.uint<1>
%r = firrtl.ref.send %w : !firrtl.uint<1>
firrtl.layerblock @A {
firrtl.ref.resolve %r : !firrtl.probe<uint<1>>
}
}
// CHECK: firrtl.module private @[[B:.+]](in %[[p:.+]]: !firrtl.uint<1>, in %[[q:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.add %[[p]], %[[q]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
// CHECK: }
// CHECK: firrtl.module private @[[A:.+]](out %[[p:.+]]: !firrtl.probe<uint<1>>, out %[[q:.+]]: !firrtl.probe<uint<1>>) attributes {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %0 = firrtl.ref.send %c0_ui1 : !firrtl.uint<1>
// CHECK: firrtl.ref.define %[[q]], %0 : !firrtl.probe<uint<1>>
// CHECK: %c0_ui1_1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.send %c0_ui1_1 : !firrtl.uint<1>
// CHECK: firrtl.ref.define %[[p]], %1 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @NestedCaptureHardware() {
// CHECK: %[[b1:.+]], %[[b2:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A-B.sv", excludeFromFileList>} @[[B]]
// CHECK: %[[a1:.+]], %[[a2:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: %0 = firrtl.ref.resolve %[[a2]] : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[b1]], %0 : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.resolve %[[a1]] : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[b2]], %1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @NestedCaptureHardware() {
firrtl.layerblock @A {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
%c1_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.layerblock @A::@B {
%0 = firrtl.add %c0_ui1, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
}
}
}
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>)
// CHECK: %c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
// CHECK: firrtl.when %[[p]] : !firrtl.uint<1> {
// CHECK: %0 = firrtl.add %[[p]], %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
// CHECK: }
// CHECK: }
// CHECK: firrtl.module @WhenUnderLayer() {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: firrtl.matchingconnect %[[p]], %c0_ui1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @WhenUnderLayer() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.layerblock @A {
%c1_ui1 = firrtl.constant 1 : !firrtl.uint<1>
firrtl.when %c0_ui1 : !firrtl.uint<1> {
%0 = firrtl.add %c0_ui1, %c1_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
}
}
}
// Test that subfield, subindex, and subaccess are moved out of layerblocks to
// avoid capturing non-passive types.
//
// CHECK: firrtl.module private @[[SubOpsInLayerBlock_A:[A-Za-z0-9_]+]]
// CHECK-SAME: in %[[port:[A-Za-z0-9_]+]]: !firrtl.uint<1>
// CHECK-NEXT: firrtl.node %[[port]]
// CHECK-NEXT: }
// CHECK: firrtl.module @SubOpsInLayerBlock
// CHECK-NEXT: firrtl.subaccess
// CHECK-NEXT: firrtl.subindex
// CHECK-NEXT: firrtl.subfield
firrtl.module @SubOpsInLayerBlock(
in %a: !firrtl.vector<vector<bundle<a: uint<1>, b flip: uint<2>>, 2>, 2>,
in %b: !firrtl.uint<1>
) {
firrtl.layerblock @A {
%0 = firrtl.subaccess %a[%b] : !firrtl.vector<vector<bundle<a: uint<1>, b flip: uint<2>>, 2>, 2>, !firrtl.uint<1>
%1 = firrtl.subindex %0[0] : !firrtl.vector<bundle<a: uint<1>, b flip: uint<2>>, 2>
%2 = firrtl.subfield %1[a] : !firrtl.bundle<a: uint<1>, b flip: uint<2>>
%3 = firrtl.node %2 : !firrtl.uint<1>
}
}
//===--------------------------------------------------------------------===//
// Connecting/Defining Refs
//===--------------------------------------------------------------------===//
// Src and Dst Outside Layerblock.
//
// CHECK: firrtl.module private @[[A:.+]]() {
// CHECK: }
// CHECK: firrtl.module @SrcDstOutside() {
// CHECK: %0 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %1 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>>
// CHECK: firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A:.+]]()
// CHECK: }
firrtl.module @SrcDstOutside() {
%0 = firrtl.wire : !firrtl.probe<uint<1>, @A>
%1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>, @A>
}
}
// Src Outside Layerblock.
//
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.ref.send %[[p]] : !firrtl.uint<1>
// CHECK: %1 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @SrcOutside() {
// CHECK: %0 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[p]], %1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @SrcOutside() {
%0 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
%1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>, @A>
}
}
// Dst Outside Layerblock.
//
// CHECK: firrtl.module private @[[A:.+]](out %[[p:.+]]: !firrtl.probe<uint<1>>)
// CHECK: %0 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %[[p]], %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @DestOutside() {
// CHECK: %0 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: firrtl.ref.define %0, %[[p]] : !firrtl.probe<uint<1>>
// CHECK: }
firrtl.module @DestOutside() {
%0 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
%1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.ref.define %0, %1 : !firrtl.probe<uint<1>, @A>
}
}
// Src and Dst Inside Layerblock.
//
// CHECK: firrtl.module private @[[A:.+]]() {
// CHECK: %0 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %1 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @SrcDstInside() {
// CHECK: firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]()
// CHECK: }
firrtl.module @SrcDstInside() {
firrtl.layerblock @A {
%0 = firrtl.wire : !firrtl.probe<uint<1>, @A>
%1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.ref.define %1, %0 : !firrtl.probe<uint<1>, @A>
}
}
//===--------------------------------------------------------------------===//
// Resolving Colored Probes
//===--------------------------------------------------------------------===//
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>) {
// CHECK: %0 = firrtl.ref.send %[[p]] : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @ResolveColoredRefUnderLayerBlock() {
// CHECK: %w = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: %0 = firrtl.ref.resolve %w : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[p]], %0 : !firrtl.uint<1>
// CHECK: }
firrtl.module @ResolveColoredRefUnderLayerBlock() {
%w = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
%0 = firrtl.ref.resolve %w : !firrtl.probe<uint<1>, @A>
}
}
// CHECK: firrtl.module @ResolveColoredRefUnderEnabledLayer() {
// CHECK: %w = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %0 = firrtl.ref.resolve %w : !firrtl.probe<uint<1>>
// CHECK: }
firrtl.module @ResolveColoredRefUnderEnabledLayer() attributes {layers=[@A]} {
%w = firrtl.wire : !firrtl.probe<uint<1>, @A>
%0 = firrtl.ref.resolve %w : !firrtl.probe<uint<1>, @A>
}
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>) {
// CHECK: %0 = firrtl.ref.send %[[p]] : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @ResolveColoredRefPortUnderLayerBlock1() {
// CHECK: %foo_o = firrtl.instance foo @Foo(out o: !firrtl.probe<uint<1>>)
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]
// CHECK: %0 = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[p]], %0 : !firrtl.uint<1>
// CHECK: }
firrtl.module @ResolveColoredRefPortUnderLayerBlock1() {
%foo_o = firrtl.instance foo @Foo(out o : !firrtl.probe<uint<1>, @A>)
firrtl.layerblock @A {
%x = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>, @A>
}
}
// CHECK: firrtl.module private @[[A:.+]]() {
// CHECK: %foo_o = firrtl.instance foo @Foo(out o: !firrtl.probe<uint<1>>)
// CHECK: %0 = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @ResolveColoredRefPortUnderLayerBlock2() {
// CHECK: firrtl.instance {{.+}} {lowerToBind, output_file = #hw.output_file<"layers-Test-A.sv", excludeFromFileList>} @[[A]]()
// CHECK: }
firrtl.module @ResolveColoredRefPortUnderLayerBlock2() {
firrtl.layerblock @A {
%foo_o = firrtl.instance foo @Foo(out o : !firrtl.probe<uint<1>, @A>)
%x = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>, @A>
}
}
// CHECK: firrtl.module @ResolveColoredRefPortUnderEnabledLayer() {
// CHECK: %foo_o = firrtl.instance foo @Foo(out o: !firrtl.probe<uint<1>>)
// CHECK: %0 = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>>
// CHECK: }
firrtl.module @ResolveColoredRefPortUnderEnabledLayer() attributes {layers=[@A]} {
%foo_o = firrtl.instance foo @Foo(out o : !firrtl.probe<uint<1>, @A>)
%x = firrtl.ref.resolve %foo_o : !firrtl.probe<uint<1>, @A>
}
//===--------------------------------------------------------------------===//
// Inline Layers
//===--------------------------------------------------------------------===//
// CHECK: sv.macro.decl @[[INLINE:.*]]["Inline"]
firrtl.layer @Inline inline {
// CHECK: sv.macro.decl @Inline_Inline
firrtl.layer @Inline inline {}
firrtl.layer @Bound bind {
// CHECK: sv.macro.decl @Inline_Bound_Inline
firrtl.layer @Inline inline {}
firrtl.layer @Bound bind {
// CHECK: sv.macro.decl @Inline_Bound_Bound_Inline
firrtl.layer @Inline inline {}
}
}
}
firrtl.layer @Bound bind {
// CHECK: sv.macro.decl @Bound_Inline
firrtl.layer @Inline inline {}
}
// CHECK: firrtl.module private @ModuleWithInlineLayerBlocks_Inline_Bound() {
// CHECK: %w3 = firrtl.wire : !firrtl.uint<3>
// CHECK: sv.ifdef @Inline_Bound_Inline {
// CHECK: %w4 = firrtl.wire : !firrtl.uint<4>
// CHECK: }
// CHECK: }
// CHECK: firrtl.module private @ModuleWithInlineLayerBlocks_Bound() {
// CHECK: %w5 = firrtl.wire : !firrtl.uint<5>
// CHECK: sv.ifdef @Bound_Inline {
// CHECK: %w6 = firrtl.wire : !firrtl.uint<6>
// CHECK: }
// CHECK: }
// CHECK: firrtl.module @ModuleWithInlineLayerBlocks() {
// CHECK: sv.ifdef @[[INLINE]] {
// CHECK: %w1 = firrtl.wire : !firrtl.uint<1>
// CHECK: sv.ifdef @Inline_Inline {
// CHECK: %w2 = firrtl.wire : !firrtl.uint<2>
// CHECK: }
// CHECK: firrtl.instance inline_bound {lowerToBind, output_file = #hw.output_file<"layers-Test-Inline-Bound.sv", excludeFromFileList>} @ModuleWithInlineLayerBlocks_Inline_Bound()
// CHECK: }
// CHECK: firrtl.instance bound {lowerToBind, output_file = #hw.output_file<"layers-Test-Bound.sv", excludeFromFileList>} @ModuleWithInlineLayerBlocks_Bound()
// CHECK: }
firrtl.module @ModuleWithInlineLayerBlocks() {
firrtl.layerblock @Inline {
%w1 = firrtl.wire : !firrtl.uint<1>
firrtl.layerblock @Inline::@Inline {
%w2 = firrtl.wire : !firrtl.uint<2>
}
firrtl.layerblock @Inline::@Bound {
%w3 = firrtl.wire : !firrtl.uint<3>
firrtl.layerblock @Inline::@Bound::@Inline {
%w4 = firrtl.wire : !firrtl.uint<4>
}
}
}
firrtl.layerblock @Bound {
%w5 = firrtl.wire : !firrtl.uint<5>
firrtl.layerblock @Bound::@Inline {
%w6 = firrtl.wire : !firrtl.uint<6>
}
}
}
}
// -----
firrtl.circuit "Simple" {
firrtl.layer @A bind {
firrtl.layer @B bind {
firrtl.layer @C bind {}
}
}
firrtl.module @Simple() {
%a = firrtl.wire : !firrtl.uint<1>
%b = firrtl.wire : !firrtl.uint<2>
firrtl.layerblock @A {
%aa = firrtl.node %a: !firrtl.uint<1>
%c = firrtl.wire : !firrtl.uint<3>
firrtl.layerblock @A::@B {
%bb = firrtl.node %b: !firrtl.uint<2>
%cc = firrtl.node %c: !firrtl.uint<3>
firrtl.layerblock @A::@B::@C {
%ccc = firrtl.node %cc: !firrtl.uint<3>
}
}
}
}
}
// CHECK-LABEL: firrtl.circuit "Simple"
//
// CHECK: sv.verbatim "`include \22layers-Simple-A.sv\22\0A
// CHECK-SAME: `include \22layers-Simple-A-B.sv\22\0A
// CHECK-SAME: `ifndef layers_Simple_A_B_C\0A
// CHECK-SAME: define layers_Simple_A_B_C"
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A-B-C.sv", excludeFromFileList>
// CHECK: sv.verbatim "`include \22layers-Simple-A.sv\22\0A
// CHECK-SAME: `ifndef layers_Simple_A_B\0A
// CHECK-SAME: define layers_Simple_A_B"
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A-B.sv", excludeFromFileList>
// CHECK: sv.verbatim "`ifndef layers_Simple_A\0A
// CHECK-SAME: define layers_Simple_A"
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A.sv", excludeFromFileList>
//
// CHECK: firrtl.module private @Simple_A_B_C(
// CHECK-NOT: firrtl.module
// CHECK-SAME: in %[[cc_port:[_a-zA-Z0-9]+]]: !firrtl.uint<3>
// CHECK-NEXT: %ccc = firrtl.node %[[cc_port]]
// CHECK-NEXT: }
//
// CHECK: firrtl.module private @Simple_A_B(
// CHECK-NOT: firrtl.module
// CHECK-SAME: in %[[b_port:[_a-zA-Z0-9]+]]: !firrtl.uint<2>
// CHECK-SAME: in %[[c_port:[_a-zA-Z0-9]+]]: !firrtl.uint<3>
// CHECK-SAME: out %[[cc_port:[_a-zA-Z0-9_]+]]: !firrtl.probe<uint<3>>
// CHECK-NEXT: %bb = firrtl.node %[[b_port]]
// CHECK-NEXT: %cc = firrtl.node %[[c_port]]
// CHECK-NEXT: %0 = firrtl.ref.send %cc
// CHECK-NEXT: firrtl.ref.define %[[cc_port]], %0
// CHECK-NEXT: }
//
// CHECK: firrtl.module private @Simple_A(
// CHECK-NOT: firrtl.module
// CHECK-SAME: in %[[a_port:[_a-zA-Z0-9]+]]: !firrtl.uint<1>
// CHECK-SAME: out %[[c_port:[_a-zA-Z0-9_]+]]: !firrtl.probe<uint<3>>
// CHECK-NEXT: %aa = firrtl.node %[[a_port]]
// CHECK: %[[c_ref:[_a-zA-Z0-9]+]] = firrtl.ref.send %c
// CHECK-NEXT: firrtl.ref.define %[[c_port]], %[[c_ref]]
// CHECK-NEXT: }
//
// CHECK: firrtl.module @Simple() {
// CHECK-NOT: firrtl.module
// CHECK-NOT: firrtl.layerblock
// CHECK: %[[A_B_C_cc:[_a-zA-Z0-9_]+]] = firrtl.instance a_b_c {
// CHECK-SAME: lowerToBind
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A-B-C.sv"
// CHECK-SAME: excludeFromFileList
// CHECK-SAME: @Simple_A_B_C(
// CHECK-NEXT: %[[A_B_b:[_a-zA-Z0-9_]+]], %[[A_B_c:[_a-zA-Z0-9_]+]], %[[A_B_cc:[_a-zA-Z0-9_]+]] = firrtl.instance a_b {
// CHECK-SAME: lowerToBind
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A-B.sv", excludeFromFileList>
// CHECK-SAME: @Simple_A_B(
// CHECK-NEXT: %[[A_B_cc_resolve:[_a-zA-Z0-9]+]] = firrtl.ref.resolve %[[A_B_cc]]
// CHECK-NEXT: firrtl.matchingconnect %[[A_B_C_cc]], %[[A_B_cc_resolve]]
// CHECK-NEXT: firrtl.matchingconnect %[[A_B_b]], %b
// CHECK-NEXT: %[[A_a:[_a-zA-Z0-9_]+]], %[[A_c:[_a-zA-Z0-9_]+]] = firrtl.instance a {
// CHECK-SAME: lowerToBind
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A.sv", excludeFromFileList>
// CHECK-SAME: @Simple_A(
// CHECK-NEXT: %[[A_c_resolve:[_a-zA-Z0-9]+]] = firrtl.ref.resolve %[[A_c]]
// CHECK-NEXT: firrtl.matchingconnect %[[A_B_c]], %[[A_c_resolve]]
// CHECK-NEXT: firrtl.matchingconnect %[[A_a]], %a
// CHECK: }
//
// CHECK-DAG: sv.verbatim "`endif // layers_Simple_A"
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A.sv", excludeFromFileList>
// CHECK-DAG: sv.verbatim "`endif // layers_Simple_A_B"
// CHECK-SAME: output_file = #hw.output_file<"layers-Simple-A-B.sv", excludeFromFileList>
// -----
firrtl.circuit "ModuleNameConflict" {
firrtl.layer @A bind {}
firrtl.module private @ModuleNameConflict_A() {}
firrtl.module @ModuleNameConflict() {
%a = firrtl.wire : !firrtl.uint<1>
firrtl.instance foo @ModuleNameConflict_A()
firrtl.layerblock @A {
%b = firrtl.node %a : !firrtl.uint<1>
}
}
}
// CHECK-LABEL: firrtl.circuit "ModuleNameConflict"
//
// CHECK: firrtl.module private @[[groupModule:[_a-zA-Z0-9_]+]](in
//
// CHECK: firrtl.module @ModuleNameConflict()
// CHECK-NOT: firrtl.module
// CHECK: firrtl.instance foo @ModuleNameConflict_A()
// CHECK-NEXT: firrtl.instance {{[_a-zA-Z0-9]+}} {lowerToBind,
// CHECK-SAME: @[[groupModule]](
// -----
// Layerblock lowering must allow a value to be captured twice.
// https://github.com/llvm/circt/issues/6694
firrtl.circuit "CaptureHardwareMultipleTimes" {
firrtl.layer @A bind {
firrtl.layer @B bind {}
}
firrtl.extmodule @CaptureHardwareMultipleTimes ()
// CHECK: firrtl.module private @[[A:.+]](in %[[p:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.add %[[p]], %[[p]] : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
// CHECK: }
// CHECK: firrtl.module @CaptureSrcTwice() {
// CHECK: %c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
// CHECK: %[[p:.+]] = firrtl.instance {{.+}} @[[A]]
// CHECK: firrtl.matchingconnect %[[p]], %c0_ui1 : !firrtl.uint<1>
// CHECK: }
firrtl.module @CaptureSrcTwice() {
%c0_ui1 = firrtl.constant 0 : !firrtl.uint<1>
firrtl.layerblock @A {
%0 = firrtl.add %c0_ui1, %c0_ui1 : (!firrtl.uint<1>, !firrtl.uint<1>) -> !firrtl.uint<2>
}
}
// CHECK: firrtl.module private @[[A:.+]](out %[[dst:.+]]: !firrtl.probe<uint<1>>, in %[[src:.+]]: !firrtl.uint<1>)
// CHECK: %0 = firrtl.ref.send %[[src]] : !firrtl.uint<1>
// CHECK: %w2 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %[[dst]], %w2 : !firrtl.probe<uint<1>>
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @CaptureAsDstThenSrc() {
// CHECK: %w1 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %[[out:.+]], %[[in:.+]] = firrtl.instance {{.+}} @[[A]](out {{.+}}: !firrtl.probe<uint<1>>, in {{.+}}: !firrtl.uint<1>)
// CHECK: %0 = firrtl.ref.resolve %w1 : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[in]], %0 : !firrtl.uint<1>
// CHECK: firrtl.ref.define %w1, %[[out]] : !firrtl.probe<uint<1>>
// CHECK: }
firrtl.module @CaptureAsDstThenSrc() {
%w1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
// capture first as a sink.
%w2 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.ref.define %w1, %w2 : !firrtl.probe<uint<1>, @A>
// Capture again, as a source.
%2 = firrtl.ref.resolve %w1 : !firrtl.probe<uint<1>, @A>
}
}
// CHECK: firrtl.module private @[[A:.+]](in %[[src:.+]]: !firrtl.uint<1>, out %[[dst:.+]]: !firrtl.probe<uint<1>>)
// CHECK: %0 = firrtl.ref.send %[[src]] : !firrtl.uint<1>
// CHECK: %1 = firrtl.ref.resolve %0 : !firrtl.probe<uint<1>>
// CHECK: %w2 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: firrtl.ref.define %[[dst]], %w2 : !firrtl.probe<uint<1>>
// CHECK: }
// CHECK: firrtl.module @CaptureAsSrcThenDst() {
// CHECK: %w1 = firrtl.wire : !firrtl.probe<uint<1>>
// CHECK: %[[in:.+]], %[[out:.+]] = firrtl.instance {{.+}} @[[A]]
// CHECK: firrtl.ref.define %w1, %[[out]] : !firrtl.probe<uint<1>>
// CHECK: %0 = firrtl.ref.resolve %w1 : !firrtl.probe<uint<1>>
// CHECK: firrtl.matchingconnect %[[in]], %0 : !firrtl.uint<1>
// CHECK: }
firrtl.module @CaptureAsSrcThenDst() {
%w1 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.layerblock @A {
// capture first as a source.
%2 = firrtl.ref.resolve %w1 : !firrtl.probe<uint<1>, @A>
// capture again, as a sink.
%w2 = firrtl.wire : !firrtl.probe<uint<1>, @A>
firrtl.ref.define %w1, %w2 : !firrtl.probe<uint<1>, @A>
}
}
}
// -----
// HierPathOps are rewritten when operations with inner symbols inside
// layerblocks are moved into new modules.
// https://github.com/llvm/circt/issues/6717
firrtl.circuit "HierPathOps" {
firrtl.extmodule @HierPathOps ()
hw.hierpath @nla1 [@Foo::@foo_A]
hw.hierpath @nla2 [@Foo::@bar, @Bar]
hw.hierpath private @nla3 [@Foo::@baz]
firrtl.layer @A bind {}
firrtl.module @Bar() {}
firrtl.module @Foo() {
%0 = firrtl.wire sym @foo_A : !firrtl.uint<1>
firrtl.layerblock @A {
firrtl.instance bar sym @bar @Bar()
%1 = firrtl.wire sym @baz : !firrtl.uint<1>
}
}
}
// CHECK-LABEL: firrtl.circuit "HierPathOps"
//
// CHECK: hw.hierpath @nla1 [@Foo::@foo_A]
// CHECK-NEXT: hw.hierpath @nla2 [@Foo::@[[inst_sym:[_A-Za-z0-9]+]], @[[mod_sym:[_A-Za-z0-9_]+]]::@bar, @Bar]
// CHECK-NEXT: hw.hierpath private @nla3 [@Foo::@[[inst_sym]], @[[mod_sym]]::@baz]
//
// CHECK: firrtl.module {{.*}} @[[mod_sym]]()
// CHECK-NEXT: firrtl.instance bar sym @bar
// CHECK-NEXT: firrtl.wire sym @baz
//
// CHECK: firrtl.module @Foo()
// CHECK-NEXT: firrtl.wire sym @foo_A :
// CHECK-NEXT: firrtl.instance {{.*}} sym @[[inst_sym]]
// -----
// Check the output file behavior when both a DUT and a testbench directory are
// specified. In the test below, Foo is the testbench and Bar is the DUT.
firrtl.circuit "Foo" attributes {
annotations = [
{
class = "sifive.enterprise.firrtl.TestBenchDirAnnotation",
dirname = "testbench"
}
]
} {
firrtl.layer @A bind attributes {output_file = #hw.output_file<"testbench/", excludeFromFileList>} {}
firrtl.module @Bar() attributes {
annotations = [
{
class = "sifive.enterprise.firrtl.MarkDUTAnnotation"
}
]
} {
firrtl.layerblock @A {
%a = firrtl.wire : !firrtl.uint<1>
}
}
firrtl.module @Foo() {
firrtl.layerblock @A {
%a = firrtl.wire : !firrtl.uint<1>
}
}
}
// CHECK-LABEL: firrtl.circuit "Foo"
//
// CHECK: sv.verbatim
// CHECK-SAME: #hw.output_file<"testbench{{/|\\\\}}layers-Foo-A.sv", excludeFromFileList>
//
// CHECK: firrtl.module {{.*}} @Bar_A
// CHECK-SAME: #hw.output_file<"testbench{{/|\\\\}}", excludeFromFileList>
// CHECK: firrtl.module {{.*}} @Foo_A
// CHECK-SAME: #hw.output_file<"testbench{{/|\\\\}}", excludeFromFileList>
//
// CHECK: sv.verbatim
// CHECK-SAME: #hw.output_file<"testbench{{/|\\\\}}layers-Foo-A.sv", excludeFromFileList>
// -----
// Check that we correctly implement the verilog header and footer for B.
firrtl.circuit "Foo" {
firrtl.layer @A bind {
firrtl.layer @X bind {}
}
firrtl.layer @B bind {}
firrtl.module @Foo() {}
}
// CHECK: firrtl.circuit "Foo" {
// CHECK: sv.verbatim "`ifndef layers_Foo_B\0A`define layers_Foo_B" {output_file = #hw.output_file<"layers-Foo-B.sv", excludeFromFileList>}
// CHECK: firrtl.module @Foo() {
// CHECK: }
// CHECK: sv.verbatim "`endif // layers_Foo_B" {output_file = #hw.output_file<"layers-Foo-B.sv", excludeFromFileList>}
// CHECK: }
// -----
// Check rwprobe ops are updated.
// CHECK-LABEL: circuit "RWTH"
firrtl.circuit "RWTH" {
firrtl.layer @T bind { }
firrtl.module @RWTH() attributes {convention = #firrtl<convention scalarized>, layers = [@T]} {
%d_p = firrtl.instance d @DUT(out p: !firrtl.rwprobe<uint<1>, @T>)
%one = firrtl.constant 1 : !firrtl.uint<1>
firrtl.ref.force_initial %one, %d_p, %one: !firrtl.uint<1>, !firrtl.rwprobe<uint<1>, @T>, !firrtl.uint<1>
}
// CHECK: firrtl.module private @DUT_T(out %p: !firrtl.rwprobe<uint<1>>) {
// CHECK-NEXT: %w = firrtl.wire sym @[[SYM:.+]] : !firrtl.uint<1>
// CHECK-NEXT: %0 = firrtl.ref.rwprobe <@DUT_T::@[[SYM]]> : !firrtl.rwprobe<uint<1>>
// CHECK-NEXT: firrtl.ref.define %p, %0 : !firrtl.rwprobe<uint<1>>
// CHECK-NEXT: }
// CHECK-NEXT: firrtl.module @DUT(out %p: !firrtl.rwprobe<uint<1>>) attributes {convention = #firrtl<convention scalarized>} {
// CHECK-NEXT: %t_p = firrtl.instance t sym @t {lowerToBind, output_file = #hw.output_file<"layers-RWTH-T.sv", excludeFromFileList>} @DUT_T(out p: !firrtl.rwprobe<uint<1>>)
// CHECK-NEXT: firrtl.ref.define %p, %t_p : !firrtl.rwprobe<uint<1>>
// CHECK-NEXT: }
firrtl.module @DUT(out %p: !firrtl.rwprobe<uint<1>, @T>) attributes {convention = #firrtl<convention scalarized>} {
firrtl.layerblock @T {
%w = firrtl.wire sym @sym : !firrtl.uint<1>
%0 = firrtl.ref.rwprobe <@DUT::@sym> : !firrtl.rwprobe<uint<1>>
%1 = firrtl.ref.cast %0 : (!firrtl.rwprobe<uint<1>>) -> !firrtl.rwprobe<uint<1>, @T>
firrtl.ref.define %p, %1 : !firrtl.rwprobe<uint<1>, @T>
}
}
}