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 Request] Poke Instance Values #15

Closed
leonardt opened this issue Feb 27, 2021 · 7 comments
Closed

[Feature Request] Poke Instance Values #15

leonardt opened this issue Feb 27, 2021 · 7 comments
Labels
enhancement New feature or request

Comments

@leonardt
Copy link
Contributor

I'm interested in adding support for a pysv style driver where the input stimuli are generated by a Python class. The difficulty here is transferring the values from Python to SV. We could call separate methods for each port value (with each method returning a value), but that seems a bit convoluted. Is there any possibility of having the Python code somehow poke values in the simulation? It seems like we'd need some DPI support for this to work, but maybe if we could pass a handle to an instance, we could set the values of ports.

@Kuree Kuree added the enhancement New feature or request label Feb 27, 2021
@Kuree
Copy link
Owner

Kuree commented Feb 27, 2021

I can think of two ways to do it. Both approach has some advantages and drawbacks.

Pure DPI-based approach

The DPI defined by LRM does support pass by reference. Here is an example to set values from C:

import "DPI-C" function void set(output int a);

module top;

logic [31:0] a;

initial begin
    set(a);
    $display("value is: %0d", a);
end

endmodule
void set(int *a) { *a = 42; }

If you run the code, you will see logic a is set to 42.

The issue is that Python doesn't support pass by reference, so there needs a translation to bridge the gap. One simple way I can think of is adding another return type such as Reference, which essentially assigns names and types to the return tuple. Consider the following mock example:

@py(a=Int32, b=Int16, return_type=Reference(c=Int32, d=Int32, e=Int16))
def foo(a, b):
    return a + b, a, b

Then it will be translated into the following C signature

void foo(int32_t a, int16_t b, int32_t *c, int32_t *d, int16_t *e);

Then in SV you do the following:

logic[31:0] a, c, d;
logic[15:0] b, e;

initial begin
foo(a, b, c, d, e);   // c, d, e will be set in the C function
end

I haven't tested this out with Verilator, but I suspect this should work as well.

The issue with that is the downstream tools like fault need to assemble the arguments together, and possibly need to unwrap the return value from a high-level construct before handing it over to pysv.

VPI-based approach

Setting values is much easier to do in VPI, since there is a dedicated section in the LRM describing how it is done, and how you can pass in a handle of a RTL instance and change their port values. Here are advantages of using it:

  1. I have a working framework in hgdb that already implements this partially. I can port the code over to handle that.
  2. VPI allows introspection at runtime, so we can catch illegal usage at runtime (this could be done at compile time at fault though).
  3. It will make the SystemVerilog backend of much easier since you can just define a custom system task as follows:
$drive_signals(top);

where top is the test bench module name;

However, I'm a little bit reluctant to do it via API that due to the following reasons:

  1. I haven't figured out a way to make system task working with Verilator yet. So passing in an instance handle to pysv could be difficult. Even if it is possible, setting values via VPI has some side-effects that's difficult to deal with. For instance, we need to change how Verilator testbench is written as it is not an event-driven simulator.
  2. A VPI->Python translation layer is required to allow python function access VPI objects. I haven't done that part yet.
  3. VPI-based libraries are difficult to test since the real implementation relies on the linker to solve. We need to provide our own VPI implementation if we want to unit test it. I can however, port over my VPI emulator from hgdb for testing.

Please let me know what you think.

@leonardt
Copy link
Contributor Author

leonardt commented Mar 1, 2021

I think the DPI approach should work if it's simpler, let me brainstorm about the interface, perhaps there's some alternative to just returning the reference values that's a bit more natural

@leonardt
Copy link
Contributor Author

leonardt commented Mar 1, 2021

Actually we might be able to just handle the references at the fault level. So a user in fault could say something like circuit.a = 3 and internally we remap that code to use the pysv style return, so i think at a first pass we can just have the simple return interface

@Kuree
Copy link
Owner

Kuree commented Mar 1, 2021

So a user in fault could say something like circuit.a = 3 and internally we remap that code to use the pysv style return, so i think at a first pass we can just have the simple return interface

Are you referring to a) primitive as return type or b) reference/class object as return type?

@leonardt
Copy link
Contributor Author

leonardt commented Mar 2, 2021

I think reference is required since that's how you supply the names for each return value?

@Kuree
Copy link
Owner

Kuree commented Mar 2, 2021

Got it. I'm going to implement that.

@Kuree Kuree closed this as completed in 07054b7 Mar 2, 2021
@Kuree
Copy link
Owner

Kuree commented Mar 2, 2021

Should be working now. Feel free to reopen or open another issue if it doesn't work with fault.

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

No branches or pull requests

2 participants