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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
|
// SPDX-License-Identifier: Apache-2.0
package chiselTests.stage
import chisel3._
import chisel3.stage.ChiselStage
import chisel3.testers.TesterDriver.createTestDirectory
import chiselTests.Utils
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import firrtl.options.Dependency
object ChiselStageSpec {
class Bar extends Module {
val in = IO(Input(UInt(4.W)))
val out = IO(Output(UInt(4.W)))
out := ~in
}
class Foo extends Module {
val addr = IO(Input(UInt(4.W)))
val out = IO(Output(Bool()))
val memory = SyncReadMem(8, Bool())
val bar = Module(new Bar)
bar.in := addr
out := memory(bar.out)
}
class UserExceptionModule extends RawModule {
assert(false, "User threw an exception")
}
class UserExceptionNoStackTrace extends RawModule {
throw new Exception("Something bad happened") with scala.util.control.NoStackTrace
}
class RecoverableError extends RawModule {
3.U >> -1
}
}
class ChiselStageSpec extends AnyFlatSpec with Matchers with Utils {
import ChiselStageSpec._
private trait ChiselStageFixture {
val stage = new ChiselStage
}
behavior.of("ChiselStage$.emitChirrtl")
it should "return a CHIRRTL string" in {
ChiselStage.emitChirrtl(new Foo) should include("infer mport")
}
behavior.of("ChiselStage$.emitFirrtl")
it should "return a High FIRRTL string" in {
ChiselStage.emitFirrtl(new Foo) should include("mem memory")
}
it should "return a flattened FIRRTL string with '-e high'" in {
val args = Array("-e", "high", "-td", createTestDirectory(this.getClass.getSimpleName).toString)
(new ChiselStage)
.emitFirrtl(new Foo, args) should include("module Bar")
}
behavior.of("ChiselStage$.emitVerilog")
it should "return a Verilog string" in {
ChiselStage.emitVerilog(new Foo) should include("endmodule")
}
it should "return a flattened Verilog string with '-e verilog'" in {
val args = Array("-e", "verilog", "-td", createTestDirectory(this.getClass.getSimpleName).toString)
(new ChiselStage)
.emitVerilog(new Foo, args) should include("module Bar")
}
behavior.of("ChiselStage$.elaborate")
ignore should "generate a Chisel circuit from a Chisel module" in {
info("no files were written")
catchWrites { ChiselStage.elaborate(new Foo) } shouldBe a[Right[_, _]]
}
behavior.of("ChiselStage$.convert")
ignore should "generate a CHIRRTL circuit from a Chisel module" in {
info("no files were written")
catchWrites { ChiselStage.convert(new Foo) } shouldBe a[Right[_, _]]
}
ignore should "generate a FIRRTL circuit from a CHIRRTL circuit" in {
info("no files were written")
catchWrites {
ChiselStage.convert(ChiselStage.elaborate(new Foo))
} shouldBe a[Right[_, _]]
}
behavior.of("ChiselStage$.emitChirrtl")
ignore should "generate a CHIRRTL string from a Chisel module" in {
val wrapped = catchWrites { ChiselStage.emitChirrtl(new Foo) }
info("no files were written")
wrapped shouldBe a[Right[_, _]]
info("returned string looks like FIRRTL")
wrapped.right.get should include("circuit")
}
behavior.of("ChiselStage$.emitFirrtl")
ignore should "generate a FIRRTL string from a Chisel module" in {
val wrapped = catchWrites { ChiselStage.emitFirrtl(new Foo) }
info("no files were written")
wrapped shouldBe a[Right[_, _]]
info("returned string looks like FIRRTL")
wrapped.right.get should include("circuit")
}
behavior.of("ChiselStage$.emitVerilog")
ignore should "generate a Verilog string from a Chisel module" in {
val wrapped = catchWrites { ChiselStage.emitVerilog(new Foo) }
info("no files were written")
wrapped shouldBe a[Right[_, _]]
info("returned string looks like Verilog")
wrapped.right.get should include("endmodule")
}
behavior.of("ChiselStage$.emitSystemVerilog")
ignore should "generate a SystemvVerilog string from a Chisel module" in {
val wrapped = catchWrites { ChiselStage.emitSystemVerilog(new Foo) }
info("no files were written")
wrapped shouldBe a[Right[_, _]]
info("returned string looks like Verilog")
wrapped.right.get should include("endmodule")
}
behavior.of("ChiselStage phase ordering")
it should "only run elaboration once" in new ChiselStageFixture {
info("Phase order is:\n" + stage.phaseManager.prettyPrint(" "))
val order = stage.phaseManager.flattenedTransformOrder.map(Dependency.fromTransform)
info("Elaborate only runs once")
exactly(1, order) should be(Dependency[chisel3.stage.phases.Elaborate])
}
behavior.of("ChiselStage$ exception handling")
it should "truncate a user exception" in {
info("The user's java.lang.AssertionError was thrown")
val exception = intercept[java.lang.AssertionError] {
ChiselStage.emitChirrtl(new UserExceptionModule)
}
val message = exception.getMessage
info("The exception includes the user's message")
message should include("User threw an exception")
info("The stack trace is trimmed")
(exception.getStackTrace.mkString("\n") should not).include("java")
}
it should "NOT add a stack trace to an exception with no stack trace" in {
val exception = intercept[java.lang.Exception] {
ChiselStage.emitChirrtl(new UserExceptionNoStackTrace)
}
val message = exception.getMessage
info("The exception includes the user's message")
message should include("Something bad happened")
info("The exception should not contain a stack trace")
exception.getStackTrace should be(Array())
}
it should "NOT include a stack trace for recoverable errors" in {
val exception = intercept[java.lang.Exception] {
ChiselStage.emitChirrtl(new RecoverableError)
}
val message = exception.getMessage
info("The exception includes the standard error message")
message should include("Fatal errors during hardware elaboration. Look above for error list.")
info("The exception should not contain a stack trace")
exception.getStackTrace should be(Array())
}
behavior.of("ChiselStage exception handling")
it should "truncate a user exception" in {
info("The user's java.lang.AssertionError was thrown")
val exception = intercept[java.lang.AssertionError] {
(new ChiselStage).emitChirrtl(new UserExceptionModule)
}
info(s""" - Exception was a ${exception.getClass.getName}""")
val message = exception.getMessage
info("The exception includes the user's message")
message should include("User threw an exception")
val stackTrace = exception.getStackTrace.mkString("\n")
info("The stack trace is trimmed")
(stackTrace should not).include("java")
info("The stack trace include information about running --full-stacktrace")
stackTrace should include("--full-stacktrace")
}
it should """not truncate a user exception with "--full-stacktrace"""" in {
info("The user's java.lang.AssertionError was thrown")
val exception = intercept[java.lang.AssertionError] {
(new ChiselStage).emitChirrtl(new UserExceptionModule, Array("--full-stacktrace"))
}
info(s""" - Exception was a ${exception.getClass.getName}""")
val message = exception.getMessage
info("The exception includes the user's message")
message should include("User threw an exception")
info("The stack trace is not trimmed")
exception.getStackTrace.mkString("\n") should include("java")
}
it should "NOT add a stack trace to an exception with no stack trace" in {
val exception = intercept[java.lang.Exception] {
(new ChiselStage).emitChirrtl(new UserExceptionNoStackTrace)
}
val message = exception.getMessage
info("The exception includes the user's message")
message should include("Something bad happened")
info("The exception should not contain a stack trace")
exception.getStackTrace should be(Array())
}
it should "NOT include a stack trace for recoverable errors" in {
val exception = intercept[java.lang.Exception] {
(new ChiselStage).emitChirrtl(new RecoverableError)
}
val message = exception.getMessage
info("The exception includes the standard error message")
message should include("Fatal errors during hardware elaboration. Look above for error list.")
info("The exception should not contain a stack trace")
exception.getStackTrace should be(Array())
}
it should "include a stack trace for recoverable errors with '--throw-on-first-error'" in {
val exception = intercept[java.lang.Exception] {
(new ChiselStage).emitChirrtl(new RecoverableError, Array("--throw-on-first-error"))
}
val stackTrace = exception.getStackTrace.mkString("\n")
info("The exception should contain a truncated stack trace")
stackTrace shouldNot include("java")
info("The stack trace include information about running --full-stacktrace")
stackTrace should include("--full-stacktrace")
}
it should "include an untruncated stack trace for recoverable errors when given both '--throw-on-first-error' and '--full-stacktrace'" in {
val exception = intercept[java.lang.Exception] {
val args = Array("--throw-on-first-error", "--full-stacktrace")
(new ChiselStage).emitChirrtl(new RecoverableError, args)
}
val stackTrace = exception.getStackTrace.mkString("\n")
info("The exception should contain a truncated stack trace")
stackTrace should include("java")
}
}
|