Introduction

This is general documentation for my MIPS emulator written in Python.

Goals

  • Cross-platform
  • Minimal binary size
  • Make debugging the MIPS assembly language easier than what QtSpim offers
  • Minimal dependencies

Limitations

  • A minimal emulator for the MIPS assembly language that uses the University of Saskatchewan's CMPT 215, class as a baseline for what features are supported

Installation

Prerequisites

  • Have Python 3.10 or higher installed
  • Have pip3 installed

Installing dependencies

while you are in the root of your project run:
pip3 install -r requirements.txt

NOTE: on some installations it is simply pip, while others use pip3

Currently there are only three dependencies:

  • pyQt5
  • termcolor
  • toml

This project could probably do without termcolor but, for now, it is fine as it is.

Usage

Running the emulator

Now you can simply run the main.py file with the path to an assembly file as an argument
python3 main.py <path_to_assembly_file>

or alterantively you can complile the python files into a c executable binary, this is useful if you want the emulator to be available as a shell command by moving it to ~/.local/bin or any other executable path

Compiling and running the emulator

To compile the emulator, first enssure that you can run the make command then simply run,
make build

this will compile a binary in the dist/ subdiretory of the project

to run the emulator simply ./dist/PyMIPS <path_to_assembly_file>

Configuration file

The Configuration file is pymips.toml

Features

keyvaluesdescription
register_basebin dec hexthe numerical base all registers display in, under the hood it's still decimal
memory_mappedtrue falseenable or disable memory mapped registers
end_of_instructiontrue falseenable or disable end of instruction

Runner

keyvaluesdescription
entry_pointlabel namethe label which executes at the start of the program
file_to_runpaththe path to the assembly file to run

Debugger

keyvaluesdescription
breakpointslist of line number(s)a list of line numbers to break at
watchpointslist of expression(s)a list of expressions to watch

Architecture

main.py

This is the main entry point for the entire program

Taking in arguments

We take in two inputs using the stdlib's argparse module, the first argument is a path to the assembly file that you want to run, this does not check for the validity of the .asm or .s file, which is you could conceivably load a python file or a simple text file, and only the pre-processor might throw an error, if not then the interpreter will further downstream. The --no-gui arg can be passed to disable the GUI and just run the Interpreter.

Setting things up

Setup, the IDE and colour palette (dark theme). We also set up an exception hook, this exception hook allows us to catch our custom defined exceptions in exceptions.py and catch them to act appropriately, like catching an exit code or RecursionError.

This however still allows us to continue on general Python exceptions, which are handled by PyQt.

exceptions.py

There is a general base/ parent class for all custom exceptions called InterpreterException which inherits from the in-built Exception class. This class is an abstract class cannot be instantiated on its own, you need to instantiate one of it's many subclasses.

The InterpreterException class takes in a message that will be displayed to the user upon encountering the exception, it can also take in three optional keyword arguments: label_that_crashed, instruction_that_crashed and exit_code.

Interpreter Exceptions

NameDescriptionExample
InterpreterSyntaxErrorwhen a syntax error is encountered in the assembly codean empty label or out of place label
InterpreterProcessErrorwhen functions are called out of the expected orderthe Interpreter is run before the labels and memory is mapped
InterpreterRegisterErrorwhen an invalid register is usedsome value is set to register $t55
InterpreterControlFlowErrorwhen an unexpected control flow event occursthe code has reached someplace it shouldn't, processing a jump instruction from the Multiplexer
InterpreterValueError
InterpreterConversionErroran invalid conversion took place
InterpreterRuntimeErrora general runtime exception
InterpreterInstructionErroran instruction is encountered that is not validan invalid instruction xyz is encountered