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] Fix SRAM instance paths in OMIR #2039

Merged
merged 2 commits into from
Oct 26, 2021

Conversation

fabianschuiki
Copy link
Contributor

Fix an issue in EmitOMIR where the instance paths of SRAMs would be incorrectly rendered as OMMemberReferenceTarget instead of the correct OMMemberInstanceTarget. This also includes figuring out the module name that the final SRAM is going to have, which in the case of a firrtl.mem is a bit tricky/fragile: the actual module name for the memory is only generated after lowering to the HW dialect, at which point the OMIR has long been emitted. This change "predicts" the name that the memory is going to have by querying getFirMemoryName(), which looks like it's going to be accurate in most cases we currently care about.

In the long run, we'll want better ways to encode this formulation of an instance path and ideally dealy it until ExportVerilog time.

Fix an issue in `EmitOMIR` where the instance paths of SRAMs would be
incorrectly rendered as `OMMemberReferenceTarget` instead of the correct
`OMMemberInstanceTarget`. This also includes figuring out the module
name that the final SRAM is going to have, which in the case of a
`firrtl.mem` is a bit tricky/fragile: the actual module name for the
memory is only generated after lowering to the HW dialect, at which
point the OMIR has long been emitted. This change "predicts" the name
that the memory is going to have by querying `getFirMemoryName()`, which
looks like it's going to be accurate in most cases we currently care
about.

In the long run, we'll want better ways to encode this formulation of an
instance path and ideally dealy it until `ExportVerilog` time.
@fabianschuiki fabianschuiki added bug Something isn't working FIRRTL Involving the `firrtl` dialect labels Oct 26, 2021
Copy link
Contributor

@prithayan prithayan left a comment

Choose a reason for hiding this comment

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

Looks good

Copy link
Member

@seldridge seldridge left a comment

Choose a reason for hiding this comment

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

Nice.

I'm annoyed that we don't have a good answer for how to update this during the memory replacement and have to (seemingly) pick up the pieces after it happens. I.e., is it possible (or a good idea) to update the target at the conversion from memory to instance?

This is clearly not necessary, but I think it's doable once we move away from OMIR encoded as dictionaries to whatever plethora of OMIR dialects exist. E.g., this could be represented as a canonicalization if we an actual op, in a separate dialect, for representing OMMemberReferenceTarget that morphs into an OMMemberInstanceTarget if the type of the thing with the symbol that it's pointing at changes.

lib/Dialect/FIRRTL/Transforms/EmitOMIR.cpp Outdated Show resolved Hide resolved
Comment on lines +649 to +668
[&] {
if (type == "OMMemberInstanceTarget") {
if (auto instOp = dyn_cast<InstanceOp>(tracker.op)) {
target.push_back('/');
target.append(instOp.name());
target.push_back(':');
target.append(addSymbol(instOp.moduleNameAttr()));
return;
}
if (auto memOp = dyn_cast<MemOp>(tracker.op)) {
target.push_back('/');
target.append(memOp.name());
target.push_back(':');
target.append(memOp.getSummary().getFirMemoryName());
return;
}
}
target.push_back('>');
target.append(componentName);
}();
Copy link
Member

Choose a reason for hiding this comment

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

This lambda is clever (I hadn't seen this syntax before...), but is it necessary? 😉

Copy link
Contributor Author

@fabianschuiki fabianschuiki Oct 26, 2021

Choose a reason for hiding this comment

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

😃 The trouble is that the ">componentName" case needs to run if either type != "OMMemberInstanceTarget" or none of the if statements runs. And since you you cannot check type == ... in the same if condition as you do auto instOp = ... you cannot fold the outer if into the inner ones. So either you need to

  • have a bool to track whether any of the ifs above produced a result
  • have ">componentName" output twice, once as else for the outer and once for the inner if statement
  • have a closure that allows for early return

Co-authored-by: Schuyler Eldridge <schuyler.eldridge@gmail.com>
@fabianschuiki
Copy link
Contributor Author

@seldridge I'm annoyed that we don't have a good answer for how to update this during the memory replacement and have to (seemingly) pick up the pieces after it happens. I.e., is it possible (or a good idea) to update the target at the conversion from memory to instance?

The trouble is that the conversion to an instance happens only in LowerToHW. So we'd only know what exactly to put here after lowering is done (and a symbol for the instantiated module has been created). I think what's missing is a way to encode "put the OMIR-formatted path of @someMagicInstance here" in the IR after lowering to HW. Then you wouldn't have to guess about the nature of that symbol (memory, instance, module, whatever), but could just rely on something late in the pipeline filling in the correct path. That could be a separate OMIR dialect, or an auxiliary operation whose result you could stick into sv.verbatim.

This is clearly not necessary, but I think it's doable once we move away from OMIR encoded as dictionaries to whatever plethora of OMIR dialects exist. E.g., this could be represented as a canonicalization if we an actual op, in a separate dialect, for representing OMMemberReferenceTarget that morphs into an OMMemberInstanceTarget if the type of the thing with the symbol that it's pointing at changes.

Yes once we have a more fleshed-out dialect to do this tracking of structured data this should become easier. But especially the distinction of the different OMIR targets seems to be an artifact of the Scala code encoding the nature of the target in the type system, which is great on the Scala side. But on the MLIR side, all you actually need is a symbol for the target itself, and the type of target is fairly evident from what kind of operation it's attached to (module, instance, wire, reg, mem, etc.). I'd expect an OMIR-inspired dialect to be more MLIR-idiomatic such that morphing these targets is unnecessary.

@fabianschuiki fabianschuiki merged commit 98303db into llvm:main Oct 26, 2021
@fabianschuiki fabianschuiki deleted the omir-mem-fix branch October 26, 2021 15:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working FIRRTL Involving the `firrtl` dialect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants