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

[Moore] Add AssignedVarOp and canonicalization for VariableOp. #7251

Merged

Conversation

hailongSun2000
Copy link
Member

@hailongSun2000 hailongSun2000 commented Jun 28, 2024

The canonicalization for VariableOp is aimed at merging the "easy use" of the variable and its value(continuous assignment) into a new op called assigned_variable. Don't handle blocking_assign and nonBlocking_assign due to the dominance.
The "easy use" is assigning a value to a variable with the whole bit-width, in other words, exclude the bits slice, concatenation operator, etc.

@hailongSun2000
Copy link
Member Author

Appendix:

/home/phoenix/work/HDLBits/test01.sv:4:10: error: Unsupported drive the same wire 'l' two times now
  assign l = 1'b0;
         ^
module {
  moore.module @Foo() {
    %l = moore.net wire : <l1>
    %l_0 = moore.assigned_variable name "l" %1 : <l1>
    %0 = moore.constant true : i1
    %1 = moore.conversion %0 : !moore.i1 -> !moore.l1
    moore.assign %l, %1 : l1
    %2 = moore.constant false : i1
    %3 = moore.conversion %2 : !moore.i1 -> !moore.l1
    moore.assign %l, %3 : l1
    moore.output
  }
}

Copy link
Member

@uenoku uenoku left a comment

Choose a reason for hiding this comment

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

I think it's reasonable to make SVModuleOp graph region op for progressive lowering into core dialects. However it's a big change for Moore dialect design so would be nice to have consensus on this change.

lib/Dialect/Moore/Transforms/MergeAssignments.cpp Outdated Show resolved Hide resolved
lib/Dialect/Moore/Transforms/MergeAssignments.cpp Outdated Show resolved Hide resolved
`:` type($result)
}];
}

def AssignedVarOp : MooreOp<"assigned_variable", [
Copy link
Member

Choose a reason for hiding this comment

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

Do we need a new op? NetOp seems to have an assignment operand so is that same?

Copy link
Member Author

Choose a reason for hiding this comment

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

You're totally right! NetOp has an assignment operand. Maybe I think I need to rename it. Like def AssignedDeclOp : MooreOp<"assigned_decl(aration)", [, what do @fabianschuiki @uenoku think? By the way, slang will throw an error, if we drive the same variable multiple times.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm yeah good question... SV differentiates between nets and variables in quite a few places. My gut feeling is that turning a VariableOp into a NetOp with an assignment isn't going to be correct in general 🤔. The AssignedVariableOp feels like a good step, because it retains the variable-ness but makes it explicit that it is continuously assigned a specific value.

I'm pretty sure we'll be able to write some simplification passes that take always_comb procedures that write to variables through moore.blocking_assign and convert that into a simple moore.assigned_variable for simplicity. Then only the truly annoying uses of variables would remain (the ones interacting with the event queue, have delays, etc.).

@hailongSun2000
Copy link
Member Author

I'll separate the changing of SVModule into a different PR.

@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch from fd08bf5 to 843f558 Compare July 1, 2024 09:37
@fabianschuiki
Copy link
Contributor

I'm wondering if this could work as a canonicalization pattern defined on VariableOp 🤔. The pattern could theoretically go through all users of the variable op and if there is a single continuous assignment, the assigned value could be merged into a new AssignedVariableOp. But I'm not sure how idiomatic and scalable it is to scan an entire user list in a canonicalization... @uenoku may have an opinion on that 😏

@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch 2 times, most recently from ef922c6 to ade3855 Compare July 2, 2024 03:23
@uenoku
Copy link
Member

uenoku commented Jul 2, 2024

It makes sense to implement it as canonicalization. We do the same thing for SV so compile time should be OK. However in that case please make sure lowering pass can lower them even without canonicalization.

@hailongSun2000 hailongSun2000 changed the title [Moore] Add AssignedVarOp and a graph region for SVModule. [Moore] Add AssignedVarOp and MergeAssignments pass. Jul 3, 2024
@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch 2 times, most recently from c8c19f6 to edce0c1 Compare July 3, 2024 08:21
@hailongSun2000
Copy link
Member Author

Hey, @fabianschuiki @uenoku! I add the canonicalization pattern for moore.variable. But it seems can not keep the original variable, if not call replaceOp() /replaceOpWithNewOp(), the canonicalize() will not take effect.

Comment on lines 270 to 288
for (auto *user : op->getUsers())
if (isa<ContinuousAssignOp>(user) &&
(user->getOperand(0) == op.getResult())) {
auto assignVarOp = rewriter.create<AssignedVarOp>(
op->getLoc(), op.getType(), op.getName(), user->getOperand(1));
rewriter.replaceOp(op, assignVarOp);
return success();
}
return failure();
}
Copy link
Member

Choose a reason for hiding this comment

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

I think you must ensure that there is no multiple ContinuousAssignOp.

Copy link
Member Author

@hailongSun2000 hailongSun2000 Jul 4, 2024

Choose a reason for hiding this comment

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

Slang has guaranteed that the variable has only one continuous assignment. For example:

int x;
assign x = 32;
assign x = 64;
source.sv:4:9: error: cannot have multiple continuous assignments to variable 'x'
 assign x = 64;
        ^
source.sv:3:9: note: also assigned here
 assign x = 32;

I'll leave a comment about this.

Copy link
Member

@uenoku uenoku Jul 4, 2024

Choose a reason for hiding this comment

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

I think we shouldn't rely on implicit assumption of slang. We should at least check that property in our verifier.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, I'll add this.

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 understood why we need to check whether there are multiple continuous assignments for the same variable. Because the --canonicalize operates on the IR, not from AST to IR, right?

Copy link
Member

Choose a reason for hiding this comment

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

Yes, I think we should able to use Moore dialect not only for slang.

@uenoku
Copy link
Member

uenoku commented Jul 3, 2024

Can we remove mergeAssignments pass if we implemented it as a canonicalization?

@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch from dcbc38f to 1234b63 Compare July 4, 2024 02:14
@hailongSun2000
Copy link
Member Author

I have removed the MergeAssignments pass.

@hailongSun2000 hailongSun2000 changed the title [Moore] Add AssignedVarOp and MergeAssignments pass. [Moore] Add AssignedVarOp and canonicalization for VariableOp. Jul 4, 2024
@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch from 1234b63 to e89aa9e Compare July 4, 2024 03:16
Comment on lines 270 to 279
llvm::DenseSet<Operation *> variables;
Value initial;
for (auto *user : op->getUsers())
if (isa<ContinuousAssignOp>(user) &&
(user->getOperand(0) == op.getResult())) {
// Don't canonicalize the multiple continuous assignment to the same
// variable.
if (variables.contains(op))
return failure();

variables.insert(op);
initial = user->getOperand(1);
}
Copy link
Member

Choose a reason for hiding this comment

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

I think we don't need variables set.

Suggested change
llvm::DenseSet<Operation *> variables;
Value initial;
for (auto *user : op->getUsers())
if (isa<ContinuousAssignOp>(user) &&
(user->getOperand(0) == op.getResult())) {
// Don't canonicalize the multiple continuous assignment to the same
// variable.
if (variables.contains(op))
return failure();
variables.insert(op);
initial = user->getOperand(1);
}
Value initial;
for (auto *user : op->getUsers())
if (isa<ContinuousAssignOp>(user) &&
(user->getOperand(0) == op.getResult())) {
// Don't canonicalize the multiple continuous assignment to the same
// variable.
if (initial)
return failure();
initial = user->getOperand(1);
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Nice~ ! 💯

Copy link
Member

@uenoku uenoku left a comment

Choose a reason for hiding this comment

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

One nit, otherwise LGTM!

[Moore] Add the canonicalization pattern for VariableOp.
@hailongSun2000 hailongSun2000 force-pushed the hailong/add-assigned-variable-op branch from e89aa9e to 1f3374f Compare July 4, 2024 07:20
@hailongSun2000
Copy link
Member Author

Thanks for the code review 😃 .

@hailongSun2000 hailongSun2000 merged commit aa03227 into llvm:main Jul 4, 2024
4 checks passed
@fabianschuiki
Copy link
Contributor

Very cool! 🥳

@hailongSun2000 hailongSun2000 deleted the hailong/add-assigned-variable-op branch July 10, 2024 05:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants