dol: initial dol commit
[jump.git] / dol / src / dol / visitor / cell / lib / spu / Fifo.cpp
1 #include "Fifo.h"
2
3 /**
4  *
5  */
6 Fifo::Fifo(unsigned size = 18) {
7         //except at the beginning, _head and _tail must never overlap,
8         //otherwise one does not know whether the buffer is full or
9         //empty. to have nevertheless a buffer with the given capacity,
10         //a buffer with one more element is allocated.
11
12         _size = size;
13         _buffer = (char *) _malloc_align(_size, ALIGNMENT_FACTOR);
14   if(!_buffer) {
15     fprintf(stderr,"[FIFO] Memory allocation failure\n");
16     exit(-1);
17   }
18         _pos = 0;
19         _tail = 0;
20         _blocked = 0;
21
22         _inTail = 0;
23         _activeDMA = false;
24 }
25
26 /**
27  *
28  */
29 Fifo::~Fifo() {
30         if (_buffer) {
31                 _free_align(_buffer);
32         }
33         _buffer = 0;
34         _pos = 0;
35         _tail = 0;
36 }
37
38 /**
39  *
40  */
41 unsigned Fifo::read(void *destination, unsigned len) {
42
43         char* buffer = (char*) destination;
44         unsigned read = (len <= used() ? len : used());
45
46         if (_tail + read < _size) {
47                 memcpy(buffer, _buffer + _tail, read);
48         } else {
49                 memcpy(buffer, _buffer + _tail, _size - _tail);
50                 memcpy(buffer + _size - _tail, _buffer, read - _size + _tail);
51         }
52
53         _tail = ((unsigned) (_tail + read) % _size);
54         _pos -= read;
55         return read;
56 }
57
58 /**
59  *
60  */
61 unsigned Fifo::write(const void *source, unsigned len) {
62
63         char* buffer = (char*) source;
64         unsigned write = (len <= unused() ? len : unused());
65         unsigned head = (_tail + _pos) % _size;
66
67         if (head + write < _size) {
68                 memcpy(_buffer + head, buffer, write);
69         } else {
70                 memcpy(_buffer + head, buffer, _size - head);
71                 memcpy(_buffer, buffer + _size - head, write - _size + head);
72         }
73
74         _pos += write;
75         return write;
76 }
77
78 /**
79  * Size of this fifo
80  */
81 unsigned Fifo::size() const {
82         return (_size);
83 }
84
85 /**
86  * How many bytes is currently free in the buffer
87  */
88 unsigned Fifo::unused() const {
89         return (_size) - used();
90 }
91
92 /**
93  * How many data are currently stored in the fifo
94  */
95 unsigned Fifo::used() const {
96         return _pos;
97 }
98
99 /*
100  * Get the pointer to the start of the queue
101  */
102 char *Fifo::getQueuePointer() {
103         return _buffer;
104 }
105
106 /*
107  * Has completed a dma read process, i.e. has read out of the queue
108  */
109 void Fifo::dmaRead(unsigned len) {
110         _activeDMA = false;
111
112         if (len == 0) {
113                 _blocked = BLOCKED_MAX_NR;
114         } else {
115                 _tail = ((unsigned) (_tail + len) % _size);
116                 _pos -= len;
117         }
118 }
119
120 /*
121  * Start a DMA request, returns the current space one have
122  */
123 unsigned Fifo::dmaStart() {
124         _activeDMA = true;
125
126         if (_tail + _pos > _size) {
127                 return _size - _tail;
128         } else {
129                 return _pos;
130         }
131 }
132
133 /*
134  * Is allowed to start a dma request
135  */
136 bool Fifo::dmaAllowed() {
137         if (_blocked > 0) {
138                 _blocked--;
139                 return false;
140         } else {
141                 return !_activeDMA;
142         }
143 }
144
145 /**
146  * Test the implementation
147  */
148 /*
149  int main() {
150  std::cout.width(5);
151  Fifo *myFifo = new Fifo();
152  for (int j = 0; j < 3; j++) {
153  for (int i = 0; i < 6; i++) {
154  std::cout << "write " << i << " to Fifo.    ";
155  int write = myFifo->write(&i, sizeof(int));
156  printf(" %d ", write);
157  if (write == sizeof(int)) {
158  std::cout << "used: " << std::setw(2) << myFifo->used()
159  << ", unused: " << std::setw(2) << myFifo->unused()
160  << ", size: "  << std::setw(2) << myFifo->size()
161  << std::endl;
162  } else {
163  std::cout << std::endl;
164  }
165  }
166  for (int i = 0; i < 6; i++) {
167  int value;
168  int read = myFifo->read(&value, sizeof(int));
169  printf(" %d ", read);
170  if (read == sizeof(int)) {
171  std::cout << "read " << value << "  from Fifo   ";
172  std::cout << "used: " << std::setw(2) << myFifo->used()
173  << ", unused: " << std::setw(2) << myFifo->unused()
174  << ", size: "  << std::setw(2) << myFifo->size()
175  << std::endl;
176  }
177  }
178  }
179  delete myFifo;
180  return 0;
181  }
182  */