﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="thpdoc.xsl"?>
<page id="Lists" noauto = "1">
  <subsection>
	<p>Lists are one of the key features of THDL++. They allow making loops and <kw>generate</kw> statements for the cases when normal <kw>generate</kw> <kw>for</kw> won't work. This page describes such use cases and presents examples.</p>
	<p>All lists exist at compile-time only and are unrolled during VHDL generation. If you are looking for a way of managing lists of numbers in hardware, see <link>Core.Primitives.FIFO</link> and <link>Core.RAMs.Synchronous.SimpleRAM</link> entities from <link>corelib</link>.</p></subsection>
  <section name="Creating lists">
    The easiest way to declare a fixed list is to use a <kw>const</kw> declaration:
	<code>const any MyNumbers = (1, 2, 3, 4);</code>
    The <kw>any</kw> keyword means "no associated VHDL type" and should always be used for compile-constants that have no VHDL equivalents.<br/>
	You can easily concatenate lists:
	<code>const any MyNumbers2 = (MyNumbers, 5, 6);</code>
    You can also make functions that build lists:
	<code>any BuildList(int start, int end)
{
	list result = __list();
	for (int i = start; i le end; i++)
		result = (result, i);
	return result;
}
	
const list MyNumbers = BuildList(1, 8);</code>
	Please use the <kw>__list</kw> keyword to declare an empty list or list consisting of 1 element. Note that you will  need to explicitly use the <kw>__list</kw> keyword if you are passing an implicit list (without prior <kw>const</kw> declaration) as a function or template argument. E.g. you can include a FIFO filled with fixed numbers in your testbench by using this code:
	<code>Core.Primitives.ListFifo&lt;__list(1,2,3,4), 8&gt; fifo(
	clk = clk,
	reset = auto,
	DataPull = auto,
	DataPush = auto,
	DataOut = auto
);</code>
	Finally, there are several built-in functions returning lists: <kw>__ports</kw>, <kw>__attributes</kw>.
</section>
<section name="Accessing lists">
	The main use case for a list is the <kw>generate</kw> <kw>foreach</kw> statement. E.g.:
	<code>const any stages = (SquareInput, AddOne, AddTwo);
generate Instances foreach(any stage in stages)
{
	stage Inst(
		Input = auto,
		Output = auto
		);
}</code>
This will produce the following VHDL code:
<code>Instances_0_Inst : Square_Input
	port map (
		Input => Instances_0_thp_Inst_autosig_Input,
		Output => Instances_0_thp_Inst_autosig_Output
	);

Instances_1_Inst : Add_One
	port map (
		Input => Instances_1_thp_Inst_autosig_Input,
		Output => Instances_1_thp_Inst_autosig_Output
	);

Instances_2_Inst : Add_Two
	port map (
		Input => Instances_2_thp_Inst_autosig_Input,
		Output => Instances_2_thp_Inst_autosig_Output
	);
</code>
	Alternatively, you could use the <kw>generate</kw> <kw>for</kw> construct. The following code is equivalent to the previous example:
<code>const any stages = (SquareInput, AddOne, AddTwo);
generate Instances for(int i = 0; i lt sizeof(stages); i++)
{
	stages[i] Inst(
		Input = auto,
		Output = auto
		);
}</code>
	You can also access lists from the <kw>for</kw>/<kw>foreach</kw> loops:
<code>process testbench()
{
	const any values = (1, 2, 3, 4, 5);
	foreach (any val in values)
	{
		sig = val;
		wait(10ns);
	}
}</code>
</section>
	<section name="Remarks">
	<p>Note that you cannot declare global constants. Every constant should be declared inside an entity, class, namespace, process or function.</p>
	<p>Please also note that functions accepting lists as arguments will not be synthesized to VHDL. I.e. the following code won't compile:</p>
	<code>int sum_first(any lst, int index)
{
	int sum = 0;
	for (int i = 0; i lt sizeof(lst); i++)
	{
		sum += lst[i];
		if (i == (index - 1))
			return sum;
	}
	return sum;
}

process test (clk.rising)
{
	sig2 = sum_first(__list(1,2,3,4), sig1);
}
</code>
	<p>As VHDL does not have an equivalent of lists, compiling sum_first into VHDL will not be possible.</p>
	<p>On the other hand, the following code will compile:</p>
	<code>process test (clk.rising)
{
	const int sum = sum_first(__list(1,2,3,4), 3);
	sig2 = sum;
}</code>
	<p>As the call to sum_first does not depend on non-constant value (e.g. signal values), sum_first will be executed during compilation time and the VHDL code will look like that:</p>
	<code>test : process (clk) is
begin
	if rising_edge(clk) then
		sig2 &lt;= X"06";
	end if;
end process test;</code>
	<p>However, you still can compile a list-related function to VHDL if you make the list a template argument. In this case THDL++ compiler will generate a version of the function for this specific list embedding its contents into the code:</p>
	<code>template &lt;any lst&gt;int sum_first(int index)
{
	int sum = 0;
	for (int i = 0; i lt sizeof(lst); i++)
	{
		sum += lst[i];
		if (i == (index - 1))
			return sum;
	}
	return sum;
}

process test (clk.rising)
{
	sig2 = sum_first&lt;__list(1,2,3,4)&gt;(sig1);
}</code>
	<p>The generated VHDL function will look like that:</p>
	<code>function sum_first_list_1_2_3_4 (index: integer) return integer is
	variable sum : integer;
begin
	sum := 0;
	sum := (sum + 1);
	if (0 = (index - 1)) then
		return sum;
	end if;
	sum := (sum + 2);
	if (1 = (index - 1)) then
		return sum;
	end if;
	sum := (sum + 3);
	if (2 = (index - 1)) then
		return sum;
	end if;
	sum := (sum + 4);
	if (3 = (index - 1)) then
		return sum;
	end if;
	return sum;
end function sum_first_list_1_2_3_4;</code>	
  </section>
<seealso id="__list"/>
<seealso id="__decl"/>
<seealso id="__ports"/>
<seealso id="__attributes"/>
<seealso id="const"/>
<seealso id="for"/>
<seealso id="foreach"/>
<seealso id="generate"/>
</page>