home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pctech
/
1986_08
/
atbench
/
atperf.c
< prev
next >
Wrap
Text File
|
1986-05-29
|
13KB
|
413 lines
/*
* 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);
}