Skip to content

Commit f7326b0

Browse files
committed
vhpidirect: add header file and 'demo' (ghdl/ghdl#1059)
1 parent c8efd3d commit f7326b0

File tree

7 files changed

+522
-0
lines changed

7 files changed

+522
-0
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.. program:: ghdl
2+
.. _COSIM:VHPIDIRECT:Examples:cinterface:
3+
4+
C interface
5+
###########
6+
7+
:cosimtree:`demo <vhpidirect/cinterface/demo>`
8+
**********************************************
9+
10+
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.

doc/vhpidirect/examples/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ Examples
88
quickstart
99
shared
1010
arrays
11+
cinterface
1112
other

test.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,5 +135,8 @@ def test_vhpidirect_arrays_matrices_framebuffer(self):
135135
self._sh([str(self.vhpidirect / 'arrays' / 'matrices' / 'framebuffer' / 'run.sh')])
136136

137137

138+
def test_vhpidirect_cinterface_demo(self):
139+
check_call(self.shell + [str(self.vhpidirect / 'cinterface' / 'demo' / 'run.sh')], shell=True)
140+
138141
def test_vpi_quickstart(self):
139142
self._sh([str(self.vpi / 'quickstart' / 'run.sh')])

vhpidirect/cinterface/demo/main.c

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#include <stdlib.h>
2+
#include <stdint.h>
3+
#include <stdio.h>
4+
#include <stdbool.h>
5+
#include <assert.h>
6+
#include <string.h>
7+
8+
#include <ghdl.h>
9+
10+
typedef struct rec_t {
11+
char r_char;
12+
int32_t r_int;
13+
} rec_t;
14+
15+
typedef enum {standby, start, busy, done} enum_t;
16+
17+
void testCinterface(
18+
char v_char,
19+
int32_t v_int,
20+
uint32_t v_nat,
21+
uint32_t v_pos,
22+
double v_real,
23+
bool v_bool,
24+
bool v_bit,
25+
int64_t v_time,
26+
rec_t* v_rec,
27+
uint8_t v_enum,
28+
ghdl_NaturalDimArr_t* v_str,
29+
ghdl_NaturalDimArr_t* v_vec_int,
30+
ghdl_NaturalDimArr_t* v_vec_real,
31+
ghdl_NaturalDimArr_t* v_vec_bool,
32+
ghdl_NaturalDimArr_t* v_vec_bit,
33+
ghdl_NaturalDimArr_t* v_vec_phy,
34+
ghdl_NaturalDimArr_t* v_vec_rec,
35+
ghdl_NaturalDimArr_t* v_vec_enum,
36+
ghdl_NaturalDimArr_t* v_2vec_real
37+
) {
38+
assert(v_char == 'k');
39+
printf("v_char : %c\n", v_char);
40+
41+
assert(v_int == -6);
42+
printf("v_int : %d\n", v_int);
43+
44+
assert(v_nat == 9);
45+
printf("v_nat : %d\n", v_nat);
46+
47+
assert(v_pos == 3);
48+
printf("v_pos : %d\n", v_pos);
49+
50+
assert(v_real == 3.34);
51+
printf("v_real : %f\n", v_real);
52+
53+
assert(v_bool == true);
54+
printf("v_bool : %d\n", v_bool);
55+
56+
assert(v_bit == true);
57+
printf("v_bit : %d\n", v_bit);
58+
59+
assert(v_time == 20e6);
60+
printf("v_time : %d\n", v_time);
61+
62+
assert(v_rec != NULL);
63+
assert(v_rec->r_char == 'y');
64+
assert(v_rec->r_int == 5);
65+
printf("v_rec : %p %c %d\n", v_rec, v_rec->r_char, v_rec->r_int);
66+
67+
assert(v_enum == busy);
68+
printf("v_enum : %d %d\n", v_enum, busy);
69+
70+
char* str = ghdlToString(v_str);
71+
printf("v_str : %p '%s' [%d]\n", v_str->array, str, strlen(str));
72+
73+
int* len = malloc(2 * sizeof(int));
74+
75+
int32_t* vec_int;
76+
ghdlToArray(v_vec_int, (void**)&vec_int, len, 1);
77+
assert(vec_int[0] == 11);
78+
assert(vec_int[1] == 22);
79+
assert(vec_int[2] == 33);
80+
assert(vec_int[3] == 44);
81+
assert(vec_int[4] == 55);
82+
printf("v_vec_int : %p [%d]\n", vec_int, len[0]);
83+
84+
double* vec_real;
85+
ghdlToArray(v_vec_real, (void**)&vec_real, len, 1);
86+
assert(vec_real[0] == 0.5);
87+
assert(vec_real[1] == 1.75);
88+
assert(vec_real[2] == 3.33);
89+
assert(vec_real[3] == -0.125);
90+
assert(vec_real[4] == -0.67);
91+
assert(vec_real[5] == -2.21);
92+
printf("v_vec_real : %p [%d]\n", vec_real, len[0]);
93+
94+
bool* vec_bool;
95+
ghdlToArray(v_vec_bool, (void**)&vec_bool, len, 1);
96+
assert(vec_bool[0] == 0);
97+
assert(vec_bool[1] == 1);
98+
assert(vec_bool[2] == 1);
99+
assert(vec_bool[3] == 0);
100+
printf("v_vec_bool : %p [%d]\n", vec_bool, len[0]);
101+
102+
bool* vec_bit;
103+
ghdlToArray(v_vec_bit, (void**)&vec_bit, len, 1);
104+
assert(vec_bit[0] == 1);
105+
assert(vec_bit[1] == 0);
106+
assert(vec_bit[2] == 1);
107+
assert(vec_bit[3] == 0);
108+
printf("v_vec_bit : %p [%d]\n", vec_bit, len[0]);
109+
110+
int64_t* vec_phy;
111+
ghdlToArray(v_vec_phy, (void**)&vec_phy, len, 1);
112+
assert(vec_phy[0] == 1e6);
113+
assert(vec_phy[1] == 50e3);
114+
assert(vec_phy[2] == 1.34e9);
115+
printf("v_vec_phy : %p [%d]\n", vec_phy, len[0]);
116+
117+
rec_t* vec_rec;
118+
ghdlToArray(v_vec_rec, (void**)&vec_rec, len, 1);
119+
assert(vec_rec[0].r_char == 'x');
120+
assert(vec_rec[0].r_int == 17);
121+
assert(vec_rec[1].r_char == 'y');
122+
assert(vec_rec[1].r_int == 25);
123+
printf("v_vec_rec : %p [%d]\n", vec_rec, len[0]);
124+
125+
uint8_t* vec_enum;
126+
ghdlToArray(v_vec_enum, (void**)&vec_enum, len, 1);
127+
assert(vec_enum[0] == start);
128+
assert(vec_enum[1] == busy);
129+
assert(vec_enum[2] == standby);
130+
printf("v_vec_enum : %p [%d]\n", vec_enum, len[0]);
131+
132+
double* vec2_real_base;
133+
ghdlToArray(v_2vec_real, (void**)&vec2_real_base, len, 2);
134+
double (*vec2_real)[len[0]] = (double(*)[len[0]])vec2_real_base;
135+
assert(vec2_real[0][0] == 0.1);
136+
assert(vec2_real[0][1] == 0.25);
137+
assert(vec2_real[0][2] == 0.5);
138+
assert(vec2_real[1][0] == 3.33);
139+
assert(vec2_real[1][1] == 4.25);
140+
assert(vec2_real[1][2] == 5.0);
141+
printf("v_2vec_real : %p [%d, %d]\n", vec_enum, len[1], len[0]);
142+
}
143+
144+
void getString(ghdl_NaturalDimArr_t* ptr) {
145+
*ptr = ghdlFromString("HELLO WORLD");
146+
}
147+
148+
void getIntVec(ghdl_NaturalDimArr_t* ptr) {
149+
int32_t vec[6] = {11, 22, 33, 44, 55};
150+
int32_t len[1] = {5};
151+
int x;
152+
for ( x=0 ; x<len[0] ; x++ ) {
153+
printf("%d: %d\n", x, vec[x]);
154+
}
155+
*ptr = ghdlFromArray(vec, len, 1);
156+
}
157+
158+
ghdl_AccNaturalDimArr_t* getLine() {
159+
return ghdlAccFromString("HELLO WORLD");
160+
}

vhpidirect/cinterface/demo/run.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/usr/bin/env sh
2+
3+
set -e
4+
5+
cd $(dirname "$0")
6+
7+
echo "Analyze tb.vhd"
8+
ghdl -a -O0 -g tb.vhd
9+
10+
echo "Build tb (with main.c and headers)"
11+
ghdl -e -O0 -g -Wl,-I../../ -Wl,main.c tb
12+
13+
echo "Execute tb"
14+
./tb

vhpidirect/cinterface/demo/tb.vhd

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
use std.textio.line;
2+
3+
entity tb is
4+
end;
5+
6+
architecture arch of tb is
7+
8+
type rec_t is record
9+
r_char: character;
10+
r_int : integer;
11+
end record;
12+
13+
type enum_t is (standby, start, busy, done);
14+
15+
type int_vec_t is array(natural range <>) of integer;
16+
type real_vec_t is array(natural range <>) of real;
17+
type bool_vec_t is array(natural range <>) of boolean;
18+
type time_vec_t is array(natural range <>) of time;
19+
type rec_vec_t is array(natural range <>) of rec_t;
20+
type enum_vec_t is array(natural range <>) of enum_t;
21+
22+
type real_2vec_t is array (natural range <>, natural range <>) of real;
23+
24+
begin
25+
process
26+
27+
procedure testCinterface(
28+
v_char : character := 'k';
29+
v_int : integer := -6;
30+
v_nat : natural := 9;
31+
v_pos : positive := 3;
32+
v_real : real := 3.34;
33+
v_bool : boolean := true;
34+
v_bit : bit := '1';
35+
v_time : time := 20 ns;
36+
v_rec : rec_t := ('y', 5);
37+
v_enum : enum_t := busy;
38+
v_str : string := "hellostr";
39+
v_vec_int : int_vec_t := (11, 22, 33, 44, 55);
40+
v_vec_real : real_vec_t := (0.5, 1.75, 3.33, -0.125, -0.67, -2.21);
41+
v_vec_bool : bool_vec_t := (false, true, true, false);
42+
v_vec_bit : bit_vector := ('1', '0', '1', '0');
43+
v_vec_time : time_vec_t := (1 ns, 50 ps, 1.34 us);
44+
v_vec_rec : rec_vec_t := (('x', 17),('y', 25));
45+
v_vec_enum : enum_vec_t := (start, busy, standby);
46+
v_2vec_real : real_2vec_t := ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0))
47+
) is
48+
begin assert false report "VHPIDIRECT testCinterface" severity failure; end;
49+
attribute foreign of testCinterface : procedure is "VHPIDIRECT testCinterface";
50+
51+
function getString return string is
52+
begin assert false report "VHPIDIRECT getString" severity failure; end;
53+
attribute foreign of getString : function is "VHPIDIRECT getString";
54+
55+
function getIntVec return int_vec_t is
56+
begin assert false report "VHPIDIRECT getIntVec" severity failure; end;
57+
attribute foreign of getIntVec : function is "VHPIDIRECT getIntVec";
58+
59+
function getLine return line is
60+
begin assert false report "VHPIDIRECT getLine" severity failure; end;
61+
attribute foreign of getLine : function is "VHPIDIRECT getLine";
62+
63+
constant g_str: string := getString;
64+
constant g_int_vec: int_vec_t := getIntVec;
65+
66+
variable g_line: line := getLine;
67+
68+
begin
69+
70+
testCinterface(
71+
v_char => 'k',
72+
v_int => -6,
73+
v_nat => 9,
74+
v_pos => 3,
75+
v_real => 3.34,
76+
v_bool => true,
77+
v_bit => '1',
78+
v_time => 20 ns,
79+
v_rec => ('y', 5),
80+
v_enum => busy,
81+
v_str => "hellostr",
82+
v_vec_int => (11, 22, 33, 44, 55),
83+
v_vec_real => (0.5, 1.75, 3.33, -0.125, -0.67, -2.21),
84+
v_vec_bool => (false, true, true, false),
85+
v_vec_bit => ('1', '0', '1', '0'),
86+
v_vec_time => (1 ns, 50 ps, 1.34 us),
87+
v_vec_rec => (('x', 17),('y', 25)),
88+
v_vec_enum => (start, busy, standby),
89+
v_2vec_real => ((0.1, 0.25, 0.5),(3.33, 4.25, 5.0))
90+
);
91+
92+
report "g_str'length: " & integer'image(g_str'length) severity note;
93+
if g_str'length /= 0 then
94+
report "g_str: " & g_str severity note;
95+
end if;
96+
report "string: " & getString severity note;
97+
98+
report "g_int_vec'length: " & integer'image(g_int_vec'length) severity note;
99+
for x in g_int_vec'range loop
100+
report integer'image(x) & ": " & integer'image(g_int_vec(x)) severity note;
101+
assert g_int_vec(x) = 11*(x+1) severity warning;
102+
end loop;
103+
104+
report "g_line: " & g_line.all severity note;
105+
report "getLine: " & getLine.all severity note;
106+
assert getLine.all = "HELLO WORLD" severity failure;
107+
108+
wait;
109+
end process;
110+
end;

0 commit comments

Comments
 (0)