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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
|
// SPDX-License-Identifier: Apache-2.0
package chiselTests
import chisel3._
import chisel3.stage.ChiselStage
import chisel3.testers.BasicTester
import chisel3.util._
class FailingAssertTester() extends BasicTester {
assert(false.B)
// Wait to come out of reset
val (_, done) = Counter(!reset.asBool, 4)
when(done) {
stop()
}
}
class SucceedingAssertTester() extends BasicTester {
assert(true.B)
// Wait to come out of reset
val (_, done) = Counter(!reset.asBool, 4)
when(done) {
stop()
}
}
class PipelinedResetModule extends Module {
val io = IO(new Bundle {})
val a = RegInit(0xbeef.U)
val b = RegInit(0xbeef.U)
assert(a === b)
}
// This relies on reset being asserted for 3 or more cycles
class PipelinedResetTester extends BasicTester {
val module = Module(new PipelinedResetModule)
module.reset := RegNext(RegNext(RegNext(reset)))
val (_, done) = Counter(!reset.asBool, 4)
when(done) {
stop()
}
}
class ModuloAssertTester extends BasicTester {
assert((4.U % 2.U) === 0.U)
stop()
}
class FormattedAssertTester extends BasicTester {
val foobar = Wire(UInt(32.W))
foobar := 123.U
assert(foobar === 123.U, "Error! Wire foobar =/= %x! This is 100%% wrong.\n", foobar)
stop()
}
class BadUnescapedPercentAssertTester extends BasicTester {
assert(1.U === 1.U, "I'm 110% sure this is an invalid message")
stop()
}
class PrintableFormattedAssertTester extends BasicTester {
val foobar = Wire(UInt(32.W))
foobar := 123.U
assert(foobar === 123.U, cf"Error! Wire foobar =/= $foobar%x This is 100%% wrong.\n")
stop()
}
class PrintableBadUnescapedPercentAssertTester extends BasicTester {
assert(1.U === 1.U, p"I'm 110% sure this is an invalid message")
stop()
}
class PrintableAssumeTester extends Module {
val in = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
val w = Wire(UInt(8.W))
w := 255.U
assume(w === 255.U, cf"Assumption failed, Wire w =/= $w%x")
out := in
}
class PrintableScopeTester extends Module {
val in = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
out := in
val w = Wire(UInt(8.W))
w := 255.U
val printableWire = cf"$w"
val printablePort = cf"$in"
}
class AssertPrintableWireScope extends BasicTester {
val mod = Module(new PrintableScopeTester)
assert(1.U === 2.U, mod.printableWire)
stop()
}
class AssertPrintablePortScope extends BasicTester {
val mod = Module(new PrintableScopeTester)
mod.in := 255.U
assert(1.U === 1.U, mod.printablePort)
stop()
}
class AssertPrintableFailingWhenScope extends BasicTester {
val mod = Module(new PrintableWhenScopeTester)
assert(1.U === 1.U, mod.printable)
stop()
}
class AssumePrintableWireScope extends BasicTester {
val mod = Module(new PrintableScopeTester)
assume(1.U === 1.U, mod.printableWire)
stop()
}
class AssumePrintablePortScope extends BasicTester {
val mod = Module(new PrintableScopeTester)
mod.in := 255.U
assume(1.U === 1.U, mod.printablePort)
stop()
}
class PrintableWhenScopeTester extends Module {
val in = IO(Input(UInt(8.W)))
val out = IO(Output(UInt(8.W)))
out := in
val w = Wire(UInt(8.W))
w := 255.U
var printable = cf""
when(true.B) {
printable = cf"$w"
}
}
class AssertSpec extends ChiselFlatSpec with Utils {
"A failing assertion" should "fail the testbench" in {
assert(!runTester { new FailingAssertTester })
}
"A succeeding assertion" should "not fail the testbench" in {
assertTesterPasses { new SucceedingAssertTester }
}
"An assertion" should "not assert until we come out of reset" in {
assertTesterPasses { new PipelinedResetTester }
}
"Assert Printables" should "respect port scoping" in {
assertTesterPasses { new AssertPrintablePortScope }
}
"Assert Printables" should "respect wire scoping" in {
a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssertPrintableWireScope) }
}
"Assume Printables" should "respect port scoping" in {
assertTesterPasses { new AssumePrintablePortScope }
}
"Assume Printables" should "respect wire scoping" in {
a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssumePrintableWireScope) }
}
"Assert Printables" should "respect when scope" in {
a[ChiselException] should be thrownBy { ChiselStage.elaborate(new AssertPrintableFailingWhenScope) }
}
"Assertions" should "allow the modulo operator % in the message" in {
assertTesterPasses { new ModuloAssertTester }
}
they should "allow printf-style format strings with arguments" in {
assertTesterPasses { new FormattedAssertTester }
}
they should "allow printf-style format strings in Assumes" in {
val chirrtl = ChiselStage.emitChirrtl(new PrintableAssumeTester)
chirrtl should include(
"""assume(w === 255.U, cf\"Assumption failed, Wire w =/= $w%%%%x\")\n", w)"""
)
}
they should "not allow unescaped % in the message" in {
a[java.util.UnknownFormatConversionException] should be thrownBy {
extractCause[java.util.UnknownFormatConversionException] {
ChiselStage.elaborate { new BadUnescapedPercentAssertTester }
}
}
}
they should "allow printable format strings with arguments" in {
assertTesterPasses { new FormattedAssertTester }
}
they should "not allow unescaped % in the printable message" in {
a[java.util.UnknownFormatConversionException] should be thrownBy {
extractCause[java.util.UnknownFormatConversionException] {
ChiselStage.elaborate { new BadUnescapedPercentAssertTester }
}
}
}
}
|