Last active
March 15, 2022 07:28
-
-
Save shutebt01/f840186c62e0c8ce2ff9 to your computer and use it in GitHub Desktop.
Python LMC (Little Man Computer) Emulator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Created on 22 Oct 2014 | |
Little Man Computer Emulator | |
@author: shutebt01 | |
''' | |
import tkinter | |
import sys | |
import threading, time | |
from tkinter.constants import * | |
tk = tkinter.Tk(); | |
current = 0 | |
acumulator = 0 | |
last = 0 | |
def callback(sv, pos, type): | |
print(sv.get() + ":" + str(pos) + ":" + type) | |
if (type == "Assembly"): | |
AssemblyParser(sv, pos) | |
#if (type == "Machine"): | |
# MachineParser(sv, pos) | |
#null method for invalid string | |
def null(string, pos): | |
print("Invalid Thing") | |
# Assembly Parser Start | |
def hlt(string, pos): | |
try: | |
MachineCellsSV[pos].set("000") | |
except: | |
pass | |
def add(string, pos): | |
value = 100 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(100, 200, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def sub(string, pos): | |
value = 200 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(200, 300, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def sta(string, pos): | |
value = 300 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(300, 400, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def lda(string, pos): | |
value = 500 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(500, 600, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def bra(string, pos): | |
value = 600 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(600, 700, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def brz(string, pos): | |
value = 700 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(700, 800, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def brp(string, pos): | |
value = 800 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(800, 900, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
def inp(string, pos): | |
try: | |
MachineCellsSV[pos].set("901") | |
except: | |
pass | |
def out(string, pos): | |
try: | |
MachineCellsSV[pos].set("902") | |
except: | |
pass | |
def dat(string, pos): | |
value = 0 | |
try: | |
value = value + int(string[1]) | |
except: | |
pass | |
if value in range(0, 1000, 1): | |
try: | |
MachineCellsSV[pos].set(str(value)) | |
except: | |
pass | |
AssemblyConversion = {"HLT":hlt, "ADD":add, "SUB":sub, | |
"STA":sta, "LDA":lda, "BRA":bra, | |
"BRZ":brz, "BRP":brp, "INP":inp, | |
"OUT":out, "DAT":dat} | |
def AssemblyParser(sv, pos): | |
fullString = sv.get() | |
splitString = fullString.split() | |
if len(splitString) != 0: | |
AssemblyConversion.get(splitString[0], null)(splitString, pos) | |
#Assembly Parser End | |
#Machine executor Begin | |
class ExecThread(threading.Thread): | |
current = 0 | |
acumulator = 0 | |
last = 0 | |
def __init__(self): | |
threading.Thread.__init__(self, name="Execution Thread") | |
self._target = self.execute | |
def ex0xx(self, addr): | |
print("Executing Halt") | |
self.current = 100 | |
def ex1xx(self, addr): | |
print("Executing Add") | |
global MachineCellsSV | |
remote = int(MachineCellsSV[addr].get()) | |
self.acumulator += remote | |
def ex2xx(self, addr): | |
print("Executing Sub") | |
global MachineCellsSV | |
remote = int(MachineCellsSV[addr].get()) | |
self.acumulator -= remote | |
def ex3xx(self, addr): | |
print("Executing Sta") | |
global MachineCellsSV | |
MachineCellsSV[addr].set(self.acumulator) | |
def ex5xx(self, addr): | |
print("Executing Lda") | |
global MachineCellsSV | |
remote = int(MachineCellsSV[addr].get()) | |
self.acumulator = remote | |
def ex6xx(self, addr): | |
print("Executing Bra") | |
self.current = addr | |
def ex7xx(self, addr): | |
print("Executing Brz") | |
if self.acumulator == 0: | |
self.current = addr | |
def ex8xx(self, addr): | |
print("Executing Brp") | |
if self.acumulator >= 0: | |
self.current = addr | |
def setAcumulator(self, ac, iv): | |
ac = iv.get() | |
def unlock(self, lock): | |
lock=False | |
def ex9xx(self, addr): | |
print("Executing I/O") | |
if addr == 1: | |
top = tkinter.Toplevel(tk) | |
iv = tkinter.IntVar(top) | |
text = tkinter.Entry(top, textvariable=iv) | |
text.pack() | |
iv.trace("w", lambda name, index, mode, ac=self.acumulator, iv=iv: setAcumulator(ac, iv)) | |
close = tkinter.Button(top, text="Close", command=top.destroy()) | |
close.pack() | |
lock=True | |
top.wm_protocol("WM_DELETE_WINDOW", lambda lock=lock: unlock(lock)) | |
top.mainloop() | |
while lock: | |
pass | |
if addr == 2: | |
tkinter.messagebox.showinfo("Output", "Output Is: " + str(self.acumulator)) | |
def execute(self): | |
global MachineCellsSV | |
print("Starting Execution") | |
self.current = 0 | |
MacineExecParser = {"0":self.ex0xx, "1":self.ex1xx, | |
"2":self.ex2xx, "3":self.ex3xx, | |
"5":self.ex5xx, "6":self.ex6xx, | |
"7":self.ex7xx, "8":self.ex8xx, | |
"9":self.ex9xx} | |
try: | |
while self.current <=99: | |
value = MachineCellsSV[self.current].get() | |
self.current += 1 | |
MacineExecParser.get(value[0], self.ex0xx)(int(value[1:3])) | |
print("Finished Execution") | |
print(self.acumulator) | |
except Exception as e: | |
print(str(e)) | |
def halt(self): | |
self.current = 100 | |
ExecThread = ExecThread() | |
#Assembly executor END | |
class Cell(tkinter.StringVar): | |
def __init__(self, pos, type): | |
self.pos = pos | |
self.type = type | |
tkinter.StringVar.__init__(self) | |
# TODO: determine what lambda does | |
tkinter.StringVar.trace(self, "w", lambda name, index, mode, self=self: callback(self, self.pos, type)) | |
AssemblyCells = [None]*100 | |
AssemblyCellsSV = [None]*100 | |
for i in range(0, 100, 1): | |
AssemblyCellsSV[i] = Cell(i, "Assembly") | |
ittrvar = AssemblyCellsSV[i] | |
ittrvar.set("HLT") | |
AssemblyLbls = [None]*100 | |
MachineCells = [None]*100 | |
MachineCellsSV = [None]*100 | |
for i in range(0, 100, 1): | |
MachineCellsSV[i] = Cell(i, "Machine") | |
ittrvar = MachineCellsSV[i] | |
ittrvar.set("000") | |
MachineLbls = [None]*100 | |
tk.title("Little Man Computer") | |
frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2) | |
frame.pack(fill=BOTH,expand=1) | |
#Assembly Code GUI Section | |
AssemblyLabel = tkinter.Label(frame, text = "Assembly") | |
AssemblyLabel.grid(row=0, column=0) | |
AssemblyFrame = tkinter.Frame(frame, relief=RIDGE, borderwidth=2, width=200, height=500) | |
AssemblyFrame.grid(row=1, column=0, rowspan=6) | |
AssemblyCanvas = tkinter.Canvas(AssemblyFrame, width=100, height=250) | |
AssemblyCanvas.pack(side=LEFT, fill=BOTH) | |
AssemblyScroll = tkinter.Scrollbar(AssemblyFrame, command=AssemblyCanvas.yview) | |
AssemblyCanvas.config(yscrollcommand=AssemblyScroll.set, scrollregion=(-200,0,50,2110)) | |
AssemblyScroll.pack(side=RIGHT, fill=Y) | |
AssemblyCanvasFrame = tkinter.Frame(AssemblyCanvas) | |
AssemblyCanvasFrameFiller = tkinter.Label(AssemblyCanvasFrame, text="Hidden", height=3) | |
AssemblyCanvasFrameFiller.grid(row=0, column=0) | |
for i in range(0, 100, 1): | |
AssemblyLbls[i] = tkinter.Label(AssemblyCanvasFrame, text = str(i)) | |
AssemblyLbls[i].grid(row=i+1, column=0) | |
AssemblyCells[i] = tkinter.Entry(AssemblyCanvasFrame, width=10, textvariable=AssemblyCellsSV[i]) | |
AssemblyCells[i].grid(row=i+1, column=1) | |
AssemblyCanvas.create_window(0, 1030, window=AssemblyCanvasFrame) | |
# Machine Code GUI Section | |
MachineLabel = tkinter.Label(frame, text = "Machine Code") | |
MachineLabel.grid(row=0, column=2) | |
MachineFrame = tkinter.Frame(frame, relief=RIDGE, borderwidth=2, width=200, height=500) | |
MachineFrame.grid(row=1, column=2, rowspan=6) | |
MachineCanvas = tkinter.Canvas(MachineFrame, width=100, height=250) | |
MachineCanvas.pack(side=LEFT, fill=BOTH) | |
MachineScroll = tkinter.Scrollbar(MachineFrame, command=MachineCanvas.yview) | |
MachineCanvas.config(yscrollcommand=MachineScroll.set, scrollregion=(-200,0,50,2110)) | |
MachineScroll.pack(side=RIGHT, fill=Y) | |
MachineCanvasFrame = tkinter.Frame(MachineCanvas) | |
MachineCanvasFrameFiller = tkinter.Label(MachineCanvasFrame, text="Hidden", height=3) | |
MachineCanvasFrameFiller.grid(row=0, column=0) | |
for i in range(0, 100, 1): | |
MachineLbls[i] = tkinter.Label(MachineCanvasFrame, text = str(i)) | |
MachineLbls[i].grid(row=i+1, column=0) | |
MachineCells[i] = tkinter.Entry(MachineCanvasFrame, width=10, textvariable=MachineCellsSV[i]) | |
MachineCells[i].grid(row=i+1, column=1) | |
MachineCanvas.create_window(0, 1030, window=MachineCanvasFrame) | |
#Other GUI Stuff | |
InfoLBL1 = tkinter.Label(frame, text="This program will") | |
InfoLBL2 = tkinter.Label(frame, text="only parse from") | |
InfoLBL3 = tkinter.Label(frame, text="assembly to machine") | |
InfoLBL1.grid(row = 1, column=1) | |
InfoLBL2.grid(row = 2, column=1) | |
InfoLBL3.grid(row = 3, column=1) | |
ControlExec = tkinter.Button(frame, text="Start", command=ExecThread.execute) | |
ControlStop = tkinter.Button(frame, text="Stop", command=ExecThread.halt) | |
ControlExec.grid(row=1, column=3) | |
ControlStop.grid(row=2, column=3) | |
ExecThread.start() | |
tk.mainloop(); | |
try: | |
tk.destroy(); | |
except: | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment