-
Notifications
You must be signed in to change notification settings - Fork 603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement asTypeOf, refactor internal APIs #450
Conversation
|
assert( DataMirror.widthOf(truncate).get == 3 ) | ||
assert( truncate === 3.U ) | ||
assert( DataMirror.widthOf(expand).get == 3 ) | ||
assert( expand === 1.U ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why DataMirror.widthOf
instead of just .widthOption
or .getWidth
, also, why does DataMirror.widthOf
exist? @sdtwigg
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think DataMirror provides a more reflection-like API for reflection-like operations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your opinion, in user Chisel code should people use DataMirror
over .getWidth
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's a good argument for an explicit reflection-like API, especially since there are subtleties with width (inferred width doesn't get computed until after Chisel).
But in any case we should standardize on one, and deprecate the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, a discussion for a different PR I think
@@ -15,26 +15,22 @@ import chisel3.internal.sourceinfo._ | |||
* of) other Data objects. | |||
*/ | |||
sealed abstract class Aggregate extends Data { | |||
private[core] def cloneTypeWidth(width: Width): this.type = cloneType | |||
private[core] def width: Width = flatten.map(_.width).reduce(_ + _) | |||
private[core] def getElements: Seq[Data] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed at the Chisel meeting today, getElements
could be public, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might be reviewing an outdated version, getElements is public...
@@ -15,26 +15,22 @@ import chisel3.internal.sourceinfo._ | |||
* of) other Data objects. | |||
*/ | |||
sealed abstract class Aggregate extends Data { | |||
private[core] def cloneTypeWidth(width: Width): this.type = cloneType | |||
private[core] def width: Width = flatten.map(_.width).reduce(_ + _) | |||
def getElements: Seq[Data] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ScalaDoc?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, will do.
private[chisel3] lazy val flatten = elements.toIndexedSeq.flatMap(_._2.flatten) | ||
private[core] override def typeEquivalent(that: Data): Boolean = that match { | ||
case that: Record => | ||
this.getClass == that.getClass && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually what we want? Bulk connect works on things that are not the same class but have the same elements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there's potential debate to be had here. I think a stricter check makes sense, since I think there's an argument to be made for type equality having meaning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't realize in doAggregateMux
we are currently requiring that the classes be the same so yeah, I agree with keeping this strict. It is interesting that you can't create a Mux between two otherwise identical anonymous Bundles but you can bulk connect them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Mux they kind of have to be the same class, because you need to pick one as the return type. The least arbitrary thing to do is to pick one but require it be the same as the other.
For connections, there is a debate to be had, but relaxing it later is always easier than imposing a new restriction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think they should require the same class. I can't currently think of a use case where you want to create the same Record in everything but class. For library-like interfaces I think you would want to end up using the library's Record constructor, rather than trying to create your own record with the same elements.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aye, it all makes sense now!
@@ -390,6 +392,9 @@ abstract trait Num[T <: Data] { | |||
sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) | |||
extends Bits(width, lit) with Num[UInt] { | |||
|
|||
private[core] override def typeEquivalent(that: Data): Boolean = | |||
that.isInstanceOf[UInt] && this.width == that.width // TODO: should this be true for unspecified widths? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I think it should be true for unspecified widths
private[chisel3] lazy val flatten: IndexedSeq[Bits] = | ||
(0 until length).flatMap(i => this.apply(i).flatten) | ||
override def getElements: Seq[Data] = | ||
(0 until length).map(apply(_)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ScalaDoc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's a reason to re-define the ScalaDoc in override functions in subclasses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fair enough
}) | ||
res | ||
private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { | ||
this := that.asUInt | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scala style is to not use procedure syntax: http://docs.scala-lang.org/style/declarations
ie. ): Unit = {
|
||
def do_asTypeOf[T <: Data](that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { | ||
val thatCloned = Wire(that.chiselCloneType) | ||
thatCloned.connectFromBits(asUInt()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just my opinion but I generally prefer to use this.
when invoking methods on the object at hand. That asUInt()
just looks like some magical functional call rather than calling something on this
|
||
/** Assigns this node from Bits type. Internal implementation for asTypeOf. | ||
*/ | ||
private[core] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return type
val ret = Wire(this.cloneType) | ||
ret := that | ||
ret.asInstanceOf[this.type] | ||
private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is same comment as the previous one about procedure syntax, I think there are a few of these in this PR
Everything else fixed. More discussion on role if type in typeEquivalent may be necessary |
There's a conflict in |
Conflict fixed. CloneSupertype now works for fixed point (requiring the binary point to be the same) and parts of Analog have been updated to fit the new API. Merging as soon as tests go green... |
Several refactor changes that shouldn't affect non-nonsensical Chisel:
cloneSupertype
(eliminates the premise of Is there a reason we do an explicit Mux compatibility check? #446)typeEquivalent
internal API. This andcloneSupertype
eliminates the need fortypesCompatible
, which is inexplicably a Mux operation.cloneTypeWidth
fromData
toBits
. It used to silently drop thewidth
parameter when called on any non-Bits, which is just sketchy. This makes uses of it explicit and always correct, minus the Bool case.Bits.pad
(which can instead create a new UInt/etc from scratch) and Reg (which clears widths behind the scenes for you). Not sure how to address the Reg case.flatten
, hopefully will remove it eventually using more local operations. The stragglers are mainly Bindings directionality checks, which can be made more local with a resolution to Consolidate directionality data #440.Originally the intention was to remove fromBits and the less clean APIs that it relied on (like flatten), but many more yaks were shaved. flatten hasn't been removed yet, but should be possible in the near future,