This is an old revision of the document!


Alternate Buffer

We start with the previous definition of a templated buffer:

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   (i : N-1 : b[i].R = b[i+1].L;)
   b[0].L = L;
   b[N-1].R = R;
}

In this version, we used the = operation to connect channels to each other. There are other ways this can be done, and here we describe the syntax for a number of different options that achieve the same result in terms of creating a FIFO.

Using auxillary variables

We can create an array of size N-1 to correspond to the internal channels between the N buffers.

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   chan(int) ch[N-1];
   (i : N-1 : b[i].R = ch[i];)
   (i : N-1 : b[i+1].L = ch[i];)
   b[0].L = L;
   b[N-1].R = R;
}

This can be re-written as follows:

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   chan(int) ch[N-1];
   (i : 1 .. N-1 : b[i].L = ch[i-1]; b[i].R = ch[i]; )
   b[0].L = L; b[0].R = ch[0];
   b[N-1].L = ch[N-2]; b[N-1].R = R;
}

Another version of this is the following:

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   chan(int) ch[N-1];
   (i : N :  
      [ i = 0 ->    b[i].L = L; b[i].R = ch[i];
     [] i = N-1 ->  b[i].L = ch[i-1]; b[i].R = R;
     [] else -> b[i].L = ch[i-1]; b[i].R = ch[i];
      ]
   )
}

Using port connections directly

Instead of using the dot notation to explicitly connect ports, we observe that each set of connections operates on the same instance b[i]. This can be written as follows:

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   chan(int) ch[N-1];
   (i : N :  
      [ i = 0 ->    b[i](L,ch[i]);
     [] i = N-1 ->  b[i](ch[i-1],R);
     [] else -> b[i](ch[i-1], ch[i]);
      ]
   )
}

This approach relies on the order of ports being known; if instead it is preferable to connect ports by name, the following syntax is also valid.

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   one_place_buffer b[N];
   chan(int) ch[N-1];
   (i : N :  
      [ i = 0 ->    b[i](.L=L, .R=ch[i]);
     [] i = N-1 ->  b[i](.L=ch[i-1], .R=R);
     [] else -> b[i](.L=ch[i-1], .R=ch[i]);
      ]
   )
}

Dynamic creation of buffers

ACT also permits instances to be created one at a time. So rather than declaring a single buffer array of size N, we can create it one segment of the array at a time.

template<pint N>
defproc buffer (chan?(int) L; chan!(int) R)
{
   chan(int) ch[N-1];
   (i : N :  
       one_place_buffer b[i..i];
      [ i = 0 ->    b[i](.L=L, .R=ch[i]);
     [] i = N-1 ->  b[i](.L=ch[i-1], .R=R);
     [] else -> b[i](.L=ch[i-1], .R=ch[i]);
      ]
   )
}

Each b[i..i] slice augments the array b.