diff options
Diffstat (limited to 'MicSim/components/microprogram.py')
| -rw-r--r-- | MicSim/components/microprogram.py | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/MicSim/components/microprogram.py b/MicSim/components/microprogram.py new file mode 100644 index 0000000..ec84886 --- /dev/null +++ b/MicSim/components/microprogram.py @@ -0,0 +1,204 @@ + +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 + """ + little_endian=self.c["RAM"].read() + ##### 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["RAM"].write() # Write little endian value into memory + 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 + |
