diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index a159b464786..1ac7716f098 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -4,6 +4,7 @@ package chisel3.experimental import chisel3._ import chisel3.internal._ +import chisel3.properties.Property import scala.annotation.{implicitNotFound, tailrec} import scala.collection.mutable @@ -145,6 +146,8 @@ package object dataview { case (_: Reset, a: AsyncReset) => /* Allow DontCare in the target only */ case (DontCare, _) => + /* Allow Property[_] <=> Property[_] views when the underlying type is the same */ + case (a: Property[_], b: Property[_]) if a.getPropertyType == b.getPropertyType => /* All other views produce a runtime error. */ case _ => val fieldName = viewFieldName(vex) diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index bd8296de1bc..6278f78bafb 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -113,9 +113,6 @@ private[chisel3] object BiConnect { elemConnect(sourceInfo, left_e, right_e, context_mod) // TODO(twigg): Verify the element-level classes are connectable } - case (left_p: Property[_], right_p: Property[_]) => - // We can consider supporting this, but it's a lot of code and we should be moving away from <> anyway - Builder.error(s"${left_p._localErrorContext} does not support <>, use :<>= instead")(sourceInfo) // Handle Vec case case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { if (left_v.length != right_v.length) { diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 4ca77b8f2fc..446706da029 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -408,10 +408,14 @@ private[chisel3] object MonoConnect { def propConnect( sourceInfo: SourceInfo, - sink: Property[_], - source: Property[_], + sinkProp: Property[_], + sourceProp: Property[_], context: BaseModule ): Unit = { + // Reify sink and source if they're views. + val sink = reify(sinkProp) + val source = reify(sourceProp) + checkConnect(sourceInfo, sink, source, context) // Add the PropAssign command directly onto the correct BaseModule subclass. context match { @@ -447,16 +451,13 @@ private[chisel3] object checkConnect { context_mod: BaseModule ): Unit = { checkConnection(sourceInfo, sink, source, context_mod) - } - def apply( - sourceInfo: SourceInfo, - sink: Property[_], - source: Property[_], - context_mod: BaseModule - ): Unit = { - checkConnection(sourceInfo, sink, source, context_mod) - checkConnect.checkPropertyConnection(sourceInfo, sink, source) + // Extra checks for Property[_] elements. + (sink, source) match { + case (sinkProp: Property[_], sourceProp: Property[_]) => + checkConnect.checkPropertyConnection(sourceInfo, sinkProp, sourceProp) + case (_, _) => + } } def checkConnection( diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index 6aac475d13d..2d873558f81 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -7,7 +7,7 @@ import firrtl.{ir => fir} import firrtl.annotations.{InstanceTarget, IsMember, ModuleTarget, ReferenceTarget, Target} import chisel3.internal._ import chisel3.internal.{firrtl => ir} -import chisel3.experimental.{prefix, requireIsHardware, SourceInfo} +import chisel3.experimental.{prefix, requireIsHardware, Analog, SourceInfo} import chisel3.experimental.hierarchy.Instance import scala.reflect.runtime.universe.{typeOf, TypeTag} import scala.annotation.{implicitAmbiguous, implicitNotFound} @@ -170,10 +170,13 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { override def convertUnderlying(value: D) = Path(value) } - // We can't just do <: Data because Property subclasses Data + // We can't just do <: Element because Property subclasses Element implicit def aggregatePathTypeInstance[A <: Aggregate]: RecursivePropertyType.Aux[A, Path, Path] = dataPathTypeInstance[A] - implicit def elementPathTypeInstance[E <: Element]: RecursivePropertyType.Aux[E, Path, Path] = dataPathTypeInstance[E] + implicit def bitsPathTypeInstance[E <: ToBoolable]: RecursivePropertyType.Aux[E, Path, Path] = dataPathTypeInstance[E] + implicit def clockPathTypeInstance[E <: Clock]: RecursivePropertyType.Aux[E, Path, Path] = dataPathTypeInstance[E] + implicit def analogPathTypeInstance[E <: Analog]: RecursivePropertyType.Aux[E, Path, Path] = dataPathTypeInstance[E] + implicit def enumPathTypeInstance[E <: EnumType]: RecursivePropertyType.Aux[E, Path, Path] = dataPathTypeInstance[E] implicit def memPathTypeInstance[M <: MemBase[_]]: RecursivePropertyType.Aux[M, Path, Path] = new RecursivePropertyType[M] { @@ -208,7 +211,7 @@ private[chisel3] object PropertyType extends LowPriorityPropertyTypeInstances { * describe a set of non-hardware types, so they have no width, cannot be used * in aggregate Data types, and cannot be connected to Data types. */ -sealed trait Property[T] extends Data { self => +sealed trait Property[T] extends Element { self => sealed trait ClassType private object ClassType { implicit def classTypeProvider( @@ -231,11 +234,10 @@ sealed trait Property[T] extends Data { self => Builder.error(s"${this._localErrorContext} does not support .asUInt.") 0.U } - private[chisel3] def allElements: Seq[Element] = Nil private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo): Unit = { Builder.error(s"${this._localErrorContext} cannot be driven by Bits") } - private[chisel3] def firrtlConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + override private[chisel3] def firrtlConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { that match { case pthat: Property[_] => MonoConnect.propConnect(sourceInfo, this, pthat, Builder.forcedUserModule) case other => Builder.error(s"${this._localErrorContext} cannot be connected to ${that._localErrorContext}") @@ -243,7 +245,7 @@ sealed trait Property[T] extends Data { self => } - def litOption: Option[BigInt] = None + override def litOption: Option[BigInt] = None def toPrintable: Printable = { throwException(s"Properties do not support hardware printing" + this._errorContext) } diff --git a/src/test/scala/chiselTests/properties/PropertySpec.scala b/src/test/scala/chiselTests/properties/PropertySpec.scala index 1a11a30627d..fc71fc78f06 100644 --- a/src/test/scala/chiselTests/properties/PropertySpec.scala +++ b/src/test/scala/chiselTests/properties/PropertySpec.scala @@ -3,6 +3,7 @@ package chiselTests.properties import chisel3._ +import chisel3.experimental.FlatIO import chisel3.properties.{Class, Path, Property, PropertyType} import chiselTests.{ChiselFlatSpec, MatchesAndOmits} import circt.stage.ChiselStage @@ -407,22 +408,6 @@ class PropertySpec extends ChiselFlatSpec with MatchesAndOmits { )() } - it should "NOT support <>" in { - class MyBundle extends Bundle { - val foo = Property[String]() - val bar = Flipped(Property[BigInt]()) - } - val e = the[ChiselException] thrownBy ChiselStage.emitCHIRRTL( - new RawModule { - val aligned = IO(new MyBundle) - val flipped = IO(Flipped(new MyBundle)) - aligned <> flipped - }, - Array("--throw-on-first-error") - ) - e.getMessage should include("Field '_.bar' of type Property[Integer] does not support <>, use :<>= instead") - } - it should "support being nested in a Bundle in a wire" in { class MyBundle extends Bundle { val foo = Property[String]() @@ -584,4 +569,23 @@ class PropertySpec extends ChiselFlatSpec with MatchesAndOmits { "propassign barB, barObj" )() } + + it should "support FlatIO" in { + val chirrtl = ChiselStage.emitCHIRRTL(new RawModule { + val flatModule = Module(new RawModule { + val io = FlatIO(new Bundle { + val bool = Input(Bool()) + val prop = Input(Property[Int]()) + }) + }) + + flatModule.io.bool := true.B + flatModule.io.prop := Property(1) + }) + + matchesAndOmits(chirrtl)( + "connect flatModule.bool, UInt<1>(0h1)", + "propassign flatModule.prop, Integer(1)" + )() + } }