Programming Assignment 4 (RAM Model of Computing)

Random Access Machine (RAM) is a theoretical model of computing that consists of a very basic set of operations that operate on a set of "registers" to describe effective computability. In this assignment, we will implement a Python implementation of RAM. The RAM model consists of an indefinite number of registers, R1, R2, ..., each capable of storing a natural number. The instruction set consists of the following 7 instructions:
  1. INC Ri, increment the contents of register Ri by 1.
  2. DEC Ri, decrement the contents of register Ri by 1; keep Ri unchanged if Ri is 0.
  3. CLR Ri, set the contents of register Ri to 0.
  4. MOV Ri Rj, replace the contents of register Ri by the contents of Rj, leaving Rj the same.
  5. JMP N, next instruction to execute is set to the one with label N.
  6. Rj JMP N, if contents of Rj is 0 the next instruction to execute is set to the one with label N, otherwise the instruction that follows executes as usual.
  7. CONTINUE, do nothing.
Any of the above instructions, when used in a RAM program, may be preceded by a label Ni:, where i is a natural number. A RAM program consists of two parts: the first part assigns values to registers and the second part is a finite sequence of instructions, usually ending with the CONTINUE instruction. The RAM program may contain comment lines that begin with a #.

It is possible to use a register (in the second part of the program) without assigning it a value in the first part of the program. Such registers should be assumed to have a value of 0.

An example of a RAM program is shown below (p1.ram):

# Program to add two numbers
# inputs are in r1 and r2
# output, as always, is in r1
#
# initialize input registers
r1 = 9
R2 = 3
#
# begin program
n0: R2 JMP N1
    INC R1
    DEC R2
    JMP N0
N1: CONTINUE
The execution of a RAM program starts with the assignment of values to registers and then executing the instructions in the second part one at a time in sequence. The sequence may be altered by one of the the JMP instructions. The RAM program terminates when it executes the CONTINUE instruction.

Write a Python program that executes a RAM program stored in a file whose name is provided as command line input. An optional -d command line parameter may be provided to execute the RAM program in debug mode in which each instruction that is executed is displayed. Two sample runs are shown below:

Mac-mini:ram raj$ python3 RAM.py p1.ram
Input:
R1 ==> 9
R2 ==> 3

Output:
R1 = 12

Mac-mini:ram raj$ python3 RAM.py -d p1.ram
Input:
R1 ==> 9
R2 ==> 3

Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: 	INC R1
Executing: 	DEC R2
Executing: 	JMP N0
Executing: N0:	R2 JMP N1
Executing: N1:	CONTINUE

Output:
R1 = 12
Mac-mini:ram raj$ 

Dictionaries to the rescue!!

To solve this assignment, we will resort to the dictionary data structure of Python. In particular, we will record the values of registers, the instruction number for labels, and inner details of individual instructions in dictionaries. Here are the three variables that you would have to construct and manipulate in the program:
registers = {'R1': 9, 'R2': 3}

code = [ {'labeldef': 'N0', 'opcode': 'CJMP', 'register1': 'R2', 'jmplabel': 'N1'}, 
         {'opcode': 'INC', 'register1': 'R1'}, 
         {'opcode': 'DEC', 'register1': 'R2'}, 
         {'opcode': 'UJMP', 'jmplabel': 'N0'}, 
         {'labeldef': 'N1', 'opcode': 'CONTINUE'}
       ]

labels = {'N0': 0, 'N1': 4}

Few RAM programs for your testing purposes: p1.ram, p2.ram, p3.ram, p4.ram.