• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

llcontrol-core.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  *
00003  * File: llcontrol-core.c
00004  *
00005  * $RCSfile: llcontrol-core.c,v $
00006  * 
00007  * Copyright (C) 2001 D-TACQ Solutions Ltd
00008  * not to be used without owner's permission
00009  *
00010  * Description:
00011  *     application implementing the LOW LATENCY CONTROL feature
00012  *
00013  * $Id: llcontrol-core.c,v 1.1.4.33 2010/08/26 16:25:52 pgm Exp $
00014  * $Log: llcontrol-core.c,v $
00015  * Revision 1.1.4.33  2010/08/26 16:25:52  pgm
00016  * more switchable instrumentation
00017  *
00018  * Revision 1.1.4.32  2009/09/29 13:09:14  pgm
00019  * RFM emulation (not complete)
00020  *
00021  * Revision 1.1.4.31  2009/04/02 13:19:01  pgm
00022  * docs away
00023  *
00024  * Revision 1.1.4.30  2009/03/28 22:23:05  pgm
00025  * ao32cpci first cut looks good
00026  *
00027  * Revision 1.1.4.29  2009/03/28 18:47:39  pgm
00028  * sync2VAO32 take 1
00029  *
00030  * Revision 1.1.4.28  2009/03/26 14:52:03  pgm
00031  * split sync2v, acq216 from main core
00032  *
00033  * Revision 1.1.4.27  2009/03/26 12:40:36  pgm
00034  * reuse same dac_src for each card, avoid data overrun
00035  *
00036  * Revision 1.1.4.26  2007/02/19 15:22:23  pgm
00037  * *** empty log message ***
00038  *
00039  * Revision 1.1.4.25  2006/02/23 21:56:40  pgm
00040  * remove unwanted statics
00041  *
00042  * Revision 1.1.4.24  2006/02/22 11:15:36  pgm
00043  * ensure tlatch zero in case of code re-use without new process create
00044  *
00045  * Revision 1.1.4.23  2006/01/28 18:18:55  pgm
00046  * ST_CAPDONE
00047  *
00048  * Revision 1.1.4.22  2006/01/19 20:15:28  pgm
00049  * *** empty log message ***
00050  *
00051  * Revision 1.1.4.21  2006/01/15 11:18:18  pgm
00052  * SYNC_2V
00053  *
00054  * Revision 1.1.4.20  2006/01/09 13:40:31  pgm
00055  * SYNC_2V mode implemented
00056  *
00057  * Revision 1.1.4.19  2005/11/30 10:52:53  pgm
00058  * *** empty log message ***
00059  *
00060  * Revision 1.1.4.18  2005/11/04 17:26:18  pgm
00061  * *** empty log message ***
00062  *
00063  * Revision 1.1.4.17  2005/10/22 12:18:56  pgm
00064  * *** empty log message ***
00065  *
00066  * Revision 1.1.4.16  2005/10/20 20:51:00  pgm
00067  * *** empty log message ***
00068  *
00069  * Revision 1.1.4.15  2005/10/03 15:03:48  pgm
00070  * acq216 llc with prams
00071  *
00072  * Revision 1.1.4.14  2005/09/25 20:32:34  pgm
00073  * LLCV2 initial poll corrected
00074  *
00075  * Revision 1.1.4.13  2005/08/12 20:28:20  pgm
00076  * *** empty log message ***
00077  *
00078  * Revision 1.1.4.12  2005/08/12 10:05:53  pgm
00079  * *** empty log message ***
00080  *
00081  * Revision 1.1.4.11  2005/08/12 09:51:25  pgm
00082  * *** empty log message ***
00083  *
00084  * Revision 1.1.4.10  2005/08/11 10:02:24  pgm
00085  * SYNC_ECM - init host side slave memory areas
00086  *
00087  * Revision 1.1.4.9  2005/08/01 12:39:55  pgm
00088  * includes bridge test
00089  *
00090  * Revision 1.1.4.8  2005/08/01 11:10:24  pgm
00091  * V2 part 1 running - local status, no hbpoll - ECM 100 achieved
00092  *
00093  * Revision 1.1.4.7  2004/12/13 21:39:15  pgm
00094  * correct DAC base offset
00095  *
00096  * Revision 1.1.4.6  2004/12/10 12:01:26  pgm
00097  * fix timing
00098  *
00099  * Revision 1.1.4.5  2004/12/09 22:31:57  pgm
00100  * microsecond timestamps do the BIZ - ECM20 here we go
00101  *
00102  * Revision 1.1.4.4  2004/12/09 12:58:34  pgm
00103  * various attempts at repartitioning for speed
00104  *
00105  * Revision 1.1.4.3  2004/12/08 14:51:39  pgm
00106  * *** empty log message ***
00107  *
00108  * Revision 1.1.4.2  2004/11/14 09:50:44  pgm
00109  * Doxygen type docs
00110  *
00111  * Revision 1.1.4.1  2004/11/04 07:13:13  pgm
00112  * merged multicard case
00113  *
00114  * Revision 1.1.2.8  2004/09/26 19:50:58  pgm
00115  * *** empty log message ***
00116  *
00117  * Revision 1.1.2.7  2004/09/26 15:28:40  pgm
00118  * *** empty log message ***
00119  *
00120  * Revision 1.1.2.6  2004/09/26 11:32:38  pgm
00121  * multiboard tstats pollstats in
00122  *
00123  * Revision 1.1.2.5  2004/09/25 21:16:28  pgm
00124  * multiboard case runs
00125  *
00126  * Revision 1.1.2.4  2004/09/25 11:53:03  pgm
00127  * first pass multi done - check it works for n==1
00128  *
00129  * Revision 1.1.2.3  2004/09/25 09:12:35  pgm
00130  * *** empty log message ***
00131  *
00132  * Revision 1.1.2.2  2004/09/25 09:08:31  pgm
00133  * first UI/test split
00134  *
00135  * Revision 1.1.2.1  2004/09/25 08:44:47  pgm
00136  * *** empty log message ***
00137  *
00138  */
00139 
00140 
00141 /** @file llcontrol-core.c module implements the core of llcontrol loop.
00142  *
00143  - mmapMboxes() - get app mapping for mailboxes
00144 
00145  - mmapBuffer() - get dmabuff and phys addresses
00146 
00147  - runSCM() - capture using soft trigger
00148 
00149  - runECM() - capture using external clock
00150 <p>
00151 <h2>Linux 2.4 Host Only:</h2>
00152 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4
00153 
00154   Note on HOST MEMORY MAP: assumes bootcommand configured as follows,
00155   to allow a 16MB host area per card in at the top of memory.
00156   This host area will be slaved off the pci backplane
00157 
00158  - mem=NNN restrict memory for Linux. Must allow Nx16MB + gap
00159  - acq32_big_buf_base=0xnnnn : informs driver of start of area
00160  - acq32_big_buf_len=0xxxxx  : informs driver of length of area
00161 
00162 eg
00163 
00164 [dt100@cp605 dt100]$ cat /proc/cmdline mem=320M acq32.load_order=slotbased 
00165 
00166  acq32_big_buf_base=0x18000000 acq32_big_buf_len=0x08000000
00167 
00168 For the purpose of LLCONTROL, each 16MB card are is used as follows:
00169 
00170 - 0x000000 .. 0xefffff (15MB) - AI reception area (controlled by client app).
00171 - 0xf00000 .. 0xffffff (1MB)  - message buffers (owned by target).
00172 
00173 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4 2.4
00174 
00175 
00176 This means that if the llcontrol app is using an incrementing memory
00177 strategy in host buffer for AI, this is subject to max 15MB
00178 (80K samples at 96 channels).
00179 
00180 The message buffers are used for DAC output. 
00181 The application reserves a Mesage Frame Address (MFA) from the target 
00182 before copying data to slave memory.
00183 The MFA is an index into the message buffer memory.
00184 
00185 </p>
00186 
00187 <h2>Linux 2.6 Host: </h2>
00188 the host buffer is setup dynamically, but is LIMITED to 4MB, 
00189 of which the top 1M is used for messaging.
00190 
00191 */
00192 
00193 
00194 
00195 #include "local.h"
00196 
00197 #include <assert.h>
00198 #include <stdio.h>
00199 #include <stdlib.h>
00200 
00201 #include <errno.h>
00202 #include <fcntl.h>
00203 #include <sys/ioctl.h>
00204 #include <sys/mman.h>
00205 #include <sys/stat.h>
00206 #include <sys/time.h>
00207 #include <sys/types.h>
00208 #include <stdio.h>
00209 #include <unistd.h>
00210 
00211 #include <popt.h>
00212 
00213 #include "acq32ioctl.h"
00214 #include "acq32busprot.h"
00215 
00216 #include "llif.h"
00217 #include "llprotocol.h"
00218 
00219 
00220 #include "llcontrol.h"
00221 #include "x86timer.h"
00222 
00223 #ifdef __ACQ196__
00224 #define FLAVOR "ACQ196"
00225 #else
00226 #define FLAVOR "ACQ32"
00227 #endif
00228 
00229 
00230 #include "llcontrol-core.h"
00231 
00232 const char* core_ident = "$Revision: 1.1.4.33 $ B1102\n";
00233 
00234 
00235 
00236 
00237 
00238 static void mbox_updateTstats(
00239         u32 cmd, struct Card* card, struct TimingStats* tstats)
00240 /** update timing stats from card mailbox. */
00241 {
00242         llSetCmd(card->mbx, cmd+LLC_CSR_M_READCTR);
00243         tstats->tinst      = llGetTinst(card->mbx);       
00244         tstats->tprocess   = llGetTprocess(card->mbx);
00245 
00246 /** @todo - with hbpoll ON, WaitDmaDone should be a formality -
00247  * single poll to confirm done - we should CHECK THIS IS TRUE
00248  */
00249         PRINTF(2)( "Capture Done: [%d] Tsample:%d Tprocess:%d Tnow:%d\n",
00250                    card->slot,
00251                    tstats->tlatch, tstats->tprocess, tstats->tinst );
00252 }
00253 
00254 
00255 
00256 
00257 void v2_updateTstats(
00258         u32 cmd, struct Card* card, struct TimingStats* tstats)
00259 /** updates timing stats from embedded host buffer data */
00260 {
00261         u32* stats = getVaddr(card->buf, LLCV2_OFFSET_STATUS_HSBT);
00262         tstats->tinst = llv2_extend32(stats[BP_MB_LLC_TINST], 
00263                                       stats[LLCV2_STATUS_TINST]);
00264         tstats->tprocess = LLC_GET_TCYCLE(stats[BP_MB_LLC_CSR]);
00265 }
00266 
00267 
00268 void (*updateTstats)(u32 cmd, struct Card* card, struct TimingStats* tstats) = 
00269         mbox_updateTstats;
00270 /**< virtual function to retrieve timing stats.
00271  *  defaults to V1 mode mbox_updateTstats().
00272  */
00273 
00274 
00275 
00276 void doApplicationWork(struct TestDescription* td, u32 offset)
00277 /* copy data to a user buffer. A real app may do more than this ;-) */
00278 {
00279         EACHCARD_INIT;
00280         int work_len = td_sample_size(td);
00281         int work_offset = td->iter * work_len;
00282 
00283         FOREACHCARD{
00284                 memcpy(td->work_buf[icard]+work_offset,
00285                        getVaddr(EACHBUF(td), offset),
00286                        work_len);
00287         }
00288 }
00289 
00290 
00291 
00292 static u32 card_v1_WaitDmaDone(struct Card* card)
00293 {
00294         return llWaitDmaDone(card->mbx);
00295 }
00296 
00297 u32 card_v2_WaitDmaDone(struct Card* card)
00298 {
00299         return llv2WaitDmaDone(card->mbx, 
00300                                getVaddr(card->buf, LLCV2_OFFSET_STATUS_HSBT));
00301 }
00302 
00303 
00304 
00305 u32 (*waitDmaDone)(struct Card *c) = card_v1_WaitDmaDone;
00306 /**< virtual function to block until DMA done.
00307  *  defaults to V1 mbox
00308  */
00309 
00310         
00311 int user_abort = 0;    /** @todo could be set by a signal */
00312 
00313 static int do_run( struct TestDescription* td, int soft_clock )
00314 /** runs the test.
00315  * PSEUDO-CODE:
00316  *
00317  - (1) Clear the latch timer
00318  - (2) Set a local memory target address and arm the capture
00319  - (3) Poll for counter running (hardware counter starts on external gate)
00320  - (4) Iterate for required number of samples:
00321  - (5)     [optionally send a soft clock command]  trigger an acquisition
00322  - (6)     Wait for DMA Done - at this point data is available in target mem.
00323  *         A "real" control application is probably getting most of its calcs 
00324  *         done here rather than simply polling
00325  - (7)     [Get the latch (sample) and current uSec counters from the boards - 
00326  *          only if interested]
00327  - (8)     Check the process has not stopped (external gate high)
00328  - (9)     [optionally update the target address - else it gets overwritten]
00329  - (a)     using DACS - preallocate a MFA for dac data.
00330  - (b)     write data to host side buffer(f(MFA)) and post MFA
00331  - (b.1)
00332          * take the incoming value on feedback_channel
00333          * and propagate to all DACS.
00334          * default is to assume HAWG on DAC0
00335          * (so feedback_channel better be 0 !),
00336          * but td->update_dacs makes a better test.
00337  - (b.15)  
00338          * special case where we are DRIVING the
00339          * initial DAC signal from host side. 
00340  - (b.2)
00341          *  simple feedforward case - just drive all DACS
00342          *  from AWG pattern.
00343 
00344  - (c)     later, pick up another MFA
00345  - (d)     finally, return final set of MFA's. might be a good idea to ensure 
00346            data is zero at this point
00347  */
00348 {
00349         struct TimingStats tstats[MAXCARDS] = {};
00350         struct DacBuf {
00351                 MFA mfa;
00352                 void* bbb;
00353         } dac_buf[MAXCARDS];
00354 #define EACHMFA      (dac_buf[icard].mfa)
00355 #define EACHBBB      (dac_buf[icard].bbb)
00356 #define EACHDAC_BASE (EACHBBB + EACHMFA)
00357 #define EACHDAC_BASE16 ((u16*)EACHDAC_BASE)
00358 
00359         u32 cmd = LLC_MAKE_DECIM(td->decimation);
00360         u32 offset = 0;
00361 
00362         unsigned ipoll = 0;
00363         int uses_dacs = td->update_dacs || td->feedback;
00364 
00365         EACHCARD_INIT;
00366 
00367         if (uses_dacs) FOREACHCARD { /* (a) */
00368                 EACHBBB = getVaddr(EACHBUF(td), 0);
00369                 EACHMFA = mu_reserveOutbound(EACHMBX(td));
00370         }
00371         FOREACHCARD{ /* (1) */
00372                 llSetTlatch(EACHMBX(td), tstats[icard].tlatch = 0xffffffff);
00373         }
00374    
00375         FOREACHCARD{ /* (2) */
00376                 updateTargetAddr(cmd+LLC_CSR_M_ARM, EACHCARD(td), offset);
00377         }
00378 
00379 
00380         if (td->update_dacs){
00381                 void *dac_src = td_get_next_dac_data(td);
00382                 FOREACHCARD{
00383                         llSetDacs(EACHMBX(td), dac_src,
00384                                         (char*)getVaddr(EACHBUF(td), 0));
00385                 }
00386         }
00387         // wait for gate /* (3) */
00388 
00389         while( !llCounterRunning(FIRSTMBX(td), cmd) ){ 
00390                 POLLALERT(ipoll, "Polling for Counter Running\n");
00391         }
00392 
00393         INIT_TIMER;
00394         /* WORKTODO - assumes all cards now running */
00395 
00396         
00397         for ( td->iter = 0; td->iter != td->iterations; ++td->iter ){ /* (4) */
00398                 if (soft_clock) FOREACHCARD{ /* (5) */
00399                         llSetCmd(EACHMBX(td), cmd+LLC_CSR_M_SOFTCLOCK);
00400                 }
00401         
00402                 if (td->hb_polling) FOREACHCARD{
00403                         MARK_TIME(0, "hb_polling");
00404                         tstats[icard].hb_poll = 
00405                                 hbPoll(EACHBUF(td), offset, 
00406                                         td->channels*2, &user_abort);
00407                 }
00408 
00409                 
00410                 FOREACHCARD{                                  /* (6)+(7) */
00411                         MARK_TIME(1, "waitDmaDone() before");
00412                         tstats[icard].tlatch = waitDmaDone(EACHCARD(td));
00413                         MARK_TIME(2, "waitDmaDone() after");
00414                 }
00415 
00416                 if (!td->min_latency_test) FOREACHCARD{        /* (6)+(7) */
00417                         updateTstats(cmd, EACHCARD(td), &tstats[icard]);    
00418                 }
00419 
00420                 
00421                 if (td->do_work){
00422                         doApplicationWork(td, offset);
00423                 }
00424 
00425                 if (td->feedback) { /* (b.1) */
00426                         u16 *pvin = (u16 *)getVaddr(FIRSTBUF(td), offset);
00427                         u16 vin = pvin[td->feedback_channel];
00428                         u32 feedback = vin << 16 | vin;
00429 
00430                         PRINTF(1)("feedback 0x%08x\n", feedback);
00431 
00432                         FOREACHCARD{   
00433                                 MARK_TIME(3, "feedback 1");
00434                                 memset32(EACHDAC_BASE, feedback, DAC_COUNT/2);
00435 
00436                                 if (td->update_dacs){ /* (b.15) */
00437 
00438                                         u16* excite = td_get_next_dac_data(td);
00439                                 
00440                                         EACHDAC_BASE16[td->feedback_channel] 
00441                                          = excite[td->feedback_channel];
00442                                 }
00443                                 MARK_TIME(4, "feedback 2");
00444                                 mu_putOutbound(EACHMBX(td), EACHMFA); 
00445                                 MARK_TIME(5, "feedback 3");
00446                         }
00447                 }else if (td->update_dacs){ /** (b.2) */
00448                         void* dac_data = td_get_next_dac_data(td);
00449                         FOREACHCARD{
00450                                 memcpy(EACHDAC_BASE, 
00451                                        dac_data+icard*32,
00452                                        DAC_SAMPLE_SIZE);
00453                                 mu_putOutbound(EACHMBX(td), EACHMFA);
00454                         }
00455 
00456                 }
00457                 
00458                 /* check process completion.
00459                  * if hardware_gateoff is employed, then the app would need
00460                  * to make use of a pre-arranged DIO encoding for on/off instead                 */
00461                  
00462                 if (!td->hardware_gate_off &&
00463                      !llCounterRunning(FIRSTMBX(td), cmd )){          /* (8) */
00464                         fprintf( stderr, "Trigger is off - stop\n" );
00465                         break;
00466                 }
00467                 
00468                 FOREACHCARD_MARK_TIME(6, "after llCounterRunning check");
00469 
00470                 // maybe set new target addr
00471 
00472                 if ( !td->overwrite ){
00473                         offset += td->sample_offset;
00474 
00475                         FOREACHCARD{                                    /* 9 */
00476                                 updateTargetAddr(cmd, EACHCARD(td), offset);
00477                                 MARK_TIME(7, "after updateTargetAddr");
00478                         }
00479                 }else{
00480                         if (td->hb_polling) FOREACHCARD{
00481                                 hbPrimePoll(EACHBUF(td), 
00482                                             offset, td_sample_size(td));
00483                                 MARK_TIME(7, "after hbPrimePoll");
00484                         }
00485                 }
00486 
00487                 // maybe wait for an interval 
00488                 // (crudely simulate the effect of control calculation!)
00489 
00490                 if ( td->arg.interval ){
00491                         u32 tinst;
00492 
00493                         printf("hello interval %d\n", td->arg.interval);
00494                         do {
00495                                 llSetCmd(FIRSTMBX(td), cmd+LLC_CSR_M_READCTR);
00496                                 tinst = llGetTinst(FIRSTMBX(td));
00497                         }
00498                         while ( tinst - tstats[0].tlatch < td->arg.interval );
00499                 }
00500 
00501                 if (uses_dacs){
00502                         FOREACHCARD{ /* (c) */
00503                                 MARK_TIME(8, "mu_reserveOutbound() before");
00504                                 EACHMFA = mu_reserveOutbound(EACHMBX(td));
00505                                 MARK_TIME(9, "mu_reserveOutbound() after");
00506                         }                       
00507                 }
00508 
00509                 if (td->tlog){          
00510                         FOREACHCARD{
00511                                 tstats[icard].target_poll =
00512                                         getMboxPollcount(EACHMBX(td));
00513                                 MARK_TIME(10, "10");
00514                                 updateTimingStats(
00515                                         td->stats_buf[icard], 
00516                                         td->iter, 
00517                                         &tstats[icard]);
00518                                 MARK_TIME(11, "11");
00519                         }
00520                 }       
00521                 TIMER_CHECK_OVERFLOW;
00522         }
00523         
00524         if (uses_dacs) FOREACHCARD{ /* (d) */
00525                mu_putOutbound(EACHMBX(td), EACHMFA);
00526         }                       
00527         G_quit = 1;
00528         return 0;
00529 #undef EACHMFA
00530 #undef EACHBBB
00531 #undef EACHDAC_BASE
00532 #undef EACHDAC_BASE16
00533 }
00534 
00535 
00536 
00537 static int runSCM( struct TestDescription* td )
00538 /** Run a Test - Soft Clock Master. */
00539 {
00540         return do_run( td, 1 );
00541 }
00542  
00543 
00544 
00545 
00546  
00547 static int runECM( struct TestDescription* td )
00548 /** Run a Test - External Clock Master. */
00549 {
00550         return do_run ( td, 0 );
00551 }
00552 
00553 u32 commandModifiers(struct TestDescription *td) {
00554         u32 mods = 0;
00555 
00556         if (td->V2_BUFS[LLCV2_INIT_MARKER] == LLCV2_INIT_MAGIC_MARKER){
00557                 mods |= BP_FC_SET_LLCV2_INIT;
00558         }
00559 
00560         return mods;
00561 }
00562 
00563 
00564 
00565 static int measureBridge(struct MU *mu) 
00566 /** Run a test - measureBridge performance. */
00567 {
00568 #define NMEASURE 20
00569         static struct {
00570                 unsigned elapsed;
00571                 u32 mbox;
00572         } stats[NMEASURE];
00573         int im;
00574         unsigned sum = 0;
00575         
00576         for (im = 0; im != NMEASURE; ++im){
00577                 INIT_TIMER;
00578                 stats[im].mbox = getMbox(mu, 3);
00579                 stats[im].elapsed = get_elapsed_microseconds(0);
00580 
00581                 usleep(10000);
00582         }      
00583 
00584         fprintf(stderr, "[%2s], %10s, %10s\n","id", "mbox3", "usecs");
00585         for (im = 0; im != NMEASURE; ++im){
00586                 sum += stats[im].elapsed;
00587 
00588                 fprintf(stderr, "[%2d], 0x%08x, %10d\n",
00589                         im, stats[im].mbox, stats[im].elapsed);
00590         }
00591 
00592         fprintf(stderr, "mean  %10s, %12.1f\n", "", (float)sum/NMEASURE);
00593         return 0;
00594 }
00595 
00596 static int measureBridgeStats(struct TestDescription *td, struct MU *mu)
00597 {
00598         static struct {
00599                 int min;
00600                 int max;
00601                 int sum;
00602                 int samples;
00603         } stats = { 1000000, -1000000, 0, 0 };
00604 
00605         int im;
00606         int current;
00607         EACHCARD_INIT;
00608 
00609 
00610         if ( td->mask_ints ){
00611                 PRINTF(1)( "mask ints 0x%04x\n", td->mask_ints_mask );
00612                 FOREACHCARD{
00613                         acq32_maskInts(EACHMBX(td), td->mask_ints_mask);
00614                 }
00615         }
00616 
00617         for (im = 0; im != td->iterations; ++im){
00618                 INIT_TIMER;
00619                 getMbox(mu, 3);
00620                 
00621                 current = get_elapsed_microseconds(0);
00622 
00623                 if (current < stats.min){
00624                         stats.min = current;
00625                 }else if (current > stats.max){
00626                         stats.max = current;
00627                 }
00628                 stats.sum += current;
00629                 stats.samples++;
00630         }
00631 
00632         if (td->mask_ints){
00633                 FOREACHCARD{
00634                         acq32_enableInts(EACHMBX(td), td->mask_ints_mask);
00635                 }
00636         }
00637 
00638         fprintf(stderr, "measureBridgeStats results from %d polls\n", 
00639                 stats.samples);
00640         fprintf(stderr, "%10s %d\n", "min", stats.min);
00641         fprintf(stderr, "%10s %d\n", "max", stats.max);
00642         fprintf(stderr, "%10s %.2f\n", "mean", (float)stats.sum/stats.samples);
00643         return 0;
00644 }
00645 
00646 int runTest( struct TestDescription* td )
00647 /** generic top level text exec. */
00648 {
00649         int rc = 0;
00650         int status;
00651         EACHCARD_INIT;
00652 
00653         PRINTF(1)("runTest mode %d\n", td->mode);
00654 
00655         if ((status = sigsetjmp(G_env, 1)) == 0){
00656                 if ( td->tlog ){
00657                         int ne = td->iterations;
00658                         FOREACHCARD{
00659                                 td->stats_buf[icard] = 
00660                                         calloc(sizeof(struct TimingStats), ne);
00661                                 assert(td->stats_buf[icard]);
00662                         }
00663                 }
00664 
00665                 if ( td->mask_ints ){
00666                         PRINTF(1)( "mask ints 0x%04x\n", td->mask_ints_mask );
00667                         FOREACHCARD{
00668                                 acq32_maskInts(EACHMBX(td), 
00669                                                td->mask_ints_mask);
00670                         }
00671                 }
00672 
00673                 switch( td->mode ){
00674                 case M_NULL:
00675                         FOREACHCARD{
00676                                 enterLLCSoftClock(EACHMBX(td), 
00677                                                   td->clkpos, 
00678                                                   td->trpos, 
00679                                                   td->internal_loopback,
00680                                                   0);
00681                         }
00682                         rc  = 0;
00683                         break;
00684                 case M_SCM:
00685                         FOREACHCARD{
00686                                 enterLLCSoftClock(EACHMBX(td), 
00687                                                   td->clkpos, td->trpos, 
00688                                                   td->internal_loopback,
00689                                                   commandModifiers(td));
00690                         }
00691                         if (isAcq216()){
00692                                 rc = runSCM216(td);
00693                         }else{
00694                                 rc = runSCM( td );
00695                         }
00696                         break;
00697                 case M_ECS:
00698                 case M_ECM:
00699                         FOREACHCARD{
00700                                 enterLLCExtClock(
00701                                         EACHMBX(td),
00702                                         td->clkpos, td->trpos, 
00703                                         td->arg.divisor,td->internal_loopback,
00704                                         commandModifiers(td));
00705                         }
00706                         rc = runECM( td );
00707                         break;
00708                 case M_SYNC_ECM:
00709                         FOREACHCARD{
00710                                 appEnterLLC_SYNC_ECM(
00711                                         THIS_CARD, EACHMBX(td), td);
00712                         }
00713                         rc = runSYNC_ECM(td, 0);
00714                         break;
00715                 case M_SYNC_2V:
00716                         FOREACHCARD{
00717                                 appEnterLLC_SYNC_2V(
00718                                         THIS_CARD, EACHMBX(td), td);
00719                         }
00720                         rc = runSYNC_2V(td, 0);
00721                         break;  
00722                 case M_SYNC_2VAO32:
00723                         FOREACHCARD{
00724                                 appEnterLLC_SYNC_2VAO32(
00725                                         THIS_CARD, EACHMBX(td), td);
00726                         }
00727                         rc = runSYNC_2VAO32(td, 0);
00728                         break;          
00729                 case M_SYNC_2VRFM:
00730                         appEnterLLC_SYNC_2VRFM();
00731                         rc = runSYNC_2VRFM(td, 0);
00732                         break;
00733                 case M_MEASURE_BRIDGE:
00734                         if (td->iterations > 20){
00735                                 FOREACHCARD(measureBridgeStats(
00736                                                     td, EACHMBX(td)));
00737                         }else{
00738                                 FOREACHCARD(measureBridge(EACHMBX(td)));
00739                         }
00740                         return 0;
00741                 default:
00742                         assert( 0 );
00743                 }
00744 
00745         }else{
00746                 fprintf( stderr, "longjmp!\n");
00747                 fprintf( stderr, "ERROR:runTest got a SNACK, 0x%08x\n", 
00748                          status );
00749                 rc = -1;
00750         }
00751 
00752                 
00753         FOREACHCARD{
00754                 leaveLLC(EACHMBX(td));
00755         }
00756 
00757         if ( td->mask_ints ){
00758                 FOREACHCARD{
00759                         acq32_enableInts(EACHMBX(td), td->mask_ints_mask);
00760                 }
00761                 PRINTF(1)( "mask ints 0x%04x clear\n", td->mask_ints_mask );
00762         }
00763 
00764         return rc;
00765 }
00766 
00767 #include <signal.h>
00768 
00769 static struct TestDescription* S_td;
00770 
00771 static void quit_handler( int signum )
00772 {
00773         EACHCARD_INIT;
00774         struct TestDescription* td = S_td;
00775 
00776         fprintf( stderr, "Quitting Time - mailboxes were\n" );
00777 
00778         FOREACHCARD{
00779                 fprintf(stderr, "0x%08x  0x%08x  0x%08x  0x%08x\n",
00780                         getMbox(EACHMBX(td), 0), 
00781                         getMbox(EACHMBX(td), 1),    
00782                         getMbox(EACHMBX(td), 2),
00783                         getMbox(EACHMBX(td), 3) );
00784         }
00785 
00786         FOREACHCARD{
00787                 showLastWrites(EACHMBX(S_td));
00788         }
00789 
00790         FOREACHCARD{
00791                 leaveLLC(EACHMBX(S_td));
00792         }
00793         exit( signum );
00794 }
00795 
00796 void setupAbortHandler( struct TestDescription* td )
00797 {
00798         static struct sigaction  def_action = { { quit_handler } };
00799 
00800         S_td = td;    // ugly global. use class var in C++
00801     
00802         sigaction( SIGINT, &def_action, 0 );
00803 }
00804 
00805 
00806 
00807 
00808 static void monitor_handler( int signum )
00809 {
00810         static u32 old_mboxes[4];
00811         u32 new_mboxes[4];
00812         int ibox;
00813         int changed = 0;
00814 
00815         for ( ibox = 0; ibox != 4; ++ibox ){
00816                 new_mboxes[ibox] = getMbox( S_td->cards[0].mbx, ibox );
00817                 if ( new_mboxes[ibox] != old_mboxes[ibox] ){
00818                         changed = 1;
00819                 }
00820         }
00821         
00822         if ( changed || verbose > 2 ){
00823                 fprintf( stderr, "%8d ", S_td->iter );
00824                 for ( ibox = 0; ibox != 4; ++ibox ){
00825                         fprintf( stderr, "0x%08x%c ", 
00826                                  new_mboxes[ibox], 
00827                                  new_mboxes[ibox]!=old_mboxes[ibox]? '*': ' ' );
00828                             
00829                         old_mboxes[ibox] = new_mboxes[ibox];
00830                 }
00831                 fprintf( stderr, "\n" );
00832         }
00833         if ( G_quit ){
00834                 setupMonitor( 0 );
00835                 fprintf( stderr, "monitor quitting\n" );
00836         }           
00837 }
00838 
00839 void setupMonitor( int millisec )
00840 {
00841         static struct sigaction monitor_action = { { monitor_handler } };
00842         static struct itimerval new_timer = {};
00843 
00844         new_timer.it_value.tv_usec    =
00845                 new_timer.it_interval.tv_usec = millisec*1000;
00846     
00847         sigaction( SIGALRM, &monitor_action, 0 );
00848         setitimer( ITIMER_REAL, &new_timer, 0 );
00849 }
00850 
00851 void initCardResource(struct Card* card)
00852 {
00853         card->mbx = mmapMbox(card->slot);
00854         card->buf = mmapBigBuffer(card->slot, ACQ196_BIGBUF_AREA);
00855         hbPrimeBuffer(card->buf);
00856 
00857         get_cpu_clock_speed();
00858 }
00859 
00860 
00861 
00862 static void debug_prompt(int icard, int ibuf, u32 addr)
00863 /** promnpt user to ensure pram set (temporary pre-update measure). */
00864 {
00865         static const char * LLCV2_LOOKUP[] = {
00866                 [LLCV2_INIT_AI_HSBT] = "AI_target",
00867                 [LLCV2_INIT_AO_HSBS] = "AO_src",
00868                 [LLCV2_INIT_DO_HSBS] = "DO src",
00869                 [LLCV2_INIT_STATUS_HSBT] = "STATUS_target"
00870         };
00871         fprintf(stderr, "V2: please ensure card %d has pram %s set 0x%08x\n",
00872                 icard, LLCV2_LOOKUP[ibuf], addr);
00873 }
00874 void initV2Stats(struct TestDescription *td)
00875 {
00876         updateTstats = v2_updateTstats;
00877         waitDmaDone  = card_v2_WaitDmaDone;
00878 
00879         EACHCARD_INIT;
00880 
00881         FOREACHCARD{
00882                 u32* init = getVaddr(EACHBUF(td), 0);
00883                 int ibuf;
00884                 
00885                 for (ibuf = 0; ibuf != LLCV2_INIT_LAST; ++ibuf){
00886                         switch(ibuf){
00887                         case LLCV2_INIT_MARKER:
00888                                 init[ibuf] = td->V2_BUFS[ibuf];
00889                                 break;
00890                         case LLCV2_INIT_AI_HSBT:
00891                         case LLCV2_INIT_AO_HSBS:
00892                         case LLCV2_INIT_DO_HSBS:
00893                         case LLCV2_INIT_STATUS_HSBT:
00894                                 if (td->V2_BUFS[ibuf] != V2_NOBUF){
00895                                         init[ibuf] = 
00896                                                 td->V2_BUFS[ibuf] |
00897                                                 getBusAddr(EACHBUF(td),0);
00898                                         debug_prompt(icard, ibuf, init[ibuf]);
00899                                 }else{
00900                                         init[ibuf] = 0;
00901                                 }
00902                                 break;
00903                         default:
00904                                 init[ibuf] = td->V2_BUFS[ibuf];
00905                                 break;
00906                         }
00907                 }
00908         }
00909 }
00910 
00911 
00912 
00913 
00914 
00915 
00916 

Generated on Wed Jan 5 2011 for llcontrol by  doxygen 1.7.1