diff --git a/core/src/main/scala/chisel3/AggregateImpl.scala b/core/src/main/scala/chisel3/AggregateImpl.scala index 9fd1a546b53..7c146c8d770 100644 --- a/core/src/main/scala/chisel3/AggregateImpl.scala +++ b/core/src/main/scala/chisel3/AggregateImpl.scala @@ -138,7 +138,7 @@ private[chisel3] trait AggregateImpl extends Data { thiz: Aggregate => clone } - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { val _asUInt = _resizeToWidth(that, this.widthOption, true)(identity) // If that is a literal and all constituent Elements can be represented as literals, return a literal val ((_, allLit), rvalues) = { @@ -147,7 +147,7 @@ private[chisel3] trait AggregateImpl extends Data { thiz: Aggregate => // Chisel only supports zero width extraction if hi = -1 and lo = 0, so do it manually val _extracted = if (elt.getWidth == 0) 0.U(0.W) else _asUInt(hi - 1, lo) // _fromUInt returns Data but we know that it is an Element - val rhs = elt._fromUInt(_extracted).asInstanceOf[Element] + val rhs = elt._fromUIntPrivate(_extracted).asInstanceOf[Element] ((hi, literal && rhs.isLit), rhs) } } diff --git a/core/src/main/scala/chisel3/BitsImpl.scala b/core/src/main/scala/chisel3/BitsImpl.scala index 1a22e65e9b7..78d285fa2fe 100644 --- a/core/src/main/scala/chisel3/BitsImpl.scala +++ b/core/src/main/scala/chisel3/BitsImpl.scala @@ -392,7 +392,7 @@ private[chisel3] trait UIntImpl extends BitsImpl with Num[UInt] { self: UInt => override private[chisel3] def _asUIntImpl(first: Boolean)(implicit sourceInfo: SourceInfo): UInt = this - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = { _resizeToWidth(that, this.widthOption, true)(identity).asInstanceOf[this.type] } @@ -518,7 +518,7 @@ private[chisel3] trait SIntImpl extends BitsImpl with Num[SInt] { self: SInt => override def _asSIntImpl(implicit sourceInfo: SourceInfo): SInt = this - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = _resizeToWidth(that.asSInt, this.widthOption, false)(_.asSInt).asInstanceOf[this.type] } @@ -545,7 +545,7 @@ private[chisel3] trait ResetTypeImpl extends Element { self: Reset => DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) ) - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { val _wire = Wire(this.cloneTypeFull) _wire := that _wire @@ -574,7 +574,7 @@ private[chisel3] trait AsyncResetImpl extends Element { self: AsyncReset => DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) ) - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = that.asBool.asAsyncReset + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = that.asBool.asAsyncReset protected def _asAsyncResetImpl(implicit sourceInfo: SourceInfo): AsyncReset = this @@ -644,7 +644,7 @@ private[chisel3] trait BoolImpl extends UIntImpl { self: Bool => protected def _asAsyncResetImpl(implicit sourceInfo: SourceInfo): AsyncReset = pushOp(DefPrim(sourceInfo, AsyncReset(), AsAsyncResetOp, ref)) - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): this.type = { _resizeToWidth(that, this.widthOption, true)(identity).asBool.asInstanceOf[this.type] } } diff --git a/core/src/main/scala/chisel3/ChiselEnumImpl.scala b/core/src/main/scala/chisel3/ChiselEnumImpl.scala index d11881a40ea..8e4cda8ef20 100644 --- a/core/src/main/scala/chisel3/ChiselEnumImpl.scala +++ b/core/src/main/scala/chisel3/ChiselEnumImpl.scala @@ -41,7 +41,7 @@ private[chisel3] abstract class EnumTypeImpl(private[chisel3] val factory: Chise pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) } - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = factory.apply(that.asUInt) protected def _impl_===(that: EnumType)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that) diff --git a/core/src/main/scala/chisel3/ClockImpl.scala b/core/src/main/scala/chisel3/ClockImpl.scala index afd8341b965..62e58d1b5e4 100644 --- a/core/src/main/scala/chisel3/ClockImpl.scala +++ b/core/src/main/scala/chisel3/ClockImpl.scala @@ -32,5 +32,5 @@ private[chisel3] trait ClockImpl extends Element { DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) ) - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = that.asBool.asClock + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = that.asBool.asClock } diff --git a/core/src/main/scala/chisel3/DataImpl.scala b/core/src/main/scala/chisel3/DataImpl.scala index bd4f13a8285..d6cdfb4efcb 100644 --- a/core/src/main/scala/chisel3/DataImpl.scala +++ b/core/src/main/scala/chisel3/DataImpl.scala @@ -861,8 +861,13 @@ private[chisel3] trait DataImpl extends HasId with NamedComponent { self: Data = } /** Return a value of this type from a UInt type. Internal implementation for asTypeOf. + * + * Protected so that it can be implemented by the external FixedPoint library */ - private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data + protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data + + // Package private alias for _fromUInt so we can call it elsewhere in chisel3 + private[chisel3] final def _fromUIntPrivate(that: UInt)(implicit sourceInfo: SourceInfo): Data = _fromUInt(that) // The actual implementation of do_asUInt // @param first exists because of awkward behavior in Aggregate that requires changing 0.U to be zero-width to fix @@ -1242,7 +1247,7 @@ final case object DontCare extends Element with connectable.ConnectableDocs { def toPrintable: Printable = PString("DONTCARE") - private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { Builder.error("DontCare cannot be a connection sink (LHS)") this } diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index 79ba0bbba93..00384e9c800 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -70,7 +70,7 @@ final class Analog private (private[chisel3] val width: Width) extends Element { override private[chisel3] def _asUIntImpl(first: Boolean)(implicit sourceInfo: SourceInfo): UInt = throwException("Analog does not support asUInt") - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { Builder.error("Analog does not support fromUInt") Wire(Analog(that.width)) } diff --git a/core/src/main/scala/chisel3/properties/Property.scala b/core/src/main/scala/chisel3/properties/Property.scala index dab3a5cee19..b9c8989b2bd 100644 --- a/core/src/main/scala/chisel3/properties/Property.scala +++ b/core/src/main/scala/chisel3/properties/Property.scala @@ -235,7 +235,7 @@ sealed trait Property[T] extends Element { self => Builder.error(s"${this._localErrorContext} does not support .asUInt.") 0.U } - override private[chisel3] def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { Builder.exception(s"${this._localErrorContext} cannot be driven by UInt") } diff --git a/src/test/scala-2/chiselTests/RecordSpec.scala b/src/test/scala-2/chiselTests/RecordSpec.scala index ff73124aa10..2acf3a1f3cf 100644 --- a/src/test/scala-2/chiselTests/RecordSpec.scala +++ b/src/test/scala-2/chiselTests/RecordSpec.scala @@ -3,10 +3,11 @@ package chiselTests import chisel3._ -import chisel3.experimental.OpaqueType +import chisel3.experimental.{OpaqueType, SourceInfo} import chisel3.reflect.DataMirror import chisel3.simulator.scalatest.ChiselSim import chisel3.simulator.stimulus.RunUntilFinished +import chisel3.testing.scalatest.FileCheck import chisel3.util.{Counter, Queue} import circt.stage.ChiselStage import org.scalatest.flatspec.AnyFlatSpec @@ -113,7 +114,7 @@ object RecordSpec { } } -class RecordSpec extends AnyFlatSpec with Matchers with ChiselSim { +class RecordSpec extends AnyFlatSpec with Matchers with ChiselSim with FileCheck { import RecordSpec._ behavior.of("Records") @@ -127,11 +128,12 @@ class RecordSpec extends AnyFlatSpec with Matchers with ChiselSim { } they should "emit FIRRTL bulk connects when possible" in { - val chirrtl = ChiselStage.emitCHIRRTL( - gen = new ConnectionTestModule(fooBarType, fooBarType) + val chirrtl = ChiselStage.emitCHIRRTL(new ConnectionTestModule(fooBarType, fooBarType)) + chirrtl.fileCheck()( + """| CHECK: connect io.outMono, io.inMono + | CHECK: connect io.outBi, io.inBi + |""".stripMargin ) - chirrtl should include("connect io.outMono, io.inMono @") - chirrtl should include("connect io.outBi, io.inBi @") } they should "not allow aliased fields" in { @@ -170,10 +172,40 @@ class RecordSpec extends AnyFlatSpec with Matchers with ChiselSim { class MyRecord extends Record { lazy val elements = VectorMap("sanitize me" -> UInt(8.W)) } - val chirrtl = ChiselStage.emitCHIRRTL(new RawModule { - val out = IO(Output(new MyRecord)) - }) - chirrtl should include("output out : { sanitizeme : UInt<8>}") + ChiselStage + .emitCHIRRTL(new RawModule { + val out = IO(Output(new MyRecord)) + }) + .fileCheck()( + """|CHECK: output out : { sanitizeme : UInt<8>} + |""".stripMargin + ) + } + + // This is not a great API but it enables the external FixedPoint library + they should "support overriding _fromUInt" in { + class MyRecord extends Record { + val foo = UInt(8.W) + val elements = SeqMap("foo" -> foo) + override protected def _fromUInt(that: UInt)(implicit sourceInfo: SourceInfo): Data = { + val _w = Wire(this.cloneType) + _w.foo := that ^ 0x55.U(8.W) + _w + } + } + ChiselStage + .emitCHIRRTL(new RawModule { + val in = IO(Input(UInt(8.W))) + val out = IO(Output(new MyRecord)) + out := in.asTypeOf(new MyRecord) + }) + .fileCheck()( + """|CHECK: wire [[wire:.*]] : { foo : UInt<8>} + |CHECK: node [[node:.*]] = xor(in, UInt<8>(0h55)) + |CHECK: connect [[wire]].foo, [[node]] + |CHECK: connect out, [[wire]] + |""".stripMargin + ) } "Bulk connect on Record" should "check that the fields match" in {