dol: initial dol commit
[jump.git] / dol / src / dol / visitor / hds / lib / WindowedFifo.cpp
1 #include "WindowedFifo.h"\r
2 \r
3 /**\r
4  *\r
5  */\r
6 WindowedFifo::WindowedFifo(char* name, unsigned size = 20) {\r
7     //std::cout << "Create WindowedFifo." << std::endl;\r
8     _size = size;\r
9     _buffer = new char[_size];\r
10     _head = 0;\r
11     _tail = 0;\r
12     _headRoom = 0;\r
13     _tailRoom = 0;\r
14     _use = 0;\r
15     //indicates whether Fifo is empty or full if _head == _tail\r
16     //_isFull = false;\r
17     _isHeadReserved = false;\r
18     _isTailReserved = false;\r
19     _name = new char[strlen(name) + 1];\r
20     strcpy(_name, name);\r
21 }\r
22 \r
23 /**\r
24  *\r
25  */\r
26 WindowedFifo::~WindowedFifo() {\r
27     //std::cout << "Delete WindowedFifo." << std::endl;\r
28     if (_buffer) {\r
29         delete _buffer;\r
30     }\r
31     if (_name) {\r
32         delete _name;\r
33     }\r
34     _buffer = 0;\r
35     _head = 0;\r
36     _tail = 0;\r
37     _name = 0;\r
38     _use = 0;\r
39     //std::cout << "Deleted WindowedFifo." << std::endl;\r
40 }\r
41 \r
42 /**\r
43  *\r
44  */\r
45 unsigned WindowedFifo::reserve(void** dest, unsigned len) {\r
46     char** destination = (char**)dest;\r
47     //std::cout << "Attempt to reserve " << len << " bytes." << std::endl;\r
48 \r
49     //can only reserve once piece at a time\r
50     if (_isHeadReserved) {\r
51         *destination = 0;\r
52         return 0;\r
53     }\r
54 \r
55     while (unused() == 0) {\r
56       wait(_readEvent);\r
57     }\r
58 \r
59     //reserve at most as much memory as still available in the buffer\r
60     unsigned write = (len <= _size - _use ? len : _size - _use);\r
61 \r
62     if (write > 0) {\r
63         //if wrap-around in buffer: return only buffer for the\r
64         //contiguous buffer space\r
65         if (_head + write > _size) {\r
66             write = _size - _head;\r
67         }\r
68 \r
69         _headRoom = (_head + write) == _size? 0 : _head + write;\r
70         *destination = &(_buffer[_head]);\r
71         _isHeadReserved = true;\r
72 \r
73         //the following comparison is unsafe in a multi-threaded\r
74         //environment and potentially leads to race-conditions\r
75         /*if (_headRoom == _tail) {\r
76             _isFull = true;\r
77         } else {\r
78             _isFull = false;\r
79         }*/\r
80     }\r
81 \r
82     //std::cout << "Reserved " << write << " bytes." << std::endl;\r
83     _writeReserve = write; \r
84     return write;\r
85 }\r
86 \r
87 /**\r
88  *\r
89  */\r
90 void WindowedFifo::release() {\r
91     if (_isHeadReserved) {\r
92         //std::cout << "Released " << _headRoom - _head << " bytes." << std::endl;\r
93         _head = _headRoom;\r
94         _use += _writeReserve;\r
95         _isHeadReserved = false;\r
96         _writeEvent.notify();\r
97     }\r
98 }\r
99 \r
100 /**\r
101  *\r
102  */\r
103 unsigned WindowedFifo::capture(void **dest, unsigned len) {\r
104     char** destination = (char**)dest;\r
105     //std::cout << "Attempt to capture " << len << " bytes." << std::endl;\r
106 \r
107     if (_isTailReserved) {\r
108         //std::cout << "Only one attempt to capture allowed." << std::endl;\r
109         *destination = 0;\r
110         return 0;\r
111     }\r
112 \r
113     while (used() == 0) {\r
114       wait(_writeEvent);\r
115     }\r
116 \r
117     //capture at most as much data as available in the buffer\r
118     unsigned read = (len <= _use ? len : _use);\r
119 \r
120     if ( read > 0 ) {\r
121         //if wrap-around in buffer: return only buffer for the\r
122         //contiguous buffer space\r
123         if (_tail + read> _size) {\r
124             read = _size - _tail;\r
125         }\r
126 \r
127         _tailRoom = (_tail + read) == _size ? 0 : _tailRoom = _tail + read;\r
128         *destination = &(_buffer[_tail]);\r
129         _isTailReserved = true;\r
130     }\r
131 \r
132     //std::cout << "Captured " << read << " bytes." << std::endl;\r
133 \r
134     _readReserve = read; \r
135     return read;\r
136 }\r
137 \r
138 /**\r
139  *\r
140  */\r
141 void WindowedFifo::consume() {\r
142     if (_isTailReserved) {\r
143         //std::cout << "Consumed " << _tailRoom - _tail << " bytes." << std::endl;\r
144         _tail = _tailRoom;\r
145         _use -= _readReserve;\r
146         _isTailReserved = false;\r
147         //_isFull = false;\r
148         _readEvent.notify();\r
149     }\r
150 }\r
151 \r
152 /**\r
153  *\r
154  */\r
155 unsigned WindowedFifo::size() const {\r
156     return _size;\r
157 }\r
158 \r
159 /**\r
160  *\r
161  */\r
162 unsigned WindowedFifo::unused() const {\r
163     return _size - _use;\r
164 }\r
165 \r
166 /**\r
167  *\r
168  */\r
169 unsigned WindowedFifo::used() const {\r
170         return _use;\r
171     /*if (_headRoom > _tail) {\r
172         return _headRoom - _tail;\r
173     } else if (_headRoom == _tail) {\r
174         if (_isFull == true) {\r
175             return _size;\r
176         } else {\r
177             return 0;\r
178         }\r
179     }\r
180     return _headRoom + _size - _tail;*/\r
181 }\r
182 \r
183 /**\r
184  *\r
185  */\r
186 char* WindowedFifo::getName() const {\r
187     return _name;\r
188 }\r
189 \r
190 /**\r
191  * Test the implementation\r
192  */\r
193 /*\r
194 #include <iostream>\r
195 #include <iomanip>\r
196 #define LENGTH 10\r
197 \r
198 class producer : public sc_module\r
199 {\r
200     public:\r
201     WindowedFifo *wfifo;\r
202 \r
203     SC_HAS_PROCESS(producer);\r
204 \r
205     producer(sc_module_name name) : sc_module(name)\r
206     {\r
207       SC_THREAD(main);\r
208     }\r
209 \r
210     void main()\r
211     {\r
212         for (int j = 0; j < LENGTH; j++) {\r
213             //std::cout << "write " << i << " to Fifo.    ";\r
214             int *buf1;\r
215             int write = wfifo->reserve((void**)&buf1, sizeof(int));\r
216 \r
217             if (write == sizeof(int)) {\r
218                 *buf1 = j;\r
219                 wfifo->release();\r
220                 //std::cout << "used: " << std::setw(2) << wfifo->used()\r
221                 //        << ", unused: " << std::setw(2) << wfifo->unused()\r
222                 //        << ", size: "  << std::setw(2) << wfifo->size()\r
223                 //        << std::endl;\r
224             } else {\r
225                 std::cout << "Not successful: " << write << std::endl;\r
226             }\r
227         }\r
228         printf("producer returns.\n");\r
229     }\r
230 };\r
231 \r
232 class consumer : public sc_module\r
233 {\r
234     public:\r
235     WindowedFifo *wfifo;\r
236 \r
237     SC_HAS_PROCESS(consumer);\r
238 \r
239     consumer(sc_module_name name) : sc_module(name)\r
240     {\r
241         SC_THREAD(main);\r
242     }\r
243 \r
244     void main()\r
245     {\r
246         for (int j = 0; j < LENGTH; j++) {\r
247             int* buf3;\r
248             int read = wfifo->capture((void**)&buf3, sizeof(int));\r
249             if (read == sizeof(int)) {\r
250                 std::cout << "read " << (unsigned)*buf3 << "  from WindowedFifo   ";\r
251                 std::cout << "used: " << std::setw(2) << wfifo->used()\r
252                         << ", unused: " << std::setw(2) << wfifo->unused()\r
253                         << ", size: "  << std::setw(2) << wfifo->size()\r
254                         << std::endl;\r
255                 wfifo->consume();\r
256             } else {\r
257                 std::cout << "Read nothing from WindowedFifo." << std::endl;\r
258             }\r
259         }\r
260         printf("consumer returns.\n");\r
261     }\r
262 };\r
263 \r
264 class top : public sc_module\r
265 {\r
266     public:\r
267     WindowedFifo *wfifo_inst;\r
268     producer *prod_inst;\r
269     consumer *cons_inst;\r
270 \r
271     top(sc_module_name name) : sc_module(name)\r
272     {\r
273         wfifo_inst = new WindowedFifo("myfifo", 4);\r
274 \r
275         prod_inst = new producer("producer");\r
276         prod_inst->wfifo = wfifo_inst;\r
277 \r
278         cons_inst = new consumer("consumer");\r
279         cons_inst->wfifo = wfifo_inst;\r
280      }\r
281 };\r
282 \r
283 int sc_main (int argc , char *argv[]) {\r
284     top top1("top");\r
285     sc_start();\r
286     return 0;\r
287 }\r
288 */\r