Skip to content
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

[FIRRTL] Add InstanceInfo Analysis #7612

Merged
merged 19 commits into from
Sep 23, 2024

Conversation

seldridge
Copy link
Member

Add a new InstanceInfo analysis. This analysis provides common information which can be computed from a single walk of the InstanceGraph. The idea behind this is that there are a large amount of common information that different passes want to compute which all follows this same walk (and therefore has the same algorithmic complexity to compute it). Move all this information into a single, common analysis.

This analysis currently enables O(1) queries of if something is the DUT, is instantiated under the DUT, or is instantiated under a layer. More queries can be added as they are identified.

This new analysis naturally depends on the InstanceGraph analysis.

Add a new InstanceInfo analysis.  This analysis provides common
information which can be computed from a single walk of the InstanceGraph.
The idea behind this is that there are a large amount of common
information that different passes want to compute which all follows this
same walk (and therefore has the same algorithmic complexity to compute
it).  Move all this information into a single, common analysis.

This analysis currently enables O(1) queries of if something is the DUT,
is instantiated under the DUT, or is instantiated under a layer.  More
queries can be added as they are identified.

This new analysis naturally depends on the InstanceGraph analysis.

Signed-off-by: Schuyler Eldridge <[email protected]>
Copy link
Contributor

@prithayan prithayan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial comments, will take a deeper look in a while.

lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
};
} // namespace

InstanceInfo::InstanceInfo(Operation *op, mlir::AnalysisManager &am) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the op required here ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the docs [1], yes, it needs to have a constructor of (Operation *) or (Operation *, AnalysisManager &). I tested this just now and the compiler will reject it without it.

Good eye, though. This is clearly unused in the body.

Copy link
Contributor

@dtzSiFive dtzSiFive left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments, almost done...

include/circt/Analysis/FIRRTLInstanceInfo.h Outdated Show resolved Hide resolved
bool isDut;

/// Indicates if this module is instantiated under the design-under-test.
InstanceInfo::LatticeValue underDut = {LatticeValue::Kind::Unknown};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, not sure if this can be neatly reflected here or not but is the DUT module itself considered "underDUT"? ancestor / proper ancestor sort of thing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this interpretation of underDut makes more sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I switched to some very exact language in 09b03f1. This language could hint the new interpretation of "under" isn't quite right. Specifically, is an instance of the DUT under the DUT? I went back and forth here and settled on it is under the DUT, i.e., the new interpretation makes sense.

Changed in 0d28c7a.

WDYT?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After further thought on this, I changed to use "any" instead of "atLeastOne" in fa3de1e. This tends to better match, for lack of better inspiration, functional programming style "any of" or "all of" methods. "any" is also much shorter.

include/circt/Analysis/FIRRTLInstanceInfo.h Show resolved Hide resolved
include/circt/Analysis/FIRRTLInstanceInfo.h Outdated Show resolved Hide resolved

bool InstanceInfo::isUnderDut(FModuleOp op) {
auto underDut = getModuleAttributes(op).underDut;
return underDut.kind == LatticeValue::Mixed ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially if this grows more properties, some helpers on the lattice value to interpret it (like we do with other LatticeValue's in our code base) might help reduce boilerplate and chance of accidental mistakes / improve readability.

isPossiblyTrue() (kind >= Constant) /isKnownTrue() (kind == Constant && constant) or even may/must, just as ideas.

This is fine as-is for now.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this should grow some of these helpers. After applying a comment from Prithayan to reuse the allInstances* functions, the need for these helpers is lessened in this PR.

I'll leave this to future work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some helpers inspired from what IMCP's lattice value provides in 7efde85.

lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@prithayan prithayan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another round of comments.


bool InstanceInfo::isDut(FModuleOp op) { return getModuleAttributes(op).isDut; }

bool InstanceInfo::isUnderDut(FModuleOp op) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems more like, a "May analysis", so mayBeUnderDut is an option unless the difference between isUnderDut and isFullyUnderDut is well understood.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd opt against "maybe/may be" only because it implies the possibility of something being true. I.e., this seems closer to "unknown". Since I couldn't think of something pithy, I opted for more verbose names in 09b03f1. This uses the verbose convention atLeastOneInstance<property> and allInstances<property>.

I'm open to alternatives, though.

lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
@seldridge
Copy link
Member Author

Following up on an offhand remark from @rwy7, I do think that this can grow into computing edge-centric properties as well. I.e., this can get information about the instances and not just the modules/aggregate properties of all instances of modules. I'll leave this to future work as I don't want to overload this with too many things that don't have users.

Copy link
Contributor

@prithayan prithayan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using a topological sort simplifies the analysis, this looks good.
The usage of ReversePostOrderTraversal vs inverse_post_order_ext needs to be resolved and fixed.

lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
lib/Analysis/FIRRTLInstanceInfo.cpp Outdated Show resolved Hide resolved
// determinend by their instantiations.
DenseSet<InstanceGraphNode *> visited;
for (auto *root : iGraph) {
for (auto *modIt : llvm::inverse_post_order_ext(root, visited)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering, what's the difference between inverse and reverse post order ? ReversePostOrderTraversal seems to be used for topological sorted order, which is what the requirement is in this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably reverse of post order VS post-order on the inverse graph.

Good question! RPO is classic/ideal here.

Without cycles I'm not sure it matters (but would want to stare at it more...), and with them we can't guarantee convergence in a single walk (FWIW).

Using RPO, might be simplest conceptually as it's what we all expect here anyway and is more familiar for this sort of thing.

I was reaching for RPO in my suggestion, tbh.

FWIW we use inv post order elsewhere so hopefully thats correct/intentional for the same reason mentioned above, but might be good to check or ping those authors :).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empirically, I think it's the same in how it's being used here. Possibly, ReversePostOrder is slightly cleaner as it avoids having to do the pattern of nesting an inverse_post_order_ext under iteration over the nodes in the graph. I.e., the below can be replaced with what follows it:

DenseSet<InstanceGraphNode *> visited;
for (auto *root : iGraph) {
  for (auto *modIt : llvm::inverse_post_order_ext(root, visited)) {
    /* ... */
  }
}
ReversePostOrder<InstanceGraph *> rpo(iGraph);
for (auto *modIt : rpo) {
  /* ... */
}

I switched over to this in 8f1cedf.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chiming in a little late to this thread, but yes RPO and IPO should both visit the "parent" modules before the "children" modules, so it doesn't really matter which you use, but we usually use IPO for two reasons:

  1. RPO does a post-order walk, storing the elements to a SmallVector, and then walks it in reverse. IPO might be slightly faster because it doesn't need to build a vector of all modules.
  2. RPO will only visit modules which are reachable from the top level module (i.e. our instance graph trait implementation does not work well with multiple public modules), while the double loop used for IPO side steps this issue and visits all modules.

Copy link
Contributor

@prithayan prithayan Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, thanks @youngar , this clarifies my confusion of RPO vs IPO, sticking with IPO makes sense.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM. Changed back in 3fbec15.

@seldridge seldridge merged commit fe34e15 into main Sep 23, 2024
4 checks passed
@seldridge seldridge deleted the dev/seldridge/firrtl-InstanceInfo-analysis branch September 23, 2024 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants