-
Notifications
You must be signed in to change notification settings - Fork 9
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
How to call C functions with opaque pointers (VHPIDIRECT) #30
Comments
Well, as a workaround you can use a procedure instead of a function if you don't need the return value: entity tb is
generic (
g_TCP_PORT : natural := 14000
);
end tb;
architecture arch of tb is
type t_tcp_listener is access integer;
impure function new_tcp_listener (tcp_port : natural) return t_tcp_listener is
begin report "VHPIDIRECT new_tcp_listener" severity failure; end;
attribute foreign of new_tcp_listener : function is "VHPIDIRECT new_tcp_listener";
procedure delete_tcp_listener (variable listener : t_tcp_listener) is
begin report "VHPIDIRECT delete_tcp_listener" severity failure; end;
attribute foreign of delete_tcp_listener : procedure is "VHPIDIRECT delete_tcp_listener";
begin
process
variable net: t_tcp_listener;
begin
net := new_tcp_listener(g_TCP_PORT);
delete_tcp_listener(net);
wait;
end process;
end; This works, if you don't touch the variable |
Yes, you are hitting the limitations of vhdl: a function parameter cannot be an access type (or have an access type).
You can indeed use a procedure instead.
Or simply use handles instead of pointers.
|
After some experimentation I've found few caveats:
Nevertheless, I succeed in writing to a constrained std_logic_vector variable via a procedure: library ieee;
use ieee.std_logic_1164.all;
entity obj_tb is
end obj_tb;
architecture arch of obj_tb is
type t_my_obj is access integer;
impure function new_obj (arg : natural) return t_my_obj is
begin report "VHPIDIRECT new_obj" severity failure; end;
attribute foreign of new_obj : function is "VHPIDIRECT new_obj";
procedure read_data_obj(variable obj : in t_my_obj;
variable data : out std_logic_vector(0 to 31)) is
begin report "VHPIDIRECT read_data_obj" severity failure; end;
attribute foreign of read_data_obj: procedure is "VHPIDIRECT read_data_obj";
begin
process
variable obj: t_my_obj;
variable data: std_logic_vector(31 downto 0);
begin
obj := new_obj(512);
read_data_obj(obj, data);
report "Data read: " & to_string(data) severity note;
wait;
end process;
end; #include <stddef.h>
#include <stdlib.h>
typedef struct {
int data;
} obj;
obj* new_obj(int arg) {
obj* myobj = malloc(sizeof(obj));
myobj->data = arg;
return myobj;
}
typedef struct {
char data[32];
} read_data_obj_record;
void read_data_obj(obj* myobj, read_data_obj_record* rec) {
int mydata = myobj->data;
for (size_t i = 0; i < 32; i++) {
rec->data[i] = mydata & 0x80000000 ? 0x03 : 0x02;
mydata = mydata << 1;
}
} $ ghdl -a --std=08 test_arguments.vhd
$ ghdl -e -Wl,testobj.c --std=08 obj_tb
./obj_tb
test_arguments.vhd:26:5:@0ms:(report note): Data read: 00000000000000000000001000000000 Though this seems to contradict the documentation: this record is passed by reference as the first argument to the subprogram. Maybe this is not true when passing access types? I couldn't get working anything more complex than a single |
Hi,
I'm developing a library to allow my VHDL testbenches to be able to listen to TCP connections and send / receive data. The library is written in a object oriented sytle, in which each function receives a pointer to a struct that stores the object internal state, for example:
Now, I couldn't find in the documentation and examples what VHDL type to use for storing an opaque pointer that comes from the C code. The best I could think was using an 'access type', but you can't call functions with an 'access type' argument:
Is there some way of invoking C functions with opaque pointers?
Thanks,
Augusto.
The text was updated successfully, but these errors were encountered: