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

[RTG] Add some additional debug printing #7889

Open
wants to merge 1 commit into
base: maerhart-rtg-bags-capi
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 104 additions & 22 deletions lib/Dialect/RTG/Transforms/ElaborationPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "circt/Dialect/RTG/IR/RTGVisitors.h"
#include "circt/Dialect/RTG/Transforms/RTGPasses.h"
#include "mlir/IR/PatternMatch.h"
#include "llvm/Support/Debug.h"
#include <deque>
#include <random>

Expand Down Expand Up @@ -73,6 +74,15 @@ class ElaboratorValue {
return isOpaque == other.isOpaque && value == other.value;
}

virtual std::string toString() const {
std::string out;
llvm::raw_string_ostream stream(out);
stream << "<opaque ";
value.print(stream);
stream << " at " << this << ">";
return out;
}
Comment on lines +77 to +84
Copy link
Member

Choose a reason for hiding this comment

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

Can this be done by defining the << operator. This can also, if only used in debug, can be guarded under NDEBUG. E.g., something like https://github.com/llvm/circt/blob/main/include/circt/Analysis/FIRRTLInstanceInfo.h#L198

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a great point! Thanks for reviewing!


protected:
ElaboratorValue(Value value, bool isOpaque)
: isOpaque(isOpaque), value(value) {}
Expand All @@ -85,15 +95,21 @@ class ElaboratorValue {
/// Holds an evaluated value of a `SetType`'d value.
class SetValue : public ElaboratorValue {
public:
SetValue(Value value, SmallVector<ElaboratorValue *> &&set,
bool debug = false)
: ElaboratorValue(value, false), originalSize(set.size()), debug(debug),
set(set) {
SetValue(Value value, SmallVector<ElaboratorValue *> &&set)
: ElaboratorValue(value, false), debug(false), set(set) {
assert(isa<SetType>(value.getType()));

if (debug)
for (auto [i, val] : llvm::enumerate(set))
debugMap[i] = val;
// Make sure the vector is sorted and has no duplicates.
llvm::sort(this->set);
this->set.erase(std::unique(this->set.begin(), this->set.end()),
this->set.end());
}

SetValue(Value value, SmallVector<ElaboratorValue *> &&set,
SmallVector<ElaboratorValue *> &&debugMap)
: ElaboratorValue(value, false), debug(true), set(set),
debugMap(debugMap) {
assert(isa<SetType>(value.getType()));

// Make sure the vector is sorted and has no duplicates.
llvm::sort(this->set);
Expand Down Expand Up @@ -121,14 +137,31 @@ class SetValue : public ElaboratorValue {
return set == otherSet->set;
}

ArrayRef<ElaboratorValue *> getAsArrayRef() const { return set; }
std::string toString() const override {
assert(debug && "must be in debug mode");

ElaboratorValue *getAtIndexForDebug(size_t idx) const {
assert(debug && "must have been constructed in debug mode");
return debugMap.lookup(idx);
std::string out;
llvm::raw_string_ostream stream(out);
stream << "<set {";
DenseSet<ElaboratorValue *> visited;
for (auto *val : debugMap) {
if (visited.contains(val))
continue;
if (!visited.empty())
stream << ", ";
visited.insert(val);
stream << val->toString();
}
stream << "} at " << this << ">";
return out;
}

const size_t originalSize;
ArrayRef<ElaboratorValue *> getAsArrayRef() const { return set; }

ArrayRef<ElaboratorValue *> getDebugMap() const {
assert(debug && "must be in debug mode");
return debugMap;
}

private:
// Whether this set was constructed in debug mode.
Expand All @@ -142,7 +175,7 @@ class SetValue : public ElaboratorValue {

// A map to guarantee deterministic behavior when the 'rtg.elaboration'
// attribute is used in debug mode.
DenseMap<size_t, ElaboratorValue *> debugMap;
SmallVector<ElaboratorValue *> debugMap;
};

/// Holds an evaluated value of a `SequenceType`'d value.
Expand Down Expand Up @@ -177,6 +210,16 @@ class SequenceClosureValue : public ElaboratorValue {
return sequence == seq->sequence && args == seq->args;
}

std::string toString() const override {
std::string out;
llvm::raw_string_ostream stream(out);
stream << "<sequence @" << sequence.getValue() << "(";
llvm::interleaveComma(args, stream,
[&](auto *val) { stream << val->toString(); });
stream << ") at " << this << ">";
return out;
}

StringAttr getSequence() const { return sequence; }
ArrayRef<ElaboratorValue *> getArgs() const { return args; }

Expand Down Expand Up @@ -323,7 +366,14 @@ class Elaborator : public RTGOpVisitor<Elaborator, FailureOr<DeletionKind>,
set.emplace_back(interpValue);
}

internalizeResult<SetValue>(op.getSet(), std::move(set), options.debugMode);
if (options.debugMode) {
SmallVector<ElaboratorValue *> debugMap(set);
internalizeResult<SetValue>(op.getSet(), std::move(set),
std::move(debugMap));
return DeletionKind::Delete;
}

internalizeResult<SetValue>(op.getSet(), std::move(set));
return DeletionKind::Delete;
}

Expand All @@ -334,16 +384,17 @@ class Elaborator : public RTGOpVisitor<Elaborator, FailureOr<DeletionKind>,
ElaboratorValue *selected;
if (options.debugMode) {
auto intAttr = op->getAttrOfType<IntegerAttr>("rtg.elaboration");
if (set->originalSize != set->getAsArrayRef().size())
size_t originalSize = set->getDebugMap().size();
if (originalSize != set->getAsArrayRef().size())
op->emitWarning("set contained ")
<< (set->originalSize - set->getAsArrayRef().size())
<< (originalSize - set->getAsArrayRef().size())
<< " duplicate value(s), the value at index " << intAttr.getInt()
<< " might not be the intended one";
selected = set->getAtIndexForDebug(intAttr.getInt());
if (!selected)
if (originalSize <= intAttr.getValue().getZExtValue())
return op->emitError("'rtg.elaboration' attribute value out of bounds, "
"must be between 0 (incl.) and ")
<< set->originalSize << " (excl.)";
<< originalSize << " (excl.)";
selected = set->getDebugMap()[intAttr.getInt()];
} else {
std::uniform_int_distribution<size_t> dist(
0, set->getAsArrayRef().size() - 1);
Expand All @@ -356,19 +407,34 @@ class Elaborator : public RTGOpVisitor<Elaborator, FailureOr<DeletionKind>,

FailureOr<DeletionKind>
visitOp(SetDifferenceOp op, function_ref<void(Operation *)> addToWorklist) {
auto original = cast<SetValue>(state.at(op.getOriginal()))->getAsArrayRef();
auto *originalElaboratorValue = cast<SetValue>(state.at(op.getOriginal()));
auto original = originalElaboratorValue->getAsArrayRef();
auto diff = cast<SetValue>(state.at(op.getDiff()))->getAsArrayRef();

SmallVector<ElaboratorValue *> result;
std::set_difference(original.begin(), original.end(), diff.begin(),
diff.end(), std::inserter(result, result.end()));

internalizeResult<SetValue>(op.getResult(), std::move(result),
options.debugMode);
if (options.debugMode) {
DenseSet<ElaboratorValue *> diffSet(diff.begin(), diff.end());
SmallVector<ElaboratorValue *> debugMap;
for (auto *el : originalElaboratorValue->getDebugMap())
if (!diffSet.contains(el))
debugMap.push_back(el);

internalizeResult<SetValue>(op.getResult(), std::move(result),
std::move(debugMap));
return DeletionKind::Delete;
}

internalizeResult<SetValue>(op.getResult(), std::move(result));
return DeletionKind::Delete;
}

LogicalResult elaborate(TestOp testOp) {
LLVM_DEBUG(llvm::dbgs()
<< "\n=== Elaborating Test @" << testOp.getSymName() << "\n\n");

DenseSet<Operation *> visited;
std::deque<Operation *> worklist;
DenseSet<Operation *> toDelete;
Expand Down Expand Up @@ -410,6 +476,22 @@ class Elaborator : public RTGOpVisitor<Elaborator, FailureOr<DeletionKind>,
if (failed(result))
return failure();

LLVM_DEBUG({
if (options.debugMode) {
llvm::dbgs() << "Elaborating " << *curr << " to\n[";

llvm::interleaveComma(curr->getResults(), llvm::dbgs(),
[&](auto res) {
if (state.contains(res))
llvm::dbgs() << state.at(res)->toString();
else
llvm::dbgs() << "unknown";
});

llvm::dbgs() << "]\n\n";
}
});

if (*result == DeletionKind::Delete)
toDelete.insert(curr);

Expand Down
Loading