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

Run the object code from somewhere else then GHDL #819

Closed
Ingrimmel opened this issue May 14, 2019 · 5 comments
Closed

Run the object code from somewhere else then GHDL #819

Ingrimmel opened this issue May 14, 2019 · 5 comments

Comments

@Ingrimmel
Copy link

Hi,

i am playing around with GHDL for a view weeks by now.
In the last days i am trying to find a way to run the object file, generated by gcc, wihtout the further usage of ghdl.

Therefore i analyzed the code in unix but i couldn't figure out how to run the file so far.

Is there a workaround for this task or do you have some advices for me to solve it?

Or is there even a simple way to figure out the name of the function i have to call plus the needed sequence and type of the values i have to hand over to the function?

I know that this request is pretty uncommon, therefore i would like to thank you already now for every help.

Greetings

Ingrimmsch

P.S.: I added the simple example i am using to figure it out inside this .zip file:
ghdl_example.zip

@eine
Copy link
Collaborator

eine commented May 14, 2019

Hi @Ingrimmsch, there are multiple ways to achieve what you want.

In the last days i am trying to find a way to run the object file, generated by gcc, wihtout the further usage of ghdl.

Therefore i analyzed the code in unix but i couldn't figure out how to run the file so far.

Some context: the object files are generated after executing ghdl -a. That is the first step (analysis). In order to complete the 'compilation' of a design, you need to also elaborate it. You do that with ghdl -e. Last, the simulation is executed with ghdl -r.

I assume that you already knew this, because you read https://ghdl.readthedocs.io/en/latest/using/QuickStartGuide.html at some point. But you might have not understood that you won't get any binary after ghdl -e, if you are using mcode backend (you can check the backend you are using with ghdl --version).

Is there a workaround for this task or do you have some advices for me to solve it?

The most straighforward solution is for you to use any backend which is not mcode (i.e. GCC or LLVM). This is because mcode is a built-in backend which executes the last steps of elaboration in-memory and runs the simulation directly. Conversely, GCC/LLVM cannot run from memory, so an executable binary is always created as a result of the elaboration (ghdl -e). Please see the table in https://github.com/ghdl/ghdl#building-ghdl and the hints in https://ghdl.readthedocs.io/en/latest/building/Building.html.

Or is there even a simple way to figure out the name of the function i have to call plus the needed sequence and type of the values i have to hand over to the function?

Additionaly, it is possible to wrap GHDL in some external C/Ada program. As explained in https://ghdl.readthedocs.io/en/latest/using/Foreign.html#wrapping-and-starting-a-ghdl-simulation-from-a-foreign-program, you can write your own C program, and declare ghdl_main as an external function: extern int ghdl_main (int argc, char **argv);. In this context, there are two possible approaches for elaboration/compilation after analyzing VHDL sources:

  • Execute gcc -c my_prog.c and then ghdl -e -Wl,my_prog.o design (with GCC/LLVM backends *1).
  • Execute ghdl --bind design and gcc my_prog.c -Wl,$(ghdl --list-link design) (with any backend).

The result will be equivalent in both cases: an executable binary with the default entrypoint set to your main function. With the first procedure, If you don't write any main function in my_prog.c, the entrypoint will default to ghdl_main *2.

Furthemore, it is possible to let the binary be dynamically loaded, as if it was a shared library. This allows to use the same binary in two contexts:

  • Direct execution, which defaults to main.
  • Loading through dlopen and executing any of the functions. This allows to start from main or to jump to ghdl_main directly, skipping main.

There are some details to take into account when following this last approach, which are related to the visibility of the symbols/functions compiled into the binary/shared library. But I won't go into details now. Please, let us know if you want further details.

I know that this request is pretty uncommon, therefore i would like to thank you already now for every help.

Your are very welcome. But you need not to worry about it. This question is much common than you think. It is not usual for VHDL simulators/compilers to support multiple backends, so many people need some time to wrap their head around it.

The next question that might arise, is how to pass CLI arguments to the binary you generated. More precisely, how do you parse argc and argv from VHDL. The answer is that you do not do it. You just define generics in the top entity (your testbench): https://ghdl.readthedocs.io/en/latest/using/Simulation.html#cmdoption-ghdl-ggeneric. See #607.

P.S.: I added the simple example i am using to figure it out inside this .zip file:
ghdl_example.zip

I downloaded it and had a look at it. But I did nothing with it, because I think that your question is not really related to the design (VHDL code), but to how to use the tool (GHDL). Nonetheless, let us know if you have any further issue once you have understood the differences between backends.

Last, but not least, please feel free to suggest any enhancement to the docs, if you find that it can be made easier to follow for newcomers.


*1 @tgingold, I am not sure about this, since you did some recent changes to mcode related to the generation of shared libraries. Is it currently possible to generate an executable object (name it binary or shared library) with mcode?

*2 @tgingold, I am neither sure about this. Is correct to say the the first method above will default to ghdl_main but that the second one will not compile to an executable binary if main is not defined?

EDIT

@Ingrimmsch, please, let me suggest you to use VUnit, once you have understood the basics of GHDL. It will make it easier for you to set (complex) generics, generate/open waveforms and print/log messages. Precisely, I use VUnit + GHDL to generate executable binaries that I can then move and run as independent programs.

@tgingold
Copy link
Member

tgingold commented May 14, 2019 via email

@Ingrimmel
Copy link
Author

Hi @1138-4eb,

thank you for your detailed answer.

First of all -> As a backend i am already using GCC 9.1.0, which is why i already was able to generate some object code.

I saw that it's possible to run the GHDL simulation like this, but that wont solve my problem. Probably i wasn't specific enough:
Let's stay with my small "adder.vhdl" example. What i'd like to achieve is, that i can hand over the values of the input ports (High/low) and that i can read the values of the outputs with C.

I want to try to make a live-time simulation of a VHDL code to extend a small program at my university.

Therefore i thought that it would be the easiest way to take the pre-generated object-code of GHDL and use it to simulate a VHDL codes behavior live-time.

When the project is finished i want to use a view vhdl modules, connect them virtually with real In- and Out-Pins to make a Piece of hardware thats not as performant as the final FPGA but that you can use to test the basic functions.

I hope my attempt is more understandable like this.

Greetings

Ingrimmsch

@eine
Copy link
Collaborator

eine commented May 18, 2019

I saw that it's possible to run the GHDL simulation like this, but that wont solve my problem. Probably i wasn't specific enough:
Let's stay with my small "adder.vhdl" example. What i'd like to achieve is, that i can hand over the values of the input ports (High/low) and that i can read the values of the outputs with C.

See comment about generics above:

The next question that might arise, is how to pass CLI arguments to the binary you generated. More precisely, how do you parse argc and argv from VHDL. The answer is that you do not do it. You just define generics in the top entity (your testbench): ghdl.readthedocs.io/en/latest/using/Simulation.html#cmdoption-ghdl-ggeneric. See #607.

To read the outputs, you can use VHPIDIRECCT or VPI. The following example uses VHPI: https://github.com/VUnit/vunit/pull/465/files

I want to try to make a live-time simulation of a VHDL code to extend a small program at my university.

Therefore i thought that it would be the easiest way to take the pre-generated object-code of GHDL and use it to simulate a VHDL codes behavior live-time.

When the project is finished i want to use a view vhdl modules, connect them virtually with real In- and Out-Pins to make a Piece of hardware thats not as performant as the final FPGA but that you can use to test the basic functions.

VUnit/vunit#465, VUnit/vunit#470 and VUnit/vunit#476 are work in progress to make it easier to implement these kind of co-simulation schemes with VHPIDIRECT. There are other examples where the 'view' is implemented with Flask and Vuejs, but the core functionality is the same.

@eine
Copy link
Collaborator

eine commented May 3, 2020

Repository ghdl/ghdl-cosim contains documentation and examples about the features discussed above.

@eine eine closed this as completed May 3, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants