diff options
| author | Megan Wachs | 2022-01-11 10:10:20 -0800 |
|---|---|---|
| committer | GitHub | 2022-01-11 18:10:20 +0000 |
| commit | 747d16311bdf185d2e98e452b14cb5d8ccca004c (patch) | |
| tree | 4f73b2e875107153d324b9062ec0bf955c2ddb18 | |
| parent | 2b48fd15a7711dcd44334fbbc538667a102a581a (diff) | |
Lookupable: add Either version (#2335)
* Add Lookupable for Either
* Lookupable: enhance the @public/@instantiable error message to include traits and Eithers
Co-authored-by: Jack Koenig <koenig@sifive.com>
4 files changed, 48 insertions, 2 deletions
diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index 1223d6ce..8552267a 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -18,8 +18,8 @@ import chisel3.internal.{throwException, AggregateViewBinding, Builder, ChildBin * Sealed. */ @implicitNotFound( - "@public is only legal within a class marked @instantiable and only on vals of type" + - " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option" + "@public is only legal within a class or trait marked @instantiable, and only on vals of type" + + " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable, Option, or Either" ) trait Lookupable[-B] { type C // Return type of the lookup @@ -381,6 +381,27 @@ object Lookupable { ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) } } } + implicit def lookupEither[L, R]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupableL: Lookupable[L], + lookupableR: Lookupable[R] + ) = new Lookupable[Either[L, R]] { + type C = Either[lookupableL.C, lookupableR.C] + def definitionLookup[A](that: A => Either[L, R], definition: Definition[A]): C = { + val ret = that(definition.proto) + ret.map { x: R => lookupableR.definitionLookup[A](_ => x, definition) }.left.map { x: L => + lookupableL.definitionLookup[A](_ => x, definition) + } + } + def instanceLookup[A](that: A => Either[L, R], instance: Instance[A]): C = { + import instance._ + val ret = that(proto) + ret.map { x: R => lookupableR.instanceLookup[A](_ => x, instance) }.left.map { x: L => + lookupableL.instanceLookup[A](_ => x, instance) + } + } + } implicit def lookupIsInstantiable[B <: IsInstantiable]( implicit sourceInfo: SourceInfo, compileOptions: CompileOptions diff --git a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala index efc81f94..63beb394 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/DefinitionSpec.scala @@ -319,6 +319,16 @@ class DefinitionSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|ConcreteHasBlah".mt, "10")) } + it("3.11: should work on eithers") { + class Top() extends Module { + val i = Definition(new HasEither()) + i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) + i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) + } + val (_, annos) = getFirrtlAndAnnos(new Top) + annos should contain(MarkAnnotation("~Top|HasEither>x".rt, "xright")) + annos should contain(MarkAnnotation("~Top|HasEither>y".rt, "yleft")) + } } describe("4: toDefinition") { it("4.0: should work on modules") { diff --git a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala index de03b74b..5b78b7cc 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/Examples.scala @@ -195,6 +195,11 @@ object Examples { @public val x: Option[UInt] = Some(Wire(UInt(3.W))) } @instantiable + class HasEither() extends Module { + @public val x: Either[Bool, UInt] = Right(Wire(UInt(3.W)).suggestName("x")) + @public val y: Either[Bool, UInt] = Left(Wire(Bool()).suggestName("y")) + } + @instantiable class HasVec() extends Module { @public val x = VecInit(1.U, 2.U, 3.U) } diff --git a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala index e6bf04c1..f62d1e49 100644 --- a/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala +++ b/src/test/scala/chiselTests/experimental/hierarchy/InstanceSpec.scala @@ -288,6 +288,16 @@ class InstanceSpec extends ChiselFunSpec with Utils { val (_, annos) = getFirrtlAndAnnos(new Top) annos should contain(MarkAnnotation("~Top|Top/i:HasPublicConstructorArgs>x".rt, "10")) } + it("3.11: should work on eithers") { + class Top() extends Module { + val i = Instance(Definition(new HasEither())) + i.x.map(x => mark(x, "xright")).left.map(x => mark(x, "xleft")) + i.y.map(x => mark(x, "yright")).left.map(x => mark(x, "yleft")) + } + val (_, annos) = getFirrtlAndAnnos(new Top) + annos should contain(MarkAnnotation("~Top|Top/i:HasEither>x".rt, "xright")) + annos should contain(MarkAnnotation("~Top|Top/i:HasEither>y".rt, "yleft")) + } } describe("4: toInstance") { it("4.0: should work on modules") { |
