summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authormergify[bot]2022-02-04 02:26:06 +0000
committerGitHub2022-02-04 02:26:06 +0000
commitdd5c643ae86c234041092efee4386cc82e59331d (patch)
tree355dae453c8380d9a83b7b038ed1269450c0ea43 /core
parent56d789c17cec32cb985ebce2651bf7269f95b5d1 (diff)
Fix bundle elements performance regression (#2396) (#2398)
* Only call _elementsImpl once in Bundle.elements * Distinguish compiler plugin and reflective _elementsImpl Bundle.elements now will only do post-processing if the user is using plugin-generated _elementsImpl. This improves performance for the case where the user does not opt-in to using the plugin to generate _elementsImpl. (cherry picked from commit 5fead89ee0132355e551bcb6b87cc2a6db679bee) Co-authored-by: Jack Koenig <koenig@sifive.com>
Diffstat (limited to 'core')
-rw-r--r--core/src/main/scala/chisel3/Aggregate.scala25
1 files changed, 19 insertions, 6 deletions
diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala
index ec64f28b..06ae36f3 100644
--- a/core/src/main/scala/chisel3/Aggregate.scala
+++ b/core/src/main/scala/chisel3/Aggregate.scala
@@ -1207,8 +1207,19 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
* assert(uint === "h12345678".U) // This will pass
* }}}
*/
- final lazy val elements: SeqMap[String, Data] = {
- val hardwareFields = _elementsImpl.flatMap {
+ final lazy val elements: SeqMap[String, Data] =
+ // _elementsImpl is a method, only call it once
+ _elementsImpl match {
+ // Those not using plugin-generated _elementsImpl use the old reflective implementation
+ case oldElements: VectorMap[_, _] => oldElements.asInstanceOf[VectorMap[String, Data]]
+ // Plugin-generated _elementsImpl are incomplete and need some processing
+ case rawElements => _processRawElements(rawElements)
+ }
+
+ // The compiler plugin is imperfect at picking out elements statically so we process at runtime
+ // checking for errors and filtering out mistakes
+ private def _processRawElements(rawElements: Iterable[(String, Any)]): SeqMap[String, Data] = {
+ val hardwareFields = rawElements.flatMap {
case (name, data: Data) =>
if (data.isSynthesizable) {
Some(s"$name: $data")
@@ -1241,7 +1252,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
if (hardwareFields.nonEmpty) {
throw ExpectedChiselTypeException(s"Bundle: $this contains hardware fields: " + hardwareFields.mkString(","))
}
- VectorMap(_elementsImpl.toSeq.flatMap {
+ VectorMap(rawElements.toSeq.flatMap {
case (name, data: Data) =>
Some(name -> data)
case (name, Some(data: Data)) =>
@@ -1251,15 +1262,17 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record {
case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn))
}: _*)
}
- /*
- * This method will be overwritten by the Chisel-Plugin
+
+ /* The old, reflective implementation of Bundle.elements
+ * This method is optionally overwritten by the compiler plugin for much better performance
*/
protected def _elementsImpl: Iterable[(String, Any)] = {
val nameMap = LinkedHashMap[String, Data]()
for (m <- getPublicFields(classOf[Bundle])) {
getBundleField(m) match {
case Some(d: Data) =>
- // Checking for chiselType is done in elements method
+ requireIsChiselType(d)
+
if (nameMap contains m.getName) {
require(nameMap(m.getName) eq d)
} else {