Created
March 4, 2012 23:42
-
-
Save miguelarca/1975429 to your computer and use it in GitHub Desktop.
Archivos que contienen la clases del proyecto de arquitectura del computador
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
# -*- coding: utf-8 -*- | |
__author__="miguel" | |
__date__ ="$03/02/2012 01:08:28 PM$" | |
import sys | |
from memoria import Memoria | |
from utilidades import * | |
class Computador: | |
def __init__(self, tam_memoria): | |
"""Clase que simula el computador""" | |
self.memoria = Memoria(tam_memoria) | |
self.MQ = 0 # Registro del computador | |
self.IR = "00000000000000000000" # Registro de Instrucciones | |
self.MAR = 0 # Registro de direccion de memoria | |
self.IBR = "00000000000000000000" # Buffer del registro de instrucciones | |
self.MBR = "00000000000000000000" # Buffer del registro de direccion de memoria | |
self.AC = 0 # Acumulador | |
self.PC = 0 # Contador | |
def cargarPrograma(self, archivo): | |
""" Metodo que carga un archivo, lo compila y luego lo carga en la memoria | |
lanza una excepcion si el archivo no existe o no se puede leer""" | |
try: | |
file = open(archivo,"r") | |
parse = "" | |
for l in file: | |
linea = l.split(",") | |
parse = instr_a_bin(linea[1].strip()) | |
self.memoria.setBloque(int(linea[0]),parse) | |
except IOError: | |
print "Error al leer el archivo" | |
sys.exit(1) | |
else: | |
file.close() | |
return True | |
def dumpMemoria(self): | |
""" Metodo que retorna una lista con los valores almacenados en la memoria | |
del computador""" | |
for i in range(self.memoria.getTamano()): | |
yield self.memoria.getBloque(i) | |
def aumentaPC(self): | |
""" Metodo que incrementa el PC por uno """ | |
self.PC += 1 | |
def inst_00001010(self,mem): | |
""" Metodo que ejecuta la instruccion LOAD MQ | |
Toma lo que esta en el registro MQ y lo guarda en el acumulador""" | |
self.AC = self.MQ | |
def inst_00001001(self, mem): | |
""" Metodo que ejecuta la instruccion LOAD MQ (MX) | |
Transfiere el contenido de la posicion de memoria X a | |
el registro MQ | |
@param mem posicion de la memoria de donde tomar el valor""" | |
self.MQ = strbin_int(self.memoria.getBloque(mem)) | |
def inst_00100001(self,mem): | |
""" Metodo que ejecuta la instruccion STOR M(X) | |
transfiere el contenido del acumulador a la posicion | |
de memoria X | |
@para mem posicion de memoria donde se va a alamacenar el valor""" | |
self.memoria.setBloque(mem,int_bin(self.AC)) | |
def inst_00000001(self,mem): | |
""" Metodo que ejecuta la instrucion LOAD M(X) | |
transfiere el contenido de M(X) al acumulador | |
@param mem posicion de la memoria de donde se va a transferir""" | |
self.AC = strbin_int(self.memoria.getBloque(mem)) | |
def inst_00001101(self,mem): | |
""" Metodo que ejecuta la instrucion JUMP M(X) | |
Capta la siguiente instruccion ubicada en M(X) | |
@param mem posicion de la memoria a donde se va a buscar la | |
instruccion""" | |
self.PC = mem | |
def inst_00001111(self,mem): | |
""" Metodo que ejecuta la instruccion JUMP + M(X) | |
Si el numero en el acumulador es no negativo, | |
captar la siguiente instrucion ubicada en M(X) | |
@param mem posicion de la memoria a donde se va a buscar la | |
instruccion""" | |
if self.AC > 0 : | |
self.PC = mem | |
def inst_00000101(self,mem): | |
""" Metodo que ejecuta la instruccion ADD M(X) | |
Suma el valor en M(X) a AC y guardar el resultado en AC | |
@para mem posicion en la memoria donde esta almacenado el | |
valor a sumar """ | |
self.AC += strbin_int(self.memoria.getBloque(mem)) | |
def inst_00000110(self,mem): | |
""" Metodo que ejecuta la instruccion SUB M(X) | |
Resta el valor en M(X) a AC y guardar el resultado en AC | |
@para mem posicion en la memoria donde esta almacenado el | |
valor a restar """ | |
self.AC -= strbin_int(self.memoria.getBloque(mem)) | |
def inst_00001011(self,mem): | |
""" Metodo que ejecuta la instruccion MUL M(X) | |
Multiplica el valor en M(X) por MQ y guardar el resultado en AC | |
@para mem posicion en la memoria donde esta almacenado el | |
valor a restar """ | |
self.AC = self.MQ * strbin_int(self.memoria.getBloque(mem)) | |
def inst_00001100(self,mem): | |
""" Metodo que ejecuta l instruccion DIV M(X) | |
Divide AC por M(X), coloca el cociente en MQ y el resto en AC""" | |
self.MQ = self.AC / strbin_int(self.memoria.getBloque(mem)) | |
self.AC = self.AC % strbin_int(self.memoria.getBloque(mem)) | |
def captaInst(self): | |
""" Metodo que capta la siguiente instruccion """ | |
self.MAR = self.PC | |
self.MBR = self.memoria.getBloque(self.MAR) | |
self.IR = self.MBR[0:8] | |
self.MAR = strbin_int(self.MBR[8:20]) | |
self.aumentaPC() | |
def ejecutaInst(self): | |
""" Metodo que ejecuta la instruccion dada""" | |
#Diccionario que mapea la instruccion con el metodo a ejecutar | |
instruccion_metodo = {"00001010":self.inst_00001010,"00001001":self.inst_00001001,"00100001":self.inst_00100001, | |
"00000001":self.inst_00000001,"00001101":self.inst_00001101,"00001111":self.inst_00001111, | |
"00000101":self.inst_00000101,"00000110":self.inst_00000110,"00001100":self.inst_00001100} | |
if self.IR != "00000000": | |
instruccion_metodo[self.IR](self.MAR) | |
return False | |
else: | |
return True | |
############# Getters y Setters ############################################ | |
def getMQ(self): | |
"""Metodo que retorna el valor que se encuentre almacenado en MQ""" | |
return int_bin(self.MQ,20) | |
def setMQ(self, val): | |
""" Metodo que guarda el valor en val al MQ""" | |
self.MQ = val | |
def getIR(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en IR """ | |
return self.IR | |
def setIR(self, val): | |
""" Metodo que guarda el valor en val al IR """ | |
self.IR = val | |
def getMAR(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en MAR """ | |
return int_bin(self.MAR,20) | |
def setMAR(self, val): | |
""" Metodo que guarda el valor en val al MAR """ | |
self.MAR = val | |
def getIBR(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en IBR """ | |
return self.IBR | |
def setIBR(self, val): | |
""" Metodo que guarda el valor en val al IBR """ | |
self.IBR = val | |
def getMBR(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en MBR """ | |
return self.MBR | |
def setMBR(self, val): | |
""" Metodo que guarda el valor en val al MBR """ | |
self.MBR = val | |
def getAC(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en AC """ | |
return int_bin(self.AC,20) | |
def setAC(self, val): | |
""" Metodo que guarda el valor en val al AC """ | |
self.AC = val | |
def getPC(self): | |
""" Metodo que retorna el valor que se encuentre almacenado en PC """ | |
return int_bin(self.PC,20) | |
def setPC(self, val): | |
""" Metodo que guarda el valor en val al PC """ | |
self.PC = val | |
def getTamMemoria(self): | |
return self.memoria.getTamano() | |
def getContador(self): | |
return self.PC |
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
# -*- coding: utf-8 -*- | |
class Memoria: | |
def __init__(self,tam): # Constructor que toma el tamaño de la memoria a crear | |
""" Clase para el manejo de la memoria | |
@autor: Miguel Mendez | |
""" | |
if tam > 0: | |
self.tamano = tam | |
else: | |
self.tamano = 1 | |
self.bloques = ["00000000000000000000"]*self.tamano | |
def getBloque(self, blk): | |
""" | |
Metodo que toma como parametros el indice del bloque donde esta almacenada la informacion | |
@param int id del bloque | |
@return string con la informacion alamacenada en el bloque o None si el parametro blk | |
esta fuera de rango""" | |
if blk < self.tamano and blk >= 0: | |
return self.bloques[blk] | |
else: | |
return None | |
def setBloque(self, blk, val): | |
""" | |
Metodo que toma como parametro el bloque de memoria a guardar y la data a almacenar | |
@param blk int bloque de memoria donde se va a almacenar | |
@param val string data a ser alamacenada, en formato binario | |
""" | |
if blk < self.tamano and blk >= 0: | |
self.bloques[blk]=val | |
def getTamano(self): | |
""" | |
Metodo que retorna el tamano de la memoria, osea la cantidad de bloques | |
@return int tamano | |
""" | |
return self.tamano | |
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
#!/usr/bin/python | |
import wx | |
import sys | |
from microsimview import MicroSimView | |
def main(argv): | |
if len(argv) > 1: | |
programa = argv[1] | |
else: | |
programa = "programa.txt" | |
app = wx.App() | |
MicroSimView(None, -1, 'MicroSim', programa) | |
app.MainLoop() | |
return 0 | |
if __name__ == '__main__': | |
main(sys.argv) |
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
# -*- coding: utf-8 -*- | |
# | |
import time | |
import wx | |
from computador import Computador | |
class MicroSimView(wx.Dialog): | |
def __init__ (self, parent, ID, title, programa): | |
wx.Dialog.__init__(self, parent, ID, title, size=(450, 300)) | |
font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD) | |
heading = wx.StaticText(self, -1, 'Simulador de Micro MicroSim', (100, 15)) | |
heading.SetFont(font) | |
self.timer = wx.Timer(self) | |
self.c = Computador(100) | |
self.mensajeTexto = wx.StaticText(self, -1, '', (25, 40)) | |
wx.StaticLine(self, -1, (25, 70), (400,1)) | |
wx.StaticText(self, -1, 'MQ', (25, 80)) | |
wx.StaticText(self, -1, 'IR', (25, 100)) | |
wx.StaticText(self, -1, 'IBR', (25, 120)) | |
wx.StaticText(self, -1, 'MBR', (25, 140)) | |
wx.StaticText(self, -1, 'PC', (25, 160)) | |
wx.StaticText(self, -1, 'AC', (25, 180)) | |
wx.StaticText(self, -1, 'MAR', (25, 200)) | |
self.MQtxt = wx.StaticText(self, -1, self.c.getMQ(), (100, 80)) | |
self.IRtxt = wx.StaticText(self, -1, self.c.getIR(), (100, 100)) | |
self.IBRtxt = wx.StaticText(self, -1, self.c.getIBR(), (100, 120)) | |
self.MBRtxt = wx.StaticText(self, -1, self.c.getMBR(), (100, 140)) | |
self.PCtxt = wx.StaticText(self, -1, self.c.getPC(), (100, 160)) | |
self.ACtxt = wx.StaticText(self, -1, self.c.getAC(), (100, 180)) | |
self.MARtxt = wx.StaticText(self, -1, self.c.getMAR(), (100, 200)) | |
self.salirBoton = wx.Button(self, 1, 'Salir', (330,160), (60, 30)) | |
self.memoriaBoton = wx.Button(self, 2, 'Ver memoria', (300,80), (120, 30)) | |
self.ejecutarBoton = wx.Button(self, 3, 'Ejecutar', (300,120), (120, 30)) | |
self.Bind(wx.EVT_BUTTON, self.OnOk, id=1) | |
self.Bind(wx.EVT_BUTTON, self.OnViewMem, id=2) | |
self.Bind(wx.EVT_BUTTON, self.OnEjecuta, id=3) | |
if self.c.cargarPrograma(programa): | |
self.mensajeTexto.SetLabel("Programa cargado exitosamente") | |
else: | |
self.mensajeTexto.SetLabel("Error al cargar el programa") | |
self.Centre() | |
self.ShowModal() | |
self.Destroy() | |
def setControles(self): | |
self.MQtxt.SetLabel(self.c.getMQ()) | |
self.IRtxt.SetLabel(self.c.getIR()) | |
self.IBRtxt.SetLabel(self.c.getIBR()) | |
self.MBRtxt.SetLabel(self.c.getMBR()) | |
self.PCtxt.SetLabel(self.c.getPC()) | |
self.ACtxt.SetLabel(self.c.getAC()) | |
self.MARtxt.SetLabel(self.c.getMAR()) | |
time.sleep(1) | |
def OnOk(self, event): | |
self.Close() | |
def OnViewMem(self, event): | |
MemoriaView(self,-1,self.c) | |
def OnEjecuta(self, event): | |
self.mensajeTexto.SetLabel("Programa ejecutando........") | |
self.salirBoton.Enable(False) | |
self.memoriaBoton.Enable(False) | |
self.ejecutarBoton.Enable(False) | |
file = open("ejecucion.txt","w") | |
termino = False; | |
while termino == False: | |
self.c.captaInst() | |
termino = self.c.ejecutaInst() | |
self.setControles() | |
log = "MQ "+self.c.getMQ()+" IR "+self.c.getIR()+" IBR "+self.c.getIBR()+" MBR "+self.c.getMBR()+" PC "+self.c.getPC()+" AC "+self.c.getAC()+" MAR "+self.c.getMAR()+"\n" | |
file.write(log) | |
file.close() | |
self.salirBoton.Enable(True) | |
self.memoriaBoton.Enable(True) | |
self.ejecutarBoton.Enable(True) | |
self.mensajeTexto.SetLabel("Programa finalizado") | |
class MemoriaView(wx.Dialog): | |
def __init__ (self, parent, ID, comp): | |
wx.Dialog.__init__(self, parent, ID, "Bloque de Memoria", size=(300, 600)) | |
font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD) | |
heading = wx.StaticText(self, -1, 'Instrucciones en memoria', (50, 15)) | |
heading.SetFont(font) | |
wx.StaticLine(self, -1, (25, 70), (400,1)) | |
self.listBox1 = wx.ListBox(choices=[], id=-1, | |
name='listBox1', parent=self, pos=wx.Point(60, 80),size=wx.Size(220, 450), style=0) | |
self.listBox1.SetBackgroundColour(wx.Colour(226, 235, 238)) | |
for bloque in comp.dumpMemoria(): | |
self.listBox1.Append(bloque) | |
wx.Button(self, 1, 'OK', (120,535), (60, 30)) | |
self.Bind(wx.EVT_BUTTON, self.OnOk, id=1) | |
self.Centre() | |
self.ShowModal() | |
self.Destroy() | |
def OnOk(self, event): | |
self.Close() | |
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
# -*- coding: utf-8 -*- | |
""" | |
Funcion que toma unentero como parametro y lo convierte en su equivalente en | |
binario, con un tamaño por defecto de 12 bits, con padding a la derecha automatico | |
@param int x entero a ser transformado | |
@param int width el tamaño o la cantidad de bits requeridos, por defecto 12 | |
@return string la representación binaria de x que vino como parametro | |
""" | |
def int_bin(x,width=12): | |
return ''.join(str((x>>i)&1) for i in xrange(width-1,-1,-1)) | |
def strbin_int(val): | |
if val[0]=="1": | |
return int("-0b"+val,2) #retorna uno negativo | |
else: | |
return int("0b"+val,2)# positivo | |
""" | |
Función que toma una instruccion y la trasforma en su equivalente a binario | |
para luego ser ejecutada por el microprocesador simulado | |
""" | |
def instr_a_bin(inst): | |
#instruccion_set = {"LOAD MQ":"00001010","LOAD MQ M(X)":"00001001","STOR M(X)":"00100001","LOAD M(X)":"00000001","JUMP M(X)":"00001101","JUMP + M(X)":"00001111","ADD M(X)":"00000101","SUB M(X)":"00000110","MUL M(X)":"00001100"} | |
inst_part = inst.split(" ") | |
tamano = len(inst_part) | |
###################### LOAD ########################################## | |
if inst_part[0] == "LOAD": | |
if tamano == 2: | |
if inst_part[1] == "MQ":# Transfiere el contenido del registro MQ al Acumulador | |
return "00001010000000000000" | |
else: # entonces es M(X) | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00000001"+op # y luego lo llevamos a una expresion binaria | |
elif tamano == 3:# entonces es LOAD MQ M(X) | |
op = int_bin(int(inst_part[2][2:-1])) # Tomamos el numero dentro de M(), lo convertimos a int | |
return "00001001"+op | |
else: | |
return inst | |
###################### JUMP ########################################## | |
elif inst_part[0] == "JUMP": | |
if tamano == 2:# entonces es JUMP M(X) | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00001101"+op # y luego lo llevamos a una expresion binaria | |
elif tamano == 3:# entonces es JUMP + M(X) | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00001111"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
###################### ADD ########################################## | |
elif inst_part[0] == "ADD": | |
if tamano == 2: | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00000101"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
###################### SUB ########################################## | |
elif inst_part[0] == "SUB": | |
if tamano == 2: | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00000110"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
###################### MUL ########################################## | |
elif inst_part[0] == "MUL": | |
if tamano == 2: | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00001011"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
###################### DIV ########################################## | |
elif inst_part[0] == "DIV": | |
if tamano == 2: | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00001100"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
###################### STOR ########################################## | |
elif inst_part[0] == "STOR": | |
if tamano == 2: | |
op = int_bin(int(inst_part[1][2:-1]))# Tomamos el numero dentro de M(), lo convertimos a int | |
return "00010010"+op # y luego lo llevamos a una expresion binaria | |
else: | |
return inst | |
##################### es un numero ################################## | |
else: | |
if inst[0]=="-": # si el numero es negativo | |
neg = int_bin(int(inst[1:]),20) # sacamos su binario sin el signo | |
return neg.replace("0","1",1) # agregamos 1 al inicio para determinar signo negativo | |
else: | |
return int_bin(int(inst),20) # numero es positivo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment