Simpletron
Simpletron is a software based computer simulator which is capable of executing instructions written in Simpletron Machine Language (SML) Simpletron contains an accumulator – a special register in which information is put before it uses in calculations and or examined in various ways It has memory of size 100 words (can be extended) each word can be referenced by their location 00, 01, 02, …., 99 Word is a signed four digit decimal number such as +3364, -1293, +0007, -0001 SML instructions occupies one word of the Simpletron’s Memory SML instruction will always be positive SML data can be positive or negative The first two digits of the SML instruction are the operation code The last two digits of the SML instruction are the operand (i.e memory location of the operand).
SML Operation
Input/Output Operations
Load/Store Operations
Arithmetic Operations
Transfer of Control Operations
SML Operation Codes
Input/Output Operations:
10 - Read a word from the terminal into specific location in memory
Example: +1080 – Read w word from the terminal into the memory with location 80
11 -Write a word from a specific location in memory to the terminal.
Example: +3075 – write the contents of the word with location 75 to the terminal
Load/Store Operations:
20 – Load a word from the specific location in memory into the accumulator Example: +2074 – Load the contents of the word with location 74 into the accumulator
21 – Store a word from the accumulator into a specific location in memory Example: +2165 – Store the contents of the accumulator into the word with location 65
Arithmetic Operations:
30 - Add a word in specific location in memory to the word in the Accumulator (leave result in Accumulator) Example: +3070 – Add contents of the word with location 70 to the Accumulator and the result is kept with Accumulator
31 – Subtract a word in specific location in memory from the word in the Accumulator (leave result in Accumulator) Example: +3160 – Subtract the contents of the word with location 60 from the Accumulator and the result is kept with Accumulator
32 – Divide a word in specific location in memory with the contents of the Accumulator (leave result in Accumulator) Example: +3280 – Divide the contents of the word in location 80 with the accumulator and the result is kept with Accumulator
33 – Multiply a word from a specific location in memory by the contents of the accumulator (leave result in Accumulator) Example: +3390 – Multiply the contents of the word in location 90 with the contents of the accumulator and the result is kept with Accumulator
Transfer of Control Operations:
40 – Branch to a specific location in memory Example: +4020 – branch to location 20 (i.e. next instruction to execute is at location 20)
41 – Branch to a specific location in memory if the accumulator is negative Example: +4115 – Branch to instruction at location 15 if the accumulator is negative
42 – Branch to a specific location in memory if the accumulator is zero Example: +4225 – Branch to instruction at location 25 if the accumulator is zero
43 – Halt (program has completed its task) Example: +4300
Example SML Program
Addition of Two Numbers: C = A + B
00 +1007 (Read A)
01 +1008 (Read B)
02 +2007 (Load A)
03 +3008 (Add B)
04 +2109 (Store C)
05 +1109 (write C)
06 +4300 (Halt)
07 +0000 (Variable A)
08 +0000 (Variable B)
09 +0000 (Variable C)
Maximum of Two Numbers: C = Max(A, B)
00 +1009 (Read A)
01 +1010 (Read B)
02 +2009 (Load A)
03 +3110 (Subtract B)
04 +4107 (Branch negative to 07)
05 +1109 (Write A)
06 +4300 (Halt)
07 +1110 (Write B)
08 +4300 (Halt)
09 +0000 (Variable A)
10 +0000 (Variable B)
Product of two numbers
00 +1099 (Read)
01 +1098 (Read)
02 +2099 (Load)
03 +3398 (Multiply)
04 +2150 (Store)
05 +1150 (Write)
06 +1199 (Write)
07 +1198 (Write)
08 +4300 (Halt)
09 -99999 (Sentinel)
How Simpletron works?
Once all the SML instructions are syntactically correct, instructions are placed in the Simpletron memory array starting from 00.
Simpletron starts executing the instructions one by one. The Instruction counter will incremented by one (unless the current instruction is a branch instruction)
Instruction cane fetched using:
instructionRegister = memory[instructionCounter];
operationCode and operand can be extracted as below
operationCode = instructionRegister / 100;
operand = instructionRegister % 100;
Read - scanf(“%d”, &memory[operand]);
Write – printf(“%d”, memory[operand]);
Load – accumulator = memory[operand];
Store – memory[operand] = accumulator;
Add – accumulator += memory[operand];
Subtract - accumulator -= memory[operand];
Divide - accumulator = memory[operand] / accumulator;
Multiply – accumulator *= memory[operand];
Branch – instructionCounter = operand
Branch if negative if(accumulator < 0)
{
instructionCounter = operand;
}
Branch if zero if(accumulator == 0)
{
instructionCounter = operand;
}
Simpletron Error checking
SML program should be syntactically correct During execution phase Simpletron should check for various kinds of errors like
- Divide by zero
- Invalid operation code
- Accumulator overflow
#include <iostream> #include <iomanip> using namespace std; const int SIZE = 100; const int MAX_WORD = 9999, MIN_WORD = -9999; const long SENTITEL = -99999; enum Commands { READ = 10,WRITE , LOAD = 20, STORE, ADD = 30, SUBTRACT , DIVIDE , MULTIPLY, BRANCH = 40, BRANCHNEG, BRANCHZERO, HALT }; void load(int * const); void execute(int * const, int * const, int * const, int * const, int * const, int * const); void dump(const int *const, int, int, int, int, int); bool validWord(int); int main() { int memory[SIZE] = { 0 }; int accumulator = 0, instuctionCounter = 0, instructionRegister = 0, opCode = 0, operand = 0; load(memory); execute(memory, &accumulator,&instuctionCounter,&instructionRegister,&opCode,&operand); dump(memory, accumulator, instuctionCounter, instructionRegister, opCode, operand); system("pause"); //cin.get(); return 0; } void load(int *const loadMemory) { long instruction; int i = 0; cout << "*** Welcome to Simpletron ***\n" << "*** Please Enter your Program one instrution ***\n" << "*** (or Data word) at a time. I will type the ***\n" << "*** location number and question mark (?). ***\n" << "*** You then type the word for that location. ***\n" << "*** Type the senitel -99999 to stop entering ***\n" << "*** your Program ***\n" << "00 ? "; cin >> instruction; while (instruction != SENTITEL) { if (!validWord(instruction)) cout << "Number Out of range. Please enter a valid Number "; else loadMemory[i++] = instruction; //function setfill sets the padding character for unused filled width cout << setw(2) << setfill('0') << i << " ? "; cin >> instruction; } } bool validWord(int word) { return word >= MIN_WORD && word <= MAX_WORD; } void execute(int * const memory, int * const acPtr, int * const icPtr, int * const irPtr, int * const opCodePtr, int * const opPtr) { bool fatal = false; int temp; const char *messages[] = { "Accumulatoroverflow ***", "Attempt to devide by Zero ***", "Invalid op Code Detected ***"}, *termString = "\n*** Simpletron execution abnormally Terminated ***", *fatalString = "\n*** FATAL ERROR:"; cout << "\n ****START SIMPLETRON EXECUTION***********\n\n"; do { *irPtr = memory[*icPtr]; *opCodePtr = *irPtr / 100; *opPtr = *irPtr % 100; switch (*opCodePtr) { case READ: cout << "Enter an integer: "; cin >> temp; while (!validWord(temp)) { cout << "Number out of Range.Please Enter again: "; cin >> temp; } memory[*opPtr] = temp; ++(*icPtr); break; case WRITE: cout << "Content of " << setw(2) << setfill('0') << *opPtr << ": " << memory[*opPtr] << '\n'; ++(*icPtr); break; case LOAD: *acPtr = memory[*opPtr]; ++(*icPtr); break; case STORE: memory[*opPtr] = *acPtr; ++(*icPtr); break; case ADD: temp = *acPtr + memory[*opPtr]; if (!validWord(temp)) { cout << fatalString << messages[0] << termString << '\n'; fatal = true; } else { *acPtr = temp; ++(*icPtr); } break; case SUBTRACT: temp = *acPtr - memory[*opPtr]; if (!validWord(temp)) { cout << fatalString << messages[0] << termString << '\n'; fatal = true; } else { *acPtr = temp; ++(*icPtr); } break; case DIVIDE: if (memory[*opPtr] == 0) { cout << fatalString << messages[1] << termString << '\n'; fatal = true; } else { *acPtr = temp; ++(*icPtr); } break; case MULTIPLY: temp = *acPtr * memory[*opPtr]; if (!validWord(temp)) { cout << fatalString << messages[0] << termString << '\n'; fatal = true; } else { *acPtr = temp; ++(*icPtr); } break; case BRANCH: *icPtr = *opPtr; break; case BRANCHNEG: *acPtr < 0 ? *icPtr = *opPtr : ++(*icPtr); break; case BRANCHZERO: *acPtr == 0 ? *icPtr = *opPtr : ++(*icPtr); break; case HALT: cout << "***************SIMPLETRON EXECUTION TERMINATED**************\n"; break; default: cout << fatalString << messages[2] << termString << '\n'; fatal = true; break; } } while (*opCodePtr != HALT && !fatal); cout << "\n*********** END SIMPLETRON EXECTION****************\n"; } void dump(const int * const memory, int accumulator, int instructionCounter, int instructionRegister, int operationalCode, int operand) { void output(const char *const, int, int, bool);//prototype cout << "\n REGISTERS:\n"; output("accumulator", 5, accumulator, true); output("instructionCounter", 2, instructionCounter, false); output("instructionRegister", 5, instructionRegister, true); output("operationalCode", 2, operationalCode, false); output("operand", 2, operand, false); cout << "\nMEMORY :\n"; int i = 0; cout << setfill(' ') << setw(3)<<' '; //print header for (; i <= 9; ++i) { cout << setw(5) << i << ' '; } for (i = 0; i < SIZE; ++i) { if (i % 10 == 0) { cout << '\n' << setw(2) << i << ' '; } cout << setiosflags(ios::internal | ios::showpos) << setw(5) << setfill('0') << memory[i] << ' ' << resetiosflags(ios::internal | ios::showpos); } cout << endl; } void output(const char * const sPtr, int width, int value, bool sign) { cout << setfill(' ') << setiosflags(ios::left) << setw(20) << sPtr << ' '; //is a +/- Sign Needed? if (sign) cout << setiosflags(ios::showpos | ios::internal); //setup for displaying accumulator value etc cout << resetiosflags(ios::left) << setfill('0'); //determine the field width and dispay value if (width == 5) cout << setw(width) << value << '\n'; else //width is 2 cout << setfill(' ') << setw(3) << ' ' << setw(width) << setfill('0') << value << '\n'; //disable sign if it was set if (sign) cout << resetiosflags(ios::showpos | ios::internal); }
Output:
*** Welcome to Simpletron *** *** Please Enter your Program one instrution *** *** (or Data word) at a time. I will type the *** *** location number and question mark (?). *** *** You then type the word for that location. *** *** Type the senitel -99999 to stop entering *** *** your Program
***
00 ? 1099
01 ? 1098
02 ? 2099
03 ? 3398
04 ? 2150
05 ? 1150
06 ? 1199
07 ? 1198
08 ? 4300
09 ? -99999
****START SIMPLETRON EXECUTION***********
Enter an integer: 4
Enter an integer: 9
Content of 50: 36
Content of 99: 4
Content of 98: 9
***************SIMPLETRON EXECUTION TERMINATED**************
*********** END SIMPLETRON EXECTION****************
REGISTERS:
accumulator +0036
instructionCounter 08
instructionRegister +4300
operationalCode 43
operand 00
MEMORY :
0 1 2 3 4 5 6 7 8 9
0 +1099 +1098 +2099 +3398 +2150 +1150 +1199 +1198 +4300 +0000
10 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
20 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
30 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
40 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
50 +0036 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
60 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
70 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
80 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
90 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0009 +0004
Press any key to continue . . .