class Pipelinecpu(object): '''This class is the pipelinecpu''' def __init__(self): self.control = Control() self.register = Registers(32) self.pcreg = PipelineReg() self.if_id = PipelineReg() self.id_exe = PipelineReg() self.exe_mem = PipelineReg() self.mem_wb = PipelineReg() self.alu = Alu() self.memory = Memory() self.initializePipeline() def getRegisterState(self): return self.register.getRegisterState() def getInstructionCount(self): return self.instructionCount def getDataCount(self): return self.dataCount def getInstruction(self, i): return self.memory.readMemory(i) def readMemory(self, i): return self.memory.readMemory(i) def getPC(self): return self.pc def initializePipeline(self): ## Deletes memory and instruction count self.signalWPC = 1 self.signalWIR = 1 self.regData = 0 self.pc = 0 self.signalBtaken = 0 self.signalSld = 0 self.signalWreg = 0 self.signalLOADDEPEN = 1 self.inst = '' self.signalShift = 0 self.tempinst = '' ## Initializes Registers self.memory.initialize() self.register.initialize() self.pcreg.initialize() self.if_id.initialize() self.id_exe.initialize() self.exe_mem.initialize() self.mem_wb.initialize() ## Forwarding Unit def __forwardingUnit(self): int2 = functools.partial(int, base=2) self.rs1IsReg = (self.opcode != int2(opcodes['bne'])) & (self.opcode != int2(opcodes['beq'])) & ( self.opcode != int2(opcodes['branch'])) self.rs2IsReg = (self.opcode == int2(opcodes['and'])) | (self.opcode == int2(opcodes['or'])) | ( self.opcode == int2(opcodes['add'])) | \ (self.opcode == int2(opcodes['sub'])) | (self.opcode == int2(opcodes['sra'])) | ( self.opcode == int2(opcodes['sll'])) | \ (self.opcode == int2(opcodes['srl'])) # ALU A select signal ADEPEN1 = ((self.exe_mem.signalWreg == 1) & (self.readReg1 == self.exe_mem.regD) | (self.mem_wb.signalWreg == 1) & \ (self.readReg1 == self.mem_wb.regD)) & (self.rs1IsReg) ADEPEN2 = ((self.mem_wb.signalWreg == 1) & (self.readReg1 == self.mem_wb.regD)) & (self.rs1IsReg) self.signalADEPEN = ADEPEN1 * 2 + ADEPEN2 #ALU B select signal BDEPEN1 = ((self.exe_mem.signalWreg == 1) & (self.readReg2 == self.exe_mem.regD) | (self.mem_wb.signalWreg == 1) & \ (self.readReg2 == self.mem_wb.regD)) & (self.rs2IsReg) BDEPEN2 = (self.mem_wb.signalWreg == 1) & (self.readReg2 == self.mem_wb.regD) & (self.rs2IsReg) | ( not self.rs2IsReg) self.signalBDEPEN = BDEPEN1 * 2 + BDEPEN2 #LOADDEPEN EXE_A_DEPEN = (self.readReg1 == self.exe_mem.regD) & (self.exe_mem.signalSld == 1) & (self.rs1IsReg) EXE_B_DEPEN = (self.readReg2 == self.exe_mem.regD) & (self.exe_mem.signalSld == 1) & (self.rs2IsReg) | \ (self.readReg2 == self.exe_mem.regD) & (self.exe_mem.signalSld == 1) & (self.opcode == int2(opcodes['store'])) self.signalLOADDEPEN = not (EXE_A_DEPEN | EXE_B_DEPEN) #STORE self.signalQDEPEN = (self.readReg2 == self.exe_mem.regD) & (self.exe_mem.signalWreg == 1) ## Instruction Fetch Stage def __cpuStageIF(self, bin_instruction, instruction): self.signalBtaken = self.control.getBtaken() if self.signalBtaken: self.nextPC = twos_to_int(self.if_id.instruction & 0x3FFFFFF, 26) else: self.nextPC = self.pc + 1 int2 = functools.partial(int, base=2) if self.opcode == 10 or self.opcode == 11: self.signalWPC = not(((self.opcode == int2(opcodes['bne'])) | (self.opcode == int2(opcodes['beq']))) & \ self.exe_mem.signalWreg & (not self.exe_mem.signalSld)) self.signalWPC = int(self.signalWPC) self.signalWIR = self.signalWPC else: if self.signalLOADDEPEN | (self.opcode == 9): #not loaddepen or after load is store self.signalWPC = 1 self.signalWIR = 1 else: self.signalWIR = 0 self.signalWPC = 0 ''' elif self.opcode == 9: self.signalWPC = not(self.exe_mem.signalWreg & (self.exe_mem.signalSld |self.exe_mem.regD == self.readReg2)) self.signalWPC = int(self.signalWPC) self.signalWIR = self.signalWPC ''' if self.signalWPC: self.pc = self.nextPC else: self.pc = self.pc if self.signalWIR: self.if_id.instruction = bin_instruction self.if_id.inst = instruction else: self.if_id.instruction = self.if_id.instruction self.if_id.inst = self.if_id.inst return self.pc ## Instruction Decode Stage def __cpuStageID(self): #self.id_exe = self.if_id # Pipeline shift ## instruction Decode self.opcode = (self.if_id.instruction & 0xFC000000) >> 26 # inst[31:26] # Sets control based on opcode and zeroResult self.control.signalIn(self.opcode, self.exe_mem.zeroResult) self.readReg1 = (self.if_id.instruction & 0x001F0000) >> 16 # inst[20:16] if self.control.getSst(): # store self.readReg2 = (self.if_id.instruction & 0x03E00000) >> 21 #inst[25:21] else: self.readReg2 = (self.if_id.instruction & 0x0000001F) # inst[4:0] # Forwarding Detect self.__forwardingUnit() self.id_exe.regD = ((self.if_id.instruction & 0x03E00000) >> 21) # rd # Sets ID_EXE registers based on register data self.signalShift = self.control.getShift() if self.signalShift: self.id_exe.readData1 = self.readReg1 # sa for shift instructions else: self.id_exe.readData1 = self.register.readRegister(self.readReg1) self.id_exe.readData2 = self.register.readRegister(self.readReg2) # Stores the necessary control bits in ID_EXE registers self.id_exe.signalisStore = self.control.getisSTORE() self.id_exe.signalBtaken = self.control.getBtaken() self.id_exe.signalQDEPEN = int(self.signalQDEPEN) self.id_exe.signalADEPEN = self.signalADEPEN #print 'ADEPEN', self.id_exe.signalADEPEN self.id_exe.signalBDEPEN = self.signalBDEPEN #print 'BDEPEN', self.id_exe.signalBDEPEN self.id_exe.signalAluOp = self.control.getAluOp() #print 'ALUOP', self.id_exe.signalAluOp self.id_exe.signalWz = self.control.getWz() & (self.signalLOADDEPEN | (self.opcode == 9)) & (not self.exe_mem.signalBtaken) self.id_exe.signalWreg = self.control.getWreg() & (self.signalLOADDEPEN | (self.opcode == 9)) & (not self.exe_mem.signalBtaken) self.id_exe.signalWmem = self.control.getWmem() & (self.signalLOADDEPEN | (self.opcode == 9)) & (not self.exe_mem.signalBtaken) self.id_exe.signalSld = self.control.getSld() self.id_exe.inst = self.if_id.inst # Sets ID_EXE registers immediateValue based on control signal sext if self.control.getSext(): self.id_exe.immediateValue = twos_to_int(self.if_id.instruction & 0xFFFF, 16) else: self.id_exe.immediateValue = self.if_id.instruction & 0xFFFF self.istransfer = (self.opcode == 10 or self.opcode == 11 or self.opcode == 12) self.iswrite = (self.id_exe.signalWreg or self.id_exe.signalWmem) if (not self.istransfer) & self.iswrite: self.tempinst = self.id_exe.inst elif self.istransfer & (self.exe_mem.inst == 'stall'): self.tempinst = self.id_exe.inst elif self.id_exe.inst == '': self.tempinst = self.id_exe.inst elif self.istransfer & (self.opcode == 12): self.tempinst = self.id_exe.inst else: self.tempinst = 'stall' ## Instruction Execution Stage def __cpuStageEXE(self): self.exe_mem.inst = self.tempinst self.exe_mem.signalisStore = self.id_exe.signalisStore self.exe_mem.signalBtaken = self.id_exe.signalBtaken self.exe_mem.signalADEPEN = self.id_exe.signalADEPEN self.exe_mem.signalBDEPEN = self.id_exe.signalBDEPEN self.exe_mem.signalAluOp = self.id_exe.signalAluOp self.exe_mem.readData2 = self.id_exe.readData2 self.exe_mem.regD = self.id_exe.regD self.exe_mem.signalWmem = self.id_exe.signalWmem self.exe_mem.signalWreg = self.id_exe.signalWreg self.exe_mem.signalSld = self.id_exe.signalSld self.exe_mem.signalWz = self.id_exe.signalWz # forwarding if self.id_exe.signalADEPEN == 0: self.aluA = self.id_exe.readData1 elif self.id_exe.signalADEPEN == 2: self.aluA = self.exe_mem.aluResult elif self.id_exe.signalADEPEN == 3: self.aluA = self.regData else: print 'Error!' if self.id_exe.signalBDEPEN == 0: self.aluB = self.id_exe.readData2 elif self.id_exe.signalBDEPEN == 1: self.aluB = self.id_exe.immediateValue elif self.id_exe.signalBDEPEN == 2: self.aluB = self.mem_wb.aluResult elif self.id_exe.signalBDEPEN == 3: self.aluB = self.regData else: print 'Error!' ''' if self.exe_mem.signalQDEPEN == 0: self.storeD = self.id_exe.readData2 elif self.exe_mem.signalQDEPEN == 1: self.storeD = self.regData else: print 'Error!' ''' self.exe_mem.signalQDEPEN = int(self.id_exe.signalQDEPEN) #self.exe_mem.storeD = self.storeD self.alu.compute(self.id_exe.signalAluOp, self.aluA, self.aluB) ## Sets EXE_MEM registers self.exe_mem.aluResult = self.alu.getResults() if self.id_exe.signalWz: self.exe_mem.zeroResult = self.alu.getZero() ## Memory Stage def __cpuStageMEM(self): self.mem_wb.inst = self.exe_mem.inst self.mem_wb.regD = self.exe_mem.regD self.mem_wb.readData2 = self.exe_mem.readData2 self.mem_wb.aluResult = self.exe_mem.aluResult self.mem_wb.signalSld = self.exe_mem.signalSld self.mem_wb.signalWreg = self.exe_mem.signalWreg self.mem_wb.signalWmem = self.exe_mem.signalWmem if self.exe_mem.signalQDEPEN == 0: self.storeD = self.exe_mem.readData2 elif self.exe_mem.signalQDEPEN == 1: self.storeD = self.regData else: print 'Error!' self.mem_wb.signalQDEPEN = self.exe_mem.signalQDEPEN ## Read from Memory self.mem_wb.memReadData = self.memory.readMemory(self.exe_mem.aluResult) ## Write to Memory if self.exe_mem.signalWmem: self.memory.writeMemory(int_to_twos(self.exe_mem.aluResult), self.storeD) ## Write Back Stage def __cpuStageWB(self): self.inst = self.mem_wb.inst self.signalWreg = self.mem_wb.signalWreg self.signalSld = self.mem_wb.signalSld if self.signalSld: self.regData = self.mem_wb.memReadData else: self.regData = self.mem_wb.aluResult if self.signalWreg: self.register.writeRegister(self.mem_wb.regD, self.regData) def atomicStep(self, bin_instruction, instruction): self.__cpuStageWB() self.__cpuStageMEM() self.__cpuStageEXE() self.__cpuStageID() return self.__cpuStageIF(bin_instruction, instruction)