Re: [vhdl-200x] Record slices (branched from Directional records proposal)

From: Daniel Kho <daniel.kho@gmail.com>
Date: Wed Jul 18 2012 - 19:57:56 PDT

Correction (add extra check in if-condition).

On 19 July 2012 10:53, Daniel Kho <daniel.kho@gmail.com> wrote:

> <quote>Still, VHDL /= std_ulogic</quote>
> Yes, that's why I mentioned the use of type casting and type conversions
> to reduce them to std_ulogics.
> For scalar types that make sense as a bus signal, for example, integers,
> we can use conversion functions to reduce them to bits.
> Jim, I agree other types such as "time" and "real" should not be reduced
> to bits, so perhaps more checks should be done to avoid this problem? We
> should only resolve signals that make sense anyway.
>
> Types "time" and "real" etc. may still be part of the record, but they are
> just not resolved.
> Perhaps adding an extra check to the condition might do the trick?
> if field'mode = out and isBusType(field) then
>
> <quote>you're confusing resolution functions and modes.</quote>
> Perhaps not.
> But after reading my own post again, I noticed there was a typo. The
> output bus of the entity should be a resolved signal, like this:
>
> entity master is port(
>
> clk, rst : in std_logic;
>
> bus_rio : resolveObjects misc
>
> );
>
> Then in the architecture of this entity, we could have the following
> assignment:
> bus_rio <= obj;
>
> <quote>Resolution functions are associated with types (e.g. std_logic vs.
> std_ulogic), not with the port mode.</quote>
> I applied the resolution function to a signal with a datatype. I was
> associating the resolution function with the "misc" type. It's output is of
> the "misc" record type, and the input to this function is an array of the
> "misc" type. I did not associate the resolution function with the port mode.
> But one thing I did was to use the resolution function to _check_ for the
> modes of the each field element, and resolve only those with the "out" mode.
>
> <quote>They are invoked to resolve multiple drivers for the same signal
> </quote>
> That was exactly what I was trying to accomplish with that resolution
> function.
>
> With the above changes, we now have the following:
>
>
> -- record containing fields with disparate types
>
> type misc is record
>
> int : integer;
>
> float : real;
>
> snum : signed(7 downto 0);
>
> end record misc;
>
>
> type misc_vector is array(natural range<>) of misc;
>
> mode m_mode of misc is (snum => out, others => in);
>
>
>
> function resolveObjects(signal misc_vct: in misc_vector) return misc is
>
> -- loop over fields and resolve elements with multiple drivers.
>
> for field in misc'fields loop
>
> --resolve only fields that have an "out" mode/direction (only "out"s
> will cause the multiple driver problem).
>
> --Inputs are ignored since they are fanned out.
>
> if field'mode = out and isBusType(field) then
>
> ... -- multiple driver outputs for obj.snum will be resolved.
>
> end if;
>
> end loop;
>
> end function resolveObjects;
>
>
>
> --example instance
>
> entity master is port(
>
> clk, rst : in std_logic;
>
> bus_rio : resolveObjects misc
>
> );
>
> end entity master;
>
>
> architecture rtl of master is
>
> --obj is driven from multiple processes, or structurally-connected
> blocks.
>
> signal obj : resolveObjects misc;
>
> begin
>
> bus_rio <= obj;
>
> end architecture rtl;
>
>
> -daniel
>
>
>
> On 19 July 2012 08:13, <ryan.w.hinton@l-3com.com> wrote:
>
>> Yes, there is a problem. In the VHDL *language*, your assumption is a
>> non-starter. Granted, I expect a synthesis tool to reduce everything to
>> bits. But there is no such requirement in the language. So I can't get
>> past your first sentence.****
>>
>> ** **
>>
>> Sorry for the abruptness, but this is a sore spot for me. VHDL describes
>> hardware, but the language itself is not hardware. It's a full, rich
>> programming language with all the features necessary to implement any
>> algorithm. Of course different languages are better for different tasks.
>> Still, VHDL /= std_ulogic.****
>>
>> ** **
>>
>> On a side-note, you're confusing resolution functions and modes.
>> Resolution functions are associated with types (e.g. std_logic vs.
>> std_ulogic), not with the port mode. They are invoked to resolve multiple
>> drivers for the same signal -- including e.g. multiple processes in the
>> same entity, not just on ports.****
>>
>> ** **
>>
>> - Ryan****
>>
>> ** **
>>
>> *From:* owner-vhdl-200x@eda.org [mailto:owner-vhdl-200x@eda.org] *On
>> Behalf Of *Daniel Kho
>> *Sent:* Wednesday, July 18, 2012 2:03 PM
>> *To:* vhdl-200x@eda.org
>> *Subject:* Re: [vhdl-200x] Record slices (branched from Directional
>> records proposal)****
>>
>> ** **
>>
>> <quote>...Each field can have a different data type...</quote>
>> Yes, but let's assume everything resolves down to std_ulogic at the
>> finest element level, so we only need to deal with vectors of std_ulogics,
>> or matrices of std_ulogics, etc.
>> For example, (un)signed is a vector of std_ulogic, and for other vector
>> types, type conversions may be needed, as in the case of bit_vectors or
>> boolean_vectors for example. For scalar types (integer, real, etc.), we
>> could use conversion functions to convert to vectors of std_ulogics.
>>
>> Ryan, would this work for you in the case of resolution functions?
>> From your example, say we have the signal "obj" driven by two different
>> processes/blocks. Assume only the "snum" field is being driven by both
>> processes, and "int" and "float" are inputs to both blocks (so they are not
>> being driven).
>>
>>
>> type misc_vector is array(natural range<>) of misc;
>>
>> -- object of this type****
>>
>> signal obj : resolveObjects misc;****
>>
>> mode m_mode of misc is (snum => out, others => in);****
>>
>> ****
>>
>> ...****
>>
>> function resolveObjects(signal misc_vct: in misc_vector) return misc is*
>> ***
>>
>> -- loop over fields and resolve elements with multiple drivers.****
>>
>> for field in misc'fields loop****
>>
>> --resolve only fields that have an "out" mode/direction (only "out"s
>> will cause the multiple driver problem).****
>>
>> --Inputs are ignored since they are fanned out.****
>>
>> if field'mode = out then****
>>
>> ... -- multiple driver outputs for obj.snum will be resolved.***
>> *
>>
>> end if;****
>>
>> end loop;****
>>
>> end function resolveObjects;****
>>
>> ** **
>>
>> --example instance****
>>
>> entity master is port(****
>>
>> clk, rst : in std_logic;****
>>
>> bus_rio : m_mode misc****
>>
>> );****
>>
>> end entity master;****
>>
>> ** **
>>
>>
>> Any problems with doing something like this?
>>
>> regards, daniel
>>
>> ****
>>
>> On 19 July 2012 01:25, <ryan.w.hinton@l-3com.com> wrote:****
>>
>> 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;****
>>
>> ****
>>
>> -- loop 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()
>> subprograms 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) of 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] *On
>> Behalf Of *Peter Flake
>> *Sent:* Wednesday, July 18, 2012 8:31 AM
>> *To:* 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] *On
>> Behalf Of *Huffman, Nathanael D (GE Healthcare)
>> *Sent:* 17 July 2012 23:02
>> *To:* 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<owner-vhdl-200x@eda.org>]
>> *On Behalf Of *Brent Hayhoe
>> *Sent:* Tuesday, July 17, 2012 4:50 PM****
>>
>>
>> *To:* 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 iterate 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 before. */
>> 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.
>> someRecordArray(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);
>>
>> 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);
>>
>> 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;
>> 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 have 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,****
>>
>> ****
>>
>> 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****
>>
>> ****
>>
>> Registered Number: 1744190 England.****
>>
>> Registered Office:****
>>
>> ****
>>
>> 4th Floor, Imperial House,****
>>
>> 15 Kingsway,****
>>
>> London, WC2B 6UN, U.K.****
>>
>>
>>
>
Received on Wed Jul 18 19:58:21 2012

This archive was generated by hypermail 2.1.8 : Wed Jul 18 2012 - 19:58:24 PDT