Skip to content

Commit 7ef6716

Browse files
jackkoenigucbjrl
authored andcommitted
Catch returns from within when blocks and provide an error message (#842)
Resolves #841 (cherry picked from commit b17998e)
1 parent 02ccdf6 commit 7ef6716

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

chiselFrontend/src/main/scala/chisel3/core/Module.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ object Module {
4949
val module: T = bc // bc is actually evaluated here
5050

5151
if (Builder.whenDepth != 0) {
52-
throwException("Internal Error! When depth is != 0, this should not be possible")
52+
throwException("Internal Error! when() scope depth is != 0, this should have been caught!")
5353
}
5454
if (Builder.readyForModuleConstr) {
5555
throwException("Error: attempted to instantiate a Module, but nothing happened. " +

chiselFrontend/src/main/scala/chisel3/core/When.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,14 @@ final class WhenContext(sourceInfo: SourceInfo, cond: Option[() => Bool], block:
7171
if (firrtlDepth > 0) { pushCommand(AltBegin(sourceInfo)) }
7272
cond.foreach( c => pushCommand(WhenBegin(sourceInfo, c().ref)) )
7373
Builder.whenDepth += 1
74-
block
74+
try {
75+
block
76+
} catch {
77+
case ret: scala.runtime.NonLocalReturnControl[_] =>
78+
throwException("Cannot exit from a when() block with a \"return\"!" +
79+
" Perhaps you meant to use Mux or a Wire as a return value?"
80+
)
81+
}
7582
Builder.whenDepth -= 1
7683
cond.foreach( c => pushCommand(WhenEnd(sourceInfo,firrtlDepth)) )
7784
if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) }

src/test/scala/chiselTests/When.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,4 +106,26 @@ class WhenSpec extends ChiselFlatSpec {
106106
"Conditional connections to submodule ports" should "be handled properly" in {
107107
assertTesterPasses(new SubmoduleWhenTester)
108108
}
109+
110+
"Returning in a when scope" should "give a reasonable error message" in {
111+
val e = the [ChiselException] thrownBy {
112+
elaborate(new Module {
113+
val io = IO(new Bundle {
114+
val foo = Input(UInt(8.W))
115+
val bar = Input(UInt(8.W))
116+
val cond = Input(Bool())
117+
val out = Output(UInt(8.W))
118+
})
119+
def func(): UInt = {
120+
when(io.cond) {
121+
// This is bad, do not do this!!!
122+
return io.foo
123+
}
124+
return io.bar
125+
}
126+
io.out := func()
127+
})
128+
}
129+
e.getMessage should include ("Cannot exit from a when() block with a \"return\"")
130+
}
109131
}

0 commit comments

Comments
 (0)