From bfa96d40f117755b9c98a395678d43ab6d1715cf Mon Sep 17 00:00:00 2001 From: renaetaylor Date: Wed, 6 Dec 2017 23:15:36 -0500 Subject: [PATCH] Comments Formatted/added comments --- ALU.cpp | 37 ++++++++++ ALU.h | 14 ++++ ALUControl.cpp | 32 ++++++--- ALUControl.h | 13 ++++ ASMParser.cpp | 163 +++++++++++++++++++++++++-------------------- ControlLine.cpp | 1 + ControlLine.h | 3 + DataMem.cpp | 25 ++++++- DataMem.h | 12 +++- FileReader.cpp | 18 ++++- FileReader.h | 4 +- Instruction.cpp | 17 +++-- InstructionMem.cpp | 19 +++++- InstructionMem.h | 3 +- MUX.cpp | 17 +++++ MUX.h | 12 ++++ MainControl.cpp | 4 ++ MainControl.h | 7 +- Opcode.cpp | 36 ++++++---- Opcode.h | 4 ++ Processor.cpp | 34 +++++++++- Processor.h | 10 ++- ProgramCounter.cpp | 2 + ProgramCounter.h | 2 + RegisterTable.cpp | 8 ++- Registers.cpp | 22 ++++++ Registers.h | 8 ++- SLTwo.cpp | 4 ++ SLTwo.h | 6 ++ SignExtend.cpp | 7 ++ SignExtend.h | 9 +++ main.cpp | 11 ++- 32 files changed, 444 insertions(+), 120 deletions(-) diff --git a/ALU.cpp b/ALU.cpp index 0201237..7c875a5 100644 --- a/ALU.cpp +++ b/ALU.cpp @@ -1,24 +1,38 @@ #include "ALU.h" +/* This class functions as the Arithmetic Logic Unit by performing arithmetic and + * logical operations based on a given hex input value and outputs the result of the + * operation performed. + */ + +// Set-up ALU with default values ALU::ALU(){ input1 = "0x00000000"; input2 = "0x00000000"; result = "0x00000000"; } + +// testing // void ALU::setInputs(int first, int second){ // input1 = first; // input2 = second; // } + +// Set string values as inputs for ALU void ALU::setInputs(string first, string second){ input1 = first; input2 = second; } + +// First calculation method for ALU given a control signal void ALU::calculate(string _control){ control = _control; stringstream ss; + + // Control signal = 2 if(control == "0x2"){ one = stol(input1.substr(2), nullptr, 16); two = stol(input2.substr(2), nullptr, 16); @@ -31,6 +45,8 @@ void ALU::calculate(string _control){ }else{ result = "0x" + ss.str(); } + + // Control signal = 6 }else if(control == "0x6"){ one = stol(input1.substr(2), nullptr, 16); two = stol(input2.substr(2), nullptr, 16); @@ -43,6 +59,8 @@ void ALU::calculate(string _control){ }else{ result = "0x" + ss.str(); } + + // Control signal = 9 }else if(control == "0x9"){ one = stol(input1.substr(2), nullptr, 16); two = stol(input2.substr(2), nullptr, 16); @@ -52,17 +70,22 @@ void ALU::calculate(string _control){ }else{ result = "0x0"; } + + // testing // ss << std::hex << calc; // if (ss.str().size()>8){ // result = "0x" + ss.str().substr(ss.str().size()-8); // }else{ // result = "0x" + ss.str(); // } + }else{ cout << control << endl; cerr << "Wrong ALU Control signal" << endl; exit(1); } + + // testing // stringstream toHex; // toHex << std::hex << result; // string s = toHex.str(); @@ -70,25 +93,33 @@ void ALU::calculate(string _control){ // s = s.substr(s.size()-8); // } // result = stoi(s, nullptr, 16); + if(calc == 0){ zeroValue = "0x1"; + }else{ zeroValue = "0x0"; } } + +// Second calulation method for ALU without a given control signal void ALU::calculate(){ stringstream ss; one = stol(input1.substr(2), nullptr, 16); two = stol(input2.substr(2), nullptr, 16); calc = one + two; ss << std::hex << calc; + if (ss.str().size()>8){ result = "0x" + ss.str().substr(ss.str().size()-8); + }else{ result = "0x" + ss.str(); } + + // testing // result = input1 + input2; // stringstream toHex; // toHex << std::hex << result; @@ -97,13 +128,17 @@ void ALU::calculate(){ // s = s.substr(s.size()-8); // } // result = stoi(s, nullptr, 16); + if(calc == 0){ zeroValue = "0x1"; + }else{ zeroValue = "0x0"; } } + +// Returns the input values to the ALU in hexadecimal string ALU::inputs(){ stringstream toHex; toHex << "First input: "; @@ -115,6 +150,8 @@ string ALU::inputs(){ return toHex.str(); } + +// Returns the output values to the ALU in hexadecimal string ALU::outputs(){ stringstream toHex; toHex << "Output: "; diff --git a/ALU.h b/ALU.h index b626736..6a38b92 100644 --- a/ALU.h +++ b/ALU.h @@ -5,22 +5,36 @@ #include using namespace std; + +/* This class functions as the Arithmetic Logic Unit by performing arithmetic and + * logical operations based on a given hex input value and outputs the result of the + * operation performed. + */ + class ALU{ public: + // Set-up ALU with default values of hex 0 ALU(); // void setInputs(int first, int second); + + // Sets string values as inputs for ALU void setInputs(string first, string second); // Two calculate methods, with or without control signals void calculate(string _control); void calculate(); + // Returns the input values to the ALU in hexadecimal string inputs(); + // Returns the output values to the ALU in hexadecimal string outputs(); + + // Getter methods string getZeroValue(){return zeroValue;}; string getResult(){return result;}; string getControlSignal(){return control;}; + private: string input1; string input2; diff --git a/ALUControl.cpp b/ALUControl.cpp index 9628093..c9aec3e 100644 --- a/ALUControl.cpp +++ b/ALUControl.cpp @@ -1,39 +1,55 @@ #include "ALUControl.h" +/* This class computes the output signal of the ALU based on either a control signal + * or a function code and returns the values for ALUOp1, ALUOp2, and the function code + */ + +// Set up ALU Control void ALUControl::setControl(string op1, string op2){ control = op1.substr(2) + op2.substr(2); } + +// Compute output signal based on the control signal (I-type) or opcode (R-Type) void ALUControl::compute(){ + // LW and SW == ADD if(control == "00"){ - // LW and SW == add output = "0x2"; + + // BEQ == SUB }else if(control == "01"){ - // Beq == sub output = "0x6"; + + // R-type }else{ - // R-type + // ADD if (funcCode == "100000"){ - // add output = "0x2"; + + // SUB }else if(funcCode == "100010"){ - // sub output = "0x6"; + + // AND }else if(funcCode == "100100"){ - // and output = "0x0"; + // OR }else if(funcCode == "100101"){ - // or output = "0x1"; + + // SLT }else if(funcCode == "101010"){ - // set on less than output = "0x9"; } } } + + string ALUControl::inputs(){ + // testing // cout << control << ' ' << funcCode << ' ' << output; + stringstream ss; ss << "Inputs: "; ss << "\n ALUOp1: 0x" << control.at(0); diff --git a/ALUControl.h b/ALUControl.h index e282152..325f283 100644 --- a/ALUControl.h +++ b/ALUControl.h @@ -5,14 +5,27 @@ #include using namespace std; + +/* This class computes the output signal of the ALU based on either a control signal + * or a function code and returns the values for ALUOp1, ALUOp2, and the function code + */ + class ALUControl{ public: ALUControl(){}; + // Set up ALU Control void setControl(string op1, string op2); + + // Compute output signal based on the control signal (I-type) or function code (R-Type) void compute(); + + // Sets function code based on given string of numbers void setFuncCode(string f){funcCode = f;}; + + // Returns values for ALUOp1, ALUOp2, and the function code string inputs(); + // Returns output string outputs(); private: diff --git a/ASMParser.cpp b/ASMParser.cpp index d0ea109..e2abe2f 100644 --- a/ASMParser.cpp +++ b/ASMParser.cpp @@ -1,12 +1,19 @@ #include "ASMParser.h" +/* This class reads in a MIPS assembly file and checks its syntax. If + * the file is syntactically correct, this class will retain a list + * of Instructions (one for each instruction from the file). This + * list of Instructions can be iterated through. + */ + +// Specify a text file containing MIPS assembly instructions. Function +// checks syntactic correctness of file and creates a list of Instructions. ASMParser::ASMParser(string filename) - // Specify a text file containing MIPS assembly instructions. Function - // checks syntactic correctness of file and creates a list of Instructions. { Instruction i; myFormatCorrect = true; + // testing // myLabelAddress = 0x400000; ifstream in; @@ -14,8 +21,10 @@ ASMParser::ASMParser(string filename) if(in.bad()){ myFormatCorrect = false; } + else{ string line; + while( getline(in, line)){ i.setPlain(line); string opcode(""); @@ -25,22 +34,22 @@ ASMParser::ASMParser(string filename) getTokens(line, opcode, operand, operand_count); if(opcode.length() == 0 && operand_count != 0){ - // No opcode but operands - myFormatCorrect = false; - break; + // No opcode but operands + myFormatCorrect = false; + break; } + Opcode o = opcodes.getOpcode(opcode); - Opcode o = opcodes.getOpcode(opcode); if(o == UNDEFINED){ - // invalid opcode specified - myFormatCorrect = false; - break; + // invalid opcode specified + myFormatCorrect = false; + break; } - bool success = getOperands(i, o, operand, operand_count); + if(!success){ - myFormatCorrect = false; - break; + myFormatCorrect = false; + break; } string encoding = encode(i); @@ -55,8 +64,8 @@ ASMParser::ASMParser(string filename) } +// Iterator that returns the next instruction in the list of instructions Instruction ASMParser::getNextInstruction() - // Iterator that returns the next Instruction in the list of Instructions. { if(myIndex < (int)(myInstructions.size())){ myIndex++; @@ -68,55 +77,58 @@ Instruction ASMParser::getNextInstruction() } -void ASMParser::getTokens(string line, - string &opcode, - string *operand, - int &numOperands) - // Decomposes a line of assembly code into strings for the opcode field and operands, - // checking for syntax errors and counting the number of operands. + +// Decomposes a line of assembly code into strings for the opcode field and operands, +// checking for syntax errors and counting the number of operands. +void ASMParser::getTokens(string line, string &opcode, string *operand, int &numOperands) { // locate the start of a comment string::size_type idx = line.find('#'); - if (idx != string::npos) // found a ';' - line = line.substr(0,idx); - int len = line.length(); - opcode = ""; - numOperands = 0; + if (idx != string::npos) // found a ';' + line = line.substr(0,idx); + int len = line.length(); + opcode = ""; + numOperands = 0; if (len == 0) return; int p = 0; // position in line // line.at(p) is whitespace or p >= len while (p < len && isWhitespace(line.at(p))) - p++; + p++; + // opcode starts while (p < len && !isWhitespace(line.at(p))) { - opcode = opcode + line.at(p); - p++; + opcode = opcode + line.at(p); + p++; } - // for(int i = 0; i < 3; i++){ + + // testing + // for(int i = 0; i < 3; i++){ int i = 0; + while(p < len){ while ( p < len && isWhitespace(line.at(p))) - p++; + p++; // operand may start bool flag = false; - while (p < len && !isWhitespace(line.at(p))) - { - if(line.at(p) != ','){ - operand[i] = operand[i] + line.at(p); - flag = true; - p++; - } - else{ - p++; - break; - } - } + + while (p < len && !isWhitespace(line.at(p))) { + if(line.at(p) != ','){ + operand[i] = operand[i] + line.at(p); + flag = true; + p++; + } + else{ + p++; + break; + } + } + if(flag == true){ - numOperands++; + numOperands++; } i++; } @@ -126,8 +138,10 @@ void ASMParser::getTokens(string line, string::size_type idx2 = operand[numOperands-1].find(')'); if (idx == string::npos || idx2 == string::npos || - ((idx2 - idx) < 2 )){ // no () found + ((idx2 - idx) < 2 )){ + // no () found } + else{ // split string string offset = operand[numOperands-1].substr(0,idx); string regStr = operand[numOperands-1].substr(idx+1, idx2-idx-1); @@ -140,22 +154,22 @@ void ASMParser::getTokens(string line, // ignore anything after the whitespace after the operand - // We could do a further look and generate an error message - // but we'll save that for later. return; } + +// Returns true if s represents a valid decimal integer bool ASMParser::isNumberString(string s) - // Returns true if s represents a valid decimal integer { - int len = s.length(); - if (len == 0) return false; - if ((isSign(s.at(0)) && len > 1) || isDigit(s.at(0))) - { + int len = s.length(); + if (len == 0) return false; + if ((isSign(s.at(0)) && len > 1) || isDigit(s.at(0))) + { + // check remaining characters for (int i=1; i < len; i++) { - if (!isdigit(s.at(i))) return false; + if (!isdigit(s.at(i))) return false; } return true; } @@ -163,8 +177,8 @@ bool ASMParser::isNumberString(string s) } +// Converts a string to an integer. Assumes s is something like "-231" and produces -231 int ASMParser::cvtNumString2Number(string s) - // Converts a string to an integer. Assumes s is something like "-231" and produces -231 { if (!isNumberString(s)) { @@ -192,10 +206,9 @@ int ASMParser::cvtNumString2Number(string s) } -bool ASMParser::getOperands(Instruction &i, Opcode o, - string *operand, int operand_count) - // Given an Opcode, a string representing the operands, and the number of operands, - // breaks operands apart and stores fields into Instruction. +// Given an Opcode, a string representing the operands, and the number of operands, +// breaks operands apart and stores fields into Instruction. +bool ASMParser::getOperands(Instruction &i, Opcode o, string *operand, int operand_count) { if(operand_count != opcodes.numOperands(o)) @@ -231,25 +244,26 @@ bool ASMParser::getOperands(Instruction &i, Opcode o, } if(imm_p != -1){ - if(isNumberString(operand[imm_p])){ // does it have a numeric immediate field? + if(isNumberString(operand[imm_p])){ imm = cvtNumString2Number(operand[imm_p]); if(((abs(imm) & 0xFFFF0000)<<1)) // too big a number to fit return false; } else{ - if(opcodes.isIMMLabel(o)){ // Can the operand be a label? + if(opcodes.isIMMLabel(o)){ + // Debugging // cout<< "check" << endl; - // Assign the immediate field an address - // imm = cvtNumString2Number(operand[imm_p]); - // imm = myLabelAddress; - // cout<< operand[imm_p] < using namespace std; + +// This class sets the name and value of the control line + class ControlLine{ public: // Default constructor, set the value to 0x0, name to "control_line", length to -1 diff --git a/DataMem.cpp b/DataMem.cpp index f041a05..1975217 100644 --- a/DataMem.cpp +++ b/DataMem.cpp @@ -1,9 +1,16 @@ #include "DataMem.h" +/* This class returns the value of the memory address and the data to read/write + * when given an input file + */ + +// Default constructor DataMem::DataMem(){ } + +// Returns the value of the memory address and the data to write string DataMem::inputs(){ stringstream in; in << "Inputs: "; @@ -12,14 +19,20 @@ string DataMem::inputs(){ return in.str(); } + +// Returns the read data in hex string DataMem::outputs(){ return "0x" + readData; } + +// Read corresponding content from address string DataMem::read(string address){ address = remove0x(address); + // testing // cout << address << endl; std::transform(address.begin(), address.end(), address.begin(), ::tolower); + if(data.count(address) == 1){ return data.at(address); }else{ @@ -27,20 +40,23 @@ string DataMem::read(string address){ } } + +// Write content to address void DataMem::write(string address, string content){ address = remove0x(address); std::transform(address.begin(), address.end(), address.begin(), ::tolower); content = remove0x(content); std::transform(content.begin(), content.end(), content.begin(), ::tolower); + if (data.count(address) == 0){ data.insert(std::pair(address, content)); } else { data.at(address) = content; } - } +// Print out the whole data memory string DataMem::toString(){ string s = "\n\n======================================\n"; s += "Data Memmory:\n(All value in hex)\n"; @@ -55,6 +71,8 @@ string DataMem::toString(){ return s; } + +// Method to open the memory_contents_input file void DataMem::readFile(string fileName){ ifstream infile; infile.open(fileName.c_str()); @@ -69,6 +87,7 @@ void DataMem::readFile(string fileName){ getline(infile, line); // Testing infile (Successful!!) // cout< data; + // Method to open the memory_contents_input file void readFile(string filename); // Private helper method to remove (possible) 0x before hex diff --git a/FileReader.cpp b/FileReader.cpp index fecb1a9..a63626a 100644 --- a/FileReader.cpp +++ b/FileReader.cpp @@ -3,7 +3,13 @@ #include // For checking for whitespace #include // For making the hash map of settings -FileReader::FileReader(string filename){ // Create the fstream with the target file (No default constructor) +/* This class reads in a Proj2 Config File from the constructor. + * If the config file is improperly formatted, or the ASM doesn't compile, + * an exception will be thrown. + */ + +// Create the fstream with the target file (No default constructor) +FileReader::FileReader(string filename){ // Debug Line // std::cout << "Filereader started.\n"; @@ -88,34 +94,44 @@ FileReader::FileReader(string filename){ // Create the fstream with the target f // GET SETTING METHODS //=========================================================================================================// +// Returns a string containing the name of the program_input file string FileReader::getInstMem(){ return imem; } +// Returns a string containing the name of the memory_contents_input file string FileReader::getDataMem(){ return dmem; } +// Returns a string containing the name of the register_file_input file string FileReader::getRegFile(){ return regf; } +// Returns a string containing the name of the output_file string FileReader::getOutFile(){ return oputf; } +// Returns the boolean variable representing if the output mode is single +// step or batch. If it is single_step, true is returned, else false is returned bool FileReader::getOutMode(){ return is_single_step; } +// Returns the boolean variable representing if the program is in debug mode bool FileReader::getDebugMode(){ return is_debug; } +// Returns the boolean variable representing if the program prints the +// memory contents bool FileReader::getPrintMem(){ return print_memory; } +// Returns the boolean variable representing if the output is written to the output file bool FileReader::writeToFile(){ return write_to_file; } diff --git a/FileReader.h b/FileReader.h index 060dc87..e8e596b 100644 --- a/FileReader.h +++ b/FileReader.h @@ -10,7 +10,7 @@ using namespace std; /* This class reads in a Proj2 Config File from the constructor. * If the config file is improperly formatted, or the ASM doesn't compile, - * an exception will be thrown. + * an exception will be thrown. */ class FileReader{ @@ -19,8 +19,6 @@ class FileReader{ // May throw an exception FileReader(string filename); - //Do we need to make a deconstructor to close ifstream? - // Returns a string containing the name of the program_input file string getInstMem(); diff --git a/Instruction.cpp b/Instruction.cpp index 3b48aea..1a5a048 100644 --- a/Instruction.cpp +++ b/Instruction.cpp @@ -1,6 +1,9 @@ #include "Instruction.h" - +/* This class provides an internal representation for a MIPS assembly instruction. + * Any of the fields can be queried. Additionally, the class stores a 32 bit binary + * encoding of the MIPS instruction. + */ Instruction::Instruction() { @@ -8,14 +11,16 @@ Instruction::Instruction() myRS = myRT = myRD = NumRegisters; } -Instruction::Instruction(Opcode op, Register rs, Register rt, Register rd, int imm) + // You can specify all the fields to initialize the Instruction +Instruction::Instruction(Opcode op, Register rs, Register rt, Register rd, int imm) { setValues(op, rs, rt, rd, imm); } -void Instruction::setValues(Opcode op, Register rs, Register rt, Register rd, int imm) + // You can specify all the fields to initialize the Instruction +void Instruction::setValues(Opcode op, Register rs, Register rt, Register rd, int imm) { myOpcode = op; @@ -36,13 +41,15 @@ void Instruction::setValues(Opcode op, Register rs, Register rt, Register rd, in myImmediate = imm; + // testing // if(!( (imm & 0xFFFF0000) << 1)) // make sure it has nothing in upper 16 bits // myImmediate = imm; } -string Instruction::getString() -// Returns a string which represents all of the fields + +// Returns a string which represents all of the fields +string Instruction::getString() { stringstream s ; s << "OP: \t" << myOpcode << "\t" << "RD: " << myRD << "\t" << diff --git a/InstructionMem.cpp b/InstructionMem.cpp index fb994bf..b0472e1 100644 --- a/InstructionMem.cpp +++ b/InstructionMem.cpp @@ -1,6 +1,11 @@ #include "InstructionMem.h" // #include "InstrucMem/ASMParser.h" +/* This class will read in the Instruction Memory file and convert them into binary + * line by line. + */ + +// Contructor that build a Instruction memory out of an assembly file InstructionMem::InstructionMem(string program_input){ ASMParser *parser; @@ -32,21 +37,27 @@ InstructionMem::InstructionMem(string program_input){ // memAddress += 4; //incrememnt memAddress by 4 bytes i = parser->getNextInstruction(); } - delete parser; } + + +// Get the binary instruction string InstructionMem::getIns(string insAddress){ currentIn = insAddress; currentOut = ins.at(insAddress); return currentOut; } + +// Get the instruction in assembly language string InstructionMem::getInsMips(string insAddress){ currentIn = insAddress; currentOut = ins.at(insAddress); return insMips.at(insAddress); } + +// Check if there is an instruction at this address bool InstructionMem::hasIns(string insAddress){ if(ins.count(insAddress)){ return true; @@ -54,12 +65,16 @@ bool InstructionMem::hasIns(string insAddress){ return false; } + +// This function returns the string representing the inputs of Instruction Memory string InstructionMem::inputs(){ // stringstream toHex; // toHex << std::hex << currentIn; return currentIn; } + +// Function to print out the whole content of instruction memory string InstructionMem::toString(){ string s = "\n\n======================================\n"; s += "Instruction Memmory:\n(All value in hex)\n"; @@ -80,6 +95,8 @@ string InstructionMem::toString(){ return s; } + +// Helper function that adds an instruction to the corresponding address void InstructionMem::add(string insAddress, Instruction i){ // cout<<"check"< using namespace std; + +/* This class functions as a multiplexer by forwarding two input signals + * into a single line + */ + class MUX{ struct input{ @@ -17,11 +22,18 @@ struct input{ public: MUX(){}; + // testing // void setInput0(int _value); // void setInput1(int _value); + + // Sets the input values for the MUX void setInput0(string _content); void setInput1(string _content); + + // Computes MUX value based on the choice on int or string void compute(int choose); + + // testing // string getStringOutput(); // int getIntOutput(); diff --git a/MainControl.cpp b/MainControl.cpp index c26050b..44db911 100644 --- a/MainControl.cpp +++ b/MainControl.cpp @@ -1,6 +1,10 @@ #include "MainControl.h" +/* This class is the main control unit, which takes a 6-bit opcode as input an + * output 9 control signals each of which is represented as a string. + */ + // Sets up control signal vector MainControl::MainControl(){ signals.resize(10); diff --git a/MainControl.h b/MainControl.h index 3d1250c..4ca3f95 100644 --- a/MainControl.h +++ b/MainControl.h @@ -7,10 +7,13 @@ using namespace std; -// This class is the main control unit, which takes a 6-bit opcode as input and output 9 control signals each of which is represented as a string. +/* This class is the main control unit, which takes a 6-bit opcode as input an + * output 9 control signals each of which is represented as a string. + */ + class MainControl{ public: - + // Sets up control signal vector MainControl(); // Given an opcode input, sets 9 control signals (in hex) as strings diff --git a/Opcode.cpp b/Opcode.cpp index 2d7356e..111073b 100644 --- a/Opcode.cpp +++ b/Opcode.cpp @@ -2,12 +2,16 @@ using namespace std; -OpcodeTable::OpcodeTable() +/* Stores different MIPS instructions into a table containing the instructions' + * opcodes, expected operands, and other fields + */ + // Initializes all the fields for every instruction in Opcode enum +OpcodeTable::OpcodeTable() { myArray[ADD].name = "add"; myArray[ADD].numOps = 3; myArray[ADD].rdPos = 0; myArray[ADD].rsPos = 1; myArray[ADD].rtPos = 2; myArray[ADD].immPos = -1; myArray[ADD].instType = RTYPE; myArray[ADD].op_field = "000000"; myArray[ADD].funct_field = "100000"; - //Your code here + //Supported MIPS instructions myArray[SUB].name = "sub"; myArray[SUB].numOps = 3; myArray[SUB].rdPos = 0; myArray[SUB].rsPos = 1; myArray[SUB].rtPos = 2; myArray[SUB].immPos = -1; myArray[SUB].instType = RTYPE; myArray[SUB].op_field = "000000"; myArray[SUB].funct_field = "100010"; myArray[ADDI].name = "addi"; myArray[ADDI].numOps = 3; myArray[ADDI].rdPos = -1; myArray[ADDI].rsPos = 1; myArray[ADDI].rtPos = 0; myArray[ADDI].immPos = 2; myArray[ADDI].instType = ITYPE; myArray[ADDI].op_field = "001000"; myArray[MULT].name = "mult"; myArray[MULT].numOps = 2; myArray[MULT].rdPos = -1; myArray[MULT].rsPos = 0; myArray[MULT].rtPos = 1; myArray[MULT].immPos = -1; myArray[MULT].instType = RTYPE; myArray[MULT].op_field = "000000"; myArray[MULT].funct_field = "011000"; @@ -21,9 +25,10 @@ OpcodeTable::OpcodeTable() myArray[J].name = "j"; myArray[J].numOps = 1; myArray[J].rdPos = -1; myArray[J].rsPos = -1; myArray[J].rtPos = -1; myArray[J].immPos = 0; myArray[J].immLabel = true; myArray[J].instType = JTYPE; myArray[J].op_field = "000010"; } -Opcode OpcodeTable::getOpcode(string str) + // Given a valid MIPS assembly mnemonic, returns an Opcode which represents a // template for that instruction. +Opcode OpcodeTable::getOpcode(string str) { for(int i = 0; i < (int)UNDEFINED; i++){ if(myArray[i].name == str){ @@ -33,8 +38,9 @@ Opcode OpcodeTable::getOpcode(string str) return UNDEFINED; } -int OpcodeTable::numOperands(Opcode o) + // Given an Opcode, returns number of expected operands. +int OpcodeTable::numOperands(Opcode o) { if(o < 0 || o >= UNDEFINED) return -1; @@ -43,9 +49,9 @@ int OpcodeTable::numOperands(Opcode o) } -int OpcodeTable::RSposition(Opcode o) // Given an Opcode, returns the position of RS field. If field is not // appropriate for this Opcode, returns -1. +int OpcodeTable::RSposition(Opcode o) { if(o < 0 || o >= UNDEFINED) return -1; @@ -53,9 +59,10 @@ int OpcodeTable::RSposition(Opcode o) return myArray[o].rsPos; } -int OpcodeTable::RTposition(Opcode o) + // Given an Opcode, returns the position of RT field. If field is not // appropriate for this Opcode, returns -1. +int OpcodeTable::RTposition(Opcode o) { if(o < 0 || o >= UNDEFINED) return -1; @@ -63,9 +70,10 @@ int OpcodeTable::RTposition(Opcode o) return myArray[o].rtPos; } -int OpcodeTable::RDposition(Opcode o) + // Given an Opcode, returns the position of RD field. If field is not // appropriate for this Opcode, returns -1. +int OpcodeTable::RDposition(Opcode o) { if(o < 0 || o >= UNDEFINED) return -1; @@ -73,9 +81,10 @@ int OpcodeTable::RDposition(Opcode o) return myArray[o].rdPos; } -int OpcodeTable::IMMposition(Opcode o) + // Given an Opcode, returns the position of IMM field. If field is not // appropriate for this Opcode, returns -1. +int OpcodeTable::IMMposition(Opcode o) { if(o < 0 || o >= UNDEFINED) return -1; @@ -83,35 +92,38 @@ int OpcodeTable::IMMposition(Opcode o) return myArray[o].immPos; } -InstType OpcodeTable::getInstType(Opcode o) + // Given an Opcode, returns instruction type. +InstType OpcodeTable::getInstType(Opcode o) { if(o < 0 || o > UNDEFINED) return (InstType)-1; return myArray[o].instType; } -string OpcodeTable::getOpcodeField(Opcode o) + // Given an Opcode, returns a string representing the binary encoding of the opcode // field. +string OpcodeTable::getOpcodeField(Opcode o) { if(o < 0 || o > UNDEFINED) return string(""); return myArray[o].op_field; } -string OpcodeTable::getFunctField(Opcode o) + // Given an Opcode, returns a string representing the binary encoding of the function // field. +string OpcodeTable::getFunctField(Opcode o) { if(o < 0 || o > UNDEFINED) return string(""); return myArray[o].funct_field; } -bool OpcodeTable::isIMMLabel(Opcode o) // Given an Opcode, returns true if instruction expects a label in the instruction. // See "J". +bool OpcodeTable::isIMMLabel(Opcode o) { if(o < 0 || o > UNDEFINED) return false; diff --git a/Opcode.h b/Opcode.h index c0045b4..22b2fac 100644 --- a/Opcode.h +++ b/Opcode.h @@ -7,6 +7,10 @@ using namespace std; +/* Stores different MIPS instructions into a table containing the instructions' + * opcodes, expected operands, and other fields + */ + // Listing of all supported MIPS instructions enum Opcode { ADD, diff --git a/Processor.cpp b/Processor.cpp index 02bc23e..47f94a9 100644 --- a/Processor.cpp +++ b/Processor.cpp @@ -1,5 +1,10 @@ #include "Processor.h" +/* This class connects all separate parts of the processor and inputs all of the values + * found in these separate parts. + */ + +// Construct the Processor with corresponding parameters Processor::Processor(InstructionMem _iMem, DataMem _dMem, Registers _registers, bool _is_single_step, bool _is_debug, bool _print_memory, bool _write_to_file, string _output_file){ // Set up the corresponging parameter is_single_step = _is_single_step; @@ -12,6 +17,8 @@ Processor::Processor(InstructionMem _iMem, DataMem _dMem, Registers _registers, regs = _registers; } + +// The method to run the object by knowing the information in the processor parts. void Processor::run(){ initializeLines(); @@ -34,26 +41,31 @@ void Processor::run(){ } if(is_debug) cout << "ProgramCounter Done" << endl; + // ALU 1 alu1.setInputs(currentInsAddress, "0x4"); alu1.calculate(); if(is_debug) cout << "ALU 1" << endl; + // Instruction memory currentIns = imem.getIns(currentInsAddress); if(is_debug) cout << "Instruction Memory Done" << endl; + // SLTwo 1: slt1.setInput(currentIns.substr(6)); slt1.compute(); // cout << slt1.outputs() << endl; if(is_debug) cout << "Shift Left Two 1 Done" << endl; + // Get control signals from main control mc.setOpcode(currentIns.substr(0,6)); setMainSignals(mc.getControlSignals()); if(is_debug) cout << "Main Control Done" << endl; + // Mux 1: mux1.setInput0(currentIns.substr(11,5)); // cout << "CHECK HERE " < list){ regDst.setValue(list.at(0)); @@ -251,6 +277,7 @@ void Processor::setMainSignals(vector list){ regWrite.setValue(list.at(9)); } + // Out put control lines value void Processor::linesOutput(){ ss << "\n==========================\n"; @@ -269,6 +296,7 @@ void Processor::linesOutput(){ ss << zeroLine.getName() << " : " << zeroLine.getValue() << "\n\n"; } + // INput and output for each unit void Processor::unitOutput(){ ss << "==========================\n"; @@ -292,6 +320,7 @@ void Processor::unitOutput(){ ss << "Mux 3:\n" << mux3.inputs() << '\n' << "Output: "<< mux3.outputs() << "\n\n"; } + // Output all the memory content void Processor::dataOutput(){ ss << "==========================\n"; @@ -301,6 +330,7 @@ void Processor::dataOutput(){ ss << regs.toString(); } + // Actually print out or write to file void Processor::printOut(){ if(write_to_file){ diff --git a/Processor.h b/Processor.h index 2a52892..98e652b 100644 --- a/Processor.h +++ b/Processor.h @@ -20,17 +20,21 @@ #include "MainControl.h" #include "ALUControl.h" #include "SignExtend.h" -// TODO include more classes/hearders files using namespace std; + +/* This class connects all separate parts of the processor and inputs all of the values + * found in these separate parts. + */ + class Processor{ public: Processor(){}; - // Construct the Processor with correspondign parameters + // Construct the Processor with corresponding parameters Processor(InstructionMem _iMem, DataMem _dMem, Registers _registers, bool _is_single_step, bool _is_debug, bool _print_memory, bool _write_to_file, string _output_file); - // The method to run the object by knowing the information in the prantecies. + // The method to run the object by knowing the information in the processor parts. void run(); private: diff --git a/ProgramCounter.cpp b/ProgramCounter.cpp index 3a56e0b..8ae4277 100644 --- a/ProgramCounter.cpp +++ b/ProgramCounter.cpp @@ -1,5 +1,7 @@ #include "ProgramCounter.h" +// This class sets the program counter for the processor + ProgramCounter::ProgramCounter(){ cr = "0x40000"; } diff --git a/ProgramCounter.h b/ProgramCounter.h index 0b6a2ee..bf4989e 100644 --- a/ProgramCounter.h +++ b/ProgramCounter.h @@ -5,6 +5,8 @@ using namespace std; +// This class sets the program counter for the processor + class ProgramCounter{ public: diff --git a/RegisterTable.cpp b/RegisterTable.cpp index 6a4bbb2..7044131 100644 --- a/RegisterTable.cpp +++ b/RegisterTable.cpp @@ -1,5 +1,8 @@ #include "RegisterTable.h" +/* This class stores information about the valid register names for MIPS. + */ + RegisterTable::RegisterTable() { int i = 0; @@ -83,9 +86,10 @@ RegisterTable::RegisterTable() } + +// Given a string representing a MIPS register operand, returns the number associated +// with that register. If string is not a valid register, returns NumRegisters. Register RegisterTable::getNum(string reg) - // Given a string representing a MIPS register operand, returns the number associated - // with that register. If string is not a valid register, returns NumRegisters. { for(int i = 0; i < 2*NumRegisters; i++){ if(myRegisters[i].name == reg){ diff --git a/Registers.cpp b/Registers.cpp index 5690f37..6afc4c0 100644 --- a/Registers.cpp +++ b/Registers.cpp @@ -1,9 +1,15 @@ #include "Registers.h" +/* This class returns registers read in and their values + */ + +// Default constructor Registers::Registers(){ } + +// Reading process void Registers::read(){ if (readReg1 > -1 && readReg1 < 32){ readData1 = get(readReg1); @@ -13,6 +19,8 @@ void Registers::read(){ } } + +// Writing process void Registers::write(){ if (regWrite == "0x1"){ if (writeReg > -1 && writeReg < 32){ @@ -21,6 +29,8 @@ void Registers::write(){ } } + +// Presenting inputs string Registers::inputs(){ stringstream ss; ss << "Inputs: "; @@ -32,6 +42,8 @@ string Registers::inputs(){ return ss.str(); } + +// Presenting outputs string Registers::outputs(){ stringstream ss; ss << "Outputs: "; @@ -40,6 +52,8 @@ string Registers::outputs(){ return ss.str(); } + +// Returns register number string Registers::get(int num){ if(num>-1 || num<32){ return regs[num]; @@ -48,6 +62,8 @@ string Registers::get(int num){ } } + +// Sets register number void Registers::set(int num, string value){ if(num>-1 || num<32){ value = remove0x(value); @@ -58,6 +74,8 @@ void Registers::set(int num, string value){ } } + +// Prints out the registers string Registers::toString(){ string s = "\n\n======================================\n"; s += "Registers:\n(All value in hex)\n"; @@ -68,6 +86,8 @@ string Registers::toString(){ // cout<<(sizeof(regs)/sizeof(*regs))< #include #include -// #include // Pointless to use this data structure, basic array would work + +/* This class returns registers read in and their values + */ using namespace std; @@ -52,9 +54,9 @@ class Registers{ // Hashmap to represent the registers string regs[32]; - // These two should go into private but for the testing sake, i just leave them here for now + // Returns register number string get(int num); - + // Sets register number void set(int num, string value); // Initialize registers from a file diff --git a/SLTwo.cpp b/SLTwo.cpp index d1b671b..3e139cc 100644 --- a/SLTwo.cpp +++ b/SLTwo.cpp @@ -1,5 +1,9 @@ #include "SLTwo.h" +/* This class shifts the bits of a given number two to the left + */ + +// Shifts the number left by two void SLTwo::compute(){ output = input + "00"; if (output.size() > 32){ diff --git a/SLTwo.h b/SLTwo.h index cf1513d..23eaa32 100644 --- a/SLTwo.h +++ b/SLTwo.h @@ -3,12 +3,18 @@ #include using namespace std; + +/* This class shifts the bits of a given number two to the left + */ + class SLTwo{ public: SLTwo(){}; void setInput(string s){input = s;}; + // Shifts the number left by two void compute(); + string inputs(){return input;}; string outputs(){return output;}; diff --git a/SignExtend.cpp b/SignExtend.cpp index f243f14..9cc63b4 100644 --- a/SignExtend.cpp +++ b/SignExtend.cpp @@ -1,9 +1,16 @@ #include "SignExtend.h" +/* This class extends the number of bits in a binary number while preserving the + * number's positive/negative sign and value + */ + +// Sets the input given a string of binary numbers void SignExtend::setInput(string s){ input = s; } + +// Computes the sign extension of the given input void SignExtend::compute(){ char sign = input[0]; output = input; diff --git a/SignExtend.h b/SignExtend.h index e7decb7..572171d 100644 --- a/SignExtend.h +++ b/SignExtend.h @@ -4,10 +4,19 @@ // #include using namespace std; + +/* This class extends the number of bits in a binary number while preserving the + * number's positive/negative sign and value + */ + class SignExtend{ public: SignExtend(){}; + + // Sets the input given a string of binary numbers void setInput(string s); + + // Computes the sign extension of the given input void compute(); string inputs(){return input;}; diff --git a/main.cpp b/main.cpp index 3f0bb71..391bed2 100644 --- a/main.cpp +++ b/main.cpp @@ -5,13 +5,12 @@ #include "Registers.h" #include "Processor.h" -// TODO : Keep adding header file connecting with the first layer. - using namespace std; /* This program runs by creating FileReader to read in the config file and * constructing a processor and run it. */ + int main(int argc, char *argv[]){ // Debugging makefile @@ -26,34 +25,42 @@ int main(int argc, char *argv[]){ if (fr->getDebugMode()){ cout << "Instruction Mem Start.\n"; } + // Build the Instruction Memory InstructionMem imem(fr->getInstMem()); if (fr->getDebugMode()){ cout << "Instruction Mem Done.\n"; } + // Build the Data Mem if (fr->getDebugMode()){ cout << "Data Mem Start.\n"; } + DataMem dmem(fr->getDataMem()); if (fr->getDebugMode()){ cout << "Data Mem Done.\n"; } + // Build Registers if (fr->getDebugMode()){ cout << "Registers Start.\n"; } + Registers regs(fr->getRegFile()); if (fr->getDebugMode()){ cout << "Registers Done.\n"; } + // Debugging // cout << imem.toString() << dmem.toString() << regs.toString(); + // Build Processor if (fr->getDebugMode()){ cout << "Processor Setup start\n"; } Processor p(imem, dmem, regs, fr->getOutMode(), fr->getDebugMode(), fr->getPrintMem(), fr->writeToFile(), fr->getOutFile()); + if (fr->getDebugMode()){ cout << "Processor Setup Done\n"; cout << "All files check out, ready to run\n\n";