Exemplo n.º 1
0
class CPU(object):
	def __init__(self, poll, output, debug, info):
		self.wordLength = 16
		self.addressibility = 16
		self.gRegNum = 8
		self.gRegs = [ Number(self.wordLength) ] * self.gRegNum
		self.IR = Number(self.wordLength)
		self.PC = Number(self.addressibility)
		self.PSR = Number(self.wordLength)

		self.debug = debug
		self.info = info
		
		self.ch = -1

		self.SSP = Number(self.wordLength, 'b0011000000000000')	# Stack Bottom
		self.USP = Number(self.wordLength, 'b1111111000000000')	# Stack Bottom

		# Program State Register, inluding Pr, PL, CC
		# When loaded in the user program and running, the Pr will be set;
		# When a device issues a interrupt, the Pr will change into priliveged mode
		# Write to Registers will incur changes to CC

		# address of special memory mapped locations
		self.MCR  = Number(16, 'b1111111111111110')

		self.mem = Memory(self.interrupt, poll, output)
		self.writeMem = self.mem.write
		self.readMem = self.mem.read

		self.getOperands = {
			'ADDr' : ['R4-7', 'R7-10', 'R13-16'],
			'ADDimm' : ['R4-7', 'R7-10', 'I11-16'],
			'ANDr' : ['R4-7', 'R7-10', 'R13-16'],
			'ANDimm' : ['R4-7', 'R7-10', 'I11-16'],
			'BR' : ['S4-7', 'O7-16'],
			'LD' : ['R4-7', 'O7-16'],
			'ST' : ['R4-7', 'O7-16'],
			'NOT' : ['R4-7', 'R7-10'],
			'JMP' : ['R7-10'],
			'JSR' : ['O5-16'],
			'JSRR' : ['R7-10'],
			'LDI' : ['R4-7', 'O7-16'],
			'LDR' : ['R4-7','R7-10', 'O10-16'],
			'LEA' : ['R4-7', 'O7-16'],
			'STI' : ['R4-7', 'O7-16'],
			'STR' : ['R4-7','R7-10', 'O10-16'],
			'TRAP' : ['S8-16'],
			'RTI' : []
		}



	def match(self, pattern, inst):
		rulesMatch = {
			'R' : lambda segment : int(segment, 2), # Register
			'O' : lambda segment : Number(9, 'b' + segment).SEX(self.wordLength), # Offset
			'I' : lambda segment : Number(len(segment), 'b' + segment).SEX(self.wordLength), # Immediate Value
			'S' : lambda segment : segment # return the segment itself
		}

		operands = []
		for rule in pattern:
			[start, end] = rule[1:].split('-')
			operands.append(rulesMatch[rule[0]](inst.data[int(start):int(end)]))
		return operands

	def getOpcode(self, instruction):
		singleModeOpcode = {
			'0000' : 'BR',
			'0010' : 'LD',
			'0011' : 'ST',
			'1001' : 'NOT',
			'1100' : 'JMP',
			'1010' : 'LDI',
			'0110' : 'LDR',
			'1110' : 'LEA',
			'1011' : 'STI',
			'0111' : 'STR',
			'1111' : 'TRAP',
			'1000' : 'RTI'
		}

		opcode = instruction.data[0:4]
		if opcode == '0001':
			if instruction.data[10:13] == '000':
				return 'ADDr'
			elif instruction.data[10] == '1':
				return 'ADDimm'
			else:
				raise StandardError("Error -- Wrong ADD instruction format")
		if opcode == '0101':
			if instruction.data[10:13] == '000':
				return 'ANDr'
			elif instruction.data[10] == '1':
				return 'ANDimm'
			else:
				raise StandardError("Error -- Wrong AND instruction format")
		if opcode == '0100':
			if instruction.data[4] == '1':
				return 'JSR'
			elif instruction.data[4:7] == '000':
				return 'JSRR'
			else:
				raise StandardError("Error -- Wrong AND instruction format")
		else:
			return singleModeOpcode[opcode]

	def step(self):
		self.IR = self.readMem(self.PC)
		self.PC = self.PC.ADD(Number(self.wordLength, 1))
		opcode = self.getOpcode(self.IR)

		MCR = self.readMem(self.MCR)
		if MCR.data[0] == '0':	# RUN Latch is cleared
			return 0
		elif opcode:
			operands = self.match(self.getOperands[opcode], self.IR)
			apply(self.__getattribute__(opcode), operands)
			return 1
		else:
			self.info("Error: Invalid Opcode")
			return 0

	def setCC(self, index):
		PSR_left = self.PSR.bin()[:-3]
		if self.readRegCom(index) > 0:
			self.PSR = Number(16, PSR_left + '001')
		elif self.readRegCom(index) == 0:
			self.PSR = Number(16, PSR_left + '010')
		else:
			self.PSR = Number(16, PSR_left + '100')

	def getCC(self):
		return self.PSR.bin()[-3:]

	def readRegCom(self, index):
		return Tools.intCom(self.gRegs[index].bin()[1:])

# ----------------------- ISA -----------------------
	def LD(self, DR, offset):
		SRCaddr = self.PC.ADD(offset)
		self.debug('LD R' + str(DR)+ ' <- mem(' + SRCaddr.hex() + ')')
		self.gRegs[DR] = self.readMem(SRCaddr)
		self.setCC(DR)

	def BR(self, nzp, offset):
		if Tools.match(self.getCC(), nzp):
			self.PC = self.PC.ADD(offset)
			self.debug("BR offset(" + str(offset.intCom()) + ")")
		else:
			self.debug("BR -- 'not match'")

	def ST(self, SR, offset):
		DESTaddr = self.PC.ADD(offset)
		self.debug('ST R' + str(SR) + ' -> mem(' + DESTaddr.hex() + ')')
		self.writeMem(DESTaddr, self.gRegs[SR])

	def ADDr(self, DR, SR1, SR2):
		self.debug('ADDr R' + str(DR) + ' <- R' + str(SR1) + ' + R' + str(SR2))
		self.gRegs[DR] = self.gRegs[SR1].ADD(self.gRegs[SR2])
		self.setCC(DR)

	def ADDimm(self, DR, SR, Simm):
		self.debug('ADDimm R' + str(DR) + ' <- R' + str(SR) + ' + Imm(' + str(Tools.intCom(Simm.data)) + ')')
		self.gRegs[DR] = self.gRegs[SR].ADD(Simm)
		self.setCC(DR)

	def ANDr(self, DR, SR1, SR2):
		self.debug('ANDr R' + str(DR) + ' <- R' + str(SR1) + ' & R' + str(SR2))
		self.gRegs[DR] = self.gRegs[SR1].AND(self.gRegs[SR2])
		self.setCC(DR)

	def ANDimm(self, DR, SR, Simm):
		self.debug('ANDimm R' + str(DR) + ' <- R' + str(SR) + ' & Imm(' + str(Tools.intCom(Simm.data)) + ')')
		self.gRegs[DR] = self.gRegs[SR].AND(Simm)
		self.setCC(DR)

	def NOT(self, DR, SR):
		self.debug('NOT R' + str(DR) + ' <- ! R' + str(SR))
		self.gRegs[DR] = self.gRegs[SR].NOT()
		self.setCC(DR)

	def JMP(self, BR):
		self.debug('JMP PC <- R' + str(BR))
		self.PC = self.gRegs[BR]

	def JSR(self, offset):
		self.gRegs[7] = self.PC
		self.PC = self.PC.ADD(offset)
		self.debug('JSR R7 <- PC, PC <- ' + self.PC.hex())

	def JSRR(self, BR):
		self.gRegs[7] = self.PC
		self.PC = self.gRegs[BR]
		self.debug('JSRR R7 <- PC, PC <- R' + str(BR))

	def LDI(self, DR, offset):
		addr = self.PC.ADD(offset)
		self.gRegs[DR] = self.readMem(self.readMem(addr))
		self.debug('LDI R' + str(DR) + ' <- mem(mem(' + addr.hex() + '))')
		self.setCC(DR)

	def STI(self, SR, offset):
		addr = self.PC.ADD(offset)
		self.writeMem(self.readMem(addr), self.gRegs[SR])
		self.debug('STI R' + str(SR) + ' -> mem(mem(' + addr.hex() + '))')

	def LDR(self, DR, BR, offset):
		addr = self.gRegs[BR].ADD(offset)
		self.gRegs[DR] = self.readMem(addr)
		self.setCC(DR)
		self.debug('LDR R' + str(DR) + ' <- mem(' + 'R' + str(BR) + ' + ' + str(offset.int()) + ')')

	def STR(self, SR, BR, offset):
		addr = self.gRegs[BR].ADD(offset)
		self.writeMem(addr, self.gRegs[SR])
		self.debug('STR R' + str(SR) + ' -> mem(' + 'R' + str(BR) + ' + ' + str(offset.int()) + ')')

	def LEA(self, DR, offset):
		self.gRegs[DR] = self.PC.ADD(offset)
		self.setCC(DR)
		self.debug('LEA R' + str(DR) + ' <- PC + ' + str(offset.intCom()))

	def TRAP(self, vector):
		self.gRegs[7] = self.PC		# R7 <- PC
		self.PC = self.readMem(Number(16, 'b00000000' + vector))	# PC <- mem[ZEX(vector)]
		self.debug('TRAP V' + vector)

	def RTI(self):
		# Return From interrupt
		privileged = (self.PSR.data[0] == '0')
		if privileged:
			SSP = self.gRegs[6]
			self.PC = self.readMem(SSP)
			self.PSR = self.readMem(SSP.ADD(Number(self.wordLength, 1)))
			self.gRegs[6] = SSP.ADD(Number(self.wordLength, 2))
		else:
			raise Exception("Exception: RTI not privileged")

	def interrupt(self, PL, vector):
		assert(len(vector) == 8)
		if int(self.PSR.data[5:8], 2) > int(PL, 2):
			self.debug("[CPU]: interrupt Rejected")
			return 	# Reject the interrupt
		addr = Number(16, 'b00000001' + vector)
		SSP = self.gRegs[6]
		self.writeMem(SSP.MINUS(Number(self.wordLength, 1)), self.PSR)
		self.writeMem(SSP.MINUS(Number(self.wordLength, 2)), self.PC)
		self.gRegs[6] = SSP.MINUS(Number(self.wordLength, 2))
		self.PC = self.readMem(addr)
		self.PSR = Number(16, 'b00000' + PL + '00000000')
		self.debug("[CPU]: interrupt accepted")
		self.ch = -1