Skip to content

Commit 648366a

Browse files
Implement Lookupable for HasTarget (used by SRAM) (backport #4481) (#4482)
* Implement Lookupable for HasTarget (used by SRAM) (#4481) (cherry picked from commit a7a68e5) * Fix for 6.x --------- Co-authored-by: Jack Koenig <koenig@sifive.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent b84d108 commit 648366a

File tree

6 files changed

+64
-7
lines changed

6 files changed

+64
-7
lines changed

core/src/main/scala/chisel3/experimental/hierarchy/core/Lookupable.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,30 @@ object Lookupable {
412412
}
413413
}
414414

415+
// TODO, this, cloneMemToContext, and cloneDataToContext should be unified
416+
private def cloneHasTargetToContext(
417+
hasTarget: HasTarget,
418+
context: BaseModule
419+
)(
420+
implicit sourceInfo: SourceInfo
421+
): HasTarget = {
422+
hasTarget match {
423+
case HasTarget.Impl(st: MemBase[_]) =>
424+
HasTarget(cloneMemToContext(st, context))
425+
}
426+
}
427+
428+
implicit def lookupHasTarget(implicit sourceInfo: SourceInfo): Simple[HasTarget] =
429+
new Lookupable[HasTarget] {
430+
type C = HasTarget
431+
def definitionLookup[A](that: A => HasTarget, definition: Definition[A]): C = {
432+
cloneHasTargetToContext(that(definition.proto), definition.getInnerDataContext.get)
433+
}
434+
def instanceLookup[A](that: A => HasTarget, instance: Instance[A]): C = {
435+
cloneHasTargetToContext(that(instance.proto), instance.getInnerDataContext.get)
436+
}
437+
}
438+
415439
import scala.language.higherKinds // Required to avoid warning for lookupIterable type parameter
416440
implicit def lookupIterable[B, F[_] <: Iterable[_]](
417441
implicit sourceInfo: SourceInfo,

core/src/main/scala/chisel3/package.scala

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@ package object chisel3 {
420420

421421
/** Exposes target information and suggestName functionality of a NamedComponent.
422422
*/
423+
// This is only currently used for SRAM to hide the underlying Memory but still let users annotate it.
424+
// Rather than generalizing this, it's more likely that we'll just delete it (and the use in SRAM) in favor of Path Properties.
423425
sealed trait HasTarget {
424426
def toTarget: ReferenceTarget
425427
def toAbsoluteTarget: ReferenceTarget
@@ -434,17 +436,18 @@ package object chisel3 {
434436
}
435437

436438
object HasTarget {
437-
438-
/** This wrapping hides the actual object, ensuring users only have access
439-
* to the target methods (instead of the type of the underlying object).
440-
*/
441-
private[chisel3] def apply(t: NamedComponent): HasTarget = new HasTarget {
439+
private[chisel3] case class Impl(t: MemBase[_]) extends HasTarget {
442440
def toTarget = t.toTarget
443441
def toAbsoluteTarget = t.toAbsoluteTarget
444442
def toRelativeTarget(root: Option[BaseModule]) = t.toRelativeTarget(root)
445443

446444
def suggestName(seed: String): Unit = t.suggestName(seed)
447445
}
448446

447+
/** This wrapping hides the actual object, ensuring users only have access
448+
* to the target methods (instead of the type of the underlying object).
449+
*/
450+
private[chisel3] def apply(t: MemBase[_]): HasTarget = Impl(t)
451+
449452
}
450453
}

src/test/scala/chiselTests/experimental/hierarchy/Annotations.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ package chiselTests.experimental.hierarchy
44

55
import _root_.firrtl.annotations._
66
import chisel3.experimental.{annotate, BaseModule}
7-
import chisel3.{Data, MemBase}
7+
import chisel3.{Data, HasTarget, MemBase}
88
import chisel3.experimental.hierarchy.{Definition, Hierarchy, Instance}
99

1010
// These annotations exist purely for testing purposes
@@ -24,8 +24,13 @@ private[hierarchy] object Annotations {
2424
extends chisel3.experimental.ChiselAnnotation {
2525
def toFirrtl = if (isAbsolute) MarkAnnotation(m.toAbsoluteTarget, tag) else MarkAnnotation(m.toTarget, tag)
2626
}
27+
case class MarkChiselHasTargetAnnotation(d: HasTarget, tag: String, isAbsolute: Boolean)
28+
extends chisel3.experimental.ChiselAnnotation {
29+
def toFirrtl = if (isAbsolute) MarkAnnotation(d.toAbsoluteTarget, tag) else MarkAnnotation(d.toTarget, tag)
30+
}
2731
def mark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, false))
2832
def mark[T <: Data](d: MemBase[T], tag: String): Unit = annotate(MarkChiselMemAnnotation(d, tag, false))
33+
def mark(d: HasTarget, tag: String): Unit = annotate(MarkChiselHasTargetAnnotation(d, tag, false))
2934
def mark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true))
3035
def amark(d: Data, tag: String): Unit = annotate(MarkChiselAnnotation(d, tag, true))
3136
def amark[B <: BaseModule](d: Hierarchy[B], tag: String): Unit = annotate(MarkChiselHierarchyAnnotation(d, tag, true))

src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,16 @@ class DefinitionSpec extends ChiselFunSpec with Utils {
390390
"Cannot create a memory port in a different module (Top) than where the memory is (HasMems)."
391391
)
392392
}
393+
it("(3.o): should work on HasTarget") {
394+
class Top() extends Module {
395+
val i = Definition(new HasHasTarget)
396+
mark(i.x, "x")
397+
}
398+
val (_, annos) = getFirrtlAndAnnos(new Top)
399+
annos.collect { case c: MarkAnnotation => c } should contain(
400+
MarkAnnotation("~Top|HasHasTarget>sram_mem".rt, "x")
401+
)
402+
}
393403
}
394404
describe("(4): toDefinition") {
395405
it("(4.a): should work on modules") {

src/test/scala/chiselTests/experimental/hierarchy/Examples.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
package chiselTests.experimental.hierarchy
44

55
import chisel3._
6-
import chisel3.util.Valid
6+
import chisel3.util.{SRAM, Valid}
77
import chisel3.experimental.hierarchy._
88
import chisel3.experimental.{attach, Analog, BaseModule}
99

@@ -223,6 +223,11 @@ object Examples {
223223
@public val xy = (x, y)
224224
}
225225
@instantiable
226+
class HasHasTarget() extends Module {
227+
val sram = SRAM(1024, UInt(8.W), 1, 1, 0)
228+
@public val x: HasTarget = sram.underlying.get
229+
}
230+
@instantiable
226231
class HasVec() extends Module {
227232
@public val x = VecInit(1.U, 2.U, 3.U)
228233
}

src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,16 @@ class InstanceSpec extends ChiselFunSpec with Utils {
439439
val (chirrtl, _) = getFirrtlAndAnnos(new AddTwoNestedInstantiableDataWrapper(4))
440440
exactly(3, chirrtl.serialize.split('\n')) should include("connect i1.in, i0.out")
441441
}
442+
it("(3.r): should work on HasTarget") {
443+
class Top() extends Module {
444+
val i = Instance(Definition(new HasHasTarget))
445+
mark(i.x, "x")
446+
}
447+
val (_, annos) = getFirrtlAndAnnos(new Top)
448+
annos.collect { case c: MarkAnnotation => c } should contain(
449+
MarkAnnotation("~Top|Top/i:HasHasTarget>sram_mem".rt, "x")
450+
)
451+
}
442452
}
443453
describe("(4) toInstance") {
444454
it("(4.a): should work on modules") {

0 commit comments

Comments
 (0)