00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
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
00241 {
00242 llSetCmd(card->mbx, cmd+LLC_CSR_M_READCTR);
00243 tstats->tinst = llGetTinst(card->mbx);
00244 tstats->tprocess = llGetTprocess(card->mbx);
00245
00246
00247
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
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
00271
00272
00273
00274
00275
00276 void doApplicationWork(struct TestDescription* td, u32 offset)
00277
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
00307
00308
00309
00310
00311 int user_abort = 0;
00312
00313 static int do_run( struct TestDescription* td, int soft_clock )
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
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 {
00368 EACHBBB = getVaddr(EACHBUF(td), 0);
00369 EACHMFA = mu_reserveOutbound(EACHMBX(td));
00370 }
00371 FOREACHCARD{
00372 llSetTlatch(EACHMBX(td), tstats[icard].tlatch = 0xffffffff);
00373 }
00374
00375 FOREACHCARD{
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
00388
00389 while( !llCounterRunning(FIRSTMBX(td), cmd) ){
00390 POLLALERT(ipoll, "Polling for Counter Running\n");
00391 }
00392
00393 INIT_TIMER;
00394
00395
00396
00397 for ( td->iter = 0; td->iter != td->iterations; ++td->iter ){
00398 if (soft_clock) FOREACHCARD{
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{
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{
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) {
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){
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){
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
00459
00460
00461
00462 if (!td->hardware_gate_off &&
00463 !llCounterRunning(FIRSTMBX(td), cmd )){
00464 fprintf( stderr, "Trigger is off - stop\n" );
00465 break;
00466 }
00467
00468 FOREACHCARD_MARK_TIME(6, "after llCounterRunning check");
00469
00470
00471
00472 if ( !td->overwrite ){
00473 offset += td->sample_offset;
00474
00475 FOREACHCARD{
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
00488
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{
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{
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
00539 {
00540 return do_run( td, 1 );
00541 }
00542
00543
00544
00545
00546
00547 static int runECM( struct TestDescription* td )
00548
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
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
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;
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
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