/*****************************************************************************/
/* 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;
}
}
|
|
|