summaryrefslogtreecommitdiff
path: root/src/test/scala/chiselTests/experimental/ForceNames.scala
blob: 233b4a5fa3508e975bbffd550983c50181837a43 (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
// See LICENSE for license details.

package chiselTests

import firrtl._
import chisel3._
import chisel3.experimental.annotate
import chisel3.stage.{ChiselGeneratorAnnotation, ChiselStage}
import chisel3.util.experimental.{forceName, ForceNameAnnotation, ForceNamesTransform, InlineInstance}
import firrtl.annotations.{Annotation, ReferenceTarget}
import firrtl.options.{Dependency, TargetDirAnnotation}
import firrtl.stage.RunFirrtlTransformAnnotation
import logger.{LogLevel, LogLevelAnnotation}

/** Object containing Modules used for testing */
object ForceNamesHierarchy {
  class WrapperExample extends Module {
    val in = IO(Input(UInt(3.W)))
    val out = IO(Output(UInt(3.W)))
    val inst = Module(new Wrapper)
    inst.in := in
    out := inst.out
    forceName(out, "outt")
  }
  class Wrapper extends Module with InlineInstance {
    val in = IO(Input(UInt(3.W)))
    val out = IO(Output(UInt(3.W)))
    val inst = Module(new MyLeaf)
    forceName(inst, "inst")
    inst.in := in
    out := inst.out
  }
  class MyLeaf extends Module {
    val in = IO(Input(UInt(3.W)))
    val out = IO(Output(UInt(3.W)))
    out := in
  }
  class RenamePortsExample extends Module {
    val in = IO(Input(UInt(3.W)))
    val out = IO(Output(UInt(3.W)))
    val inst = Module(new MyLeaf)
    inst.in := in
    out := inst.out
    forceName(inst.in, "inn")
  }
  class ConflictingName extends Module {
    val in = IO(Input(UInt(3.W)))
    val out = IO(Output(UInt(3.W)))
    out := in
    forceName(out, "in")
  }
  class BundleName extends Module {
    val in = IO(new Bundle {
      val a = Input(UInt(3.W))
      val b = Input(UInt(3.W))
    })
    val out = IO(Output(UInt(3.W)))
    out := in.a + in.b
  }
}

class ForceNamesSpec extends ChiselFlatSpec {

  def run[T <: RawModule](
    dut:        => T,
    testName:   String,
    inputAnnos: Seq[Annotation] = Nil,
    info:       LogLevel.Value = LogLevel.None
  ): Iterable[String] = {
    def stage = new ChiselStage {
      override val targets = Seq(
        Dependency[chisel3.stage.phases.Elaborate],
        Dependency[chisel3.stage.phases.Convert],
        Dependency[firrtl.stage.phases.Compiler]
      )
    }

    val annos = List(
      TargetDirAnnotation("test_run_dir/ForceNames"),
      LogLevelAnnotation(info),
      ChiselGeneratorAnnotation(() => dut)
    ) ++ inputAnnos

    val ret = stage.execute(Array(), annos)
    val verilog = ret.collectFirst {
      case e: EmittedVerilogCircuitAnnotation => e.value.value
    }.get

    verilog.split("\\\n")
  }
  "Force Names on a wrapping instance" should "work" in {
    val verilog = run(new ForceNamesHierarchy.WrapperExample, "wrapper")
    exactly(1, verilog) should include("MyLeaf inst")
  }
  "Force Names on an instance port" should "work" in {
    val verilog = run(new ForceNamesHierarchy.RenamePortsExample, "instports")
    atLeast(1, verilog) should include("input  [2:0] inn")
  }
  "Force Names with a conflicting name" should "error" in {
    intercept[CustomTransformException] {
      run(new ForceNamesHierarchy.ConflictingName, "conflicts")
    }
  }
  "Force Names of an intermediate bundle" should "error" in {
    intercept[CustomTransformException] {
      run(
        new ForceNamesHierarchy.BundleName,
        "bundlename",
        Seq(ForceNameAnnotation(ReferenceTarget("BundleName", "BundleName", Nil, "in", Nil), "inn"))
      )
    }
  }
}