aboutsummaryrefslogtreecommitdiff
path: root/MicSim/components/microprogram.py
diff options
context:
space:
mode:
authorLoic GUEGAN <loic.guegan@yahoo.fr>2018-09-02 16:31:49 +0200
committerLoic GUEGAN <loic.guegan@yahoo.fr>2018-09-02 16:31:49 +0200
commita110465a4261e582025b6344facb7fa65c0acd56 (patch)
tree69f92f3186d47e2dc4a6b811c35238b02b0ec37d /MicSim/components/microprogram.py
parentcec2994481b3df8422603f864c1286524d5b3eff (diff)
Add unit tests, refactoring
Diffstat (limited to 'MicSim/components/microprogram.py')
-rw-r--r--MicSim/components/microprogram.py204
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
+