root/branches/streaming-rework/tests/test-timestampedbuffer.cpp

Revision 392, 10.8 kB (checked in by pieterpalmers, 17 years ago)

- document TimestampedBuffer? class
- partially ported timestamp handling to TimestampedBuffer?
- introduced test for TimestampedBuffer? class

Line 
1 /***************************************************************************
2 Copyright (C) 2007 by Pieter Palmers   *
3                                                                         *
4 This program is free software; you can redistribute it and/or modify  *
5 it under the terms of the GNU General Public License as published by  *
6 the Free Software Foundation; either version 2 of the License, or     *
7 (at your option) any later version.                                   *
8                                                                         *
9 This program is distributed in the hope that it will be useful,       *
10 but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12 GNU General Public License for more details.                          *
13                                                                         *
14 You should have received a copy of the GNU General Public License     *
15 along with this program; if not, write to the                         *
16 Free Software Foundation, Inc.,                                       *
17 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <argp.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <endian.h>
29
30 #include <signal.h>
31 #include "src/debugmodule/debugmodule.h"
32
33 #include <netinet/in.h>
34
35 #include "src/libstreaming/cycletimer.h"
36
37 #include "src/libutil/TimestampedBuffer.h"
38
39 #include <pthread.h>
40
41 using namespace FreebobUtil;
42
43 class TimestampedBufferTestClient
44     : public TimestampedBufferClient {
45 public:
46     bool processReadBlock(char *data, unsigned int nevents, unsigned int offset) {return true;};
47     bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset) {return true;};
48    
49     void setVerboseLevel(int l) {setDebugLevel(l);};
50 private:
51     DECLARE_DEBUG_MODULE;
52 };
53
54 IMPL_DEBUG_MODULE( TimestampedBufferTestClient, TimestampedBufferTestClient, DEBUG_LEVEL_VERBOSE );
55
56 DECLARE_GLOBAL_DEBUG_MODULE;
57
58 int run;
59 // Program documentation.
60 static char doc[] = "FreeBoB -- Timestamped buffer test\n\n";
61
62 // A description of the arguments we accept.
63 static char args_doc[] = "";
64
65
66 struct arguments
67 {
68     short verbose;
69     uint64_t wrap_at;
70     uint64_t frames_per_packet;
71     uint64_t events_per_frame;
72     float rate;
73     uint64_t total_cycles;
74     uint64_t buffersize;
75 };
76
77 // The options we understand.
78 static struct argp_option options[] = {
79     {"verbose",     'v',    "n",    0,  "Verbose level" },
80     {"wrap",        'w',    "n",    0,  "Wrap at (ticks) (3072000)" },
81     {"fpp",        'f',    "n",    0,  "Frames per packet (8)" },
82     {"epf",        'e',    "n",    0,  "Events per frame (10)" },
83     {"rate",        'r',    "n",    0,  "Rate (ticks/frame) (512.0)" },
84     {"cycles",        'c',    "n",    0,  "Total cycles to run (2000)" },
85     {"buffersize",        'b',    "n",    0,  "Buffer size (in frames) (1024)" },
86     { 0 }
87 };
88
89 //-------------------------------------------------------------
90
91 // Parse a single option.
92 static error_t
93 parse_opt( int key, char* arg, struct argp_state* state )
94 {
95     // Get the input argument from `argp_parse', which we
96     // know is a pointer to our arguments structure.
97     struct arguments* arguments = ( struct arguments* ) state->input;
98     char* tail;
99
100     switch (key) {
101         case 'v':
102             if (arg) {
103                 arguments->verbose = strtol( arg, &tail, 0 );
104                 if ( errno ) {
105                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
106                     return ARGP_ERR_UNKNOWN;
107                 }
108             } else {
109                 if ( errno ) {
110                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
111                     return ARGP_ERR_UNKNOWN;
112                 }
113             }
114             break;
115         case 'w':
116             if (arg) {
117                 arguments->wrap_at = strtol( arg, &tail, 0 );
118                 if ( errno ) {
119                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
120                     return ARGP_ERR_UNKNOWN;
121                 }
122             } else {
123                 if ( errno ) {
124                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
125                     return ARGP_ERR_UNKNOWN;
126                 }
127             }
128             break;
129         case 'f':
130             if (arg) {
131                 arguments->frames_per_packet = strtol( arg, &tail, 0 );
132                 if ( errno ) {
133                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
134                     return ARGP_ERR_UNKNOWN;
135                 }
136             } else {
137                 if ( errno ) {
138                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
139                     return ARGP_ERR_UNKNOWN;
140                 }
141             }
142             break;
143         case 'e':
144             if (arg) {
145                 arguments->events_per_frame = strtol( arg, &tail, 0 );
146                 if ( errno ) {
147                     fprintf( stderr, "Could not parse 'epf' argument\n" );
148                     return ARGP_ERR_UNKNOWN;
149                 }
150             } else {
151                 if ( errno ) {
152                     fprintf( stderr, "Could not parse 'epf' argument\n" );
153                     return ARGP_ERR_UNKNOWN;
154                 }
155             }
156             break;
157         case 'c':
158             if (arg) {
159                 arguments->total_cycles = strtol( arg, &tail, 0 );
160                 if ( errno ) {
161                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
162                     return ARGP_ERR_UNKNOWN;
163                 }
164             } else {
165                 if ( errno ) {
166                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
167                     return ARGP_ERR_UNKNOWN;
168                 }
169             }
170             break;
171         case 'b':
172             if (arg) {
173                 arguments->buffersize = strtol( arg, &tail, 0 );
174                 if ( errno ) {
175                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
176                     return ARGP_ERR_UNKNOWN;
177                 }
178             } else {
179                 if ( errno ) {
180                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
181                     return ARGP_ERR_UNKNOWN;
182                 }
183             }
184             break;
185         case 'r':
186             if (arg) {
187                 arguments->rate = strtof( arg, &tail );
188                 if ( errno ) {
189                     fprintf( stderr, "Could not parse 'rate' argument\n" );
190                     return ARGP_ERR_UNKNOWN;
191                 }
192             } else {
193                 if ( errno ) {
194                     fprintf( stderr, "Could not parse 'rate' argument\n" );
195                     return ARGP_ERR_UNKNOWN;
196                 }
197             }
198             break;                       
199        default:
200             return ARGP_ERR_UNKNOWN;
201     }
202     return 0;
203 }
204
205 // Our argp parser.
206 static struct argp argp = { options, parse_opt, args_doc, doc };
207
208
209 static void sighandler (int sig)
210 {
211         run = 0;
212 }
213
214 int main(int argc, char *argv[])
215 {
216    
217     TimestampedBuffer *t=NULL;
218     TimestampedBufferTestClient *c=NULL;
219    
220     struct arguments arguments;
221
222     // Default values.
223     arguments.verbose        = 0;
224     arguments.wrap_at = 3072000LLU; // 1000 cycles
225     arguments.frames_per_packet = 8;
226     arguments.events_per_frame = 10;
227     arguments.rate = 512.0;
228     arguments.total_cycles = 2000;
229     arguments.buffersize = 1024;
230    
231     // Parse our arguments; every option seen by `parse_opt' will
232     // be reflected in `arguments'.
233     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
234         fprintf( stderr, "Could not parse command line\n" );
235         exit(1);
236     }
237    
238     setDebugLevel(arguments.verbose);
239    
240     run=1;
241
242     signal (SIGINT, sighandler);
243     signal (SIGPIPE, sighandler);
244    
245     c=new TimestampedBufferTestClient();
246    
247     if(!c) {
248         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBufferTestClient\n");
249         exit(1);
250     }
251     c->setVerboseLevel(arguments.verbose);
252    
253     t=new TimestampedBuffer(c);
254    
255     if(!t) {
256         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBuffer\n");
257         delete c;
258         exit(1);
259     }
260     t->setVerboseLevel(arguments.verbose);
261
262     t->init();
263    
264     // Setup the buffer
265     t->setBufferSize(arguments.buffersize);
266     t->setEventSize(sizeof(int));
267     t->setEventsPerFrame(arguments.events_per_frame);
268
269     t->setUpdatePeriod(arguments.frames_per_packet);
270     t->setNominalRate(arguments.rate);
271    
272     t->setWrapValue(arguments.wrap_at);
273    
274     t->prepare();
275    
276     usleep(1000);
277
278     int dummyframe_in[arguments.events_per_frame*arguments.frames_per_packet];
279     int dummyframe_out[arguments.events_per_frame*arguments.frames_per_packet];
280    
281     for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
282         dummyframe_in[i]=i;
283     }
284    
285     uint64_t timestamp=0;
286     t->setBufferTailTimestamp(timestamp);
287     timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
288    
289     uint64_t time=0;
290    
291     for(unsigned int cycle=0;cycle < arguments.total_cycles; cycle++) {
292         // simulate the rate adaptation
293         int64_t diff=time-timestamp;
294        
295         if (diff>(int64_t)arguments.wrap_at/2) {
296             diff -= arguments.wrap_at;
297         } else if (diff<(-(int64_t)arguments.wrap_at)/2){
298             diff += arguments.wrap_at;
299         }
300        
301         debugOutput(DEBUG_LEVEL_NORMAL, "Simulating cycle %d @ time=%011llu, diff=%lld\n",cycle,time,diff);
302        
303         if(diff>0) {
304             // write one packet
305             t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
306            
307             // read one packet
308             t->readFrames(arguments.frames_per_packet, (char *)&dummyframe_out);
309            
310             // check
311             bool pass=true;
312             for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
313                 pass = pass && (dummyframe_in[i]==dummyframe_out[i]);
314             }
315             if (!pass) {
316                 debugOutput(DEBUG_LEVEL_NORMAL, "write/read check for cycle %d failed\n",cycle);
317             }
318            
319             // update the timestamp
320             timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
321             if (timestamp >= arguments.wrap_at) {
322                 timestamp -= arguments.wrap_at;
323             }
324         }
325        
326         // simulate the cycle timer clock in ticks
327         time += 3072;
328         if (time >= arguments.wrap_at) {
329             time -= arguments.wrap_at;
330         }
331        
332         // allow for the messagebuffer thread to catch up
333         usleep(200);
334
335     }
336
337     delete t;
338     delete c;
339        
340     return EXIT_SUCCESS;
341 }
342
343
Note: See TracBrowser for help on using the browser.