Skip to content

Commit

Permalink
Merge branch 'master' into logicVectors
Browse files Browse the repository at this point in the history
  • Loading branch information
radonnachie committed Apr 19, 2020
2 parents 54746cc + e9040a9 commit 7ddd6fa
Show file tree
Hide file tree
Showing 11 changed files with 353 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
vhpidirect/quickstart/math,
vhpidirect/quickstart/customc,
vhpidirect/quickstart/package,
vhpidirect/quickstart/sharedvar,
vhpidirect/wrapping/basic,
vhpidirect/wrapping/time,
vhpidirect/linking/bind,
Expand Down Expand Up @@ -48,6 +49,7 @@ jobs:
vhpidirect/quickstart/math,
vhpidirect/quickstart/customc,
vhpidirect/quickstart/package,
vhpidirect/quickstart/sharedvar,
vhpidirect/wrapping/basic,
vhpidirect/wrapping/time,
#vhpidirect/linking/bind, ! needs investigation, output of list-link seems to have wrong path format
Expand Down
31 changes: 30 additions & 1 deletion doc/vhpidirect/examples/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,33 @@ Since either C sources or pre-compiled ``.o`` objects can be added, in C/C++ pro

If the auxillary VHPIDIRECT subprograms need to be accessed in more than one entity, it is possible to package the subprograms. This also makes it very easy to reuse the VHPIDIRECT declarations in different projects.

In this example 2 different entities use a C defined ``c_printInt(val: integer)`` subprogram to print two different numbers. Subprogram declaration requirements are detailed under the :ref:`COSIM:VHPIDIRECT:Declarations` section.
In this example two different entities use a C defined ``c_printInt(val: integer)`` subprogram to print two different numbers. Subprogram declaration requirements are detailed under the :ref:`COSIM:VHPIDIRECT:Declarations` section.

.. _COSIM:VHPIDIRECT:Examples:quickstart:sharedvar:

:cosimtree:`sharedvar <vhpidirect/quickstart/sharedvar>`
********************************************************

While sharing variables through packages in VHDL 1993 is flexible, in VHDL 2008 protected types need to be used.
However, GHDL allows to relax some rules of the LRM through :option:`-frelaxed`.

This example shows multiple alternatives to share variables through packages, depending on the target version of the standard.
Three different binaries are built from the same entity, using:

* A VHDL 1993 package with ``--std=93``.

* A VHDL 1993 package with ``--std=08 -frelaxed``.

* A VHDL 2008 package with ``--std=08``.

.. NOTE::
Procedure ``setVar`` is not strictly required. It is used to allow the same descriptions of the entity/architectures
to work with both VHDL 1993 and VHDL 2008. See the bodies of the procedure in :cosimtree:`pkg_93.vhd <vhpidirect/quickstart/sharedvar/pkg_93.vhd>` and :cosimtree:`pkg_08.vhd <vhpidirect/quickstart/sharedvar/pkg_08.vhd>`.

As an alternative to using a shared variable in VHDL, subdir :cosimtree:`shint <vhpidirect/quickstart/sharedvar/shint>`
contains an approach based on a helper record type which is used as a handle. Mimicking the concept of *methods* from
Object Oriented (OO) programming, helper C functions are used to read/write the actual variables, instead of sharing
data through an access/pointer. This approach is more verbose than others, but it works with either VHDL 1993 or VHDL
2008 without modification and without requiring :option:`-frelaxed`. Moreover, it enhances encapsulation, as it provides
a user-defined API between VHDL and C, which can improve maintainability when sources are reused. As a matter of fact,
this approach is found in verification projects such as `VUnit <http://vunit.github.io/>`_ and `OSVVM <https://osvvm.org/>`_.
28 changes: 28 additions & 0 deletions vhpidirect/quickstart/sharedvar/ent.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use work.pkg.all;

entity ent is
end ent;

architecture rtl_A of ent is
begin
process
begin
report "Entity1: c_Var is " & integer'image(getVar);
report "Entity1: setting c_Var to 1." severity note;
setVar(1);
c_printVar;
wait;
end process;
end rtl_A ;

architecture rtl_B of ent is
begin
process
begin
report "Entity2: c_Var is " & integer'image(getVar);
report "Entity2: setting c_Var to 2." severity note;
setVar(2);
c_printVar;
wait;
end process;
end rtl_B;
11 changes: 11 additions & 0 deletions vhpidirect/quickstart/sharedvar/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include<stdio.h>

int var;

int* getInt_ptr(){
return &var;
}

void printInt(){
printf("C-side print of int: %d\n", var);
}
50 changes: 50 additions & 0 deletions vhpidirect/quickstart/sharedvar/pkg_08.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package pkg is
type int_ptr is access integer;

impure function c_Int_ptr return int_ptr;
attribute foreign of c_Int_ptr : function is "VHPIDIRECT getInt_ptr";

procedure c_printVar;
attribute foreign of c_printVar : procedure is "VHPIDIRECT printInt";

type int_ptr_prot is protected
procedure set ( i: integer);
impure function get return integer;
end protected int_ptr_prot;

shared variable c_Var: int_ptr_prot;

procedure setVar ( int: integer );

impure function getVar return integer;

end pkg;

package body pkg is
impure function c_Int_ptr return int_ptr is begin
assert false report "VHPI" severity failure;
end;

procedure c_printVar is
begin
assert false report "c_printVar VHPI" severity failure;
end;

procedure setVar ( int: integer ) is begin
c_Var.set(int);
end;

impure function getVar return integer is begin
return c_Var.get;
end;

type int_ptr_prot is protected body
variable var: int_ptr := c_Int_ptr;
procedure set ( i: integer) is begin
var.all := i;
end procedure;
impure function get return integer is begin
return var.all;
end get;
end protected body int_ptr_prot;
end pkg;
36 changes: 36 additions & 0 deletions vhpidirect/quickstart/sharedvar/pkg_93.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package pkg is
type int_ptr is access integer;

function c_Int_ptr return int_ptr;
attribute foreign of c_Int_ptr : function is "VHPIDIRECT getInt_ptr";

procedure c_printVar;
attribute foreign of c_printVar : procedure is "VHPIDIRECT printInt";

shared variable c_Var : int_ptr := c_Int_ptr;

procedure setVar ( int: integer );

impure function getVar return integer;

end package pkg;

package body pkg is
function c_Int_ptr return int_ptr is
begin
assert false report "c_Int_ptr VHPI" severity failure;
end;

procedure c_printVar is
begin
assert false report "c_printVar VHPI" severity failure;
end;

procedure setVar ( int: integer ) is begin
c_Var.all := int;
end;

impure function getVar return integer is begin
return c_Var.all;
end;
end package body pkg;
74 changes: 74 additions & 0 deletions vhpidirect/quickstart/sharedvar/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env sh

set -e

cd $(dirname "$0")


echo "VHDL 93: Analyze pkg_93.vhd ent.vhd tb.vhd"
ghdl -a --std=93 pkg_93.vhd ent.vhd tb.vhd

echo "Build tb_93 with main.c"
ghdl -e --std=93 -Wl,main.c -o tb_93 tb

echo "Execute tb_93"
./tb_93

echo "Clean tb_93"
rm work-obj*.cf tb_93 *.o
echo ""


echo "VHDL 08 -frelaxed: Analyze pkg_93.vhd ent.vhd tb.vhd"
ghdl -a --std=08 -frelaxed pkg_93.vhd ent.vhd tb.vhd

echo "Build tb_08relaxed with main.c"
ghdl -e --std=08 -frelaxed -Wl,main.c -o tb_08relaxed tb

echo "Execute tb_08relaxed"
./tb_08relaxed

echo "Clean tb_08relaxed"
rm work-obj*.cf tb_08relaxed *.o
echo ""


echo "VHDL 08: Analyze pkg_08.vhd ent.vhd tb.vhd"
ghdl -a --std=08 pkg_08.vhd ent.vhd tb.vhd

echo "Build tb_08 with main.c"
ghdl -e --std=08 -Wl,main.c -o tb_08 tb

echo "Execute tb_08"
./tb_08

echo "Clean tb_08"
rm work-obj*.cf tb_08 *.o
echo ""


echo "VHDL 93: Analyze shint/pkg.vhd shint/ent.vhd tb.vhd"
ghdl -a shint/pkg.vhd shint/ent.vhd tb.vhd

echo "Build tb_93shint with main.c"
ghdl -e -Wl,shint/main.c -o tb_93shint tb

echo "Execute tb_93shint"
./tb_93shint

echo "Clean tb_93shint"
rm work-obj*.cf tb_93shint *.o
echo ""


echo "VHDL 08: Analyze shint/pkg.vhd shint/ent.vhd tb.vhd"
ghdl -a --std=08 shint/pkg.vhd shint/ent.vhd tb.vhd

echo "Build tb_08shint with main.c"
ghdl -e --std=08 -Wl,shint/main.c -o tb_08shint tb

echo "Execute tb_08shint"
./tb_08shint

echo "Clean tb_08shint"
rm work-obj*.cf tb_08shint *.o
30 changes: 30 additions & 0 deletions vhpidirect/quickstart/sharedvar/shint/ent.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use work.pkg.all;

entity ent is
end ent;

architecture rtl_A of ent is
begin
process
constant c_var: shint_t := new_shint(0);
begin
report "Entity1: c_Var is " & integer'image(read(c_var));
report "Entity1: setting c_Var to 1." severity note;
write(c_var, 1);
print(c_var);
wait;
end process;
end rtl_A ;

architecture rtl_B of ent is
begin
process
constant c_var: shint_t := new_shint(0);
begin
report "Entity2: c_Var is " & integer'image(read(c_var));
report "Entity2: setting c_Var to 2." severity note;
write(c_var, 2);
print(c_var);
wait;
end process;
end rtl_B;
18 changes: 18 additions & 0 deletions vhpidirect/quickstart/sharedvar/shint/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <stdio.h>
#include <stdint.h>

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

int32_t V[10];

void write_int ( uint8_t id, int32_t v ) {
V[id] = v;
}

int32_t read_int ( uint8_t id ) {
return V[id];
}

void print_int ( uint8_t id ) {
printf("C-side print of int: %d\n", V[id]);;
}
58 changes: 58 additions & 0 deletions vhpidirect/quickstart/sharedvar/shint/pkg.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package pkg is

procedure write_int ( id: integer; v: integer ) ;
attribute foreign of write_int : procedure is "VHPIDIRECT write_int";

impure function read_int ( id: integer ) return integer;
attribute foreign of read_int : function is "VHPIDIRECT read_int";

procedure print_int ( id: integer );
attribute foreign of print_int : procedure is "VHPIDIRECT print_int";

type shint_t is record
-- Private
p_id: integer;
end record;

impure function new_shint(id: integer := -1) return shint_t;
procedure write ( shint: shint_t; v: integer );
impure function read ( shint: shint_t ) return integer;
procedure print ( shint: shint_t );

end pkg;

package body pkg is

-- VHPIDIRECT

procedure write_int ( id: integer; v: integer ) is begin
assert false report "VHPIDIRECT write_int" severity failure;
end;

impure function read_int ( id: integer ) return integer is begin
assert false report "VHPIDIRECT read_int" severity failure;
end;

procedure print_int ( id: integer ) is begin
assert false report "VHPIDIRECT print_int" severity failure;
end;

-- VHDL

impure function new_shint ( id: integer := -1 ) return shint_t is begin
return (p_id => id);
end;

procedure write ( shint: shint_t; v: integer ) is begin
write_int(shint.p_id, v);
end;

impure function read ( shint: shint_t ) return integer is begin
return read_int(shint.p_id);
end function;

procedure print ( shint: shint_t ) is begin
print_int(shint.p_id);
end;

end pkg;
16 changes: 16 additions & 0 deletions vhpidirect/quickstart/sharedvar/tb.vhd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
entity tb is
end tb;

architecture arch of tb is
begin

entA : entity work.ent(rtl_A);
entB : entity work.ent(rtl_B);

process
begin
report "Testbench." severity note;
wait;
end process;

end;

0 comments on commit 7ddd6fa

Please sign in to comment.