RTF/68K means 'Real Time Fortran 77 for 68K Processors' and consists
of a compiler and a run-time library. It provides (almost) full Fortran
77 for 68K series microprocessors while satisfying some additional demands,
namely:
- Compatibility with VAX-11 Fortran (which is a superset of the standard
ANSI X3.9-1978),
- Good overall run-time efficiency,
- Easy and efficient applicability to real-time and system implementation
problems.
The entire 68K processor family is supported: MC68000/08, MC68010/12,
and 68020/30/40. While the latter are object-code compatible with the earlier
family members, the compiler optionally produces code which utilizes the
additional features of the 68020/30/40.
RTF generates code for the 68881/68882 floating point coprocessor. In
case no floating point coprocessor is installed, it relies on an f-line
exception handler to call the floating point software emulation as either
part of the RTF runtime library or a system-level exception handler, as
for the 68040.
RTF/68K is, for the purpose of easy adaptability, written in a comprehensive
'very-high-level' language (4000 lines of source code for the compiler).
Nevertheless, the compiler is portable because a translator generates Fortran
code out of this source. Thus, the compiler is also available in Fortran
form (the same is true for the translator). RTF/68K runs on VAX as a cross-compiler
and on 68K as a native compiler.
RTF/68K produces an intermediate assembly code as output. This is then
further processed by one of the available assemblers, e.g. r68020 of OS-9.
The connection to linkers, e.g. l68 of OS-9, is thus obtained automatically.
Calling sequences and debug information generated by RTF/68K conform
to the CERN standard for 68K processors, or optionally to the requirements
of specific operating systems (e.g. OS-9).
The RTF/68K run-time library is to 95% written in RTF/68K. The small
rest, which provides the interfacing to the environment (hardware setup
and operating system, if any) is assembler. Thus, RTF/68K is essentially
self-contained and easily adapted to any software environment.
The RTF/68K package is available free on distribution tape or Floppy
disk - ready to be used with VAX computers running VMS and for 68k systems
running OS-9. Compiler and run-time system can be adapted to other 32-bit
systems with little effort. The major host/target systems are: any 68k
board running OS-9, and any Macintosh running MacSYS. Host-only systems
include VAX/VMS and Macintosh with MPW. Target-only systems are numerous
- mostly 68k boards without an operating system.
Since VAX computers are widely used in fields where 16/32-bit micros
might also find their place, and since VAX-11 Fortran is friendly in that
it digests virtually every Fortran, the RTF/68K syntax has been made as
similar as possible to VAX-11 Fortran. RTF/68K is best described by stating
the omissions and extensions as compared to VAX-11 Fortran.
Omissions:
- The input/output statements are not fully implemented;
namely, direct-access read/write is available only via subroutine calls,
and INQUIRE is missing.
- The EQUIVALENCE statement does not automatically increase storage
allocation in case of size incompatibility. Moreover, only pairs of two
variable names are accepted.
- DATA statements may contain only one variable per constants list.
- COMPLEX data are not supported.
- Arrays may have up to five indices only.
Some important VAX-11 Fortran features are explicitly implemented, e.g.
the syntax of hexadecimal and octal numbers; INCLUDE statements; short
(one and two byte) data types; and end-of-line comments.
Extensions:
- Pointer-based variables are available.
- Explicit access to the processor (and coprocessor) registers is possible
under Fortran variable names.
- Explicit access to absolute addresses is possible under Fortran names,
allowing easy and efficient memory-mapped I/O.
- EQUIVALENCE is allowed with pointers and thus also with formal arguments.
- Entire COMMON blocks may be based on pointers and can thus be assigned
to memory dynamically. This offers almost everything that is available
with 'structs' or 'records' in other languages. For convenience such COMMON
blocks may be called RECORDs.
- Entire COMMONs may also be placed at absolute addresses, e.g. for
memory-mapped I/O to 'structured' sets of hardware registers.
- Arguments may be passed by value as well as by reference.
- Global variables are possible; e.g., all COMMON blocks could be stated
once at the beginning of a file and are then valid for all routines that
follow.
- The data types INTEGER*1,*2 are supported. These are useful for accessing
some hardware devices, and may as well serve for saving a factor of two
or four in memory.
- 'Strong typing' may be forced by IMPLICIT NONE. This is highly recommended
as a big step towards writing correct programs. In any case, warnings are
given by the compiler if undeclared variables are definitely read-accessed.
Misspelt names on the left hand side in assignment statements, however,
require IMPLICIT NONE to be detected.
- Besides DO index=.. ENDDO and DO WHILE, DO UNTIL and DO FOREVER are
available.
- The number of routine arguments may vary and can be obtained inside
the routine by CALL NUMPAR(num). If this statement is omitted, however,
and the actual number of arguments differs from the declared one, a run-time
message is issued.
- The generated code is position-independent.
- All routines are re-entrant. Recursive calls are possible. Libraries
are sharable.
- Subroutines can serve as interrupt handlers without any software overhead
between interrupt vector and routine entry. Also, they may be used as event
flag handlers known under some operating systems.
- Integer constants may be written in decimal, hexadecimal, octal, binary,
and ASCII form.
- Dynamic storage allocation is provided with the ALLOCATE ... ENDBLOCK
construct.
- All the ISA bit-handling functions are implemented with fast in-line
code.
- Special in-line subroutines and functions provide for efficient block-moves,
bit handling, and semaphore control for system implementation.
- Embedded assembly code is possible.
- 'Hardware subroutines' (implemented as special coprocessors) are supported
with generation of fast in-line code.
Since some of these concepts are unusual in Fortran (but look a bit
like Pascal or C), a few examples might illustrate their use. Remember
that without the additional features used here you would have to write
it in assembler or use external assembler routines (the calling of which
costs extra time). Note that some of the examples below are intentionally
quite tricky.
equivalence (VIOR,'FFF980'X) ! this states the address of
integer*2 VIOR ! ..the hardware register
VIOR=0 ! issue command
STATUS=VIOR ! ..to read hardware status
integer function FAK(N) ! this is the most obsolete
if(N.le.1) then ! ..example of recursion
FAK=1
else
FAK=N*FAK(N-1)
endif
end
subroutine TERMIO ! this routine is activated
interrupt 122 ! whenever interrupt 122 occurs
implicit integer*1 (a-z)
parameter (RxD_ready=3)
equivalence (STAT,'FF2000'X),
(DATA,'FF2001'X)
if(btest(STAT,RxD_ready)) then
I=I+1
BUF(I)=DATA ! ..and then reads hardware
...
logical function THERE(ADDR) ! tests if ADDR exists
integer*2 ADDR,JUNK,SSAVE,S ! (in supervisor mode)
integer*4 IVEC(0:255),IVECSAV
equivalence (IVEC,0),(S,SR)
IVECSAV=IVEC(2) ! save old vector contents
SSAVE=S ! .. and status register
assign 2 to IVEC(2) ! link bus errors to label
JUNK=ADDR ! test if address responds
THERE=.true.
goto 1
2 THERE=.false. ! go here if bus error
1 IVEC(2)=IVECSAV
S=SSAVE ! the UNLK instruction will
end ! .. clean up the stack
program Dyn_Storage
real @FIELD(0:3,N,N) ! dynamic storage allocation
accept *,N
...
allocate 4*4*N**2 for FIELD ! allocate proper number
FIELD(0,2,3)=PHI ! of bytes for FIELD
...
endblock
allocate * for FIELD ! exactly the same as above
FIELD(0,2,3)=PHI ! * allocates amount stated
... ! in declaration
end block
The next example shows how a pointer-based COMMON or RECORD may be used
to describe data structures which don't have a fixed location in memory.
In this example, the entire structure is even a formal subroutine argument.
subroutine ANALYZE(EVENT,...)
record /EVENT/ TOF(32),CALO(128),PAT,CNT(6)
or alternatively
common /@EVENT/ TOF(32),CALO(128),PAT,CNT(6)
integer TOF,CALO,PAT,CNT
...
if(iand(PAT,'11'O) .ne. 0 .and. CALO(2).ge.MIN)
...
This is an example where a COMMON block is bound to a fixed absolute
address:
common/'100000'X/ VMX_SPACE(0:'3FFFF'X),EXTRA_VMX('40000'X)
RTF/68K has been used to implement a wide range of different applications,
such as the FASTBUS routine package, Mini-GD3, CAMAC readout tasks, a complex
VME multiprocessor system for driftchamber readout and on-line analysis,
the RTF/68K runtime library, and last but not least the RTF/68K compiler
itself.
Given that RTF/68K is made primarily for real-time applications of moderately
to very complex microprocessor systems with close connections to hardware
('embedded systems'), it may be worthwile to summarize the arguments for
specific extensions offered by RTF/68K. The most crucial and least usual
extension is the provsion for memory mapped I/O, and the arguments for
this are as follows.
- In the environment of physics experiments, the problem-oriented part
of the application (e.g. analysis algorithms) usually will be, or is already,
programmed in Fortran.
- One of the essentials of microprocessors with big address space
is the simplicity and efficiency of memory-mapped I/O.
- The access to the hardware is only in simplistic cases a small subset
of the whole application. Instead, a proven way to keep the hardware simple
is by interaction with a programmable device like a micro- processor -
hence the name 'embedded system'. The processors (and their programs) act
as an interface with one leg deep inside the hardware.
- Complete hardware-independence of the application program is an
illusion for this reason. There is no argument why only programs that are
anyway unreadable (assembler) should be allowed to be hardware dependent,
unless one wants to maintain admired 'experts' and grateful
'users' that are supposed to understand nothing and hence are not allowed
to really exploit the system.
- The access to static absolute addresses is very simple to understand
for normal (not 'real-time') Fortran users because Fortran always had a
'hardware-dependent' component - the possible knowledge of how variables
are arranged in memory. This access fits directly into the ordinary Fortran
syntax. The extension to dynamic addressing by pointers is well known from
other high-level languages. Both concepts are straightforward to implement
into Fortran.
- A memory-mapped software interface to the hardware is by orders
of magnitude faster than even the optimally coded usual subroutine/call
interface - just because the processor hardware is able to do it directly
in one instruction.
- In summary, Fortran with extensions like in RTF/68K is suited for
problem and system programming. It allows to write the entire application
in a single high-level language. Non-experts find an easy way to system
programming.
In fact, at least one very complex readout and analysis system with
34 tightly coupled (shared memory) VME processors has been written in RTF/68K.
It was not necessary to use assembler statements. None of the participants
started as an expert in this project, and yet is was finished in a very
short time.