示例#1
0
class CPU:

    def __init__(self, hilillos_to_run, quantum):

        self.__pcb = PCBDataStructure()
        self.threads_barrier = Barrier(2)
        self.__dead_barrier = False
        self.__killing_lock = Lock()  # Lock used to kill the barrier
        self.__waiting_lock = Lock()
        self.__system_main_memory = MainMemory(self.__pcb, hilillos_to_run)
        self.__simulation_statistics = SimulationStatistics()
        self.__core0 = Core(0, self)
        self.__core1 = Core(1, self)
        self.__core_count = 2
        self.running_cores = 2
        self.__system_clock = 0
        self.__default_quantum = quantum
        self.__core_finished = False
        self.__core_finished_counter = 0

        # Data buss, instruction buss, cache 0, cache 1
        self.__locks = [Lock(), Lock(), Lock(), Lock()]
        self.__lock_owner = [-1, -1, -1, -1]

    # Starts the cores for the simulation and prints statistics after the cores are finished
    def start_cores(self):
        self.__core1.start()
        if self.__core_count > 1:
            self.__core0.start()
        thread = Thread(target=self.print_statistics(), args=())
        thread.start()

    # Print the statistics
    def print_statistics(self):
        self.__core0.join()
        self.__core1.join()
        self.__simulation_statistics.add_cache(0, self.__core0.get_data_cache())
        self.__simulation_statistics.add_cache(1, self.__core1.get_data_cache())
        self.__simulation_statistics.add_data_memory(self.__system_main_memory.get_data_memory())
        self.__simulation_statistics.print_statistics()
        print("Simulation Finished")

    # Method to use the barrier
    def wait(self):
        if self.__core_count > 1:
            if not self.__core_finished:
                try:
                    barrier_thread_id = self.threads_barrier.wait()
                    if barrier_thread_id == 0:
                        self.__system_clock += 1
                        print("Ciclo de reloj: " + str(self.__system_clock))
                except:
                    self.__system_clock += 1
                    print("Ciclo de reloj: " + str(self.__system_clock))
            else:
                self.__system_clock += 1
                print("Ciclo de reloj: " + str(self.__system_clock))
                if self.__core_finished_counter == 2:
                    self.__simulation_statistics.add_data_memory(self.__system_main_memory.get_data_memory())

    # Method to kill the barrier
    def kill_barrier(self):
        self.__killing_lock.acquire(True)
        if not self.__dead_barrier:
            self.threads_barrier.abort()
            self.__dead_barrier = True
        self.__killing_lock.release()

    # Method to acquire specific lock
    def acquire__lock(self, lock_index, core_id):
        if self.__locks[lock_index].acquire(False):
            self.__lock_owner[lock_index] = core_id
            return True
        return False

    # Method to release specific lock
    def release_lock(self, lock_index):
        self.__lock_owner[lock_index] = -1
        self.__locks[lock_index].release()

    # Method to release all the locks acquired by the core
    def release_locks(self, core_id):
        for index in range(0, 4):
            if self.__lock_owner[index] == core_id:
                self.__locks[index].release()
                self.__lock_owner[index] = -1

    # Method to get the PCB structure
    def get_pcb_ds(self):
        return self.__pcb

    # Method to get the main memory
    def get_main_memory(self):
        return self.__system_main_memory

    # Method to invalidate
    # Receives the number of the core (0 or 1), and the memory_address of the block to change,
    # and the new state of that block
    def change_state_of_block_on_core_cache(self, core, memory_address, new_state):
        if core == 0:
            self.__core0.change_cache_block_state(memory_address, new_state)
        else:
            self.__core1.change_cache_block_state(memory_address, new_state)

    # Return if the memory address its on the other core cache
    def get_if_mem_address_is_on_core_cache(self, core, memory_address):
        if core == 0 or self.__core_count <= 1:
            return self.__core0.get_if_mem_address_is_on_self_cache(memory_address)
        else:
            return self.__core1.get_if_mem_address_is_on_self_cache(memory_address)

    # Return the state of the memory address block on the core cache
    def get_state_of_mem_address_on_core(self, core, memory_address):
        if core == 0 or self.__core_count <= 1:
            return self.__core0.get_memory_address_state_on_cache(memory_address)
        else:
            return self.__core1.get_memory_address_state_on_cache(memory_address)

    # Method to store the cache block of the core on the main memory
    def store_data_cache_block_on_mm_on_core(self, memory_address, cache_block_new_state, core):
        if core == 0 or self.__core_count <= 1:
            return self.__core0.store_data_cache_block_on_main_mem(memory_address, cache_block_new_state)
        else:
            return self.__core1.store_data_cache_block_on_main_mem(memory_address, cache_block_new_state)

    # Method to invalidate RL on core, assumes that core has both cores and data bus locks
    def invalidate_rl_on_core(self, mem_address, core):
        if core == 0 or self.__core_count <= 1:
            return self.__core0.invalidate_self_rl(mem_address)
        else:
            return self.__core1.invalidate_self_rl(mem_address)

    # Method to set core finished bool to true
    def notify_core_finished(self):
        self.__core_finished = True

    # Method to get the default quantum
    def get_default_quantum(self):
        return self.__default_quantum

    # Method to get the simulation statistics
    def get_simulation_statistics(self):
        return self.__simulation_statistics

    # Method to increase the finished cores counter
    def increase_finished_counter(self):
        self.__core_finished_counter += 1