X-Git-Url: http://sraa.de/git/?a=blobdiff_plain;f=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2Flib%2Fppu%2FWindowedFifo.cpp;fp=dol%2Fsrc%2Fdol%2Fvisitor%2Fcell%2Flib%2Fppu%2FWindowedFifo.cpp;h=16e09ba1aa4b3c38bf245f3f8c3d5d354d3dcce1;hb=8c411cf24ed0eb889191aaeafd8fa1e69081df42;hp=0000000000000000000000000000000000000000;hpb=dea7a4fb1ed110d3ce6e6d9255103d724bd66c0e;p=jump.git diff --git a/dol/src/dol/visitor/cell/lib/ppu/WindowedFifo.cpp b/dol/src/dol/visitor/cell/lib/ppu/WindowedFifo.cpp new file mode 100644 index 0000000..16e09ba --- /dev/null +++ b/dol/src/dol/visitor/cell/lib/ppu/WindowedFifo.cpp @@ -0,0 +1,223 @@ +#include "WindowedFifo.h" + +/** + * + */ +WindowedFifo::WindowedFifo(unsigned size = 20) { + //std::cout << "Create WindowedFifo." << std::endl; + _size = size; + _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR); + if(!_buffer) { + fprintf(stderr,"[WFIFO] Memory allocation failure\n"); + exit(-1); + } + + _head = 0; + _tail = 0; + + _headRoom = 0; + _tailRoom = 0; + _use = 0; + _blocked = 0; + + _isHeadReserved = false; + _isTailReserved = false; + _activeDMA = false; +} + +/** + * + */ +WindowedFifo::~WindowedFifo() { + if (_buffer) { + _free_align(_buffer); + } + _buffer = 0; + _head = 0; + _tail = 0; + _use = 0; +} + +/** + * + */ +unsigned WindowedFifo::reserve(void** dest, unsigned len) { + char** destination = (char**) dest; + //std::cout << "Attempt to reserve " << len << " bytes." << std::endl; + + //can only reserve one piece at a time + if (_isHeadReserved) { + *destination = 0; + return 0; + } + + //reserve at most as much memory as still available in the buffer + unsigned write = (len <= _size - _use ? len : _size - _use); + + if (write > 0) { + //if wrap-around in buffer: return only buffer for the + //contiguous buffer space + if (_head + write > _size) { + write = _size - _head; + } + + _headRoom = (_head + write) == _size ? 0 : _head + write; + *destination = &(_buffer[_head]); + _isHeadReserved = true; + } + + //std::cout << "Reserved " << write << " bytes." << std::endl; + _writeReserve = write; + return write; +} + +/** + * + */ +void WindowedFifo::release() { + if (_isHeadReserved) { + //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl; + _head = _headRoom; + _use += _writeReserve; + _isHeadReserved = false; + } +} + +/** + * + */ +unsigned WindowedFifo::capture(void **dest, unsigned len) { + char** destination = (char**) dest; + //std::cout << "Attempt to capture " << len << " bytes." << std::endl; + + if (_isTailReserved) { + //std::cout << "Only one attempt to capture allowed." << std::endl; + *destination = 0; + return 0; + } + + //capture at most as much data as available in the buffer + unsigned read = (len <= _use ? len : _use); + + if (read > 0) { + //if wrap-around in buffer: return only buffer for the + //conntiguous buffer space + if (_tail + read > _size) { + read = _size - _tail; + } + + _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read; + *destination = &(_buffer[_tail]); + _isTailReserved = true; + } + + //std::cout << "Captured " << read << " bytes." << std::endl; + _readReserve = read; + return read; +} + +/** + * + */ +void WindowedFifo::consume() { + if (_isTailReserved) { + //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl; + _tail = _tailRoom; + _use -= _readReserve; + _isTailReserved = false; + } +} + +/** + * + */ +unsigned WindowedFifo::size() const { + return _size; +} + +/** + * + */ +unsigned WindowedFifo::unused() const { + return _size - _use; +} + +/** + * + */ +unsigned WindowedFifo::used() const { + return _use; +} + +/* + * Get the pointer to the start of the queue + */ +char *WindowedFifo::getQueuePointer() { + return _buffer; +} + +/* + * Has completed a dma read process, i.e. has read out of the queue + */ +void WindowedFifo::dmaRead(unsigned len) { + _activeDMA = false; + + if (len == 0) { + _blocked = BLOCKED_MAX_NR; + } else { + _tail = ((unsigned) (_tail + len) % _size); + _use -= len; + } +} + +/* + * Start a DMA request, returns the current space one have + */ +unsigned WindowedFifo::dmaStart() { + _activeDMA = true; + + // If we go over the end, we only take as much as is on one side! + //return used(); + + if (_tail + _use > _size) { + return _size - _tail; + } else { + return _use; + } +} + +/* + * Is allowed to start a dma request + */ +bool WindowedFifo::dmaAllowed() { +#ifndef STORE_REQUESTS + if (_blocked > 0) { + _blocked--; + return false; + } else { + return !_activeDMA; + } +#else + return !_activeDMA; +#endif +} + +/** + * Is needed for DMA transfers + */ +unsigned WindowedFifo::dmaWrite(const void *source, unsigned len) { + + char* buffer = (char*) source; + + if (_head + len < _size) { + memcpy(_buffer + _head, buffer, len); + } else { + // We should never be here! + memcpy(_buffer + _head, buffer, _size - _head); + memcpy(_buffer, buffer + _size - _head, len - _size + _head); + } + _use += len; + _head = (_head + len) >= _size ? _head + len - _size : _head + len; + + return len; +}