-
Notifications
You must be signed in to change notification settings - Fork 263
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
[3/3] Support up to N external memory models #470
base: master
Are you sure you want to change the base?
Conversation
71b04fa
to
82b7833
Compare
e6ce955
to
eedd1d6
Compare
@kraigher, I think this is ready for a preliminary review. |
b705a2d
to
d5ea76d
Compare
Ok I will try to have a look this weekend. You have kept me busy discussion your other enhancements. |
It's ok. Nonetheless, this is not ready for merge. I'd just be glad to hear any thoughts about where I am heading. |
It seems you have reformatted many files making it harder to review. |
Also I do not think the integer_vector_ptr should be changed at all. It it has nothing to do with the memory model except that it is being used as a storage medium. |
The integer_vector_ptr is not even used to store bytes but integers. It is a general purpose data structure that has no benefit of reading or writing bytes in an external object file. It is in the memory model that this flexibility must be added. |
In the simplest case just add a natural range 0 to 1 to the memory_t where 0 means use integer_vector_ptr and 1 means use external read_byte/write_byte calls. |
You can check the first 11 commits: https://github.com/VUnit/vunit/pull/470/files/b6bca4993ad78c66618767f76a60739372b3e086. That's before I switched to
The memory model is exclusive to verification components. After I implemented it for the memory model only (first 11 commits), I realized that:
With my latest proposal,
Helper C functions (read_byte, write_byte) are useful to implement communication with external processes, be it through pipes, sockets, gRPC, etc. Binding the array through an access type reduces the overhead, as assignments and reads are direct. For example, in #465 an array is defined in C and
Yet, I did not see where in the memory model is a array of bytes/characters defined. It seems that a integer type is used to store data. This is because
That was the first approach. But instead of a natural range 0 to 1, I used field
|
The reason the I think you are trying to solve to many problems at once here. Sure I agree that it could be interesting to have a general purpose dynamic length integer array that can inter-operate with an C-object. But that is a different feature than having an external memory model. Just substituting the integer vector in the memory_t with an external vector would not provide an external memory model. I say this because I assume the semantics of an external memory model would be to read and write bytes whereas the memory_t stores packed integers to represent permission flags and expected data in addition to the data bytes. If this approach should be feasible the memory_t would need to store the data bytes separately in a byte array. In this case maybe this array could be shared with a C-object and could be considered to be an external memory model. So in this case the first task becomes to add a dynamic byte array data type to VUnit that can have an external implementation in a C-object. It is easier to review if such a task is done in isolation as a separate PR. So in summary I can agree that having a general purpose approach with external data arrays could be elegant I think it needs to be done on the byte level and not on the integer level to work with the memory model. |
Then, I assume that this PR only works accidentaly. In the axi_dma example, the external memory is used but all the data is set/read from VUnit, so I didn't realize that the C part would see encoded content.
This was a misunderstanding on my side. I thought that bytes were being saved in an array of integers in order to avoid type conversions to/from characters; and permissions and other metainfo were saved in Regarding a general purpose dynamic length integer array that can inter-operate with an C-object, the content in #476 is mostly a copy of the extension to the vector of integers in this PR:
I wish it was possible to use the same logic to manipulate external arrays of integers, characters or even custom record types. But I am afraid this is not possible with VHDL 1993. What about VHDL 2008 or 2019?
Although my first approach was to only support reading/writing bytes (because I thought that the internal memory model would use an array of bytes); after understanding the context, I think that we can support four 'models':
The first and the last one are implemented already. The second and the third will be possible after #476, as you suggested. I think that the implementation order should be 1, 2, 4, 3. |
1e564c2
to
099730a
Compare
d0bb7e0
to
87e079a
Compare
87e079a
to
0e25027
Compare
* add sigabrt.md
NOT READY FOR MERGE
Ref #465.
Close #462.
This PR allows to use
integer_vector_access_t
(memory buffers) defined in external C functions, along with the default internal model. The API for the testbench is as follows:extmemory_pkg-novhpi.vhd
, which declaresread_byte
andwrite_byte
in VHDL, so no C files are required and cannot be used.ui.set_objects([c_obj])
to add pre-built object and to automatically useextmemory_pkg-vhpi.vhd
, which declaresread_byte
andwrite_byte
as external. C definitions of the functions/procedures is required. The definition can be empty if external memory models are not to be used.constant memory : memory_t := new_memory;
: default memory model.constant memory : memory_t := new_memory(n, length);
: wheren
is any integer/=0
, will use the external memory identified by the number (n
).n<0
calls to the external memory model are executed through VHPI functionsread_byte
andwrite_byte
.n>0
, a foreign array is mapped to a VHDL access type through functionget_addr
. [NOT IMPLEMENTED YET].The API for the C sources is:
Issues with the current implementation:
When a function/procedure is decorated withattribute foreign
it is compulsory to provide a definition in C, either if only the default internal model is to be used (see Unused, undefined foreign function makes elaboration fail ghdl/ghdl#793). Therefore, currently astubs.c
file is used unless the user provides a custom implementation.stubs.c
file, which will be useless for most of the users. Moreover, this is currently only supported by GHDL (and not for mcode backend).An alternative is to conditionally comment the two lines that declare the functions/procedures as foreign. @kraigher, what do you think? Should I move those two functions/procedures to a separate package to make it easier to change it? Or is it possible to process the file at compile time?axi_dma
so the tests can only be executed on simulators with VHPI support. It would be desirable to provide two sets of test runs, one without VHPI and another one with VHPI.length
is fixed for now, and explicitly set. By the same token, permissions are unset/non-existent. This produces multiple errors incheck_address
. Therefore, some of the checks are skipped for external memories. They are still used for the default memory model, in case multiple models are used at the same time.deallocate
,reallocate
andresize
are not implemented yet.n>0
, where the base address of an external buffer is assigned to an access type in VHDL,integer_vector
would need to be of typearray (natural range <>) of character;
. However, it is of typeinteger
.