Could polymorphism (function/procedure overloading) work dynamically without huge impacts to the language? Currently, the polymorphism "happens" at compile time, not at execution time, but there is not one selection, but several to be made, all for the same statement.
For the analysis to have a chance, it would have to find overloaded versions of the subprogram for all the types indicated by the range of the index variable (sub-ranges of records and their indices might come in handy here). Then it could build an implied case statement to invoke each specific subprogram per the index.
Not sure what kind of limitations would have to be put on uses of this for it to be synthesizable. Obviously a for-loop would be pretty straight forward (unrolling), but what if you passed one of those indexes in through a port or argument?
Better the compiler build (and maintain) that case statement than me...
Andy D Jones
Electrical Engineering
Lockheed Martin Missiles and Fire Control
Dallas TX
From: owner-vhdl-200x@eda.org [mailto:owner-vhdl-200x@eda.org] On Behalf Of ryan.w.hinton@L-3com.com
Sent: Wednesday, July 18, 2012 12:26 PM
To: vhdl-200x@eda.org
Subject: EXTERNAL: Re: [vhdl-200x] Record slices (branched from Directional records proposal)
You're right, it would be hard to create an expression with these dynamically-accessed fields, but VHDL has rather capable polymorphism. Here's a reasonable example.
-- record containing fields with disparate types
type misc is record
int : integer;
float : real;
snum : signed(7 downto 0);
end record misc;
-- object of this type
signal obj : misc;
-- loo p over fields and write to a single line in a LINE variable
for field in misc'fields loop
write(ln, obj.field);
end loop;
writeline(F, ln);
This could work because the write procedure is overloaded for all of the types in the record. If the O.P. overloads his pack() and unpack() subpro grams appropriately, it seems like a similar construction will work for him. Interestingly, the currently language allows the OTHERS choice in aggregates despite the typical case where it doesn't work. And I've never had a problem with it in my code because it doesn't make any sense to use it in the wrong way.
This can be accomplished by extending the language to implicitly declare an (anonymous) enumerated type whose values are the record type field names in order. Then the record field access (dot syntax) becomes very similar to an array lookup. In LRM parlance, it acts like an indexed name instead of a selected name. Existing code simply uses the enumeration literals everywhere, while the code above uses a constant (the loop index) o f the enumeration type. We could add record type attributes T'FIELDS to provide a range containing the field names, and T'FIELDS_TYPE to provide the enumerated type for the field names. This is the only sane approach I've yet seen to this proposal.
I don't see any backward compatibility issues with this interpretation -- in particular with visibility, homographs, and overloading. But I haven't fully researched the implications (esp. indexed versus selected name). And I'm still not sure I like it, but I can't seem to find any compelling reason against it.
Are there any other good use cases? So far this has been suggested for use with directional ports (more comments coming on that topic) and in FOR loops utilizing polymorphism.
Enjoy!
- Ryan
From: owner-vhdl-200x@eda.org<mailto:owner-vhdl-200x@eda.org> [mailto:owner-vhdl-200x@eda.org] On Behalf Of Peter Flake
Sent: Wednesday, July 18, 2012 8:31 AM
To: vhdl-200x@eda.org<mailto:vhdl-200x@eda.org>
Subject: RE: EXTERNAL: Re: [vhdl-200x] Directional records proposal
I think that the problem with a language-native way is that there is no dynamic typing. Each field can have a different data type, and so there is no expression type that could represent any field in the record. An alternative is to use the VHPI.
Peter.
From: owner-vhdl-200x@eda.org<mailto:owner-vhdl-200x@eda.org> [mailto:owner-vhdl-200x@eda.org] On Behalf Of Huffman, Nathanael D (GE Healthcare)
Sent: 17 July 2012 23:02
To: vhdl-200x@eda.org<mailto:vhdl-200x@eda.org>
Subject: RE: EXTERNAL: Re: [vhdl-200x] Directional records proposal
I use record types as command and status registers. In order to make this useful I have a tcl script that generates overloaded pack() and unpack() functions that convert the records into slvs for interfacing with a databus for the processor. I think the ability to loop through record elements could allow a language-native way of doing this rather than using a pre-processor to generate these functions. The individual functions would still be required due to the different types for each register, but they could be coded in a generic way by looping through the record and concatenating rather than the "hard-coded" method of assigning record fields to slices of the returned vector.
Nathanael
From: owner-vhdl-200x@eda.org<mailto:owner-vhdl-200x@eda.org> [mailto:owner-vhdl-200x@eda.org] On Behalf Of Brent Hayhoe
Sent: Tuesday, July 17, 2012 4:50 PM
To: vhdl-200x@eda.org<mailto:vhdl-200x@eda.org>
Subject: Re: EXTERNAL: Re: [vhdl-200x] Directional records proposal
Daniel,
I would agree that iterating through elements of records is required and although I can't think of any obvious examples, I'm sure I've had code in the past that would have benefited from it.
Maybe we need something like a 'foreach rec_type loop' structure to cycle through the record's elements.
On 17/07/2012 16:45, Daniel Kho wrote:
Andy,
<quote>
Can a for-loop ite rate through the elements of a record? If so, are there any restrictions? This ability would be really nice for converting records of slv elements to one long slv, (and back), etc. But other than that fairly narrow application, I can't think of any huge benefits of it. Anybody have some other useful applications?
For I in sub_record_type'range loop
My_vector(j to j + my_record.i'length) := my_record.i;
J := j + my_record.i'length + 1;
End loop;
</quote
I was thinking of using something like this in a resolution function to selectively iterate across a record:
<code>
/* same like bef ore. */
type t_cpu_bus is record
...
end record t_cpu_bus;
/* vector of records that needs to be resolved. */
type t_cpuBusVector is array(natural range <>) of t_cpu_bus;
/* the resolution function - just an idea, more work needed here. */
function resolveRecords(signal someRecordArray: t_cpuBusVector) return t_cpu_bus is
variable resolvedRecord: t_cpu_bus := (adr | dat => (others=>'0'), we | en => '1', others=>'-'); -- possible use of don't-cares for inputs here?
begin
/* Here we resolve between 2 records that drive the same signals. But, we need a more complete solution that iterates the resolution of N records.
*/
/* Loop across elements of record.
someRecordArray(0) = the record.
someRecordArr ay(0).i = one of the record's elements (assume an array type, can be array of std_logic, std_ulogic, bit. E.gs.: unsigned/signed, std_ulogic_vector, bit_vector).
(someRecordArray(0).i)(j) = one of the record's subelements (assume the subelement is std_ulogic).
*/
/* Here we are assuming the lengths and datatypes for both records are identical. We can implement extra checks / assertions here.
I use "someRecordArray(0)" though it may as well be "someRecordArray(1)".
Note: Accessing i from (someRecordArray(0).i) in the for-declaration may be illegal as of current version of the standard.
*/
for i in (someRecordArray(0).i)'range loop
/* Compare the sub-elements of each record type. Here, the sub-elements are concatenated, then compared. */
case? (someRecordArray(0).i)(j) & (someRecordArray(1).i)(j) is
when "--" => (resolvedRecord.i)(j) <= '-';
when "UX" | "XU" => (resolvedRecord.i)(j) <= 'X';
when "U-" => (resolvedRecord.i)(j) <= (someRecordArray(1).i)(j);
when "-U" => (resolvedRecord.i)(j) <= (someRecordArray(0).i)(j);
& nbsp; when "X-" | "-X" => (resolvedRecord.i)(j) <= 'X';
when "W-" | "-W" => (resolvedRecord.i)(j) <= 'W';
when "ZZ" => (resolvedRecord.i)(j) <= 'Z';
when "Z-" => (resolvedRecord.i)(j) <= (someRecordArray(1).i)(j);
when "-Z" => (resolvedRecord.i)(j) <= (someRecordArray(0).i)(j);
& nbsp;
when "10" | "01" => (resolvedRecord.i)(j) <= 'X';
when "HH" => (resolvedRecord.i)(j) <= 'H';
when "11" | "1H" | "H1" => (resolvedRecord.i)(j) <= '1';
when "00" | "0L" | "L0" => (resolvedRecord.i)(j) <= '0';
when others => (resolvedRecord.i)(j) <= 'X';
end case?;
j := j + someRecordArray(0).i'length + 1;
&nbs p; return resolvedRecord;
end function resolveRecords;
signal cpu_bus: resolveRecords t_cpu_bus;
</code>
This is an example that tries to resolve between 2 records I/Os. More work needed here to have a more generic function that resolves N number of records.
Also, this example tries to resolve _every_ element of the record. We could implement more conditionals within the resolution function to be more selective in resolving only those elements we need.
I have used some constructs that are not supported by the current version of the standard, such as accessing record subelements [using someRecordArray(0).i)(j)], which may need more rethinking.
Another question raised before by Ryan: how do we get the compiler to distinguish between a custom mode and a resolution function?
<quote>Regarding resolution functions, it doesn't make sense to hav e a user-defined mode for a type with a resolution function. I suggest that such a model be illegal.</quote>
Previously we had this:
bus_rio : m_master t_cpu_bus;
which is a port definition with a custom mode.
And now, to resolve between various records, we have this:
signal cpu_bus: resolveRecords t_cpu_bus;
As suggested before by Ryan, it's probably good to make illegal trying to associate a port or signal to both a resolution function and a custom mode. We should only be able to either associate a resolution function, or a custom mode to a port or signal, not both at the same time. Then it becomes clear and unambiguous to the compiler as to whether a mode association is required or a resolution function is required.
-daniel
-- Regards, &nb sp; Brent Hayhoe. Aftonroy Limited Telephone: +44 (0)20-8449-1852 135 Lancaster Road, New Barnet, Mobile: +44 (0)79-6647-2574 Herts., EN4 8AJ, U.K. Email: Brent.Hayhoe@Aftonroy.com<mailto:Brent.Hayhoe@Aftonroy.com> Registered Number: 1744190 England. Registered Office: 4th Floor, Imperial House, 15 Kingsway, London, WC2B 6UN, U.K.Received on Wed Jul 18 19:46:59 2012
This archive was generated by hypermail 2.1.8 : Wed Jul 18 2012 - 19:47:22 PDT