2018-08-31 18:42:12 +02:00
|
|
|
|
|
|
|
|
|
from components.ijvm import ijvm
|
|
|
|
|
|
2018-09-01 17:22:49 +02:00
|
|
|
|
# TODO: Switch MAR as 32bits address (multiply its value by for)
|
|
|
|
|
# then same for SP and LV
|
|
|
|
|
|
2018-08-31 18:42:12 +02:00
|
|
|
|
class Microprogram:
|
|
|
|
|
|
|
|
|
|
def __init__(self,components):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
self.c=components # Link components to microprogram
|
|
|
|
|
if self.c["RAM"]==None: # Check if RAM is initialize
|
2018-08-31 18:42:12 +02:00
|
|
|
|
raise RuntimeError("Microprogram initialization fail, RAM is not initialized")
|
|
|
|
|
|
|
|
|
|
def run(self):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Start microprogram
|
|
|
|
|
"""
|
2018-08-31 18:42:12 +02:00
|
|
|
|
self.c["LV"]=(1024)# Place stack to 1024
|
|
|
|
|
self.c["SP"]=(1024-1) # Init SP to LV-1 (because otherwise first element of the stack will be enty because of BIPUSH impl
|
|
|
|
|
|
|
|
|
|
for i in range(1,30): # Launche first 30 insctructions
|
|
|
|
|
self.fetch() # Fetch
|
2018-08-31 20:11:10 +02:00
|
|
|
|
self.c["PC"]+=1 # INC PC after fetch
|
|
|
|
|
if self.exec()==1: # Execute opcode and halt if return code is 1
|
|
|
|
|
break;
|
2018-08-31 18:42:12 +02:00
|
|
|
|
|
|
|
|
|
def fetch(self):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Fetch next byte from memory into MBR
|
|
|
|
|
"""
|
2018-08-31 18:42:12 +02:00
|
|
|
|
opcode=self.c["RAM"].fetch()
|
|
|
|
|
self.c["MBR"]=opcode # Opcode to MBR
|
|
|
|
|
|
|
|
|
|
def rd(self):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Read data into memory
|
|
|
|
|
"""
|
2018-08-31 18:42:12 +02:00
|
|
|
|
data=self.c["RAM"].read()
|
|
|
|
|
self.c["MDR"]=data
|
|
|
|
|
|
|
|
|
|
def wr(self):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Write data into memory
|
|
|
|
|
"""
|
2018-08-31 18:42:12 +02:00
|
|
|
|
self.c["RAM"].write()
|
|
|
|
|
|
2018-08-31 20:18:08 +02:00
|
|
|
|
def exec(self): # TODO: Implement opcode
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Execute next opcode
|
|
|
|
|
"""
|
2018-09-01 16:49:12 +02:00
|
|
|
|
opcode=self.c["MBRU"] # Get loaded OpCode (/!\ We used MBRU not MBR because MBR is signed)
|
2018-08-31 18:42:12 +02:00
|
|
|
|
if opcode==ijvm["NOP"]: # NOP
|
|
|
|
|
pass
|
|
|
|
|
elif opcode==ijvm["BIPUSH"]: # BIPUSH
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch byte to push in MBR
|
|
|
|
|
self.c["SP"]+=1 # Increment stack pointer
|
|
|
|
|
self.c["MAR"]=self.c["SP"] # Copy SP to MAR
|
|
|
|
|
self.c["MDR"]=self.c["MBR"] # Set MDR to MBR
|
|
|
|
|
self.c["TOS"]=self.c["MBR"] # Set MDR to MBR
|
|
|
|
|
self.wr() # Write data to stack
|
|
|
|
|
elif opcode==ijvm["IADD"]:
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["H"]=self.c["TOS"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["TOS"]=self.c["MDR"]+self.c["H"]
|
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
elif opcode==ijvm["ISUB"]:
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["H"]=self.c["TOS"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["TOS"]=self.c["MDR"]-self.c["H"]
|
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
elif opcode==ijvm["POP"]:
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["TOS"]=self.c["MDR"]
|
|
|
|
|
elif opcode==ijvm["DUP"]:
|
|
|
|
|
self.c["SP"]+=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
elif opcode==ijvm["IAND"]:
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["H"]=self.c["TOS"]
|
|
|
|
|
self.rd()
|
2018-09-01 10:19:06 +02:00
|
|
|
|
self.c["TOS"]=(self.c["MDR"] & self.c["H"])
|
2018-08-31 18:42:12 +02:00
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
elif opcode==ijvm["IOR"]:
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["H"]=self.c["TOS"]
|
|
|
|
|
self.rd()
|
2018-09-01 10:19:06 +02:00
|
|
|
|
self.c["TOS"]=(self.c["MDR"] | self.c["H"])
|
2018-08-31 18:42:12 +02:00
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
elif opcode==ijvm["SWAP"]:
|
|
|
|
|
self.c["MAR"]=self.c["SP"]-1
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.c["H"]=self.c["MDR"]
|
|
|
|
|
self.wr()
|
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.c["MAR"]=self.c["SP"]-1
|
|
|
|
|
self.wr()
|
|
|
|
|
self.c["TOS"]=self.c["H"]
|
2018-09-01 10:19:06 +02:00
|
|
|
|
elif opcode==ijvm["ILOAD"]:
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch local variable to push onto the stack
|
|
|
|
|
self.c["H"]=self.c["LV"]
|
|
|
|
|
self.c["MAR"]=self.c["MBRU"]+self.c["H"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["SP"]+=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.wr()
|
|
|
|
|
self.c["TOS"]=self.c["MDR"]
|
|
|
|
|
elif opcode==ijvm["ISTORE"]:
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch local variable offset where to store
|
|
|
|
|
self.c["H"]=self.c["LV"]
|
|
|
|
|
self.c["MAR"]=self.c["MBRU"]+self.c["H"]
|
|
|
|
|
self.c["MDR"]=self.c["TOS"]
|
|
|
|
|
self.wr()
|
|
|
|
|
self.c["SP"]-=1
|
|
|
|
|
self.c["MAR"]=self.c["SP"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.c["TOS"]=self.c["MDR"]
|
|
|
|
|
elif opcode==ijvm["IINC"]:
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch local variable offset to inc
|
|
|
|
|
self.c["H"]=self.c["LV"]
|
|
|
|
|
self.c["MAR"]=self.c["MBRU"]+self.c["H"]
|
|
|
|
|
self.rd()
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch inc value
|
|
|
|
|
self.c["H"]=self.c["MDR"]
|
|
|
|
|
self.c["MDR"]=self.c["MBR"]+self.c["H"]
|
|
|
|
|
self.wr()
|
2018-09-01 16:49:12 +02:00
|
|
|
|
elif opcode==ijvm["GOTO"]:
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch first byte
|
|
|
|
|
self.c["OPC"]=self.c["PC"]-1
|
|
|
|
|
self.c["H"]=self.c["MBR"]<<8
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch second byte
|
|
|
|
|
self.c["H"]=self.c["MBRU"]|self.c["H"]
|
|
|
|
|
self.c["PC"]=self.c["OPC"]+self.c["H"]
|
2018-08-31 20:11:10 +02:00
|
|
|
|
elif opcode==ijvm["OUT"]:
|
|
|
|
|
self.fetch();self.c["PC"]+=1 # Fetch byte to push in MBR
|
2018-09-01 16:49:12 +02:00
|
|
|
|
print(str(chr(self.c["MBRU"])),end="") # MBRU because no char which are negative
|
2018-08-31 20:11:10 +02:00
|
|
|
|
elif opcode==ijvm["HALT"]:
|
|
|
|
|
return(1)
|
2018-08-31 18:42:12 +02:00
|
|
|
|
else:
|
|
|
|
|
if opcode in ijvm:
|
|
|
|
|
print("Instruction {} not yet implemented.".format(ijvm[opcode]))
|
|
|
|
|
else:
|
2018-09-01 16:49:12 +02:00
|
|
|
|
raise RuntimeError("Instruction {} not found on address {}".format(opcode,self.c["PC"]-1))
|
2018-08-31 20:11:10 +02:00
|
|
|
|
return(0)
|
2018-08-31 18:42:12 +02:00
|
|
|
|
|
|
|
|
|
def dump(self):
|
2018-08-31 20:11:10 +02:00
|
|
|
|
"""
|
|
|
|
|
Print RAM, stack and registers
|
|
|
|
|
"""
|
|
|
|
|
print("-------------- RAM --------------")
|
|
|
|
|
self.c["RAM"].dump()
|
|
|
|
|
print("------------- Stack -------------")
|
|
|
|
|
self.c["RAM"].dumpRange(self.c["LV"],self.c["SP"])
|
|
|
|
|
print("----------- Registers -----------")
|
|
|
|
|
for key,value in self.c.items():
|
|
|
|
|
if key!="RAM":
|
|
|
|
|
print("{}={}".format(key,value))
|
|
|
|
|
print("---------------------------------")
|