summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/AutoNestedCloneSpec.scala
blob: 401766e2796570a41c5a8912867e068e510b9b85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: Apache-2.0

package chiselTests
import chisel3._
import chisel3.testers.TestUtils
import org.scalatest.matchers.should.Matchers

class BundleWithAnonymousInner(val w: Int) extends Bundle {
  val inner = new Bundle {
    val foo = Input(UInt(w.W))
  }
}

// TODO all `.suggestNames` are due to https://github.com/chipsalliance/chisel3/issues/1802
class AutoNestedCloneSpec extends ChiselFlatSpec with Matchers with Utils {
  val usingPlugin: Boolean = TestUtils.usingPlugin
  val elaborate = TestUtils.elaborateNoReflectiveAutoCloneType _

  behavior of "autoCloneType of inner Bundle in Chisel3"

  it should "clone a doubly-nested inner bundle successfully" in {
    elaborate {
      class Outer(val w: Int) extends Module {
        class Middle(val w: Int) {
          class InnerIOType extends Bundle {
            val in = Input(UInt(w.W))
          }
          def getIO: InnerIOType = new InnerIOType
        }
        val io = IO(new Bundle {}).suggestName("io")
        val myWire = Wire((new Middle(w)).getIO)
      }
      new Outer(2)
    }
  }

  it should "clone an anonymous inner bundle successfully" in {
    elaborate {
      class TestTop(val w: Int) extends Module {
        val io = IO(new Bundle {}).suggestName("io")
        val myWire = Wire(new Bundle{ val a = UInt(w.W) })
      }
      new TestTop(2)
    }
  }

  it should "pick the correct $outer instance for an anonymous inner bundle" in {
    elaborate {
      class Inner(val w: Int) extends Module {
        val io = IO(new Bundle{
          val in = Input(UInt(w.W))
          val out = Output(UInt(w.W))
        }).suggestName("io")
      }
      class Outer(val w: Int) extends Module {
        val io = IO(new Bundle{
          val in = Input(UInt(w.W))
          val out = Output(UInt(w.W))
        }).suggestName("io")
        val i = Module(new Inner(w))
        val iw = Wire(chiselTypeOf(i.io))
        iw <> io
        i.io <> iw
      }
      new Outer(2)
    }
  }

  it should "clone an anonymous, bound, inner bundle of another bundle successfully" in {
    elaborate {
      class TestModule(w: Int) extends Module {
        val io = IO(new BundleWithAnonymousInner(w) ).suggestName("io")
        val w0 = WireDefault(io)
        val w1 = WireDefault(io.inner)
      }
      new TestModule(8)
    }
  }

  it should "clone an anonymous, inner bundle of a Module, bound to another bundle successfully" in {
    elaborate {
      class TestModule(w: Int) extends Module {
        val bun = new Bundle {
          val foo = UInt(w.W)
        }
        val io = IO(new Bundle {
          val inner = Input(bun)
        }).suggestName("io")
        val w0 = WireDefault(io)
        val w1 = WireDefault(io.inner)
      }
      new TestModule(8)
    }
  }

  it should "clone a double-nested anonymous Bundle" in {
    elaborate {
      class TestModule() extends Module {
        val io = IO(new Bundle {
          val inner = Input(new Bundle {
            val x = UInt(8.W)
          })
        }).suggestName("io")
      }
      new TestModule()
    }
  }

  if (usingPlugin) {
    // This works with the plugin, but is a null pointer exception when using reflective autoclonetype
    it should "support an anonymous doubly-nested inner bundle" in {
      elaborate {
        class Outer(val w: Int) extends Module {
          class Middle(val w: Int) {
            def getIO: Bundle = new Bundle {
              val in = Input(UInt(w.W))
            }
          }
          val io = IO(new Bundle {}).suggestName("io")
          val myWire = Wire((new Middle(w)).getIO)
        }
        new Outer(2)
      }
    }

    it should "support anonymous Inner bundles that capture type parameters from outer Bundles" in {
      elaborate(new MultiIOModule {
        class MyBundle[T <: Data](n: Int, gen: T) extends Bundle {
          val foo = new Bundle {
            val x = Input(Vec(n, gen))
          }
          val bar = Output(Option(new { def mkBundle = new Bundle { val x = Vec(n, gen) }}).get.mkBundle)
        }
        val io = IO(new MyBundle(4, UInt(8.W)))
        val myWire = WireInit(io.foo)
        val myWire2 = WireInit(io.bar)
        io.bar.x := io.foo.x
      })
    }
  }
}