home *** CD-ROM | disk | FTP | other *** search
- /*
- * ATPERF -- PC Tech Journal AT Hardware Performance Test
- *
- * Version 2.03
- * Originally written 05/17/86
- * Last modified 03/24/87
- * Changes:
- * 1. First release (1.00).
- * 2. Correct to work with zero-wait state memory (1.01).
- * 3. Detects an unsupported processor (1.01).
- * 4. Change to support 8088, 8086, and 80386 (2.00).
- * 5. Add support for 80188 and 80186 (2.01)
- * 6. Add support for 80387 (2.01)
- * 7. Added tests to measure low wait state 386 reads (2.02)
- * 8. Added support for pipelined writes (2.02)
- * 9. Added cache detection (2.03)
- *
- * Copyright (c) 1986, 1987, 1988, Ziff Communications Company
- * Program by: Ted Forgeron, Paul Pierce
- *
- * Measures clock rates and memory speeds
- * of PC and AT compatible computers.
- */
-
- /*
- * Measurements are accumulated in the acctime array. Each
- * element is identified by one of these constants.
- * IRB Instruction fetch, byte
- * IRW Instruction fetch, word
- * IRD Instruction fetch, dword
- * IRX Instruction fetch, slow byte
- * MRB RAM read byte
- * MRW RAM read word
- * MRD RAM read dword
- * MWB RAM write byte
- * MWW RAM write word
- * MWD RAM write dword
- * RRB ROM read byte
- * RRW ROM read word
- * RRD ROM read dword
- * ERB EMM read byte
- * ERW EMM read word
- * ERD EMM read dword
- * EWB EMM write byte
- * EWW EMM write word
- * EWD EMM write dword
- * VWB Video write byte
- * VWW Video write word
- * VWD Video write dword
- * CRB Cache read byte
- * CRW Cache read word
- * CRD Cache read dword
- */
-
- #define IRB 0
- #define IRW 1
- #define IRX 2
- #define MRB 3
- #define MWB 4
- #define RRB 5
- #define ERB 6
- #define EWB 7
- #define VWB 8
- #define MRW 9
- #define MWW 10
- #define RRW 11
- #define ERW 12
- #define EWW 13
- #define VWW 14
- #define IRD 15
- #define MRD 16
- #define MWD 17
- #define RRD 18
- #define ERD 19
- #define EWD 20
- #define VWD 21
- #define CRB 22
- #define CRW 23
- #define CRD 24
-
- #define VARS88 3
- #define VARS186 3
- #define VARS286 15
- #define VARS386 25
-
- /* Measurement procedures */
- extern unsigned multime();
- extern unsigned bclctime();
- extern unsigned wmovtime();
- extern unsigned dmovtime();
- extern unsigned dlodtime();
- extern unsigned dramtime();
- extern unsigned dimmtime();
- extern unsigned bdaatime();
- extern unsigned bmvstime();
- extern unsigned wmvstime();
- extern unsigned dmvstime();
- extern unsigned bromtime();
- extern unsigned wromtime();
- extern unsigned dromtime();
- extern unsigned wpshtime();
- extern unsigned dpshtime();
- extern unsigned bemmtime();
- extern unsigned wemptime();
- extern unsigned demptime();
- extern unsigned wemmtime();
- extern unsigned demmtime();
- extern unsigned bvidtime();
- extern unsigned wvidtime();
- extern unsigned dvidtime();
- extern unsigned fptime();
-
- /* Timer rate in MHz */
- #define TIMER2_RATE 1.193180
-
- /* Number of processor clocks in a multiply instruction */
- #define MULCLKS88 118
- /* #define MULCLKS186 36.5 */
- #define MULCLKS186 36
- #define MULCLKS286 21
- #define MULCLKS386 25
-
- /* Overhead in the multiply test */
- #define MULOVH88 (11 + 22*count/100 )
- #define MULOVH186 (8 + 21*count/100 )
- #define MULOVH286 (15 + 14*count/100 )
- #define MULOVH386 (15 + 14*count/100 )
-
- /* Overhead in the mov instruction test */
- #define MOVOVH88 ( clktime * (31 + 22*count/100) )
- #define MOVOVH186 ( clktime * (30 + 20*count/100) )
- #define MOVOVH286 ( clktime * (15 + 14*count/100) )
- #define MOVOVH386 ( clktime * (15 + 14*count/100) )
-
- /* Overhead in pusha instruction test */
- #define WPOVH ( clktime * (15 + 9*count/200) )
- #define DPOVH ( clktime * (15 + 9*count/200) )
-
- /* Number of numeric processor clocks in a FP divide */
- #define FPCLKS88 197
- #define FPCLKS186 197
- #define FPCLKS286 203
- #define FPCLKS386 200
- #define FPCLKS387 98
-
- /* Processor overhead in the FP divide test */
- #define FPOVH88 ( clktime * 2 * FPCOUNT )
- #define FPOVH186 ( clktime * 2 * FPCOUNT )
- #define FPOVH286 ( clktime * 9 * FPCOUNT )
- #define FPOVH386 ( clktime * 7.5 * 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
-
- /* Variables which hold constants selected by cpu type */
- int access_clks;
-
- int cpu; /* CPU type: 0=86/88,1=80186,2=80286,3=80386 */
- 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 fastmath; /* Set for 80387 */
- int emmok; /* Set if extended memory is present */
- int ndpok; /* Set if math coprocessor is present */
- int six; /* Set if cpu is 8086 or 80186 */
- int mw_pipe; /* Set if there is a write pipeline register */
- int ew_pipe; /* Set for EMM pipeline register */
- int cache; /* Set if there is a cache */
-
- double raw; /* Variable for raw data */
- double acctime[VARS386]; /* Accumulators for speeds */
- int count; /* Number of ops per trial */
- int trials; /* Number of repetitions */
-
-
- /*
- * Main program.
- */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
-
- measure();
- display();
- }
-
- measure()
- {
- register int i;
-
- count = COUNT;
- trials = TRIALS;
-
- /*
- * 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);
-
- /*
- * Detect the type of video card and save the
- * information for the video measurements.
- */
-
- setup_video();
-
- /*
- * Find out the CPU type and set
- * parameters accordingly.
- */
-
- cpu = cpu_type();
- six = 0;
- cache = 0;
- mw_pipe = 0;
- ew_pipe = 0;
-
- switch (cpu) {
-
- case 0:
- access_clks = 4;
- measure88();
- break;
-
- case 1:
- access_clks = 4;
- measure186();
- break;
-
- case 2:
- access_clks = 2;
- measure286();
- break;
-
- case 3:
- access_clks = 2;
- measure386();
- adjust386();
- break;
-
- default:
- printf("\nThis version of ATPERF is for ");
- printf("8088/86/188/186/286/386");
- printf("-based machines only.\n");
- exit(1);
- }
-
- /*
- * Release EMM memory page.
- */
-
- if (emmok)
- finish_emm();
- }
-
- display()
- {
- register int i;
-
-
- /*
- * Display the basic measurement results and
- * performance index relative to a 8 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 2.03, Copyright (c) 1986, 1987, 1988, ");
- printf("Ziff Communications Co.\n");
- printf("Written by Ted Forgeron and Paul Pierce\n");
- printf("IBM PC/AT model 339 (8 MHz) = 1.00 for relative ");
- printf("measurements.\n");
- if (cpu < 2)
- printf("\n");
- printf(" ");
- printf(" Byte Word ");
- if (cpu > 2)
- printf("Dword ");
- printf("Relative\n");
-
- printf("Average instruction fetch:");
- printf("%#10.2g uS", acctime[IRB]);
- printf("%#10.2g uS", acctime[IRW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[IRD]);
- printf("%#10.2g\n", 0.403/acctime[IRW]);
-
- if (cpu < 2) {
- printf("\n");
- } else {
- if (cache) {
- printf("Average Cache hit time: ");
- printf("%#10.2g uS", acctime[MRB]);
- printf("%#10.2g uS", acctime[MRW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[MRD]);
- printf("%#10.2g\n", 0.401/acctime[MRW]);
-
- printf("Average Cache miss time: ");
- printf("%#10.2g uS", acctime[CRB]);
- printf("%#10.2g uS", acctime[CRW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[CRD]);
- printf("%#10.2g\n", 0.401/acctime[CRW]);
- } else {
- printf("Average RAM read time: ");
- printf("%#10.2g uS", acctime[MRB]);
- printf("%#10.2g uS", acctime[MRW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[MRD]);
- printf("%#10.2g\n", 0.401/acctime[MRW]);
- }
-
- printf("Average RAM write time: ");
- printf("%#10.2g uS", acctime[MWB]);
- printf("%#10.2g uS", acctime[MWW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[MWD]);
- printf("%#10.2g\n", 0.401/acctime[MWW]);
-
- if (emmok) {
- printf("Average EMM read time: ");
- printf("%#10.2g uS", acctime[ERB]);
- printf("%#10.2g uS", acctime[ERW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[ERD]);
- printf("%#10.2g\n", 0.402/acctime[ERW]);
-
- printf("Average EMM write time: ");
- printf("%#10.2g uS", acctime[EWB]);
- printf("%#10.2g uS", acctime[EWW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[EWD]);
- printf("%#10.2g\n", 0.402/acctime[EWW]);
- }
- printf("Average ROM read time: ");
- printf("%#10.2g uS", acctime[RRB]);
- printf("%#10.2g uS", acctime[RRW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[RRD]);
- printf("%#10.2g\n", 0.401/acctime[RRW]);
-
- printf("Average Video write time: ");
- printf("%#10.2g uS", acctime[VWB]);
- printf("%#10.2g uS", acctime[VWW]);
- if (cpu > 2)
- printf("%#10.2g uS", acctime[VWD]);
- printf("%#10.2g\n", 2.415/acctime[VWW]);
- }
-
- switch (cpu) {
-
- case 0:
- if (six)
- printf(" 8086");
- else
- printf(" 8088");
- break;
-
- case 1:
- if (six)
- printf("80186");
- else
- printf("80188");
- break;
-
- case 2:
- printf("80286");
- break;
-
- case 3:
- printf("80386");
- break;
- }
- printf(" CPU clock rate: ");
- printf("%#4.1g MHz", clkrate);
- printf(" Relative: %#4.2g\n", clkrate/8.0);
-
- if (ndpok) {
- switch(cpu) {
-
- case 0:
- case 1:
- printf(" 8087");
- break;
-
- case 2:
- printf("80287");
- break;
-
- case 3:
- if (fastmath)
- printf("80387");
- else
- printf("80287");
- break;
- }
- printf(" Coprocessor 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.
- */
-
- if (cpu == 3)
- raw = acctime[MRD] / clktime;
- else
- raw = acctime[IRW] / 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");
- if (cpu < 2) {
- if (six)
- analyze("Fetch", acctime[IRW],
- acctime[IRW], 2.0*acctime[IRW], "");
- else
- analyze("Fetch", acctime[IRB],
- acctime[IRW], 2.0*acctime[IRW], "");
- } else {
- if (cache) {
- analyze("Cache hit",
- acctime[MRB], acctime[MRW],
- acctime[MRD], "cache");
- analyze("Cache miss",
- acctime[CRB], acctime[CRW],
- acctime[CRD], "");
- } else {
- analyze("RAM read",
- acctime[MRB], acctime[MRW], acctime[MRD], "");
- }
- analyze("RAM write",
- acctime[MWB], acctime[MWW], acctime[MWD],
- mw_pipe? "pipelined" : "");
- if (emmok) {
- analyze("EMM read",
- acctime[ERB], acctime[ERW], acctime[ERD],
- cache && acctime[ERD] < acctime[MRD] + 0.5*clktime?
- "cache" : "");
- analyze("EMM write",
- acctime[EWB], acctime[EWW], acctime[EWD],
- ew_pipe? "pipelined" : "");
- }
- analyze("ROM read",
- acctime[RRB], acctime[RRW], acctime[RRD],
- cache && acctime[ERD] < acctime[MRD] + 0.5*clktime?
- "cache" : "");
- analyze("Video write",
- acctime[VWB], acctime[VWW], acctime[VWD], "");
- }
- }
-
- measure88()
- {
- register int i;
-
- /*
- * 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 *
- ((double)MULCLKS88*count + MULOVH88));
- }
-
- /*
- * 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;
-
- /*
- * Clear all of the memory speed accumulators.
- */
-
- for (i = 0; i < VARS88; i++)
- acctime[i] = 0;
-
- /*
- * Do the memory speed tests.
- */
-
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of timer ticks for
- * "count" clc instructions, which are
- * limited by memory fetch time.
- */
-
- raw = bclctime(count);
-
- /*
- * Accumulate the number of microseconds
- * per instruction fetch by adjusting for
- * the timer rate, test overhead, and
- * instruction count.
- */
-
- acctime[IRB] +=
- (raw / TIMER2_RATE - MOVOVH88) / count;
-
- /*
- * Make a similar measurement for the
- * two byte "mov" instruction.
- */
-
- raw = wmovtime(count);
- acctime[IRW] +=
- (raw / TIMER2_RATE - MOVOVH88) / count;
-
- /*
- * Make a similar measurement for the
- * 4 clock "daa" instruction.
- */
-
- raw = bdaatime(count);
- acctime[IRX] +=
- (raw / TIMER2_RATE - MOVOVH88) / count;
- }
-
- /*
- * Calculate averages for all measurements.
- */
-
- for (i = 0; i < VARS88; i++)
- acctime[i] /= trials;
-
- /*
- * 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 - FPOVH88) /
- FPCLKS88 / FPCOUNT;
- }
- fpacc /= trials;
- fprate = 1.0/fpacc;
- }
-
- /*
- * Set 86 flag if 2 clock byte instructions
- * execute faster than 4 clock instructions
- * due to being fetched two to a word.
- */
-
- six = acctime[IRB] < 0.9*acctime[IRX];
- }
-
- measure186()
- {
- register int i;
-
- /*
- * 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 *
- ((double)MULCLKS186*count + MULOVH186));
- }
-
- /*
- * 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;
-
- /*
- * Clear all of the memory speed accumulators.
- */
-
- for (i = 0; i < VARS186; i++)
- acctime[i] = 0;
-
- /*
- * Do the memory speed tests.
- */
-
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of timer ticks for
- * "count" clc instructions, which are
- * limited by memory fetch time.
- */
-
- raw = bclctime(count);
-
- /*
- * Accumulate the number of microseconds
- * per instruction fetch by adjusting for
- * the timer rate, test overhead, and
- * instruction count.
- */
-
- acctime[IRB] +=
- (raw / TIMER2_RATE - MOVOVH186) / count;
-
- /*
- * Make a similar measurement for the
- * two byte "mov" instruction.
- */
-
- raw = wmovtime(count);
- acctime[IRW] +=
- (raw / TIMER2_RATE - MOVOVH186) / count;
-
- /*
- * Make a similar measurement for the
- * 4 clock "daa" instruction.
- */
-
- raw = bdaatime(count);
- acctime[IRX] +=
- (raw / TIMER2_RATE - MOVOVH186) / count;
- }
-
- /*
- * Calculate averages for all measurements.
- */
-
- for (i = 0; i < VARS186; i++)
- acctime[i] /= trials;
-
- /*
- * 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 - FPOVH186) /
- FPCLKS186 / FPCOUNT;
- }
- fpacc /= trials;
- fprate = 1.0/fpacc;
- }
-
- /*
- * Set 86 flag if 2 clock byte instructions
- * execute faster than 4 clock instructions
- * due to being fetched two to a word.
- */
-
- six = acctime[IRB] < 0.9*acctime[IRX];
- }
-
- measure286()
- {
- register int i;
-
- /*
- * 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 *
- ((double)MULCLKS286*count + MULOVH286));
-
- }
-
- /*
- * 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;
-
- /*
- * Clear all of the memory speed accumulators.
- */
-
- for (i = 0; i < VARS286; i++)
- acctime[i] = 0;
-
- /*
- * Do the memory speed tests.
- */
-
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of timer ticks for
- * "count" clc instructions, which are
- * limited by memory fetch time.
- */
-
- raw = bclctime(count);
-
- /*
- * Accumulate the number of microseconds
- * per instruction fetch by adjusting for
- * the timer rate, test overhead, and
- * instruction count.
- */
-
- acctime[IRB] +=
- (raw / TIMER2_RATE - MOVOVH286) / count;
-
- /*
- * Make a similar measurement for the
- * two byte "mov" instruction.
- */
-
- raw = wmovtime(count);
- acctime[IRW] +=
- (raw / TIMER2_RATE - MOVOVH286) / count;
-
-
- /*
- * Measure byte read+write time
- * measuring movs instructions.
- */
-
- raw = bmvstime(count);
- acctime[MRB] += raw/(TIMER2_RATE*count);
-
- /*
- * Calculate ROM read time by
- * measuring movs from ROM to RAM.
- */
-
- raw = bromtime(count);
- acctime[RRB] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure word write using the
- * pusha instruction.
- */
-
- raw = wpshtime(count) - WPOVH;
- acctime[MWW] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure movs (read+write) time.
- */
-
- raw = wmvstime(count);
- acctime[MRW] += raw/(TIMER2_RATE*count);
- raw = wromtime(count);
- acctime[RRW] += raw/(TIMER2_RATE*count);
-
- /*
- * If EMM is present, do measurements
- * on it using the same techniques.
- */
-
- if (emmok) {
-
- /*
- * Measure byte mov in EMM.
- */
-
- raw = bemmtime(count);
- acctime[ERB] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure word write,
- * calculate word read.
- */
-
- raw = wemptime(count) - WPOVH;
- acctime[EWW] += raw/(TIMER2_RATE*count);
- raw = wemmtime(count);
- acctime[ERW] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Measure byte and word writes
- * into video RAM.
- */
-
- raw = bvidtime(count);
- acctime[VWB] += raw/(TIMER2_RATE*count);
- raw = wvidtime(count);
- acctime[VWW] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Calculate averages for all measurements.
- */
-
- for (i = 0; i < VARS286; i++)
- acctime[i] /= trials;
-
- /*
- * Adjust word write times by subtracting
- * the instruction fetch time.
- */
-
- acctime[MWW] -= acctime[IRW]/16;
- if (emmok)
- acctime[EWW] -= acctime[IRW]/16;
-
- /*
- * Adjust for extra time per instruction when
- * measuring zero wait state memory.
- */
-
- if (acctime[MWW] < 3.375*clktime)
- acctime[MWW] -= clktime/8;
- if (emmok)
- if (acctime[EWW] < 3.375*clktime)
- acctime[EWW] -= clktime/8;
-
- /*
- * Calculate byte write time by assuming the same
- * ratio between read and write as for word access.
- */
-
- acctime[MWB] = acctime[MRB] * acctime[MWW] /
- acctime[MRW];
- if (emmok)
- acctime[EWB] = acctime[ERB] * acctime[EWW] /
- acctime[ERW];
-
- /*
- * Calculate read times by subtracting write time from
- * mov (read+write) time.
- */
-
- acctime[MRB] = acctime[MRB] - acctime[MWB];
- acctime[MRW] = acctime[MRW] - acctime[MWW];
- acctime[RRB] = acctime[RRB] - acctime[MWB];
- acctime[RRW] = acctime[RRW] - acctime[MWW];
- if (emmok) {
- acctime[ERB] = acctime[ERB] - acctime[EWB];
- acctime[ERW] = acctime[ERW] - acctime[EWW];
- }
-
- /*
- * 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 - FPOVH286) /
- FPCLKS286 / FPCOUNT;
- }
- fpacc /= trials;
- fprate = 1.0/fpacc;
- }
-
- /*
- * Fill in dword variables to
- * provide complete input to
- * analyze.
- */
-
- acctime[MRD] = 2.0 * acctime[MRW];
- acctime[MWD] = 2.0 * acctime[MWW];
- acctime[ERD] = 2.0 * acctime[ERW];
- acctime[EWD] = 2.0 * acctime[EWW];
- acctime[RRD] = 2.0 * acctime[RRW];
- acctime[VWD] = 2.0 * acctime[VWW];
- }
-
- double accrd1, accrd2;
- measure386()
- {
- register int i;
- double pfetch;
-
- /*
- * Make a preliminary measurement of fetch time to
- * use in fine-tuning the clock measurement.
- */
-
- raw = dmovtime(count);
- pfetch = raw / TIMER2_RATE / count / 14;
-
- /*
- * 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 *
- ((double)MULCLKS386*count + MULOVH386));
-
- }
-
- /*
- * 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;
-
- /*
- * Clear all of the memory speed accumulators.
- */
-
- for (i = 0; i < VARS386; i++)
- acctime[i] = 0;
- accrd1 = 0;
- accrd2 = 0;
-
- /*
- * Do the memory speed tests.
- */
-
- for (i = 0; i < trials; i++) {
-
- /*
- * Obtain the number of timer ticks for
- * "count" clc instructions, which are
- * limited by memory fetch time.
- */
-
- raw = bclctime(count);
-
- /*
- * Accumulate the number of microseconds
- * per instruction fetch by adjusting for
- * the timer rate, test overhead, and
- * instruction count.
- */
-
- acctime[IRB] +=
- (raw / TIMER2_RATE - MOVOVH386) / count;
-
- /*
- * Make a similar measurement for the
- * two byte and four byte "mov" instruction.
- */
-
- raw = wmovtime(count);
- acctime[IRW] +=
- (raw / TIMER2_RATE - MOVOVH386) / count;
-
- raw = dimmtime(count);
- acctime[IRD] +=
- (raw / TIMER2_RATE / 14 - MOVOVH386) / count;
-
-
- /*
- * Measure byte read+write time
- * measuring movs instructions.
- */
-
- raw = bmvstime(count);
- acctime[MRB] += raw/(TIMER2_RATE*count);
-
- /*
- * Calculate ROM read time by
- * measuring movs from ROM to RAM.
- */
-
- bromtime(count); /* To prime a cache */
- raw = bromtime(count);
- acctime[RRB] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure word and dword write using the
- * pusha instruction.
- */
-
- raw = wpshtime(count) - WPOVH;
- acctime[MWW] += raw/(TIMER2_RATE*count);
-
- raw = dpshtime(count) - DPOVH;
- acctime[MWD] += raw/(TIMER2_RATE*count);
-
- /*
- * Measure word and dword
- * movs (read+write) time.
- */
-
- raw = wmvstime(count);
- acctime[MRW] += raw/(TIMER2_RATE*count);
- wromtime(count);
- raw = wromtime(count);
- acctime[RRW] += raw/(TIMER2_RATE*count);
-
- raw = dmvstime(count);
- acctime[MRD] += raw/(TIMER2_RATE*count);
- dromtime(count);
- raw = dromtime(count);
- acctime[RRD] += raw/(TIMER2_RATE*count);
-
- /*
- * Use some alternate methods to measure read time.
- */
-
- raw = dimmtime(count);
- accrd1 += raw/(TIMER2_RATE*count*14);
-
- raw = dlodtime(count);
- accrd2 += raw/(TIMER2_RATE*count*2);
-
- raw = dramtime(count);
- acctime[CRD] += raw/(TIMER2_RATE*count);
-
- /*
- 54rr * If EMM is present, do measurements
- * on it using the same techniques.
- */
-
- if (emmok) {
-
- bemmtime(count);
- raw = bemmtime(count);
- acctime[ERB] += raw/(TIMER2_RATE*count);
-
- raw = wemptime(count) - WPOVH;
- acctime[EWW] += raw/(TIMER2_RATE*count);
- wemmtime(count);
- raw = wemmtime(count);
- acctime[ERW] += raw/(TIMER2_RATE*count);
-
- raw = demptime(count) - DPOVH;
- acctime[EWD] += raw/(TIMER2_RATE*count);
- demmtime(count);
- raw = demmtime(count);
- acctime[ERD] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Measure writes
- * into video RAM.
- */
-
- raw = bvidtime(count);
- acctime[VWB] += raw/(TIMER2_RATE*count);
- raw = wvidtime(count);
- acctime[VWW] += raw/(TIMER2_RATE*count);
- raw = dvidtime(count);
- acctime[VWD] += raw/(TIMER2_RATE*count);
- }
-
- /*
- * Calculate averages for all measurements.
- */
-
- for (i = 0; i < VARS386; i++)
- acctime[i] /= trials;
- accrd1 /= trials;
- accrd2 /= trials;
- }
-
- adjust386()
- {
- register int i;
- double fpclks;
-
- /*
- * Adjust word write times by subtracting
- * the instruction fetch time.
- */
-
- acctime[MWW] -= acctime[IRW]/16;
- acctime[MWD] -= acctime[IRW]/8;
- if (emmok) {
- acctime[EWW] -= acctime[IRW]/16;
- acctime[EWD] -= acctime[IRW]/8;
- }
-
- /*
- * Adjust for extra time per instruction when
- * measuring zero wait state memory.
- */
-
- if (acctime[MWW] < 3.375*clktime)
- acctime[MWW] -= clktime;
- if (acctime[MWD] < 3.375*clktime)
- acctime[MWD] -= clktime;
- if (emmok) {
- if (acctime[EWW] < 3.375*clktime)
- acctime[EWW] -= clktime;
- if (acctime[EWD] < 3.375*clktime)
- acctime[EWD] -= clktime;
- }
-
- /*
- * Calculate byte write time by assuming the same
- * ratio between read and write as for word access.
- */
-
- acctime[MWB] = acctime[MRB] * acctime[MWW] /
- acctime[MRW];
- if (emmok)
- acctime[EWB] = acctime[ERB] * acctime[EWW] /
- acctime[ERW];
-
- /*
- * Calculate read times by subtracting write time from
- * mov (read+write) time.
- */
-
- acctime[MRB] = acctime[MRB] - acctime[MWB];
- acctime[MRW] = acctime[MRW] - acctime[MWW];
- acctime[MRD] = acctime[MRD] - acctime[MWD];
-
- /*
- * Don't believe read time if less than 2 clocks
- */
-
- if (acctime[MRD] < 1.75*clktime) {
- mw_pipe = 1;
- }
-
- /*
- * Use alternate read times for double, if better.
- */
-
- if (accrd1 < acctime[MRD] || mw_pipe) {
- acctime[MRB] = accrd1;
- acctime[MRW] = accrd1;
- acctime[MRD] = accrd1;
- }
- if (accrd2 < acctime[MRD]) {
- acctime[MRB] = accrd2;
- acctime[MRW] = accrd2;
- acctime[MRD] = accrd2;
- }
-
- acctime[RRB] = acctime[RRB] - acctime[MWB];
- acctime[RRW] = acctime[RRW] - acctime[MWW];
- acctime[RRD] = acctime[RRD] - acctime[MWD];
- if (mw_pipe) {
- acctime[RRB] += acctime[MRD];
- acctime[RRW] += acctime[MRD];
- acctime[RRD] += acctime[MRD];
- }
- if (emmok) {
- acctime[ERB] = acctime[ERB] - acctime[EWB];
- acctime[ERW] = acctime[ERW] - acctime[EWW];
- acctime[ERD] = acctime[ERD] - acctime[EWD];
- if (acctime[ERD] < 1.75*clktime) {
- ew_pipe = 1;
- acctime[ERB] = acctime[MRD];
- acctime[ERW] = acctime[MRD];
- acctime[ERD] = acctime[MRD];
- }
- }
-
- if (acctime[CRD] - accrd2 > accrd2 + 0.5*clktime) {
- cache = 1;
- acctime[CRD] -= accrd2;
- acctime[CRW] = acctime[CRD];
- acctime[CRB] = acctime[CRD];
- }
-
- /*
- * 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) {
-
- fastmath = detect_387();
- if (fastmath)
- fpclks = FPCLKS387;
- else
- fpclks = FPCLKS386;
- fprate = 0;
- for (i = 0; i < trials; i++) {
- raw = fptime(count);
- fpacc += (raw / TIMER2_RATE - MULOVH386) / count;
- }
- fpacc = (fpacc / trials - 1.5*acctime[IRD]) / fpclks;
- fprate = 1.0/fpacc;
- }
- }
-
- /*
- * 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.
- * Similar arguments can be made about 32 bit accesses.
- *
- * 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, dtime, notes)
- char *name;
- double btime;
- double wtime;
- double dtime;
- char *notes;
- {
- double t;
-
- /*
- * Print the heading
- */
-
- printf("%-12s", name);
-
- /*
- * Determine whether the memory is byte
- * oriented, word oriented, dword oriented, or other.
- * (If other, the data are suspect.)
- */
-
- if (wtime > dtime*0.66 &&
- wtime < dtime*1.33) {
- printf(" Dword ");
- t = dtime;
- } else if (wtime*2 > dtime*0.66 &&
- wtime*2 < dtime*1.33 &&
- btime > wtime*0.66 &&
- btime < wtime*1.33) {
- printf(" Word ");
- t = wtime;
- } else if (btime*2 > wtime*0.66 &&
- btime*2 < wtime*1.33) {
- printf(" Byte ");
- t = btime;
- } else {
- printf(" Strange");
- t = btime;
- }
-
- /*
- * Determine the number of wait states
- * by dividing by the clock period,
- * subtracting two processor clock times,
- * and rounding down to an integer.
- */
-
- t = t / clktime - access_clks;
- if (t < 0.0)
- t = 0.0;
- /****** printf(" %6d", (unsigned)t); ******/
- printf(" %6.1g", t);
- printf(" %s\n", notes);
- }