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

Revision 419, 19.8 kB (checked in by pieterpalmers, 16 years ago)

namespace simplification

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 Util;
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     uint64_t start_at_cycle;
76 };
77
78 // The options we understand.
79 static struct argp_option options[] = {
80     {"verbose",     'v',    "n",    0,  "Verbose level" },
81     {"wrap",        'w',    "n",    0,  "Wrap at (ticks) (3072000)" },
82     {"fpp",        'f',    "n",    0,  "Frames per packet (8)" },
83     {"epf",        'e',    "n",    0,  "Events per frame (10)" },
84     {"rate",        'r',    "n",    0,  "Rate (ticks/frame) (512.0)" },
85     {"cycles",        'c',    "n",    0,  "Total cycles to run (2000)" },
86     {"buffersize",        'b',    "n",    0,  "Buffer size (in frames) (1024)" },
87     {"startcycle",        's',    "n",    0,  "Start at cycle (0)" },
88     { 0 }
89 };
90
91 //-------------------------------------------------------------
92
93 // Parse a single option.
94 static error_t
95 parse_opt( int key, char* arg, struct argp_state* state )
96 {
97     // Get the input argument from `argp_parse', which we
98     // know is a pointer to our arguments structure.
99     struct arguments* arguments = ( struct arguments* ) state->input;
100     char* tail;
101
102     switch (key) {
103         case 'v':
104             if (arg) {
105                 arguments->verbose = strtoll( arg, &tail, 0 );
106                 if ( errno ) {
107                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
108                     return ARGP_ERR_UNKNOWN;
109                 }
110             } else {
111                 if ( errno ) {
112                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
113                     return ARGP_ERR_UNKNOWN;
114                 }
115             }
116             break;
117         case 'w':
118             if (arg) {
119                 arguments->wrap_at = strtoll( arg, &tail, 0 );
120                 if ( errno ) {
121                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
122                     return ARGP_ERR_UNKNOWN;
123                 }
124             } else {
125                 if ( errno ) {
126                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
127                     return ARGP_ERR_UNKNOWN;
128                 }
129             }
130             break;
131         case 'f':
132             if (arg) {
133                 arguments->frames_per_packet = strtoll( arg, &tail, 0 );
134                 if ( errno ) {
135                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
136                     return ARGP_ERR_UNKNOWN;
137                 }
138             } else {
139                 if ( errno ) {
140                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
141                     return ARGP_ERR_UNKNOWN;
142                 }
143             }
144             break;
145         case 'e':
146             if (arg) {
147                 arguments->events_per_frame = strtoll( arg, &tail, 0 );
148                 if ( errno ) {
149                     fprintf( stderr, "Could not parse 'epf' argument\n" );
150                     return ARGP_ERR_UNKNOWN;
151                 }
152             } else {
153                 if ( errno ) {
154                     fprintf( stderr, "Could not parse 'epf' argument\n" );
155                     return ARGP_ERR_UNKNOWN;
156                 }
157             }
158             break;
159         case 'c':
160             if (arg) {
161                 arguments->total_cycles = strtoll( arg, &tail, 0 );
162                 if ( errno ) {
163                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
164                     return ARGP_ERR_UNKNOWN;
165                 }
166             } else {
167                 if ( errno ) {
168                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
169                     return ARGP_ERR_UNKNOWN;
170                 }
171             }
172             break;
173         case 's':
174             if (arg) {
175                 arguments->start_at_cycle = strtoll( arg, &tail, 0 );
176                 if ( errno ) {
177                     fprintf( stderr, "Could not parse 'startcycle' argument\n" );
178                     return ARGP_ERR_UNKNOWN;
179                 }
180             } else {
181                 if ( errno ) {
182                     fprintf( stderr, "Could not parse 'startcycle' argument\n" );
183                     return ARGP_ERR_UNKNOWN;
184                 }
185             }
186             break;
187         case 'b':
188             if (arg) {
189                 arguments->buffersize = strtoll( arg, &tail, 0 );
190                 if ( errno ) {
191                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
192                     return ARGP_ERR_UNKNOWN;
193                 }
194             } else {
195                 if ( errno ) {
196                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
197                     return ARGP_ERR_UNKNOWN;
198                 }
199             }
200             break;
201         case 'r':
202             if (arg) {
203                 arguments->rate = strtof( arg, &tail );
204                 if ( errno ) {
205                     fprintf( stderr, "Could not parse 'rate' argument\n" );
206                     return ARGP_ERR_UNKNOWN;
207                 }
208             } else {
209                 if ( errno ) {
210                     fprintf( stderr, "Could not parse 'rate' argument\n" );
211                     return ARGP_ERR_UNKNOWN;
212                 }
213             }
214             break;                       
215        default:
216             return ARGP_ERR_UNKNOWN;
217     }
218     return 0;
219 }
220
221 // Our argp parser.
222 static struct argp argp = { options, parse_opt, args_doc, doc };
223
224
225 static void sighandler (int sig)
226 {
227         run = 0;
228 }
229
230 int main(int argc, char *argv[])
231 {
232    
233     TimestampedBuffer *t=NULL;
234     TimestampedBufferTestClient *c=NULL;
235    
236     struct arguments arguments;
237
238     // Default values.
239     arguments.verbose        = 0;
240     arguments.wrap_at = 3072000LLU; // 1000 cycles
241     arguments.frames_per_packet = 8;
242     arguments.events_per_frame = 10;
243     arguments.rate = 512.0;
244     arguments.total_cycles = 2000;
245     arguments.buffersize = 1024;
246     arguments.start_at_cycle = 0;
247    
248     // Parse our arguments; every option seen by `parse_opt' will
249     // be reflected in `arguments'.
250     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
251         fprintf( stderr, "Could not parse command line\n" );
252         exit(1);
253     }
254    
255     setDebugLevel(arguments.verbose);
256    
257     run=1;
258
259     signal (SIGINT, sighandler);
260     signal (SIGPIPE, sighandler);
261    
262     c=new TimestampedBufferTestClient();
263    
264     if(!c) {
265         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBufferTestClient\n");
266         exit(1);
267     }
268     c->setVerboseLevel(arguments.verbose);
269    
270     t=new TimestampedBuffer(c);
271    
272     if(!t) {
273         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBuffer\n");
274         delete c;
275         exit(1);
276     }
277     t->setVerboseLevel(arguments.verbose);
278
279     t->init();
280    
281     // Setup the buffer
282     t->setBufferSize(arguments.buffersize);
283     t->setEventSize(sizeof(int));
284     t->setEventsPerFrame(arguments.events_per_frame);
285
286     t->setUpdatePeriod(arguments.frames_per_packet);
287     t->setNominalRate(arguments.rate);
288    
289     t->setWrapValue(arguments.wrap_at);
290    
291     t->setTickOffset(10000);
292    
293     t->prepare();
294    
295     usleep(1000);
296    
297     debugOutput(DEBUG_LEVEL_NORMAL, "Start setBufferHeadTimestamp test...\n");
298     {
299         bool pass=true;
300         uint64_t time=arguments.start_at_cycle*3072;
301         int dummyframe_in[arguments.events_per_frame*arguments.frames_per_packet];
302        
303         // initialize the timestamp
304         uint64_t timestamp=time;
305         if (timestamp >= arguments.wrap_at) {
306             // here we need a modulo because start_at_cycle can be large
307             timestamp %= arguments.wrap_at;
308         }
309        
310         // account for the fact that there is offset,
311         // and that setBufferHeadTimestamp doesn't take offset
312         // into account
313         uint64_t timestamp2=timestamp+t->getTickOffset();
314         if (timestamp2>=arguments.wrap_at) {
315             timestamp2-=arguments.wrap_at;
316         }
317        
318         t->setBufferHeadTimestamp(timestamp2);
319        
320         timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
321         if (timestamp >= arguments.wrap_at) {
322             timestamp -= arguments.wrap_at;
323         }
324        
325         // write some packets
326         for (unsigned int i=0;i<20;i++) {
327             t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
328             timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
329             if (timestamp >= arguments.wrap_at) {
330                 timestamp -= arguments.wrap_at;
331             }
332         }
333    
334         for(unsigned int cycle=arguments.start_at_cycle;
335             cycle < arguments.start_at_cycle+arguments.total_cycles;
336             cycle++) {
337                 uint64_t ts_head, fc_head;
338                
339                 t->setBufferHeadTimestamp(timestamp);
340                 t->getBufferHeadTimestamp(&ts_head, &fc_head);
341                
342                 if (timestamp != ts_head) {
343                     debugError(" cycle %4u error: %011llu != %011llu\n",
344                         timestamp, ts_head);
345                         pass=false;
346                 }
347                
348                 timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
349                 if (timestamp >= arguments.wrap_at) {
350                     timestamp -= arguments.wrap_at;
351                 }
352            
353             // simulate the cycle timer clock in ticks
354             time += 3072;
355             if (time >= arguments.wrap_at) {
356                 time -= arguments.wrap_at;
357             }
358            
359             // allow for the messagebuffer thread to catch up
360             usleep(200);
361            
362             if(!run) break;
363         }
364        
365         if(!pass) {
366             debugError("Test failed, exiting...\n");
367    
368             delete t;
369             delete c;
370            
371             return -1;
372            
373         }
374     }
375    
376
377    
378     debugOutput(DEBUG_LEVEL_NORMAL, "Start read/write test...\n");
379     {
380         int dummyframe_in[arguments.events_per_frame*arguments.frames_per_packet];
381         int dummyframe_out[arguments.events_per_frame*arguments.frames_per_packet];
382    
383         for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
384             dummyframe_in[i]=i;
385         }
386        
387         uint64_t time=arguments.start_at_cycle*3072;
388        
389         // initialize the timestamp
390         uint64_t timestamp=time;
391         if (timestamp >= arguments.wrap_at) {
392             // here we need a modulo because start_at_cycle can be large
393             timestamp %= arguments.wrap_at;
394         }
395         t->setBufferTailTimestamp(timestamp);
396        
397         timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
398         if (timestamp >= arguments.wrap_at) {
399             timestamp -= arguments.wrap_at;
400         }
401    
402         for(unsigned int cycle=arguments.start_at_cycle;
403             cycle < arguments.start_at_cycle+arguments.total_cycles;
404             cycle++) {
405            
406             // simulate the rate adaptation
407             int64_t diff=(time%arguments.wrap_at)-timestamp;
408            
409             if (diff>(int64_t)arguments.wrap_at/2) {
410                 diff -= arguments.wrap_at;
411             } else if (diff<(-(int64_t)arguments.wrap_at)/2){
412                 diff += arguments.wrap_at;
413             }
414            
415             debugOutput(DEBUG_LEVEL_NORMAL, "Simulating cycle %d @ time=%011llu, diff=%lld\n",cycle,time,diff);
416            
417             if(diff>0) {
418                 uint64_t ts_head, fc_head;
419                 uint64_t ts_tail, fc_tail;
420                
421                 // write one packet
422                 t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
423    
424                 // read the buffer head timestamp
425                 t->getBufferHeadTimestamp(&ts_head, &fc_head);
426                 t->getBufferTailTimestamp(&ts_tail, &fc_tail);
427                 debugOutput(DEBUG_LEVEL_NORMAL,
428                         " TS after write: HEAD: %011llu, FC=%04u\n",
429                         ts_head,fc_head);
430                 debugOutput(DEBUG_LEVEL_NORMAL,
431                         "                 TAIL: %011llu, FC=%04u\n",
432                         ts_tail,fc_tail);
433    
434                 // read one packet
435                 t->readFrames(arguments.frames_per_packet, (char *)&dummyframe_out);
436    
437                 // read the buffer head timestamp
438                 t->getBufferHeadTimestamp(&ts_head, &fc_head);
439                 t->getBufferTailTimestamp(&ts_tail, &fc_tail);
440                 debugOutput(DEBUG_LEVEL_NORMAL,
441                         " TS after write: HEAD: %011llu, FC=%04u\n",
442                         ts_head,fc_head);
443                 debugOutput(DEBUG_LEVEL_NORMAL,
444                         "                 TAIL: %011llu, FC=%04u\n",
445                         ts_tail,fc_tail);
446    
447                 // check
448                 bool pass=true;
449                 for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
450                     pass = pass && (dummyframe_in[i]==dummyframe_out[i]);
451                 }
452                 if (!pass) {
453                     debugOutput(DEBUG_LEVEL_NORMAL, "write/read check for cycle %d failed\n",cycle);
454                 }
455    
456                 // update the timestamp
457                 timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
458                 if (timestamp >= arguments.wrap_at) {
459                     timestamp -= arguments.wrap_at;
460                 }
461             }
462    
463             // simulate the cycle timer clock in ticks
464             time += 3072;
465             if (time >= arguments.wrap_at) {
466                 time -= arguments.wrap_at;
467             }
468            
469             // allow for the messagebuffer thread to catch up
470             usleep(200);
471            
472             if(!run) break;
473         }
474     }
475    
476     // second run, now do block processing
477     debugOutput(DEBUG_LEVEL_NORMAL, "Start block read test...\n");
478     {
479         unsigned int blocksize=32;
480         int dummyframe_out_block[arguments.events_per_frame*arguments.frames_per_packet*blocksize];
481         int dummyframe_in[arguments.events_per_frame*arguments.frames_per_packet];
482    
483         for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
484             dummyframe_in[i]=i;
485         }
486        
487         uint64_t time=arguments.start_at_cycle*3072;
488        
489         // initialize the timestamp
490         uint64_t timestamp=time;
491         if (timestamp >= arguments.wrap_at) {
492             // here we need a modulo because start_at_cycle can be large
493             timestamp %= arguments.wrap_at;
494         }
495         t->setBufferTailTimestamp(timestamp);
496        
497         timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
498         if (timestamp >= arguments.wrap_at) {
499             timestamp -= arguments.wrap_at;
500         }
501    
502         for(unsigned int cycle=arguments.start_at_cycle;
503             cycle < arguments.start_at_cycle+arguments.total_cycles;
504             cycle++) {
505            
506             // simulate the rate adaptation
507             int64_t diff=(time%arguments.wrap_at)-timestamp;
508            
509             if (diff>(int64_t)arguments.wrap_at/2) {
510                 diff -= arguments.wrap_at;
511             } else if (diff<(-(int64_t)arguments.wrap_at)/2){
512                 diff += arguments.wrap_at;
513             }
514            
515             debugOutput(DEBUG_LEVEL_NORMAL, "Simulating cycle %d @ time=%011llu, diff=%lld\n",cycle,time,diff);
516            
517             if(diff>0) {
518                 uint64_t ts_head, fc_head;
519                 uint64_t ts_tail, fc_tail;
520                
521                 // write one packet
522                 t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
523    
524                 // read the buffer head timestamp
525                 t->getBufferHeadTimestamp(&ts_head, &fc_head);
526                 t->getBufferTailTimestamp(&ts_tail, &fc_tail);
527                 debugOutput(DEBUG_LEVEL_NORMAL,
528                         " TS after write: HEAD: %011llu, FC=%04u\n",
529                         ts_head,fc_head);
530                 debugOutput(DEBUG_LEVEL_NORMAL,
531                         "                 TAIL: %011llu, FC=%04u\n",
532                         ts_tail,fc_tail);
533    
534                 if (fc_head > blocksize) {
535                     debugOutput(DEBUG_LEVEL_NORMAL,"Reading one block (%u frames)\n",blocksize);
536                    
537                     // read one block
538                     t->readFrames(blocksize, (char *)&dummyframe_out_block);
539        
540                     // read the buffer head timestamp
541                     t->getBufferHeadTimestamp(&ts_head, &fc_head);
542                     t->getBufferTailTimestamp(&ts_tail, &fc_tail);
543                     debugOutput(DEBUG_LEVEL_NORMAL,
544                             " TS after read: HEAD: %011llu, FC=%04u\n",
545                             ts_head,fc_head);
546                     debugOutput(DEBUG_LEVEL_NORMAL,
547                             "                TAIL: %011llu, FC=%04u\n",
548                             ts_tail,fc_tail);
549                 }
550                
551                 // update the timestamp
552                 timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
553                 if (timestamp >= arguments.wrap_at) {
554                     timestamp -= arguments.wrap_at;
555                 }
556             }
557    
558             // simulate the cycle timer clock in ticks
559             time += 3072;
560             if (time >= arguments.wrap_at) {
561                 time -= arguments.wrap_at;
562             }
563            
564             // allow for the messagebuffer thread to catch up
565             usleep(200);
566            
567             if(!run) break;
568         }
569     }
570
571     delete t;
572     delete c;
573        
574     return EXIT_SUCCESS;
575 }
576
577
Note: See TracBrowser for help on using the browser.