X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2Flib%2Fspu%2FFifo.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2Flib%2Fspu%2FFifo.cpp;h=959b70f1a800f33e7ffe131f7f260a3cf7c4bce1;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/cell/lib/spu/Fifo.cpp b/dol/src/dol/visitor/cell/lib/spu/Fifo.cpp new file mode 100644 index 0000000..959b70f --- /dev/null +++ b/dol/src/dol/visitor/cell/lib/spu/Fifo.cpp @@ -0,0 +1,182 @@ +#include "Fifo.h" + +/** + * + */ +Fifo::Fifo(unsigned size = 18) { + //except at the beginning, _head and _tail must never overlap, + //otherwise one does not know whether the buffer is full or + //empty. to have nevertheless a buffer with the given capacity, + //a buffer with one more element is allocated. + + _size = size; + _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR); + if(!_buffer) { + fprintf(stderr,"[FIFO] Memory allocation failure\n"); + exit(-1); + } + _pos = 0; + _tail = 0; + _blocked = 0; + + _inTail = 0; + _activeDMA = false; +} + +/** + * + */ +Fifo::~Fifo() { + if (_buffer) { + _free_align(_buffer); + } + _buffer = 0; + _pos = 0; + _tail = 0; +} + +/** + * + */ +unsigned Fifo::read(void *destination, unsigned len) { + + char* buffer = (char*) destination; + unsigned read = (len <= used() ? len : used()); + + if (_tail + read < _size) { + memcpy(buffer, _buffer + _tail, read); + } else { + memcpy(buffer, _buffer + _tail, _size - _tail); + memcpy(buffer + _size - _tail, _buffer, read - _size + _tail); + } + + _tail = ((unsigned) (_tail + read) % _size); + _pos -= read; + return read; +} + +/** + * + */ +unsigned Fifo::write(const void *source, unsigned len) { + + char* buffer = (char*) source; + unsigned write = (len <= unused() ? len : unused()); + unsigned head = (_tail + _pos) % _size; + + if (head + write < _size) { + memcpy(_buffer + head, buffer, write); + } else { + memcpy(_buffer + head, buffer, _size - head); + memcpy(_buffer, buffer + _size - head, write - _size + head); + } + + _pos += write; + return write; +} + +/** + * Size of this fifo + */ +unsigned Fifo::size() const { + return (_size); +} + +/** + * How many bytes is currently free in the buffer + */ +unsigned Fifo::unused() const { + return (_size) - used(); +} + +/** + * How many data are currently stored in the fifo + */ +unsigned Fifo::used() const { + return _pos; +} + +/* + * Get the pointer to the start of the queue + */ +char *Fifo::getQueuePointer() { + return _buffer; +} + +/* + * Has completed a dma read process, i.e. has read out of the queue + */ +void Fifo::dmaRead(unsigned len) { + _activeDMA = false; + + if (len == 0) { + _blocked = BLOCKED_MAX_NR; + } else { + _tail = ((unsigned) (_tail + len) % _size); + _pos -= len; + } +} + +/* + * Start a DMA request, returns the current space one have + */ +unsigned Fifo::dmaStart() { + _activeDMA = true; + + if (_tail + _pos > _size) { + return _size - _tail; + } else { + return _pos; + } +} + +/* + * Is allowed to start a dma request + */ +bool Fifo::dmaAllowed() { + if (_blocked > 0) { + _blocked--; + return false; + } else { + return !_activeDMA; + } +} + +/** + * Test the implementation + */ +/* + int main() { + std::cout.width(5); + Fifo *myFifo = new Fifo(); + for (int j = 0; j < 3; j++) { + for (int i = 0; i < 6; i++) { + std::cout << "write " << i << " to Fifo. "; + int write = myFifo->write(&i, sizeof(int)); + printf(" %d ", write); + if (write == sizeof(int)) { + std::cout << "used: " << std::setw(2) << myFifo->used() + << ", unused: " << std::setw(2) << myFifo->unused() + << ", size: " << std::setw(2) << myFifo->size() + << std::endl; + } else { + std::cout << std::endl; + } + } + for (int i = 0; i < 6; i++) { + int value; + int read = myFifo->read(&value, sizeof(int)); + printf(" %d ", read); + if (read == sizeof(int)) { + std::cout << "read " << value << " from Fifo "; + std::cout << "used: " << std::setw(2) << myFifo->used() + << ", unused: " << std::setw(2) << myFifo->unused() + << ", size: " << std::setw(2) << myFifo->size() + << std::endl; + } + } + } + delete myFifo; + return 0; + } + */