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
On 17 July 2012 21:05, Daniel Kho <daniel.kho@gmail.com> wrote:
> Yes, the "type mode" can be withdrawn.
>
> I'm fine with either "mode" or "port mode" for the mode definitions. Any
> terminology that is non-ambiguous is fine with me.
> I shortened your original "port mode" to just "mode" so that Brent's code
> becomes clearer (having a "port mode" encapsulated within a "port"
> definition is confusing):
>
>
> entity master is
> port (
> ...
> bus_rio : mode (
> ...
>
> ) t_cpu_bus
> );
> end entity master;
>
> In Brent's case:
> bus_rio : mode (
> ...
> ) t_cpu_bus;
>
> is equivalent to:
> bus_rio : m_master t_cpu_bus;
>
> Here, `mode(...)` = `m_master`, so both syntaxes can be used depending on
> user preference.
>
>
> RE:
>
> <quote>subtype t_cpu_bus_mosi is t_cpu_bus (adr to en); -- a record with
> adr, dat, we, en
>
> --or --
> subtype t_cpu_bus_miso is t_cpu_bus range sdt to err; -- a record with
> sdt, ack, err
> </quote>
>
> Perhaps it's a good idea to use the second option so as to be consistent
> with subtype range definitions:
>
> subtype t_cpu_bus_miso is t_cpu_bus range sdt to err; -- a record with
> sdt, ack, err
>
> -daniel
>
>
>
> On 17 July 2012 19:57, Jones, Andy D <andy.d.jones@lmco.com> wrote:
>
>> I think the enumerated type of modes (type mode) is no longer needed.
>> It is incomplete as soon as you define a new mode. It was suggested early
>> in association with an array-type definition of composite modes which I
>> believe was withdrawn.****
>>
>> ** **
>>
>> The syntax for a mode declaration is still in work. I used “port mode”
>> since mode is not a keyword but port already is. We need to ensure that the
>> new syntax is sufficiently identifiable but not mistaken for any existing
>> code. The less of the statement that has to be analyzed to do that, the
>> better (enables better diagnostic messages). Maybe “mode” by itself can
>> accomplish that?****
>>
>> ** **
>>
>> mode m_master of t_cpu_bus is (…****
>>
>> ** **
>>
>> --or—****
>>
>> ** **
>>
>> port mode m_master of t_cpu_bus is (…****
>>
>> ** **
>>
>> There has been some discussion about syntax for a non-all-inclusive
>> subtype of a record. Is a parenthesized range (like an array) sufficient?
>> Do we need a ‘.’ before the ‘(range)’? Do we use a subrange declaration
>> like that for an enumerated type, or like that of an array:****
>>
>> ** **
>>
>> subtype t_cpu_bus_mosi is t_cpu_bus (adr to en); -- a record with adr,
>> dat, we, en****
>>
>> ** **
>>
>> --or -- ****
>>
>>
>> subtype t_cpu_bus_miso is t_cpu_bus range sdt to err; -- a record with
>> sdt, ack, err
>>
>> ****
>>
>> Note that the whole issue of non-all-inclusive subtypes of records (and
>> implicit types of record element names) is only very narrowly associated
>> with composite modes. The only place where these intersect is in the
>> potential syntax for the composite mode declaration. ****
>>
>> ** **
>>
>> But there are MANY other issues that are impacted by non-all-inclusive
>> subtypes of records:****
>>
>> ** **
>>
>> 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;****
>>
>> ** **
>>
>> Since these are almost entirely different issues (composite modes and
>> non-all-inclusive record subtypes), I recommend we treat them entirely
>> separately.****
>>
>> ** **
>>
>> ** **
>>
>> *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 *Daniel Kho
>> *Sent:* Tuesday, July 17, 2012 3:36 AM
>> *To:* vhdl-200x@eda.org
>> *Subject:* Re: EXTERNAL: Re: [vhdl-200x] Directional records proposal****
>>
>> ** **
>>
>> Here's a summary of our discussion so far.
>>
>> /* Packaged definitions. */
>> /* Type definition */
>> type t_cpu_bus is record
>> adr : std_logic_vector(15 downto 0); --Address
>> dat : std_logic_vector(15 downto 0); --Data from master to slave
>> we : std_logic; --Write enable from master
>> en : std_logic; --Enable from master
>> sdt : std_logic_vector(15 downto 0); --Data from slave to master
>> ack : std_logic; --Acknowledge from slave
>> err : std_logic; --Error from slave
>> end record t_cpu_bus;
>>
>> subtype t_cpu_bus_mosi is t_cpu_bus (adr to en); -- a record with adr,
>> dat, we, en
>> subtype t_cpu_bus_miso is t_cpu_bus (sdt to err); -- a record with sdt,
>> ack, err
>>
>>
>>
>> type mode is (in,out,inout,buffer,linkage); --explicitly specify
>> enumerated type for valid values of mode. Not mandatory for implementation.
>> /* Andy and Daniel
>> Minor change to standard: allow specifying record ranges.
>> Both mode definitions can work well with each other. One uses
>> externally-declared subtype definitions using record
>> ranges (which is good for modularity), and the other uses record
>> ranges directly in the mode definitions.
>> */
>> /* Master Mode definition */
>> mode m_master of t_cpu_bus is (t_cpu_bus_mosi => out, others => in);
>> mode m_master of t_cpu_bus is (adr to en => out, others => in);
>> -- alternate definition without using subtype.
>>
>>
>> /* Slave Mode definition */
>> mode m_slave of t_cpu_bus is (t_cpu_bus_mosi => in, others => out);
>> mode m_slave of t_cpu_bus is (adr to en => in, others => out);
>> -- alternate definition
>>
>>
>> /* Monitor Mode definition */
>> mode m_monitor of t_cpu_bus is (others => in);
>> mode m_monitor of t_cpu_bus is (others => in); -- alternate
>> definition
>>
>>
>>
>> /* Alternate mode syntax. Choose either this or the above, not both (they
>> don't work well together). */
>> /* Ryan. */
>> mode m_master of t_cpu_bus is
>> adr, dat, we, en : out;
>> sdt, ack, err : in;
>> end mode m_master;
>>
>>
>>
>>
>> /* Entity declarations */
>>
>> /* This is the original shorthand method by Andy.
>> */
>> /* Master entity */
>> entity master is
>> port (
>> clk, rst : in std_logic;
>> bus_rio : m_master t_cpu_bus);
>> end entity;
>>
>>
>> /* Slave entity */
>> entity slave is
>> port (
>> clk, rst : in std_logic;
>> bus_rio : m_slave t_cpu_bus);
>> end entity;
>>
>> /* Monitor entity */
>> entity monitor is
>> port (
>> clk, rst : in std_logic;
>> bus_rio : m_monitor t_cpu_bus);
>> end entity;
>>
>>
>>
>>
>> /* Brent and Olof.
>> Alternate entity declarations with direct record I/O mappings.
>>
>> These instantiations should be equivalent to Andy's, except that you
>> do not need to specify the "named modes" m_master,
>> m_slave, and m_monitor.
>>
>> This syntax does not conflict with Andy's, so both can be specified
>> in the standard.
>> */
>> entity master is
>> port (
>> clk, rst : in std_logic;
>> bus_rio : mode (
>> adr : out std_logic_vector(15 downto 0);
>> dat : out std_logic_vector(15 downto 0);
>> we : out std_logic;
>> en : out std_logic;
>> sdt : in std_logic_vector(15 downto 0);
>> ack : in std_logic;
>> err : in std_logic
>> ) t_cpu_bus
>> );
>> end entity master;
>>
>>
>> entity slave is
>> port (
>> clk, rst : in std_logic;
>> bus_rio : mode (
>> adr : in std_logic_vector(15 downto 0);
>> dat : in std_logic_vector(15 downto 0);
>> we : in std_logic;
>> en : in std_logic;
>> sdt : out std_logic_vector(15 downto 0);
>> ack : out std_logic;
>> err : out std_logic
>> ) t_cpu_bus
>> );
>> end entity slave;
>>
>>
>>
>>
>> /* Top level */
>> signal cpu_bus : t_cpu_bus; -- TODO: (From Ryan): consider
>> cpu_bus as a resolved signal.
>>
>> i0_master : master
>> port map (
>> clk => clk,
>> rst => rst,
>> bus_rio => cpu_bus);
>>
>> /* Second master driving the same cpu_bus. */
>> i1_master : master
>> port map (
>> clk => clk,
>> rst => rst,
>> bus_rio => cpu_bus);
>>
>> i_slave : slave
>> port map (
>> clk => clk,
>> rst => rst,
>> bus_rio => cpu_bus);
>>
>> i_monitor : monitor
>> port map (
>> clk => clk,
>> rst => rst,
>> bus_rio => cpu_bus);
>>
>>
>>
>> Let me know if there is anything I've missed.
>>
>> -daniel
>>
>> ****
>>
>> On 16 July 2012 20:50, Jones, Andy D <andy.d.jones@lmco.com> wrote:****
>>
>> I think Brent’s proposal is an excellent implementation of an “anonymous”
>> port mode for a record, and in that role provides beneficial functionality.
>> ****
>>
>> ****
>>
>> The benefits to associating named port modes with types is to provide
>> encapsulation. A package could define the entire bus: the type(s), the
>> modes, functions, procedures, etc. Associating the mode with the type also
>> provides a unique name space (port mode master of cpu_bus is different from
>> port mode master of i2c_bus). ****
>>
>> ****
>>
>> The encapsulation also provides a way to conduct a bus interface across
>> intermediate levels of hierarchy without necessarily needing to know
>> anything about it at those levels, or change port maps when the bus
>> changes. ****
>>
>> ****
>>
>> This is the same advantage of using record types for generics today: one
>> can add or subtract information from the record type as the design evolves,
>> and intermediate levels just pass along whatever is in the conduit
>> transparently. If a lower level module needs a generic, add it to the
>> record definition, assign it at the top, and extract it at the leaf level:
>> done! This same ability could be available to signal and variable ports on
>> entities and procedures. ****
>>
>> ****
>>
>> ****
>>
>> *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 *Daniel Kho
>> *Sent:* Monday, July 16, 2012 6:59 AM
>> *To:* vhdl-200x@eda.org
>> *Subject:* EXTERNAL: Re: [vhdl-200x] Directional records proposal****
>>
>> ****
>>
>> Hi Brent, Olof,
>> Neat. I feel this is similar to Andy's proposal, only difference (other
>> than the "unconn" mode) is that the definitions are made within the
>> entities themselves, while in Andy's case, they are all defined using the
>> "port mode" structure outside of the entity definitions. Perhaps it's a
>> good idea to implement both style alternatives in the standard, so users
>> have the flexibility to choose whichever they prefer.
>>
>> Another thing mentioned by Ryan is that we need to consider resolution
>> functions (to take into consideration the scenario where there are multiple
>> drivers to the same nets/ports). I agree that changing any of the mode
>> syntax could possibly affect how resolution functions work and vice versa.
>>
>> <quote>... we *don't* want a resolution function for type t_cpu_bus. It
>> doesn't even make sense because only parts -- in fact different parts -- of
>> the record are driven by each entity. But we *do* want resolution
>> functions for the elements of t_cpu_bus.</quote
>>
>> Ryan, do you think perhaps it's still possible to have a resolution
>> function for the record type t_cpu_bus, but the function iteratively
>> resolves the elements of the type? This means that we still (iteratively
>> and selectively) resolve the elements of the t_cpu_bus type. And, perhaps
>> use matching conditionals (such as matching relational operators, etc.) to
>> resolve only those ports we need, and treat the rest as don't cares (or
>> unconnected)?
>> This idea just crossed my mind, but I haven't thought of a workable
>> solution yet, so I'm not completely sure if it's feasible.
>>
>> regards, daniel****
>>
>> On 16 July 2012 19:19, Olof Kindgren <olof.kindgren@orsoc.se> wrote:****
>>
>> 2012/7/15 Brent Hayhoe <Brent.Hayhoe@aftonroy.com>:****
>>
>> > It's really great to see so much interest in this topic. It's something
>> > that I had hoped would have made it into the 2008 revision as this
>> problem
>> > has been bugging me for a long time.
>> >
>> > I feared that it had been subsumed into the interface concept, which I
>> > believe in itself could be an excellent addition to introduce into
>> VHDL, but
>> > I believe the record I/O problem should be solved in its own right and
>> also
>> > not limited to just a master and slave port concepts.
>> >
>> > Forgive me if am I re-covering old ground, but I think the problem is
>> not
>> > with the record type itself, instead it resides within the port mode
>> > structure and can be solved by the addition of a new mode (which seems
>> to
>> > have been alluded to in some posts).
>> >
>> > I'd like to suggest looking at the problem from this different angle
>> and so
>> > given our record type definition:
>> >
>> > type cpu_bus_r is
>> > record
>> > adr_vl : std_logic_vector(15 downto 0); --Address
>> > dat_vl : std_logic_vector(15 downto 0); --Data from master to
>> > slave
>> > we_l : std_logic; --Write enable from
>> > master
>> > en_l : std_logic; --Enable from master
>> > sdt_vl : std_logic_vector(15 downto 0); --Data from slave to
>> > master
>> > ack_l : std_logic; --Acknowledge from
>> slave
>> > err_l : std_logic; --Error from slave
>> >
>> > end record cpu_bus_r;
>> >
>> > we need a new a new port mode of, let's say 'record' (being a kind of
>> > hierarchical mode):****
>>
>>
>> >
>> >
>> > entity master is
>> > port (****
>>
>> > clk_i : in std_logic;
>> > bus_r : record (
>> > adr_vl : out std_logic_vector(15 downto 0);
>> > dat_vl : out std_logic_vector(15 downto 0);
>> > we_l : out std_logic;
>> > en_l : out std_logic;
>> > sdt_vl : in std_logic_vector(15 downto 0);
>> > ack_l : in std_logic;
>> > err_l : in std_logic
>> > ) cpu_bus_r;
>> > rst_i : in std_logic
>> > );
>> > end entity master;****
>>
>>
>> >
>> >
>> > entity slave is
>> > port (****
>>
>> > clk_i : in std_logic;
>> > bus_rio : record (
>> > adr_vl : in std_logic_vector(15 downto 0);
>> > dat_vl : in std_logic_vector(15 downto 0);
>> > we_l : in std_logic;
>> > en_l : in std_logic;
>> > sdt_vl : out std_logic_vector(15 downto 0);
>> > ack_l : out std_logic;
>> > err_l : out std_logic
>> > ) cpu_bus_r;
>> > rst_i : in std_logic
>> > );
>> > end entity slave;
>> >
>> > which then leads to instantiations as shown:
>> >
>> > signal clk_s : std_logic;
>> > signal cpu_bus_rs : cpu_bus_r;
>> > signal rst_s : std_logic;
>> >
>> > master_inst : master
>> > port map (
>> > clk_i => clk_s,
>> > bus_rio => cpu_bus_rs,
>> > rst_i => rst_s
>> > );
>> >
>> > slave_inst : slave
>> > port map (
>> > clk_i => clk_s,
>> > bus_rio => cpu_bus_rs,
>> > rst_i => rst_s
>> > );
>> >
>> > I can imagine this may cause problems for compiler designers, but from a
>> > user perspective I think it will cover all problem areas.
>> >
>> > Functions could still use the existing format, as all ports by
>> definition
>> > are inputs and procedures would use the same new structure as entities
>> (with
>> > the 'record' sub-modes being limited to 'in', 'out' or 'inout').
>> >
>> > This does make the entity/component (and procedure) declarations more
>> > verbose, but the instantiations will be quite compact. It should also
>> allow
>> > recursive record types to be mapped.
>> >
>> > The instantiation mappings could still be expanded to individual element
>> > mappings (cf. existing record or array elements), but we could also
>> consider
>> > another new mode type to allow an unconnected mapping for a particular
>> > record element in an object that does not use that element.
>> >
>> > The open keyword will work as a mapping, but the object then has to
>> define
>> > an unused 'out' element to be instantiated as 'open'. A new sub-mode of
>> > unconnected would mean the port of that record would not have to be
>> assigned
>> > or read from within the object, but just defined in the declaration e.g.
>> >
>> > entity slave2 is
>> > port (
>> > clk_i : in std_logic;
>> > bus_rio : record (
>> > adr_vl : in std_logic_vector(15 downto 0);
>> > dat_vl : in std_logic_vector(15 downto 0);
>> > we_l : in std_logic;
>> > en_l : in std_logic;
>> > sdt_vl : out std_logic_vector(15 downto 0);
>> > ack_l : out std_logic;
>> > err_l : unconn std_logic
>> > ) cpu_bus_r;
>> > rst_i : in std_logic
>> > );
>> > end entity slave2;
>> >
>> > Let's see what you all think.
>> >
>> > Apologies for my verbosity and I hope I'm not talking complete hogwash!
>> >
>> >
>> > --
>> >
>> > 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.
>> >****
>>
>> This is an interesting idea. A bit too verbose compared to what I
>> originally had in mind, but it seems to get the job done.
>>
>> If we go down this route, I'm not sure we really need to introduce a
>> record in the port though. Wouldn't it just be sufficient with a dot
>> notation?
>>
>> Example:****
>>
>> entity slave2 is
>> port (
>> clk_i : in std_logic;****
>>
>> cpu_bus_r.adr_vl : in std_logic_vector(15 downto 0);
>> cpu_bus_r.dat_vl : in std_logic_vector(15 downto 0);
>> cpu_bus_r.we_l : in std_logic;
>> cpu_bus_r.en_l : in std_logic;
>> cpu_bus_r.sdt_vl : out std_logic_vector(15 downto 0);
>> cpu_bus_r.ack_l : out std_logic;
>> cpu_bus_r.err_l : unconn std_logic****
>>
>> rst_i : in std_logic
>> );
>> end entity slave2;
>>
>> ****
>>
>> --****
>>
>> Olof Kindgren
>> ______________________________________________
>> ORSoC
>> Website: www.orsoc.se
>> Email: olof.kindgren@orsoc.se
>> ______________________________________________
>> FPGA, ASIC, DSP - embedded SoC design****
>>
>>
>>
>
Received on Tue Jul 17 08:45:43 2012
This archive was generated by hypermail 2.1.8 : Tue Jul 17 2012 - 08:46:09 PDT