/* mipstest.c 02/10/01 nm cap=pm info "-Ae -g -w3 -DMPE=1" echo this needs gcc or MPE/iX 6.5 or later HP C -o mipstest.otemp auxobj libcansi.lib.sys auxobj getcr.o auxobj asmloops.o auxobj libcinit.lib.sys -e mipstest.pub */ /*-------------------------------------------------------------------- Time it takes for the 4 asmloop routines on various CPUs: # ticks #instr 9x8 440mhz 650mhz ----- ----- ------ ------ asmloops 10000 10070 5099 5064 asmloops_nopar 10004 10077 9467 9451 asmloops_nopar2 10004 14520 36195 36191 asmloops_par 10004 6074 5076 5064 9x8 is 968 and 918 (both took same # of ticks) 440mhz is a 9000 A-Class and "110 MHz" 3000 A-Class (same # of ticks) 650mhz is a 9000 rp2430 We chose asmloops_nopar to be the default loop used herein, because it's the closest to a 1:1 ratio on across all tested CPUs. --------------------------------------------------------------------*/ #pragma optimize on #ifndef HPUX #define HPUX 0 #endif #ifndef MPE #define MPE 0 #endif #if HPUX & MPE error; +*/0 error; #endif #include /* isalpha() */ #include #include #include #include #include #if HPUX #include #include #endif typedef short int int16; typedef int int32; typedef long long int int64; typedef unsigned int uint32; #define num_mtypes 4 /* 4 different kinds of asmloops */ #define best_mtype 1 extern int32 asmloops (int32 numloops); /* mtype 0 */ extern int32 asmloops_nopar (int32 numloops); /* mtype 1 */ extern int32 asmloops_nopar2 (int32 numloops); /* mtype 2 */ extern int32 asmloops_par (int32 numloops); /* mtype 3 */ static char version[] = "@(#) MIPSTEST 2002-10-01"; static char copyright [] = "Copyright (c) 2002 Allegro Consultants, Inc. www.allegro.com"; int32 base_mips = 0, best_mips = 0, burp_size = 0, /* # of microseconds */ debug1 = 0, dummy, explained_faster = 0, first_time = 1, global_mtype = best_mtype, /* best = nearly 1:1 on A-Class */ interesting_mips = 0, itmr_ticks_per_sec = 0, itmr_ticks_per_micro = 0, /* # ticks per microsecond */ num_interesting= 0, saw_deduce = 0, saw_mtype = 0, scaled_mips = 0, show_best_only = 0, use_itmr = 0, verbose = 0, want_all = 0, want_deduce = 0, want_memtouch = 0, want_multisizes= 0; int16 err1, err2; struct asmloop_ent { int32 (*sy_call) (int32); const char *sy_name; }; struct asmloop_ent pasmloops [num_mtypes]; #if HPUX extern int64 gethrtime (void); #endif #if MPE extern int64 get_time (void); extern int64 micro_to_ticks (int64 ticks); extern int64 ticks_to_micro (int64 ticks); int64 gethrtime (void); #pragma intrinsic COMMAND #pragma intrinsic GETPRIVMODE #pragma intrinsic TERMINATE #pragma intrinsic XCONTRAP #endif /* more externals for assembler routines...*/ extern void get_many_itmrs (int32 *p); extern uint32 getcr16 (void); /* returns ITMR register */ extern int32 asmloops_measure_blink (void); /* returns # of ticks */ extern int32 asmloops_measure_burp (void); /* returns # of ticks */ /* shorten "printf"s a bit... */ #define MSG0(xxx) (void) printf (xxx) #define MSG1(xxx,x1) (void) printf (xxx, x1) #define MSG2(xxx,x1,x2) (void) printf (xxx, x1,x2) #define MSG3(xxx,x1,x2,x3) (void) printf (xxx, x1,x2,x3) #define MSG4(xxx,x1,x2,x3,x4) (void) printf (xxx, x1,x2,x3,x4) #define MSG5(xxx,x1,x2,x3,x4,x5) (void) printf (xxx, x1,x2,x3,x4,x5) /*---------------------forwards ----------------------*/ void chk_sizeof_die (const char *msg, int32 exp_n, int32 act_n); void die (const char *msg); void disclaimer (void); const char *fmt_mtype (int32 mtype); int64 my_ticks_to_micro (int64 ticks); int64 my_micro_to_ticks (int64 micros); void show_help (void); void usage (void); /**************************************************************/ void chk_sizeof_die (const char *msg, int32 act_n, int32 exp_n) { if (debug1) (void) printf ("sizeof %s = %d\n", msg, act_n); if (exp_n != act_n) { MSG2 ("oops: sizeof %s = %d, should be %d\n", act_n, exp_n); die ("internal coding error"); } } /* end chk_sizeof_die proc */ /**************************************************************/ int compar (const void *arg1, const void *arg2) { /* for qsort */ return *(int32 *) arg1 - *(int32 *) arg2; } /* end compar proc */ /**************************************************************/ #if MPE void cy_handler (void) { TERMINATE (); } /* end cy_handler proc */ #endif /**************************************************************/ int32 determine_real_mips (int32 mtype, int32 loops) { int64 best_nanos = 0, micros64, nano1, nano2, nanos; int32 best_ticks = 0, instr, itmr_1, itmr_2, ktr, mips, ticks; float scaled_mips_f, scale_f; char msgbuf [80], msgbuf2 [80]; if (verbose || saw_mtype) MSG1 ("\nDetermining hardware clock speed using %s ...\n", fmt_mtype (mtype)); best_ticks = 0x7fffffff; for (ktr = 1; ktr <= 10; ktr++) { asmloops_nopar2 (1); /* get into cache */ asmloops (1); /* get into cache */ dummy = getcr16 (); /* get into cache */ dummy++; /* make lint happy */ nano1 = gethrtime (); itmr_1 = getcr16 (); switch (mtype) { case 0: instr = asmloops (loops); break; case 1: instr = asmloops_nopar (loops); break; case 2: instr = asmloops_nopar2 (loops); break; case 3: instr = asmloops_par (loops); break; } itmr_2 = getcr16 (); nano2 = gethrtime (); ticks = itmr_2 - itmr_1; if ((best_ticks == 0) || ((ticks > 0) && (ticks < best_ticks)) ) best_ticks = ticks; nanos = nano2 - nano1; if ((best_nanos == 0) || ((nanos > 0) && (nanos < best_nanos)) ) best_nanos = nanos; if (debug1) MSG3 (" instr = %d, ticks = %8d, micros = %6d\n", instr, (int32) ticks, (int32) (nanos / 1000)); } if (use_itmr) micros64 = my_ticks_to_micro ((int64) best_ticks); else micros64 = best_nanos / 1000; if (verbose) MSG3 (" instr = %d, best micros = %d, best ticks = %d\n", instr, (int32) micros64, (int32) best_ticks); if (micros64 <= 1) return 0; /* too small to use */ mips = (int32) (instr / micros64); scale_f = (float) best_ticks / instr; scaled_mips_f = mips * scale_f; scaled_mips = scaled_mips_f; if ((interesting_mips > 0) && (mips > interesting_mips)) { if (num_interesting++ == 0) { burp_size = (int32) micros64; MSG2 ("\nMax burp size about = %d microsecs (%d ticks)\n", burp_size, best_ticks); } } if ((mips > best_mips) || (!show_best_only) || debug1) { (void) sprintf (msgbuf, "user MHz = %4d; hardware MHz = %5.1f", mips, scaled_mips_f); if ((loops == 10000000) && (!verbose)) if (want_all || saw_mtype) (void) sprintf (msgbuf2, " (%s)", fmt_mtype (mtype)); else msgbuf2 [0] = (char) 0; else if (want_all || saw_mtype) (void) sprintf (msgbuf2, " (#i = %8d; %s)", loops, fmt_mtype (mtype)); else (void) sprintf (msgbuf2, " (#i = %8d)", loops); MSG2 ("%s%s\n", msgbuf, msgbuf2); if (first_time) { first_time = 0; if (mips <= (scaled_mips_f * 0.8)) { MSG0 ("\nNote: appears to be a reduced clock-rate CPU\n"); if (!saw_deduce) want_deduce = 1; } } if ((mips > (scaled_mips_f + 1.0)) && (! explained_faster) ) { explained_faster = 1; MSG0 ("\n"); MSG0 ("Note: some CPUs are very good at executing more than one " "instruction\n"); MSG0 (" per clock cycle ... on such systems, the 'user' " "MHz may\n"); MSG0 (" sometimes be more than the actual hardware MHz.\n"); } } return mips; } /* end determine_real_mips proc */ /**************************************************************/ void die (const char *msg) { MSG1 ("\n%s\n", msg); MSG0 ("\n"); exit (1); } /**************************************************************/ void disclaimer (void) { MSG0 ("\n"); MSG0 ("We have tried to make this program accurately measure CPU\n"); MSG0 ("performance. However, between us being merely human\n"); MSG0 ("(i.e., we can make mistakes), and the CPUs being PA-RISC\n"); MSG0 ("(which can be tricky to measure from model to model), we\n"); MSG0 ("have to state that we make no claims of accuracy for the\n"); MSG0 ("measurements shown.\n"); MSG0 ("\n"); MSG0 ("The source code for this program is available, free,\n"); MSG0 ("upon request: info@allegro.com\n"); MSG0 ("\n"); (void) fflush (stdout); } /* end disclaimer proc */ /**************************************************************/ const char * fmt_mtype (int32 mtype) { switch (mtype) { case 0: return "asmloops"; case 1: return "asmloops_nopar"; case 2: return "asmloops_nopar2"; case 3: return "asmloops_par"; } return "unknown mtype"; } /* end fmt_mtype proc */ /**************************************************************/ void get_cpu_rating (void) { int32 my_mips; #if MPE itmr_ticks_per_sec = (int32) my_micro_to_ticks (1000000); itmr_ticks_per_micro = (int32) my_micro_to_ticks (1); if (debug1) (void) printf ("ticks/sec = %d, ticks/micro = %d\n", itmr_ticks_per_sec, itmr_ticks_per_micro); #endif #if HPUX struct pst_dynamic psd; struct pst_processor psp; long sc_ticks; /* size_t nspu = 0; */ /* get information about all processors, first obtaining * number of processor context instances */ if (debug1) MSG1 ("sizeof (pst_dynamic) = %d\n", sizeof (struct pst_dynamic)); sc_ticks = sysconf(_SC_CLK_TCK); if (verbose) MSG1 ("_SC_CLK_TCK = %d\n", sc_ticks); if (pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) == -1) { perror ("pstat_getdynamic failed"); return; } /* nspu = psd.psd_proc_cnt; */ if (pstat_getprocessor (&psp, sizeof (psp), 1 /*get 1 cpu's worth */, 0) == -1) { perror ("pstat_getprocessor failed"); return; } /* psp.psp_iticksperclktick is interval timer counts (CR16) */ if (verbose) MSG1 ("psp_iticksperclktick = %d\n", psp.psp_iticksperclktick); itmr_ticks_per_sec = psp.psp_iticksperclktick * sc_ticks; itmr_ticks_per_micro = itmr_ticks_per_sec * 1000000; #endif if (use_itmr && (itmr_ticks_per_sec == 0)) { MSG0 ("Oops: we could not determine ITMR ticks per second," "-i cancelled\n"); use_itmr = 0; } /* deduce clock rating ... */ my_mips = itmr_ticks_per_sec / 1000000; /* in millions */ MSG1 ("Rated CPU speed: %d MHz\n", my_mips); MSG0 ("\n"); /* blank line */ if (use_itmr) if (want_all) MSG0 ("Will use ITMR to determine speed\n\n"); else MSG1 ("Will use ITMR to determine speed, and %s\n\n", fmt_mtype (global_mtype)); else if (want_all) MSG0 ("Will use gethrtime to measure time\n\n"); else if (verbose) MSG1 ("Will use gethrtime to measure time, and %s\n\n", fmt_mtype (global_mtype)); } /* end get_cpu_rating proc */ /**************************************************************/ #if HPUX1020 int64 gethrtime (void) { struct timespec cur_time; int64 micros64; if (clock_gettime (CLOCK_REALTIME, &cur_time) == -1) { perror ("clock_gettime(CLOCK_REALTIME) failed"); die ("Unable to determine time"); } micros64 = (1000000000 * (int64) cur_time.tv_sec) + (int64) cur_time.tv_nsec; return micros64; } /* end gethrtime proc */ #endif /**************************************************************/ #if MPE int64 gethrtime (void) { GETPRIVMODE (); return (get_time () * (int64) 1000); } /* end gethrtime proc */ #endif /* MPE */ /**************************************************************/ void initialize (void) { int32 inx; MSG1 ("\n%s\n", version); MSG1 ("%s\n", copyright); chk_sizeof_die ("int16", sizeof (int16), 2); chk_sizeof_die ("int32", sizeof (int32), 4); chk_sizeof_die ("uint32", sizeof (uint32), 4); chk_sizeof_die ("int64", sizeof (int64), 8); pasmloops [0].sy_call = &asmloops; pasmloops [1].sy_call = &asmloops_nopar; pasmloops [2].sy_call = &asmloops_nopar2; pasmloops [3].sy_call = &asmloops_par; for (inx = 0; inx < num_mtypes; inx++) pasmloops [inx].sy_name = fmt_mtype (inx); #if MPE XCONTRAP (&cy_handler, &dummy); /* control-Y will terminate */ #endif } /* end initialize proc */ /**************************************************************/ int64 my_micro_to_ticks (int64 micros) { #if MPE GETPRIVMODE (); return micro_to_ticks (micros); #endif #if HPUX return (itmr_ticks_per_sec / 1000000.0) / micros; #endif } /* end my_micro_to_ticks proc */ /**************************************************************/ int64 my_ticks_to_micro (int64 ticks) { #if MPE GETPRIVMODE (); return ticks_to_micro (ticks); #endif #if HPUX return (int64) (ticks / (itmr_ticks_per_sec / 1000000.0)); #endif } /* end my_ticks_to_micro proc */ /**************************************************************/ void parse_options (int32 argc, char *argv []) { int inx; char *itemp; for (inx = 1; inx < argc; inx++) { itemp = argv [inx]; if (strcmp (itemp, "-?") == 0) { usage (); MSG0 ("\n"); MSG0 ("For more information, run with -help\n"); exit (0); } if (strcmp (itemp, "-all") == 0) want_all = 1; else if (strcmp (itemp, "-d") == 0) debug1 = 1; else if (strcmp (itemp, "-deduce") == 0) { saw_deduce = 1; want_deduce = 1; } else if (strcmp (itemp, "-help") == 0) { show_help (); usage (); exit (0); } else if (strcmp (itemp, "-i") == 0) use_itmr = 1; else if (strcmp (itemp, "-memtouch") == 0) want_memtouch = 1; else if (strcmp (itemp, "-multi") == 0) want_multisizes = 1; else if (strcmp (itemp, "-nodeduce") == 0) { saw_deduce = 1; want_deduce = 0; } else if (strcmp (itemp, "-v") == 0) { MSG1 ("%s\n", version); exit (0); } else if (strcmp (itemp, "-verbose") == 0) verbose = 1; else if (strcmp (itemp, "-0") == 0) { global_mtype = 0; saw_mtype = 1; } else if (strcmp (itemp, "-1") == 0) { global_mtype = 1; saw_mtype = 1; } else if (strcmp (itemp, "-2") == 0) { global_mtype = 2; saw_mtype = 1; } else if (strcmp (itemp, "-3") == 0) { global_mtype = 3; saw_mtype = 1; } else { MSG1 ("Unknown option: %s\n", itemp); die ("...run with -help for information, " "or -? for quick usage"); } }; if (debug1) verbose = 1; if (debug1) { MSG1 ("sizeof (long) = %d\n", sizeof (long)); } } /* end parse_options proc */ /**************************************************************/ void show_consecutive_itmrs (void) { int32 inx, itmrs [16]; MSG0 ("Interval timer, successive calls (&deltas):\n"); get_many_itmrs (itmrs); for (inx = 0; inx < 10; inx ++) if (inx == 0) MSG2 ("%2d : $%8x\n", inx, itmrs [inx]); else MSG3 ("%2d : $%8x (%4d)\n", inx, itmrs [inx], itmrs [inx] - itmrs [inx - 1]); MSG0 ("\n"); } /* end show_consecutive_itmrs proc */ /**************************************************************/ void show_help (void) { MSG0 ("\n"); #define Z(xxx) MSG0 (xxx); /* HELPER text for "-help"... */ /* Start HELPER text */ Z("MIPSTEST is a program to measure the \"MHz\" (clock speed) of\n") Z("PA-RISC computers.\n") Z(" \n") Z("We have tried to make this program accurately measure CPU\n") Z("performance. However, between us being merely human (i.e., we\n") Z("can make mistakes), and the CPUs being PA-RISC (which can be\n") Z("tricky to measure from model to model), we have to state that we\n") Z("make no claims of accuracy for the measurements shown.\n") Z(" \n") Z("The source code for this program is available, free, upon\n") Z("request: info@allegro.com\n") Z(" \n") Z("Sample output:\n") Z(" \n") Z(" :run mipstest.pub.allegro\n") Z(" System being used:\n") Z(" HPCPUNAME = SERIES 968RX\n") Z(" Rated CPU speed: 64 MHz\n") Z(" \n") Z(" Measuring speed...\n") Z(" user MHz = 63; hardware MHz = 63.2\n") Z(" \n") Z("Versions exist for MPE/iX and HP-UX.\n") /* end HELPER text */ #undef Z } /* end show_help proc */ /**************************************************************/ void show_system (void) { char cmd [80]; MSG0 ("System being used:\n"); (void) fflush (stdout); #if MPE (void) strcpy (cmd, "showvar HPCPUNAME\r"); COMMAND (cmd, &err1, &err2); #endif #if HPUX (void) strcpy (cmd, "uname -a"); (void) system (cmd); (void) strcpy (cmd, "model"); (void) system (cmd); #endif /* we ignore any errors from COMMAND or system() */ } /* end show_system proc */ /**************************************************************/ void show_tests_quick (void) { uint32 itmr_1, itmr_2; int32 best_ticks [num_mtypes], instrs [num_mtypes], inx, ktr, loops, ticks [num_mtypes]; /* setup counters ...*/ for (inx = 0; inx < num_mtypes; inx++) { best_ticks [inx] = 0x7fffffff; instrs [inx] = 0; ticks [inx] = 0; } /* try 100 times to time a "short" loop... */ /* (we try many times because there's a chance that */ /* we'll be interrupted (e.g., time slice) during */ /* some of the tests. We'll take the best test. */ loops = 10000; for (ktr = 1; ktr <= 100; ktr++) { /* May as well try all of our known assembly loops */ for (inx = 0; inx < num_mtypes; inx++) { dummy = (pasmloops [inx].sy_call) (1); /* get into cache */ dummy++; /* make lint happy */ dummy = getcr16 (); /* get into cache */ /* do the timing loop (loops is typically 10,000) */ itmr_1 = getcr16 (); instrs [inx] = (pasmloops [inx].sy_call) (loops); itmr_2 = getcr16 (); ticks [inx] = itmr_2 - itmr_1; if ((ticks [inx] > 0) && (ticks [inx] < best_ticks [inx])) best_ticks [inx] = ticks [inx]; } if ((ktr < 9) & debug1) (void) printf ("%d -> %d ticks; %d -> %d; %d -> %d; %d -> %d\n", instrs [0], ticks [0], instrs [1], ticks [1], instrs [2], ticks [2], instrs [3], ticks [3]); } if (verbose) { MSG0 ("\n"); for (inx = 0; inx < num_mtypes; inx++) MSG3 ("Best time (ticks) for %6d instructions: %8d (%s)\n", instrs [inx], best_ticks [inx], fmt_mtype (inx)); } } /* end show_tests_quick proc */ /**************************************************************/ void test_gethrtime (void) { int64 nanos1, nanos2; nanos1 = gethrtime (); nanos2 = gethrtime (); if (debug1) { #if HPUX MSG1 ("gethrtime #1 --> %lld\n", nanos1); MSG1 ("gethrtime #2 --> %lld\n", nanos2); MSG1 (" delta = %lld nanosecs\n", nanos2 - nanos1); #endif #if MPE /* gcc has problems with printing 64-bit integers */ MSG0 ("Testing gethrtime...\n"); MSG1 (" delta of two gethrtimes --> %d nanosecs\n", (int32) (nanos2 - nanos1)); #endif } if (nanos1 == nanos2) { MSG0 ("note: gethrtime resolution doesn't look real fine\n"); return; } if ((nanos1 % 1000) != 0) return; if ((nanos2 % 1000) != 0) return; if (((nanos1 % 5000) == 0) && ((nanos2 % 5000) == 0) ) { MSG0 ("note: gethrtime resolution looks like 5 microsecs or worse\n"); return; } if (((nanos1 % 1000) == 0) && ((nanos2 % 1000) == 0) ) { MSG0 ("note: gethrtime resolution looks like 1 microsec or worse\n"); return; } } /* end test_gethrtime proc */ /**************************************************************/ #if MPE void *valloc (size_t bytes) /* NOT FULLY COMPATIBLE...don't free()! */ { int32 paddr; paddr = (int32) malloc (bytes + 4095); if (paddr == 0) return (void *) NULL; paddr = (paddr + 4095) & 0xfffff000; /* round up to page boundary */ return (void *) paddr; } /* end valloc proc */ #endif /**************************************************************/ void test_memtouch (void) { /*----------------------------------------------- Times seen on 440 MHz A-Class systems: 3000 best micros = 860300, best ticks = 378524636 best micros = 860293, best ticks = 378521673 9000 best micros = 106703, best ticks = 46941060 best micros = 106667, best ticks = 46924652 ------------------------------------------------*/ int32 *buffer; int64 best_nanos = 0, micros64, nano1, nano2, nanos; int32 best_ticks = 0, bytes, inx, itmr_1, itmr_2, ktr, mbs, /* # of megabytes to read */ rslt, ticks, words; /* # of 32-bit words to read */ /* get a page-aligned data area... */ mbs = 10; bytes = mbs * 1024 * 1024; words = bytes / sizeof (int32); buffer = (int32 *) valloc ((size_t) (bytes + 4)); if (buffer == NULL) { perror ("Failed to allocate data"); return; } if (debug1) MSG1 ("valloc returned $%x\n", (int32) buffer); MSG1 ("Timing reading %d MBs of memory...\n", mbs); (void) memset (buffer, 0, (size_t) bytes); best_ticks = 0; best_nanos = 0; for (ktr = 1; ktr <= 10; ktr++) { rslt = 0; nano1 = gethrtime (); itmr_1 = getcr16 (); for (inx = 0; inx < words; inx++) rslt = rslt | buffer [inx]; itmr_2 = getcr16 (); nano2 = gethrtime (); ticks = itmr_2 - itmr_1; if ((best_ticks == 0) || ((ticks > 0) && (ticks < best_ticks)) ) best_ticks = ticks; nanos = nano2 - nano1; if ((best_nanos == 0) || ((nanos > 0) && (nanos < best_nanos)) ) best_nanos = nanos; } if (use_itmr) micros64 = my_ticks_to_micro ((int64) best_ticks); else micros64 = best_nanos / 1000; MSG2 (" best micros = %d, best ticks = %d\n", (int32) micros64, (int32) best_ticks); exit (0); } /* end test_memtouch proc */ /**************************************************************/ void test_sleeps (void) { int64 nanos1, nanos2; int32 ticks1, ticks2; #if HPUX if (verbose) { nanos1 = gethrtime (); ticks1 = getcr16 (); (void) usleep (999999); ticks2 = getcr16 (); nanos2 = gethrtime (); MSG0 ("\n"); MSG0 ("I just did: usleep for 999,999 microseconds\n"); MSG1 (" CR16 delta = %d\n", (ticks2 - ticks1)); MSG1 (" gethrtime delta = %d\n", (int32) (nanos2 - nanos1)); MSG0 ("\n"); } #endif if (verbose) { nanos1 = gethrtime (); ticks1 = getcr16 (); (void) sleep (1); ticks2 = getcr16 (); nanos2 = gethrtime (); MSG0 ("I just slept for 1 second:\n"); MSG1 (" CR16 delta = %d\n", (ticks2 - ticks1)); MSG1 (" gethrtime delta = %d\n", (int32) (nanos2 - nanos1)); MSG0 ("\n"); } } /* end test_sleeps proc */ /**************************************************************/ void usage (void) { #define Z(xxx) MSG0 (xxx); MSG0 ("\n"); /* HELPER text for usage()...*/ /* Start HELPER text */ Z("MIPSTEST usage: mipstest [options]\n") Z(" \n") Z("options:\n") Z(" -all ... test MHz with all 4 methods\n") Z(" -d ... enable debugging output\n") Z(" -deduce ... try to determine blink/burp length\n") Z(" -help ... display *more* help information\n") Z(" -i ... use ITMR instead of gethrtime\n") Z(" -memtouch ... time only reading 10 MB of memory\n") Z(" -multi ... test MHz with varying size loops\n") Z(" -nodeduce...don't do -deduce\n") Z(" -v ... display version and terminate\n") Z(" -verbose... display much more output\n") Z(" -0 ... use asmloops for MHz test\n") Z(" -1 ... use asmloops_nopar for MHz test\n") Z(" -2 ... use asmloops_nopar2 for MHz test\n") Z(" -3 ... use asmloops_par for MHz test\n") /* end HELPER text */ #undef Z } /* end usage proc */ /**************************************************************/ int32 main (int32 argc, char *argv []) { #define max_blinks 100 #define max_burps 100 float speedup_f; int32 blinks [max_blinks], burps [max_burps], decr = 0, inx, loops, mips, new_loops; initialize (); parse_options (argc, argv); disclaimer (); if (want_memtouch) test_memtouch (); show_system (); get_cpu_rating (); /* gets itmr_ticks_per_sec */ if (debug1) { test_gethrtime (); test_sleeps (); show_consecutive_itmrs (); show_tests_quick (); } loops = 10000000; /* 10 million */ MSG0 ("Measuring speed...\n"); if (want_all) { for (inx = 0; inx < num_mtypes; inx++) { mips = determine_real_mips (inx, loops); if (inx == 1) /* type 1 is best for 1:1 */ best_mips = mips; } } else best_mips = determine_real_mips (global_mtype, loops); if (want_deduce || want_multisizes) { if (want_deduce) MSG0 ("\nDetermining max burp size...\n"); want_all = 0; if (want_deduce) show_best_only = 1; loops = 10000000; /* 10 million */ base_mips = determine_real_mips (global_mtype, loops) + 2; best_mips = base_mips; interesting_mips = (scaled_mips * 8) / 10 + 2; if (want_deduce) { if (interesting_mips > best_mips) best_mips = interesting_mips; else if (best_mips > interesting_mips) interesting_mips = best_mips; } if (debug1) MSG2 ("interesting_mips = %d, best_mips = %d\n", interesting_mips, best_mips); decr = 0; while (loops > 10000) { mips = determine_real_mips (global_mtype, loops); if (mips > best_mips) best_mips = mips; /* non-0 affects determine_real_mips */ if (decr == 0) { new_loops = (loops * 3) / 4; if ((loops > 30000) && (new_loops < 30000)) { loops = 30000; if (want_deduce) decr = 100; else decr = 500; } else loops = new_loops; } else loops = loops - decr; } } if (!want_deduce) exit (0); if (burp_size == 0) { MSG0 ("Unable to determine max burp size...\n" "Perhaps this is not a reduced clock-rate CPU?\n"); exit (0); } speedup_f = best_mips / (base_mips + 0.0); if (speedup_f > 1.01) MSG1 ("\nThe full rate CPU appears to be %6.1f times faster.\n", speedup_f); MSG0 ("\n"); MSG0 ("\nAttempting to determine length of CPU sleep (blink)...\n"); MSG0 ("blink ticks:"); for (inx = 0; inx < max_blinks; inx++) blinks [inx] = asmloops_measure_blink (); qsort (blinks, max_blinks, sizeof (blinks [0]), &compar); MSG1 (" mean = %7d ticks\n", blinks [max_burps / 2]); if (verbose) { MSG0 (" all burp lengths seen:\n"); for (inx = 0; inx < max_blinks; inx++) { MSG1 (" %8d", blinks [inx]); if ((inx % 8) == 7) MSG0 ("\n"); } MSG0 ("\n"); } MSG0 ("\n"); MSG0 ("\nAttempting to determine length of CPU use (burp)...\n"); MSG0 ("burp ticks: "); for (inx = 0; inx < max_burps; inx++) burps [inx] = asmloops_measure_burp (); qsort (burps, max_burps, sizeof (burps [0]), &compar); MSG1 (" mean = %7d ticks\n", burps [max_burps / 2]); if (verbose) { MSG0 (" all burp lengths seen:\n"); for (inx = 0; inx < max_burps; inx++) { (void) printf (" %8d", burps [inx]); if ((inx % 8) == 7) MSG0 ("\n"); } MSG0 ("\n"); } return 0; } /* end main proc */