Ai
1 Star 0 Fork 0

labs/excelCPU

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
compileExcelASM16.py 17.26 KB
一键复制 编辑 原始数据 按行查看 历史
Inkbox 提交于 2024-01-27 21:19 +08:00 . Main Excel files, compiler, and sample programs
#COMPILER FOR EXCEL-ASM16
#USE: py compileExcelASM16.py [program.s] ROM.xlsx
import sys
import os
import time
import math
from openpyxl import load_workbook
compiled = False;
filePath = ""
spreadsheet = ""
startTime = 0
data = []
program = []
output = []
labelOpen = False
labelToUse = ""
RED = '\033[91m';
ENDCOLOR = '\033[0m';
def integerError(lineNumber):
print(RED + "\tInteger outside of expected range, line: " + str(lineNumber)+ ENDCOLOR)
compileResults()
def syntaxError(lineNumber):
print(RED + "\tSyntax Error, line: " + str(lineNumber)+ ENDCOLOR)
compileResults()
def labelError(lineNumber):
print(RED + "\tDouble label detected, line " + str(lineNumber) + ENDCOLOR)
compileResults()
def referenceNotFoundError(labelName):
print(RED + "\tReference to variable or label not found, " + str(labelName) + ENDCOLOR)
compileResults()
def unrecognizedError(lineNumber):
print(RED + "\tUnrecognized Instruction, line " + str(lineNumber) + ENDCOLOR)
compileResults()
def varSequenceError(lineNumber):
print(RED + "\tVariables must be defined before program code, line " + str(lineNumber) + ENDCOLOR)
compileResults()
def varUseError(varName):
print(RED + "\tVariable cannot be used like label, var: " + str(lineNumber) + ENDCOLOR)
compileResults()
def orgError(lineNumber):
print(RED + "\tProgram Count exceeds target address, line " + str(lineNumber) + ENDCOLOR)
compileResults()
def incResourceError(resourceName, lineNumber):
print(RED + "\tResource " + resourceName + " could not be found, line " + str(lineNumber) + ENDCOLOR)
compileResults()
def lengthError(exceededWords):
print(RED + "\tProgram length exceeds available RAM by " + str(exceededWords) + " words" + ENDCOLOR)
compileResults()
def ROMbookError():
print(RED + "\tCould not save to specified workbook, make sure the file is closed and try again" + ENDCOLOR)
exit()
def createLine(label, operations):
return [label, operations]
def getCurrentAddress():
address = len(data)
for operations in program:
address = address + len(operations[1])
return address
def getLocationOfLabel(labelName):
location = 0
for var in data:
if (labelName == var[0]):
varUseError(labelName)
location = location + 1
for operations in program:
if (labelName == operations[0]):
return location
location = location + len(operations[1])
return -1
def getVarIndex(varName):
i = 0
for var in data:
if (varName == var[0]):
return i
i = i + 1
return -1
def includeBIN(fileName):
with open(fileName, "rb") as incFile:
cycle = False
lastValue = 0
while (word := incFile.read(1)):
value = int.from_bytes(word, "big")
if (cycle):
value = (lastValue * 256) + value
if (value >= pow(2, 16)):
input()
program.append(createLine("", [value]))
cycle = False
else:
lastValue = value
cycle = True
if (cycle): #catching last single byte value
program.append(createLine("", [(lastValue * 256)]))
return
def parseNumber(numberString, lineNumber):
prefix = numberString[0]
numberString = numberString[1:]
result = 0
if (prefix == "$" or prefix == "@"):
result = int(numberString, 16)
if (result > 65535):
integerError(lineNumber)
elif (prefix == "#"):
result = int(numberString)
if (result > 65535):
integerError(lineNumber)
elif (prefix == "R" and numberString.isdigit() and int(numberString) <= 15):
result = int(numberString)
if (result > 15):
integerError(lineNumber)
else: #is a label
result = getLocationOfLabel(prefix + numberString)
if (result == -1 and lineNumber == -1): #second time around
referenceNotFoundError(prefix + numberString)
elif (result == -1):
return "LABEL-" + (prefix + numberString)
if (result > 65535):
integerError(lineNumber)
if (result < 0):
integerError(lineNumber)
return result
def encode(line, lineNumber):
#convert to list of integers
opcode = line[0]
operand0 = 0
operand1 = 0
twoWord = False
#check instruction format:
if (opcode == "JMP"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
twoWord = True
operand0 = int("0000", 16)
operand1 = parseNumber(line[1], lineNumber)
elif (opcode == "JEQ"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
twoWord = True
operand0 = int("0100", 16)
operand1 = parseNumber(line[1], lineNumber)
elif (opcode == "JLT"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
twoWord = True
operand0 = int("0200", 16)
operand1 = parseNumber(line[1], lineNumber)
elif (opcode == "JGE"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
twoWord = True
operand0 = int("0300", 16)
operand1 = parseNumber(line[1], lineNumber)
elif (opcode == "LOAD"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
varVal = getVarIndex(line[2]) #check if references variable
if (line[1][0] == "R" and not(str(varVal)[0] == "-")):
twoWord = True
operand0 = int("0400", 16) + (parseNumber(line[1], lineNumber) * 16)
operand1 = varVal
elif (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("1900", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
elif (line[1][0] == "R" and line[2][0] == "@"):
twoWord = True
operand0 = int("0400", 16) + (parseNumber(line[1], lineNumber) * 16)
operand1 = parseNumber(line[2], lineNumber)
elif (line[1][0] == "R" and (line[2][0] == "$" or line[2][0] == "#")):
twoWord = True
operand0 = int("0500", 16) + (parseNumber(line[1], lineNumber) * 16)
operand1 = parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "STORE"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0700", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
elif (line[1][0] == "R" and line[2][0] == "@"):
twoWord = True
operand0 = int("0600", 16) + (parseNumber(line[1], lineNumber) * 16)
operand1 = parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "TRAN"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0800", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "ADD"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0900", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "SUB"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0A00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "MULT"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0B00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "DIV"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0C00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "INC"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
if (line[1][0] == "R"):
operand0 = int("0D00", 16) + (parseNumber(line[1], lineNumber) * 16)
else:
syntaxError(lineNumber)
elif (opcode == "DEC"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
if (line[1][0] == "R"):
operand0 = int("0E00", 16) + (parseNumber(line[1], lineNumber) * 16)
else:
syntaxError(lineNumber)
elif (opcode == "AND"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("0F00", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "OR"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("1000", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "XOR"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("1100", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "NOT"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
if (line[1][0] == "R"):
operand0 = int("1200", 16) + (parseNumber(line[1], lineNumber) * 16)
else:
syntaxError(lineNumber)
elif (opcode == "ROL"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (not(line[1][0]) == line[2][0] and line[1][0] == "R"):
operand0 = int("1300", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "ROR"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (not(line[1][0] == line[2][0]) and line[1][0] == "R"):
operand0 = int("1400", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "CMP"):
if (not(len(line) == 3)):
syntaxError(lineNumber)
if (line[1][0] == line[2][0] and line[1][0] == "R"):
operand0 = int("1500", 16) + (parseNumber(line[1], lineNumber) * 16) + parseNumber(line[2], lineNumber)
else:
syntaxError(lineNumber)
elif (opcode == "CLC"):
if (not(len(line) == 1)):
syntaxError(lineNumber)
operand0 = int("1600", 16)
elif (opcode == "STC"):
if (not(len(line) == 1)):
syntaxError(lineNumber)
operand0 = int("1700", 16)
elif (opcode == "NOP"):
if (not(len(line) == 1)):
syntaxError(lineNumber)
operand0 = int("1800", 16)
elif (len(line) == 3 and line[1] == "="): #variables
if (len(program) > 0):
varSequenceError(lineNumber)
data.append(createLine(line[0], line[2]))
return None
elif (len(line) == 1 and line[0] == ".DATA"):
return None
elif (len(line) == 1 and line[0] == ".CODE"):
#ADD JUMP TO START OF PROGRAM
data.insert(0, createLine("", len(data) + 2)) #number of words in data section
data.insert(0, createLine("", int("0000", 16))) #JMP
return None
elif (opcode == "ORG"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
targetAddress = parseNumber(line[1], lineNumber)
currentAddress = getCurrentAddress()
if (currentAddress > targetAddress):
orgError(lineNumber)
while(currentAddress < targetAddress):
program.append(createLine("", [0]))
currentAddress = currentAddress + 1
return None
elif (opcode == ".INC"):
if (not(len(line) == 2)):
syntaxError(lineNumber)
line[1] = line[1].replace("\"", "")
line[1] = line[1].replace("\'", "")
if (not(os.path.isfile(line[1]))):
incResourceError(line[1], lineNumber)
includeBIN(line[1])
return None
else:
unrecognizedError(lineNumber)
if (not twoWord):
#print(str(hex(operand0)).upper())
return [operand0]
else:
#print(str(hex(operand0)).upper() + ", " + str(hex(operand1)).upper())
return [operand0, operand1]
def parseProgram():
global output
global compiled
global data
for value in data:
if (len(value[0]) > 0):
value[1] = parseNumber(value[1], 0)
output.append(value[1])
for operations in program:
for value in operations[1]:
output.append(value)
if (len(output) > 65536):
lengthError(len(output) - 65536)
compiled = True
return
def parseUnmarkedLabels():
pLine = 0
for operations in program:
valLine = 0
for val in operations[1]:
if ("LABEL" in str(val)):
program[pLine][1][valLine] = parseNumber(val[6:], -1)
valLine = valLine + 1
pLine = pLine + 1
return
def compileASM(filepath):
file = open(filepath, "r")
lineNumber = 1 #file line number for specifying errors
for line in file:
#print(line)
line = line.upper()
line = line.split(";") #getting rid of comments
line[0] = line[0].replace("\n", "") #removing return line
line[0] = line[0].replace("\r", "")
line[0] = line[0].strip()
#print(line)
if (len(line[0]) > 0):
parseLine(line[0], lineNumber)
lineNumber = lineNumber + 1
parseUnmarkedLabels()
parseProgram()
compileResults()
def parseLine(line, lineNumber):
global labelOpen
global labelToUse
labelLine = line.split(":");
label = labelLine[0]
if (":" in line and len(labelLine[1]) <= 1):
if (labelOpen):
labelError(lineNumber)
labelToUse = label #add a label with no operations to program
labelOpen = True
return
elif (":" not in line):
if (labelOpen):
label = labelToUse
labelOpen = False
else:
label = ""
else:
if (labelOpen):
labelError(lineNumber)
line = labelLine[1].strip()
line = line.split(" ")
#print(str(lineNumber) + "\t" + str(label) + "\t" + str(line))
operations = encode(line, lineNumber)
if (not(operations == None)):
program.append(createLine(label, operations))
return
def sendToSpreadsheet():
#load excel file
workbook = load_workbook(filename = spreadsheet)
#open workbook
sheet = workbook.active
try:
i = 0
while (i < pow(2, 16)):
if (i < len(output)):
sheet.cell(row = math.floor(i / 256) + 1, column = (i % 256) + 1, value = output[i])
else:
sheet.cell(row = math.floor(i / 256) + 1, column = (i % 256) + 1, value = 0)
i = i + 1
#save the file
workbook.save(filename = spreadsheet)
except:
ROMbookError()
return
def compileResults():
if (not(compiled)):
print(RED + "\tProgram could not be compiled" + ENDCOLOR)
else:
print("\tProgram compiled Successfully")
#print(output)
print("\tProgram length in words: " + str(getCurrentAddress()))
print("\tWriting to spreadsheet ROM...")
sendToSpreadsheet()
print("\tFinished in " + str(time.time()-startTime)[:6] + "s")
exit()
if __name__ == "__main__":
startTime = time.time()
os.system('color')
print("\tStarting operation...")
if (len(sys.argv) == 3):
filePath = sys.argv[1]
spreadsheet = sys.argv[2]
elif (len(sys.argv) == 1):
print(RED + "\tInsufficent arguments, no ASM file specified" + ENDCOLOR)
compileResults()
elif (len(sys.argv) == 2):
print(RED + "\tInsufficent arguments, no target spreadsheet specified" + ENDCOLOR)
compileResults()
else:
print(RED + "\tArguments too many" + ENDCOLOR)
compileResults()
if (not(os.path.isfile(filePath))):
print(RED + "\tFile " + filePath + " not found" + ENDCOLOR)
compileResults()
compileASM(filePath)
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/labs/excelCPU.git
git@gitee.com:labs/excelCPU.git
labs
excelCPU
excelCPU
main

搜索帮助