Jump to content


Defining Circular Buffer


  • You cannot reply to this topic
2 replies to this topic

#1 naeemkazmi

    Newbie

  • Members
  • Pip
  • 2 posts

Posted 10 June 2009 - 12:44 AM

What will be the best way to define a circular buffer, consist of constant values?

Should I use stream (Does stream allow reading and writing at same time?? That what we need in circular buffer, reading one value and shift all values.)
OR
Should I use Array of registers? (Is it possible to define an array of registers in ImpulseC??)
OR
I have to use simple array like C?

Your suggestions will be appreciated. smile.gif

Thanks

#2 Jonathan

    Member

  • Members
  • PipPip
  • 25 posts

Posted 10 June 2009 - 08:08 AM

QUOTE (naeemkazmi @ Jun 10 2009, 04:44 AM) <{POST_SNAPBACK}>
What will be the best way to define a circular buffer, consist of constant values?

Should I use stream (Does stream allow reading and writing at same time?? That what we need in circular buffer, reading one value and shift all values.)
OR
Should I use Array of registers? (Is it possible to define an array of registers in ImpulseC??)
OR
I have to use simple array like C?

Your suggestions will be appreciated. :)

Thanks


Take what I say with a grain of salt - I'm learning Impulse C as well - and in fact I'm really mostly answering to make sure I understand Impulse C (we'll see when someone else answers if I'm right - I.E. please comment heavily on even the most marginal error in my explanation, please!)

It is most efficent to use arrays when you index them using a constant - it allows Impulse C to distribute each element of the array over different memory blocks allowing simultanous reads and writes to all members of the array. To do this with a circular buffer WITHIN a process, you should be able to do the following:

char buffer[N]; // Note that N must be a constant value for this to be efficient
int i;
char read_character, write_character;
#pragma CO NONRECURSIVE buffer // Only assert this if no buffer[i] value will ever depend on a buffer[i-1] value, else the compiled code will work incorrectly

//... code //...
read_character = buffer[0];
for ( i = 0; i < N - 1; i++ ) {
#pragma CO UNROLL
buffer[i] = buffer[i+1];
}
buffer[N] = write_character;

// Note: this must be compiled with the scalarize array variables option. According to the docs this will try and make buffer into a series of registers, but I thought I had read elsewhere that this really distributed arrays over multiple memory blocks allowing parallel reads/writes to the array. I suspect what it's really doing is just replacing each instance of buffer[i] with buffer_i, and letting the compiler figure out if it should be a register or memory location. Either way it only works if the index is a constant.

This may SEEM inefficent from a normal C perspective, copying the entire buffer down one every time you want to read and write from it, but the entire for loop happens in 1 clock cycle (less if buffer is implemented as registers?), where as if you tried to rotate the index instead of the buffer then you could not read and write simultanously because both the beginning and end of the circular buffer would be in the same memory block (and, also, I think it takes two cycles to index an array in memory and then read or write from it - I'm not certain on this point though so I would love some reassurance or a correction).

Now, if your circular buffer is used between two processes, then you must use a stream (besides the data path, it has several signals that synchronize the loading and offloading between two otherwise asynchronous processes). However, when local to a process there's no need to do so. Just be careful about one thing if you use the array instead of a stream - fill it with data the first time or you'll be getting garbage values for the first few cycles.

#3 RalphBodenner

    Advanced Member

  • Admin
  • PipPipPip
  • 348 posts

Posted 10 June 2009 - 10:27 AM

Thanks for taking the time to help another user, Jonathan smile.gif I'll offer a few clarifications of your explanation:

QUOTE (Jonathan @ Jun 10 2009, 09:08 AM) <{POST_SNAPBACK}>
It is most efficent to use arrays when you index them using a constant - it allows Impulse C to distribute each element of the array over different memory blocks allowing simultanous reads and writes to all members of the array.

Yes, this is mostly right: indices that can be determined at compile-time can result in better performance. The Impulse C compiler can scalarize an array under certain conditions, turning what would normally be a block RAM (which has at most two ports and can thus only access two elements in parallel) into registers (your "memory blocks"), which can all be read in parallel.

QUOTE (Jonathan @ Jun 10 2009, 09:08 AM) <{POST_SNAPBACK}>
...(and, also, I think it takes two cycles to index an array in memory and then read or write from it - I'm not certain on this point though so I would love some reassurance or a correction).

Indexing and reading/writing an array can happen in a single clock.

Ralph Bodenner
Impulse Accelerated Technologies, Inc.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users