-
Notifications
You must be signed in to change notification settings - Fork 48
[Formal][PropertyAnnotation] Annotating IOG-based invariants #855
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
Changes from 32 commits
53ca2ff
e56f380
8a4696f
935a000
e742725
b9f632b
3c64778
b4e5fd4
f52748b
5accc26
c05778f
82ec8c6
eb3e39f
dcb74b6
bb75abf
f437c3a
bc68eef
789d98b
39adf31
7418c16
daa3dc0
df03ade
e1401b5
b69f6f6
4dbefde
d0d5f97
833fcef
5ed765b
20e867b
c239467
b227f81
f33ef2f
4ee3a5d
3fce970
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| #pragma once | ||
|
|
||
| #include "dynamatic/Analysis/NameAnalysis.h" | ||
| #include "dynamatic/Support/LLVM.h" | ||
| #include "mlir/IR/Value.h" | ||
| #include <unordered_set> | ||
|
|
||
| namespace dynamatic { | ||
| struct IOG; | ||
| struct IOGPathSet; | ||
|
|
||
| // An IOG path set is a structure that describes a set of paths between two | ||
| // operations: For any unit `u` within the IOG, it says whether there exists a | ||
| // path going through `u` or not. | ||
| struct IOGPathSet { | ||
|
Jiahui17 marked this conversation as resolved.
|
||
| IOGPathSet(const IOG &iog, Operation *start, Operation *end); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should it be a class method of IOG? iog.getPathSet(start, end)
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They are identical. I prefer the one I chose. |
||
|
|
||
| std::unordered_set<Operation *> units; | ||
| Operation *start; | ||
| Operation *end; | ||
| }; | ||
|
|
||
| // An In-order graph (IOG) of a dataflow circuit is a subgraph of the dataflow | ||
| // circuit. It contains one and only one entry channel (i.e. an argument of a | ||
| // FuncOp) which can reach all other operations using only channels part of the | ||
| // IOG. The IOG does not lose or gain any tokens: For any merge/mux, all the | ||
| // data inputs must be contained in the IOG, and for any fork, only a single | ||
| // output can be part of the IOG. Similarly, all branch outputs are part of the | ||
| // IOG, and for each join-operation, only a single input is part of the IOG. | ||
| // This way, there is a fixed number of tokens within the IOG. | ||
| struct IOG { | ||
|
Jiahui17 marked this conversation as resolved.
|
||
| IOG() = default; | ||
| std::unordered_set<Operation *> units; | ||
| llvm::DenseSet<mlir::Value> channels; | ||
| BlockArgument entry; | ||
|
|
||
| inline bool contains(Operation *op) const { | ||
| auto iter = units.find(op); | ||
| return iter != units.end(); | ||
| } | ||
|
|
||
| inline bool contains(mlir::Value channel) const { | ||
| auto iter = channels.find(channel); | ||
| return iter != channels.end(); | ||
| } | ||
|
|
||
| void debug() const { | ||
| std::vector<mlir::Value> stack; | ||
| llvm::DenseSet<mlir::Value> visited; | ||
| stack.push_back(entry); | ||
| visited.insert(entry); | ||
| while (!stack.empty()) { | ||
| mlir::Value channel = stack.back(); | ||
| stack.pop_back(); | ||
| Operation *prev = channel.getDefiningOp(); | ||
| if (prev == nullptr) { | ||
| llvm::errs() << "entry"; | ||
| } else { | ||
| llvm::errs() << getUniqueName(prev); | ||
| } | ||
| Operation *next = channel.getUses().begin()->getOwner(); | ||
| assert(next); | ||
| assert(contains(next)); | ||
| llvm::errs() << " -> " << getUniqueName(next) << "\n"; | ||
| for (mlir::Value out : next->getResults()) { | ||
| if (auto iter = visited.find(out); iter != visited.end()) | ||
| continue; | ||
| if (contains(out)) { | ||
| visited.insert(out); | ||
| stack.push_back(out); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| }; | ||
|
|
||
| std::vector<IOG> findAllIOGs(ModuleOp modOp); | ||
|
|
||
| } // namespace dynamatic | ||
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.
the output or all outputs? Technically we can choose whether to have a single output or multiple outputs