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

feat: hierarchical flattening #90

Closed
wants to merge 11 commits into from
Closed

feat: hierarchical flattening #90

wants to merge 11 commits into from

Conversation

uduse
Copy link
Collaborator

@uduse uduse commented Jan 13, 2023

Hierarchical flattening for modules discussed in #86.

TODO:

  • remove tree dependency
  • add tests
  • add more docs

@codecov
Copy link

codecov bot commented Jan 13, 2023

Codecov Report

Attention: 9 lines in your changes are missing coverage. Please review.

Comparison is base (831e8d3) 87.36% compared to head (cd5950a) 87.30%.

❗ Current head cd5950a differs from pull request most recent head 094d6c5. Consider uploading reports for the commit 094d6c5 to get more accurate results

Files Patch % Lines
hdl21/flatten.py 88.88% 9 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

@dan-fritchman
Copy link
Owner

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?
I think it's only 3.10+.

@dan-fritchman
Copy link
Owner

OK commenting on specific lines is totally broken(?).
More on is_flat, particularly the types of things that are & aren't "flat" -

  • PrimitiveCall and ExternalModuleCall are indeed flat
  • GeneratorCall generally is not.

Each generator-call, having been through elaboration, will have a .result field, which is a Module.
This'll just need the tweak to, if encountering a GeneratorCall, inspect its result as a module.

@uduse
Copy link
Collaborator Author

uduse commented Jan 18, 2023

Does that "or operator creates Union types" work in Pythons v3.7-3.9?
I think it's only 3.10+.

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.

@uduse uduse requested a review from dan-fritchman January 24, 2023 21:16
@uduse uduse self-assigned this Jan 24, 2023
@uduse uduse added the enhancement New feature or request label Jan 24, 2023
@uduse uduse linked an issue Jan 24, 2023 that may be closed by this pull request
@uduse uduse marked this pull request as ready for review January 24, 2023 22:56
@uduse uduse changed the title feat: hierarchical flattening draft feat: hierarchical flattening Jan 24, 2023
@uduse
Copy link
Collaborator Author

uduse commented Apr 12, 2023

ping

@dan-fritchman
Copy link
Owner

Sorry what's the "ping" there?
I left a bunch of commentary back in January. Did it get resolved?

@uduse
Copy link
Collaborator Author

uduse commented Apr 12, 2023

Sorry what's the "ping" there? I left a bunch of commentary back in January. Did it get resolved?

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 Show resolved Hide resolved
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))
Copy link
Owner

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:

def _copy_to_internal(sig: Signal) -> Signal:
. (I don't think we will?)

Copy link
Collaborator Author

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.

hdl21/flatten.py Show resolved Hide resolved
hdl21/flatten.py Outdated Show resolved Hide resolved
hdl21/flatten.py Outdated Show resolved Hide resolved
hdl21/flatten.py Show resolved Hide resolved
hdl21/flatten.py Outdated Show resolved Hide resolved
@dan-fritchman
Copy link
Owner

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.

@uduse uduse marked this pull request as draft May 25, 2023 01:14
@uduse
Copy link
Collaborator Author

uduse commented May 25, 2023

@dan-fritchman updated based on your feedback, passes tests locally.

dan-fritchman added a commit that referenced this pull request May 25, 2023
Mostly catch up to Vlsir main, un-block #90
@uduse uduse marked this pull request as ready for review May 26, 2023 19:31
@uduse uduse requested a review from dan-fritchman May 26, 2023 19:31
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)):
Copy link
Owner

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?

Copy link
Owner

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)

Copy link
Collaborator Author

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?

@dan-fritchman
Copy link
Owner

Added a few more tests here:
04eba75

There's 3 things, two related groups:

  • Supporting Generators should be pretty quick. They've already been elaborated ("run"); just dispatch all the flattening-code to their result Module.
  • Slice and Concat will have some more mechanics. There is an existing elaborator-pass hdl21/elab/elaborators/slices.py which does "resolution" for them on a per-Module basis. I expect flattening will need something similar, enacting this across Instance/ Module boundaries.

@dan-fritchman
Copy link
Owner

A few more things not included in those tests which should be added, and should be pretty straightforward:

  • Instances of ExternalModules
  • Instances of Generator (calls)

@uduse
Copy link
Collaborator Author

uduse commented Nov 24, 2023

  • Seems GeneratorCall is no longer explicit. I am taking that part out.
  • I'm not exactly sure how to handle Slice and Concat. How about this: there will be no Slice and Concat on the flattened module, only Signal with various widths.

@uduse uduse requested a review from dan-fritchman November 24, 2023 01:52
@uduse uduse marked this pull request as draft November 24, 2023 01:52
new_conns = {}
new_parents = parents + (inst,)
for src_port_name, sig in inst.conns.items():
if isinstance(sig, h.Signal):
Copy link
Owner

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)):
Copy link
Owner

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):
Copy link
Owner

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, and
  • ExternalModuleCall - which we should regard as "already flat"

@dan-fritchman dan-fritchman mentioned this pull request Dec 18, 2023
@dan-fritchman
Copy link
Owner

dan-fritchman commented Dec 18, 2023

OK here's a few proposed tweaks: #213.
Including (for now) just raising a NotImplementedError when encountering slices and/or concats.
Can either roll those commits in here, or use that PR instead.

@uduse
Copy link
Collaborator Author

uduse commented Dec 24, 2023

Closing in favor of #213

@uduse uduse closed this Dec 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hierarchical Flattening for Modules
2 participants