CPSC 220, Fall 2018
Lab 3: Writing a Larc Simulator

The assignment for this lab is to write a Java program that simulates the Larc computer. The program will be a "functional simulator." That is, it makes no attempt to simulate Larc on a hardware level. Instead, it acts an an interpretor for Larc machine language programs: It imitates Larc's fetch-and-execute cycle by carrying out the operation indicated by each machine language instruction, without trying to perform that operation in the same way that Larc would.

There are many ways to design the simulation program. You are not required to use any particular design. But whatever design you choose, it should be well-organized and should follow all the usual Java programming style rules. Your program should, of course, be beautiful and a pleasure to read.

Your simulator program is due in two weeks, on Thursday, September 27. Turn it in to your homework folder in /classes/cs220/homework. If your simulater is in one file, LarcSim.java, you can just copy it into your homework folder. If your solutions uses several files, you should place them inside a folder named lab3 inside your homework folder. And remember that Lab 2 is due next week!

Some Setup

As a starting point, you can use the file LarcSim.java. This program starter file has a main() routine that reads a Larc machine language program file and converts it into an array of short. Each short value in the array is one instruction in the machine language program. You will not need to make any changes to main(). You can find a copy of LarcSim.java in the folder /classes/cs220. There is also a copy of TextIO.java in that folder, in case you want to use it for input.

There are two subroutine stubs in LarcSim.java. One, loadProgram(), just loads the program from the array into the the Larc computer's memory; this routine will be very short. The other subroutine that you need to complete is execute(), which simulates the execution of the machine language program that has been loaded into memory.

When LarcSim is run, it needs a machine language program to execute. If you run LarcSim with no command line argument, it will put up a file chooser dialog box where you can select the input file. This will work for example, if you run the program from inside Eclipse. To give the name of the program on the command line instead, run the program with a command of the form

java  LarcSim  program.out

where program.out is the name of the file that contains the machine language program. The directory larcML, which you can find in /classes/cs220, contains some sample machine language programs that you can use to try out your simulator. You could also use the programs that you write for Lab 2. The machine language program does not have to be in the same directory as your simulator; you can use a path to the file. For example, to run the sample program calc.out directly from the larcML directory on the server, you can say

java  LarcSim  /classes/cs220/larcML/calc.out

The Simulator

As we discussed in class, your program will need variables to represent at least the following: the 16 registers, the 65536-location memory, and the program counter. At the core of your simulation is a loop that imitates the fetch-and-execute cycle. In this loop, you fetch an instruction from memory, increment the program counter, and simulate the execution of the instruction.

There are 16 types of instruction, determined by the opcode — the four high-order bits of the instruction. If the opcode is syscall (15, or 1111 in binary), you will have to simulate a system trap. For the purposes of this simulation, you can use standard Java I/O (System.out.println and either TextIO or Scanner) to simulate the four I/O traps.

In all of this, you will have to carefully follow the instruction set architecture described in Chapter 3 of the Larc manual (which was handed out in class). In particular, to agree with that specification, you should initialize the stack pointer, register number 10, to 0xFC00.

Error Conditions

In addition to simulating the execution of legal machine language programs, your simulator should detect certain error conditions. When such an error is encountered, you should halt the simulation with an error message such as, "System halted by error," with a description of the error. In particular, your simulator program should not crash when an error occurs; it should report the error and exit gracefully. Error conditions that you are required detect are:

The Larc manual specifies two other kinds of errors that are optional in your implementation: accessing memory location 0xFC00 or higher, and trying to use register number 14 or register number 15.

Note that when implementing the syscall for reading an integer from the user, if the user's input is not legal, the simulator does not crash or report an error. It just returns the integer zero in register one.

Remember that while register 0 must always hold the value 0, it is not an error to try to store a value into register 0. However, doing so will have no effect on the value stored in the register.

Suggestions

You might consider writing classes to represent memory, the set of registers, and machine language instructions. You can write them as static nested classes or in separate files. Of course, it is also possible to write the program using only subroutines.

It is natural for the register and memory arrays in your program to be arrays of short, but Java makes it difficult to work with short values, since it does arithmetic computations using ints, even when the operands are of type short. In my solution, my approach was to use arrays of short but to have methods for putting and getting values from the array that work with values of type int. Here, for example, is my Memory class, which you can use in your program if you like.

private static class Memory {
    short[] memory = new short[1<<16];
    void put(int location, int value) {
        location = location & 0xFFFF;
        if (location >= 0xFC00) {
            throw new RuntimeException(
                    "Illegal access to reserved memory location " 
                    + location + " in user mode.");
        }
        memory[location] = (short)value;
    }
    int get(int location) {
        location = location & 0xFFFF;
        if (location >= 0xFC00) {
            throw new RuntimeException(
                    "Illegal access to reserved memory location " 
                    + location + " in user mode.");
        }
        return memory[location];
    }
}

Doing sign extension for the LIMM and SIMM values is tricky, since Java won't do it automatically. Given a machine language instruction, ins, of type int, here is how my program gets sign-extended LIMM and SIMM values from the instruction, where limm and simm are of type int:

limm = (byte)ins;
simm = (ins << 28) >> 28;

Implementing the logical shift right instruction is also tricky, since when you shift a 16-bit value, zeros should be inserted at bit position 15, but Java will apply the shift to 32-bit ints and will insert the zeros at bit position 31. You can fix this by making sure that all of the bits beyound bit postion 15 are zero before you shift right. For example,

shifted = (b & 0xFFFF) >> c;