Array Type Generics


Proposal Information

  • Who Updates: RyanHinton
  • Date Proposed: 2013-05-02
  • Date Last Updated: 2013-05-02
  • Priority:
  • Complexity:
  • Focus: General Language

Summary

Type generics allow passing data of arbitrary types through an entity or subprogram. A classic example is a generic 2-way mux component. However, often two types are involved where the second type is an array of the first type. An example is an N-way mux component. This proposal allows annotating (and requiring) a generic type to be an array of another generic type.

Requirements

Allow a type generic to be annotated as being an array of another generic type. See #Use_cases for syntax.

Related Issues: None = General

Competing Issues: None at this time

Use cases

N-way mux

Consider an N-way mux component.

entity mux
  generic (
    type ELEM;
    type ARR is array (integer) of ELEM);
  port (
    inputs : in  ARR;
    select : in  integer;
    muxed  : out ELEM);
end entity;

The ARR type generic declaration indicates that the index type is integer and the element type is ELEM. We could allow a full subtype indication, but it probably isn't necessary. I can use this component in a variety of settings.

  • ELEM => time     
    and
    ARR => time_vector
  • ELEM => signed 
    and
    ARR => signed_vector
  • ELEM => real 
    and
    ARR => real_vector
  • ELEM => std_logic
    and
    ARR => std_logic_vector

Inner product

Another example is an inner product, a key operation in an FIR filter (and lots of other settings).

entity inner_product
  generic (
    type ELEM;
    type ARR is array (integer) of ELEM;
    ZERO : ELEM;
    function "*"(a,b : ELEM) return ELEM is <>;
    function "+"(a,b : ELEM) return ELEM is <>);
  port (
    left  : in  ARR;
    right : in  ARR;
    iprod : out ELEM);
end entity;

architecture generic of inner_product is
begin
  process(all) is
    variable tmp : ELEM;
  begin
    tmp := ZERO;
    for idx in left'range loop
      tmp := tmp + left(idx) * right(idx);
    end loop;
    iprod <= tmp;
    -- this only works if they have identical ranges; it's easy to extend to 
    -- different ranges as long as both are ascending or descending, which can 
    -- be guaranteed with an alias
  end process;
end architecture;

This inner product component works equally well for any numeric type.

  • ELEM => integer 
    and
    ARR => integer_vector
  • ELEM => real 
    and
    ARR => real_vector
  • ELEM => complex 
    and
    ARR => complex_vector
  • ELEM => signed 
    and
    ARR => signed_vector
  • ELEM => sfixed 
    and
    ARR => sfixed_vector

(Some of these vector types are not defined in the current standard, but they're obvious.) Pipelining the calculation is left as an exercise for the designer. The point is that without special getter functions, this would not be possible.

Serial to parallel

This case shows using the array as an L-value, which isn't possible using subprograms.

entity serial_to_parallel
  generic (
    type ELEM;
    type ARR is array (integer) of ELEM);
  port (
    serial       : in  ELEM;
    parallel     : out ARR;
    parallel_stb : out std_logic;
    clk          : in  std_logic);
end entity;

architecture generic of serial_to_parallel is
begin
  process(clk) is
    variable collect : parallel'subtype;
    variable pos     : parallel'range := parallel'low;
    --BUG: inserts values right-to-left for descending ranges
  begin
    if rising_edge(clk) then
      -- CANNOT DO THIS directly, and indirectly only with major headache 
      -- without this proposal
      collect(pos) := serial;

      parallel_stb <= '0';
      if pos = parallel'high then
        pos          := parallel'low;
        parallel_stb <= '1';
        parallel     <= collect;
      else
        pos := pos + 1;
      end if;
    end if;
  end process;
end architecture;

Variations

Generic index

We could also allow the array index to come from a type generic.

entity mux
  generic (
    type ELEM;
    type INDEX;
    type ARR is array (INDEX) of ELEM;
...

RyanHinton can't come up with a good use case for this, but it would be nice to not preclude the capability if it's easy to specify and implement. (RyanHinton: implementors seem to pick and choose which features to implement according to their resources and perceived importance of various features. So if allowing the index to be a type generic is particularly hard and/or rare, they will simply postpone implementation. In other words, the committee can specify what it wants, and the cost/benefit tradeoff will determine if/when it is implemented.)

No index specified

We could probably get away without specifying the index at all. Especially if we add a 'index attribute to array types to get the index subtype. But in most cases we can just use attributes on the object of interest. These uses break down if the array type of interest has more than one index, but the #Generic_index case can't handle this seamlessly, either.

entity mux
  generic (
    type ELEM;
    type INDEX;
    type ARR is array of ELEM;
...

Comments

Peter's original proposal had provisions for marking items as arrays. It also had a sense of numeric, however, I don't remember there being a way to allow types such as unsigned, and signed to be designated as a numeric. This is part of the reason I added a proposal for abstract packages. -- JimLewis - 2013-05-02

ADA has already solved this issue: https://en.wikibooks.org/wiki/Ada_Programming/Generics#Generic_formal_types -- LievenLemiengre - 2016-04-22

Arguments FOR

Arguments AGAINST

-- KevinJennings - 2013-05-09

Since the type is defined within the entity, how does the user of the entity define a signal of the correct type? For the N-way mux example, there would have to be an array of the proper type hooked up...since the array type is defined locally to the entity, it would not be visible. That's why, in today's world, one would define these things in a package which would then be used both by the N-way mux and the code that instantiates the N-way mux. Am I missing something?

[Main.RyanHinton - 2013-06-18] The array type is not defined in the entity. What looks like an array type declaration is merely specifying that an array type with some features is expected as a generic. I like the similarity to an array type declaration because it's familiar. But you can't decalre a new type in an interface list, so there shouldn't be any ambiguity.

--Main.CliffordWalinsky - 2013-11-13

I agree with KevenJennings -- the appropriate abstraction to use in the generic list for the inner product example is an interface package. Generic packages can define multiple types and subtypes dependent on generic types.

Supporters

-- RyanHinton - 2013-05-02

-- Brent Hayhoe -2013-15-02

-- JimLewis - 2014-12-04

-- MortenZilmer - 2015-01-21

-- PatrickLehmann - 2016-12-30

Add your signature here to indicate support for this proposal.

Topic revision: r11 - 2020-02-17 - 15:34:26 - JimLewis
 
Copyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback