-
Notifications
You must be signed in to change notification settings - Fork 351
[FIRRTL] Lower registers under ifdefs #8605
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
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.
Great work!
Overall strategy seems right, thanks for putting this together!
I didn't finish going through it but left some comments mostly re:inner symbols 👍 .
@@ -107,53 +115,273 @@ void FirRegLowering::addToIfBlock(OpBuilder &builder, Value cond, | |||
} | |||
} | |||
|
|||
/// Attach an inner-sym to field-id 0 of the given register, or use an existing | |||
/// inner-sym, if present. | |||
static StringAttr getInnerSymFor(InnerSymbolNamespace &innerSymNS, |
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.
Sorry you had to roll your own thing for this! 🙃
9b08888
to
7af7812
Compare
56e2e54
to
fb0402f
Compare
fb0402f
to
3039c4e
Compare
In seq-to-sv, we transform seq FirRegOps to sv RegOps. This is done using a helper called FirRegLowering. This PR changes FirRegLowering to correctly lower registers under ifdef blocks. The initialization of registers is placed in an initial block at the footer of the enclosing HWModuleOp. In order to initialize registers buried under ifdefs, we have to refer to these registers by a local XMR, because the buried registers will not dominate the initial block. We build these in a prepass over the MLIR module, returning a "PathTable" sending buried FirRegOps to their HierPathOps. The main FirRegLowering procedure operates in parallel on each HWModuleOp. Each invocation is now handed a const reference to the path table, which allows us to produce an XMRRefOp as needed while emitting the register initialization code at the footer of the HWModule. The initialization code for a register has to be guarded under the same ifdef conditions as the register itself. To do this, while lowering registers, we record the conditions under which the register is defined, and recreate them to guard the initialization code. When we lower a register, we attempt to transform any input mux tree into an SV if-else tree of connects. This PR modifies the if-else generation to co-locate the if-else with the register. So if a register is guarded under an ifdef, then the if-else structure driving it will also be under the same ifdef.
3039c4e
to
a913d1a
Compare
In seq-to-sv, we transform seq FirRegOps to sv RegOps. This is done using a helper called FirRegLowering. This PR changes FirRegLowering to correctly lower registers under ifdef blocks.
The initialization of registers is placed in an initial block at the footer of the enclosing HWModuleOp. In order to initialize registers buried under ifdefs, we have to refer to these registers by a local XMR, because the buried registers will not dominate the initial block. We build these in a prepass over the MLIR module, returning a "PathTable" sending buried FirRegOps to their HierPathOps.
The main FirRegLowering procedure operates in parallel on each HWModuleOp. Each invocation is now handed a const reference to the path table, which allows us to produce an XMRRefOp as needed while emitting the register initialization code at the footer of the HWModule.
The initialization code for a register has to be guarded under the same ifdef conditions as the register itself. To do this, while lowering registers, we record the conditions under which the register is defined, and recreate them to guard the initialization code.
When we lower a register, we attempt to transform any input mux tree into an SV if-else tree of connects. This PR modifies the if-else generation to co-locate the if-else with the register. So if a register is guarded under an ifdef, then the if-else structure driving it will also be under the same ifdef.
Fixes: #8461