-
Notifications
You must be signed in to change notification settings - Fork 373
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
doc: add VHPIDIRECT demo #1059
doc: add VHPIDIRECT demo #1059
Conversation
c41e8e3
to
7c4edf0
Compare
bb01693
to
1aa54a8
Compare
I started #1194, because I hadn't seen this. @umarcor Nice and explicit post again. I would only add that I have an example for contrained array sharing, with the bounds set in C. I struggled for a while to try pass a generic to a package for the size of the array, which required VHDL 2008 (for generic packages). But VHDL 2002 (I think) upwards requires shared variables to be protected, and I could not see a way to set the pointer of the protected access type variables. Instead I have that the vhdl side accesses an integer, and then uses that to define the bounded array type.
How do I second the request for a documented section on external interfacing with GHDL? Much appreciation for your efforts again! EditFixed code block markdown. |
Is this still unfinished? It seems like it's been merged. If it has been merged, I'd like to reference it from the documentation. |
@RocketRoss, first off, thanks for your kind words. Much appreciated. Since I see you are interested and proactive on this topic, I'll dump all my knowledge, as a complement to what we already shared in #1184 and #1185. Please, bear with me and don't be overwhelmed ;). The purpose is for you (and others) to have this as a collection of references, not to understand everything as you read it.
In the following repo, several existing examples are gathered: https://github.com/eine/hwd-ide/tree/develop/examples. You will find the one you point to at https://github.com/eine/hwd-ide/tree/develop/examples/VHPI/ygdes_ghdl_extra. Other relevant examples are:
I think the reason these are not integrated in the docs yet is because there is no coherency and the entrypoint can be harsh. There is https://ghdl.readthedocs.io/en/latest/examples/README.html, but not any Quick Start alike.
As commented, https://ghdl.readthedocs.io/en/latest/examples/README.html exists, and you already found this PR. Potentially, most or all of the examples from https://github.com/eine/hwd-ide/tree/develop/examples can be migrated to the docs/examples subdir of this repo. However, many of them require additional external dependencies. I think we should be careful with including content in the main repo which is not required by GHDL itself. There are already C, Ada and Python snippets in https://ghdl.readthedocs.io/en/latest/using/Foreign.html, which is a short page. Having a lot of not properly explained references can be misleading instead of helpful. Precisely...
Since repo ghdlsynth-beta was moved to ghdl/ghdl-yosys-plugin a few days ago, and ghdl/ghdl-systemc-fosdem16 was created, I think it makes sense to reconsider ghdl/ghdl-yosys-plugin#98 (comment) and March 27, 2020 6:42 PM. Either ghdl/ghdl-examples can be created to contain examples about cosimulation and implementation; or ghdl/ghdl-cosim (maybe renaming ghdl-systemc-fosdem16) can be created to contain examples about different cosimulation solutions. In any case, docs would belong to any of those repos. Of course, it would be possible to cross-reference the content from ghdl.rtfd.io.
I believe this is the priority. Any modification (small or large) should focus on providing an easier entry path to users interested on (easy) cosimulation with GHDL. These are some currently missing ideas that, I think, would be interesting to be answered in the docs:
Also:
In this context, the purpose of this PR is not to solve any of the points above. Instead, it is to contribute a C header file (https://github.com/ghdl/ghdl/pull/1059/files#diff-b9e1702ba149af36a1889cdc33997902) which users can copy to their cosimulation projects as a helper or kind of "C API for GHDL's VHPIDIRECT". Currently, @hackfin, @bradleyharden, @ndesgranges, others and me, we are all facing the same issues when trying to reverse engineer details of how to interact with GHDL at runtime from C/C++ without using VPI. Hopefully, such as shared header file would make it easier for all of us to build new functionalities on top of GHDL, and to share hints/tricks. Should a repo named ghdl/ghdl-cosim be created, I believe this PR might be the foundation, along with ghdl/ghdl-systemc-fosdem16. Moreover, in the next version of the VHDL standard there might be a Direct Programming Interface (DPI) which might feel surprisingly close to GHDL's current VHPIDIRECT. Should that happen, either Anyway, note that this PR is NOT ready to be merged. It is a proof of concept to hopefully discuss the details with other potential users.
This is not included because it is straightforward as long as you hardcode the length in both VHDL and C. I thought it would be easy enough for anyone that is going to dive into this topic. However, it is true that the inmediate next step (defining the size in C and having VHDL pick it) is not as straightforward as it might seem. Actually, this is the main underlaying issue in VUnit/vunit#603: how to bind VHDL and C without having to duplicate all the content.
If you want to keep using shared variables but not protected types, and you want to use a generic in the package to set the size, I believe you can use Alternatively, not to require Nonetheless, note that using a protected type does not solve your issue: you still need to get a parameter from C (either through a function call or an access), in order to set the size of the constrained type in VHDL. Hence, essentially, you did exactly what most of the available examples do, either directly or indirectly. Well guessed! The elegant solution would be to use unconstrained arrays in VHDL. That allows not to hardcode the size of the arrays. This is what this PR is mostly about. Unconstrained arrays, and other complex types, are represented through undocumented (i.e. implementation dependent) fat pointers in VHDL. The header file in this PR provides helper functions to interact with those from C.
Yes, this is unfinished. Don't let GitHub's web GUI fool you. If you go to "Browse files" and check in which branch you are, you will see "Tree: 1d8faaa". That means you are watching the content of some arbitrary commit (in this case, the HEAD of a PR). I will review your PR (#1195), as you have addressed some of the ideas that I listed above. |
Concluding Discussion point:
I mean, I still had to pass an interface generic, but I could do it. Just to really explain: The protected type alone does nothing, but it is the requirement of VHDL-2008, with which I could create a generics-enabled-package with an array type with a range dependent on a generic. The toplevel would map its generic to the package, and so I could (per run) change the size of the array with an interface generic. This is not a nice solution. I am happier with the alternative I found. Especially because the runtime generics interface is en route to be deprecated.
It does exactly as the solution I discovered. Would have been nice to see this.. it is buried so deeply. Real response:
I think that referencing the source of VUnit, vhpidirect, sharedobject and ghdlex will be the conclusion of this suggested example page. Will confirm my current PR (#1195) and then work on such an example page. I think your listed topics are exhaustive (maybe missing systemc mixing as per ghdl-systemc-fosdem16). Ones I can cover vs cannot:
If this is where concrete MWE end up, I like it. Including this PR's header, at least for the more complex examples. I feel like just including it from the basic examples too, so that it settles as comfortable.
I did not find this page useful, but we are talking about revamping it so I'll only highlight the issue around the one promising link at
Yes! It's so tantilising. I wanted to crawl through VUnit's source, then ghdlex's source, and the PR's source... VUnit#568 is eye wateringly cool... but it's all too much and in so many different directions.... > there is no coherency and the entrypoint can be harsh.
Yes, and I have just tackled these issues so I am happy to document it before it is stale. Do you have a pointer for python, or the general approach for other languages? Surely the answer isnt that you just elaborate with an object file with an entrypoint and ghdl detects that?)
Subtle f. I think that it'd be good to start a dedicated page for this talk... maybe in my ghdl fork (linked in future comments etc). I don't feel like that is perfect because I still want to collect all the examples you mentioned. Maybe those can be PR to this proposed repo... maybe the ghdl-cosim-info suggested repo... gosh. First thing first is to start somewhere neat. Conclusion: I will stop short of fat pointers and strings, because I have yet to understand that. I have seen source, just need to get around to playing with it. Where do we move this discussion/progress board? (Apologies for hijacking the comment tree) I can always edit and just change it to a link to a repost elsewhere. Thanks @umarcor |
This is what I believe that can/could be avoided with However, note that the "external/foreign" features are not limited to resources declared in packages (first sentence in https://ghdl-rad.readthedocs.io/en/c-access-example-doc/examples/quick_start/Caccess/README.html#the-files; more on this below). You can declare all this code in the declarative part of an architecture too. This depends on the scope you want for this features, not on resources being VHDL-only or VHDL with external attributes. See
From a purely demo standpoint this adds an unnecessary level of complexity (the package). However, it does make sense for any practical use case, where the external resources are to be used from more than a single arch. In fact, I did also start with such an example and I then found that it could be simplified.
Although I agree, on the one hand generics are going nowhere in the close and mid future. On the other hand, since GHDL lacks built-in support for a (JSON, YAML) configuration file, usage of generics is currently the only option for external tools to provide runtime args without requiring complementary C code. The language server supports Hence, I believe that the most simple example should use top-level generics and the external resources should be declared in the architecture. Actually, the same as this PR, but using only one or two types, instead of all of them. This would be first step before going to a more complete example, such as "C Access". See https://ghdl-rad.readthedocs.io/en/latest/examples/quick_start/README.html for a feel of this "progressive" introduction of the content.
Yes. Hope we can make that hidden content easier to find for future users!
Actually, https://ghdl-rad.readthedocs.io/en/c-access-example-doc/examples/quick_start/Caccess/README.html#the-files includes the declarations of
Ideally, I'd like to copy about a dozen examples. I think that https://ghdl.readthedocs.io/en/latest/examples/README.html is a good tradeoff for a lack of time to adapt examples to the format/style expected in GHDL's docs. Specially, because such format/style is not really defined. However, since we agree on adding, at least, a few of them, we might define it.
It is meant to be copied almost as-is to a section named "What can be done with VHPIDIRECT?". It is not a list of tasks that need to be done, but ideas to gather people around.
I created https://github.com/umarcor/ghdl-cosim as a fork of ghdl/ghdl-systemc-fosdem16. I moved the existing content to subdir I believe we can use that fork to work on extending the docs and adding four examples:
2/4 of these are already written, the first one is straightforward, and I'd say I can find where I have the implementation of the last one. The idea is to let users understand by it is desirable to use the provided header file, but not to force them to use it. They are entitled to use their own custom VHDL-foreign APIs, and for GHDL as a project that's ok too. Hence, feel free to open issues there in order to discuss how to organise the content/sources. Once we are happy with the result, we can ask Tristan whether he prefers to have the content merged in the main repo or kept as a separate repo/site. Probably, some will be moved (explanations) and some will be separate (actual examples).
The dead links are my fault :(. The content is now available as VUnit/cosim (vunit.github.io/cosim). I'll update the refs. Anyway, I agree that it is not very useful. As said, it is a tradeoff. If we are going to provide a few actual examples, this content would be renamed to "other interesting projects that use VHPIDIRECT and GHDL for cosimulation".
On the one hand, I'm so glad to feel the excitement in your words! On the other hand, that's the nature of open source, and very specially of the very small VHDL open source community. It has advantages or disadvantages. Making it easy to new users is definitely not the best asset we have. Let's try to change that (at least slightly)!
Then, go ahead and create as many issues/PRs/MWEs in umarcor/ghdl-cosim as you wish to. Do not be stopped just because you don't know where to put the content now. We can shape it and tidy up later. Just ensure that all the examples include some script that allows to compile/build and execute them (for CI).
There is a trick here: the general approach is to interface with C. This is because... well, C is C. The point is that, because C is C, most languages (either interpreted or compiled) can effectively use objects, libraries, binaries with a C-alike interface. Hence, in the specific case of Python, the approach I have tried is ctypes. In the end, I'm using C but with a different syntax. Actually, this is what VUnit/cosim, VUnit#568 and VUnit#603 are about. https://github.com/VUnit/cosim/blob/master/examples/buffer/corun.py#L63-L90 is an example of how to:
Relevant notes:
Indeed... 😆
eine/hwd-ide:examples@ I believe Yann was one of the first users of VHPIDIRECT who wrote about it and released code examples. All of us came after him. Unfortunately, I could not find any copy of the french linux related magazine where I think the articles were published.
I created umarcor/ghdl-cosim as a fork of ghdl/ghdl-systemc-fosdem16 instead of ghdl/ghdl, because I think it is better for us to focus on cosimulation through VHPIDIRECT (which is what we've been mostly talking about). However, I'm ok with moving the discussion to your fork, should you feel more comfortable there.
This is mostly what @bradleyharden and me have been working on. Hence, I think it is ok if you focus on other types which you are interested on but which are not included in this PR yet.
It's absolutely ok. The purpose of this PR was to discuss about it. I did expect it to be hijacked and the actual work to be moved elsewhere. Actually, work is already been done in several places, and this was/is an attempt to put a common resource for all of us. |
Now that I have been thinking about it, ghdlFromArray() mallocs void pointers for both the array (in my updates under umarcor#1 at least) and the bounds (always did for the bounds). Do these pointers get free()'d by the ghdl simulator when the top entity completes? A valgrind run shows that C malloc'd pointers (generally occurs when constructing a fat pointer) do not get cleared. This makes sense, as it is the custom c programs right to malloc, but responsibility to free. 👍 |
Yes, I think you are correct. The one (VHDL or C) that allocates something does need to free it. Anyway, I'm pinging @tgingold and @bradleyharden here, because they have discussed it before: December 21, 2019 8:16 AM. I'm closing this PR. Now that ghdl/ghdl-cosim exists, further work is to be done in ghdl/ghdl-cosim#3. Fare well 1059... |
Ref #1053
This is work in progress to provide an example/demo of how to use VHPIDIRECT features.
Since the ABI is not settled yet, I am unsure about adding
ghdl.h
to the codebase. That's why, in this PR, it is added as an example/demo in the docs.Types included in this demo:
character
/char
,integer
/int32_t
,natural
/uint32_t
,positive
/uint32_t
,real
/double
,boolean
/bool
,bit
/bool
,time
/int64_t
, shortenum
/uint8_t
)line
)As expected, handling unconstrained arrays is neither straightforward nor intuitive. Hence, the main purpose of the demo is to make it easier for new users to use these. The following helper functions are provided:
char* ghdlToString(ghdl_NaturalDimArr_t* ptr)
: convert a fat pointer of an unconstrained string, to a (null terminated) C stringvoid ghdlToArray(ghdl_NaturalDimArr_t* ptr, void** vec, int* len, int num)
: convert a fat pointer of an uncontrained array with (up to 3) dimensions of type 'natural', to C typesghdl_NaturalDimArr_t ghdlFromString(char *string)
: convert a (null terminated) C string, to a fat pointer of an unconstrained stringghdl_NaturalDimArr_t ghdlFromArray(void* vec, int* len, int num)
: convert C types representing an unconstrained array with a dimension of type 'natural', to a fat pointer (not complete yetchar* ghdlAccToString(ghdl_AccNaturalDimArr_t *line)
: convert an access to an unconstrained string, to a (null terminated) C stringvoid ghdlAccToArray(ghdl_AccNaturalDimArr_t* ptr, void** vec, int* len, int num)
: convert an access to an unconstrained array with a dimension of type 'natural', to C types (not implemented yet)ghdl_AccNaturalDimArr_t* ghdlAccFromArray(uint32_t length, size_t bytes)
: convert C types representing an unconstrained array with a dimension of type 'natural', to an accessghdl_AccNaturalDimArr_t* ghdlAccFromString(char *string)
: convert a (null terminated) C string, to an access to an unconstrained stringCurrently, there is an issue with
getIntVec
, which as a wrapper aroundghdlFromArray
to return an unconstrained array of integers from C to VHDL. Although the array is returned, only 3 out of 5 elements are correct. The last two have unexpected values. See the following log:These lines are printed from C:
and these are printed from VHDL:
@bradleyharden, I merged https://github.com/bradleyharden/vunit/blob/ext_pkg_prototypes/vunit/vhdl/data_types/src/ext_ptr/ghdl_types.c into
ghdl.h
so that we can hopefully shareghdl.h
for different projects. However, I found some mismatches between the prototype of some functions (ghdlToString and ghdlFromString), regarding the usage of values or references. You will find comments in the sources of this PR showing both versions.