aboutsummaryrefslogtreecommitdiff
path: root/src/test/scala/firrtlTests/transforms/LegalizeClocksAndAsyncResets.scala
blob: d28fbcc2c03ca40ad7c18704a275e7ffb05a65df (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
142
143
144
145
146
147
// SPDX-License-Identifier: Apache-2.0

package firrtlTests.transforms

import firrtl._
import firrtl.testutils._
import firrtl.testutils.FirrtlCheckers.containLine

class LegalizeClocksTransformSpec extends FirrtlFlatSpec {
  def compile(input: String): CircuitState =
    (new MinimumVerilogCompiler).compileAndEmit(CircuitState(parse(input), ChirrtlForm), Nil)

  behavior.of("LegalizeClocksTransform")

  it should "not emit @(posedge 1'h0) for stop" in {
    val input =
      """circuit test :
        |  module test :
        |    stop(asClock(UInt(1)), UInt(1), 1)
        |""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge _GEN_0) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge 1")
  }

  it should "not emit @(posedge 1'h0) for printf" in {
    val input =
      """circuit test :
        |  module test :
        |    printf(asClock(UInt(1)), UInt(1), "hi")
        |""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge _GEN_0) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge 1")
  }

  it should "not emit @(posedge 1'h0) for reg" in {
    val input =
      """circuit test :
        |  module test :
        |    output out : UInt<8>
        |    input in : UInt<8>
        |    reg r : UInt<8>, asClock(UInt(0))
        |    r <= in
        |    out <= r
        |""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge _GEN_0) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge 1")
  }

  it should "not emit @(posedge 1'h0) for mem" in {
    val input =
      """circuit test :
        |  module test :
        |    output rdata : UInt<8>
        |    input wdata : UInt<8>
        |    input addr : UInt<5>
        |    mem m :
        |      data-type => UInt<8>
        |      depth => 32
        |      read-latency => 0
        |      write-latency => 1
        |      reader => r
        |      writer => w
        |      read-under-write => undefined
        |    m.r.clk <= asClock(UInt(0))
        |    m.r.en <= UInt(1)
        |    m.r.addr <= addr
        |    rdata <= m.r.data
        |    m.w.clk <= asClock(UInt(0))
        |    m.w.en <= UInt(1)
        |    m.w.mask <= UInt(1)
        |    m.w.addr <= addr
        |    m.w.data <= wdata
        |""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge _GEN_1) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge 1")
  }

  it should "not emit @(posedge clock or posedge 1'h0) for a constantly deasserted areset" in {
    val input = """circuit test :
                  |  module test :
                  |    input clock : Clock
                  |    input i: UInt<1>
                  |    output z: UInt<1>
                  |    wire reset : AsyncReset
                  |    reset <= asAsyncReset(UInt<1>("h0"))
                  |    reg r : UInt<1>, clock with : (reset => (reset, UInt(0)))
                  |    r <= i
                  |    z <= r""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge clock or posedge _GEN_0) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge clock or posedge 1")
  }

  it should "not emit @(posedge clock or posedge 1'h1) for a constantly asserted areset" in {
    val input = """circuit test :
                  |  module test :
                  |    input clock : Clock
                  |    input i: UInt<1>
                  |    output z: UInt<1>
                  |    wire reset : AsyncReset
                  |    reset <= asAsyncReset(UInt<1>("h1"))
                  |    reg r : UInt<1>, clock with : (reset => (reset, UInt(0)))
                  |    r <= i
                  |    z <= r""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge clock or posedge _GEN_0) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge clock or posedge 1")
  }

  it should "not emit @(posedge 1'h0 or posedge 1'h0) for a reg with tied off clocks and areset" in {
    val input = """circuit test :
                  |  module test :
                  |    input i: UInt<1>
                  |    output z: UInt<1>
                  |    wire clock : Clock
                  |    clock <= asClock(UInt(1))
                  |    wire reset : AsyncReset
                  |    reset <= asAsyncReset(UInt<1>("h0"))
                  |    reg r : UInt<1>, clock with : (reset => (reset, UInt(0)))
                  |    r <= i
                  |    z <= r""".stripMargin
    val result = compile(input)
    result should containLine(s"always @(posedge _GEN_0 or posedge _GEN_1) begin")
    result.getEmittedCircuit.value shouldNot include("always @(posedge clock or posedge 1")
    result.getEmittedCircuit.value shouldNot include("or posedge 1")
  }

  it should "deduplicate injected nodes for literal clocks" in {
    val input =
      """circuit test :
        |  module test :
        |    printf(asClock(UInt(1)), UInt(1), "hi")
        |    stop(asClock(UInt(1)), UInt(1), 1)
        |""".stripMargin
    val result = compile(input)
    result should containLine(s"wire  _GEN_0 = 1'h1;")
    // Check that there's only 1 _GEN_0 instantiation
    val verilog = result.getEmittedCircuit.value
    val matches = "wire\\s+_GEN_0\\s+=\\s+1'h1".r.findAllIn(verilog)
    matches.size should be(1)

  }
}