Lab 4 -- The Machine

We will now build an abstraction of an entire hardware machine using the components already defined, and a couple of new components.

Interfaces

The specifications for the machine and the new components are:
public interface MachineI {
  MemoryI getMem ();
  ProcessorI getProc ();
  ioUnitI getIO ();

  /**
   * Tests each component of the machine. For example, attempts to
   * store a number in a known memory location, and then read that
   * location, etc. 
   */
  void selfTest ();
}

//------------------------------------------

public interface ioUnitI {
  /**
   * The default underlying byte-oriented input stream.
   */
  java.io.InputStream DEFAULT_ISTREAM = System.in;

  /**
   * The default underlying byte-oriented output stream.
   */
  java.io.OutputStream DEFAULT_OSTREAM = System.out;

  java.io.PrintWriter getWriter ();
  java.io.StreamTokenizer getReader ();

  /**
   * A call to readData reads one integer from the input stream. The call
   * will block until there is something to read.
   * @exception ioE If the input cannot be parsed as a number.
   */
  Word readData () throws ioE;

  void writeData (Word w); 
}

//------------------------------------------

public interface ProcessorI {
  ALUI getALU ();

  Word fetchPC ();
  Word fetchACC ();
  Instruction fetchIR ();

  void storePC (Word newpc);
  void storeACC (Word newacc);
  void storeIR (Instruction newir);
}


To do:

Using the following guidelines, write classes Machine, Processor, and ioUnit that implement the appropriate interfaces. Write any additional classes that you need to make your code compile and run properly:

The CPU

The central processing unit is usually called the CPU. The CPU is the core of the machine; it contains the ALU as well as a variety of registers. In our machine, the registers are:

The IO Unit

The I/O unit communicates with the outside world using streams. Intuitively streams are unbounded sequences of values. The java.io package supports streams extensively.

Underlying any Java stream is a stream of bytes. Such byte streams called InputStream and OutputStream are low-level and rarely used directly in applications. For our purposes, we would like to view the input stream as carrying a sequence of numbers and we would also like to write arbitrary values to the output stream. We can achieve this with a bit of work.

First, we move from byte streams to character streams using the classes InputStreamReader and OutputStreamWriter. The read and write operations on these streams handle only one character at a time (which maycorrespond to more than one byte on the underlying byte stream). For efficiency, these streams are usually wrapped using a BufferedReader and BufferedWriter.

Next, we can automatically convert a stream of characters to a stream of "tokens" where tokens represent entities such as strings, numbers, etc. This is achieved using the rather flexible class StreamTokenizer. The behavior of this class can be parameterized by a number of flags so you will need to consult the API before using it. Symmetrically, we can write arbitrary Java objects to a character stream by first wrapping it in a PrintWriter stream.

All inputs to our machine are numbers that are converted to integers and stored in the memory. A call to the method readData may throw an exception if the input cannot be parsed as a number. More importantly, the call will block waiting for input if there are no characters to read from the input stream. This is consistent with the intuitive behavior of programs: if a program is requesting an input value, then it will wait (block) until that value is supplied.


Visited times since March 23, 1999 (or the last crash).