Add python WIP
This commit is contained in:
parent
3261b6c97a
commit
82c0283b25
|
|
@ -0,0 +1,164 @@
|
|||
import time
|
||||
|
||||
class CPU:
|
||||
def __init__(self):
|
||||
self.running = False
|
||||
self.IP = 254
|
||||
self.acc = 0
|
||||
self.flags = { 'C': False, 'Z': False, 'N': False, 'Eq': False }
|
||||
self.instruction = { 'opcode': False, 'operand': False }
|
||||
self.memory = False
|
||||
|
||||
|
||||
def load_memory(self, bytes):
|
||||
self.memory = bytes + bytearray(256 - len(bytes))
|
||||
# print(self.memory)
|
||||
|
||||
def start(self):
|
||||
self.running = True
|
||||
|
||||
def step(self):
|
||||
if self.IP >= 255: # TODO CHECK
|
||||
self.IP = 0
|
||||
print("IP:", toHex(self.IP))
|
||||
self.instruction['opcode'] = self.memory[self.IP]
|
||||
self.IP = self.IP+1
|
||||
self.instruction['operand'] = self.memory[self.IP]
|
||||
self.IP = self.IP+1
|
||||
self.nums2mnems[self.instruction['opcode']](self, self.instruction['operand'])
|
||||
|
||||
print("instr:", toHex(self.instruction['opcode']), toHex(self.instruction['operand']))
|
||||
print("mnem:", self.nums2mnems[self.instruction['opcode']])
|
||||
print("acc:", self.acc, "N:", self.flags['N'])
|
||||
print("running:", self.running)
|
||||
print()
|
||||
# self.print_screen()
|
||||
print("byte 26 (keyboard):", self.memory[26])
|
||||
print()
|
||||
|
||||
def hlt(self, operand):
|
||||
self.running = False
|
||||
|
||||
def nop(self, operand):
|
||||
pass
|
||||
|
||||
def lda_lit(self, operand):
|
||||
self.acc = operand
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def lda_mem(self, operand):
|
||||
self.acc = self.memory[operand]
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def sta_lit(self, operand):
|
||||
self.memory[operand] = self.acc
|
||||
|
||||
def sta_mem(self, operand):
|
||||
self.memory[self.memory[operand]] = self.acc
|
||||
|
||||
def add_lit(self, operand):
|
||||
self.acc = self.acc + operand
|
||||
if self.acc > 255:
|
||||
self.acc = self.acc % 256
|
||||
self.flags['C'] = True
|
||||
else:
|
||||
self.flags['C'] = False
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def add_mem(self, operand):
|
||||
self.acc = self.acc + self.memory[operand]
|
||||
if self.acc > 255:
|
||||
self.acc = self.acc % 256
|
||||
self.flags['C'] = True
|
||||
else:
|
||||
self.flags['C'] = False
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def sub_lit(self, operand):
|
||||
self.acc = self.acc - operand
|
||||
if self.acc < 0:
|
||||
self.acc = self.acc % 256
|
||||
self.flags['C'] = True
|
||||
else:
|
||||
self.flags['C'] = False
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def sub_mem(self, operand):
|
||||
self.acc = self.acc - self.memory[operand]
|
||||
if self.acc > 255:
|
||||
self.acc = self.acc % 256
|
||||
self.flags['C'] = True
|
||||
else:
|
||||
self.flags['C'] = False
|
||||
self.flags['Z'] = True if self.acc == 0 else False
|
||||
self.flags['Eq'] = True if self.acc == operand else False
|
||||
self.flags['N'] = True if self.acc > 127 else False
|
||||
|
||||
def jmp_lit(self, operand):
|
||||
self.IP = operand
|
||||
|
||||
def jmp_mem(self, operand):
|
||||
self.IP = self.memory[operand]
|
||||
|
||||
def ske(self, operand): # FIXME
|
||||
# if self.flags['Eq']:
|
||||
# self.IP += 2
|
||||
if self.acc == operand:
|
||||
self.IP += 2
|
||||
|
||||
def skz(self, operand):
|
||||
if self.flags['Z']:
|
||||
self.IP += 2
|
||||
|
||||
def skn(self, operand):
|
||||
if self.flags['N']:
|
||||
self.IP += 2
|
||||
|
||||
def skc(self, operand):
|
||||
if self.flags['C']:
|
||||
self.IP += 2
|
||||
|
||||
def cst(self, operand):
|
||||
self.flags['C'] = True
|
||||
|
||||
def ccl(self, operand):
|
||||
self.flags['C'] = False
|
||||
|
||||
nums2mnems = {
|
||||
0: hlt, # x0
|
||||
1: nop, # x1
|
||||
2: lda_lit, # 02
|
||||
3: sta_lit, # 03
|
||||
4: add_lit, # 04
|
||||
5: sub_lit, # 05
|
||||
6: jmp_lit, # 06
|
||||
7: ske, # x7
|
||||
8: skz, # x8
|
||||
9: skn, # x9
|
||||
10: skc, # A
|
||||
11: cst, # B
|
||||
12: ccl, # C
|
||||
16: hlt, #
|
||||
17: nop, #
|
||||
18: lda_mem, # 12
|
||||
19: sta_mem, # 13
|
||||
20: add_mem, # 14
|
||||
21: sub_mem, # 15
|
||||
22: jmp_mem, # 16
|
||||
23: ske,
|
||||
24: skz,
|
||||
25: skn,
|
||||
26: skc,
|
||||
27: cst,
|
||||
28: ccl,
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
numericKeys = [ "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" ]
|
||||
|
||||
def toHex(n):
|
||||
return "%0.2X" % n
|
||||
|
||||
class Monitor:
|
||||
def __init__(self, cpu):
|
||||
self.cpu = cpu
|
||||
self.monitorMode = 'addressEntry' # or dataEntry
|
||||
self.monitorAddressInput = TwoDigitHexInput()
|
||||
self.monitorDataInput = TwoDigitHexInput()
|
||||
|
||||
# In data entry mode, when a full byte is keyed in,
|
||||
# the next keypress advances to the next address and continues entering data there.
|
||||
# This variable tracks whether it's time to do that or not.
|
||||
self.advanceDataEntryNextPress = False
|
||||
|
||||
def handleKeys(self):
|
||||
keypad_event = keymatrix.events.get()
|
||||
keyPressed = True if (keypad_event and keypad_event.released ) else False
|
||||
key = keymap[keypad_event.key_number] if keyPressed else False
|
||||
numericKeyPressed = True if (keyPressed and (key in numericKeys)) else False
|
||||
|
||||
|
||||
if self.cpu.running:
|
||||
if key == "runhalt":
|
||||
print("HALT PRESSED")
|
||||
self.cpu.running = False
|
||||
time.sleep(0.5) # lazy debounce
|
||||
# km.events.clear() # don't track keypresses from during the run
|
||||
|
||||
if numericKeyPressed:
|
||||
self.cpu.memory[26] = int(key, 16)
|
||||
|
||||
elif not self.cpu.running:
|
||||
if key == "runhalt":
|
||||
self.cpu.running = True
|
||||
print("\nSTARTING")
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if key == "addr":
|
||||
self.monitorMode = 'addressEntry'
|
||||
print("\nENTERING", self.monitorMode, "MODE")
|
||||
self.monitorAddressInput.currentDigit = 0
|
||||
time.sleep(0.5) # lazy debounce
|
||||
if key == "data":
|
||||
self.monitorMode = 'dataEntry'
|
||||
print("\nENTERING", self.monitorMode, "MODE")
|
||||
self.monitorDataInput.clear()
|
||||
self.advanceDataEntryNextPress = False
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if key == "step":
|
||||
print("\nSINGLE STEP FROM MONITOR ADDR")
|
||||
# self.IP = self.monitorAddressInput.value
|
||||
self.cpu.step()
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if numericKeyPressed:
|
||||
if self.monitorMode == 'addressEntry':
|
||||
self.monitorAddressInput.input(int(key, 16))
|
||||
self.cpu.IP = self.monitorAddressInput.value
|
||||
print("MA", self.cpu.IP)
|
||||
|
||||
if self.monitorMode == 'dataEntry':
|
||||
if self.advanceDataEntryNextPress:
|
||||
print("ADVANCING")
|
||||
self.cpu.IP = (self.cpu.IP + 1) % 256
|
||||
# self.monitorDataInput.clear() # reset .currentDigit
|
||||
self.monitorDataInput.set(self.cpu.memory[self.cpu.IP])
|
||||
self.advanceDataEntryNextPress = False
|
||||
self.monitorDataInput.input(int(key, 16))
|
||||
self.cpu.memory[self.cpu.IP] = self.monitorDataInput.value
|
||||
print("MD", self.monitorDataInput.value)
|
||||
if self.monitorDataInput.currentDigit == 0: # that was the second keypress, so next keypress is for the next address
|
||||
self.advanceDataEntryNextPress = True
|
||||
|
||||
print("Acc", self.cpu.acc, "IP", self.cpu.IP, "Data", self.cpu.memory[self.cpu.IP], "\n")
|
||||
|
||||
|
||||
def displayScreen(self):
|
||||
for x in range(8):
|
||||
for y in range(8):
|
||||
matrix[x, y] = self.cpu.memory[x + (8*y)]
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
#self.cpu.start()
|
||||
t = time.time()
|
||||
while (time.time() - t) < 120: # TODO: add a time delta or sth maybe so this doesn't just burn cycles
|
||||
self.handleKeys()
|
||||
display_1.print(toHex(self.cpu.IP) + toHex(self.cpu.memory[self.cpu.IP]))
|
||||
# display_1.print(toHex(self.monitorAddressInput.value) + toHex(self.cpu.memory[self.cpu.IP]))
|
||||
# display_2.print(toHex(self.cpu.IP) + toHex(self.cpu.acc))
|
||||
display_2.print(toHex(self.cpu.acc))
|
||||
self.displayScreen()
|
||||
if self.cpu.running:
|
||||
self.cpu.step()
|
||||
# time.sleep(0.5) # TODO ?
|
||||
print("timeout")
|
||||
print(self.cpu.memory)
|
||||
|
||||
|
||||
cpu = CPU()
|
||||
monitor = Monitor(cpu)
|
||||
|
||||
# preamble = '00 ' * 64
|
||||
# prog = preamble + '02 01 13 f0 12 f0 04 02 03 f0 12 f0 05 41 08 00 06 40 00 00' # STRIPES
|
||||
# offset = 64
|
||||
# prog = preamble + '02 01 13 f0 12 f0 04 02 03 f0 05 08 09 00 04 09 03 f0 07 41 06' + toHex(offset) + '00 00'
|
||||
#prog = '00'
|
||||
# program_bytes = bytearray.fromhex(prog.replace(" ", ""))
|
||||
|
||||
# Add jmp at addr 254:
|
||||
#program_with_jump = program_bytes + bytearray(254 - len(program_bytes)) + bytearray.fromhex('0600') # jump to addr 00
|
||||
# program_with_jump = program_bytes + bytearray(254 - len(program_bytes)) + bytearray.fromhex('0640') # jump to addr 0x40 (dec 64)
|
||||
|
||||
with open('test-multiply2.bin', 'rb') as file:
|
||||
program_bytes = bytearray(file.read())
|
||||
|
||||
cpu.load_memory(program_bytes)
|
||||
|
||||
monitor.run()
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import cpu
|
||||
|
||||
c = cpu.CPU()
|
||||
|
||||
print(c)
|
||||
Loading…
Reference in New Issue