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

Classes as namespaces not supported? #97

Open
fl4shk opened this issue Jun 19, 2020 · 10 comments
Open

Classes as namespaces not supported? #97

fl4shk opened this issue Jun 19, 2020 · 10 comments

Comments

@fl4shk
Copy link

fl4shk commented Jun 19, 2020

Here is a feature that I've yet to see supported in synthesis of SystemVerilog that I think would be useful, the ability to use a class as a namespace.

It's the only way to parameterize a struct placed onto a port in SystemVerilog, and it's explicitly mentioned as the way to do that in the SystemVerilog standard. I've attached an example of what I mean.

alu_module.txt

@zachjs
Copy link
Owner

zachjs commented Jun 20, 2020

This is pretty interesting! I had never really considered that classes could be used in synthesizable code. This is something I can add.

It's the only way to parameterize a struct placed onto a port in SystemVerilog

Isn't it possible to use a struct from a parameterized interface modport? This might be a little clunky, but I think it might be another way to achieve a similar result.

@fl4shk
Copy link
Author

fl4shk commented Jun 20, 2020

I am unsure if it's possible to do what you've suggested, though it does sound reasonable.

What seems impossible with SV is the ability to use interfaces as namespaces. The SV standard people seem to have intended that classes be usable for that, but as I mentioned, I don't believe any synthesis tools support that use case for classes. They give up at the sight of the class keyword, despite this specific use case being mentioned in the SV standard.

@fl4shk
Copy link
Author

fl4shk commented Jun 20, 2020

Also, I made a mistake in showing the use of classes as namespaces: :: is used rather than .. The enum usage should have been like so: AluNs(.WIDTH(WIDTH))::OP_ADD rather than AluNs(.WIDTH(WIDTH)).OP_ADD.

@zachjs
Copy link
Owner

zachjs commented Aug 8, 2020

There may be a relatively straightforward way to add support, provided that any identifiers in the class parameter bindings only refer to declarations at the top level of the module, rather than localparams defined within a procedure or generate block. Do you think this would still satisfy most use cases?

@fl4shk
Copy link
Author

fl4shk commented Aug 9, 2020

I think it'd definitely be best, in general, to also support the localparams defined within a procedure or generate block. Many, many use cases would be solved with just top level parameters and localparams, though, from what I can tell. Here is why: you can just move the parameter to the top level of the module, at least for procedures. Generate blocks might want to have a localparam based upon the loop variable, though, which may cause a problem in some cases?

@zachjs
Copy link
Owner

zachjs commented Apr 13, 2021

Sorry for the delay over here! I have been making progress behind the scenes and have pushed what I've got so far. I've added initial support for using classes in this way, but there is a key limitation. While these class scoped identifiers can be used in any context, parameter overrides can only refer to declarations the global or module scope. Please let me know if it works for you!

@zachjs
Copy link
Owner

zachjs commented Jun 19, 2021

As of 3955c47, the parameter overrides can refer to declarations in a local generate scope. I'm still eager to see if this implementation is working as you'd expect it to!

@andrewandrepowell
Copy link

andrewandrepowell commented Jun 24, 2021

Hello again!

To add to this current discussion on using classes as namespaces, it would be really nice if the following was supported.

class adder #(
  parameter type T = logic[31:0]);
  static function T operate(T operand0, T operand1);
    return operand0+operand1;
  endfunction
endclass

module reduce(clock, reset, operand0, operand1, result);
  parameter type T = logic[31:0];
  parameter type OPERATION = adder;

  input logic clock, reset;
  flow.receive operand0, operand1;
  flow.send result;

  always_ff @(posedge clock) begin
    if (reset) begin
      result.valid <= 0;
    end else begin
      result.valid <= operand0.valid&&operand1.valid;
    end;
    result.data <= OPERATION#(.T(T))::operate(operand0.data, operand1.data);
  end;

endmodule

The main thing is supporting static functions and tasks so that even operations can be abstracted from modules. This actually builds in Vivado 2020.2.

EDIT: Oops. There was a mistake with the example. I made the correction. I meant to use OPERATION to call the add operation.

@zachjs
Copy link
Owner

zachjs commented Jun 25, 2021

I've just added proper support for static methods. sv2v doesn't yet support class types as parameters (parameter type OPERATION = adder;). The current architecture surrounding the elaboration of type parameters and classes does not lend itself well to this extension, but I can look into some options.

@andrewandrepowell
Copy link

Pulled down the changes and I can see that the static functions convert. Thanks again!

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

No branches or pull requests

3 participants