Mon Apr 8 12:43:46 EDT 2013

Delay lines

Delay lines are special in that they don't fit the state picture very

Delay lines can be stored head-to-tail which makes addressing them
more straightforward, but they reduce locality in the case of small
delay lines.

Anyways, implementation can be optimized later.  The specification is
as follows:

- A delay line has a type: its length
- Otherwise it behaves as a function taking an integer index.


- Where to solve bounds checking?  It's probably best to keep the
  implementation as simple as possible, meaning to solve bounds
  checking in the DSP side, and just retun undefined value for
  out-of-bounds (but not crash!).  This points to a big shared 2^n

I'm having a hard time representing this without having an
implementation in mind, so for now I'm assuming :
- One global delay memory state
- p_delay() passes offset in this state

p_delay() is only for reading..  Maybe this can somehow be captured in
the existing state mechanism.

This would need a modification from s->s to (D s)->s.

Where to put the type annotation?  Since there is only one write
point, it seems best this is done there.  There might be multiple read

Using state, the following

(define (test-delay (dl) (x))
  (let ((sum (+ x 
                (dl-read dl 1)
                (dl-read dl 2)
                (dl-read dl 3))))
     (dl-update 10 sum)

translates to:

struct proc_si {
	float r2[10];
struct proc_so {
	float r10[10];

		float r0 = p_copy(t);
		float r1 = p_copy(t_endx);
		float r3 = p_delay(si->r2, 1.0);
		float r4 = p_delay(si->r2, 2.0);
		float r5 = p_delay(si->r2, 3.0);
		float r6 = p_add(r4, r5);
		float r7 = p_add(r3, r6);
		float r8 = p_add(param->x, r7);
		float r9 = p_copy_dl(r8);
		so->r10 = p_copy(r9);
		out->r11[t] = p_copy(r8);

which would work for the p_delay operatior, I.e. it could be something like:

#define p_delay(line, index) line[(offset + index) % length(line)]

where length() is a sizeof() style element counter, and offset is the
current delay line offset stored somewhere.  this could be a global
counter shared by all delay lines.  if the % is power-of-two this
should be straightforward.

the trouble is at the write point.  somehow the type needs to be
extended to indicate that this is not a normal array, but a single
write update.  also, the delay line memory needs to be excluded from
the double buffering scheme.

maybe what is needed is an annotation for "sample memory" or just
arrays that can be indexed and written to by the DSP loop.

it requires a bit of a cleanup for the type system.

Essentially, it needs a type-specific implementation of
single-assingment binding.

Note: keeping SSA semantics is probably a good idea.  Trouble is
really the output copying that gets in the way.

What this means is that `dl-update' is really like 'cons'.  Because of
functional semantics, the input line needs to be mentioned explicitly.
It looks as if there is more freedom this way (i.e. returning a consed
delay line in another state output than the input)

I removed the state copying, which does give a primitive expression
which has all the info (binding + full functional constructor) in one

		so->r9 = p_delay_update(r8, si->r2);

- fix type system to distinguish Array from Delay