Source code for ROMtoVHDL

#!/usr/bin/env python
#-*- coding: utf-8 -*-
import ReadWriteFiles
from MainLib import *

ROMout ="pr_op"
ProgramCounter="pr_pc"

LineProgram=0

startText = "ROM : process ({0}) is\nbegin\n\tcase {1} is\n".format(ProgramCounter, ProgramCounter)
endText = "\twhen others => {0} <= (others => '-');\n\tend case;\nend process;".format(ROMout)

INPorts=[0,1,2]
OUTPorts=[8,9,10]

startRegisterNum=16
endRegisterNum=32

[docs]def readFile(folder): """ Llegeix el fitxer dins del directori :param folder: Directori on hi ha el fitxer ROM :return: El txt amb tot el text """ l = ReadWriteFiles.readlines(folder, ReadWriteFiles.ROM) return l if l != False else exit()
[docs]def getCodeFromFolder(folder): """ Funció principal. Obté el VHDL del fitxer ROM que està dins del directori :param folder: El directori on hi ha els fitxers requerits :return: El txt amb tot el codi VHDL """ lines = readFile(folder) return getCode(lines)
[docs]def getCodeFromFile(file): """ Funció principal. Obté el VHDL del fitxer especificat :param file: Nom del fitxer d'on s'ha d'obtenir les dades :return: El txt amb tot el codi VHDL """ try: f = open(file) l = [value.rstrip("\n") for value in f.readlines() if value != "\n"] f.close() except IOError: exception("El fitxer {0} no existeix".format(file)) return getCode(l)
[docs]def getCode(lines): """ Obté el codi vhdl a partir d'una llista de línies escrites en ROM :param lines: Llista de línies escrites en format ROM :return: El txt de VHDL resultant """ logInfo("ROM-VHDL", "Iniciant conversió de ROM a VHDL") txt=startText counter=0 global LineProgram try: for line in lines: txt +='\twhen x"{:02x}" =>\n'.format(counter) li = line.split() txt += "\t\t{0} <= {1};\n".format(ROMout, Options[li[0]]("" if li[0] == "NOP" else li[1])) counter+=1 LineProgram+=1 txt += endText except KeyError: exception("Clau no correcta", LineProgram, ReadWriteFiles.ROM) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM) logSuccess("Conversió de ROM a VHDL s'ha fet correctament") return txt
[docs]def analyzeRegister(registerStr): """ Analitza si el registre està en el format correcte i és el que toca. El format hauría de ser de tipus r16 :param registerStr: La string del registre :return: El registre passat a bits """ try: if not registerStr.startswith("r"): raise Exception("El format del registre {0} no és valid ".format(registerStr)) if not (startRegisterNum <= int(registerStr[1:]) <= endRegisterNum): raise ValueError() except ValueError: exception("El registre ha d'estar entre {0} and {1}".format(startRegisterNum, endRegisterNum), LineProgram, ReadWriteFiles.ROM) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM) return "{0:b}".format(int(registerStr[1:])).zfill(4)[1:]
[docs]def analyzeHex(hex,n=8): """ Analitza si el valor és hexadecimal :param hex: La string de l'hexadecimal. S'hauria d'esciure en format x12 :param n: El nombre de bits que ha de tenir la string retornada :return: El valor hexadecimal passat a bits de llargada n >>> analyzeHex("x1") '00000001' >>> analyzeHex("x2", 4) '0010' """ try: hexVal = hex.replace("x","") return bin(int(hexVal, 16))[2:].zfill(n)[:n] except ValueError: exception("El registre {0} no està en el format correcte".format(hex))
[docs]def analyzeNOP(line): """ Analitza la NOP :param line: paràmetre que en aquest cas és inútil, però necessàri perquè cridem tots els analize amb un paràmetre :return: Retorna la comanda passada a VHDL """ return 'NOP & "0000" & "--------"'
[docs]def analyzeLDI(params): """ Analitza el LDI :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ p = params.split(",") if len(p) != 2: exception("LDI només té 2 paràmetres", LineProgram, ReadWriteFiles.ROM) register = analyzeRegister(p[0]) hex = analyzeHex(p[1]) return 'LDI & "{0}" & "{1}" & "{2}"'.format(hex[:4], register, hex[4:8])
[docs]def analyzeADC(params): """ Analitza el ADC :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ p = params.split(",") if len(p) != 2: exception("ADC has only 2 params", LineProgram, ReadWriteFiles.ROM) registre1=analyzeRegister(p[0]) registre2=analyzeRegister(p[1]) return 'ADC & "1111" & "{0}" & "{1}"'.format(registre1,registre2)
[docs]def analizeALU_B(parametres, type): """ Analitza l'ALU_B :param parametres: Paràmetres que ens passa l'usuari :param type: El tipus de ALU_B (recordar que hi havia MOV, AND, EOR...) :return: Retorna la comanda passada a VHDL """ p = parametres.split(",") if len(p) != 2: exception("{0} només té 2 paràmetres".format(type), LineProgram, ReadWriteFiles.ROM) registre1 = analyzeRegister(p[0]) registre2 = analyzeRegister(p[1]) return 'ALU_B & {0} & "00" & "{1}" & "{2}"'.format(type, registre1, registre2)
[docs]def analizeRJMP(params): """ Analitza RJMP :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ try: if len(params.split(",")) != 1: raise Exception("RJMP només té 1 paràmetre") jump = bin(int(params) % (1 << 12))[2:].zfill(12) return 'RJMP & "----" & "{0}" & "{1}"'.format(jump[4:8],jump[8:]) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM)
[docs]def analizeBREQ(params): """ Analitza el BREQ :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ try: if len(params.split(",")) != 1: raise Exception("BREQ només té 1 paràmetre") jump=bin(int(params)%(1<<7))[2:].zfill(7) return 'BRANCH & "00{0}" & "{1}" & "{2}001"'.format(jump[:2], jump[2:6], jump[6]) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM)
[docs]def analizeBRNE(params): """ Analitza el BRNE :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ try: if len(params.split(",")) != 1: raise Exception("BRNE només té 1 paràmetre") jump=bin(int(params)%(1<<7))[2:].zfill(7) return 'BRANCH & "01{0}" & "{1}" & "{2}001"'.format(jump[:2], jump[2:6], jump[6]) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM)
[docs]def analizeMOV(parametres): """ Analitza el MOV :param parameters: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeALU_B(parametres, "ALU_B_MOV")
[docs]def analizeAND(parametres): """ Analitza AND :param parameters: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeALU_B(parametres, "ALU_B_AND")
[docs]def analizeOR(parametres): """ Analitza OR :param parameters: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeALU_B(parametres, "ALU_B_OR")
[docs]def analizeEOR(parametres): """ Analitza EOR :param parameters: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeALU_B(parametres, "ALU_B_EOR")
[docs]def analizeINOUT(params,out): """ Analitza INOUT :param parameters: Paràmetres que ens passa l'usuari :param out: Boleà que indica si és in o out :return: Retorna la comanda passada a VHDL """ try: p = params.split(",") if (len(p) != 2): raise Exception("INOUT només té 2 paràmetres") if (out): p = p[::-1] registre = analyzeRegister(p[0]) valor = int(p[1]) if (not out and valor not in INPorts): raise Exception("In només pot ser {0}".format(", ".join(INPorts))) elif out and valor not in OUTPorts: raise Exception("Out només pot ser {0}".format(", ".join(OUTPorts))) except ValueError: exception("INOUT valor ha de ser un nombre decimal", LineProgram, ReadWriteFiles.ROM) except Exception as e: exception(e.message, LineProgram, ReadWriteFiles.ROM) return 'IN_OUT & "{0}000" & "{1}" & "{2}"'.format(1 if out else 0, registre, bin(int(valor))[2:].zfill(4))
[docs]def analizeIN(params): """ Analitza IN :param params: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeINOUT(params, False)
[docs]def analizeOUT(params): """ Analitza OUT :param parameters: Paràmetres que ens passa l'usuari :return: Retorna la comanda passada a VHDL """ return analizeINOUT(params, True)
def analizeORI(params): p = params.split(",") if len(p) != 2: exception("ORI només té 2 paràmetres", LineProgram, ReadWriteFiles.ROM) register = analyzeRegister(p[0]) hex = analyzeHex(p[1]) return 'ORI & "{0}" & "{1}" & "{2}"'.format(hex[:4], register, hex[4:8]) def analizeANDI(params): p = params.split(",") if len(p) != 2: exception("ANDI només té 2 paràmetres", LineProgram, ReadWriteFiles.ROM) register = analyzeRegister(p[0]) hex = analyzeHex(p[1]) return 'ANDI & "{0}" & "{1}" & "{2}"'.format(hex[:4], register, hex[4:8]) Options ={ #Llista de les opciona a analitzar. "NOP" : analyzeNOP, "LDI" : analyzeLDI, "ADC" : analyzeADC, "MOV" : analizeMOV, "RJMP" :analizeRJMP, "BREQ": analizeBREQ, "BRNE": analizeBRNE, "IN" : analizeIN, "OUT": analizeOUT, "EOR": analizeEOR, "AND": analizeAND, "OR" : analizeOR, "ORI" : analizeORI, "ANDI":analizeANDI } if (__name__ == "__main__"): print getCodeFromFile(raw_input("Escriu el nom del fitxer on hi tens el codi: "))