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

Various VPI examples #19

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open

Various VPI examples #19

wants to merge 13 commits into from

Conversation

bellaz89
Copy link

@bellaz89 bellaz89 commented Apr 28, 2020

In this PR four VPI usage examples are added.

VPI examples

The directory contains some VPI usage examples:

  1. helloworld: minimal VPI code example that runs a simulation, prints a message and exits.
  2. access: signal read/write example on an adder component using vpi_put_value and vpi_get_value.
  3. list: example on signal hierarchy iteration using vpi_iterateand vpi_scan.
  4. timestep: shows how to run a simulation for an arbitrary number of timesteps.

to run a test, just go in an example directory and execute

sh run.sh

@bellaz89 bellaz89 mentioned this pull request Apr 28, 2020
15 tasks
Copy link
Member

@umarcor umarcor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, I think that 6 examples can be extracted from this content, instead of 4. I would propose the following structure:

  • quickstart
    • hello
    • helloworld
    • access
    • access_hierarchy
    • timestep
  • list

Please, add these additional examples/tests to CI. To do so, edit .github/workflows/test.yml and add new items to the task lists in lines 19 and 66.

See further comments below.

.gitignore Outdated Show resolved Hide resolved
@@ -1,4 +1,5 @@
Examples
########

TBC
See :cosimtree:`VPI examples <vpi>` directory
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As commented in #1, TBC at the end of doc/index.rst should be replaced with one or a few notes/tips/hints about minimum knowledge to use VPI. Optionally, that content might be written in doc/vpi/index.rst and included in the toctree.

Anyway, this file should contain a toctree (as done in doc/vhpidirect/examples/index.rst), so that a nice TOC is shown in the sidebar.

Copy link
Author

@bellaz89 bellaz89 Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that proper documentation in RST format is necessary. For now, what I can do, is to add a list of examples in rst format. The rest will come later :P

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote a couple of paragraphs in #1 (comment), which you can copy and paste at the end of doc/index.rst.

The examples cannot be a list. There are two options:

As long as all the files (one or multiple) are added to the toctree, the TOC in the sidebar will have the same structure regardless of the number of files.

Copy link
Author

@bellaz89 bellaz89 Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see the changes I did yesterday......

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is really annoying when GitHub shows a subset of changes or an outdated set of changes...

@@ -0,0 +1,14 @@
## VPI examples
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file should be written in RST and located in subdir doc. The motivation to use RST is that we might want to add labels for cross-referencing these examples. The location is because we are keeping docs separate from code sources.

Moreover, each example should have a header of the appropriate level. This is necessary for the TOC.

In VHPIDIRECT, examples are grouped (Quick start, Arrays, Other projects...). You might want to add all your examples to a section named "Quick Start", to use/create some other section, or to not create any section yet.

Copy link
Author

@bellaz89 bellaz89 Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am ok with this. However, I just did a similar thing as in ./systemc/README.md . If you think it is unnecessary I will remove that, but having a small overview of the folder is helpful for people that just want to explore the repo without directly using the documentation. See https://github.com/bellaz89/ghdl-cosim/tree/master/vpi

Copy link
Member

@umarcor umarcor Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, the existence of ./systemc/README.md is a kind of "artifact". Repo https://github.com/ghdl/ghdl-systemc-fosdem15 was created some weeks ago, due to a user's demand. The name was not correct, and it was renamed to https://github.com/ghdl/ghdl-systemc-fosdem16 a few days later. Then, we discussed about widening the scope to "co-simulation", and this repo was forked from there. We considered to rename the other once again, but we thought it would be too much trouble. Nonetheless, the content of the "old" repo was moved to subdir ./systemc and the README remains. The plan is to add it to the docs (as other examples), once we guess how to make it fit.

If you think it is unnecessary I will remove that, but having a small overview of the folder is helpful for people that just want to explore the repo without directly using the documentation.

Honestly, I had not thought about it, but it sounds as a good idea! From this point of view:

  • The docs need not to link this file, but headers should link to the corresponding subdirs.
  • This file should contain one or multiple links to the docs, where these very brief descriptions are extended.
  • Do we want a single vpi/README.md? Two (vpi/quickstart/README.md and vpi/list/README.md)? Or all of them?

vpi/README.md Outdated

The directory contains some VPI usage examples:

1. [helloworld](./helloworld/) minimal VPI code example that runs a simulation, prints a message and exits.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explanations need to be a little more verbose. As a rule of thumb, the first paragraph in each example explains why the example is relevant (why we decided to add it). Second and further paragraphs explain what is implemented in the example and which files/functions/features are used.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above: this is repository documentation. The full documentation in rst format will come with successive PRs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3. [list](./list/) example on signal hierarchy iteration using `vpi_iterate`and `vpi_scan`.
4. [timestep](./timestep/) shows how to run a simulation for an arbitrary number of timesteps.

to run a test, just go in the directory and execute
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment applies to all the examples in this repo. It would better fit either as an admonition in the main page, or in the README.

It can be a separate PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should go in the main README, along with an explanation about "groups of examples" (see #19 (comment)).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now included in #21.

vpi/access/vpi.c Outdated

val.format = vpiBinStrVal;
val.value.str = "0101";
printf("set %s in tb.nibble1 \n", val.value.str);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that there are two main differences between the vpi.c sources of helloworld and access:

  • In access the values of some signals are written/read.
  • In access the signals are not in the top-level entity, but in an instance.

Hence, I think that two access examples should exist. Each showing one of the new features. Of course, both can share sources. It seems that #define hdl_prefix tb. can be added and overwritten when calling GHDL/GCC.

Copy link
Author

@bellaz89 bellaz89 Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am ok in splitting the tests, or if you prefer, I can just make a simple tb.vhd that do not use ent.vhd to just demonstrate how to read/write signals. Or are you referring to the top module ports??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #19 (comment).

Or are you referring to the top module ports??

I mean that the same C source can be used to first inspect ent directly (no testbench, no hierarchy) and then inspect tb/ent (with testbench, with hierarchy).

  • In the first case, ent.vhd and vpi_access.c are required, and -Dhdl_prefix="ent".
  • For the second case, ent.vhd, tb.vhd and vpi_access.c are required, and -Dhdl_prefix="tb.ent".

The purpose of this pair of examples is to show that the access logic is the same, regardless of using hierarchical names or not.

@@ -0,0 +1,20 @@
#!/usr/bin/env sh
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about duplicated files above.

@@ -0,0 +1,39 @@
library ieee;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment about duplicated files above.

@@ -0,0 +1,71 @@
#include <vpi_user.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that all VHDL sources are the same for all the examples. Do you think that it can be a common pattern for all VPI examples? Or do you expect other features to require different VHDL sources?

I ask it because it seems that the 4-7 examples that are part of this PR differ on the vpi.c file and the compilation commands only.

Copy link
Author

@bellaz89 bellaz89 Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is that to demonstrate very basic usage of VPI, the VHDL component under test do not matter so much. So, for helloworld I can, for example, just put a complete void top module without any signals, because at the end the VPI code is interacting with the simulator but not with the simulation. If you think it is better, I can try to make the ent.vhd and tb.vhd even more concise in each test.

Copy link
Member

@umarcor umarcor Apr 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This. In VHPIDIRECT examples, many C sources are common but VHDL sources need to be different. Here, as you said, VHDL sources are almost irrelevant (as long as they contain the minimum features that we want to test). Hence, instead of making ent.vhd and tb.vhd more concise in each test, I would suggest to make them general enough so that they can used in any VPI example (last structure in #19 (comment)). If some example in the future requires some weird feature in VHDL, we will consider adding different VHDL sources to the corresponding subdir. But, for now, it seems unnecessary.

vpi/list/vpi.c Outdated Show resolved Hide resolved
@bellaz89
Copy link
Author

bellaz89 commented Apr 30, 2020

@umarcor
Thank you for the feedback! I am waiting for your response :)

In the meanwhile, I tried to implement a part of your suggestions.

@umarcor
Copy link
Member

umarcor commented Apr 30, 2020

I don't understand why I cannot reply to some of the previous (outdated) comments, but I can reply to some other. Hence, I think that the review and this comment might be a little messy. Hope we can understand each other...

So, do you suggest to put every common vhd file in the same directory?

The structure that we are following is that each new file that is added to the repo, is required for a reason. If two examples use a source which is almost the same except for a line or a few lines, we consider whether it can be shared by adding some parameter. Should doing so involve too much complexity, it is ok to duplicate very similar files.

Even if some examples contain similar or same code, I would not recommend moving them out of the particular example folder to limit the necessity to look around to the minimum (and IMHO it is very important in a documentation project).

Also, in this way the user loses the ability to compile/run a single test, so I discourage this solution. For code examples IMHO it is more important self-containment rather than code reuse.

We need to balance complexity and verbosity. On the one hand, we want intermediate and advanced users to pick any isolated example and run/use it directly. On the other hand, we want unexperienced users which are reading the docs in order (as a tutorial), not to be continuously diffing many files that look similar and which might or might not be the same.

We are currently handling this as subsections (groups of examples). So, in this PR the "atomic unit" is vpi/quickstart. The script that is guaranteed to work alone is vpi/quickstart/run.sh. Then, vpi/quickstart/access/run.sh might exist, and it might be completely independent, but this is not guaranteed. In some cases, you need to call the parent script first. In other cases, the parent script does execute the child explicitly.

PLI_INT32 reason,
int64_t cycles){

s_cb_data cbData;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this deserves a reference/cite, either here or in the docs. Where should users search for the definition of s_cb_data? In vpi_user.h? The standard? Some book?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now explained in #21.


begin

ent_0: entity work.ent
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels not to be valid VHDL. Is it on purpose?

Anyway, correct or purposely incorrect, I'd suggest to use a for generate instead:

    i_ent: for I in 0 to 3 generate
      w_ent: entity work.ent 
      port map (nibble1 => nibble1,
                nibble2 => nibble2,
                sum => sum,
                carry_out => carry_out);
   end generate;

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script is running, the CI completes without any error, and GHDL doesn't pop out even a Warning. Therefore I think it is valid VHDL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprising... I would expect sum and carry_out to collide, since four different drivers are connected to the same signal. I simulated it and, when one of the instances drives a different value, sum and/or carry_out are X. @tgingold, should this produce a warning?

Anyway, I think we should build a proper adder chain to sum two 4*4=16bit numbers.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, now I see that you were talking about a multiple-driving issue. I agree that it is strange that GHDL doesn't catch it and I will fix that. Please could you be a bit more descriptive and giving the code lines where the problem is next time?

Copy link
Member

@umarcor umarcor May 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please could you be a bit more descriptive and giving the code lines where the problem is next time?

Sure! Sorry about it. I was convinced that you had done it on purpose, because you only wanted to explore the hierarchy without caring about the content.

I will take care of fixing this source if you want; so you can focus on VPI-specific issues which I'm less comfortable with.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Equivalent source included in #21.

cbData.user_data = 0;
cbData.value = 0;

// the callback is executed after a delay of 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my ignorance, it seems that these lines (35-37) are optional. That is, the first example would also work with cbData.time = NULL (as per the common header above). However, I'm afraid that cbData.time = NULL and cbData.reason = cbAfterDelay might produce either a crash or weird behaviour.

Hence, I think that we should have three "hello" examples:

  • begin/hello: same as begin_end but without common_vpi.h, or same as helloworld but without simuTime.
  • helloworld
  • begin_end

Anyway, we can move forward and I will take care of adding begin/hello after this PR is merged.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Example hello is now included in #21.

* VPI. This is accomplished registering a chain of callbacks.
*/

// register a cbAfterDelay callback that executes delay_ro_cb after 1 timestep
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that some discussion/explanation is required about why four different callbacks are used. Why do we need to register cbReadOnlySynch if cbReadWriteSynch is going to be executed in the same chain anyway?

@bellaz89
Copy link
Author

bellaz89 commented May 1, 2020

Hi,

I think that I won't work anymore on this PR. Either because I don't believe that, given the scope of the PR, implementing more changes will lead to any quality improvement, and (more important) because I don't have more time to spend on this. So, take it as it is and do what you want with the PR. You can merge it and do the changes you prefer later, you can reject it or you can make it as a pending PR indefinitely. I am fine with whatever decision you will take.

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

Successfully merging this pull request may close these issues.

5 participants