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

[PoC] Interfacing GHDL to other languages: declaration of foreign C functions #465

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

umarcor
Copy link
Member

@umarcor umarcor commented Apr 6, 2019

This PR is an example of how users can use GHDL + VUnit + VHPIDIRECT without built-in types. For practical cases, using string_ptr, byte_vector_ptr and/or integer_vector_ptr instead is recommended. See #507, #476.

Using 1138-4EB/hwd-ide/tree/examples-vhpi/examples/VHPI as a reference, this PR extends example array_axis_vcs to use data defined in a foreign C function. Moreover, the entrypoint to the binary is a foreign main function, instead of the (default) ghdl_main.

  • tb_axis_loop.vhd is renamed to tb_py_axis_loop.vhd.
    • The instantiation of the UUT and the VCs is moved to a separate file: tb_vc_axis_loop.vhd
  • tb_c_axis_loop.vhd is added. This is equivalent to tb_py_axis_loop.vhd but, instead of reading/writing data from/to CSV files, data is generated in some C function and the output is evaluated in another C function.
  • In file pkg_c.vhd, the equivalencies between VHDL functions/types and the foreign resources are declared.
  • run.py is modified in order to first build the C sources to an object and then pass the object to GHDL for elaboration.

These examples are functional ATM. However, there are some issues that can be improved:

  • The additional elaboration flags are being passed to both testbenches. This means that the py testbench is also being executed through the foreign main function. This is not required, and it should be avoided.
  • I find it ugly to execute GCC explicitly in the run.py. I'd rather add the C sources as any other source (lib.add_source_files(join(root, "src/**/*.c")) and let VUnit handle it. However, I don't know if this can work with other simulators that support VHPI, or is something specific to GHDL. @kraigher, is this something you would like to support? Note that this same approach can be used to, e.g., let the simulation draw images in a window during simulation (see xvga). How to provide different sets of C objects to several testbenches: some of the C sources are common, and some are specific for each testbench. This is implemented in [3/3] Support up to N external memory models #470.
  • If I execute python3 run.py -v --elaborate, the application (main) is executed, but GHDL is skipped, so the check fails. I would expect the binary not to be executed at all. [add sim_opt 'ghdl.elab_e' to run 'ghdl -e' instead of 'ghdl --elab-run --no-run' #467]
  • When the simulation is successful, but the C check fails, VUnit reports pass. main.c and/or tb_c_axis_loop.vhd should be updated in order to fix this. See fix: nonzero return values should produce a fail #469.

I'm now building an example that uses AXI Master, instead of AXI Stream, in order to try the alternative memory model as commented at #462. Is there any AXI Master IP in the VUnit codebase which I can use as a UUT? See #462 (comment)

@umarcor
Copy link
Member Author

umarcor commented Apr 6, 2019

Apart from the copyright issues, I think that the acceptance tests are failing because the GHDL version being used at appveyor is v0.35. I could successfully execute them with GHDL 0.36-dev (20181129-168-g50da90f5).

@kraigher
Copy link
Collaborator

kraigher commented Apr 7, 2019

It is possible to set a sim_option for just one test case or test bench so you do not have to set it for all test benches.

Regarding adding support for invoking GCC from VUnit I do not think it makes sense. For building C-code there already lots of tools out there and it does not seem worth the effort to add dependency scanning, build rules, compiler flag settings etc for GCC to VUnit. You could just call an external makefile from the run.py file to build any C-code.

Regarding '--elaborate' the GHDL binary must be called for elaboration to be performed. I guess in this example since you are wrapping the GHDL main function with data generation and checking you need to check the ARGV and skip data generation and checking unless the run flag was given.

@umarcor
Copy link
Member Author

umarcor commented Apr 7, 2019

It is possible to set a sim_option for just one test case or test bench so you do not have to set it for all test benches.

Thanks. I'll look for the correct syntax to do so.

Regarding adding support for invoking GCC from VUnit I do not think it makes sense. For building C-code there already lots of tools out there and it does not seem worth the effort to add dependency scanning, build rules, compiler flag settings etc for GCC to VUnit. You could just call an external makefile from the run.py file to build any C-code.

I agree that it is possible, and desirale indeed, to rely on external makefiles, cmakes, etc. This is specially so because foreign declarations can be written not only in C, but in multiple other languages.

Hence, I did not explain myself properly. I meant adding -Wl,path/to/a/c/object to sim_options. If I built all the sources externally and saved the objects to say vunit_out/ghdl/libraries/c, it would be possible to add the directory (or all the objects in it) automatically, without having to manually add each of them as sim options. In the current example there is a single object file, but in a practical design there might be multiple. However, I don't know if vunit_out/ghdl/libraries/c/*.o is the best location. I am using join(root, 'src/test/main.o') for now.

Regarding '--elaborate' the GHDL binary must be called for elaboration to be performed.

I opened a new issue to discuss this. Please see #466.

@kraigher
Copy link
Collaborator

kraigher commented Apr 7, 2019

Wouldnt the user want to specify unique .o files for each testbench/test. Then all of them cannot be automatically added.

@umarcor
Copy link
Member Author

umarcor commented Apr 7, 2019

Now, the elaboration flag -Wl, is only added to the testbench that uses the external memory/buffer. This produces an error during elaboration. I opened an issue about it: ghdl/ghdl#793. As commented there, the alternatives now are to provide two versions of some VHDL sources or to provide a stubs.c file. I'm going with this second option until I get some reply from Tristan.

Wouldnt the user want to specify unique .o files for each testbench/test. Then all of them cannot be automatically added.

In the current implementation of the external memory model, I provide different sets of .o files to the testbenches, depending on what type(s) of model(s) are used. I'll try to adapt the AXI DMA example ASAP.

@umarcor umarcor force-pushed the feat-foreign-c branch 3 times, most recently from f4c7f2c to 14f9c2e Compare April 8, 2019 11:45
@umarcor umarcor changed the title [POC] Interfacing GHDL to other languages: declaration of foreign C functions Interfacing GHDL to other languages: declaration of foreign C functions Apr 8, 2019
@umarcor umarcor marked this pull request as ready for review April 8, 2019 11:48
@umarcor
Copy link
Member Author

umarcor commented Apr 8, 2019

@kraigher, I think this is ready for review now. As you see, I replaced the protected shared variables with a memory_t, which is similar to the one used in VUnit. Nevertheless, the main objective of this PR is to provide an example of how to use VUnit and GHDL to interact with foreign languages: https://www.diffchecker.com/ck5A79oZ

There are three implementation details wich I am not completely happy with, but I couldn't guess how to do it better:

In the "traditional testbench", stubs.c is used just to show how to wrap a GHDL + VUnit simulation in a C application. In the second testbench, a buffer is allocated in the C application and VHPIDIRECT callbacks are used to share data between the testbench and the application.

@umarcor umarcor changed the title Interfacing GHDL to other languages: declaration of foreign C functions [PoC] Interfacing GHDL to other languages: declaration of foreign C functions Sep 7, 2019
@umarcor umarcor force-pushed the feat-foreign-c branch 2 times, most recently from d51c831 to 0694f40 Compare September 13, 2019 03:06
@umarcor umarcor force-pushed the feat-foreign-c branch 3 times, most recently from f4f5c70 to c5b75cb Compare December 2, 2019 06:18
@eine eine added the CoSim label Feb 10, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants