Skip to content

Conversation

mmaloney-sf
Copy link
Contributor

Introduces a new API withModulePrefix.

Example:

class Submod extends RawModule {
  // ...
}

class Top extends RawModule {
  val noprefix_inst = Module(new Submod)

  withModulePrefix("Foo") {
    val foo_inst = Module(new Submod)
  }

  withModulePrefix("Bar") {
    val bar_inst = Module(new Submod)
  }
}

This will result in the definition of the following modules:

  module Submod :
    skip

  module Foo_Submod :
    skip

  module Bar_Submod : 
    skip

  public module Top :

    inst noprefix_inst of Submod
    inst foo_inst of Foo_Submod
    inst bar_inst of Bar_Submod

Only module definitions are prefixed. Other circuit components, such as wires and registers, are unaffected.

Module prefixes nest, where Foo_Bar_Submod indicating that a prefix Foo exists in the grantparent or higher of the instance of Submod.

When using this API withInstantiate, two instantiations under two distinct module prefix blocks will result in two "copies" of the definition, one for each prefix. Conversely, two instantiations under the same module prefix block will share the same prefixed definition.

Contributor Checklist

  • Did you add Scaladoc to every public function/method?
  • Did you add at least one test demonstrating the PR?
  • Did you delete any extraneous printlns/debugging code?
  • Did you specify the type of improvement?
  • Did you add appropriate documentation in docs/src?
  • Did you request a desired merge strategy?
  • Did you add text to be included in the Release Notes for this change?

Type of Improvement

  • Feature (or new API)

Desired Merge Strategy

  • Squash: The PR will be squashed and merged (choose this if you have no preference).
  • Rebase: You will rebase the PR onto master and it will be merged with a merge commit.

Release Notes

Reviewer Checklist (only modified by reviewer)

  • Did you add the appropriate labels? (Select the most appropriate one based on the "Type of Improvement")
  • Did you mark the proper milestone (Bug fix: 3.6.x, 5.x, or 6.x depending on impact, API modification or big change: 7.0)?
  • Did you review?
  • Did you check whether all relevant Contributor checkboxes have been checked?
  • Did you do one of the following when ready to merge:
    • Squash: You/ the contributor Enable auto-merge (squash), clean up the commit message, and label with Please Merge.
    • Merge: Ensure that contributor has cleaned up their commit history, then merge with Create a merge commit.

@seldridge seldridge added the Feature New feature, will be included in release notes label Oct 26, 2024
Copy link
Contributor

@jackkoenig jackkoenig left a comment

Choose a reason for hiding this comment

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

Generally looks good, 1 question about _.

Also we need to define and test the behavior for Definition and Instance. Instance should have no interaction with the prefix but should Definition? My initial reaction is "no" since Definition is essentially a separate Chisel elaboration, but I'm unsure. Any thoughts @mwachs5, @azidar, @seldridge?

We also probably need a way to remove the prefix, e.g. withNoModulePrefix or withOverrideModulePrefix("") or something.

@mwachs5
Copy link
Contributor

mwachs5 commented Oct 28, 2024

Well, for definitions I think you do want the module prefix baked into it somehow. Is it a Val def = withModulePrefix (Definition(new Foo)) or perhaps it's better something one adds as an argument the Definition/Module/Instantiate APIs directly?

@mwachs5
Copy link
Contributor

mwachs5 commented Oct 28, 2024

Actually now that I wrote the above comment I really think it's a more natural thing to do than withModulePrefix(...) even for Module. For the latter why would we be doing it for more than one child ever, isn't it always started at one module or definition instantiation?

@jackkoenig
Copy link
Contributor

jackkoenig commented Oct 28, 2024

Actually now that I wrote the above comment I really think it's a more natural thing to do than withModulePrefix(...) even for Module. For the latter why would we be doing it for more than one child ever, isn't it always started at one module or definition instantiation?

I agree that we should instead make it an argument to Module, Definition, and Instantiate, but I just want to note that it's less about prefixing more than one child at a time, and more about adding 1 new API vs. modifying n (where n appears to be 3, but any other added APIs will also potentially need to add prefix).

So let's proceed with adding prefix as an optional (well optional via overloading) argument to Module, Definition, and Instantiate, but I want to call out some potential future work.

  1. How do we deal with instantiating modules from different prefix "namespaces"? For example, say you have a library of Queues and you want to instantiate from the library rather than forcing the current prefix. We could add another overloaded form of Module, Definition, and Instantiate to "set" the prefix rather than push to it, or we could add something similar to withModulePrefix but just for that use case.
  2. How do we deal with prefix for the top module? Should there be a way from within a Module class to set the prefix for yourself (and all children) or should it just be done on the command-line?

@mwachs5
Copy link
Contributor

mwachs5 commented Oct 28, 2024

So let's proceed with adding prefix as an optional (well optional via overloading) argument to Module, Definition, and Instantiate, but I want to call out some potential future work.

  1. How do we deal with instantiating modules from different prefix "namespaces"? For example, say you have a library of Queues and you want to instantiate from the library rather than forcing the current prefix. We could add another overloaded form of Module, Definition, and Instantiate to "set" the prefix rather than push to it, or we could add something similar to withModulePrefix but just for that use case.

Hm, very good point. I guess it's almost like you are forced to opt-in to making your component a valid 'top level' component that gets to control the prefixing.

  1. How do we deal with prefix for the top module? Should there be a way from within a Module class to set the prefix for yourself (and all children) or should it just be done on the command-line?

This makes me wonder, what is the behavior of doing something like:

val q = Module(withModulePrefix(new Queue))

Do you get an error? Is it the same as withModulePrefix(Module(new Queue))? Probably if not, you should get an error... and if so, isn't that the answer to the question 2?

@jackkoenig
Copy link
Contributor

So let's proceed with adding prefix as an optional (well optional via overloading) argument to Module, Definition, and Instantiate, but I want to call out some potential future work.

  1. How do we deal with instantiating modules from different prefix "namespaces"? For example, say you have a library of Queues and you want to instantiate from the library rather than forcing the current prefix. We could add another overloaded form of Module, Definition, and Instantiate to "set" the prefix rather than push to it, or we could add something similar to withModulePrefix but just for that use case.

Hm, very good point. I guess it's almost like you are forced to opt-in to making your component a valid 'top level' component that gets to control the prefixing.

Right, how should we do this? Maybe the answer depends on how we want to do linking.

  1. How do we deal with prefix for the top module? Should there be a way from within a Module class to set the prefix for yourself (and all children) or should it just be done on the command-line?

This makes me wonder, what is the behavior of doing something like:

val q = Module(withModulePrefix(new Queue))

Do you get an error? Is it the same as withModulePrefix(Module(new Queue))? Probably if not, you should get an error... and if so, isn't that the answer to the question 2?

I don't think it's the answer to question (2) though since we're moving to making the prefix an argument to Module, Definition, and Instance unless you're opinion on this has changed lol.

@mwachs5
Copy link
Contributor

mwachs5 commented Oct 29, 2024

don't think it's the answer to question (2) though since we're moving to making the prefix an argument to Module, Definition, and Instance unless you're opinion on this has changed lol.

Yes it has changed because as you pointed out it will not be so uncommon to call

withModulePrefix { HelperObjectThatActuallyCallsModule }

so if we need withModulePrefix anyway not sure we should expose it on the others

@jackkoenig jackkoenig marked this pull request as ready for review November 8, 2024 20:35
Co-authored-by: Megan Wachs <megan@sifive.com>
Copy link
Contributor

@mwachs5 mwachs5 left a comment

Choose a reason for hiding this comment

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

approving with minor comments! Thanks for adding this great feature

Copy link
Contributor

@jackkoenig jackkoenig left a comment

Choose a reason for hiding this comment

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

LGTM, consider fixing nit

@jackkoenig jackkoenig enabled auto-merge (squash) November 8, 2024 23:51
auto-merge was automatically disabled November 8, 2024 23:55

Head branch was pushed to by a user without write access

@jackkoenig jackkoenig merged commit 0e19171 into chipsalliance:main Nov 9, 2024
15 checks passed
@jackkoenig jackkoenig added this to the 7.0 milestone Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature New feature, will be included in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants