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

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 Device

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:

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