VX/FPT - Record/Replay (Hamlet)
VX/FPT instruments the user's code to capture and to replay:
- File and terminal I/O
- The arguments of interface routines
- Interfaces to shared memory
For example, the subroutine:
SUBROUTINE GET_VISCOSITY_TABLE
C
COMMON /VTAB/ VISCOSITY(1000)
C
OPEN(7,FILE='VISCOSITY.DAT',ACCESS='DIRECT',STATUS='OLD')
DO I=1,1000
READ(7,REC=I,ERR=200)VISCOSITY(I)
ENDDO
WRITE(1,100)
100 FORMAT (/,'Viscosity table read successfully')
CLOSE (7)
RETURN
C
200 WRITE(1,300)
300 FORMAT (/,'Error reading viscosity table - aborting')
STOP
C
END
|
is modified by VX/FPT to read:
SUBROUTINE GET_VISCOSITY_TABLE
C
INCLUDE 'rr_cmn.fpi'
C
COMMON /VTAB/VISCOSITY(1000)
C
IF (.NOT. REPLAY_IO(1,7)) THEN
OPEN (7,FILE='VISCOSITY.DAT',ACCESS='DIRECT',STATUS='OLD')
ENDIF
DO I=1,1000
IF (REPLAY_IO(2,7)) THEN
READ (RR_LUN_FOR_REPLAY,*)RR_IOSTAT
READ (RR_LUN_FOR_REPLAY,*)VISCOSITY(I)
ELSE
READ (7,REC=I,IOSTAT=RR_IOSTAT)VISCOSITY(I)
ENDIF
IF (RR_INPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_INPUT,*)RR_IOSTAT
WRITE (RR_LUN_TO_RECORD_INPUT,*)VISCOSITY(I)
ENDIF
IF (RR_IOSTAT .NE. 0) THEN
GOTO 200
ENDIF
ENDDO
IF (.NOT. REPLAY_IO(3,1)) THEN
WRITE (1,100)
ENDIF
IF (RR_OUTPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_OUTPUT,100)
ENDIF
100 FORMAT (/,'Viscosity table read successfully')
IF (.NOT. REPLAY_IO(4,7)) THEN
CLOSE (7)
ENDIF
RETURN
C
200 CONTINUE
IF (.NOT. REPLAY_IO(5,1)) THEN
WRITE (1,300)
ENDIF
IF (RR_OUTPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_OUTPUT,300)
ENDIF
300 FORMAT (/,'Error reading viscosity table - aborting')
STOP
C
END
|
The Changes VX/FPT Has Made
VX/FPT has inserted an INCLUDE statement for declaration of the variables used to control record and replay.
INCLUDE 'rr_cmn.fpi' |
The control variables, RR_LUN_FOR_REPLAY, RR_OUTPUT_RECORD_F etc. are in COMMON blocks. The file also contains declarations of the control functions such as REPLAY_IO(N,UNIT). This function determines whether the unit is being replayed or not.
The OPEN statement has been enclosed in a test to find whether or not the unit, in this case unit 7, is being replayed.
IF (.NOT. REPLAY_IO(1,7)) THEN
OPEN (7,FILE='VISCOSITY.DAT',ACCESS='DIRECT',STATUS='OLD')
ENDIF
|
If unit 7 is replayed from the captured data, we don't need to open the file. This means that the original files don't need to be present when the code is first tested.
The read of the viscosity array has been enclosed in a test.
IF (REPLAY_IO(2,7)) THEN
READ (RR_LUN_FOR_REPLAY,*)RR_IOSTAT
READ (RR_LUN_FOR_REPLAY,*)VISCOSITY(I)
ELSE
READ (7,REC=I,IOSTAT=RR_IOSTAT)VISCOSITY(I)
ENDIF
|
If unit 7 is being replayed, VISCOSITY(I) is read from the replay file. If not, the original READ statement is executed.
VX/FPT inserts code to capture the values from the viscosity file.
IF (RR_INPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_INPUT,*)RR_IOSTAT
WRITE (RR_LUN_TO_RECORD_INPUT,*)VISCOSITY(I)
ENDIF
|
The original READ statement had an END= destination. This has been replaced by capturing the IOSTAT value in the READ. The IOSTAT is replayed to the variable RR_IOSTAT and this is used to control jumping to the error destination by the statements:
IF (RR_IOSTAT .NE. 0) THEN
GOTO 200
ENDIF
RR_IOSTAT is also replayed from the recorded file, so that the recording behaves in exactly the same way as the original code.
The WRITE statement to unit 1 is modified in a similar way. Once again, the statement is enclosed in a test, and is not executed if unit 1 is being replayed. The file does not need to exist during the initial stages of testing.
IF (.NOT. REPLAY_IO(3,1)) THEN
WRITE (1,100)
ENDIF
IF (RR_OUTPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_OUTPUT,100)
ENDIF
100 FORMAT (/,'Viscosity table read successfully')
|
Note that VX/FPT captures the outputs from the program as well as the inputs. In a migration project, the outputs may be compared on the old and new hosts as a diagnostic tool.
The Extent of the Changes
VX/FPT has re-written so much of this small subroutine that it is almost unrecognisable. This is not typical. It has happened because the subroutine contains almost nothing but I/O statements. Usually, the record/replay process makes very few changes to a large program.
A Shared Memory Location
Many programs have interfaces which are shared memory locations. These may also be instrumented for record and replay. In the code fragment below, VISBUFR is part of a memory block shared between a simulation program and the visual scene generator.
C Only the visual system knows where the ground is
RADAR_ALT=-RVISBUF(3)
|
To instrument this interface, we need to tell VX/FPT that the memory is shared. This is done by annotating a declaration of VISBUFR. The annotation doesn't need to be in the main code body. It can be written in a small template file which is used only by VX/FPT. The annotation would be, for example:
COMMON /VISBUF/ RVISBUF(20),IVISBUF(200) C% Record/replay interface:: RVISBUF |
The comment beginning C% has special meaning to VX/FPT.
VX/FPT then modifies the original statement to read:
C Only the visual system knows where the ground is
C RADAR_ALT=-RVISBUF(3)
IF (REPLAY_INTERFACE(1,'RVISBUF')) THEN
READ (RR_LUN_FOR_REPLAY,*)RVISBUF_TMP(3)
ELSE
RVISBUF_TMP(3)=RVISBUF(3)
ENDIF
IF (RR_INPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_INPUT,*)RVISBUF_TMP(3)
ENDIF
RADAR_ALT=-RVISBUF_TMP(3)
|
The original statement is commented-out. Note how replay of the specific interface is controlled by the logical function REPLAY_INTERFACE(N,NAME).
VX/FPT has added a new array, RVISBUF_TMP to the code. This has the same bounds and type as the original array RVISBUF and is declared wherever it is needed.
A Sub-Program Interface
Programs may communicate with external devices or other programs through sub-program arguments. To instrument these interfaces, VX/FPT requires a declaration that the sub-program is an interface, and needs either the code of the sub-program, or a template which indicates the INTENT of the arguments - whether they are inputs, outputs or both. Templates may be written in small files outside the main body of the code, which are processed only by VX/FPT. For example:
C Template for MACRO routine TO_RADALT
C% Record/replay interface TO_RADALT
SUBROUTINE TO_RADALT(V,IADD,IE)
C% INTENT (IN) :: V
C% INTENT (IN) :: IADD
C% INTENT (OUT) :: IE
END
|
A call to TO_RADALT, for example:
CALL TO_RADALT(RADAR_ALT,23,ISTAT) |
is instrumented to read:
IF (REPLAY_INTERFACE(2,'TO_RADALT')) THEN
READ (RR_LUN_FOR_REPLAY,*)ISTAT
ELSE
CALL TO_RADALT(RADAR_ALT,23,ISTAT)
ENDIF
IF (RR_INPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_INPUT,*)ISTAT
ENDIF
IF (RR_OUTPUT_RECORD_F) THEN
WRITE (RR_LUN_TO_RECORD_OUTPUT,*)RADAR_ALT,23
ENDIF
|
VX/FPT Reference Manual
For a more complete description of the record/replay process, and of some of the special cases which arise, please see the VX/FPT Reference Manual.

