class PipelineInterface(object): def __init__(self, instruction_list, starting_pc_address, register_memory, data_mem): """ Creates the interface to the pipeline. :param instruction_list: list of Instruction objects in the order they should appear in instruction memory :param starting_pc_address: integer starting address for the program counter. This will also be the base address of instruction memory :param register_memory: list representing register memory, since the registers are just reg0,reg1, etc :param data_mem: dictionary representing data memory """ self.fetch = Fetch(instruction_list, starting_pc_address) self.write_back = WriteBack(fetch_stage=self.fetch) self.memory = Memory(data_mem, self.write_back) self.execute = Execute(self.memory) self.decode = Decode(register_memory, self.execute) self.write_back.decode_stage = self.decode def trigger_clock_cycle(self): """ For single-cycle, we really only do something useful in the fetch.on_rising_clock. It will call a method of the next stage that will do what that stage needs to and then call the next stage, etc In pipelined execution, these would be used because Fetch would fetch the instruction, place it in the intermediate register, and then return back to here, where decode.on_rising_clock would be called. :return: """ self.fetch.on_rising_clock(self.decode) self.decode.on_rising_clock() self.execute.on_rising_clock() self.memory.on_rising_clock() self.write_back.on_rising_clock() def retrieve_register_list(self): """ Helper method to return the current register file for comparing that the instruction was written back successfully :return: list representing register file """ return self.decode.register_file def retrieve_data_memory(self): """ Helper method to return the current data memory dictionary to help ensure that the data was written to the correct place :return: memory dictionary """ return self.memory.memory def retrieve_current_pc_address(self): """ Helper method to retrieve the current value of the program counter from the fetch stage. :return: int (probably) """ return self.fetch.program_counter def retrive_instruction_name(self): return self.decode.instruction.asm_version()
def __init__(self, instruction_list, starting_pc_address, register_memory, data_mem): """ Creates the interface to the pipeline. :param instruction_list: list of Instruction objects in the order they should appear in instruction memory :param starting_pc_address: integer starting address for the program counter. This will also be the base address of instruction memory :param register_memory: list representing register memory, since the registers are just reg0,reg1, etc :param data_mem: dictionary representing data memory """ self.fetch = Fetch(instruction_list, starting_pc_address) self.write_back = WriteBack(fetch_stage=self.fetch) self.memory = Memory(data_mem, self.write_back) self.execute = Execute(self.memory) self.decode = Decode(register_memory, self.execute) self.write_back.decode_stage = self.decode
def test_receive_values_and_update_addi(self): execute = Execute() expected_result = create_sized_binary_num( decode_signed_binary_number(ExecuteStageTest.data1, 32) + decode_signed_binary_number(ExecuteStageTest.immediate, 32), 32)[:32] ALUOp = 0b11 function_field = '100000' opcode = create_sized_binary_num(8, 6) ALUSrc = True 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_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 test_create_execute_object_default_values(self): execute = Execute() self.assertEqual(None, execute.ALUOp) self.assertEqual(None, execute.ALUSrc) self.assertEqual(None, execute.function_code) self.assertEqual(None, execute.opcode) self.assertEqual(None, execute.immediate) self.assertEqual(None, execute.read_data1) self.assertEqual(None, execute.read_data2) self.assertEqual(None, execute.operation) self.assertEqual(False, execute.branch_equal) self.assertEqual(False, execute.branch_not_equal) self.assertEqual(None, execute.alu_input_1) self.assertEqual(None, execute.alu_input_2) self.assertEqual(None, execute.alu_output) self.assertEqual(None, execute.alu_branch)
def test_slt_set(self): execute = Execute() expected_result = create_sized_binary_num(1, 32)[:32] ALUOp = 0b10 function_field = create_sized_binary_num(42, 6) opcode = None ALUSrc = False MemWrite = False MemtoReg = False MemRead = False Branch = False jump = False jump_address = None execute.receive_data(ExecuteStageTest.data2, ExecuteStageTest.data1, 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)