Salsa - Machine
Salsa
Topics
Nachos
User Programs in Nachos
The directory code/machine contains the source code for the hardware
that Nachos simulates. This document describes the fuctionality supported by
the architecture that Nachos simulates.
Source code in code/machine
The Nachos machine simulates an architecture approximating MIPS and can
execute arbitrary programs. This is done by loading instructions for the user
programs into Nachos main memory, initializing registers (including the
program counter) and then asking the machine to start executing those
instructions. The machine fetches the instruction that is pointed to by PCReg
(the register containing the program counter), decodes and executes it. This
fetch-decode-execute cycle is repeated until either an illegal operation is
performed or a hardware interrupt is generated. In such an event, the
execution of the MIPS instructions is suspended and a Nachos interrupt service
routine is invoked to deal with the condition.
The machine simulates the general low-level facilities of typical machines,
including interrupts, virtual memory and interrupt-driven device I/O.
Nachos has two modes of execution, one
being the above - the MIPS simulator. In this mode, user programs can only
access memory associated with the simulated machine ( mainMemory ).
The other mode is one in which the kernel executes. This happens when Nachos
first starts up, or when a user program causes a hardware trap, e.g., system
call, page fault or an illegal instruction. In this mode, Nachos executes as
a normal UNIX process - the statements corresponding to Nachos source code are
executed and the memory accessed is that assigned to Nachos variables by UNIX.
Implementation
The global variable machine represents the Nachos machine. It is
created in system.cc as part of system
initialization along with other global variables in Nachos. It is an instance
of the class Machine which is defined in machine.h . The machine object describes the
following components:
Registers
The public variable registers is an array containing 40 registers.
Some special registers are PCReg, StackReg, NextPCReg and PrevPCReg. A list
of symbolic names for special registers is in
machine.h .
There are two ways to access the registers - directly through the variable
registers , and through the routines ReadRegister() and
WriteRegister() which are part of the Machine class definition.
Memory
The variable mainMemory represents Nachos physical memory. It is
byte-addressable and organized into 128-byte pages. Physical address x
can be accessed at machine->mainMemory[x] . The number of
pages in mainMemory is defined by the variable NumPhysPages in
machine.h .
Virtual Memory
Virtual memory is supported by either a linear page table or translation
lookaside buffer but not both. The choice of which is in effect is determined
by the variables tlb and pageTable . Both are part of
the Machine class. When executing instructions, machine verifies
that only one of these variables is set and uses whichever is defined (See the
constructor implementation of the Machine object in machine.cc).
The Nachos machine also supports interrupt-driven device I/O, timers and a
system dependent interface for invoking library functions in UNIX.
Interrupts are simulated by maintaining an event
queue together with a simulated clock. A detailed explanation of both and the
timer implementation in Nachos is here .
Devices
Nachos provides a terminal console device and a disk device. Both of these
are accessed through low-level primitives that initiate an I/O operation. The
operation itself is performed later, with an "operation complete" interrupt
notifying Nachos when the operation has finished.
The Console class, defined in
console.h , simulates the behavior of a character-oriented CRT device.
Data can be written to the device one character at a time using the
PutChar() routine. When a character has been output successfully, a
"transmit complete" interrupt is scheduled and a user-supplied handler (
writeHandler ) is
invoked. This handler should check if there are more characters waiting to be
output, invoking PutChar() again if appropriate.
Similarly, input characters arrive at the terminal one by one. When a new
character arrives, the console device generates an interrupt and the
user-supplied input interrupt service routine ( readHandler ) is
invoked to retrieve a character from the device. The GetChar()
routine makes the arrived character available to the user.
When a console device is created by the constructor of class Console
, the appropriate UNIX files (usually stdout and stdin for terminal I/O)
are opened and a timer event is scheduled. The routine CheckCharAvail()
is used to poll for data, every such timer event to call
readHandler whenever data is present.
To see how console I/O works in Nachos, try
running the console test program provided. Type nachos -c at the
prompt in the userprog directory. The ConsoleTest
routine (see progtest.cc ) is invoked
which simply echoes back whatever is typed on the terminal by the user.
The Disk Device
The Disk class, defined in disk.h
, simulates the behavior of a real disk. As with a
real disk, the OS initiates operations to read or write a specific sector, and
a later interrupt indicates when the operation has actually completed. The OS
can initiate new operations only when the device is idle. Delays in accessing
a disk are simulated by dynamically varying the time between initiation of an
I/O operation and its corresponding I/O complete interrupt.
The simulated disk contains NumTracks , each containing
SectorsPerTrack sectors. Individual sectors are SectorSize
in size. All of these variables are defined in disk.h . The ReadRequest() routine
reads data from a specified sector into a buffer. Remember that the actual
data is available only after the corresponding complete interrupt takes place
- ReadRequest() returns immediately, before the actual transfer
takes place. The WriteRequest() routine is similar except that is
writes data to a single sector.
The MIPS
simulator
The implementation of the simulator is split between three files -
machine.cc , mipssim.cc and translate.cc with their
corresponding header files. The Instruction class defines an
instruction represented in binary form. The routine Decode() is
provided to decode this binary representation. OneInstruction() ,
implemented in mipssim.cc) actually
executes the instruction. It fetches the current instruction address from the
PC register, fetches it from memory, decodes it and then executes it. Any
addresses referenced as part of this cycle are translated into physical
addresses using the Translate() routine in translate.cc .
The Run() routine , defined in
mipssim.cc , turns on the simulator, initiating the
fetch-decode-execute cycle. This routine should be called by a thread running
a user program only after it has properly initialized the machine registers.
It does three things:
- Invokes OneInstruction() to actually execute the instruction.
- Invokes the debugger if single step mode has been requested by the user.
- Increments a simulated clock after each instruction.
Other Details
Apart from the functionality and components described above, the machine directory contains some files
defining classes that maintain statistics about Nachos performance ( stats.h ) and also a
system dependent interface to make library function calls in UNIX ( sysdep.h ). The files network.h and
network.cc simulate a network interface. Details on that can be
found here .
Back to Top
Last modified on Thursday, 29-May-97 18:34:07 EDT