#define SW_POPCNT 0 #define SW_LEADZ 1 CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC c CVS Info c $Date: 2005/01/10 21:56:21 $ c $Revision: 1.2 $ c $RCSfile: util.F,v $ c $Name: rel_5 $ C C Following are software versions of the leading zero and popcount C functions needed for those architectures without these features. C It also contains versions of the timing routines. The timing C routines most likely will need to be modified for each C architecture. C C Contents: C INITPC - Popcount table initialization C POPCNT - Popcount function C INITLZ - Leading zero table initialization C LEADZ - Leading zero function C WALL - Wall Clock timer function C CPUTIME - CPU timer function C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC #ifdef SW_POPCNT SUBROUTINE INITPC c Uncomment this routine for machines without popcnt hardware. c This routine initializes a 2^16 array to contain the popcount c of each index. Then the popcount of a 64 bit number can be c performed with four table look-ups. IMPLICIT INTEGER (A-Z) COMMON /POPS/POPS(0:65535) INTEGER POPS2(0:255) INTEGER POPS3(0:15) c POPS3 contains the popcount of 4 bit indices DATA POPS3/0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4/ C--CVS variable declaration TYPE CVS sequence character( 160 ) string integer stringend END TYPE CVS C--CVS initilaize variables TYPE( CVS ),save :: CVS_INFO = $ CVS("BMARKGRP $Date: 2005/01/10 21:56:21 $ $Revision: 1.2 $" // $ "$RCSfile: util.F,v $ $Name: rel_5 $", 0) c Generate array POPS2 to contain the popcount of 8 bit indices DO 10 I = 0,15 DO 10 J = 0,15 POPS2(I*16+J) = POPS3(I) + POPS3(J) 10 CONTINUE c Finally, generate array POPS to contain the popcount of 16 bit indices DO 20 I = 0,255 DO 20 J = 0,255 POPS(I*256+J) = POPS2(I) + POPS2(J) 20 CONTINUE RETURN END FUNCTION POPCNT(IVAL) c Uncomment this routine for machines without popcnt hardware. c This routine uses the array initialized in INITPC to find the c popcount of a 64-bit number. IMPLICIT INTEGER (A-Z) c Version for 64-bit words COMMON /POPS/POPS(0:65535) POPCNT = POPS(IAND(65535,IVAL)) + & POPS(IAND(65535,ISHFT(IVAL,-16))) + & POPS(IAND(65535,ISHFT(IVAL,-32))) + & POPS(IAND(65535,ISHFT(IVAL,-48))) RETURN END #endif SW_POPCNT #ifdef SW_LEADZ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c For machines without leadz hardware, define SW_LEADZ 1 at top of file. c 'INITLZ' initializes a 2^16 array to contain the position of c the leading zero of each index. c 'LEADZ' uses the table to handle 64-bit ints cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc SUBROUTINE INITLZ IMPLICIT INTEGER*8 (A-Z) COMMON /LZCNT/LZCNT(0:65535) COMMON / TWOPERS / TWO48M1, TWO32M1, TWO16M1 LZCNT(0) = 16 LZCNT(1) = 15 DO 20 I = 2,16 DO 10 J = 2**(i-1),2**I-1 LZCNT(J) = 16-I 10 CONTINUE 20 CONTINUE TWO16 = 2**16 TWO32 = TWO16 * TWO16 TWO48 = TWO32 * TWO16 TWO48M1 = TWO48 - 1 TWO32M1 = TWO32 - 1 TWO16M1 = TWO16 - 1 RETURN END FUNCTION LEADZ(IVAL) c This routine uses the array initialized in INITLZ to find the c leading zero in the first non-zero double byte. IMPLICIT INTEGER*8 (A-Z) c Version for 64-bit words COMMON /LZCNT/LZCNT(0:65535) COMMON / TWOPERS / TWO48M1, TWO32M1, TWO16M1 IF (IVAL .GT. TWO48M1) THEN LEADZ = LZCNT(IAND(TWO16M1,ISHFT(IVAL,-48))) ELSE IF (IVAL .GT. TWO32M1) THEN LEADZ = 16 + LZCNT(IAND(TWO16M1,ISHFT(IVAL,-32))) ELSE IF (IVAL .GT. TWO16M1) THEN LEADZ = 32 + LZCNT(IAND(TWO16M1,ISHFT(IVAL,-16))) ELSE LEADZ = 48 + LZCNT(IAND(TWO16M1,IVAL)) END IF RETURN END #endif SW_LEADZ FUNCTION WALL() cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Computes the amount of wall clock time that has elapsed. c c Make suitable changes to provide access to wall clock time c on architecture being used. c ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc #include "bench11.h" MY_DOUBLE WALL #ifdef CRAY REAL SECONDR WALL = SECONDR() #else MY_DOUBLE MPI_WTIME WALL = MPI_WTIME() #endif RETURN END FUNCTION CPUTIME() cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c Computes the amount of cpu time that has elapsed. c c Make suitable changes to provide access to cpu time on c architecture being used. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc #include "bench11.h" MY_DOUBLE CPUTIME #ifdef CRAY REAL TSECND CPUTIME = TSECND( ) C CPUTIME = RTC() #else REAL*4 ETIME, TARRAY(2) EXTERNAL ETIME CPUTIME = ETIME ( TARRAY ) #endif RETURN END