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
WIP: Support records in vpi #1249
base: master
Are you sure you want to change the base?
Conversation
src/grt/grt-avhpi.adb
Outdated
@@ -27,6 +27,19 @@ with Grt.Vstrings; use Grt.Vstrings; | |||
with Grt.Rtis_Utils; use Grt.Rtis_Utils; | |||
with Grt.To_Strings; | |||
|
|||
-- Acronyms that I don't understand: | |||
-- Rti |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rti: run time information. That's all the data emitted by translate to describe vhdl types and subtypes.
src/grt/grt-avhpi.adb
Outdated
@@ -27,6 +27,19 @@ with Grt.Vstrings; use Grt.Vstrings; | |||
with Grt.Rtis_Utils; use Grt.Rtis_Utils; | |||
with Grt.To_Strings; | |||
|
|||
-- Acronyms that I don't understand: | |||
-- Rti | |||
-- Rtis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
grt.rtis is the package that describes the rti.
src/grt/grt-avhpi.adb
Outdated
-- Acronyms that I don't understand: | ||
-- Rti | ||
-- Rtis | ||
-- Rtin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rti node. All the ghdl_rtin_* records defines the rti data.
src/grt/grt-avhpi.adb
Outdated
|
||
-- Questoins: | ||
-- Explanation for the Ctxt objects would be really helpful. | ||
-- Why are they used, and what do they represent? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Example for a port:
you have an rti that describes the port: its name, its type, its mode...
But you also need its address to get its value. But a port is part of an entity that can be instantiated many times. So you need the context of the port, which consists of the entity/architecture and the address of the entity/architecture instance.
src/grt/grt-avhpi.adb
Outdated
-- Questoins: | ||
-- Explanation for the Ctxt objects would be really helpful. | ||
-- Why are they used, and what do they represent? | ||
-- Does ghdl support a VHPI interface? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not at the C level. There is AVHPI which is inspired from VHPI but uses Ada style. But there is no C VHPI interface. Shouldn't be very hard to do, but there are very few examples.
src/grt/grt-avhpi.adb
Outdated
-- Why are they used, and what do they represent? | ||
-- Does ghdl support a VHPI interface? | ||
-- What's the best way to test this work. Should we add | ||
-- a cocotb dependency to the testing? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really prefer to have standalone tests. That's easier to investigate and do not depends on cocotb evolution.
src/grt/grt-avhpi.adb
Outdated
when VhpiGenericDeclK => | ||
when VhpiGenericDeclK | | ||
VhpiPortDeclK | | ||
VhpiSigDeclK => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks ok.
src/grt/grt-avhpi.adb
Outdated
Res := (Kind => AvhpiNameIteratorK, | ||
Ctxt => Ref.Ctxt, | ||
-- What does the 'N_' indicate? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the prefix for names in the vhpiHandleT. All the names in a record must be unique.
src/grt/grt-avhpi.adb
Outdated
@@ -145,6 +162,8 @@ package body Grt.Avhpi is | |||
return; | |||
end case; | |||
case Res.N_Type.Kind is | |||
-- Why only Ghdl_Rtik_Subtype_Array? | |||
-- Why not also Ghdl_Rtik_Type_Array? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, to be added ?
src/grt/grt-avhpi.adb
Outdated
return; | ||
end case; | ||
case Res.N_Type.Kind is | ||
when Ghdl_Rtik_Type_Record => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and also record subtypes ? :-)
src/grt/grt-avhpi.adb
Outdated
@@ -184,6 +254,9 @@ package body Grt.Avhpi is | |||
El_Type1 : Ghdl_Rti_Access; | |||
begin | |||
case Obj_Rti.Common.Kind is | |||
-- Does this mean we only support scanning iterators in | |||
-- generics. That doesn't make much sense. | |||
-- What am I missing? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly. In VPI you can directly get the value of a vector.
src/grt/grt-avhpi.adb
Outdated
-- Maybe signals are built as structures of signals, | ||
-- but generics are raw? So signals effectively | ||
-- contain lots of thin signal wrappers that we're | ||
-- pointing at. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, generics contain the raw value, while signals are addresses to an internal structure.
src/grt/grt-avhpi.adb
Outdated
-- An explanation of what's going on here would be really | ||
-- helpful. | ||
-- It looks like we're finding out the size of the structure | ||
-- but I've failed to understand how. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah OK. So that's the for_generate_statement. There is an array containing the sub-instances, because the block can be repeated many times. So we need to update the context to point to the corresponding sub-instance.
src/grt/grt-avhpi.adb
Outdated
@@ -219,11 +302,17 @@ package body Grt.Avhpi is | |||
end if; | |||
end; | |||
when others => | |||
-- Feels like we supported a strange subset of possible types. | |||
-- I'm curious what drove the supported features in this | |||
-- implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is mainly SDF annotations + what has been asked for VPI.
src/grt/grt-avhpi.adb
Outdated
-- Decrement number of elements left in iterator. | ||
Iterator.N_Idx := Iterator.N_Idx - 1; | ||
Error := AvhpiErrorOk; | ||
end Vhpi_Scan_Selected_Name; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That looks OK, but I haven't thoroughly reviewed this subprogram.
src/grt/grt-avhpi.adb
Outdated
@@ -398,6 +526,7 @@ package body Grt.Avhpi is | |||
Bt : constant Ghdl_Rtin_Type_Array_Acc := | |||
To_Ghdl_Rtin_Type_Array_Acc (Atype.Basetype); | |||
begin | |||
-- I don't understand what's happening here. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. An array type declaration like type my_vec is array (0 to 7) of bit
is represented as an anonymous unconstrained array type declaration type anon_my_vec is array (integer range <>) of bit
followed by a subtype declaration subtype my_vec is anon_my_vec(0 to 7)
. So we need to ignore the anonymous array type declaration and pretend that the subtype declaration is a type declaration.
src/grt/grt-vpi.adb
Outdated
@@ -68,7 +69,7 @@ package body Grt.Vpi is | |||
Version : constant String := "0.1" & NUL; | |||
|
|||
-- If true, emit traces | |||
Flag_Trace : Boolean := False; | |||
Flag_Trace : Boolean := True; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use --vpi-trace
to dynamically set this flag.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments added.
Awesome, thanks a bunch for the help! |
If you need more comments, do not hesitate.
Maybe we can start to merge some parts. For example, if it is already possible to scan through generics of a record type, this specific part could be tested and added.
|
I'm trying to understand the RTI structures but am having difficulty understanding what data is stored in the memory that the |
Note that there is the option '--dump-rti' to dump the rtis at runtime: ghdl -r design --dump-rti
That could be useful to understand how rtis work. This is implemented by grt-disp_rti, which is almost standalone.
1) VHDL types are represented as close as possible to the corresponding C type. So a scalar is represented as a scalar, an array as an array and a record as a struct.
2) For signals, the scalars and the scalar sub-elements are represented as pointers. So a bit signal is represented by a pointer, a std_logic_vector by an array of pointer, and a record by a struct of pointers. The pointer points to ghdl_signal record defined in grt-signals. The record contains the current value, but also the value for 'event, 'active, 'last_value, 'last_event...
3) for records, there is one RTI for each element, which gives the offset from the record address to the field address. But grt.rtis_utils has many subprograms to handle the rtis, including Record_To_Element.
|
Looking at grt-disp_rti is helping. I don't have any additional questions, and there's nothing that's worth reviewing yet. I'm just going through grt-disp_rti and making sure I understand what's going on. |
When a new array type is defined that binds an unbound type an anonymous RTI type object is created: type mytype is array(natural range <>) of std_logic_vector(WIDTH-1 downto 0); However when a new record type is defined that binds an unbound type an anonymous type is not created. Rather the information about the bounds is stored in the element node of the record. type mytype is record
a: std_logic_vector(WIDTH-1 downto 0);
end; This is a bit of a pain when dealing with the subcomponents of the signal, since there is no RTI type that can be easily referred to. Instead we have to refer to the unbound type, and the bounds information. It would be much more pleasant if records created anonymous types in the same way that arrays do. Is this a change that could be limited to the RTI part of the codebase or would it be more complicated? |
Also, the RTI tree has |
Also, the RTI tree has Ghdl_Rti_Object to represent signal/port/constant/generic but doesn't contain any more fine-grained objects to represent the subcomponents. Is this intentional so that we don't get a crazy number of objects that might effect peformance, so was it just that there was no advantage to it? Having more fine-grained objects could simplify things when dealing with records and arrays.
That's not possible. The size of arrays is not known when the RTIs are generated.
|
type mytype is array(natural range <>) of std_logic_vector(WIDTH-1 downto 0);
However when a new record type is defined that binds an unbound type an anonymous type is not created. Rather the information about the bounds is stored in the element node of the record.
I am not sure to understand what you means:
```
entity repro1 is
generic (WIDTH : natural := 4);
end;
architecture behav of repro1 is
type myarr is array(natural range <>) of bit_vector(WIDTH-1 downto 0);
type myrec is record
a: bit_vector(WIDTH-1 downto 0);
end record;
begin
end;
```
`ghdl -r repro1 --dump-rti`:
...
```
ghdl_rtik_architecture, D=1, sloc=5:14: behav
filename: repro1.vhdl
ghdl_rtik_entity, D=1, sloc=1:8: repro1
filename: repro1.vhdl
ghdl_rtik_generic, D=1, sloc=2:12; width: natural := 4
ghdl_rtik_type_array: myarr is array (natural range <>) of bit_vector (3 downto 0)
ghdl_rtik_type_record: myrec is record
ghdl_rtik_element: a: bit_vector (3 downto 0)
```
|
My understanding is that an anonymous RTI node with kind Ghdl_Rtik_Subtype_Array is created. The Ghdl_Rtik_Type_Array with name For the The anonymous types don't show in the disp_rti dump because they are not children of any of the blocks. |
Still trying to get my head around this. In the example you gave we'll be creating RTIs for Edit: I'm going to sleep now. Thanks for the explanations. |
Still trying to get my head around this. In the example you gave we'll be creating RTIs for a and b. Why wouldn't it be practical to create an anonymous subtype for each at the same time?
And to store the bounds within this RTI ? The consequence is that you will have to modify the RTIs each time to assign such a variable, because you could change the bounds. But RTIs are read-only.
Or having RTIs that say that the bounds are within the object ? I fear that would be much more complex or not very different from the current implementation.
|
I understand. The bounds are determined after elaboration and could change during runtime. I have to try to remember about non-synthesizable vhdl too :). |
Yes. On top of that, subprograms parameters are often of unbounded types.
|
I'm continuing to very slowly work on this. If anyone is impatient and would like to have a crack themselves, I won't be at all offended if you take over :). |
54a4434
to
c95cf91
Compare
Description
The goal is to make it possible to use cocotb with a design that uses nested records and arrays in it's ports, signals and generics. Related to issue #237.
It is a long way from being finished, but it would be useful to get some feedback. If you have the time and inclination, any comments would be appreciated.
I've added comments to the code where I have questions about how things should work.