Instructions for Lab 6

Instruction Execution

We have now built a hardware machine but we still can't execute machine programs. We are going to write the code that performs the actions required by each machine instruction. The actions needed to execute each instruction are all encapsulated in an instruction visitor:
public class ExecIns implements InsVisitor {
...
}
Clearly the visitor needs access to the machine registers, memory, ALU, etc to perform its job. In other words, you will need instance variables for the machine components. The constructor takes the entire machine as an argument and initializes the instance variables:
  public ExecIns (MachineI m) {
  ...
  }
Our job now is to write each method in the InsVisitor interface so that it updates the machine's state to reflect the effect of executing the instruction. Let's look at some examples. First, a halt instruction is straightforward:
  public void visitHaltIns (HaltIns i) throws HaltE {
    throw new HaltE();
  }
A slightly more interesting example is the clear instruction. An instruction ``clear X'' stores a 0 in the location X. This can be easily implemented as follows:
  public void visitClearIns (ClearIns i) throws MachineE {
    Word w = new Data(0);
    mem.store(i.getAddress(), w);
  }
To implement the remaining operations, we will need to describe the meaning of the instructions in some detail: The realization of the methods should now be routine.

Tracing

Our design gives us added flexibility. Consider that we want to trace the execution of the program by printing every instruction that's about to be executed. We will print the information on the machine's output stream (called here outWriter) which we get can using the method getWriter() in the ioUnit class. We can achieve this without touching any previously written code by simply writing a new visitor that behaves like ExecIns above except that it also prints every instruction before executing it. Here are the first few lines of such a visitor:
public class ExecTraceIns extends ExecIns {

  public ExecTraceIns (MachineI m) {
    super(m);
  }

  public void visitHaltIns (HaltIns i) throws HaltE {
    outWriter.println(i.toString());
    super.visitHaltIns(i);
  }

  public void visitAddIns (AddIns i) throws MachineE { 
    outWriter.println(i.toString());
    super.visitAddIns(i);
  }

  public void visitClearIns (ClearIns i) throws MachineE {
    outWriter.println(i.toString());
    super.visitClearIns(i);
  }

  ...
}

A Little Debugger

We can further refine the previous visitor to print some debugging information about the machine status at every step. The first few lines of such a visitor follow:
public class DebugIns extends ExecTraceIns {

  public DebugIns (MachineI m) {
    super(m);
  }

  public void visitHaltIns (HaltIns i) throws HaltE {
    super.visitHaltIns(i);
  }

  public void visitAddIns (AddIns i) throws MachineE { 
    super.visitAddIns(i);
    printStatus();
  }

  public void visitClearIns (ClearIns i) throws MachineE {
    super.visitClearIns(i);
    printStatus();
  }

  ...

  // assuming the visitor has instance variables proc and alu
  private void printStatus () {
    outWriter.print("\tPC=" + proc.fetchPC());
    outWriter.print("\tACC=" + proc.fetchACC());
    outWriter.print("\tGT/EQ/LT=" + alu.fetchGT() + "/" + 
		       alu.fetchEQ() + "/" + alu.fetchLT());
    outWriter.print("\n\n");
    outWriter.flush();
  }

To Do

Finish the implementation of ExecIns, ExecTraceIns, and DebugIns above. Here is a file to test your code.


Visited times since December 15, 1997 (or the last crash).

sabry@cs.uoregon.edu