Skip to content

Instantly share code, notes, and snippets.

@miguelarca
Created March 4, 2012 23:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miguelarca/1975429 to your computer and use it in GitHub Desktop.
Save miguelarca/1975429 to your computer and use it in GitHub Desktop.
Archivos que contienen la clases del proyecto de arquitectura del computador
# -*- 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
# -*- 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
#!/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)
# -*- 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()
# -*- 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