-
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
BitSetRange API #2449
BitSetRange API #2449
Conversation
integration-tests/src/test/scala/chiselTests/util/experimental/BitPat.scala
Show resolved
Hide resolved
override def toString: String = s"BitSetRange(0x${start.toString(16)} - 0x${(start + length).toString(16)})" | ||
} | ||
|
||
object BitSetRange { |
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 needs some ScalaDoc to explain the BitSetRange
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'll add them after the API goes through discussion.
Generally LGTM, would you mind have a try to copy-paste this PR to RocketChip? replacing its address decoder, to see if it can pass the rocket-chip CI. |
Thoughts on converting from generic BitSet to BitSetRange: We can also convert ANY BitSet into a list of continuous ranges. The problem is that the number of ranges maybe very large (e.g. An alternative is The steps to generate each range is as follows:
Another idea is add a |
Here is my thought:
|
@sequencer An initial version of I'm working on providing some sort of randomized testing. |
def inverse: BitSet = { | ||
val total = BitPat("b" + ("?".repeat(this.getWidth))) | ||
total.subtract(this) | ||
} |
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.
It may run forever, but this API is necessary, I think the time complexity may need to be documented? or at least tell users this API is time consuming.
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 a simple reduction into BitSet.subtract
. If I'm not mistaken, the maximum number of generated terms is width * len(term), which doesn't seems that bad ™️
Actually, if we are to document about the complexity, we may also want to document about the complexity of BitSet.subtract
?
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, basically all complexity should come from subtract
. emmm. that's time consuming as well. I think mention it on ScalaDoc is good enough yet.
Tests are added in 6f079f7. Actually I encountered an unexpected result from @sequencer Is this considered a bug, or a expected behavior? If this is indeed unexpected, then we need to keep a separate record of one BitSet's width. Also, Besides, are we going to allow binary subtraction / union / intersection between BitSets with different width? If we do, then how are we going to pad the shorter one? |
I'm going to try to summarize a really good discussion we had in Chisel dev today (thanks to @sequencer and @seldridge for the great session!). I'm going to use the term With the current implementation, it does not make sense to have That being said, I do see the utility in being able to do something like take an 1. BitSet and AddressSet are separate APIs (no inheritance relationship)This is the simplest to implement and saves us from having to make difficult implementation decisions that will be discussed in the later options. This does mean that users will have to handle any composition of 2. BitSet and AddressSet implement a common trait (HWSet? ChiselSet?)Similarly how we introduced Thus, the union of an Furthermore, this has highlighted to me that the current 3. AddressSet extends BitSet but we deprecate and remove the
|
After some discussion with @sequencer (thanks for his patience since I had so much misunderstanding), now I really like the idea of the common trait approach. If I'm understanding correctly, this approach effectively decouples the construction, optimization, and consumption of a BitSet. Operations on BitSets become more similar to operations on immutable data structures, where we construct a tree without premature normalization/optimization. Optimization is the transformation between equivalent trees, and consumption has the semantics of simple recursions on trees. If that's what we end up doing, I believe the current BitSet is the same as the union of some BitPats? So I guess (3) will work just fine. BitPat and AddressSet will be the leaf nodes in the tree and differs in the way we consume them (with pattern match or with comparison). Some other thoughts on what to do now: The original motivation behind the API is that there lacks a way to directly construct a BitSet matching ranges. How we can optimize the consumption of such ranges is sort of an afterthought. So an API like Since some library features (crossbar, router, etc) are blocked by the lack of a way to construct such BitSet, maybe we can add that feature first? Some options are:
|
We've discussed this in the developers' meeting. In order to enable development without having to be 100% certain on the API, we should merge this to master and not backport to 3.5.x. This means we can iterate a bit using the SNAPSHOTs and see how we feel about the API.
Your understanding here is 100% correct, so as you say, it's really just how should we proceed. I'm totally fine with merging some way of doing this even if it blasts down to I'm not super keen on keeping TLDR Let's go ahead with merging |
@CircuitCoder any updates on this PR? |
Just moved all logics from |
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.
generally LGTM, ask @jackkoenig to review again.
In 3.7, we should move theBitSet
manipulation logic into MFC,
but currently, we can just use this to create new circuit related to interconnection.
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've left some nitty comments and an API suggestion (I don't like using -1
as an indicator of "width not specified"). I'm not going to request changes because I will be gone for the next 2 weeks but I hope my suggestions are addressed before merging.
integration-tests/src/test/scala/chiselTests/util/experimental/BitPat.scala
Outdated
Show resolved
Hide resolved
Co-authored-by: Jack Koenig <jack.koenig3@gmail.com>
Add a new implementation of
chisel3.util.experimental.BitSet
,BitSetRange
, matching continuous bit ranges. Use cases include representing address ranges.This is currently a WIP.
TODO: A
matches
method is added to allBitSet
for testing, which currently has a naive implementation. We need to change that to a better implementation (e.g. using decoder)TODO: Maybe add a
BitSet.range
as an alias ofBitSetRange.apply
?TODO: Maybe add a overload
BitSetRange.apply(Range)
to permit code such asBitSetRange(0x1000 until 0x5000)
TODO: Documentations are not finished.
Contributor Checklist
docs/src
?Type of Improvement
new API
API Impact
Add a new class
BitSetRange
representingBitSet
corresponding to continuous bit ranges.Add a new object
BitSetRange
for constructingBitSetRange
instances.Backend Code Generation Impact
Desired Merge Strategy
Squash
Release Notes
Reviewer Checklist (only modified by reviewer)
3.4.x
, [small] API extension:3.5.x
, API modification or big change:3.6.0
)?Please Merge
?