SQL

Friday, 5 June 2015

Simpletron Machine Language (SML) in C++

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
Source Code:



#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, STOREADD = 30, 
    SUBTRACT , DIVIDE , MULTIPLYBRANCH = 40, 
    BRANCHNEGBRANCHZEROHALT
    };
 
void load(int * const);
void execute(int * constint * constint * constint * constint * constint * const);
void dump(const int *constintintintintint);
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 memoryint * const acPtrint * const icPtrint * const irPtrint * const opCodePtrint * 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 memoryint accumulatorint instructionCounterint instructionRegisterint operationalCodeint operand)
{
 void output(const char *constintintbool);//prototype
 cout << "\n REGISTERS:\n";
 output("accumulator", 5, accumulatortrue);
 output("instructionCounter", 2, instructionCounterfalse);
 output("instructionRegister", 5, instructionRegistertrue);
 output("operationalCode", 2, operationalCodefalse);
 output("operand", 2, operandfalse);
 
 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 sPtrint widthint valuebool 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 . . .