Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scala.MatchError on EmptyExpression; only manifests in rocket-chip vsim/ directory. #292

Closed
ccelio opened this issue Sep 9, 2016 · 8 comments

Comments

@ccelio
Copy link

ccelio commented Sep 9, 2016

I suspect some sort of memory/SRAM pass is going wrong.

I'm using version (6a05468), but it also manifests on master (765b880).

This is on rocket-chip (using BOOM on boom branch), and everything works in the emulator/ build directory, but fails in the vsim/ directory.

Error message:

Exception in thread "main" scala.MatchError: EmptyExpression (of class firrtl.EmptyExpression$)
    at firrtl.passes.InferTypes$.firrtl$passes$InferTypes$$infer_types_e$1(Passes.scala:172)
    at firrtl.passes.InferTypes$$anonfun$7.apply(Passes.scala:172)
    at firrtl.passes.InferTypes$$anonfun$7.apply(Passes.scala:172)
    at firrtl.Mappers$ExpMagnet$$anon$5.map(Mappers.scala:112)
    at firrtl.Mappers$ExpMap.map(Mappers.scala:144)
    at firrtl.passes.InferTypes$.firrtl$passes$InferTypes$$infer_types_e$1(Passes.scala:172)
    at firrtl.passes.InferTypes$$anonfun$firrtl$passes$InferTypes$$infer_types_s$1$5.apply(Passes.scala:213)
    at firrtl.passes.InferTypes$$anonfun$firrtl$passes$InferTypes$$infer_types_s$1$5.apply(Passes.scala:213)
    at firrtl.Mappers$StmtMagnet$$anon$3.map(Mappers.scala:54)
    at firrtl.Mappers$StmtMap.map(Mappers.scala:95)
    at firrtl.passes.InferTypes$.firrtl$passes$InferTypes$$infer_types_s$1(Passes.scala:213)
    at firrtl.passes.InferTypes$$anonfun$firrtl$passes$InferTypes$$infer_types_s$1$3.apply(Passes.scala:213)
    at firrtl.passes.InferTypes$$anonfun$firrtl$passes$InferTypes$$infer_types_s$1$3.apply(Passes.scala:213)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
    at scala.collection.immutable.List.map(List.scala:285)
    at firrtl.Mappers$StmtMagnet$$anon$4.map(Mappers.scala:44)
    at firrtl.Mappers$StmtMap.map(Mappers.scala:95)
    at firrtl.passes.InferTypes$.firrtl$passes$InferTypes$$infer_types_s$1(Passes.scala:213)
    at firrtl.passes.InferTypes$.firrtl$passes$InferTypes$$infer_types$1(Passes.scala:220)
    at firrtl.passes.InferTypes$$anonfun$run$2.apply(Passes.scala:236)
    at firrtl.passes.InferTypes$$anonfun$run$2.apply(Passes.scala:236)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
    at scala.collection.mutable.ResizableArray$class.foreach(ResizableArray.scala:59)
    at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:48)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
    at scala.collection.AbstractTraversable.map(Traversable.scala:104)
    at firrtl.passes.InferTypes$.run(Passes.scala:236)
    at firrtl.passes.ReplSeqMem$$anonfun$execute$1$$anonfun$7.apply(ReplSeqMem.scala:128)
    at firrtl.passes.ReplSeqMem$$anonfun$execute$1$$anonfun$7.apply(ReplSeqMem.scala:128)
    at firrtl.Utils$.time(Utils.scala:57)
    at firrtl.passes.ReplSeqMem$$anonfun$execute$1.apply(ReplSeqMem.scala:128)
    at firrtl.passes.ReplSeqMem$$anonfun$execute$1.apply(ReplSeqMem.scala:127)
    at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:124)
    at scala.collection.immutable.List.foldLeft(List.scala:84)
    at firrtl.passes.ReplSeqMem.execute(ReplSeqMem.scala:126)
    at firrtl.Compiler$$anonfun$compile$1.apply(Compiler.scala:71)
    at firrtl.Compiler$$anonfun$compile$1.apply(Compiler.scala:70)
    at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:124)
    at scala.collection.immutable.List.foldLeft(List.scala:84)
    at firrtl.Compiler$class.compile(Compiler.scala:70)
    at firrtl.VerilogCompiler.compile(LoweringCompilers.scala:199)
    at firrtl.Driver$.compile(Driver.scala:109)
    at firrtl.Driver$.run(Driver.scala:183)
    at firrtl.Driver$.main(Driver.scala:86)
    at firrtl.Driver.main(Driver.scala)
make: *** [/scratch/celio/boom-chip/vsim/generated-src/TestHarness.BOOMConfig.v] Error 1

To replicate:

git clone https://github.com/ucb-bar/rocket-chip.git
cd rocket-chip
git checkout boom
git submodule update --init
cd vsim
make run CONFIG=BOOMConfig
@shunshou
Copy link
Contributor

shunshou commented Sep 9, 2016

Can you e-mail me the Chisel generated *.fir file?

@ccelio
Copy link
Author

ccelio commented Sep 9, 2016

Sent.

@shunshou
Copy link
Contributor

Ok, figured out my bug. @jackkoenig gave me a suggestion on how to handle it, but what's the best generalized solution to this? b/c I'm sure this'll come up over and over again. (Something great for FIRRTL pass writing tutorial, @azidar ).

Had a function

def updateStmtRefs(s: Statement): Statement = s map updateStmtRefs map updateRef match {
      case Connect(info, EmptyExpression, exp) => EmptyStmt 
      case Connect(info, WSubIndex(EmptyExpression, _, _, _), exp)  => EmptyStmt
      case s => s
    }

But I was missing Connect(_,WSubField(EmptyExpression, ... (and possibly more??)

Is there some way to guarantee our cases are complete? It kind of requires knowledge of all of the possible WSubField, WSubIndex, etc. FIRRTL can use??? I really just want to find every time an EmptyExpression is used, so Jack recommended something like:

def hasEmptyExpr(stmt: Statement): Boolean = {
      var found = false
      def rec(e: Expression): Expression = {
        e map rec match {
          case EmptyExpression => found = true
          case _ =>
        }
        e
      }
      stmt map rec
      found
    }
    def updateStmtRefs(s: Statement): Statement = s map updateStmtRefs map updateRef match {
      case c: Connect if hasEmptyExpr(c) => EmptyStmt
      case s => s
    }
    updateStmtRefs(s)

This requires that you know how to properly use the FIRRTL mappers and seems pretty intense given what I'm trying to actually find...

Anywho, will PR this as a bug fix for now...

@shunshou
Copy link
Contributor

Also, @sdtwigg made a good point. @azidar @jackkoenig @donggyukim You should prob case out the match on EmptyExpression and print out the Statement it failed on. Would be more useful than trying to look for where it was generated manually. [And I probably would've had a harder time println-ing to look for WSubField(EmptyExpression...) if not for println-ing after already switching to Jack's solution -- b/c BOOM is huge xD].

@jackkoenig
Copy link
Contributor

I agree with the suggestion that internal errors include some sort of stack trace of where we are in the firrtl design along with the current stack trace of what function we are in. I'm not sure how to do this off the top of my head, any suggestions @sdtwigg?

@jackkoenig
Copy link
Contributor

Since you can arbitrarily nest Expressions, I do not believe it is possible for the type system or anything to guarantee you have exhaustively put all the cases. The most general way to check for all possible cases is exactly what my recommended function does, it walks the whole Firrtl subtree looking for EmptyExpressions. It would definitely be better if we did this walk more functionally via a "foreach" or "fold" though.

@azidar
Copy link
Contributor

azidar commented Sep 13, 2016

Can I close this?

@ccelio
Copy link
Author

ccelio commented Sep 13, 2016

Yes, I'm happy with it.

@ccelio ccelio closed this as completed Sep 13, 2016
@azidar azidar removed this from Finished in Firrtl Development Mar 16, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants