forked from ghdl/ghdl-cosim
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
vhpidirect: add header file and 'demo' (ghdl/ghdl#1059)
- Loading branch information
Showing
7 changed files
with
521 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.. program:: ghdl | ||
.. _COSIM:VHPIDIRECT:Examples:cinterface: | ||
|
||
C interface | ||
########### | ||
|
||
:cosimtree:`demo <vhpidirect/cinterface/demo>` | ||
********************************************** | ||
|
||
This example is a reference and a test suite for the helper C headers provided in :cosimtree:`vhpidirect`. These headers are a reference of GHDL's ABI, and can be imported to easily convert non-trivial data types between C and VHDL. However, the ABI is not settled, so it might change without prior notice. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,7 @@ Examples | |
quickstart | ||
wrapping | ||
linking | ||
demo | ||
shared | ||
cinterface | ||
other |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
#include <stdlib.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <stdbool.h> | ||
#include <assert.h> | ||
#include <string.h> | ||
|
||
#include <ghdl.h> | ||
|
||
typedef struct rec_t { | ||
char r_char; | ||
int32_t r_int; | ||
} rec_t; | ||
|
||
typedef enum {standby, start, busy, done} enum_t; | ||
|
||
void testCinterface( | ||
char v_char, | ||
int32_t v_int, | ||
uint32_t v_nat, | ||
uint32_t v_pos, | ||
double v_real, | ||
bool v_bool, | ||
bool v_bit, | ||
int64_t v_time, | ||
rec_t* v_rec, | ||
uint8_t v_enum, | ||
ghdl_NaturalDimArr_t* v_str, | ||
ghdl_NaturalDimArr_t* v_vec_int, | ||
ghdl_NaturalDimArr_t* v_vec_real, | ||
ghdl_NaturalDimArr_t* v_vec_bool, | ||
ghdl_NaturalDimArr_t* v_vec_bit, | ||
ghdl_NaturalDimArr_t* v_vec_phy, | ||
ghdl_NaturalDimArr_t* v_vec_rec, | ||
ghdl_NaturalDimArr_t* v_vec_enum, | ||
ghdl_NaturalDimArr_t* v_2vec_real | ||
) { | ||
assert(v_char == 'k'); | ||
printf("v_char : %c\n", v_char); | ||
|
||
assert(v_int == -6); | ||
printf("v_int : %d\n", v_int); | ||
|
||
assert(v_nat == 9); | ||
printf("v_nat : %d\n", v_nat); | ||
|
||
assert(v_pos == 3); | ||
printf("v_pos : %d\n", v_pos); | ||
|
||
assert(v_real == 3.34); | ||
printf("v_real : %f\n", v_real); | ||
|
||
assert(v_bool == true); | ||
printf("v_bool : %d\n", v_bool); | ||
|
||
assert(v_bit == true); | ||
printf("v_bit : %d\n", v_bit); | ||
|
||
assert(v_time == 20e6); | ||
printf("v_time : %d\n", v_time); | ||
|
||
assert(v_rec != NULL); | ||
assert(v_rec->r_char == 'y'); | ||
assert(v_rec->r_int == 5); | ||
printf("v_rec : %p %c %d\n", v_rec, v_rec->r_char, v_rec->r_int); | ||
|
||
assert(v_enum == busy); | ||
printf("v_enum : %d %d\n", v_enum, busy); | ||
|
||
char* str = ghdlToString(v_str); | ||
printf("v_str : %p '%s' [%d]\n", v_str->array, str, strlen(str)); | ||
|
||
int* len = malloc(2 * sizeof(int)); | ||
|
||
int32_t* vec_int; | ||
ghdlToArray(v_vec_int, (void**)&vec_int, len, 1); | ||
assert(vec_int[0] == 11); | ||
assert(vec_int[1] == 22); | ||
assert(vec_int[2] == 33); | ||
assert(vec_int[3] == 44); | ||
assert(vec_int[4] == 55); | ||
printf("v_vec_int : %p [%d]\n", vec_int, len[0]); | ||
|
||
double* vec_real; | ||
ghdlToArray(v_vec_real, (void**)&vec_real, len, 1); | ||
assert(vec_real[0] == 0.5); | ||
assert(vec_real[1] == 1.75); | ||
assert(vec_real[2] == 3.33); | ||
assert(vec_real[3] == -0.125); | ||
assert(vec_real[4] == -0.67); | ||
assert(vec_real[5] == -2.21); | ||
printf("v_vec_real : %p [%d]\n", vec_real, len[0]); | ||
|
||
bool* vec_bool; | ||
ghdlToArray(v_vec_bool, (void**)&vec_bool, len, 1); | ||
assert(vec_bool[0] == 0); | ||
assert(vec_bool[1] == 1); | ||
assert(vec_bool[2] == 1); | ||
assert(vec_bool[3] == 0); | ||
printf("v_vec_bool : %p [%d]\n", vec_bool, len[0]); | ||
|
||
bool* vec_bit; | ||
ghdlToArray(v_vec_bit, (void**)&vec_bit, len, 1); | ||
assert(vec_bit[0] == 1); | ||
assert(vec_bit[1] == 0); | ||
assert(vec_bit[2] == 1); | ||
assert(vec_bit[3] == 0); | ||
printf("v_vec_bit : %p [%d]\n", vec_bit, len[0]); | ||
|
||
int64_t* vec_phy; | ||
ghdlToArray(v_vec_phy, (void**)&vec_phy, len, 1); | ||
assert(vec_phy[0] == 1e6); | ||
assert(vec_phy[1] == 50e3); | ||
assert(vec_phy[2] == 1.34e9); | ||
printf("v_vec_phy : %p [%d]\n", vec_phy, len[0]); | ||
|
||
rec_t* vec_rec; | ||
ghdlToArray(v_vec_rec, (void**)&vec_rec, len, 1); | ||
assert(vec_rec[0].r_char == 'x'); | ||
assert(vec_rec[0].r_int == 17); | ||
assert(vec_rec[1].r_char == 'y'); | ||
assert(vec_rec[1].r_int == 25); | ||
printf("v_vec_rec : %p [%d]\n", vec_rec, len[0]); | ||
|
||
uint8_t* vec_enum; | ||
ghdlToArray(v_vec_enum, (void**)&vec_enum, len, 1); | ||
assert(vec_enum[0] == start); | ||
assert(vec_enum[1] == busy); | ||
assert(vec_enum[2] == standby); | ||
printf("v_vec_enum : %p [%d]\n", vec_enum, len[0]); | ||
|
||
double* vec2_real_base; | ||
ghdlToArray(v_2vec_real, (void**)&vec2_real_base, len, 2); | ||
double (*vec2_real)[len[0]] = (double(*)[len[0]])vec2_real_base; | ||
assert(vec2_real[0][0] == 0.1); | ||
assert(vec2_real[0][1] == 0.25); | ||
assert(vec2_real[0][2] == 0.5); | ||
assert(vec2_real[1][0] == 3.33); | ||
assert(vec2_real[1][1] == 4.25); | ||
assert(vec2_real[1][2] == 5.0); | ||
printf("v_2vec_real : %p [%d, %d]\n", vec_enum, len[1], len[0]); | ||
} | ||
|
||
void getString(ghdl_NaturalDimArr_t* ptr) { | ||
*ptr = ghdlFromString("HELLO WORLD"); | ||
} | ||
|
||
void getIntVec(ghdl_NaturalDimArr_t* ptr) { | ||
int32_t vec[6] = {11, 22, 33, 44, 55}; | ||
int32_t len[1] = {5}; | ||
int x; | ||
for ( x=0 ; x<len[0] ; x++ ) { | ||
printf("%d: %d\n", x, vec[x]); | ||
} | ||
*ptr = ghdlFromArray(vec, len, 1); | ||
} | ||
|
||
ghdl_AccNaturalDimArr_t* getLine() { | ||
return ghdlAccFromString("HELLO WORLD"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
#!/usr/bin/env sh | ||
|
||
set -e | ||
|
||
cd $(dirname "$0") | ||
|
||
echo "Analyze tb.vhd" | ||
ghdl -a -O0 -g tb.vhd | ||
|
||
echo "Build tb (with main.c and headers)" | ||
ghdl -e -O0 -g -Wl,-I../../ -Wl,main.c tb | ||
|
||
echo "Execute tb" | ||
./tb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
use std.textio.line; | ||
|
||
entity tb is | ||
end; | ||
|
||
architecture arch of tb is | ||
|
||
type rec_t is record | ||
r_char: character; | ||
r_int : integer; | ||
end record; | ||
|
||
type enum_t is (standby, start, busy, done); | ||
|
||
type int_vec_t is array(natural range <>) of integer; | ||
type real_vec_t is array(natural range <>) of real; | ||
type bool_vec_t is array(natural range <>) of boolean; | ||
type time_vec_t is array(natural range <>) of time; | ||
type rec_vec_t is array(natural range <>) of rec_t; | ||
type enum_vec_t is array(natural range <>) of enum_t; | ||
|
||
type real_2vec_t is array (natural range <>, natural range <>) of real; | ||
|
||
begin | ||
process | ||
|
||
procedure testCinterface( | ||
v_char : character := 'k'; | ||
v_int : integer := -6; | ||
v_nat : natural := 9; | ||
v_pos : positive := 3; | ||
v_real : real := 3.34; | ||
v_bool : boolean := true; | ||
v_bit : bit := '1'; | ||
v_time : time := 20 ns; | ||
v_rec : rec_t := ('y', 5); | ||
v_enum : enum_t := busy; | ||
v_str : string := "hellostr"; | ||
v_vec_int : int_vec_t := (11, 22, 33, 44, 55); | ||
v_vec_real : real_vec_t := (0.5, 1.75, 3.33, -0.125, -0.67, -2.21); | ||
v_vec_bool : bool_vec_t := (false, true, true, false); | ||
v_vec_bit : bit_vector := ('1', '0', '1', '0'); | ||
v_vec_time : time_vec_t := (1 ns, 50 ps, 1.34 us); | ||
v_vec_rec : rec_vec_t := (('x', 17),('y', 25)); | ||
v_vec_enum : enum_vec_t := (start, busy, standby); | ||
v_2vec_real : real_2vec_t := ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0)) | ||
) is | ||
begin assert false report "VHPIDIRECT testCinterface" severity failure; end; | ||
attribute foreign of testCinterface : procedure is "VHPIDIRECT testCinterface"; | ||
|
||
function getString return string is | ||
begin assert false report "VHPIDIRECT getString" severity failure; end; | ||
attribute foreign of getString : function is "VHPIDIRECT getString"; | ||
|
||
function getIntVec return int_vec_t is | ||
begin assert false report "VHPIDIRECT getIntVec" severity failure; end; | ||
attribute foreign of getIntVec : function is "VHPIDIRECT getIntVec"; | ||
|
||
function getLine return line is | ||
begin assert false report "VHPIDIRECT getLine" severity failure; end; | ||
attribute foreign of getLine : function is "VHPIDIRECT getLine"; | ||
|
||
constant g_str: string := getString; | ||
constant g_int_vec: int_vec_t := getIntVec; | ||
|
||
variable g_line: line := getLine; | ||
|
||
begin | ||
|
||
testCinterface( | ||
v_char => 'k', | ||
v_int => -6, | ||
v_nat => 9, | ||
v_pos => 3, | ||
v_real => 3.34, | ||
v_bool => true, | ||
v_bit => '1', | ||
v_time => 20 ns, | ||
v_rec => ('y', 5), | ||
v_enum => busy, | ||
v_str => "hellostr", | ||
v_vec_int => (11, 22, 33, 44, 55), | ||
v_vec_real => (0.5, 1.75, 3.33, -0.125, -0.67, -2.21), | ||
v_vec_bool => (false, true, true, false), | ||
v_vec_bit => ('1', '0', '1', '0'), | ||
v_vec_time => (1 ns, 50 ps, 1.34 us), | ||
v_vec_rec => (('x', 17),('y', 25)), | ||
v_vec_enum => (start, busy, standby), | ||
v_2vec_real => ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0)) | ||
); | ||
|
||
report "g_str'length: " & integer'image(g_str'length) severity note; | ||
if g_str'length /= 0 then | ||
report "g_str: " & g_str severity note; | ||
end if; | ||
report "string: " & getString severity note; | ||
|
||
report "g_int_vec'length: " & integer'image(g_int_vec'length) severity note; | ||
for x in g_int_vec'range loop | ||
report integer'image(x) & ": " & integer'image(g_int_vec(x)) severity note; | ||
assert g_int_vec(x) = 11*(x+1) severity warning; | ||
end loop; | ||
|
||
report "g_line: " & g_line.all severity note; | ||
report "getLine: " & getLine.all severity note; | ||
assert getLine.all = "HELLO WORLD" severity failure; | ||
|
||
wait; | ||
end process; | ||
end; |
Oops, something went wrong.