Skip to content

Commit

Permalink
Optimize .readOnly to only create views when necessary (#4271) (#4273)
Browse files Browse the repository at this point in the history
(cherry picked from commit 478eaef)

Co-authored-by: Jack Koenig <koenig@sifive.com>
  • Loading branch information
mergify[bot] and jackkoenig authored Jul 11, 2024
1 parent db47e0d commit 0ee2dc8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 1 deletion.
7 changes: 6 additions & 1 deletion core/src/main/scala/chisel3/Data.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,12 @@ object Data {
* This Data this method is called on must be a hardware type.
*/
def readOnly(implicit sourceInfo: SourceInfo): T = {
self.viewAsReadOnly(_ => "Cannot connect to read-only value")
val alreadyReadOnly = self.isLit || self.topBindingOpt.exists(_.isInstanceOf[ReadOnlyBinding])
if (alreadyReadOnly) {
self
} else {
self.viewAsReadOnly(_ => "Cannot connect to read-only value")
}
}
}
}
Expand Down
29 changes: 29 additions & 0 deletions src/test/scala/chiselTests/ReadOnlySpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import chisel3.probe._
import chisel3.properties._
import chisel3.experimental.SourceInfo
import chisel3.experimental.dataview._
import chisel3.experimental.BundleLiterals._
import chisel3.experimental.VecLiterals._

import org.scalactic.source.Position

Expand Down Expand Up @@ -364,4 +366,31 @@ class ReadOnlySpec extends ChiselFlatSpec with Utils {
})
}
}

it should "NOT create a view for literals" in {
ChiselStage.emitCHIRRTL(new RawModule {
val a = 123.U
val b = -27.S
val c = (new BiggerBundle).Lit(_.fizz -> 123.U, _.buzz -> 456.U)
val d = Vec.Lit(0.U, 23.U)
// Use referential equality to check they are the same objects (no view introduced)
assert(a.readOnly eq a)
assert(b.readOnly eq b)
assert(c.readOnly eq c)
assert(d.readOnly eq d)
})
}

it should "NOT create a view for op results" in {
ChiselStage.emitCHIRRTL(new RawModule {
val a = IO(Input(UInt(8.W)))
val b = IO(Input(new BiggerBundle))

val x = a + 1.U
val y = b.asUInt
// Use referential equality to check they are the same objects (no view introduced)
assert(x.readOnly eq x)
assert(y.readOnly eq y)
})
}
}

0 comments on commit 0ee2dc8

Please sign in to comment.