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,constantPoolLocation, stackLocation): """ Start microprogram """ self.c["LV"]=stackLocation# Place stack to 1024 self.c["SP"]=stackLocation-1 # Init SP to LV-1 (because otherwise first element of the stack will be enty because of BIPUSH impl self.c["CPP"]=constantPoolLocation 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 """ self.c["MAR"]=self.c["MAR"]*4 # Don't forget MAR address 32bits block of memory little_endian=self.c["RAM"].read() self.c["MAR"]=self.c["MAR"]/4 # Restore MAR ##### Build little endian version of MDR #### big_endian=(little_endian&0xFF)<<24 big_endian=big_endian|(((little_endian>>8)&0xFF)<<16) big_endian=big_endian|(((little_endian>>16)&0xFF)<<8) big_endian=big_endian|((little_endian>>24)&0xFF) ############################################## self.c["MDR"]=big_endian def wr(self): """ Write data into memory """ ##### Build little endian version of MDR #### little_endian=(self.c["MDR"]&0xFF)<<24 little_endian=little_endian|(((self.c["MDR"]>>8)&0xFF)<<16) little_endian=little_endian|(((self.c["MDR"]>>16)&0xFF)<<8) little_endian=little_endian|((self.c["MDR"]>>24)&0xFF) ############################################## big_endian=self.c["MDR"] # Backup MDR before change it to little endian self.c["MDR"]=little_endian # Load little endian value self.c["MAR"]=self.c["MAR"]*4 # Don't forget MAR address 32bits block of memory self.c["RAM"].write() # Write little endian value into memory self.c["MAR"]=self.c["MAR"]/4 # Restore MAR self.c["MDR"]=big_endian # Restore big endian 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["IFEQ"]: self.c["SP"]=self.c["SP"]-1 self.c["MAR"]=self.c["SP"] self.c["OPC"]=self.c["TOS"] self.rd() self.c["TOS"]=self.c["MDR"] if self.c["OPC"]==0: self.T() else: self.F() elif opcode==ijvm["IFLT"]: self.c["SP"]=self.c["SP"]-1 self.c["MAR"]=self.c["SP"] self.c["OPC"]=self.c["TOS"] self.rd() self.c["TOS"]=self.c["MDR"] if self.c["OPC"]<0: self.T() else: self.F() 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 T(self): # This function is here just to follow ijvm implementation of "Structured Computer Organization" self.fetch();self.c["PC"]+=1 # exactly like GOTO implementation self.c["OPC"]=self.c["PC"]-1 # exactly like GOTO implementation ###### GOTO2 ##### 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"] ################## def F(self): # This function is here just to follow ijvm implementation of "Structured Computer Organization" self.fetch();self.c["PC"]+=1 # Needed because memory access take 1 cycle in simulation self.c["PC"]=self.c["PC"]+1