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

Add packageless intvector examples (#5 a + c) #11

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ jobs:
vhpidirect/quickstart/wrapping/time,
vhpidirect/quickstart/linking/bind,
vhpidirect/quickstart/package,
vhpidirect/arrays/intvectorgeneric,
Copy link
Owner

Choose a reason for hiding this comment

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

I think this was mislocated as a result of merging/cherry-picking.

vhpidirect/quickstart/sharedvar,
vhpidirect/shared/shlib,
vhpidirect/shared/dlopen,
vhpidirect/shared/shghdl,
vhpidirect/arrays/intvector,
vhpidirect/arrays/intvector/maindefined,
vhpidirect/arrays/logicvector,
vhpidirect/arrays/matrices,
vhpidirect/arrays/matrices/framebuffer,
Expand Down Expand Up @@ -73,11 +75,13 @@ jobs:
vhpidirect/quickstart/wrapping/time,
#vhpidirect/quickstart/linking/bind, ! needs investigation, output of list-link seems to have wrong path format
vhpidirect/quickstart/package,
vhpidirect/arrays/intvectorgeneric,
vhpidirect/quickstart/sharedvar,
vhpidirect/shared/shlib,
#vhpidirect/shared/dlopen, ! dlfcn.h is not available on win
#vhpidirect/shared/shghdl, ! dlfcn.h is not available on win
#vhpidirect/shared/dlopen, ! dlfcn.h is not available on win
#vhpidirect/shared/shghdl, ! dlfcn.h is not available on win
vhpidirect/arrays/intvector,
vhpidirect/arrays/intvector/maindefined,
vhpidirect/arrays/logicvector,
vhpidirect/arrays/matrices,
#vhpidirect/arrays/matrices/framebuffer, ! needs ImageMagick's 'convert'
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ ent*
tb*
!*.vhd
!*.vhdl
doc/_build/*
.vunit_hash
vhpidirect/arrays/matrices/vunit_axis_vcs/vunit_out/*
20 changes: 20 additions & 0 deletions doc/vhpidirect/examples/arrays.rst
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ executing the simulation.
There is no explicit example about how to have the size defined in C, but have the allocation/deallocation performed
in VHDL. However, implementing such a solution is a matter of combining these examples with the VHDL-sized ones below.


.. _COSIM:VHPIDIRECT:Examples:arrays:intvector:maindefined:

:cosimtree:`Sized in C: First defined in main() <vhpidirect/arrays/intvector/maindefined>`
==========================================================================================================

If the integer array must be created or filled by some more advanced process before VHDL can request the array's pointer, it is
possible to execute the GHDL simulation within a custom ``int main()`` entrypoint (see :ref:`COSIM:VHPIDIRECT:Examples:wrapping:basic`).
In this example the custom entrypoint prompts the user for the size of the array and then handles the variables appropriately before
going on to execute the GHDL simulation.

:cosimtree:`Sized in VHDL <vhpidirect/arrays/intvectorgeneric>`
===============================================================================

Interface generics are the generics of the toplevel VHDL entity, and their values can be set via GHDL's runtime option :option:`-g` (see :ref:`simulation_options`). In this example an interface generic is used as an argument for the call of the VHPIDIRECT subprogram ``c_intArr_ptr(arraySize: integer)``. This subprogram is linked to the foreign C function ``getIntArr_ptr(int arraySize)`` which uses the argument to allocate an ``int*`` enough space to contain ``arraySize`` integers, populating each index thereafter. The subprogram returns the array's pointer and each index is printed out in VHDL.

.. NOTE::
The C function is actually extended to handle a second call. If the ``int*`` has been used before its memory is freed, and if the new arraySize is greater than 0, the pointer is allocated enough memory again. In this way, a VHDL subprogram call of ``c_intArr_ptr(0);`` frees the previously allocated memory.


.. _COSIM:VHPIDIRECT:Examples:arrays:intvector:vhdlsized:

:cosimtree:`Sized in VHDL <vhpidirect/arrays/intvector/vhdlsized>`
Expand Down
11 changes: 11 additions & 0 deletions vhpidirect/arrays/intvector/caux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#define SIZE_ARRAY (sizeof(intArray)/sizeof(int))

int intArray[] = {11, 22, 33, 44, 55, 66};

int getIntArrSize(){
return SIZE_ARRAY;
}

int* getIntArr_ptr(){
return intArray;
}
9 changes: 9 additions & 0 deletions vhpidirect/arrays/intvector/maindefined/caux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "caux.h"
Copy link
Owner

Choose a reason for hiding this comment

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

Isn't this somehow redundant to caux.c in the parent dir? Sure, here the size is saved in a variable, instead of using a define. However, initializing int arraySize = (sizeof(intArray)/sizeof(int)); should work for both cases. The same applies to intArray. Nothing prevents the subexample from overwriting the pointer. The hardcoded content would be useless, but I think it pays off because we want to show that users can use main optionally and without modification of helper C functions.

Copy link
Author

Choose a reason for hiding this comment

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

sizeof(intArray) in the subexamples returns sizeof(int*), not sizeof(int[])... In order make it more closely match the original example I can make this array statically defined. then we start to lose out on the extensive main() entry point passing examples to ghdl for various reasons.

I think that may be for the better though. Let's simplify this to exactly the same as the intvector example, just with the values being printed out in main before the ghdl_main() call.

An we can make the extensive examples of the cosimulation in a different PR??

Copy link
Owner

Choose a reason for hiding this comment

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

then we start to lose out on the extensive main() entry point passing examples to ghdl for various reasons.

I don't understand this sentence. Can you please reword it?

Copy link
Author

Choose a reason for hiding this comment

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

Sure. I want to be extra clear so that you can tell me if I have any misunderstandings on the examples you want.

The sub example (maindefined) is to show how to use a custom entry point (main.c) to preprocess the VHPIDIRECT shared int[] (in caux.c).
I think I made the subexample a little more complicated than it needs to be by asking for user input to defined the size of the int[].

  • This meant that the variable had to be a malloc'd int*
  • It also then strayed away from the parent example (intvector)
  • It also is a little too much too soon because it starts begging the questions of all the ways to pass arguments to main() and even arguments to ghdl_main() through main(). **

I am proposing that we cut all of the discussion out by making the sub example much more similar to the parent example (exactly the same, except a main.c that wraps ghdl_main. main() does nothing, at most prints out "ghdl simulation\n*****************".)

We then 'lose out' on the 3 points above, but I think that they start to get extensive enough that a whole section could be written on them (at least have their own examples in a different section). Those examples can be linked to in this one's documentation....

Copy link
Author

Choose a reason for hiding this comment

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

I see your point. Let's keep this example as is, just splitting allocation and initialization. Then, we can add a shintvectors as done with shint.

I think that I am agreeing with your earlier response.

Copy link
Owner

Choose a reason for hiding this comment

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

I think that I am agreeing with your earlier response.

Can you open a new PR with the status of this one when I did that comment? I believe that we can have that merged almost as is. We just want two subcases: set the size in C or set the size in VHDL. In both cases, the allocation is done in C. In the first one, it's hardcoded. In the second one, malloc is called once only, and a second helper function is used to fill it in C.

Then, we will have a better perspective about what to add here. I created #14, so this can be about the auto-reallocation logic that you have.

Copy link
Owner

@umarcor umarcor Apr 19, 2020

Choose a reason for hiding this comment

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

Bear this in mind. The question we want to answer is "How do I allocate in C and share a pointer/access while defining the size in one language only?". We need to provide two cases: hardcode the size in C (and pass it to VHDL) and harcode the size in VHDL (and pass it to C).


int getIntArrSize(){
return arraySize;
}

int* getIntArr_ptr(){
return intArray;
}
5 changes: 5 additions & 0 deletions vhpidirect/arrays/intvector/maindefined/caux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int arraySize;
int* intArray;

int getIntArrSize();
int* getIntArr_ptr();
26 changes: 26 additions & 0 deletions vhpidirect/arrays/intvector/maindefined/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <stdio.h>
#include <malloc.h>

#include "caux.h"

extern int ghdl_main(char argc, char* argv[]);

int main(char argc, char* argv[]){
char strIn[3];

printf("Enter the length of the integer array [1-99]: ");
fgets(strIn, 3, stdin);
printf("\n");
sscanf(strIn, "%d", &arraySize);

intArray = malloc(arraySize*sizeof(int));
for(int i = 0; i < arraySize; i++){
intArray[i] = 11*(i+1);
}

printf("GHDL Simulation Begin\n*****************************************\n");
int ghdlReturn = ghdl_main(argc, argv);
printf("*****************************************\nGHDL Simulation End\n");

free(intArray);
}
17 changes: 17 additions & 0 deletions vhpidirect/arrays/intvector/maindefined/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env sh

set -e

cd $(dirname "$0")

echo "Build main.o (with caux.h) [GCC]"
gcc -c main.c

echo "Analyze tb.vhd [GHDL]"
ghdl -a tb.vhd

echo "Build tb (with caux.c) [GHDL]"
ghdl -e -Wl,main.o -Wl,caux.c tb

echo "Execute tb"
./tb
36 changes: 36 additions & 0 deletions vhpidirect/arrays/intvector/maindefined/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
entity tb is
end entity tb;

architecture RTL of tb is

begin

process
function c_intArrSize return integer is-- represented C-side with int
begin
assert false report "c_intArrSize VHPI" severity failure;
end;
attribute foreign of c_intArrSize : function is "VHPIDIRECT getIntArrSize"; -- getIntArrSize is the C-side function name

type int_arr is array(0 to c_intArrSize-1) of integer;
type int_arr_ptr is access int_arr; -- represented C-side with int*

function c_intArr_ptr return int_arr_ptr is
begin
assert false report "c_intArr_ptr VHPI" severity failure;
end;
attribute foreign of c_intArr_ptr : function is "VHPIDIRECT getIntArr_ptr";

variable c_intArr : int_arr_ptr := c_intArr_ptr;

begin
report "Array length: " & integer'image(c_intArr.all'length);

for i in 0 to c_intArr.all'right loop
report "c_intArr[" & integer'image(i) &"] = " & integer'image(c_intArr.all(i));
end loop;

wait;
end process;

end architecture RTL;
Empty file modified vhpidirect/arrays/intvector/run.sh
100755 → 100644
Empty file.
37 changes: 37 additions & 0 deletions vhpidirect/arrays/intvector/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
entity tb is
end entity tb;

architecture RTL of tb is

begin

process
function c_intArrSize return integer is-- represented C-side with int
begin
assert false report "c_intArrSize VHPI" severity failure;
end;
attribute foreign of c_intArrSize : function is "VHPIDIRECT getIntArrSize"; -- getIntArrSize is the C-side function name

type int_arr is array(0 to c_intArrSize-1) of integer;
type int_arr_ptr is access int_arr; -- represented C-side with int*

function c_intArr_ptr return int_arr_ptr is
begin
assert false report "c_intArr_ptr VHPI" severity failure;
end;
attribute foreign of c_intArr_ptr : function is "VHPIDIRECT getIntArr_ptr";

variable c_intArr : int_arr_ptr := c_intArr_ptr;

begin
report "Array length: " & integer'image(c_intArr.all'length);

for i in 0 to c_intArr.all'right loop
report "c_intArr[" & integer'image(i) &"] = " & integer'image(c_intArr.all(i)) & ". Set to: " & integer'image(-2*c_intArr.all(i));
c_intArr.all(i) := -2*c_intArr.all(i);
end loop;

wait;
end process;

end architecture RTL;
17 changes: 17 additions & 0 deletions vhpidirect/arrays/intvectorgeneric/caux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <malloc.h>
#include <stddef.h>

int* intArray;
int* getIntArr_ptr(int arraySize){//function acts like a constructor so initialise the variable
if(intArray != NULL){
free(intArray);
}
if(arraySize > 0){
intArray = malloc(arraySize*sizeof(int));
for (int i = 0; i < arraySize; i++)
{
intArray[i] = 11*(i+1);
}
}
return intArray;
}
17 changes: 17 additions & 0 deletions vhpidirect/arrays/intvectorgeneric/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env sh

set -e

cd $(dirname "$0")

echo "Analyze tb.vhd"
ghdl -a tb.vhd

echo "Build tb (with caux.c) [GHDL]"
ghdl -e -Wl,caux.c tb

echo "Execute tb (-gg_array_size=2)"
./tb -gg_array_size=2

echo "Execute tb (-gg_array_size=6)"
./tb -gg_array_size=6
31 changes: 31 additions & 0 deletions vhpidirect/arrays/intvectorgeneric/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
entity tb is
generic(
g_array_size : integer := 1
);
end entity tb;

architecture RTL of tb is
begin
process
type int_arr is array(0 to g_array_size-1) of integer;
type int_arr_ptr is access int_arr; -- represented C-side with int*

impure function c_intArr_ptr(arraySize: integer) return int_arr_ptr is
begin
assert false report "c_intArr_ptr VHPI" severity failure;
end;
attribute foreign of c_intArr_ptr : function is "VHPIDIRECT getIntArr_ptr";

variable c_intArr : int_arr_ptr := c_intArr_ptr(g_array_size);
begin
report "ArraySize Interface Generic: " & integer'image(g_array_size);

for i in 0 to g_array_size-1 loop
report "c_intArr[" & integer'image(i) & "] = " & integer'image(c_intArr(i));
end loop;

c_intArr := c_intArr_ptr(0);
wait;
end process;

end architecture RTL;