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

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

<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 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:54:23 2012

This archive was generated by hypermail 2.1.8 : Wed Jul 18 2012 - 19:54:25 PDT