dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / lib / ppu / WindowedFifo.cpp
1 #include "WindowedFifo.h"
2
3 /**
4  *
5  */
6 WindowedFifo::WindowedFifo(unsigned size = 20) {
7         //std::cout << "Create WindowedFifo." << std::endl;
8         _size = size;
9         _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
10         if(!_buffer) {
11             fprintf(stderr,"[WFIFO] Memory allocation failure\n");
12             exit(-1);
13         }
14
15         _head = 0;
16         _tail = 0;
17
18         _headRoom = 0;
19         _tailRoom = 0;
20         _use = 0;
21         _blocked = 0;
22
23         _isHeadReserved = false;
24         _isTailReserved = false;
25         _activeDMA = false;
26 }
27
28 /**
29  *
30  */
31 WindowedFifo::~WindowedFifo() {
32         if (_buffer) {
33                 _free_align(_buffer);
34         }
35         _buffer = 0;
36         _head = 0;
37         _tail = 0;
38         _use = 0;
39 }
40
41 /**
42  *
43  */
44 unsigned WindowedFifo::reserve(void** dest, unsigned len) {
45         char** destination = (char**) dest;
46         //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;
47
48         //can only reserve one piece at a time
49         if (_isHeadReserved) {
50                 *destination = 0;
51                 return 0;
52         }
53
54         //reserve at most as much memory as still available in the buffer
55         unsigned write = (len <= _size - _use ? len : _size - _use);
56
57         if (write > 0) {
58                 //if wrap-around in buffer: return only buffer for the
59                 //contiguous buffer space
60                 if (_head + write > _size) {
61                         write = _size - _head;
62                 }
63
64                 _headRoom = (_head + write) == _size ? 0 : _head + write;
65                 *destination = &(_buffer[_head]);
66                 _isHeadReserved = true;
67         }
68
69         //std::cout << "Reserved " << write << " bytes." << std::endl;
70         _writeReserve = write;
71         return write;
72 }
73
74 /**
75  *
76  */
77 void WindowedFifo::release() {
78         if (_isHeadReserved) {
79                 //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;
80                 _head = _headRoom;
81                 _use += _writeReserve;
82                 _isHeadReserved = false;
83         }
84 }
85
86 /**
87  *
88  */
89 unsigned WindowedFifo::capture(void **dest, unsigned len) {
90         char** destination = (char**) dest;
91         //std::cout << "Attempt to capture " << len << " bytes." << std::endl;
92
93         if (_isTailReserved) {
94                 //std::cout << "Only one attempt to capture allowed." << std::endl;
95                 *destination = 0;
96                 return 0;
97         }
98
99         //capture at most as much data as available in the buffer
100         unsigned read = (len <= _use ? len : _use);
101
102         if (read > 0) {
103                 //if wrap-around in buffer: return only buffer for the
104                 //conntiguous buffer space
105                 if (_tail + read > _size) {
106                         read = _size - _tail;
107                 }
108
109                 _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;
110                 *destination = &(_buffer[_tail]);
111                 _isTailReserved = true;
112         }
113
114         //std::cout << "Captured " << read << " bytes." << std::endl;
115         _readReserve = read;
116         return read;
117 }
118
119 /**
120  *
121  */
122 void WindowedFifo::consume() {
123         if (_isTailReserved) {
124                 //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;
125                 _tail = _tailRoom;
126                 _use -= _readReserve;
127                 _isTailReserved = false;
128         }
129 }
130
131 /**
132  *
133  */
134 unsigned WindowedFifo::size() const {
135         return _size;
136 }
137
138 /**
139  *
140  */
141 unsigned WindowedFifo::unused() const {
142         return _size - _use;
143 }
144
145 /**
146  *
147  */
148 unsigned WindowedFifo::used() const {
149         return _use;
150 }
151
152 /*
153  * Get the pointer to the start of the queue
154  */
155 char *WindowedFifo::getQueuePointer() {
156         return _buffer;
157 }
158
159 /*
160  * Has completed a dma read process, i.e. has read out of the queue
161  */
162 void WindowedFifo::dmaRead(unsigned len) {
163         _activeDMA = false;
164
165         if (len == 0) {
166                 _blocked = BLOCKED_MAX_NR;
167         } else {
168                 _tail = ((unsigned) (_tail + len) % _size);
169                 _use -= len;
170         }
171 }
172
173 /*
174  * Start a DMA request, returns the current space one have
175  */
176 unsigned WindowedFifo::dmaStart() {
177         _activeDMA = true;
178
179         // If we go over the end, we only take as much as is on one side!
180         //return used();
181
182         if (_tail + _use > _size) {
183                 return _size - _tail;
184         } else {
185                 return _use;
186         }
187 }
188
189 /*
190  * Is allowed to start a dma request
191  */
192 bool WindowedFifo::dmaAllowed() {
193 #ifndef STORE_REQUESTS
194         if (_blocked > 0) {
195                 _blocked--;
196                 return false;
197         } else {
198                 return !_activeDMA;
199         }
200 #else
201         return !_activeDMA;
202 #endif
203 }
204
205 /**
206  * Is needed for DMA transfers
207  */
208 unsigned WindowedFifo::dmaWrite(const void *source, unsigned len) {
209
210         char* buffer = (char*) source;
211
212         if (_head + len < _size) {
213                 memcpy(_buffer + _head, buffer, len);
214         } else {
215                 // We should never be here!
216                 memcpy(_buffer + _head, buffer, _size - _head);
217                 memcpy(_buffer, buffer + _size - _head, len - _size + _head);
218         }
219         _use += len;
220         _head = (_head + len) >= _size ? _head + len - _size : _head + len;
221
222         return len;
223 }