diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6a0dc8a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+./**/test_strip.csv
+./**/__pycache__
+unit_tests.py
+tests/
diff --git a/Doc/Instructions.md b/Doc/Instructions.md
new file mode 100644
index 0000000..3f6d794
--- /dev/null
+++ b/Doc/Instructions.md
@@ -0,0 +1,67 @@
+Instrucciones:
+
+En el diseño de las instrucciones se ha intentado mantener
+libre los opcodes disponibles en la medida de lo posible para
+posibilitar la introducción de nuevas instrucciónes en el futuro
+haciendo los opcodes lo más largos posibles.
+
+ D = Dirección
+ I = Inmediato
+ S = Bits de selección
+ R = Registro de lectura
+ W = Registro de escritura
+
+noop: 0000 00XX XXXX XXXX: No toma operandos
+
+jump: 0000 01DD DDDD DDDD: Salto a D
+
+jumpz: 0000 10DD DDDD DDDD: Salto a D si flag Zero = 1
+
+nojumpz: 0000 11DD DDDD DDDD: Salto a D si flag Zero = 0
+
+limm: 0001 IIII IIII WWWW: Cargar I en W
+
+jal: 0010 00DD DDDD DDDD: Salto a D guardando dir. retorno (PC + 1)
+
+ret: 0010 01XX XXXX XXXX: No toma operandos
+
+read: 0010 10SS XXXX WWWW: SS seleccionan el puerto de lectura
+
+write: 0010 11SS RRRR XXXX: SS seleccionan el puerto de escritura
+
+MOV: 1000 RRRR XXXX WWWW: Guarda R en W
+
+NEG: 1001 RRRR XXXX WWWW: Niega R y guarda en W
+
+ADD: 1010 RRRR RRRR WWWW: R1 + R2 -> W
+
+SUB: 1011 RRRR RRRR WWWW: R1 - R2 -> W
+
+AND: 1100 RRRR RRRR WWWW: R1 & R2 -> W
+
+OR: 1101 RRRR RRRR WWWW: R1 | R2 -> W
+
+SIGNA: 1110 RRRR XXXX WWWW: Cambia signo a R y guarda en W
+
+SIGNB: 1110 XXXX RRRR WWWW: Cambia signo a R y guarda en W
+
+
+E/S:
+La entrada salida se compone de un banco de cuatro registros para la
+salida en el que se escriben los datos y cuatro puertos de entrada.
+La salida se compone unicamente de varios multiplexores y wires.
+No se han implementado escritura de inmediatos para no gastar opcodes
+y por ser menos flexibles que la escritura desde registro.
+
+Timer:
+El timer esta diseñado para tener una presición de 1ms al conectarse
+a un relog de 24MHz. Es necesario pasarle un numero(8b) de ms que en
+el caso de esta cpu se envia por el puerto 0 y permite generar señales
+periódicas de entre 1ms y 250ms.
+
+Interrupciones:
+La cpu permite 4 interrupciones externas que selecciónan una dirección
+de memoria donde se deberá encontrar una subrutina que termine en una
+instrucción ret que devuelva la ejecución del programa a su cauce normal.
+Hasta que no implemente una pila para los JAL cualquier interrupción
+sobrescribirá cualquier información presente en el registro de retorno.
diff --git a/QTui/qtSCC/.gitignore b/QTui/qtSCC/.gitignore
new file mode 100644
index 0000000..fab7372
--- /dev/null
+++ b/QTui/qtSCC/.gitignore
@@ -0,0 +1,73 @@
+# This file is used to ignore files which are generated
+# ----------------------------------------------------------------------------
+
+*~
+*.autosave
+*.a
+*.core
+*.moc
+*.o
+*.obj
+*.orig
+*.rej
+*.so
+*.so.*
+*_pch.h.cpp
+*_resource.rc
+*.qm
+.#*
+*.*#
+core
+!core/
+tags
+.DS_Store
+.directory
+*.debug
+Makefile*
+*.prl
+*.app
+moc_*.cpp
+ui_*.h
+qrc_*.cpp
+Thumbs.db
+*.res
+*.rc
+/.qmake.cache
+/.qmake.stash
+
+# qtcreator generated files
+*.pro.user*
+
+# xemacs temporary files
+*.flc
+
+# Vim temporary files
+.*.swp
+
+# Visual Studio generated files
+*.ib_pdb_index
+*.idb
+*.ilk
+*.pdb
+*.sln
+*.suo
+*.vcproj
+*vcproj.*.*.user
+*.ncb
+*.sdf
+*.opensdf
+*.vcxproj
+*vcxproj.*
+
+# MinGW generated files
+*.Debug
+*.Release
+
+# Python byte code
+*.pyc
+
+# Binaries
+# --------
+*.dll
+*.exe
+
diff --git a/QTui/qtSCC/bucle.csv b/QTui/qtSCC/bucle.csv
new file mode 100644
index 0000000..b1ae83d
--- /dev/null
+++ b/QTui/qtSCC/bucle.csv
@@ -0,0 +1,10 @@
+noop
+limm 0 R1
+limm 1 R2
+limm 10 R3
+:for
+add R1 R2 R1
+sub R3 R1 zero
+jnz for
+:end
+jump end
diff --git a/QTui/qtSCC/form.ui b/QTui/qtSCC/form.ui
new file mode 100644
index 0000000..d488e97
--- /dev/null
+++ b/QTui/qtSCC/form.ui
@@ -0,0 +1,88 @@
+
+
+ qtSCC
+
+
+
+ 0
+ 0
+ 800
+ 600
+
+
+
+ qtSCC
+
+
+
+
+ 10
+ 10
+ 781
+ 581
+
+
+
+ -
+
+
-
+
+
+ false
+
+
+
+ -
+
+
+ Search
+
+
+
+ -
+
+
+ Assemble
+
+
+
+
+
+ -
+
+
-
+
+
+ -
+
+
-
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ Save
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/QTui/qtSCC/main.py b/QTui/qtSCC/main.py
new file mode 100755
index 0000000..2a474ad
--- /dev/null
+++ b/QTui/qtSCC/main.py
@@ -0,0 +1,75 @@
+# This Python file uses the following encoding: utf-8
+import sys
+import tempfile
+
+from PyQt5.QtGui import *
+from PyQt5.QtWidgets import *
+from PyQt5.QtCore import *
+
+from qtSCC import Ui_qtSCC
+import os
+sys.path.append(os.path.abspath('../../SCC'))
+import SCCUtils
+
+class qtSCC(QMainWindow, Ui_qtSCC):
+ def __init__(self, *args, **kwargs):
+ super(qtSCC, self).__init__(*args, **kwargs)
+ self.setupUi(self)
+ self.virtual_file = tempfile.SpooledTemporaryFile(mode = "w+", encoding = "utf-8", dir = "/tmp/")
+ self.binaryCode = []
+ self.translationQueue = []
+
+ self.SearchButton.clicked.connect(self.onSearchButtonClicked)
+ self.assembleButton.clicked.connect(self.onAssembleButtonClicked)
+ self.saveButton.clicked.connect(self.onSaveButtonClicked)
+ self.fileList.itemClicked.connect(self.onFileListItemClicked)
+ self.translateList.itemClicked.connect(self.onTranslateListItemClicked)
+
+ self.show()
+
+ def onSaveButtonClicked(self):
+ pass
+ # fileName = self.saveEdit.text()
+ # SCCUtils.writeList2File(fileName, self.binaryCode)
+
+ def onAssembleButtonClicked(self):
+ for fileName in self.translationQueue:
+ binaryCode = self.assembleFile(fileName)
+ binFileName = fileName.split('.')[0];
+ binFileName = binFileName + ".bin"
+ SCCUtils.writeList2File(binFileName, binaryCode)
+ self.translationQueue = [];
+
+ def onSearchButtonClicked(self):
+ self.fileList.clear()
+ path = self.inputEdit.text()
+ path = QDir(path)
+ print(path.dirName())
+ path.setFilter(QDir.Files)
+ contentsList = path.entryList()
+ for content in contentsList:
+ basePath = self.inputEdit.text()
+ filePath = os.path.join(basePath, content)
+ self.fileList.addItem(content)
+
+ def onFileListItemClicked(self, item):
+ basePath = self.inputEdit.text()
+ filePath = os.path.join(basePath, item.text())
+ self.translateList.addItem(item.text())
+ self.translationQueue.append(filePath)
+
+ def onTranslateListItemClicked(self, item):
+ self.translationQueue.remove(item.text())
+ self.translateList.takeItem(self.translateList.currentRow())
+
+ def assembleFile(self, fileName):
+ with open(fileName, 'r') as inputFile:
+ SCCUtils.strip_input(self.virtual_file, inputFile)
+ SCCUtils.operateFile(self.virtual_file, SCCUtils.resolveDirections)
+ binaryCode = SCCUtils.operateFile(self.virtual_file, SCCUtils.translate)
+ return binaryCode
+
+if __name__ == "__main__":
+ app = QApplication([])
+ window = qtSCC()
+ app.exec_()
diff --git a/QTui/qtSCC/main.pyproject b/QTui/qtSCC/main.pyproject
new file mode 100644
index 0000000..7d87836
--- /dev/null
+++ b/QTui/qtSCC/main.pyproject
@@ -0,0 +1,3 @@
+{
+ "files": ["main.py","form.ui","qtSCC.py"]
+}
diff --git a/QTui/qtSCC/main.pyproject.user b/QTui/qtSCC/main.pyproject.user
new file mode 100644
index 0000000..e3803c2
--- /dev/null
+++ b/QTui/qtSCC/main.pyproject.user
@@ -0,0 +1,280 @@
+
+
+
+
+
+ EnvironmentId
+ {7c7d081b-5747-45bc-be8a-d21fa9398b84}
+
+
+ ProjectExplorer.Project.ActiveTarget
+ 0
+
+
+ ProjectExplorer.Project.EditorSettings
+
+ true
+ false
+ true
+
+ Cpp
+
+ CppGlobal
+
+
+
+ QmlJS
+
+ QmlJSGlobal
+
+
+ 2
+ UTF-8
+ false
+ 4
+ false
+ 80
+ true
+ true
+ 1
+ true
+ false
+ 0
+ true
+ true
+ 0
+ 8
+ true
+ 1
+ true
+ true
+ true
+ *.md, *.MD, Makefile
+ false
+ true
+
+
+
+ ProjectExplorer.Project.PluginSettings
+
+
+ true
+ true
+ true
+ true
+ true
+
+
+ 0
+ true
+
+ true
+ Builtin.Questionable
+
+ true
+ Builtin.DefaultTidyAndClazy
+ 6
+
+
+
+ true
+
+
+
+
+ ProjectExplorer.Project.Target.0
+
+ Desktop
+ Desktop
+ Desktop
+ {c334e0b1-3017-498a-a866-1e8f5e327be9}
+ -1
+ 0
+ 0
+ 0
+
+
+ 0
+ Deploy
+ Deploy
+ ProjectExplorer.BuildSteps.Deploy
+
+ 1
+
+ false
+ ProjectExplorer.DefaultDeployConfiguration
+
+ 1
+
+
+ dwarf
+
+ cpu-cycles
+
+
+ 250
+
+ -e
+ cpu-cycles
+ --call-graph
+ dwarf,4096
+ -F
+ 250
+
+ -F
+ true
+ 4096
+ false
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ kcachegrind
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+
+ 2
+
+ main
+ PythonEditor.RunConfiguration./home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/main.py
+ /home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/main.py
+ false
+ {30058bf9-10bb-4a47-9c8c-82886b053a6c}
+ /home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/main.py
+
+ false
+
+ false
+ true
+ false
+ false
+ true
+
+
+
+
+ dwarf
+
+ cpu-cycles
+
+
+ 250
+
+ -e
+ cpu-cycles
+ --call-graph
+ dwarf,4096
+ -F
+ 250
+
+ -F
+ true
+ 4096
+ false
+ false
+ 1000
+
+ true
+
+ false
+ false
+ false
+ false
+ true
+ 0.01
+ 10
+ true
+ kcachegrind
+ 1
+ 25
+
+ 1
+ true
+ false
+ true
+ valgrind
+
+ 0
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 14
+
+
+ 2
+
+ qtSCC
+ PythonEditor.RunConfiguration./home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/qtSCC.py
+ /home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/qtSCC.py
+ false
+ {30058bf9-10bb-4a47-9c8c-82886b053a6c}
+ /home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC/qtSCC.py
+
+ false
+
+ false
+ true
+ false
+ false
+ true
+
+ /home/david/Documents/ULL/Disenno/compiler/QTui/qtSCC
+
+ 2
+
+
+
+ ProjectExplorer.Project.TargetCount
+ 1
+
+
+ ProjectExplorer.Project.Updater.FileVersion
+ 22
+
+
+ Version
+ 22
+
+
diff --git a/QTui/qtSCC/qtSCC.py b/QTui/qtSCC/qtSCC.py
new file mode 100644
index 0000000..88585bc
--- /dev/null
+++ b/QTui/qtSCC/qtSCC.py
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'form.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.0
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+import sys
+
+
+
+class Ui_qtSCC(object):
+
+ def setupUi(self, qtSCC):
+ qtSCC.setObjectName("qtSCC")
+ qtSCC.resize(800, 600)
+ self.verticalLayoutWidget = QtWidgets.QWidget(qtSCC)
+ self.verticalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 781, 581))
+ self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_2.setObjectName("horizontalLayout_2")
+ self.inputEdit = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+ self.inputEdit.setReadOnly(False)
+ self.inputEdit.setObjectName("inputEdit")
+ self.horizontalLayout_2.addWidget(self.inputEdit)
+ self.SearchButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
+ self.SearchButton.setObjectName("SearchButton")
+ self.horizontalLayout_2.addWidget(self.SearchButton)
+ self.assembleButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
+ self.assembleButton.setObjectName("assembleButton")
+ self.horizontalLayout_2.addWidget(self.assembleButton)
+ self.verticalLayout.addLayout(self.horizontalLayout_2)
+ self.horizontalLayout = QtWidgets.QHBoxLayout()
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.fileList = QtWidgets.QListWidget(self.verticalLayoutWidget)
+ self.fileList.setObjectName("fileList")
+ self.horizontalLayout.addWidget(self.fileList)
+ self.verticalLayout_2 = QtWidgets.QVBoxLayout()
+ self.verticalLayout_2.setObjectName("verticalLayout_2")
+ self.translateList = QtWidgets.QListWidget(self.verticalLayoutWidget)
+ self.translateList.setObjectName("translateList")
+ self.verticalLayout_2.addWidget(self.translateList)
+ self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_3.setObjectName("horizontalLayout_3")
+ self.saveEdit = QtWidgets.QLineEdit(self.verticalLayoutWidget)
+ self.saveEdit.setObjectName("saveEdit")
+ self.horizontalLayout_3.addWidget(self.saveEdit)
+ self.saveButton = QtWidgets.QPushButton(self.verticalLayoutWidget)
+ self.saveButton.setObjectName("saveButton")
+ self.horizontalLayout_3.addWidget(self.saveButton)
+ self.verticalLayout_2.addLayout(self.horizontalLayout_3)
+ self.horizontalLayout.addLayout(self.verticalLayout_2)
+ self.verticalLayout.addLayout(self.horizontalLayout)
+
+ self.retranslateUi(qtSCC)
+ QtCore.QMetaObject.connectSlotsByName(qtSCC)
+
+ def retranslateUi(self, qtSCC):
+ _translate = QtCore.QCoreApplication.translate
+ qtSCC.setWindowTitle(_translate("qtSCC", "qtSCC"))
+ self.SearchButton.setText(_translate("qtSCC", "Search"))
+ self.assembleButton.setText(_translate("qtSCC", "Assemble"))
+ self.saveButton.setText(_translate("qtSCC", "Save"))
+
+
diff --git a/SCC/SCCDicts.py b/SCC/SCCDicts.py
new file mode 100644
index 0000000..818776d
--- /dev/null
+++ b/SCC/SCCDicts.py
@@ -0,0 +1,81 @@
+
+directions = {}
+
+# O -> opcode
+# 0 -> empty
+# X -> opcode
+# Z -> opcode
+# Y -> opcode
+JUMP_RULE = 'OOOOOOXXXXXXXXXX'
+ALU_LEFT_RULE = 'OOOOXXXX0000YYYY'
+ALU_RIGHT_RULE = 'OOOO0000XXXXYYYY'
+ALU_BOTH_RULE = 'OOOOXXXXYYYYZZZZ'
+IMM_RULE = 'OOOOXXXXXXXXYYYY'
+NOOP_RULE = 'OOOOOO0000000000'
+PORT_READ_RULE = 'OOOOOOXX0000YYYY'
+PORT_WRITE_RULE = 'OOOOOOXXYYYYZZZZ'
+WORD_WRITE_RULE = 'OOOOYYYYXXXXXXXX'
+WORD_READ_RULE = 'OOOOXXXXXXXXYYYY'
+ADDR_WRITE_RULE = 'OOOOXXXXYYYY0000'
+ADDR_READ_RULE = 'OOOO0000XXXXYYYY'
+
+prep_rules = {
+ }
+
+registers = { 'zero':'0000',
+ 'R1': '0001',
+ 'R2': '0010',
+ 'R3': '0011',
+ 'R4': '0100',
+ 'R5': '0101',
+ 'R6': '0110',
+ 'R7': '0111',
+ 'R8': '1000',
+ 'R9': '1001',
+ 'R10': '1010',
+ 'R11': '1011',
+ 'R12': '1100',
+ 'R13': '1101',
+ 'R14': '1110',
+ 'R15': '1111'
+ }
+
+rules = { 'noop': NOOP_RULE,
+ 'jump': JUMP_RULE,
+ 'jz': JUMP_RULE,
+ 'jnz': JUMP_RULE,
+ 'li': IMM_RULE,
+ 'lw': WORD_READ_RULE,
+ 'sw': WORD_WRITE_RULE,
+ 'la': ADDR_READ_RULE,
+ 'sa': ADDR_WRITE_RULE,
+ 'call': JUMP_RULE,
+ 'ret': NOOP_RULE,
+ 'mov': ALU_LEFT_RULE,
+ 'not': ALU_LEFT_RULE,
+ 'add': ALU_BOTH_RULE,
+ 'sub': ALU_BOTH_RULE,
+ 'and': ALU_BOTH_RULE,
+ 'or': ALU_BOTH_RULE,
+ 'neg': ALU_LEFT_RULE
+ }
+
+opcodeDict = { 'noop':'000000',
+ 'jump':"000001",
+ 'jz':'000010',
+ 'jnz':'000011',
+ 'li':'0001',
+ 'call':'010000',
+ 'ret':'010100',
+ 'lw':'0010',
+ 'sw':'0011',
+ 'la':'0110',
+ 'sa':'0111',
+ 'mov':'1000',
+ 'not':'1001',
+ 'add':'1010',
+ 'sub':'1011',
+ 'and':'1100',
+ 'or':'1101',
+ 'neg':'1110'
+ }
diff --git a/SCC/SCCUtils.py b/SCC/SCCUtils.py
new file mode 100644
index 0000000..fecccf9
--- /dev/null
+++ b/SCC/SCCUtils.py
@@ -0,0 +1,143 @@
+import csv
+import re
+
+from SCCDicts import *
+
+def writeList2File(fileName, list, append=0):
+ mode = ('w', 'a')[append]
+ with open(fileName, mode) as file:
+ for item in list:
+ file.write(f'{item}\n')
+
+def isRegister(operand):
+ return registers[operand]
+
+def isImm(operand):
+
+ if int(operand) > 128:
+ raise Exception(f'Operand too large. Must be under 8 bits. Received {operand}')
+
+ operand = format(int(operand), '08b')
+ return operand
+
+def isOther(operand):
+ if operand in prep_rules:
+ return opType(prep_rules[operand])
+ if operand in directions:
+ return directions[operand]
+ else:
+ raise Exception(f'Operand not recognized. Received {operand}')
+
+def isAddr(operand):
+ address = re.search(r'([0-9]+)', operand).group()
+
+ if re.match(r'^io\([0-9]+\)',operand):
+ return '000000' + format(int(address), '02b')
+ if re.match(r'^int\([0-9]+\)',operand):
+ return '00001' + format(int(address), '03b')
+ if re.match(r'^data\([0-9]+\)',operand):
+ return '1' + format(int(address), '07b')
+
+def opType(operand):
+ regexps = [r'(?:R(?:1[0-5]|[1-9])|zero)', r'[0-9]+', r'(io|data|int)\(([0-9]+)\)', r'[:a-zA-Z0-9]']
+ functions = [isRegister, isImm, isAddr, isOther] # This is a function list
+ index = -1
+ for regex in regexps:
+ index += 1
+ if re.match(regex, operand):
+ # Now a function is applied to the item to turn it into binary code
+ return functions[index](operand)
+
+ raise Exception(f'Operand {operand} is not valid')
+
+def operateFile(file, func):
+ result = func(file)
+ file.seek(0)
+ return result
+
+def translate(file):
+ #Transform assembly instructions into machine code.
+
+ result = []
+ for line in file:
+ operation = ''
+ opcode = ''
+
+ line = line.strip('\n')
+ items = line.split(' ')
+ items = list(filter(None, items))
+
+ if items[0] in opcodeDict:
+ operation = rules[items[0]]
+ opcode = opcodeDict[items[0]]
+ operation = re.sub(r'O+', opcode, operation)
+
+ items.remove(items[0])
+
+ s = 'X'
+ for item in items:
+ operand = opType(item)
+ occurences = len(re.search(s+'+', operation).group())
+ operation = re.sub(s+'+', operand[:occurences], operation)
+ s = chr((ord(s) + 1))
+
+ result.append(str(operation))
+ elif items[0][0] == ':':
+ continue
+ else:
+ raise Exception(f'ERROR: {line.split()[0]} in not a valid opcode')
+ return result
+
+def resolveDirections(file):
+
+ instructionDir = 0
+ for line in file:
+ match = re.search(r'^:([a-zA-Z0-9_-]+)', line)
+ if match:
+ directions[match.group(1)] = format(instructionDir, '010b')
+ else:
+ instructionDir += 1
+
+
+def strip_input(out_file, csvFile):
+ #with open(path, 'r') as csvFile:
+ lines = csvFile.read().splitlines()
+ code_section = preprocess(lines)
+ for line in lines[code_section:]:
+ line = line.strip()
+ if line:
+ if re.match(r'^#', line): #If line is a comment ignore it
+ continue
+ elif re.search(r'#', line): #Strip comment ater instruction
+ index = re.search(r'#', line).start()
+ out_file.write(line[0:index]+'\n')
+ else: #Add instruction to virtual file
+ out_file.write(line+'\n')
+ #Make file ready to be read again
+ out_file.seek(0)
+
+
+def read_mem_file( input_file ):
+ #assembly_code will contain the lines of assembly code to translate
+ with open(input_file, 'r') as infile:
+ return_code = []
+ assembly_code = csv.DictReader(infile, delimiter = ' ',
+ fieldnames = ["opcode", "op1", "op2"],
+ restval = None,
+ quoting = csv.QUOTE_NONE)
+ for instruction in assembly_code:
+ opc, op1, op2 = instruction["opcode"], instruction["op1"], instruction["op2"]
+ return_code.append({"opcode":opc, "op1":op1, "op2":op2})
+ return return_code
+
+def preprocess( lines ):
+ begining = 0
+ for line in lines:
+ if line != '.code':
+ match = re.search(r'^use ([a-zA-Z0-9]+) as ([a-zA-Z0-9\(\)]+$)',line)
+ if match is not None:
+ prep_rules[match.group(1)] = match.group(2)
+ begining += 1
+ else:
+ return begining + 1
+ return None
diff --git a/SCC/__pycache__/SCCDicts.cpython-38.pyc b/SCC/__pycache__/SCCDicts.cpython-38.pyc
new file mode 100644
index 0000000..4860d8b
Binary files /dev/null and b/SCC/__pycache__/SCCDicts.cpython-38.pyc differ
diff --git a/SCC/__pycache__/SCCDicts.cpython-39.pyc b/SCC/__pycache__/SCCDicts.cpython-39.pyc
new file mode 100644
index 0000000..032adf7
Binary files /dev/null and b/SCC/__pycache__/SCCDicts.cpython-39.pyc differ
diff --git a/SCC/__pycache__/SCCUtils.cpython-38.pyc b/SCC/__pycache__/SCCUtils.cpython-38.pyc
new file mode 100644
index 0000000..2c4cd68
Binary files /dev/null and b/SCC/__pycache__/SCCUtils.cpython-38.pyc differ
diff --git a/SCC/__pycache__/SCCUtils.cpython-39.pyc b/SCC/__pycache__/SCCUtils.cpython-39.pyc
new file mode 100644
index 0000000..49c6519
Binary files /dev/null and b/SCC/__pycache__/SCCUtils.cpython-39.pyc differ
diff --git a/SCC/assembler.py b/SCC/assembler.py
new file mode 100755
index 0000000..aef4e29
--- /dev/null
+++ b/SCC/assembler.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python3
+
+import sys
+import tempfile
+
+from SCCUtils import *
+
+
+def main(argv):
+ #Create virtual file
+
+ in_file_name = ""
+ out_file_name = ""
+
+ for i in range(len(argv)):
+ if argv[i] == "-i":
+ in_file_name = argv[i + 1]
+ i = i + 1
+ elif argv[i] == "-o":
+ out_file_name = argv[i + 1]
+ i = i + 1
+
+ virtual_file = tempfile.SpooledTemporaryFile(mode = "w+", encoding = "utf-8", dir = "/tmp/")
+
+ #Open input file
+ input_file = open( in_file_name, 'r' )
+ #Strip file
+ strip_input(virtual_file, input_file)
+ #resolve jump directions
+ operateFile(virtual_file, resolveDirections)
+ #translate asm into machine code
+ instructions = operateFile(virtual_file, translate)
+ input_file.close()
+ #write codd to file
+ writeList2File(out_file_name, instructions)
+
+
+
+
+
+if __name__ == "__main__":
+ main(sys.argv)
diff --git a/SCC/bucle.csv b/SCC/bucle.csv
new file mode 100644
index 0000000..b1ae83d
--- /dev/null
+++ b/SCC/bucle.csv
@@ -0,0 +1,10 @@
+noop
+limm 0 R1
+limm 1 R2
+limm 10 R3
+:for
+add R1 R2 R1
+sub R3 R1 zero
+jnz for
+:end
+jump end
diff --git a/SCC/sasm.vim b/SCC/sasm.vim
new file mode 100644
index 0000000..d0942d2
--- /dev/null
+++ b/SCC/sasm.vim
@@ -0,0 +1,39 @@
+" Vim syntax file
+" Language: SASM
+" Maintainer: David Martin
+" Latest Revision: 6/4/2021 d/m/y
+
+if exists("b:current_syntax")
+ finish
+endif
+
+
+syn match comment '#.*$'
+syn match preproc '^\.code$'
+syn keyword preproc use nextgroup=const
+syn keyword preproc as
+syn keyword opcode noop ret sw lw sa la call or add sub not movsyn
+syn keyword opcode li nextgroup=number,const
+syn keyword opaddr jump jz jnz call nextgroup=addrtag,number skipwhite
+syn match const '\w\+'
+syn match number '\d\+'
+syn match addr '[a-zA-Z0-9_-]\+$'
+syn match addrtag ':[a-zA-Z0-9_-]\+'
+syn match addr 'io(\d\+)'
+syn match addr 'data(\d\+)'
+syn match addr 'int(\d\+)'
+syn match reg 'R\d'
+
+let b:current_syntax = "sasm"
+hi def link opcode Type
+hi def link opaddr Type
+hi def link addr Constant
+hi def link const PreProc
+hi def link reg Statement
+hi def link comment Comment
+hi def link addrtag Statement
+hi def link preproc PreProc
+hi def link number Constant
+"hi def link opaddr Statement
+"hi def link op3Reg Statement
+
diff --git a/SCC/test b/SCC/test
new file mode 100644
index 0000000..252c759
--- /dev/null
+++ b/SCC/test
@@ -0,0 +1,8 @@
+0000000000000000
+0001000000000001
+0001000000010010
+0001000010100011
+1010000100100001
+1011001100010000
+0000110000000100
+0000010000000111
diff --git a/SCC/test_strip.csv b/SCC/test_strip.csv
new file mode 100644
index 0000000..5539198
--- /dev/null
+++ b/SCC/test_strip.csv
@@ -0,0 +1,5 @@
+#This is a comment
+jump etiqueta
+:etiqueta
+add zero R2 R1 #This is a commented line
+limm 127 R3
diff --git a/compile.py b/compile.py
deleted file mode 100755
index 019293e..0000000
--- a/compile.py
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/bin/env python3
-
-import csv
-import sys
-import tempfile
-import re
-
-JUMP_RULE = 'OOOOOOXXXXXXXXXX'
-ALU_LEFT_RULE = 'OOOOXXXX0000YYYY'
-ALU_RIGHT_RULE = 'OOOO0000XXXXYYYY'
-ALU_BOTH_RULE = 'OOOOXXXXYYYYZZZZ'
-IMM_RULE = 'OOOOXXXXXXXXYYYY'
-NOOP_RULE = 'OOOOOO0000000000'
-PORT_READ_RULE = 'OOOOOOXX0000YYYY'
-PORT_WRITE_RULE = 'OOOOOOXXYYYYZZZZ'
-
-registers = { 'zero':'0000',
- 'R1': '0001',
- 'R2': '0010',
- 'R3': '0011',
- 'R4': '0100',
- 'R5': '0101',
- 'R6': '0110',
- 'R7': '0111',
- 'R8': '1000',
- 'R9': '1001',
- 'R10': '1010',
- 'R11': '1011',
- 'R12': '1100',
- 'R13': '1101',
- 'R14': '1110',
- 'R15': '1111'
- }
-
-rules = { 'noop': NOOP_RULE,
- 'jump': JUMP_RULE,
- 'jz': JUMP_RULE,
- 'jnz': JUMP_RULE,
- 'limm': IMM_RULE,
- 'jal': JUMP_RULE,
- 'ret': NOOP_RULE,
- 'read': PORT_READ_RULE,
- 'write': PORT_WRITE_RULE,
- 'mov': ALU_LEFT_RULE,
- 'not': ALU_LEFT_RULE,
- 'add': ALU_BOTH_RULE,
- 'sub': ALU_BOTH_RULE,
- 'and': ALU_BOTH_RULE,
- 'or': ALU_BOTH_RULE,
- 'neg': ALU_LEFT_RULE
- }
-
-opcodeDict = { 'noop':'000000',
- 'jump':"000001",
- 'jz':'000010',
- 'jnz':'000011',
- 'limm':'0001',
- 'jal':'001000',
- 'ret':'001001',
- 'read':'001010',
- 'write':'001011',
- 'mov':'1000',
- 'not':'1001',
- 'add':'1010',
- 'sub':'1011',
- 'and':'1100',
- 'or':'1101',
- 'neg':'1110'
- }
-
-directions = {}
-
-def isRegister(operand):
- return registers[operand]
-
-def isImm(operand):
-
- if int(operand) > 128:
- raise Exception(f'Operand too large. Must be under 8 bits')
-
- operand = format(int(operand), '08b')
- return operand
-
-def isOther(operand):
- if operand in directions:
- return directions[operand]
- else:
- raise Exception(f'Operand not recognized')
-
-
-def opType(operand):
- regexps = [r'(?:R(?:1[0-5]|[1-9])|zero)', r'[0-9]+', r'[:a-zA-Z0-9]']
- functions = [isRegister, isImm, isOther]
- index = -1
- for regex in regexps:
- index += 1
- if re.match(regex, operand):
- return functions[index](operand)
-
- raise Exception(f'operand ', operand, f' is not valid')
-
-def operateFile(file, func):
- result = func(file)
- file.seek(0)
- return result
-
-def translate(file):
- #Transform assembly instructions into machine code.
-
- result = []
- for line in file:
- operation = ''
- opcode = ''
-
- line = line.strip('\n')
- items = line.split(' ')
- items = list(filter(None, items))
-
- if items[0] in opcodeDict:
- operation = rules[items[0]]
- opcode = opcodeDict[items[0]]
- operation = re.sub(r'O+', opcode, operation)
-
- items.remove(items[0])
-
- s = 'X'
- for item in items:
- operand = opType(item)
- operation = re.sub(s+'+', operand, operation)
- s = chr((ord(s) + 1))
-
- result.append(str(operation))
- elif items[0][0] == ':':
- continue
- else:
- raise Exception(f'ERROR: {line[0]} in not a valid opcode')
- return result
-
-def resolveDirections(file):
-
- instructionDir = 0
- for line in file:
- line = line.strip('\n')
- match = re.search(r'^:([a-zA-Z0-9]*)', line)
- if match:
- directions[match.group(1)] = format(instructionDir, '010b')
- else:
- instructionDir += 1
-
-
-def read_file(path):
- file = tempfile.TemporaryFile()
- strip_input(file, path)
- return read_mem_file(file)
-
-
-def strip_input(out_file, csvFile):
- #with open(path, 'r') as csvFile:
- lines = csvFile.read().splitlines()
- for line in lines:
- if re.match(r'^#', line): #If line is a comment ignore it
- continue
- elif re.search(r'#', line): #Strip comment ater instruction
- index = re.search(r'#', line).start()
- out_file.write(line[0:index]+'\n')
- else: #Add instruction to virtual file
- out_file.write(line+'\n')
- #Make file ready to be read again
- out_file.seek(0)
-
-
-def read_mem_file( input_file ):
- #assembly_code will contain the lines of assembly code to translate
- with open(input_file, 'r') as infile:
- return_code = []
- assembly_code = csv.DictReader(infile, delimiter = ' ',
- fieldnames = ["opcode", "op1", "op2"],
- restval = None,
- quoting = csv.QUOTE_NONE)
- for instruction in assembly_code:
- opc, op1, op2 = instruction["opcode"], instruction["op1"], instruction["op2"]
- return_code.append({"opcode":opc, "op1":op1, "op2":op2})
- return return_code
-
-#def strip_comments():
-
-
-def main(argv):
- #Create virtual file
- virtual_file = tempfile.SpooledTemporaryFile(mode = "w+", encoding = "utf-8", dir = "/tmp/")
-
- #Open input file
- input_file = open( "test_strip.csv", 'r' )
-
- #Strip file
- strip_input(virtual_file, input_file)
-
- operateFile(virtual_file, resolveDirections)
- instructions = operateFile(virtual_file, translate)
- input_file.close()
-
-
- with open('a.out', 'w') as file:
- for instruction in instructions:
- file.write(f'{instruction}\n')
-
-
-
-
-
-if __name__ == "__main__":
- main(sys.argv)