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

Feature to share implementation #1212

Open
taichi-ishitani opened this issue Jan 27, 2025 · 9 comments
Open

Feature to share implementation #1212

taichi-ishitani opened this issue Jan 27, 2025 · 9 comments
Labels
lang Language design

Comments

@taichi-ishitani
Copy link
Contributor

For pzbcm, I use text macros to share implementation.
For example:

I need a new feature to share implementation between design elements to re-write these interfaces in Veryl.
Followings are idenas for this.

  • Unnamed code block.

This is similar to #793 but no instance name is needed.
Code block will be expanded into the scope where it is instantiated.

  • Interface inheritance

For the above example, pzcorebus_if behaves pzcorebus_request_if and also pzcorebus_response_if.
Therefore, I think inheritance is one of suitable ways to model the above case.
Implementations of parent interfaces are expanded into the child interface.

@dalance dalance added the lang Language design label Jan 27, 2025
@dalance
Copy link
Collaborator

dalance commented Jan 27, 2025

#908 seems to be related too.

@dalance
Copy link
Collaborator

dalance commented Jan 27, 2025

I think interface inheritance / composition is better than code block approach in this case because code block provide only a feature like text macro and not special support for interface.

There are some syntax ideas:

interface Req {
    var cmd: logic;
    var cmd_accept: logic;
}

interface Resp {
    var data: logic;
    var data_accept: logic
}

interface Bundle inherit Req, Resp {
}
// This is the same as 
// interface Bundle {
//     var cmd: logic;
//     var cmd_accept: logic;
//     var data: logic;
//     var data_accept: logic
// }

// Another inherit syntax
interface Bundle {
    inherit Req;
    inherit Resp;
}

// Composition style
interface Bundle {
    inst req: Req;
    inst resp: Resp;
}

Regardless syntax style, actual member definitions becomes to be difficult to understand in case of having deep inherit depth.
The instance name in composition style seems to be meaningless, so inherit may be better.

@dalance
Copy link
Collaborator

dalance commented Jan 27, 2025

Sorry, I've mistakely closed.

@taichi-ishitani
Copy link
Contributor Author

taichi-ishitani commented Jan 28, 2025

We need to consider how propagate child's generic arguments and parameters to parent interfaces.
From point of this view, I prefer this syntax.

interface Bundle #(
  param ADDRESS_WIDTH: u32 = 8,
  param DATA_WIDTH:    u32 = 8,
) {
  inst Req  #(ADDRESS_WIDTH, DATA_WIDTH);
  inst Resp #(DATA_WIDTH);
}

@dalance
Copy link
Collaborator

dalance commented Jan 28, 2025

Surely, it seems to be necessary.
But I think the inst keyword is not proper, because the new syntax is bit differ than the existing inst declaration.
(and it is not instantiation strictly)
inherit or another appropriate keyword is necessary.

interface Bundle #(
  param ADDRESS_WIDTH: u32 = 8,
  param DATA_WIDTH:    u32 = 8,
) {
  inherit Req  #(ADDRESS_WIDTH, DATA_WIDTH);
  inherit Resp #(DATA_WIDTH);
}

@taichi-ishitani
Copy link
Contributor Author

inst keyword is not proper

Sorry, this is my miss type.

@dalance
Copy link
Collaborator

dalance commented Jan 28, 2025

Multiple inheritance and diamond problem should be considerd.

interface Base #(
    param WIDTH: u32 = 0,
) {
    var x: logic<WIDTH>,
}

interface Req #(
    param WIDTH: u32 = 0,
) {
    inherit Base #(WIDTH);

    var cmd: logic<WIDTH>;
    var cmd_accept: logic;
}

interface Resp #(
    param WIDTH: u32 = 0,
) {
    inherit Base #(WIDTH);

    var data: logic<WIDTH>;
    var data_accept: logic
}

interface Bundle #(
  param ADDRESS_WIDTH: u32 = 8,
  param DATA_WIDTH:    u32 = 8,
) {

  // Base::x is inherited from both Req and Resp with the differenct parameter override

  inherit Req  #(ADDRESS_WIDTH);
  inherit Resp #(DATA_WIDTH);
}

@taichi-ishitani
Copy link
Contributor Author

When generating SV code, parent interfaces will be expanded into child interface.
Therefore, parent interfaces cannot have members which have the same name and so Veryl compiler should report an error for the above example.

@dalance
Copy link
Collaborator

dalance commented Jan 28, 2025

Generally, there are several ways to resolve diamond problem.

  • Single inheritance only
  • Forbid nested inheritance
  • Check conflict at compile
  • Separated namespace for each inheritance path

Even if we adopt checking scheme, there are some choices about what type conflict is allowed or not.
For example, non-parameterized common parent can be allowed safely, but forbidding all naming conflict is more simple.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lang Language design
Projects
None yet
Development

No branches or pull requests

2 participants