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] Update LowerClasses to alter what PathInfo stores. #7522

Merged
merged 1 commit into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
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
44 changes: 26 additions & 18 deletions lib/Dialect/FIRRTL/Transforms/LowerClasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,18 @@ static bool shouldCreateClassImpl(igraph::InstanceGraphNode *node) {
/// to the targeted operation.
struct PathInfo {
PathInfo() = default;
PathInfo(Operation *op, FlatSymbolRefAttr symRef,
PathInfo(Location loc, bool canBeInstanceTarget, FlatSymbolRefAttr symRef,
StringAttr altBasePathModule)
: op(op), symRef(symRef), altBasePathModule(altBasePathModule) {
assert(op && "op must not be null");
: loc(loc), canBeInstanceTarget(canBeInstanceTarget), symRef(symRef),
altBasePathModule(altBasePathModule) {
assert(symRef && "symRef must not be null");
}

operator bool() const { return op != nullptr; }
/// The Location of the hardware component targeted by this path.
std::optional<Location> loc = std::nullopt;
Copy link
Member

Choose a reason for hiding this comment

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

Just double checking, since we're not using lookup anymore, do we need the PathInfo to be default constructible?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm maybe not, I'm not sure if anything else still requires that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, default constructible is still required, at least for how we're using it when we add items with try_emplace. I will go ahead and merge this for now, and we could potentially keep reworking this.


/// The hardware component targeted by this path.
Operation *op = nullptr;
/// Flag to indicate if the hardware component can be targeted as an instance.
bool canBeInstanceTarget = false;

/// A reference to the hierarchical path targeting the op.
FlatSymbolRefAttr symRef = nullptr;
Expand Down Expand Up @@ -584,17 +585,23 @@ LogicalResult PathTracker::updatePathInfoTable(PathInfoTable &pathInfoTable,
auto [it, inserted] = pathInfoTable.table.try_emplace(entry.id);
auto &pathInfo = it->second;
if (!inserted) {
auto diag =
emitError(pathInfo.op->getLoc(), "duplicate identifier found");
assert(pathInfo.loc.has_value() && "all PathInfo should have a Location");
auto diag = emitError(pathInfo.loc.value(), "duplicate identifier found");
diag.attachNote(entry.op->getLoc()) << "other identifier here";
return failure();
}

if (entry.pathAttr)
pathInfo = {entry.op, cache.getRefFor(entry.pathAttr),
entry.altBasePathModule};
else
pathInfo.op = entry.op;
// Check if the op is targetable by an instance target. The op pointer may
// be invalidated later, so this is the last time we want to access it here.
bool canBeInstanceTarget = isa<InstanceOp, FModuleLike>(entry.op);

if (entry.pathAttr) {
pathInfo = {entry.op->getLoc(), canBeInstanceTarget,
cache.getRefFor(entry.pathAttr), entry.altBasePathModule};
} else {
pathInfo.loc = entry.op->getLoc();
pathInfo.canBeInstanceTarget = canBeInstanceTarget;
}
}
return success();
}
Expand Down Expand Up @@ -1453,14 +1460,14 @@ struct PathOpConversion : public OpConversionPattern<firrtl::PathOp> {
ConversionPatternRewriter &rewriter) const override {
auto *context = op->getContext();
auto pathType = om::PathType::get(context);
auto pathInfo = pathInfoTable.table.lookup(op.getTarget());
auto pathInfoIt = pathInfoTable.table.find(op.getTarget());

// The 0'th argument is the base path by default.
auto basePath = op->getBlock()->getArgument(0);

// If the target was optimized away, then replace the path operation with
// a deleted path.
if (!pathInfo) {
if (pathInfoIt == pathInfoTable.table.end()) {
if (op.getTargetKind() == firrtl::TargetKind::DontTouch)
return emitError(op.getLoc(), "DontTouch target was deleted");
if (op.getTargetKind() == firrtl::TargetKind::Instance)
Expand All @@ -1469,6 +1476,7 @@ struct PathOpConversion : public OpConversionPattern<firrtl::PathOp> {
return success();
}

auto pathInfo = pathInfoIt->second;
auto symbol = pathInfo.symRef;

// Convert the target kind to an OMIR target. Member references are updated
Expand All @@ -1482,15 +1490,15 @@ struct PathOpConversion : public OpConversionPattern<firrtl::PathOp> {
targetKind = om::TargetKind::Reference;
break;
case firrtl::TargetKind::Instance:
if (!isa<InstanceOp, FModuleLike>(pathInfo.op))
if (!pathInfo.canBeInstanceTarget)
return emitError(op.getLoc(), "invalid target for instance path")
.attachNote(pathInfo.op->getLoc())
.attachNote(pathInfo.loc)
<< "target not instance or module";
targetKind = om::TargetKind::Instance;
break;
case firrtl::TargetKind::MemberInstance:
case firrtl::TargetKind::MemberReference:
if (isa<InstanceOp, FModuleLike>(pathInfo.op))
if (pathInfo.canBeInstanceTarget)
targetKind = om::TargetKind::MemberInstance;
else
targetKind = om::TargetKind::MemberReference;
Expand Down
13 changes: 13 additions & 0 deletions test/Dialect/FIRRTL/lower-classes.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -458,3 +458,16 @@ firrtl.circuit "OwningModulePrefix" {
firrtl.path reference distinct[0]<>
}
}

// CHECK-LABEL: firrtl.circuit "PathTargetReplaced"
firrtl.circuit "PathTargetReplaced" {
// CHECK: hw.hierpath private [[NLA:@.+]] [@PathTargetReplaced::[[SYM:@.+]]]
firrtl.module @PathTargetReplaced() {
// CHECK: firrtl.instance replaced sym [[SYM]]
firrtl.instance replaced {annotations = [{class = "circt.tracker", id = distinct[0]<>}]} @WillBeReplaced(out output: !firrtl.integer)
// CHECK: om.path_create instance %basepath [[NLA]]
%path = firrtl.path instance distinct[0]<>
}
firrtl.module private @WillBeReplaced(out %output: !firrtl.integer) {
}
}
Loading