
- 7th Sep 2021
- 16:53 pm
The Problem
Using C programming language write a program that simulates a variant of the Tiny Machine
Architecture. In this implementation memory (RAM) is split into Instruction Memory (IM) and Data
Memory (DM). Your code must implement the basic instruction set architecture (ISA) of the Tiny
Machine Architecture:
1 - LOAD
2 - ADD
3 - STORE
4 - SUB
5 - IN
6 - OUT
7 - END
8 - JMP
9 - SKIPZ
Each piece of the architecture must be accurately represented in your code (Instruction Register, Program
Counter, Memory Address Registers, Instruction Memory, Data Memory, Memory Data Registers, and
Accumulator). Data Memory will be represented by an integer array. Your Program Counter will begin
pointing to the first instruction of the program.
For the sake of simplicity Instruction Memory (IM) and Data Memory (DM) may be implemented
as separate arrays.
Hint: Implementing a struct for your Instructions and an array of these structs as your Instruction
Memory greatly simplifies this program.
Example:
typedef struct {
int opCode, device Or Address;
} Instruction;
Instruction IM[MAXPROGRAMSIZE];
Note: IM, MDR1, and IR are of type Instruction. All other CPU registers and Data Memory (DM) are of
type int.
Input Specifications:
Your simulator must run from the command line with a single input file as a parameter to main. This file
will contain a sequence of instructions for your simulator to store in “Instruction Memory” and then run
via the fetch/execute cycle. In the input file each instruction is represented with two integers: the first one
represents the opcode and the second one a memory address or a device number depending on the
instruction.
Example:
Input File
5 5 //IN 5
6 7 //OUT 7
3 0 //STORE 0
5 5 //IN 5
6 7 //OUT 7
3 1 //STORE 1
1 0 //LOAD 0
4 1 //SUB 1
3 0 //STORE 0
6 7 //OUT 7
1 1 //LOAD 1
6 7 //OUT 7
7 0 //END
Output Specifications:
Your simulator should provide output according to the input file. Along with this output your program
should provide status messages identifying details on the workings of your simulator. Output text does
not have to reflect my example word-for-word, but please provide detail on the program as it runs in a
readable format that does not conflict with the actual output of your simulator. After each instruction print
the current state of the Program Counter, Accumulator, and Data Memory. The INPUT instruction is the
only one that should prompt an interaction from the user.
Example:
Assembling Program…
Program Assembled.
Run.
PC = 10 | A = NULL | DM = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
/* input value */
X
PC = 11 | A = X | DM = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
/* outputting accumulator to screen */
X
PC = 12 | A = X | DM = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
/* storing accumulator to memory location 0 */
PC = 13 | A = X | DM = [X, 0, 0, 0, 0, 0, 0, 0, 0, 0]
… etc
Program complete.
Grading:
Your simulator will be graded on the above criteria. Your program should compile and run from the
command line with one input file parameter. Please note that your program will not just be graded on
whether or not it runs successfully; accurate simulation and a thorough demonstration of your
understanding on the workings of this architecture will constitute a large portion of this grade. As that is
the case it is in your best interest to comment your program in a concise and readable way. However, if
your program does not run or compile the maximum points possible will be 30.
For instance, to implement FETCH and instruction LOAD you must implement each step:
FETCH
MAR1 ? PC
PC ? PC + 1
MDR1 ? IM [MAR1] // IM stands for Instruction Memory (program memory)
IR ? MDR1
Case IR.OP = 1 Load is executed.
LOAD (Execute cycle)
MAR2 ? IR.ADDR
MDR2 ? DM [MAR2] //DM stands for Data Memory
A ? MDR2
Note: Lecture 1 describes the instruction set architecture of the Tiny Machine.
Submission
You need to include the following in order to have your assignment graded:
1. Your name and NID at the top of your program.
2. Name your file as your “last name” then “HW3”.c Example: LastNameHW3.c
3. Your program must be submitted as a C file.
4. Please check and double check your submission.
Missing one of the submission requirements, your assignment automatically won’t be
graded.
Note: you should use two MARs, MAR1 for IM and MAR2 for DM.
Tiny Machine ISA:
FETCH
MAR1 ? PC
PC ? PC + 1
MDR1 ? IM [MAR1] // IM stands for Instruction Memory (program memory)
IR ? MDR1
Depending on IR.OP one of the following instructions will be executed:
(Execute cycle)
LOAD MAR2 ? IR.ADDR MDR2 ? DM[MAR2] A ? MDR2 ADD MAR2 ? IR.ADDR MDR2 ? DM[MAR2] A ? A + MDR2 STORE MAR2 ? IR.ADDR MDR2 ? A DM[MAR2] ? MDR2 SUB MAR2 ? IR.ADDR MDR2 ? DM[MAR2] A ? A - MDR2 IN A ? Input value from keyboard OUT Screen ? A END Run ? 0 // In your program Run must be initialized to 1 to control the instruction cycle. JMP PC ? IR.ADDR SKIP IF (A == 0) PC ? PC + 1
Solution:
#include #include #define MAXPROGRAMSIZE 100 #define MAXMEMORYSIZE 10 struct instruct { int opCode, deviceOrAddress; }; struct instruct programMemory[MAXPROGRAMSIZE]; struct instruct instructionRegister; int accumulate; int memory[MAXMEMORYSIZE]; int progCount = 10; int memoryAddRegis; int memoryDataRegis; int decod = 0; void fetch_execute(void); void load(void); void store(void); void add(void); void sub(void); void output(void); void input(void); void skipz(void); void jump(void); int main(int argc, char *argv[]) { int c; //read input file file.txt FILE *file; if(argc!=2) { printf("Please input the file!\n"); exit(1); } file = fopen(argv[1], "r"); if (file) { printf("Assembling the Program\n"); int programIndex = 0; while ((c = getc(file)) != EOF) { c-='0'; if(c<0||c>9) { continue; } if(programIndex%2==0) { programMemory[progCount+programIndex/2].opCode=c; }else { programMemory[progCount+programIndex/2].deviceOrAddress=c; } programIndex++; } printf("Program Assembled\n Run.\n"); /*for(i=progCount;i < progCount+3;i++){ printf("\n%d %d",programMemory[i].opCode,programMemory[i].deviceOrAddress); }*/ while(decod!=7) { switch(decod) { case 0: fetch_execute(); break; case 1: load(); break; case 2: add(); break; case 3: store(); break; case 4: sub(); break; case 5: input(); break; case 6: output(); break; case 8: jump(); break; case 9: skipz(); break; } } printf("Program Complete\n"); fclose(file); }else { printf("File not found\n"); } system("PAUSE"); return 0; } void fetch_execute() { memoryAddRegis=progCount; ++progCount; memoryDataRegis = programMemory[memoryAddRegis].deviceOrAddress; instructionRegister.deviceOrAddress=memoryDataRegis; memoryDataRegis = programMemory[memoryAddRegis].opCode; instructionRegister.opCode=memoryDataRegis; decod = instructionRegister.opCode; } //Loads the contents of instructionRegister address into A (A stand for Accumulator). void load() { memoryAddRegis = instructionRegister.deviceOrAddress; memoryDataRegis = memory[memoryAddRegis]; accumulate = memoryDataRegis; decod = 0; } //Store the contents of A into instructionResister address void store() { memoryAddRegis = instructionRegister.deviceOrAddress; memoryDataRegis = accumulate; memory[memoryAddRegis] = memoryDataRegis; decod = 0; } //The data value stored at instructionRegister address is added to the A and the result is stored back in the A. void add() { memoryAddRegis = instructionRegister.deviceOrAddress; memoryDataRegis = memory[memoryAddRegis]; accumulate = accumulate+memoryDataRegis; decod = 0; } //Subtracts the value located at instructionRegister address from the A and stored the result back in the A. void sub() { memoryAddRegis = instructionRegister.deviceOrAddress; memoryDataRegis = memory[memoryAddRegis]; accumulate = accumulate-memoryDataRegis; decod = 0; } //Print out the contents of the AC in the output device. void output() { int i = 0; printf("PC = %d \t A = %d \t MEM = [",progCount,accumulate); for(i=0;i { printf("%d, ",memory[i]); } printf("%d]\n",memory[i]); decod = 0; } //A value from the input device is transferred into the A. void input() { printf("Enter a number: "); scanf("%d",&accumulate); decod = 0; } //If the contents of the Accumulator = 0 the next instruction is skipped. void skipz() { if (accumulate==0) { ++progCount; } decod = 0; } //Causes an unconditional branch to instructionRegister address. void jump() { progCount = instructionRegister.deviceOrAddress; decod = 0; }