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.