home *** CD-ROM | disk | FTP | other *** search
- /*
- * ATPERF -- PC Tech Journal AT Hardware Performance Test
- *
- * Version 1.00
- * Last modified 05/17/86
- * Copyright (c) 1986, PC Tech Journal
- * Program by: Paul Pierce, Ted Forgeron, Steven Armbrust
- *
- * Measures clock rates and memory speeds
- * of AT compatible computers.
- */
-
- #define vars 14
-
- /* Timer rate in MHz */
- #define TIMER2_RATE 1.193180
-
- /* Number of processor clocks in a multiply instruction */
- #define MULCLKS 21
-
- /* Overhead in the multiply test */
- #define MULOVH ( 15 + 14*count/100 )
-
- /* Overhead in the mov instruction test */
- #define MOVOVH ( clktime * (15 + 14*count/100) )
-
- /* Overhead in the stringop tests */
- #define STROVH ( clktime * 8 )
-
- /* Number of numeric processor clocks in a FP divide */
- #define FPCLKS 203
-
- /* Processor overhead in the FP divide test */
- #define FPOVH ( clktime * 9 * FPCOUNT )
-
- /* Count for most tests */
- #define COUNT 1000
-
- /* Count for the f. p. divide test */
- #define FPCOUNT 100
-
- /* Number of trials for each test */
- #define TRIALS 100
-
-
- double clkrate; /* Processor clock rate, MHz */
- double clktime; /* Processor clock period, usec */
- double fprate; /* FP processor clock rate, MHz */
- double fpacc; /* FP processor clock period accumulator */
- int emmok; /* Set if extended memory is present */
- int ndpok; /* Set if math coprocessor is present */
-
-
-
- /*
- * Main program.
- */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- double raw, brw, wrw; /* Variables for raw data */
- double acctime[vars]; /* Accumulators for speeds */
- int count; /* Number of ops per trial */
- int trials; /* Number of repetitions */
- register int i;
-
- count = COUNT;
- trials = TRIALS;
-
- /*
- * Measure the clock rate by executing
- * multiply instructions. Each multiply
- * takes a fixed number of clock cycles.
- */
-
- clktime = 0;
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of clock ticks for
- * "count" multiplies.
- */
-
- raw = multime(count);
-
- /*
- * Accumulate the clock time in microseconds
- * by adjusting for the timer rate,
- * number of clocks per multiply,
- * instruction count, and test overhead.
- */
-
- clktime += raw /
- (TIMER2_RATE * (MULCLKS*count + MULOVH));
- }
-
- /*
- * Calculate the average clock period by dividing by
- * the number of trials. The clock rate is the
- * inverse of the clock period.
- */
-
- clktime /= trials;
- clkrate = 1.0/clktime;
-
- /*
- * Determine whether there a math coprocessor
- * in the system.
- */
-
- ndpok = ndp_present();
-
- /*
- * Determine whether there is extended memory in the
- * system and allocate a piece of it for testing.
- */
-
- emmok = (setup_emm() == 0);
-
- /*
- * Clear all of the memory speed accumulators.
- */
-
- for (i = 0; i < vars; i++)
- acctime[i] = 0;
-
- /*
- * Do the memory speed tests.
- */
-
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of timer ticks for
- * "count" mov instructions, which are
- * limited by memory fetch time.
- */
-
- raw = wmovtime(count);
-
- /*
- * Accumulate the number of microseconds
- * per instruction fetch by adjusting for
- * the timer rate, test overhead, and
- * instruction count.
- */
-
- acctime[8] +=
- (raw / TIMER2_RATE - MOVOVH) / count;
-
- /*
- * In a similar manner, measure the
- * RAM byte write time using the stos
- * instruction.
- */
-
- brw = bstotime(count);
- acctime[2] += brw/(TIMER2_RATE*count);
-
- /*
- * Calculate memory read time by
- * measuring movs instructions
- * (read followed by write) and
- * subtracting the write time
- * measured above.
- */
-
- raw = bmvstime(count) - brw;
- acctime[0] += raw/(TIMER2_RATE*count);
-
- /*
- * Calculate ROM read time by
- * measuring movs from ROM to RAM
- * and subtracting RAM write time
- * as above.
- */
-
- raw = bromtime(count) - brw;
- acctime[4] += raw/(TIMER2_RATE*count);
-
- /*
- * Make similar measurements for
- * word operations.
- */
-
- wrw = wstotime(count);
- acctime[3] += raw/(TIMER2_RATE*count);
- raw = wmvstime(count) - wrw;
- acctime[1] += raw/(TIMER2_RATE*count);
- raw = wromtime(count) - wrw;
- acctime[5] += raw/(TIMER2_RATE*count);
-
- /*
- * If EMM is present, do measurements
- * on it using the same techniques.
- */
-
- if (emmok) {
-
- /*
- * Measure byte write,
- * calculate byte read.
- */
-
- brw = bemstime(count);
- acctime[12] += brw/(TIMER2_RATE*count);
- raw = bemmtime(count) - brw;
- acctime[10] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure word write,
- * calculate word read.
- */
-
-
- wrw = wemstime(count);
- acctime[13] += raw/(TIMER2_RATE*count);
- raw = wemmtime(count) - wrw;
- acctime[11] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Measure byte and word writes
- * into video RAM (assuming CGA adapter.)
- */
-
- raw = bvidtime(count);
- acctime[6] += raw/(TIMER2_RATE*count);
- raw = wvidtime(count);
- acctime[7] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Calculate averages for all measurements.
- */
-
- for (i = 0; i < vars; i++)
- acctime[i] /= trials;
-
- /*
- * Release EMM memory page.
- */
-
- if (emmok)
- finish_emm();
-
- /*
- * Calculate numeric processor clock
- * rate using floating point divide
- * instructions, using the same
- * technique as was used to measure
- * the processor clock rate.
- */
- if (ndpok) {
-
- fprate = 0;
- for (i = 0; i < trials; i++) {
- raw = fptime(FPCOUNT);
- fpacc += (raw / TIMER2_RATE - FPOVH) /
- FPCLKS / FPCOUNT;
- }
- fpacc /= trials;
- fprate = 1.0/fpacc;
- }
-
- /*
- * Display the basic measurement results and
- * performance index relative to a 6 MHz AT.
- */
-
- printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
- printf("ATPERF -- PC Tech Journal AT Hardware ");
- printf("Performance Test\n");
- printf("Version 1.00, Copyright (c) 1986 PC Tech ");
- printf("Journal\n");
- printf("IBM PC/AT model 339 (8 MHz) = 1.00 for relative ");
- printf("measurements.\n ");
- printf(" Byte Word Relative\n");
-
- printf("Average RAM instr. fetch: ");
- printf(" ");
- printf("%10.3g uS", acctime[8]);
- printf("%10.2g\n", 0.403/acctime[8]);
-
- printf("Average RAM read time: ");
- printf("%10.3g uS ", acctime[0]);
- printf("%10.3g uS", acctime[1]);
- printf("%10.2g\n", 0.401/acctime[1]);
-
- printf("Average RAM write time: ");
- printf("%10.3g uS ", acctime[2]);
- printf("%10.3g uS", acctime[3]);
- printf("%10.2g\n", 0.401/acctime[3]);
-
- if (emmok) {
- printf("Average EMM read time: ");
- printf("%10.3g uS ", acctime[10]);
- printf("%10.3g uS", acctime[11]);
- printf("%10.2g\n", 0.402/acctime[11]);
-
- printf("Average EMM write time: ");
- printf("%10.3g uS ", acctime[12]);
- printf("%10.3g uS", acctime[13]);
- printf("%10.2g\n", 0.402/acctime[13]);
- }
- printf("Average ROM read time: ");
- printf("%10.3g uS ", acctime[4]);
- printf("%10.3g uS", acctime[5]);
- printf("%10.2g\n", 0.401/acctime[5]);
-
- printf("Average Video write time: ");
- printf("%10.3g uS ", acctime[6]);
- printf("%10.3g uS", acctime[7]);
- printf("%10.2g\n", 2.415/acctime[7]);
-
- printf("\nClock rate: ");
- printf("%4.1g MHz", clkrate);
- printf(" Relative: %4.2g\n", clkrate/8.0);
-
- if (ndpok) {
- printf("Numeric processor clock rate: ");
- printf("%4.1g MHz", fprate);
- printf(" Relative: %4.2g\n", fprate/5.33);
- }
-
- /*
- * Calculate refresh overhead from instruction
- * fetch time by assuming that each fetch takes
- * an exact multiple of the clock period. The
- * difference between average time and the time
- * for an individual fetch is due to memory
- * refresh cycles.
- */
-
- raw = acctime[0] / clktime;
- printf("Refresh overhead: %2.1g%%\n",
- ( (raw - (int)raw) / (int)raw ) * 100);
-
- /*
- * Print information about the memory based
- * on the speed measurements.
- */
-
- printf("\nMemory ");
- printf(" Access width Wait states\n");
- analyze("RAM read", acctime[0], acctime[1]);
- analyze("RAM write", acctime[2], acctime[3]);
- if (emmok) {
- analyze("EMM read", acctime[10], acctime[11]);
- analyze("EMM write", acctime[12], acctime[13]);
- }
- analyze("ROM read", acctime[4], acctime[5]);
- analyze("Video write", acctime[6], acctime[7]);
- }
-
- /*
- * analyze
- *
- * This procedure deduces information about the memory based on
- * the measured times.
- * If byte (8 bits) and word (16 bits) times are different then
- * the memory is byte oriented since each word operation takes
- * two byte operations. Otherwise, if the byte and word
- * times are about the same, the memory is word oriented and can
- * access either a word or a byte in a single memory cycle.
- *
- * Each memory access takes an exact number of processor clock
- * cycles. The first two are required by the processor, but
- * any additional cycles are determined by the memory and are
- * called wait states (because the processor is waiting for
- * the memory.)
- */
-
- analyze(name, btime, wtime)
- char *name;
- double btime;
- double wtime;
- {
-
- /*
- * Print the heading
- */
-
- printf("%-12s", name);
-
- /*
- * Determine whether the memory is byte
- * oriented, word oriented, or neither.
- * (If neither, the data are suspect.)
- */
-
- if (btime > wtime*0.75 &&
- btime < wtime*1.25)
- printf(" Word ");
- else if (btime*2 > wtime*0.75 &&
- btime*2 < wtime*1.25)
- printf(" Byte ");
- else
- printf(" Strange");
-
- /*
- * Determine the number of wait states
- * by subtracting two processor clock times,
- * dividing by the clock period,
- * and rounding down to an integer.
- */
-
- printf(" %6.0f\n",
- (btime - 2*clktime) / clktime);
- }