Vesp 1.0 Return to lecture notes

/*****************************************************************************/ 
/*                                VESP COMPUTER 1.0.                          *
/*                        With 8 instructions extendible to 16                *
/*                              Author: A. Yavuz Oruc                         *
/*****************************************************************************/
/* This  computer program simulates the fetch,decode
/* and execute cycles of a hypothetical 16-bit computer, 
/* called VESP (_V_Ery _Simple _Processor)
/* Revised to reduce the address field to 12 bits. 2/13/03                        
/* VESP  has the following registers:                   
/* A:     16 bits (Implicit) It refers to location 0 in  VESP's memory
/* B:     16 bits (Implicit) It refers to location 1 in  VESP's memory 
/* MAR:   12 bits  IR:     16 bits  PC:    13 bits
/* Its instruction repertoire consists of the following instructions: 
/* ADD: Add         Opcode: 000  ----- A = A+B                          HexCode: 0
/* CMP: Compl       Opcode: 001  ----- A = ~A                           HexCode: 1    
/* LDA: Load        Opcode: 010  ----- M[IR[4:15] ] = M[MAR+1]          HexCode: 2
/* MOV: Move        Opcode: 011  ----- M[IR[4:15] ] = M[M[MAR+1][4:15]] HexCode: 3  
/* JMP  Jump        Opcode: 100  ----- PC = IR[4:15]                    HexCode: 4  
/* JEZ: Jump if 0   Opcode: 101  ----- If (A = 0)  PC = IR[4:15]        HexCode: 5   
/* JPS: Jump if +   Opcode: 110  ----- If (A > 0)  PC = IR[4:15]        HexCode: 6  
/* HLT: Hlt         Opcode: 111  ----- reset = 1                        HexCode: 7  
/*         Programs are entered and displayed in hex code.
/*      Please communicate all your questions and comments to                      
/*                   A. Yavuz Oruc, Professor
/*      University of Maryland, College Park, MD 20742      
/*      E-mail: yavuz@eng.umd.edu
/*                        June 2000  
*/
#include <iostream.h> 
#include <stdio.h>
#include <limits.h> 
                  
void initialize(void); int readprogram(void);
void displayprogram(int progend); 
void displayregisters(void); void displaymemory(void);
void maincycle(void);  void fetch(void);
void decode(void);     void execute(void);
                  
//AYO: Define the registers of the architecture.
typedef struct 
{short   MAR,PC,IR,clock;
 short   MEMORY[8192],S,C,F,Z,reset,add,complement;
} architecture;  architecture   vesp;
                  
int j=1;
                  
int main(void)
{int address = 0,i = 0,action = 0, step = 0,progend;
 initialize();//AYO: Initialize all the registers.
 cout << "\nWelcome to Vesp 2.0\n\n";
 do {vesp.reset = 0; //AYO: vesp will continue to run unless it is reset.
//AYO: Input program, diplay registers or memory 
     cout << "Type \n 0 to enter a program\n "
          << "1 to display registers\n 2 to display memory: ";
     cin >> action; cout << "\n";
//AYO: Read the program, display it, and execute it.    
if(action == 0) {progend = readprogram(); displayprogram(progend);
//AYO: Step through or execute the program. 
while(vesp.reset == 0)
{while(step == 0 && vesp.reset == 0)
 {cout << "Enter 1 if you wish to step the program, and 0 to execute it : ";
 scanf("%d",&step);
 if(step == 1) {maincycle(); step = 0; break;}   
 while(vesp.reset == 0) {maincycle();}
 }
 }
 
//AYO: Display the number of instructions and clock cycles executed.
cout << "The number of instructions executed  = ";  
printf("%0d",j-1);  cout << "\n";
cout << "The number of clock cycles used = ";  
printf("%0d",vesp.clock);  cout << "\n\n";
j = 1;
}
if (action == 1) displayregisters();
if (action == 2) displaymemory();
if (action == 3) readprogram();
} 
while (1);
}
                  
void initialize(void)
{vesp.PC = vesp.MEMORY[0] = vesp.MEMORY[1] = vesp.IR = 0;
 vesp.reset = 0; vesp.clock = 0;
}
                  
int readprogram(void)
{int address,instruction,progend,action = 0;
// char filename[16]; FILE *file;
 do{ cout << "Enter your program's starting " 
      << "address ( >= 2) as a 3-digit hex number: ";
 cin >> hex >> vesp.PC;
 } while (vesp.PC < 2);
 
 address =  vesp.PC; 
 while ( ( vesp.MEMORY[address-1] !=  -1 ) && (address < 4096)) //AYO: -1 marks the end.
 {cout << "Enter instruction  " 
          << address -vesp.PC  
          << " using a 4-digit hex number" << "\n";
     cout << "Or type -1 to end your program: ";
     cin >> hex >> instruction;  //AYO: read it in hex.
     vesp.MEMORY[address] = instruction;
     address = address + 1;
    }
                  
if (address >= 4096) 
{cout << "Memory overflow," 
      << "Please quit from the file menu and restart me!"; 
return address-1;}
progend = address - 1; 
return progend;
}
                  
void displayprogram(int progend) 
{int i; 
cout << "\nHere is your program: \n\n";
for (i = vesp.PC; i< progend; i++)
{
printf("Location %03X: ",i);
//cout << "Location "  <<  hex << i << ": ";  //AYO: display it in hex. 
printf("%04X",0x0000FFFF & vesp.MEMORY[i]); cout << "\n";
}
}
void displayregisters(void)
{cout << "A = ";   printf("%04X", 0x0000FFFF & vesp.MEMORY[0]);  cout << ", "; 
 cout << "B = ";   printf("%04X", 0x0000FFFF & vesp.MEMORY[1]);  cout << ", ";   
 cout << "Z = " <<   vesp.Z; cout << ", ";
 cout << "S = " <<   vesp.S; cout << ", ";
 cout << "C = " <<   vesp.C; cout << ", ";
 cout << "F = " <<   vesp.F; cout << "\n";
 cout << "MAR = ";  printf("%03X",vesp.MAR); cout << ", ";  
 cout << "PC = ";   printf("%03X",vesp.PC);  cout << ", ";  
 cout << "IR = ";   printf("%04X",vesp.IR);  cout << ", ";  
 cout << "reset = " << vesp.reset << "\n\n";
}
                  
void displaymemory(void)
{int location1,location2,i; 
 cout << "Enter the first address: ";
scanf("%3X",&location1);
cout << "Enter the last address: ";
scanf("%3X",&location2);
cout << "\n";
for (i = location1; i <= location2; i++)
{cout <<  "Location " << i << " : "; 
 cout << hex << (0x0000FFFF & vesp.MEMORY[i]); cout << "\n"; 
}
 cout << "\n";
}
                  
void maincycle(void)
{     cout << "Machine Cycle " << j << ":  ";
       j = j+1;
       //AYO: Fetch Step
        cout << "PC = ";  printf("%03X",vesp.PC);  cout << ", ";   
        cout << "\nFETCH SUBCYCLE\n";
        fetch();
        cout << "\nClock cycle = ";  printf("%0d",vesp.clock); cout << "\n\n";
        //AYO: Decode Step
        cout << "DECODE SUBCYCLE\n"; 
        decode();
        cout << "Clock cycle = ";  printf("%0d",vesp.clock); cout << "\n\n";                
        //AYO: Execute Step   
        cout << "EXECUTE SUBCYCLE\n";  
        vesp.add = vesp.complement = 0;  
        execute(); 
        cout << "Clock cycle = ";  printf("%0d",vesp.clock); cout << "\n\n";
        //AYO: Display the registers   
        cout << "A = ";     printf("%04X",0x0000FFFF & vesp.MEMORY[0]); cout << ", ";  
        cout << "B = ";     printf("%04X",0x0000FFFF & vesp.MEMORY[1]); cout << ", ";  
        cout << "Z = " <<   vesp.Z  << ", ";
        cout << "S = " <<   vesp.S  << ", ";
        cout << "C = " <<   vesp.C  << ", ";
        cout << "F = " <<   vesp.F  << "\n";
        cout << "MAR = ";   printf("%03X",vesp.MAR);  cout << ", ";  
        cout << "reset = " << vesp.reset << "\n"; 
        cout << "add = " << vesp.add << "\n"; 
        cout << "complement = " << vesp.complement << "\n\n"; 
        if( (vesp.IR >> 12 ) == 2  ||  (vesp.IR   >> 12 ) == 3) 
        {cout << "Memory["; cout << hex << (vesp.IR & 0x0FFF) << "] = "; 
         printf("%04X",0x0000FFFF & vesp.MEMORY[vesp.IR & 0x0FFF]); cout << ",\n\n";}       
}
                  
void fetch(void)
{       //clock cycle 1.  Load next instruction's address into MAR. 
        vesp.MAR =  vesp.PC; vesp.clock = vesp.clock +1;
        vesp.PC =   vesp.PC +1; //Increment PC.  
        //clock cycle 2.  Fetch the next Instruction into IR 
        cout << "MAR = ";   printf("%04X",vesp.MAR);  cout << ", "; 
        vesp.IR = vesp.MEMORY[vesp.MAR]; vesp.clock = vesp.clock +1; 
        cout << "IR = ";   printf("%04X",vesp.IR);  cout << ", "; 
}
                  
void decode(void)
{cout << "The decoded instruction is: ";  
     switch( vesp.IR   >> 12)   
         {//Add                            //Complement
          case  0: cout << "ADD\n"; break; case  1: cout << "CMP\n"; break;          
         //Load                            //Move
          case  2: cout << "LDA\n"; break; case  3: cout << "MOV\n"; break;
         //Jump                            //Jump if A = 0
          case  4: cout << "JMP\n"; break; case  5: cout << "JEZ\n"; break;
         //Jump if A > 0                   //Halt
          case  6: cout << "JPS\n"; break; case  7: cout << "HLT\n"; break;
          }                    
}
                  
                  
void execute(void)
{ short temp;
  switch(vesp.IR >> 12) 
         {//clock cycle 3.
           //Add
          case  0:  
          temp = vesp.MEMORY[0] + vesp.MEMORY[1]; vesp.clock = vesp.clock +1;                                        
          if(vesp.MEMORY[0] > 0 && vesp.MEMORY[1] > 0 && temp  <  0 || 
          vesp.MEMORY[0] < 0 && vesp.MEMORY[1] < 0  && temp  >= 0) 
          vesp.F = 1; else vesp.F = 0; //AYO: Set Overflow Flag
          if (vesp.MEMORY[0] < 0 && vesp.MEMORY[1] < 0  || temp > 0 && 
          (vesp.MEMORY[0] < 0 && vesp.MEMORY[1] > 0 || vesp.MEMORY[0] > 0 && vesp.MEMORY[1] < 0)) 
          vesp.C = 1; else vesp.C = 0; //AYO: Set Carry Flag
          vesp.MEMORY[0]  = temp;    //Save the sum in MEMORY[0]
          //AYO: Set Zero Flag
          if(vesp.MEMORY[0]  == 0) vesp.Z = 1; else vesp.Z = 0; 
          //AYO: Set Sign Flag          
          vesp.S = (vesp.MEMORY[0] & 0x8000 ) >> 15;  vesp.add = 1; break;
         //Complement
          case  1:  vesp.MEMORY[0] = ~vesp.MEMORY[0]; 
                    vesp.clock = vesp.clock +1;  
                    if(vesp.MEMORY[0]  == 0)  vesp.Z = 1; else vesp.Z = 0; 
                    vesp.S = (vesp.MEMORY[0] & 0x8000 ) >> 15;  
                    vesp.complement = 1; break;
         //Load         
         case  2:   vesp.MEMORY[vesp.IR&0x0FFF] =  
                    vesp.MEMORY[(vesp.MAR) + 1]; 
                    vesp.clock = vesp.clock +1; vesp.PC = vesp.PC + 1; break;  
         //Move
          case 3:   vesp.MEMORY[vesp.IR&0x0FFF] = 
                    vesp.MEMORY[vesp.MEMORY[(vesp.MAR) + 1]];   
                    vesp.clock = vesp.clock + 2; vesp.PC = vesp.PC + 1; break;
         //Jump
          case 4:   vesp.PC = vesp.IR & 0x1FFF;vesp.clock = vesp.clock +1; break;  
         //Branch if A is  0
          case 5:   if (vesp.MEMORY[0] == 0) 
                    {vesp.PC = vesp.IR & 0x0FFF;} 
                    vesp.clock = vesp.clock +1; break;  
         //Branch if A is > 0
          case 6: if (vesp.MEMORY[0] > 0) 
                   {vesp.PC = vesp.IR & 0x0FFF;} 
                    vesp.clock = vesp.clock +1; break;  
         //Halt
          case 7:  vesp.reset = 1;  vesp.clock = vesp.clock +1; break; 
                }    

}