[1/3] Add external models to string_ptr; add byte_vector* as an alias by umarcor · Pull Request #507 · VUnit/vunit
Not really. Note that this id is NOT the same id that was in the codebase until 6 months ago. That was renamed to ref: https://github.com/VUnit/vunit/blob/master/vunit/vhdl/data_types/src/string_ptr_pkg.vhd#L20 and https://github.com/VUnit/vunit/blob/master/vunit/vhdl/data_types/src/integer_vector_ptr_pkg.vhd#L21.
The mechanism to share buffers between C and VHDL is a char* [], i.e. an array of pointers to an arrays of chars. This id is used to decide which of those arrays of chars corresponds to a string in VHDL. See examples/vhdl/external_buffer/src/main.c:
- If mode is extacc, VHDL will execute
get_string_ptr(id)to retrieve that pointer address. - If mode is extfnc, VHDL will pass the id in each call to
write_charorread_char.
In this example, using write_char (mode extfnc) is equivalent to VHDL writing directly with mode extacc. However, this is only because of the specific C implementation of write_char. In a practical example write_char is expected to do some more complex task, such as sending data through HTTP. That's where the id is handy.
When mode is internal, field id is not used at all.
Nonetheless, ref still exists. Each string, no matter the mode, has a ref; it is assigned automaticallly, as it has always been. See:
| case mode is | |
| when internal => | |
| st.ids(st.id) := ( | |
| id => st.ptr, | |
| mode => internal, | |
| length => 0 | |
| ); | |
| reallocate_ptrs(st.ptrs, st.ptr); | |
| st.ptrs(st.ptr) := new vec_t'(1 to length => value); | |
| st.ptr := st.ptr + 1; | |
| when extacc => | |
| st.ids(st.id) := ( | |
| id => st.eptr, | |
| mode => extacc, | |
| length => length | |
| ); | |
| reallocate_eptrs(st.eptrs, st.eptr); | |
| st.eptrs(st.eptr) := get_ptr(id); | |
| st.eptr := st.eptr + 1; | |
| when extfnc => | |
| st.ids(st.id) := ( | |
| id => id, | |
| mode => extfnc, | |
| length => length | |
| ); | |
| end case; | |
| st.id := st.id + 1; | |
| return st.id-1; |
Let's suppose we want to use four strings:
- internal
- extacc with id 0
- internal
- extfnc with id 1
st.ids st.ptr st.eptr
string0 0 0
string1 1 0
string2 2 1
string3 3
So,
st.idsis an array ofrefthat contains four entries, one for each string.st.ptris the array of refs/pointers to internal strings (this is the element that has always existed, everything else is wrapped around it), and contains two entries.st.eptris the array of refs/pointers to extacc strings (idis used to get_string_ptr once only).
As a result:
st.ids(0).id is 0 (index to read/write from/to st.ptr)
st.ids(1).id is 0 (index to read/write from/to st.eptr)
st.ids(2).id is 1 (index to read/write from/to st.ptr)
st.ids(3).id is 1 (id to read/write through read_char and write_char)
Maybe I am overusing the name id? Currently, it is:
- A parameter for extacc to get the pointer from C.
- A parameter for extfnc to pass to read_char/write_char.
- The name of the field
st.ids, which contains a number (id) for each string. - The name of field
st.ids().idwhich contains a number representing either:- The corresponding index in
st.ptr. - The corresponding index in
st.eptr. - The
idparameter used when creating an extfnc string.
- The corresponding index in
EDIT
After reading this, I think that it might be easier to understand #507 (comment). I feel that it should be possible to merge st.ptr and st.eptr in a single array. But VHDL seems to fight against me doing it...