-
Notifications
You must be signed in to change notification settings - Fork 16
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
feat: hierarchical flattening #90
Conversation
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #90 +/- ##
==========================================
- Coverage 87.36% 87.30% -0.07%
==========================================
Files 107 111 +4
Lines 9784 9721 -63
==========================================
- Hits 8548 8487 -61
+ Misses 1236 1234 -2 ☔ View full report in Codecov by Sentry. |
Looking great. I don't know why it won't let me leave this as a comment - but: def is_flat(m: h.Instance | h.Instantiable) -> bool: Does that "or operator creates Union types" work in Pythons v3.7-3.9? |
OK commenting on specific lines is totally broken(?).
Each generator-call, having been through elaboration, will have a |
Oh, right. My Python version is higher than Hdl21. I will update it with the older syntax. In terms supporting types other than plain primitives, I am honestly not quite sure because I have no clue how to use them properly. Let me add some basic tests first and gradually support more cases from there. |
ping |
Sorry what's the "ping" there? |
Sorry, just wanted to know what's the status of the PR here. The PR now implements the base use case well and do have some tests that cover such usage. I think it's a good starting point? |
hdl21/flatten.py
Outdated
|
||
new_module = h.Module((m.name or "module") + "_flat") | ||
for port_name in m.ports: | ||
new_module.add(h.Port(name=port_name)) | ||
|
||
# add all signals to the root level | ||
for n in nodes: | ||
for sig in n.conns.values(): | ||
sig_name = sig.name | ||
if sig_name not in new_module.ports: | ||
new_module.add(h.Signal(name=sig_name)) |
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.
Same comment as for Ports on line 99 - we should copy the Signal attributes (besides its name).
There's also a _copy_to_internal
function which copies everything about a port, except for its porti-ness, in case we need that:
Line 107 in 945aa6e
def _copy_to_internal(sig: Signal) -> Signal: |
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.
I am not exactly sure what this _copy_to_internal
does and it seems in my application I don't need it at all.
Yeah I think the feedback should be pretty straightforward to follow up on, and we can get that merged. Happy to add any detail if any of it's unclear. |
@dan-fritchman updated based on your feedback, passes tests locally. |
Mostly catch up to Vlsir main, un-block #90
hdl21/flatten.py
Outdated
def is_flat(m: Union[h.Instance, h.Instantiable]) -> bool: | ||
if isinstance(m, h.Instance): | ||
return is_flat(m.of) | ||
elif isinstance(m, (h.PrimitiveCall, h.GeneratorCall, h.ExternalModuleCall)): |
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.
A GeneratorCall
is flat?
Why not flatten its Module
-result?
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.
This function is actually just is_flat
, come to think of it - so should be something like:
if isinstance(m, h.GeneratorCall):
return is_flat(m.result)
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.
hm... this decision is kind arbitrary because I don't use GeneratorCall
so it becomes a case I don't handle. Any suggestion how it should be handled here? Return True
if its generated module is flat?
Added a few more tests here: There's 3 things, two related groups:
|
A few more things not included in those tests which should be added, and should be pretty straightforward:
|
|
new_conns = {} | ||
new_parents = parents + (inst,) | ||
for src_port_name, sig in inst.conns.items(): | ||
if isinstance(sig, h.Signal): |
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.
Things that will be in inst.conns.values
, in addition to Signal
, will include: Slice
, Concat
.
There is a Connectable
union of everything that can go into conns
before elaboration. After, that should be reduced to:
Connectable = Union[
# Still gonna be there:
"Signal",
"Slice",
"Concat",
# Removed during elaboration:
"NoConn",
"PortRef",
# And all this `Bundle` stuff is definitely removed via elaboration:
"BundleInstance",
"AnonymousBundle",
"BundleRef",
]
hdl21/flatten.py
Outdated
def is_flat(m: Union[h.Instance, h.Instantiable]) -> bool: | ||
if isinstance(m, h.Instance): | ||
return is_flat(m.of) | ||
elif isinstance(m, (h.PrimitiveCall, h.GeneratorCall, h.ExternalModuleCall)): |
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.
This function is actually just is_flat
, come to think of it - so should be something like:
if isinstance(m, h.GeneratorCall):
return is_flat(m.result)
raise ValueError(f"signal {key} not found") | ||
new_conns[src_port_name] = target_sig | ||
|
||
if isinstance(inst.of, h.PrimitiveCall): |
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.
Needs cases for:
GeneratorCall
- which will need to be flattened, andExternalModuleCall
- which we should regard as "already flat"
OK here's a few proposed tweaks: #213. |
Closing in favor of #213 |
Hierarchical flattening for modules discussed in #86.
TODO:
tree
dependency