source: ResearchApps/PHY/WARPLAB/WARPLab7/M_Code_Reference/util/wl_benchmark.m

Last change on this file was 4815, checked in by welsh, 8 years ago

Added automatic checking of sequence number of Read IQ and Read RSSI. This was added to both the Java and MEX transports.

File size: 19.5 KB
Line 
1%==============================================================================
2% Function wl_benchmark()
3%
4% Usage: 
5%     - results = wl_benchmark( nodes )                                                             - Interactive mode
6%     - results = wl_benchmark( nodes, 'read_iq', num_trials, num_samples_per_read, num_buffers )   - Read IQ benchmark
7%     - results = wl_benchmark( nodes, 'write_iq', num_trials, num_samples_per_write, num_buffers ) - Write IQ benchmark
8%
9% NOTE:  Can be used on a single node or an array of nodes
10% NOTE:  If no output arguments are specified, then the function just prints the benchmark data
11%
12% Output:
13%     - Pretty print of benchmark info
14%     - Array of benchmark info (if the number of output arguments is 1)
15%
16%==============================================================================
17
18function data = wl_benchmark(varargin)
19    interactive_mode = 0;
20    benchmark        = 99;
21    num_rx_samples   = 0;                   % Default to zero, set to the max samples per the node Read IQ length
22    num_tx_samples   = 0;                   % Default to zero, set to the max samples per the node Write IQ length
23    num_trials       = 1000;                % Default to 1000
24    num_buffers      = 1;
25   
26   
27    %--------------------------------------------------------------------------
28    % Get inputs
29    %   
30    if (nargin == 0)
31        fprintf('Usage wl_benchmark:\n');
32        fprintf('  1. Interactive Mode:  \n');
33        fprintf('       results = wl_benchmark( nodes ) \n');
34        fprintf('  2. Batch Mode: \n');
35        fprintf('       results = wl_benchmark( nodes, "benchmark", num_trials, num_samples_per_trial, num_buffers ) \n');
36        fprintf('       where \n');
37        fprintf('         benchmark             is: [read_iq, write_iq]   \n');
38        fprintf('         num_trials            is: Number of trials to conduct for the benchmark\n');
39        fprintf('         num_samples_per_trial is: Number (1 ... Max IQ length) or "max" \n\n');
40        fprintf('         num_buffers           is: Number of RF buffers to request ([1..4] depending on the node capabilities)\n\n');
41        error('Not enough arguments are provided');
42
43    elseif (nargin == 1)
44        interactive_mode = 1;
45       
46        switch( class(varargin{1}) ) 
47            case 'wl_node'
48                nodes    = varargin{1};
49                numNodes = length(nodes);
50            otherwise
51                error('Unknown argument.  Argument is of type "%s", need "wl_node"', class(varargin{1}));
52        end       
53
54    elseif ((nargin == 4) || (nargin == 5))
55        switch( class(varargin{1}) ) 
56            case 'wl_node'
57                nodes    = varargin{1};
58                numNodes = length(nodes);
59            otherwise
60                error('Unknown argument.  Argument is of type "%s", need "wl_node"', class(varargin{1}));
61        end       
62
63        switch( class(varargin{2}) ) 
64            case 'char'
65                func     = lower( varargin{2} );
66               
67                switch( func )
68                    case 'read_iq'
69                        benchmark = 1;
70                    case 'write_iq'
71                        benchmark = 2;
72                    otherwise
73                        fprintf('Unknown Argument.  Currently supported benchmarks are: \n');
74                        fprintf('    read_iq \n');
75                        fprintf('    write_iq \n');
76                        error('Unknown benchmark function: %s \n', varargin{1} );
77                end
78            otherwise
79                error('Unknown argument.  Argument is of type "%s", need "string"', class(varargin{2}));
80        end
81       
82        switch( class(varargin{3}) ) 
83            case 'double'
84                num_trials = varargin{3};
85               
86                if ( num_trials <= 0 )
87                    num_trials = 1;
88                end
89
90            otherwise
91                error('Unknown argument.  Argument is of type "%s", need "double"', class(varargin{3}));
92        end       
93
94        switch( class(varargin{4}) ) 
95            case 'double'
96                num_rx_samples = varargin{4};
97                num_tx_samples = varargin{4};
98               
99                % Error checking for num_*_samples is done below on a per node basis
100
101            case 'char'
102                if( strcmp( 'max', lower( varargin{4} ) ) )
103                    num_rx_samples = 0;
104                    num_tx_samples = 0;
105                else
106                    fprintf('Unknown Argument.  Number of Samples currently supports:  \n');
107                    fprintf('    Number  - (ie 2^15) \n');
108                    fprintf('    "max"   - Set the number of samples to the maximum number of samples supported by the board \n');
109                    error('Unknown argument: %s \n', varargin{4} );
110                end
111
112                % Error checking for num_*_samples is done below on a per node basis
113
114            otherwise
115                error('Unknown argument.  Argument is of type "%s", need "double" or "char"', class(varargin{4}));
116        end
117
118        % Default to 1 buffer if num_buffers is not specified       
119        if (nargin == 5) 
120            switch( class(varargin{5}) ) 
121                case 'double'
122                    num_buffers = varargin{5};
123                   
124                    if ( num_buffers <= 0 )
125                        num_buffers = 1;
126                    end
127
128                otherwise
129                    error('Unknown argument.  Argument is of type "%s", need "double"', class(varargin{5}));
130            end
131        else
132            num_buffers = 1;
133        end
134    else
135        error('Arguments incorrect.  Please see usage.');
136    end
137
138   
139
140    if ( interactive_mode ) 
141
142        fprintf('------------------------------------------------------------\n');
143        fprintf('Please select benchmark to run:\n');
144        fprintf('    [ 1] Read IQ \n');
145        fprintf('    [ 2] Write IQ \n');
146        fprintf('    [99] Quit       (default) \n');
147
148        temp = input('Enter benchmark number: ','s');
149        if(isempty(temp))
150            temp = benchmark;
151            fprintf('   quitting.\n');
152            return
153        else
154            fprintf('   running test %s\n',temp); 
155            benchmark = str2num( temp );
156        end
157
158        %----------------------------------------------------------------------
159        % Specific Arguments for each benchmark
160        %
161        switch( benchmark ) 
162       
163            %------------------------------------------------------------------
164            % Read IQ Benchmark
165            %
166            case 1
167                fprintf('------------------------------------------------------------\n');
168                temp = input('Please enter the number of samples (default = Read IQ length of board): ','s');
169                if(isempty(temp))
170                    fprintf('   defaulting to Read IQ length of the board \n');
171                else
172                    fprintf('   setting to %s (will be truncated to Read IQ length of the board)\n',temp); 
173                    num_rx_samples = str2num( temp );
174                end
175
176            %------------------------------------------------------------------
177            % Write IQ Benchmark
178            %
179            case 2
180                fprintf('------------------------------------------------------------\n');
181                temp = input('Please enter the number of samples (default = Write IQ length of board): ','s');
182                if(isempty(temp))
183                    fprintf('   defaulting to Write IQ length of the board \n');
184                else
185                    fprintf('   setting to %s (will be truncated to Write IQ length of the board)\n',temp); 
186                    num_tx_samples = str2num( temp );
187                end
188           
189            %------------------------------------------------------------------
190            % Default case
191            %
192            otherwise
193                fprintf('Invalid benchmark selection.  Quitting.  \n');
194                return
195               
196        end
197
198        %----------------------------------------------------------------------
199        % Common Arguments for all benchmarks
200        %
201        fprintf('------------------------------------------------------------\n');
202        temp = input('Please enter the number of trials (default = 1000): ','s');
203        if(isempty(temp))
204            temp = sprintf('%d', num_trials);
205            fprintf('   defaulting to %s \n', temp);
206        else
207            num_trials = str2num( temp );
208           
209            if ( num_trials <= 0 )
210                num_trials = 1;
211                fprintf('   setting to 1 \n'); 
212            else
213                fprintf('   setting to %s \n',temp); 
214            end           
215        end
216   
217    end  % END interactive_mode
218   
219   
220   
221    %--------------------------------------------------------------------------
222    % Run the benchmark
223    %
224   
225    fprintf('------------------------------------------------------------\n');
226   
227    results  = [];
228    RxLength = num_rx_samples;
229    TxLength = num_tx_samples;
230
231    for n = 1:1:numNodes
232        currNode = nodes(n);
233       
234        % Set the severity of the sequence number matching to IGNORE
235        curr_severity = currNode.baseband.seq_num_match_severity;
236        currNode.baseband.seq_num_match_severity = currNode.baseband.SEQ_NUM_MATCH_IGNORE;
237
238        %----------------------------------------------------------------------
239        % Common Parameters for all benchmarks
240        %       
241        if(currNode.hwVer == 3)
242            SN = sprintf('W3-a-%05d',currNode.serialNumber);
243        else
244            SN = 'Serial Number N/A';
245        end
246       
247        ifc_ids        = currNode.wl_getInterfaceIDs();
248        maximum_rx_len = wl_basebandCmd(currNode, ifc_ids.RF_A, 'rx_buff_max_num_samples');
249
250        if ( ( RxLength == 0 ) || ( RxLength > maximum_rx_len ) )
251            RxLength       = maximum_rx_len;
252            num_rx_samples = RxLength;
253        end
254
255        maximum_tx_len = wl_basebandCmd(currNode, ifc_ids.RF_A, 'tx_buff_max_num_samples');
256       
257        if ( ( TxLength == 0 ) || ( TxLength > maximum_tx_len ) )
258            TxLength       = maximum_tx_len;
259            num_tx_samples = TxLength;
260        end
261       
262        % Set up the buffers to transfer       
263        if (num_buffers <= currNode.num_interfaces)
264            switch (num_buffers)
265                case 1
266                    RF_INF = [ifc_ids.RF_A];
267                case 2
268                    RF_INF = [ifc_ids.RF_A, ifc_ids.RF_B];
269                case 3
270                    RF_INF = [ifc_ids.RF_A, ifc_ids.RF_B, ifc_ids.RF_C];
271                case 4
272                    RF_INF = [ifc_ids.RF_A, ifc_ids.RF_B, ifc_ids.RF_C, ifc_ids.RF_D];
273            end
274        else
275            error('Node does not support that many buffers');
276        end       
277       
278       
279        % Run Benchmark       
280        %
281        % NOTE:  To get a look at the memory used during each benchmark, use the following
282        %     commands to print memory usage:
283        %         x = memory;
284        %         fprintf('Memory Usage = %20d\n', x.MemUsedMATLAB);
285        %
286        switch( benchmark ) 
287       
288            %------------------------------------------------------------------
289            % Read IQ Benchmark
290            %
291            case 1
292               fprintf('Read IQ running on node %d of %d:  ID = %4s  Serial Number = %12s  Num samples = %10d  Num buffers = %5d\n', n, numNodes, sprintf('%d',currNode.ID), SN, RxLength, num_buffers);
293               
294                rx_time = zeros(num_trials, 1);
295
296                i = num_trials;
297
298                % Test TX performance of node
299                while( i > 0 )
300                   
301                    xt = tic;
302                   
303                    rx_IQ        = wl_basebandCmd(currNode, RF_INF, 'read_IQ', 0, RxLength);                   
304                   
305                    rx_time(i,1) = toc(xt);
306                   
307                    % NOTE:  We clear the rx_IQ variable so that it is not maintained in memory during the
308                    %     next Read IQ, thereby doubling the memory required for the test.
309                    clear rx_IQ;
310                   
311                    i = i - 1;
312                end
313
314                if ( num_trials > 5 ) 
315                    rx_min_time = min(  rx_time(1:(num_trials - 5),:) );
316                    rx_max_time = max(  rx_time(1:(num_trials - 5),:) );
317                    rx_avg_time = mean( rx_time(1:(num_trials - 5),:) );
318                else
319                    rx_min_time = min(  rx_time(1:(num_trials),:) );
320                    rx_max_time = max(  rx_time(1:(num_trials),:) );
321                    rx_avg_time = mean( rx_time(1:(num_trials),:) );               
322                end
323           
324                sec_ota_time(n) = RxLength / 40e6;                                       % Each sample is at 40 MHz
325                sec_per_iq(n)   = rx_avg_time(1) / num_buffers;                          % Average IQ time over all trials (for a single buffer)
326                bits_per_sec(n) = ((RxLength * num_buffers * 4 * 8) / rx_avg_time(1));   % Each sample is 4 bytes; 8 bits per byte
327               
328           
329            %------------------------------------------------------------------
330            % Write IQ Benchmark
331            %
332            case 2
333                fprintf('Write IQ running on node %d of %d:  ID = %4s  Serial Number = %12s  Num samples = %10d  Num buffers = %5d\n', n, numNodes, sprintf('%d',currNode.ID), SN, TxLength, num_buffers );
334
335                TxData  = zeros(TxLength, 1, 'double');
336                tx_time = zeros(num_trials, 1);
337   
338                i = num_trials;
339                               
340                % Test RX performance of node
341                while ( i > 0 )
342                    xt = tic;
343                    wl_basebandCmd(currNode, RF_INF, 'write_IQ', TxData);
344                    tx_time(i,1) = toc(xt);
345                   
346                    i = i - 1;
347                end
348
349                if ( num_trials > 5 ) 
350                    tx_min_time = min(  tx_time(1:(num_trials - 5),:) );
351                    tx_max_time = max(  tx_time(1:(num_trials - 5),:) );
352                    tx_avg_time = mean( tx_time(1:(num_trials - 5),:) );
353                else
354                    tx_min_time = min(  tx_time(1:(num_trials),:) );
355                    tx_max_time = max(  tx_time(1:(num_trials),:) );
356                    tx_avg_time = mean( tx_time(1:(num_trials),:) );
357                end
358
359                sec_ota_time(n) = TxLength / 40e6;                         % Each sample is at 40 MHz
360                sec_per_iq(n)   = tx_avg_time(1);                          % Average IQ time over all trials
361                bits_per_sec(n) = ((TxLength * 4 * 8) / tx_avg_time(1));   % Each sample is 4 bytes; 8 bits per byte
362               
363           
364            %------------------------------------------------------------------
365            % Default case
366            %
367            otherwise
368                fprintf('Invalid benchmark selection.  Quitting.  \n');
369                return
370               
371        end  % END switch( benchmark )
372       
373        % Restore the severity of the sequence number matching on the node
374        currNode.baseband.seq_num_match_severity = curr_severity;
375       
376    end  % END for each node   
377
378
379    %--------------------------------------------------------------------------
380    % Print the benchmark results
381    %
382    fprintf('------------------------------------------------------------\n');
383    fprintf('Displaying results of %d nodes:\n\n', n);
384
385    extraTitle = '';
386    extraLine  = '';
387    extraArgs  = '';
388   
389    switch( benchmark ) 
390
391        %----------------------------------------------------------------------
392        % Read IQ Benchmark
393        %
394        case 1
395            extraTitle = '   Transport | MTU Size (B) | Num Samples | TX/RX Time (ms) | Num Trials | Avg Read  IQ Time (ms) | Avg Transfer Speed (Mbps) |';
396            extraLine  = '-------------------------------------------------------------------------------------------------------------------------------';
397       
398        %----------------------------------------------------------------------
399        % Write IQ Benchmark
400        %
401        case 2
402            extraTitle = '   Transport | MTU Size (B) | Num Samples | TX/RX Time (ms) | Num Trials | Avg Write IQ Time (ms) | Avg Transfer Speed (Mbps) |';
403            extraLine  = '-----------------------------------------------------------------------------------------------------------------------------';
404       
405        %----------------------------------------------------------------------
406        % Default case
407        %
408        otherwise
409            fprintf('Invalid benchmark selection.  Quitting.  \n');
410            return
411           
412    end  % END switch( benchmark )
413
414
415    fprintf('------------------------------%s\n',extraLine);
416    fprintf('|  ID |  WLVER |    Serial # |%s\n',extraTitle);
417    fprintf('------------------------------%s\n',extraLine);
418
419    for n = 1:1:numNodes
420        currNode = nodes(n);
421
422        ID       = sprintf('%d', currNode.ID);
423        WLVER    = sprintf('%d.%d.%d',currNode.wlVer_major,currNode.wlVer_minor,currNode.wlVer_revision);
424        HWVER    = sprintf('%d', currNode.hwVer);
425        MTU_SIZE = sprintf('%d', currNode.transport.getMaxPayload());
426           
427        if(currNode.hwVer == 3)
428            SN = sprintf('W3-a-%05d',currNode.serialNumber);
429        else
430            SN = 'N/A';
431        end
432       
433        if( strcmp( class(currNode.transport), 'wl_transport_eth_udp_mex' ) )
434            TPORT = 'WL Mex UDP';
435        elseif ( strcmp( class(currNode.transport), 'wl_transport_eth_udp_java' ) )
436            TPORT = 'Java UDP';
437        else
438            TPORT = 'N/A';
439        end
440
441
442        switch( benchmark ) 
443
444            %------------------------------------------------------------------
445            % Read IQ Benchmark
446            %
447            case 1
448                extraArgs = sprintf('%12s |%13s |%12d |%16.2f |%11d |%23.2f |%26.2f |',TPORT, MTU_SIZE, num_rx_samples, (sec_ota_time(n) * 1e3), num_trials, (sec_per_iq(n) * 1e3), (bits_per_sec(n) / 1e6) );
449           
450            %------------------------------------------------------------------
451            % Write IQ Benchmark
452            %
453            case 2
454                extraArgs = sprintf('%12s |%13s |%12d |%16.2f |%11d |%23.2f |%26.2f |',TPORT, MTU_SIZE, num_tx_samples, (sec_ota_time(n) * 1e3), num_trials, (sec_per_iq(n) * 1e3), (bits_per_sec(n) / 1e6) );
455           
456            %------------------------------------------------------------------
457            % Default case
458            %
459            otherwise
460                fprintf('Invalid benchmark selection.  Quitting.  \n');
461                return
462               
463        end  % END switch( benchmark )
464               
465        fprintf('|%4s |%7s |%12s |%s\n',ID,WLVER,SN,extraArgs);
466        fprintf('------------------------------%s\n',extraLine);
467    end
468
469    fprintf('\n');
470
471   
472    %--------------------------------------------------------------------------
473    % Set outputs
474    %
475    if nargout == 0
476        return
477    elseif nargout == 1
478        data = results;
479    else
480        error('Too many output arguments provided');   
481    end
482   
483end
484
485
486
Note: See TracBrowser for help on using the repository browser.