Category : System Diagnostics for your computer
Archive   : ATPERF.ZIP
Filename : ATPERF.C

 
Output of file : ATPERF.C contained in archive : ATPERF.ZIP
/*
* 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);
}


  3 Responses to “Category : System Diagnostics for your computer
Archive   : ATPERF.ZIP
Filename : ATPERF.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/