aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/parser
diff options
context:
space:
mode:
authorJack Koenig2021-08-31 14:10:29 -0700
committerJack Koenig2021-12-01 11:40:52 -0800
commit17250fba841ae3129dc798c0bc48d10200be18ae (patch)
tree37b93b1c487f78e39acd17f94faf5f5c3b24b9d8 /src/main/scala/firrtl/parser
parent64a0ca2512199c55e51ec90dbd3ec7d563472255 (diff)
Use ANTLR Listener to save memory during parsing
The ANTLR-generated concrete syntax tree (CST) takes up much more memory than the parsed .fir file. By using a Listener, we can construct the FIRRTL AST live with CST construction and null out the CST as we consume pieces of it. Not only does this improve performance, it drastically reduces max memory use for the parser.
Diffstat (limited to 'src/main/scala/firrtl/parser')
-rw-r--r--src/main/scala/firrtl/parser/Listener.scala38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/parser/Listener.scala b/src/main/scala/firrtl/parser/Listener.scala
new file mode 100644
index 00000000..ffaa22b2
--- /dev/null
+++ b/src/main/scala/firrtl/parser/Listener.scala
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package firrtl.parser
+
+import firrtl.antlr.{FIRRTLParser, _}
+import firrtl.Visitor
+import firrtl.Parser.InfoMode
+import firrtl.ir._
+
+import scala.collection.mutable
+import scala.concurrent.{Await, Future}
+import scala.concurrent.duration.Duration
+
+private[firrtl] class Listener(infoMode: InfoMode) extends FIRRTLBaseListener {
+ private var main: Option[String] = None
+ private var info: Option[Info] = None
+ private val modules = mutable.ArrayBuffer.empty[DefModule]
+
+ private val visitor = new Visitor(infoMode)
+
+ override def exitModule(ctx: FIRRTLParser.ModuleContext): Unit = {
+ val m = visitor.visitModule(ctx)
+ ctx.children = null // Null out to save memory
+ modules += m
+ }
+
+ override def exitCircuit(ctx: FIRRTLParser.CircuitContext): Unit = {
+ info = Some(visitor.visitInfo(Option(ctx.info), ctx))
+ main = Some(ctx.id.getText)
+ ctx.children = null // Null out to save memory
+ }
+
+ def getCircuit: Circuit = {
+ require(main.nonEmpty)
+ val mods = modules.toSeq
+ Circuit(info.get, mods, main.get)
+ }
+}