-
Notifications
You must be signed in to change notification settings - Fork 23
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
[Buffers] Subject Graph Implementation for MapBuf #286
base: main
Are you sure you want to change the base?
Conversation
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.
Hey Osman! Thanks for the nice pull request!
I left a couple of superficial comments to begin with, but my main request right now is a little bit more vague- could you add a subfolder to docs for MapBuf and write up a little bit of documentation of what these subject graphs are used for/how they are used?
I think it would be super useful to keep this code accessible :)
For the code itself, it is very nice, I like the general structure + the polymorphism. However, I think your internal datastructures are totally crazy-
dynamatic/experimental/include/experimental/Support/SubjectGraph.h
Lines 76 to 97 in 626024f
// Vectors and Maps to hold the input and output modules and SubjectGraphs. | |
// (input/output)Modules and ToResNum is populated the first time the | |
// SubjectGraph is created. | |
std::vector<Operation *> inputModules; | |
std::vector<Operation *> outputModules; | |
DenseMap<Operation *, unsigned int> inputModuleToResNum; | |
DenseMap<Operation *, unsigned int> outputModuleToResNum; | |
// The populated maps store channel-specific information that connects | |
// SubjectGraphs together. Each SubjectGraph has a position in the vector | |
// which determines what type of data it handles (e.g., data, address, index). | |
// Separately, a Result Number identifies which specific output channel of an | |
// Operation to connect to, since an Operation may have multiple inputs and | |
// outpus. The maps are essential for establishing the correct connections | |
// between SubjectGraphs, while the vectors determine the data types being | |
// passed through those connections. | |
std::vector<BaseSubjectGraph *> inputSubjectGraphs; | |
std::vector<BaseSubjectGraph *> outputSubjectGraphs; | |
DenseMap<BaseSubjectGraph *, unsigned int> inputSubjectGraphToResNum; | |
DenseMap<BaseSubjectGraph *, unsigned int> outputSubjectGraphToResNum; | |
static inline DenseMap<Operation *, BaseSubjectGraph *> moduleMap; |
Data structures these intense are not always a bad thing (sometimes we really do need them) but as they get more complex the need for documentation skyrockets.
There also seems to be a lot of duplication in the name generation/assign signals logic, but without comments it is difficult to know if it is needed or not.
Could you possibly close this pull request, and make another with less classes, so we can focus in on just the first 2 for discussion to begin with? I think we would get through it a little bit faster :)
Thanks again for the all the hard work!
|
||
for (auto &fanout : currentNode->fanouts) { | ||
fanout->fanins.erase(currentNode); | ||
fanout->fanins.insert(previousNode); |
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.
maybe combine these two in a static function?
previousNode->name = currentNode->name; | ||
} | ||
|
||
currentNode = previousNode; |
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.
current node is a pointer passed by value. changing the value of the pointer doesn't have any impact outside of the function body, or am I wrong?
is this supposed to change the pointer passed to the function? should it delete the previous current node first, if so?
@@ -103,6 +134,10 @@ class Node { | |||
} | |||
bool isPrimaryOutput() const { return (isOutput || isLatchInput); } | |||
|
|||
// Used to merge I/O nodes. I/O is set false and isChannelEdge is set to true | |||
// so that the node can be considered as a dataflow graph edge. | |||
void setIOChannel(); |
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.
really like this function but think its name is a bit unclear- to me the name kinda implies it sets io to true?
what do you think of convertIOToChannel ?
// Get the input and output modules of the operation. Find the result number | ||
// of the channel. | ||
for (Value operand : op->getOperands()) { | ||
if (Operation *definingOp = operand.getDefiningOp()) { |
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.
maybe leave a comment on why there would be no defining op? should this be an error, or is this a known case?
if (dotPosition != std::string::npos) { | ||
moduleType = moduleType.substr(dotPosition + 1); | ||
} else { | ||
assert(false && "operation unsupported"); |
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.
if you are inside of the MLIR infrastructure, maybe this should be done using the MLIR diagnostic library?
It looks to me this would be a factory function which returns a FailureOr, and could call op->emitError?
I'm not super experienced with this, the example I am drawing from is-
dynamatic/lib/Dialect/HW/InnerSymbolTable.cpp
Lines 44 to 47 in 261ba42
FailureOr<InnerSymbolTable> InnerSymbolTable::get(Operation *op) { | |
assert(op); | |
if (!op->hasTrait<OpTrait::InnerSymbolTable>()) | |
return op->emitError("expected operation to have InnerSymbolTable trait"); |
|
||
// Populate Subject Graph vectors | ||
for (auto *module : subjectGraphs) { | ||
module->replaceOpsBySubjectGraph(); |
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.
what do you think of the name of this function?
I'm not fully following the code, but it doesn't seem to "replace". You appear to have this interim subject graphs vector you use to build two final vectors, is that right?
Introduction
This Pull Request introduces SubjectGraph.cpp and SubjectGraph.h, which implement functionality to transform MLIR Operations into Subject Graph representations.
Key Components
SubjectGraphGenerator:
BaseSubjectGraph:
Module Specific Derived Classes:
Merging all Subject Graphs: