def test_branch_if_not_equal_true(self): execute = Execute() alu_branch_output = True branch_address = create_sized_binary_num( ExecuteStageTest.pc_value + (decode_signed_binary_number(ExecuteStageTest.immediate, 32) << 2), 32)[:32] ALUOp = 0b01 function_field = create_sized_binary_num(4, 6) opcode = '000101' ALUSrc = False MemWrite = False MemtoReg = False MemRead = False Branch = True jump = False jump_address = None execute.receive_data(ExecuteStageTest.data1, ExecuteStageTest.data2, ExecuteStageTest.immediate, ExecuteStageTest.pc_value, jump_address) execute.receive_control_information(ALUOp, function_field, opcode, ALUSrc, MemWrite, MemtoReg, MemRead, Branch, jump) self.assertEqual(alu_branch_output, execute.alu_branch) self.assertEqual(branch_address, execute.branch_address)
def set_alu_inputs(self): """ Sets the values of the two data inputs into the ALU. alu_input_1 will always be the data read from the first register in the register file, and alu_input_2 will either be the data from the second register, or the immediate, depending on the value of ALUSrc. :return: None """ if len(self.read_data1) != 32: raise Exception("(Execute): data from register 1 isn't 32 bits1") self.alu_input_1 = decode_signed_binary_number(self.read_data1, 32) # expecting 32 bit values! if self.ALUSrc: self.alu_input_2 = decode_signed_binary_number(self.immediate, 32) else: self.alu_input_2 = decode_signed_binary_number(self.read_data2, 32)
def calculate_jump_address(self): """ This happens in the decode stage, and is done by shifting the bottom 26 bits of the instruction (address) left 2 and then concatenating the top four bits of the program counter to this to create a 32 bit address to go to :return: None """ address = create_sized_binary_num(decode_signed_binary_number((self.instruction.binary_version()[6:]), 26) << 2, 28) # shift bottom 26 bits left by two self.jump_address = create_sized_binary_num(self._program_counter_value, 32)[0:4] + address # May not be right maths
def sign_extend_immediate_field(self): """ Sign extend the immediate field from 16 bits to 32 bits :return: """ if self.instruction.immediate: self.sign_extended_immediate = create_sized_binary_num( decode_signed_binary_number(self.instruction.immediate, 16), 32)
def process_memory_request(self): if self.MemRead: if decode_signed_binary_number(self.alu_result, 32) > 511: raise Exception("(Memory): Error! Trying to read data from memory with an invalid address! (%s)", self.alu_result) else: self.read_data = self.memory[self.alu_result] elif self.MemWrite: if decode_signed_binary_number(self.alu_result, 32) > 511: raise Exception("(Memory): Error! Trying to write data from memory with an invalid address! (%s)", self.alu_result) elif len(self.alu_result) != 32: raise Exception("(Memory): Error! attemping to write non-32 bit value to memory!") else: self.memory[self.alu_result] = self.write_data elif self.MemtoReg: raise Exception("(Memory): Error! MemtoReg is high, but memory isn't being read")
def update_program_counter(self, new_address): """ Updates the program counter to the new address :param new_address: new value of the program counter (STRING) :return: """ if isinstance(new_address, str): new_address = decode_signed_binary_number(new_address, 32) if new_address % 4 != 0: # Have to use whole word addressing. Sorry raise Exception("Invalid Program Counter Value!") else: self.program_counter = new_address
def calculate_branch_address(self): """ Calculate the address the branch would take if we do branch :return: None """ if self.immediate: self.branch_address = create_sized_binary_num(self._program_counter_value + (decode_signed_binary_number(self.immediate, 32) << 2), 32) if len(self.branch_address) > 32: self.branch_address = self.branch_address[:32] elif self.branch_equal or self.branch_not_equal: raise Exception("(Execute): Attempted to branch without a value in the immediate field.")
def process_alu_control(self): """ Method to process the ALU control information and set the corresponding operation for the ALU to perform. :return: None """ if self.ALUOp == 0b00: # LW/SW self.operation = 0b0010 # add elif self.ALUOp == 0b01: # branch self.operation = 0b0110 # subtract if decode_signed_binary_number(self.opcode, 6) == 4: # branch if equal self.branch_equal = True elif decode_signed_binary_number(self.opcode, 6) == 5: # branch if not equal self.branch_not_equal = True elif decode_signed_binary_number(self.opcode, 6) == 2: # jump self.branch_equal = False self.branch_not_equal = False else: raise Exception("(Execute): " "Invalid ALUOp and opcode combination! (branching ALUOp, but opcode != beq or bne") elif self.ALUOp == 0b10: # r-type instruction funct_int = decode_signed_binary_number(self.function_code, 6, True) if funct_int == 32: # addition self.operation = 0b0010 elif funct_int == 36: # logical AND self.operation = 0b0000 elif funct_int == 26: # division self.operation = 0b0011 elif funct_int == 37: # logical OR self.operation = 0b0001 elif funct_int == 24: # multiplication self.operation = 0b0100 elif funct_int == 42: # set on less than self.operation = 0b0111 elif funct_int == 34: # subtraction self.operation = 0b0110 elif funct_int == 38: # exclusive OR self.operation = 0b1000 else: raise Exception("(Execute): Invalid ALUOp and function field! " "(Couldn't decode correct ALU function from funct field!)") elif self.ALUOp == 0b11: # immediate function.. if decode_signed_binary_number(self.opcode, 6, True) == 8: # ADD Immediate self.operation = 0b0010 elif decode_signed_binary_number(self.opcode, 6, True) == 12: # AND Immediate self.operation = 0b0000 else: raise Exception("(Execute): Error! Invalid immediate function and opcode combination!") else: raise Exception("(Execute): Invalid ALUOp!")
def test_receive_values_and_update_add(self): execute = Execute() expected_result = create_sized_binary_num( decode_signed_binary_number(ExecuteStageTest.data1, 32) + decode_signed_binary_number(ExecuteStageTest.data2, 32), 32)[:32] ALUOp = 0b10 function_field = '100000' opcode = None ALUSrc = False MemWrite = False MemtoReg = False MemRead = False Branch = False jump = False jump_address = None execute.receive_data(ExecuteStageTest.data1, ExecuteStageTest.data2, ExecuteStageTest.immediate, ExecuteStageTest.pc_value, jump_address) execute.receive_control_information(ALUOp, function_field, opcode, ALUSrc, MemWrite, MemtoReg, MemRead, Branch, jump) self.assertEqual(expected_result, execute.alu_output)
def test_signed_binary_conversion(self): num1 = create_sized_binary_num(-12, 8) num2 = create_sized_binary_num(-24, 8) num3 = create_sized_binary_num(-1, 8) num4 = create_sized_binary_num(0, 8) num5 = create_sized_binary_num(-2, 8) num6 = create_sized_binary_num(4, 8) self.assertEqual('11110100', num1) self.assertEqual('11101000', num2) self.assertEqual('11111111', num3) self.assertEqual('00000000', num4) self.assertEqual('11111110', num5) self.assertEqual('00000100', num6) self.assertEqual(-12, decode_signed_binary_number(num1, 8)) self.assertEqual(-24, decode_signed_binary_number(num2, 8)) self.assertEqual(-1, decode_signed_binary_number(num3, 8)) self.assertEqual(0, decode_signed_binary_number(num4, 8)) self.assertEqual(-2, decode_signed_binary_number(num5, 8)) self.assertEqual(4, decode_signed_binary_number(num6, 8))
print( "-----------------------------------------------------------------------\n\n" ) results = python_test_program() print( "-----------------------------------------------------------------------") print("Test completed, comparing values.\n") current_reg_memory = interface.retrieve_register_list() current_data_memory = interface.retrieve_data_memory() print("-reg-|-Expected--|-----Actual--") print(" v0 |-----" + str(results[1]) + "-----|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('v0')], 32))) print(" v1 |-----" + str(results[2]) + "--|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('v1')], 32))) print(" s2 |-----" + str(results[3]) + "---|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('s2')], 32))) print(" s3 |-----" + str(results[4]) + "--|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('s3')], 32))) print(" t0 |-----" + str(results[5]) + "---|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('t0')], 32))) print(" a0 |-----" + str(results[6]) + "----|-----" + str( decode_signed_binary_number(current_reg_memory[decode_asm_register('a0')], 32)))