169 lines
4.9 KiB
Python
169 lines
4.9 KiB
Python
|
||
from components.ijvm import ijvm
|
||
|
||
class Microprogram:
|
||
|
||
def __init__(self,components):
|
||
self.c=components # Link components to microprogram
|
||
if self.c["RAM"]==None: # Check if RAM is initialize
|
||
raise RuntimeError("Microprogram initialization fail, RAM is not initialized")
|
||
|
||
def run(self):
|
||
"""
|
||
Start microprogram
|
||
"""
|
||
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
|
||
self.c["PC"]+=1 # INC PC after fetch
|
||
if self.exec()==1: # Execute opcode and halt if return code is 1
|
||
break;
|
||
|
||
def fetch(self):
|
||
"""
|
||
Fetch next byte from memory into MBR
|
||
"""
|
||
opcode=self.c["RAM"].fetch()
|
||
self.c["MBR"]=opcode # Opcode to MBR
|
||
|
||
def rd(self):
|
||
"""
|
||
Read data into memory
|
||
"""
|
||
data=self.c["RAM"].read()
|
||
self.c["MDR"]=data
|
||
|
||
def wr(self):
|
||
"""
|
||
Write data into memory
|
||
"""
|
||
self.c["RAM"].write()
|
||
|
||
def exec(self): # TODO: Implement opcode
|
||
"""
|
||
Execute next opcode
|
||
"""
|
||
opcode=self.c["MBRU"] # Get loaded OpCode (/!\ We used MBRU not MBR because MBR is signed)
|
||
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()
|
||
self.c["TOS"]=(self.c["MDR"] & self.c["H"])
|
||
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()
|
||
self.c["TOS"]=(self.c["MDR"] | self.c["H"])
|
||
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"]
|
||
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()
|
||
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"]
|
||
elif opcode==ijvm["OUT"]:
|
||
self.fetch();self.c["PC"]+=1 # Fetch byte to push in MBR
|
||
print(str(chr(self.c["MBRU"])),end="") # MBRU because no char which are negative
|
||
elif opcode==ijvm["HALT"]:
|
||
return(1)
|
||
else:
|
||
if opcode in ijvm:
|
||
print("Instruction {} not yet implemented.".format(ijvm[opcode]))
|
||
else:
|
||
raise RuntimeError("Instruction {} not found on address {}".format(opcode,self.c["PC"]-1))
|
||
return(0)
|
||
|
||
def dump(self):
|
||
"""
|
||
Print RAM, stack and registers
|
||
"""
|
||
print("-------------- RAM --------------")
|
||
self.c["RAM"].dump()
|
||
print("------------- Stack -------------")
|
||
self.c["RAM"].dumpRange(self.c["LV"]*4,self.c["SP"]*4,4) # Convert address to 32bits value
|
||
print("----------- Registers -----------")
|
||
for key,value in self.c.items():
|
||
if key!="RAM":
|
||
print("{}={}".format(key,value))
|
||
print("---------------------------------")
|