#### Programming Task 3: Simulation in Software

Starter code: [download](https://canvas.flinders.edu.au/courses/21305/files/3213069?wrap=1 "new prac3 starter download.zip")[Download download](https://canvas.flinders.edu.au/courses/21305/files/3213069/download?download_frd=1)

In this task, you will build your own computer! not a real one, but a simulated one, according to the specification below.

The **Alphatron-001** is a very simple computer, with a limited set of machine code instructions, and a small amount of free memory in which it stores both its machine code program and the data that the program operates on. (The Alphatron can only keep one program loaded in memory at a time, so multitasking is beyond its reach for now.)

The Alphatron's memory consists of 100 words. Each word can store a value from 0 to 9999. The value of a word can be conveniently represented as a 4-digit number, e.g. 9876, 0012, 0902 etc. Values can be retrieved from memory by using the memory location as an index, e.g. memory[3] contains the value stored in the 4th location in memory (counting starts from 0).

The Alphatron has 2 registers with which it performs its computations:

- a general-purpose register known as the _accumulator_
- a _program counter_, which stores the memory location of the next command to be executed

Alphatron programs perform calculations by transferring values around between the accumulator and any open locations in memory (i.e. locations that are not in use by the program). Various arithmetic operations (adding, subtracting) can be performed on these values, and the Alphatron can input numbers from the keyboard, and produce output by printing numbers to the screen.

The Alphatron follows a fetch-decode-execute cycle for running a program stored in memory:

- Fetch: The computer retrieves from memory the value of the word that is stored at the location indicated by the program counter. 
- Decode: It attempts to interpret the value as a valid machine code instruction.
- Execute: If decoding is successful, it attempts to perform the instruction, and increments the program counter (unless the instruction has explicitly modified the program counter already).

The Alphatron has a machine code language with just 13 different commands. These are described in the table below.

When a word has been fetched from memory, the decoding step breaks it up into two equal parts. The part represented by the **first two digits** of the word is the operation code or **opcode**. This is a number from 00 to 99 representing the particular instruction. Only the 13 opcodes as shown in the table are valid. The **last two digits** represent the **operand**, i.e. the value on which the instruction will be carried out.

Example: if the current location in memory contains the word 2609, this is broken up into: opcode = 26, and operand = 09. Because 26 corresponds to the SUB instruction, the purpose of the instruction will be to modify the value that is currently in the accumulator, by subtracting the value stored in location 9 in memory. So if the accumulator contains the value 7, and memory location 0009 contains the value 12, then the result of the command is that the accumulator will contain the value -5.

Note that the accumulator can contain negative values; however, memory locations can store only zero or a positive integer.

|   |   |   |
|---|---|---|
|**Mnemonic**|**Opcode**|**Meaning**|
|OUTPUT|10|Print a value to the screen. If _operand_ = 0, print the value in the accumulator. Otherwise, print the value stored in memory location _operand_.|
|INPUT|11|Read a value from standard input (the keyboard by default). Each value should be provided on a single line (so press Enter if typing in). If _operand_ = 0, store the value in the accumulator. Otherwise, store the value in memory location _operand_.|
|INC|20|Increment the accumulator (add 1 to its value).|
|DEC|21|Decrement the accumulator (subtract 1 from its value).|
|ADD|25|Add the value stored in memory location _operand_ to the value stored in the accumulator.|
|SUB|26|Subtract the value stored in memory location _operand_ from the value stored in the accumulator.|
|LOAD|30|Load the value stored in memory location _operand_ into the accumulator.|
|STORE|31|Store the value stored in the accumulator into memory location _operand_.|
|JUMP|40|Jump to memory location _operand_ (i.e. set the program counter to _operand_), and continue.|
|JUMPPOS|41|Jump to memory location _operand_ if the accumulator value is positive (greater than zero).|
|JUMPZERO|42|Jump to memory location _operand_ if the accumulator value is equal to zero.|
|HALT|99|Halt program execution (operand is ignored.)|
|SKIP|00|Do nothing (operand is ignored.)|

#### **TASK**

Your task is to implement a simulation of the Alphatron-001. The simulated computer will read a program from cin, and will execute it when the special word RUN is entered. This means that you can interactively type in a Alphatron program to your simulation program, and enter RUN to run the program you have entered.

All Alphatron programs consist of a series of 4-digit numbers, one number per line, and have the file extension .alp. A few example programs have been provided (see below).

You will complete the task by implementing Alphatron.cpp, following the specification given in Alphatron.h. (The implementation of the read_program() method has already been provided.) To test your program, run the main method in main.cpp, and enter a program, followed by RUN.

You should not modify main.cpp for this task. You may need to add methods to Alphatron.h and Alphatron.cpp.

You are also given an implementation of the method memory_dump(), which prints out a dump of the current values in memory. You are not required to use this method, but it may be useful for you for debugging purposes.

(NOTE: Because of a small design error, and also in order to facilitate programming by human programmers, the Alphatron cannot access a program statement located at **memory location 0,** and cannot store data there either. Hence, all Alphatron machine code programs start running at the instruction stored in the 2nd location in memory, i.e. at **memory location 1**.)

Of course, it's tedious to type in a whole program line by line every time you test. A more convenient way is to store your program in a text file. Then you can either copy and paste the program from the file into the Alphatron as input, or you can redirect the input into your Alphatron program to get cin from the file instead of the keyboard, as we've done in previous programming tasks. You can even, if you really want to automate everything, add the word RUN to the end of the file, as well as any input values!

The following example programs have been provided:

The program countto4.alp prints the value of the accumulator, then repeatedly increments the accumulator and prints it out, 4 times in succession. The result is that it prints   
0  
1  
2  
3  
4

The program inputplus2.alp inputs a number from the keyboard into the accumulator, increments it twice (in the accumulator), and then prints it out. The result is that it prints out the input number + 2.

The program sum.alp reads in two numbers from the keyboard, and prints out their sum.

The program maxof2.alp reads in two numbers from the keyboard. If the first one is larger, it prints 1; if the second one is larger, it prints 2, and if they are equal, it prints 0.

**Level 1**

Complete the run_program() method in order to implement the fetch-decode-execute cycle of the Alphatron. Get the following commands to work: INPUT, OUTPUT and INC. These should allow you to run example programs countto4 and inputplus2.

**Level 2**

Implement the remaining opcodes. This will allow you to run sum and maxof2.

starter files:
Alphattron.cpp
// Created by richa on 30/03/2024.
//
//

#include "Alphatron.h"

#include <iostream>
#include <iomanip>
using namespace std;

void Alphatron::memory_dump() {
    char prev = std::cout.fill('0');
    for (int row = 0; row < 10; row++) {
        for (int col = 0; col < 9; col++) {
            std::cout << std::setw(4) << memory[10 * row + col] << " ";
        }
        std::cout << std::setw(4) << memory[10 * row + 9] << std::endl;
    }
    std::cout.fill(prev);
}





void Alphatron::read_program() {
    for (int i = 0; i < 100; i++) memory[i]=0;

    std::string line;
    int memcounter = 1;
    while (std::getline(std::cin, line) && line.find("RUN") != 0) {
        int command = std::stoi(line);
        memory[memcounter++] = command;
    }
//    memory_dump();
}

Alphatron.h:
//
// Created by richa on 21/03/2024.
//

#ifndef NEW_PRAC3_ZELOTRON_H
#define NEW_PRAC3_ZELOTRON_H

#include <string>

class Alphatron {
public:
    void memory_dump();
    void read_program();
    void run_program();

private:
    // INSTRUCTION SET OPCODES
    static const int OUTPUT = 10;
    static const int INPUT = 11;
    static const int INC = 20;
    static const int DEC = 21;
    static const int ADD = 25;
    static const int SUB = 26;
    static const int LOAD = 30;
    static const int STORE = 31;
    static const int JUMP = 40;
    static const int JUMPPOS = 41;
    static const int JUMPZERO = 42;
    static const int HALT = 99;
    static const int SKIP = 0;  // 00 - not really used

    // The following function may be useful for debugging
    static std::string opcode_to_mnemonic(int opcode) {
        switch(opcode){
            case OUTPUT: return "OUTPUT"; break;
            case INPUT: return "INPUT"; break;
            case INC: return "INC"; break;
            case DEC: return "DEC"; break;
            case ADD: return "ADD"; break;
            case SUB: return "SUB"; break;
            case LOAD: return "LOAD"; break;
            case STORE: return "STORE"; break;
            case JUMP: return "JUMP"; break;
            case JUMPPOS: return "JUMPPOS"; break;
            case JUMPZERO: return "JUMPZERO"; break;
            case HALT: return "HALT"; break;
            case SKIP: return "SKIP"; break;
            default: return "INVALID OPCODE";
        }
    }

    // REGISTERS
    int accumulator = 0;    // General-purpose computer register
    int program_counter = 0;// the line in the program to execute next

    // INTERNAL STORAGE IN THE COMPUTER  (how should these arrays be initialised?)
    int memory[100];          // input memory

};


#endif //NEW_PRAC3_ZELOTRON_H

main.cpp:
#include "Alphatron.h"
#include <cstring>

int main(int argc, char *argv[]) {
    Alphatron a;
    a.read_program();
    a.run_program();
    return 0;
}


countto4.alp:
1000
2000
1000
2000
1000
2000
1000
2000
1000
9900
RUN

intputplus2.alp:
1100 INPUT into ACC
2000 INC
2000 INC
1000 OUTPUT ACC
RUN



sum.alp:  
1100 INPUT into ACC  
1110 INPUT into mem10  
2510 ADD mem10 to ACC  
1000 OUTPUT ACC  
RUN

maxof2.alp:  
1120 INPUT into m20  
1121 INPUT into m21  
3020 LOAD m20 into ACC  
2621 SUB m21 from ACC  
4109 JUMPPOS to 9  
4211 JUMPZERO to 11  
1013 OUTPUT "2" - 2 is bigger  
9900 HALT  
1014 OUTPUT "1" - 1 is bigger  
9900 HALT  
1015 OUTPUT "0" - they are equal  
9900 HALT  
0002  
0001  
0000  
RUN


----- 

for the tasks above level 1 and 2,
here's the run_program that i made:
  
void Alphatron::run_program() {  
    program_counter = 1;  
    accumulator = 0;  
    while (true) {  
  
        int instruction = memory[program_counter];  
        int opcode = instruction / 100;  
        int operand = instruction % 100;  
  
        switch (opcode) {  
            case INPUT: {  
                int value;  
                cin >> value;  
                if (operand == 0) {  
                    accumulator = value;  
                } else {  
                    memory[operand] = value;  
                }  
                break;  
            }  
            case OUTPUT: {  
                if (operand == 0) {  
                    cout << accumulator << endl;  
                } else {  
                    cout << memory[operand] << endl;  
                }  
                break;  
            }  
            case INC: {  
                accumulator++;  
                break;  
            }  
            case HALT: {  
                return;  
            }  
            case DEC: {  
                accumulator--;  
                break;  
            }  
            case ADD: {  
                accumulator += memory[operand];  
                break;  
            }  
            case SUB: {  
                accumulator -= memory[operand];  
                break;  
            }  
            case LOAD: {  
                accumulator = memory[operand];  
                break;  
            }  
            case STORE: {  
                  memory[operand] = accumulator;  
                break;  
            }  
            case JUMP: {  
                program_counter = operand;  
                continue;  
            }  
            case JUMPPOS: {  
                if (accumulator > 0) {  
                    program_counter = operand;  
               continue;  
                }  
                break;  
            }  
            case JUMPZERO: {  
                if (accumulator == 0) {  
                    program_counter = operand;  
                    continue;  
                }  
                break;  
            }  
            case SKIP: {  
                break;  
            }  
  
            default: {  
                cerr << "Invalid opcode: " << opcode << endl;  
                return;  
            }  
  
        }  
        program_counter++;  
    }



you shouldn't change any of the original methods given as they are pre-made and bug proof, 
do level 3:
Level 3
(For levels 3 and 4, your task is to write programs in the Alphatron machine language. Your submissions will be two .alp programs, called loop.alp and prime.alp. Your files should NOT contain the word RUN, or any inputs!!!)
Write the Alphatron program loop.alp, a program which reads in two numbers X and Y. The program needs to loop X times, printing Y each time.
I.e. if the input is 
4
3
then the output is
3 
3
3
3