-
Notifications
You must be signed in to change notification settings - Fork 298
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
[LowerTypes] Preserve rwprobes, forceable. #5051
[LowerTypes] Preserve rwprobes, forceable. #5051
Conversation
e8d739a
to
c7f2cca
Compare
Fixed, source operand is re-built if needed for a force (but for whatever reason expanded elsewhere). No longer split up force or release or forceable (with rwprobe result active), ever, that code is removed. This also changes things so rwprobe's are never lowered, regardless of convention, which seems reasonable if you squint they could count as "scalars". |
Wargarbl, connections to forceable declarations get sad with this unless agg preservation is on: https://github.com/dtzSiFive/reftype-inputs/blob/main/force_agg.fir Gives error:
Bit of a balancing act, will think/bake this some more... |
I think this error was because we started to reject subelement connection from HW wire PR: #4826 To fix this I guess it's sufficient to enable MergeConnection pass even when with non-aggregate preservation (currently ran only when |
Yeah there was a version of |
Thank you both very much! I'll look into that, enabling MergeConnections does resolve that error! And appreciate the context/analysis. |
69ad6b4
to
b621efd
Compare
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.
Few nits, otherwise LGTM!
.Case<RefForceOp, RefForceInitialOp, RefSendOp, VectorCreateOp, | ||
BundleCreateOp>([&](auto op) { | ||
// Reconstruct the aggregate for the ref operation. | ||
// (or vector/bundle create that were inserted.. woof.) | ||
ImplicitLocOpBuilder b(user->getLoc(), user); | ||
|
||
Value input = | ||
TypeSwitch<Type, Value>(val.getType()) | ||
.template Case<FVectorType>([&](auto vecType) { | ||
return b.createOrFold<VectorCreateOp>(vecType, mapping); | ||
}) | ||
.template Case<BundleType>([&](auto bundleType) { | ||
return b.createOrFold<BundleCreateOp>(bundleType, mapping); | ||
}) | ||
.Default([&](auto _) -> Value { return {}; }); | ||
if (!input) { | ||
user->emitError("unable to reconstruct source of type ") | ||
<< val.getType(); | ||
return; | ||
} |
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 we can use for Default
as well. Default
currently creates aggrgates by bitcast operations (since there was no vector/bundle_create at that time) so it would be way better to explicitly use vector/bundle_create.
Example: firtool -preserve-aggregate=1d-vec
.
circuit Bar:
module Bar:
input a1: UInt<1>[2]
input a2: UInt<1>[2]
input cond: UInt<1>
output b: UInt<1>[2]
b <= mux(cond, a1, a2)
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 an aside: I've noticed playing with aggregates that often names become _GEN
-- if we're exploding then reconstructing that would sure explain that. Unfortunately this doesn't (easily) lend itself to addressing that, but it'd be neat if so.
In your example you're showing another case where we "unevenly" lower things--here, the scalarization of the top module causes the vectors to be split and we'd prefer a vector/bundle create to recover those pieces vs bitcast.
Is that right?
(Makes lots of sense to me!)
Interesting point!! I am unsure... okay digging a little it appears this code was written before we had aggregate creation ops 😄 .
(( Depending on how you look at the purpose of LowerTypes, I was concerned the mechanism for materializing the aggregate might be important -- for claims like "No FIRRTL op will still take an aggregate" or if the story for foreign ops made more sense giving it an opaque blob of bits directly. In that sense this was a little suboptimal but I didn't have a better story other than rejecting. ))
Anyway a few conversations later I think this makes sense. I'll change it separately.
cc #3989 which might be useful to revive here re:neater IR but not 100% as haven't gone through that carefully.
Don't lower these as much as possible. Keep the always-lower-(non-rw-)probe behavior to workaround the memtaps / 4479 issue. Also, if we need to lower the source operand to a force statement, split it up as well. Some sharp corners here re:references to non-passive things, can be handled similarly to the force situation-- just reconstruct or cat+cast the elements back.
If not splitting the force, reconstruct the source operands from the expanded elements. This is similar to source materialization in MLIR's conversion.
Leave the boolean simplify thing along for note re:memtaps issue.
Undo change that used the input argument, which was motivated by ensuring a ref.send of a non-passive would be lowered since we always lower non-passive types. Instead, always look at the ref result for determining this, so that ref chains are consistent. We can rebuild the aggregate into the send as needed. As-is we always expand read-only references anyway, so this just ensures the send is also split apart using same logic splitting up ref.define/etc of probe's.
Per reviewer feedback, thanks!
b621efd
to
12affab
Compare
Thank you all very much for the feedback and review! Will make the suggested change re:improving other paths in an immediate follow-up. (also makes me happy to not make this so specific to references... 👍) |
Don't lower these as much as possible.
Keep the always-lower-(non-rw-)probe behavior
to workaround the memtaps / 4479 issue.
Also, if we need to lower the source operand,
re-construct/materialize it (like "Source Materialization").
This does of course mean rwprobe'ing something means it needs to be okay to preserve as an aggregate.