Example #1
0
class Mips(object):
    def __init__(self, instructions=None, data_forwarding=False):
        instructions = instructions.split("\n") if instructions else []
        self.instructions = [instruction for instruction in instructions if instruction.strip()]
        self.data_forwarding = data_forwarding
        
        self.registers = Registers(size=REGISTERS_SIZE)
        self.memory = Memory(size=MEMORY_SIZE)
        self.history = []

        self.pc = 0
        self.clock = 0
        self.instructions_completed = 0
        
        self._if = InstructionFetch(self)
        self._id = InstructionDecode(self)
        self._ex = Execute(self)
        self._mem = MemoryAccess(self)
        self._wb = WriteBack(self)
        self.pipeline = (self._if, self._id, self._ex, self._mem, self._wb)

    def run(self, life=MIPS_MAX_AGE):
        while True:
            self.history.append(self.current_state())
            self.execute_pipeline()
            self.clock += 1
            
            if self.clock > life or (all(isinstance(p.instruction, StallInstruction) for p in self.pipeline) and self.pc == 4 * len(self.instructions)):
                self.history.append(self.current_state())
                break

    def _go_forward_pipeline(self):
        if self.pipeline[4].done:
            self.pipeline[4].instruction = None
                        
        for a, b in reversed(zip(self.pipeline[:-1], self.pipeline[1:])):
            if a.done and b.instruction is None:
                b.instruction = a.instruction
                a.instruction = None
    
    def execute_pipeline(self):
        self._go_forward_pipeline()

        for phase in self.pipeline:
            phase.execute()
            if not phase.instruction:
                phase.instruction = StallInstruction()

    def jump(self, pc):
        self._if.instruction.unlock_registers(self)
        self._if.instruction = StallInstruction()
        self._id.instruction.unlock_registers(self)
        self._id.instruction = StallInstruction()
        self.pc = pc
    
    def current_state(self):
        instructions_completed = self.instructions_completed
        throughput = instructions_completed / self.clock if self.clock > 0 else 0
    
        state = {"pipeline":[p.instruction.current_state() for p in self.pipeline],
                 "registers":self.registers.current_state(),
                 "memory":self.memory.history[-4:],
                 "clock":self.clock,
                 "pc":self.pc,
                 "instructions_completed":instructions_completed,
                 "throughput":throughput}
        return state