Exemple #1
0
class Processor:

    NUMBER_OF_REGISTERS = 8

    def __init__(self, data_store, instruction_store, start_address, number_of_ways, reservation_stations_types, reservation_station_cycles, reorder_buffer_size):
        self.data_store = data_store
        self.instruction_store = instruction_store
        self.cycles = 0
        self.stopped = False
        self.register_file = RegisterFile(self.NUMBER_OF_REGISTERS)
        self.pc = start_address
        self.start_address = start_address
        self.instructions_count = 0
        self.number_of_ways = number_of_ways
        self.register_stat = RegisterStat(self.NUMBER_OF_REGISTERS)
        self.reorder_buffer = ReorderBuffer(reorder_buffer_size)
        self.reservation_stations = ReservationStations(reservation_stations_types, reservation_station_cycles, self.reorder_buffer, self)
        self.read_more_instructions = True
        self.mispredictions = 0
        self.predections = 0

    def progress(self):
        #pdb.set_trace()
        if self.stopped: return False
        self.cycles += 1
        common_data_bus_empty = True
        can_commit = True
        any_change = False
        # Update Reservation Stations
        for i in self.reservation_stations.entries.keys():
            for j in range(len(self.reservation_stations.entries[i])):
                reservation_station = self.reservation_stations.entries[i][j]
                if reservation_station.busy:
                    any_change = True
                    if reservation_station.progress == InstructionProgress.issue:
                        if reservation_station.type_ in [ FunctionalUnit.load, FunctionalUnit.store ]:
                            if reservation_station.qj == -1: # Ready to calculate address
                                reservation_station.address += reservation_station.vj
                                reservation_station.progress = InstructionProgress.execute
                                reservation_station.start()
                        elif reservation_station.operation in [InstructionType.return_, InstructionType.jump_and_link ]:
                            if reservation_station.qj == -1: # Ready to calculate address
                                reservation_station.address = reservation_station.vj
                                reservation_station.progress = InstructionProgress.execute
                                reservation_station.start()
                        elif reservation_station.operation == InstructionType.jump:
                            if reservation_station.qj == -1: # Ready to calculate address
                                reservation_station.address += reservation_station.pc + reservation_station.vj + 2
                                reservation_station.progress = InstructionProgress.execute
                                reservation_station.start()
                        elif reservation_station.qj == -1 and reservation_station.qk == -1:
                            if reservation_station.operation == InstructionType.branch_if_equal:
                                self.predections += 1
                                if reservation_station.address < 0:
                                    reservation_station.predicted_taken = True
                                    self.reorder_buffer.clear_after((reservation_station.get_reorder_buffer().get_id() + 1) % self.reorder_buffer.get_size())
                                    self.set_pc(self.pc + 2 + reservation_station.address)
                                else:
                                    reservation_station.predicted_taken = False
                            reservation_station.progress = InstructionProgress.execute
                            reservation_station.start()
                            reservation_station.progress_single_cycle()
                    elif reservation_station.progress == InstructionProgress.execute:
                        reservation_station.progress_single_cycle()
                        if reservation_station.finished():
                            reservation_station.execute()
                            reservation_station.progress = InstructionProgress.write
                            if reservation_station.operation == InstructionType.branch_if_equal:
                                if reservation_station.result == 0 ^ reservation_station.predicted_taken:
                                    self.inc_mispredictions()
                                    self.reorder_buffer.clear_after(reservation_station.get_reorder_buffer().get_id())
                                    self.set_pc(reservation_station.pc + 2)
                                else:
                                    reservation_station.get_reorder_buffer().clear()
                                    reservation_station.clear()
                    elif reservation_station.progress == InstructionProgress.write:
                        if common_data_bus_empty:
                            common_data_bus_empty = False
                            b = reservation_station.get_reorder_buffer().get_id()
                            for q in self.reservation_stations.entries.keys():
                                for w in range(len(self.reservation_stations.entries[q])):
                                    tmp = self.reservation_stations.entries[q][w]
                                    if tmp.qj == b:
                                        tmp.vj = reservation_station.result
                                        tmp.qj = -1
                            for q in self.reservation_stations.entries.keys():
                                for w in range(len(self.reservation_stations.entries[q])):
                                    tmp = self.reservation_stations.entries[q][w]
                                    if tmp.qk == b:
                                        tmp.vk = reservation_station.result
                                        tmp.qk = -1
                            rob = reservation_station.get_reorder_buffer()
                            rob.value = reservation_station.result
                            rob.set_ready(True)
                            if self.reorder_buffer.get_head() is reservation_station.get_reorder_buffer():
                                can_commit = False
                            reservation_station.clear()

        if self.reorder_buffer.get_head().is_ready() and can_commit:
            any_change = True
            rob = self.reorder_buffer.get_head()
            d = rob.dest
            self.register_file.set(d, rob.value)
            rob.clear()
            if self.register_stat.get(d) == rob.get_id():
                self.register_stat.clear(d)
            self.reorder_buffer.inc_head()
        
        #pdb.set_trace()
        # Issue new instructions
        if self.read_more_instructions:
            any_change = True
            for i in range(self.number_of_ways):
                inst = self.instruction_store.get_address(self.pc)[1]
                instruction = InstructionParser.parse(inst)
                if instruction.type_ == InstructionType.halt:
                    self.read_more_instructions = False
                    break
                if self.can_issue(instruction):
                    self.instructions_count += 1
                    print "\nIssuing : " + inst
                    self.issue(instruction)
                    self.pc += 2
                else:
                    break

        print "\nReservation Stations :"
        print self.reservation_stations

        print "Reorder Buffers :"
        print self.reorder_buffer

        print "\nRegister Status :"
        print self.register_stat


        if not any_change:
            self.stopped = True
            print ""
            print "Data Cache : "
            self.data_store.print_logs(0)
            print ""
            print "Instructions Count : " + str(self.instructions_count)
            print ""
            print "Number of mispredictions : " + str(self.mispredictions)
            print ""
            print "Number of predictions : " + str(self.predections)
        

    def execute_all(self): 
        while self.progress() != False:
            pass

    def can_issue(self, instruction):
        return self.reservation_stations.can_hold(self.get_functional_unit(instruction)) and not self.reorder_buffer.is_full()

    def issue(self, instruction):
        functional_unit = self.get_functional_unit(instruction)
        current_rob = self.reorder_buffer.get_current_empty()
        current_reservation_station = self.reservation_stations.get(functional_unit)
        if self.register_stat.busy(instruction.rs):
            h = self.register_stat.get(instruction.rs)
            if self.reorder_buffer.get(h).is_ready():
                current_reservation_station.vj = self.reorder_buffer.get(h).value
                current_reservation_station.qj = -1
            else:
                current_reservation_station.qj = h
        else:
            current_reservation_station.vj = self.register_file.get(instruction.rs)
            current_reservation_station.qj = -1

        current_reservation_station.set_busy(True)
        current_reservation_station.dest = current_rob.get_id()
        current_reservation_station.operation = instruction.type_
        current_reservation_station.pc = self.get_pc()
        current_rob.type_ = functional_unit
        current_rob.dest = instruction.rd
        current_rob.set_ready(False)
        current_rob.set_empty(False)
        current_rob.reservation_station = current_reservation_station

        if functional_unit in [ FunctionalUnit.add, FunctionalUnit.mult, FunctionalUnit.logical, FunctionalUnit.store ] or instruction.type_ == InstructionType.jump_and_link:
            if current_reservation_station.operation == InstructionType.add_immediate:
                current_reservation_station.vk = instruction.imm
                current_reservation_station.qk = -1
            elif current_reservation_station.operation == InstructionType.branch_if_equal:
                current_reservation_station.address = instruction.imm
            else:
                if self.register_stat.busy(instruction.rt):
                    h = self.register_stat.get(instruction.rt)
                    if self.reorder_buffer.get(h).is_ready():
                        current_reservation_station.vk = self.reorder_buffer.get(h).value
                        current_reservation_station.qk = -1
                    else:
                        current_reservation_station.qk = h
                else:
                    current_reservation_station.vk = self.register_file.get(instruction.rt)
                    current_reservation_station.qk = -1

        if functional_unit in [ FunctionalUnit.load ] :
            current_reservation_station.address = instruction.imm
            self.register_stat.set(instruction.rd, current_rob.get_id())
        elif functional_unit in [ FunctionalUnit.store ]:
            current_reservation_station.address = instruction.imm
        elif functional_unit in [ FunctionalUnit.branches ]:
            if instruction.type_ == InstructionType.jump:
                current_reservation_station.address = instruction.imm
        elif functional_unit in [ FunctionalUnit.add, FunctionalUnit.mult, FunctionalUnit.logical ] and current_reservation_station.operation != InstructionType.branch_if_equal:
            self.register_stat.set(instruction.rd, current_rob.get_id())

        current_reservation_station.progress = InstructionProgress.issue

    def execute_instruction(self, instruction):
        if instruction.type_ == InstructionType.store: self.store(instruction.reg_a, instruction.reg_b, instruction.imm)
        if instruction.type_ == InstructionType.jump: self.jump(instruction.reg_a, instruction.imm)
        if instruction.type_ == InstructionType.branch_if_equal: self.branch_if_equal(instruction.reg_a, instruction.reg_b, instruction.imm)
        if instruction.type_ == InstructionType.jump_and_link: self.jump_and_link(instruction.reg_a, instruction.reg_b)
        if instruction.type_ == InstructionType.return_: self.return_(instruction.reg_a)

    def get_functional_unit(self, instruction):
        if instruction.type_ == InstructionType.load : return FunctionalUnit.load
        if instruction.type_ == InstructionType.store: return FunctionalUnit.store
        if instruction.type_ == InstructionType.jump: return FunctionalUnit.branches
        if instruction.type_ == InstructionType.branch_if_equal: return FunctionalUnit.add
        if instruction.type_ == InstructionType.jump_and_link: return FunctionalUnit.branches
        if instruction.type_ == InstructionType.return_: return FunctionalUnit.branches
        if instruction.type_ == InstructionType.add: return FunctionalUnit.add
        if instruction.type_ == InstructionType.subtract: return FunctionalUnit.add
        if instruction.type_ == InstructionType.add_immediate: return FunctionalUnit.add
        if instruction.type_ == InstructionType.nand: return FunctionalUnit.logical
        if instruction.type_ == InstructionType.multiply: return FunctionalUnit.mult
        if instruction.type_ == InstructionType.halt: return FunctionalUnit.halt

    def store(self, source, base_address_register, offset):
        base_address = self.register_file.get(base_address_register)
        s = self.register_file.get(source)
        latency = self.data_store.write_in_address(base_address + offset, s)
        self.busy_for += latency

    def jump(self, base_address_register, offset):
        base_address = self.register_file.get(base_address_register)
        self.pc = self.pc + base_address + offset

    def branch_if_equal(self, source1, source2, address):
        s1 = self.register_file.get(source1)
        s2 = self.register_file.get(source2)
        if s1 == s2:
            self.pc = self.pc + address

    def jump_and_link(self, store_register, address_register):
        self.register_file.set(store_register, self.pc)
        s1 = self.register_file.get(address_register)
        self.pc = s1

    def return_(self, source):
        self.pc = self.register_file.get(source)

    def get_instruction_number(self):
        return (self.pc - self.start_address) / 2

    def get_pc(self):
        return self.pc

    def set_pc(self, value):
        self.pc = value

    def inc_mispredictions(self):
        self.mispredictions += 1