You are on page 1of 10

Created by: CPP Viewer

/*##########################################################################
#########
Note: Please don’t upload the assignments, template file/solution and lab. manual on GitHub
or others public repository.
It violates the BITS’s Intellectual Property Rights (IPR).
************************************************************************************/

#include <stdio.h>
#include <cstdint>

//Opcode of MIPS's instructions


#define R_OP 0
#define ADD_Func 32
#define ADDI_OP 0b0001000// 8
#define LW_OP 35
#define SW_OP 43
#define BNE_OP 5
#define STP_OP 63 //Not a MIPS instruction

uint32_t PC; //Program counter

int32_t JAddr;
uint8_t Shamt; // for shifting
uint8_t Funct, ALUOP;
uint8_t RS, RT, RD;
int16_t Immediate;

bool ZeroFlag; //

int32_t RegFile[32];

uint8_t Imem[256], Dmem[256]; //2^8 locations, byte addressable Instruction and Data
memory

uint8_t run = 1; //

void readRegfile(uint8_t in_reg_1, uint8_t in_reg_2, int32_t *out_reg_1, int32_t *out_reg_2) {


//First Register
*out_reg_1 = RegFile[in_reg_1];
//Second Register
*out_reg_2 = RegFile[in_reg_2];
}

void writeRegfile(uint8_t in_reg, bool RegWrite, int32_t *out_reg) {

if (RegWrite==true){
if (in_reg == 0 )
printf("Don't try to modify R0\n");
else
RegFile[in_reg] = *out_reg;}

int ALU(int in1, int in2) {


int result;
switch (ALUOP) {

//used for LW, SW, ADDI


case 0:
result = in1 + in2;

break;
//used for BNE //
case 1: result = in1 - in2;

break;
//for rest of the instruction types
case 2:
switch(Funct) {

case ADD_Func: result = in1 + in2;

break;

}
break;
}

if (result == 0)
ZeroFlag = true;
else
ZeroFlag = false;

return result;
}
uint32_t readIMM(uint32_t addr) {
//Big-endian format - lower byte - higher address
uint8_t byte0, byte1, byte2, byte3;
uint32_t instr;

byte3 = Imem[addr+0];
byte2 = Imem[addr+1];
byte1 = Imem[addr+2];
byte0 = Imem[addr+3];

instr = (byte3 << 24) + (byte2 << 16) + (byte1 << 8) + byte0;

return instr;
}
int readDMM(int addr, bool MemRead) {
//Big-endian format - lower byte - higher address
uint8_t byte0, byte1, byte2, byte3;
int data;
if (MemRead) {

byte3 = Dmem[addr+0];
byte2 = Dmem[addr+1];
byte1 = Dmem[addr+2];
byte0 = Dmem[addr+3];
data = (byte3 << 24) + (byte2 << 16) + (byte1 << 8) + byte0;
}
else
printf("Error from Data memory's read module\n");
return data;
}

void writeDMM(uint32_t addr, int data, bool MemWrite) {


//Big-endian format - lower byte - higher address
uint8_t byte0, byte1, byte2, byte3;

if (MemWrite) {
byte3 = data >> 24;
byte2 = (data & 0b00000000111111110000000000000000) >> 16;
byte1 = (data & 0b00000000000000001111111100000000) >> 8;
byte0 = (data & 0b00000000000000000000000011111111);

Dmem[addr+0] = byte3;
Dmem[addr+1] = byte2;
Dmem[addr+2] = byte1;
Dmem[addr+3] = byte0;

}
else
printf("Error from Data memory's write module\n");

uint32_t incrementPC(uint32_t pc){


return pc + 4;
}

int32_t addBranchAddr(int32_t pc, int32_t branchAddr){


return pc + branchAddr;
}

int32_t signExtn(int16_t offset) {


int32_t temp;
temp = offset;
return temp;
}

uint32_t leftShift2_16(int16_t offset) {


int32_t temp;
temp = offset;
temp = temp << 2;
return temp;
}

uint32_t leftShift2_25(int32_t offset) {


int32_t temp;
temp = offset << 2;
return temp;
}

uint8_t fetchDecodeFSM(void) {
uint8_t Opcode; // Other Global variable can be used.
//Write your code here

// fetch instruction pointed to by PC from instruction memeory decode instrution


Opcode =(readIMM(PC) >> 26);
RS =(readIMM(PC) & 0b00000011111000000000000000000000) >> 21;
RT =(readIMM(PC) & 0b00000000000111110000000000000000) >> 16;
RD =(readIMM(PC) & 0b00000000000000001111100000000000) >> 11;
Shamt = (readIMM(PC) & 0b00000000000000000000011111000000) >> 6;
Funct = (readIMM(PC) & 0b00000000000000000000000000111111);
Immediate = (readIMM(PC) & 0b00000000000000001111111111111111);

// incremement PC
PC = incrementPC(PC);

return Opcode;

void lwFSM(void) {

int32_t out_reg1, out_reg2, out_reg;


//Write your code here

// load data into source reg


readRegfile(RS, RS, &out_reg1, &out_reg1);

// compute address of mem locn


out_reg2 = ALU(out_reg1, signExtn(Immediate));

// read data memory at address


out_reg = readDMM(out_reg2, true);

// write data to target reg


writeRegfile(RT, true, &out_reg);

void swFSM(void) {
int32_t out_reg1, out_reg2, out_reg;
//Write your code here

// load data into source reg


readRegfile(RS, RT, &out_reg1, &out_reg2);

// compute address of mem locn


out_reg = ALU(out_reg1, signExtn(Immediate));

// write data memory at address


writeDMM(out_reg, out_reg2, true);

void addFSM(void) {

int32_t out_reg1, out_reg2, out_reg;


//Write your code here

// load data into source regs


readRegfile(RS, RT, &out_reg1, &out_reg2);

// compute sum of source regs


out_reg = ALU(out_reg1, out_reg2);

// write data to destination reg


writeRegfile(RD, true, &out_reg);

void addiFSM(void) {

int32_t out_reg1, out_reg2, out_reg;


//Write your code here

// load data into source reg


readRegfile(RS, RS, &out_reg1, &out_reg1);

// compute addi
out_reg = ALU(out_reg1, signExtn(Immediate));
// write data to target reg
writeRegfile(RT, true, &out_reg);

void bneFSM(void) {
int32_t out_reg1, out_reg2, out_reg;
//Write your code here

// load data into source regs


readRegfile(RS, RT, &out_reg1, &out_reg2);

// compute difference and set/reset ZeroFlag


ALU(out_reg1, out_reg2);

if (!ZeroFlag) PC = addBranchAddr(PC, leftShift2_25(signExtn(Immediate)));

void stpFSM(void) {
run=0;
}

void load_program(void);
int main(void) {

RegFile[0] = 0;
load_program();
PC = 0;
while (run) {
uint8_t opcode = fetchDecodeFSM();
switch (opcode)
{

case R_OP:
ALUOP = 2;
switch (Funct) {
case ADD_Func: addFSM();
break;

}
break;
case ADDI_OP: ALUOP = 0; addiFSM(); break;
case LW_OP: ALUOP = 0; lwFSM(); break;
case SW_OP: ALUOP = 0; swFSM(); break;
case BNE_OP: ALUOP = 1; bneFSM(); break;
case STP_OP: stpFSM(); break;
}
}
printf("The Fibonacci numbers are:\n");
for (int i = 0; i < 7; i++) {
uint8_t byte0, byte1, byte2, byte3;
int data;

data = readDMM(252-(4*i), true);


printf("%d, ", data);
}

}
void load_program(void) {

//Big-endian format lower-order addresses are used for the most significant byte
Dmem[255] = 0b00000001;
Dmem[254] = 0b00000000;
Dmem[253] = 0b00000000;
Dmem[252] = 0b00000000;

Dmem[251] = 0b00000001;
Dmem[250] = 0b00000000;
Dmem[249] = 0b00000000;
Dmem[248] = 0b00000000;

//Instructions

// Code for generating the first 7 Fibonacci numbers.

//ADDI R1, R0, 252 - ---- R1 <- R0 + 252


Imem[0] = 0b00100000;
Imem[1] = 0b00000001;
Imem[2] = 0b00000000;
Imem[3] = 0b11111100;
//ADDI R2, R0, 2 - ---- R2 <- R0 + 2 // counter
Imem[4] = 0b00100000;
Imem[5] = 0b00000010;
Imem[6] = 0b00000000;
Imem[7] = 0b00000010;
//ADDI R7, R0, 7 - ---- R7 <- R0 + 7 // Max val // doubt
Imem[8] = 0b00100000;
Imem[9] = 0b00000111;
Imem[10] = 0b00000000;
Imem[11] = 0b00000111;
//LW R3, R1, 0 - ---- R3 <- Dmem[R1 + 0]
Imem[12] = 0b10001100;
Imem[13] = 0b00100011;
Imem[14] = 0b00000000;
Imem[15] = 0b00000000;
//ADDI R1, R1, -4 - ---- R1 <- R1 - 4 //R1 - 248
Imem[16] = 0b00100000;
Imem[17] = 0b00100001;
Imem[18] = 0b11111111;
Imem[19] = 0b11111100;
//LW R4, R1, 0 - ---- R4 <- Dmem[R1 + 0]
Imem[20] = 0b10001100;
Imem[21] = 0b00100100;
Imem[22] = 0b00000000;
Imem[23] = 0b00000000;
//ADD R5, R3, R4 - ---- R5 <- R3 + R4
Imem[24] = 0b00000000;
Imem[25] = 0b01100100;
Imem[26] = 0b00101000;
Imem[27] = 0b00100000;
//SW R5, R1, -4 - ---- Dmem[R1 - 4] <- R5 // 248-4 = 244
Imem[28] = 0b10101100;
Imem[29] = 0b00100101;
Imem[30] = 0b11111111;
Imem[31] = 0b11111100;
//ADDI R2, R2, 1 - ---- R2 <- R2 + 1 //Counter
Imem[32] = 0b00100000;
Imem[33] = 0b01000010;
Imem[34] = 0b00000000;
Imem[35] = 0b00000001;
//BNE R7, R2, -7(instructions)
Imem[36] = 0b00010100;
Imem[37] = 0b01000111;
Imem[38] = 0b11111111;
Imem[39] = 0b11111001;
//STP
Imem[40] = 0b11111100;
Imem[41] = 0b00000000;
Imem[42] = 0b00000000;
Imem[43] = 0b00000000;
}

You might also like