From 4f77db9928e066aa3aa923c29bf879bf198332c6 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 30 Sep 2020 22:27:08 -0500 Subject: [PATCH 01/28] day 1+ --- ls8/cpu.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..1fdb2f893 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,18 +2,41 @@ import sys + +LDI = 0b10000010 +PRN = 0b01000111 +HLT = 0b00000001 + + class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - pass + self.ram = [ 0 ] * 256 + self.reg = [ 0 ] * 8 + self.pc = 0 + + self.running = True def load(self): """Load a program into memory.""" - address = 0 + address = 0 + filename = sys.argv[ 1 ] + + with open( filename ) as f: + for line in f: + line = line.split( '#' ) + line = line[ 0 ].strip() + + if line == '': + continue + self.ram[ address ] = int( line, 2 ) + address += 1 + + """ # For now, we've just hardcoded a program: program = [ @@ -25,10 +48,20 @@ def load(self): 0b00000000, 0b00000001, # HLT ] - + for instruction in program: - self.ram[address] = instruction + self.ram[ address ] = instruction address += 1 + """ + + # Memory Address Register (MAR) + # Memory Data Register (MDR) + def ram_read( self, MAR ): + return self.ram[ MAR ] + + + def ram_write( self, MAR, MDR ): + self.ram[ MAR ] = MDR def alu(self, op, reg_a, reg_b): @@ -62,4 +95,22 @@ def trace(self): def run(self): """Run the CPU.""" - pass + + while self.running: + # Instruction Register (IR) + IR = self.ram_read( self.pc ) + + op_a = self.ram_read( self.pc + 1 ) + op_b = self.ram_read( self.pc + 2 ) + + if IR == HLT: + self.running = False + elif IR == LDI: + self.reg[ op_a ] = [ op_b ] + self.pc += 3 + elif IR == PRN: + print( self.reg[ op_a ] ) + self.pc += 2 + else: + print( f'Instruction Register Unknown: {IR} at program counter {self.pc}' ) + self.running = False \ No newline at end of file From 01def84ab96662902381ef5132f142fc45d1f7ef Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 2 Oct 2020 21:17:50 -0500 Subject: [PATCH 02/28] day 2 --- ls8/cpu.py | 99 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 30 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 1fdb2f893..478f176f1 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -6,35 +6,52 @@ LDI = 0b10000010 PRN = 0b01000111 HLT = 0b00000001 - +ADD = 0b10100000 +SUB = 0b10100001 +MUL = 0b10100010 +DIV = 0b10100011 class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - self.ram = [ 0 ] * 256 - self.reg = [ 0 ] * 8 - self.pc = 0 - - self.running = True + self.ram = [ 0 ] * 256 + self.reg = [ 0 ] * 8 + self.reg[ 7 ] = 0xF4 + self.pc = 0 + self.running = True def load(self): """Load a program into memory.""" + if len( sys.argv ) != 2: + print( 'Insufficient number of arguments' ) + sys.exit( 1 ) + address = 0 filename = sys.argv[ 1 ] - with open( filename ) as f: - for line in f: - line = line.split( '#' ) - line = line[ 0 ].strip() - - if line == '': - continue - - self.ram[ address ] = int( line, 2 ) - address += 1 + try: + with open( filename ) as f: + for line in f: + line = line.split( '#' ) + num = line[ 0 ].strip() + + if num == '': + continue + else: + try: + self.ram[ address ] = int( num, 2 ) + except: + print( 'Could not convert string to integer' ) + + address += 1 + + + except: + print( 'File not found' ) + sys.exit( 1 ) """ # For now, we've just hardcoded a program: @@ -66,10 +83,18 @@ def ram_write( self, MAR, MDR ): def alu(self, op, reg_a, reg_b): """ALU operations.""" + if op == ADD: + self.reg[ reg_a ] += self.reg[ reg_b ] + + elif op == SUB: + self.reg[ reg_a ] -= self.reg[ reg_b ] - if op == "ADD": - self.reg[reg_a] += self.reg[reg_b] - #elif op == "SUB": etc + elif op == MUL: + self.reg[ reg_a ] *= self.reg[ reg_b ] + + elif op == DIV: + self.reg[ reg_a ] /= self.reg[ reg_b ] + else: raise Exception("Unsupported ALU operation") @@ -93,6 +118,30 @@ def trace(self): print() + + def execute( self, instruction, op_a, op_b ): + if instruction == HLT: + self.running = False + + elif instruction == LDI: + self.reg[ op_a ] = op_b + self.pc += 2 + + elif instruction == PRN: + print( self.reg[ op_a ] ) + self.pc += 1 + + elif instruction in [ ADD, SUB, MUL, DIV ]: + self.alu( instruction, op_a, op_b ) + self.pc += 2 + + else: + print( f'Instruction Register Unknown: {instruction} at program counter {self.pc}' ) + self.running = False + + self.pc += 1 + + def run(self): """Run the CPU.""" @@ -103,14 +152,4 @@ def run(self): op_a = self.ram_read( self.pc + 1 ) op_b = self.ram_read( self.pc + 2 ) - if IR == HLT: - self.running = False - elif IR == LDI: - self.reg[ op_a ] = [ op_b ] - self.pc += 3 - elif IR == PRN: - print( self.reg[ op_a ] ) - self.pc += 2 - else: - print( f'Instruction Register Unknown: {IR} at program counter {self.pc}' ) - self.running = False \ No newline at end of file + self.execute( IR, op_a, op_b ) \ No newline at end of file From 4b9e5600f063d920468b169a156363ec79657323 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 2 Oct 2020 21:26:00 -0500 Subject: [PATCH 03/28] day 2 code tweaks --- ls8/cpu.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 478f176f1..346fe8144 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -94,7 +94,7 @@ def alu(self, op, reg_a, reg_b): elif op == DIV: self.reg[ reg_a ] /= self.reg[ reg_b ] - + else: raise Exception("Unsupported ALU operation") @@ -119,11 +119,11 @@ def trace(self): print() - def execute( self, instruction, op_a, op_b ): - if instruction == HLT: - self.running = False - - elif instruction == LDI: + def execute( self, instruction ): + op_a = self.ram_read( self.pc + 1 ) + op_b = self.ram_read( self.pc + 2 ) + + if instruction == LDI: self.reg[ op_a ] = op_b self.pc += 2 @@ -149,7 +149,7 @@ def run(self): # Instruction Register (IR) IR = self.ram_read( self.pc ) - op_a = self.ram_read( self.pc + 1 ) - op_b = self.ram_read( self.pc + 2 ) - - self.execute( IR, op_a, op_b ) \ No newline at end of file + if IR == HLT: + self.running = False + else: + self.execute( IR ) \ No newline at end of file From 8c464033992541999d065c77bf1d42dddce6db76 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 2 Oct 2020 23:46:52 -0500 Subject: [PATCH 04/28] day 2 converted to branch table --- ls8/cpu.py | 70 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 29 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 346fe8144..d811dbd3d 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -22,6 +22,25 @@ def __init__(self): self.pc = 0 self.running = True + self.brnchtbl = {} + self.brnchtbl[ LDI ] = self.hndl_ldi + self.brnchtbl[ PRN ] = self.hdnl_prn + self.brnchtbl[ ADD ] = self.hndl_alu + self.brnchtbl[ SUB ] = self.hndl_alu + self.brnchtbl[ MUL ] = self.hndl_alu + self.brnchtbl[ DIV ] = self.hndl_alu + + + # Memory Address Register (MAR) + # Memory Data Register (MDR) + def ram_read( self, MAR ): + return self.ram[ MAR ] + + + def ram_write( self, MAR, MDR ): + self.ram[ MAR ] = MDR + + def load(self): """Load a program into memory.""" @@ -42,7 +61,7 @@ def load(self): continue else: try: - self.ram[ address ] = int( num, 2 ) + self.ram_write( address, int( num, 2 ) ) except: print( 'Could not convert string to integer' ) @@ -71,15 +90,6 @@ def load(self): address += 1 """ - # Memory Address Register (MAR) - # Memory Data Register (MDR) - def ram_read( self, MAR ): - return self.ram[ MAR ] - - - def ram_write( self, MAR, MDR ): - self.ram[ MAR ] = MDR - def alu(self, op, reg_a, reg_b): """ALU operations.""" @@ -98,6 +108,7 @@ def alu(self, op, reg_a, reg_b): else: raise Exception("Unsupported ALU operation") + def trace(self): """ Handy function to print out the CPU state. You might want to call this @@ -119,27 +130,19 @@ def trace(self): print() - def execute( self, instruction ): - op_a = self.ram_read( self.pc + 1 ) - op_b = self.ram_read( self.pc + 2 ) - - if instruction == LDI: - self.reg[ op_a ] = op_b - self.pc += 2 - - elif instruction == PRN: - print( self.reg[ op_a ] ) - self.pc += 1 + def hndl_ldi( self, ins, a, b ): + self.reg[ a ] = b + self.pc += 3 - elif instruction in [ ADD, SUB, MUL, DIV ]: - self.alu( instruction, op_a, op_b ) - self.pc += 2 - else: - print( f'Instruction Register Unknown: {instruction} at program counter {self.pc}' ) - self.running = False + def hdnl_prn( self, ins, a, b ): + print ( self.reg[ a ] ) + self.pc += 2 + - self.pc += 1 + def hndl_alu( self, ins, a, b ): + self.alu( ins, a, b ) + self.pc += 3 def run(self): @@ -151,5 +154,14 @@ def run(self): if IR == HLT: self.running = False + + elif IR not in self.brnchtbl: + print( f'Instruction Register Unknown: {IR} at program counter {self.pc}' ) + self.running = False else: - self.execute( IR ) \ No newline at end of file + op_a = self.ram_read( self.pc + 1 ) + op_b = self.ram_read( self.pc + 2 ) + + func = self.brnchtbl[ IR ] + func( IR, op_a, op_b ) + \ No newline at end of file From f6f9d01e4449635a1a12d67aa0fa84cada303892 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 00:30:58 -0500 Subject: [PATCH 05/28] day 2 formatting and code structure --- ls8/cpu.py | 63 +++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index d811dbd3d..e76f0989a 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -3,6 +3,7 @@ import sys +# Instructions -------------------------------------------> LDI = 0b10000010 PRN = 0b01000111 HLT = 0b00000001 @@ -10,10 +11,13 @@ SUB = 0b10100001 MUL = 0b10100010 DIV = 0b10100011 +# ========================================================> + class CPU: """Main CPU class.""" + # Constructor ----------------------------------------> def __init__(self): """Construct a new CPU.""" self.ram = [ 0 ] * 256 @@ -22,24 +26,27 @@ def __init__(self): self.pc = 0 self.running = True - self.brnchtbl = {} - self.brnchtbl[ LDI ] = self.hndl_ldi - self.brnchtbl[ PRN ] = self.hdnl_prn - self.brnchtbl[ ADD ] = self.hndl_alu - self.brnchtbl[ SUB ] = self.hndl_alu - self.brnchtbl[ MUL ] = self.hndl_alu - self.brnchtbl[ DIV ] = self.hndl_alu + # Branch Table + self.b_tbl = {} + self.b_tbl[ LDI ] = self.hndl_ldi + self.b_tbl[ PRN ] = self.hdnl_prn + self.b_tbl[ ADD ] = self.hndl_alu + self.b_tbl[ SUB ] = self.hndl_alu + self.b_tbl[ MUL ] = self.hndl_alu + self.b_tbl[ DIV ] = self.hndl_alu + # ====================================================> + # Memory Functions -----------------------------------> # Memory Address Register (MAR) # Memory Data Register (MDR) def ram_read( self, MAR ): return self.ram[ MAR ] - + # ===========> def ram_write( self, MAR, MDR ): self.ram[ MAR ] = MDR - + # ===========> def load(self): """Load a program into memory.""" @@ -57,7 +64,7 @@ def load(self): line = line.split( '#' ) num = line[ 0 ].strip() - if num == '': + if num == '' or num == '\n': continue else: try: @@ -71,26 +78,10 @@ def load(self): except: print( 'File not found' ) sys.exit( 1 ) - - """ - # For now, we've just hardcoded a program: - - program = [ - # From print8.ls8 - 0b10000010, # LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, # PRN R0 - 0b00000000, - 0b00000001, # HLT - ] - - for instruction in program: - self.ram[ address ] = instruction - address += 1 - """ + # ====================================================> + # ALU ------------------------------------------------> def alu(self, op, reg_a, reg_b): """ALU operations.""" if op == ADD: @@ -108,7 +99,7 @@ def alu(self, op, reg_a, reg_b): else: raise Exception("Unsupported ALU operation") - + # Traceback ------------------------------------------> def trace(self): """ Handy function to print out the CPU state. You might want to call this @@ -128,23 +119,27 @@ def trace(self): print(" %02X" % self.reg[i], end='') print() + # ====================================================> + # Instruction Handlers -------------------------------> def hndl_ldi( self, ins, a, b ): self.reg[ a ] = b self.pc += 3 - + # ===========> def hdnl_prn( self, ins, a, b ): print ( self.reg[ a ] ) self.pc += 2 - + # ===========> def hndl_alu( self, ins, a, b ): self.alu( ins, a, b ) self.pc += 3 + # ====================================================> + # Main Loop ------------------------------------------> def run(self): """Run the CPU.""" @@ -155,13 +150,13 @@ def run(self): if IR == HLT: self.running = False - elif IR not in self.brnchtbl: + elif IR not in self.b_tbl: print( f'Instruction Register Unknown: {IR} at program counter {self.pc}' ) self.running = False else: op_a = self.ram_read( self.pc + 1 ) op_b = self.ram_read( self.pc + 2 ) - func = self.brnchtbl[ IR ] + func = self.b_tbl[ IR ] func( IR, op_a, op_b ) - \ No newline at end of file +# EoF ----------------------------------------------------> \ No newline at end of file From f95adcf9e487a48aa4b57b72376d98577524d40d Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 00:38:54 -0500 Subject: [PATCH 06/28] day 2 add comments and remove superfluous var --- ls8/cpu.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index e76f0989a..62b2ad573 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -125,17 +125,17 @@ def trace(self): # Instruction Handlers -------------------------------> def hndl_ldi( self, ins, a, b ): self.reg[ a ] = b - self.pc += 3 + self.pc += 3 # +1 base increment plus 1 for each used operand # ===========> def hdnl_prn( self, ins, a, b ): print ( self.reg[ a ] ) - self.pc += 2 + self.pc += 2 # +1 base increment plus 1 for each used operand # ===========> def hndl_alu( self, ins, a, b ): self.alu( ins, a, b ) - self.pc += 3 + self.pc += 3 # +1 base increment plus 1 for each used operand # ====================================================> From 270ebfe84a99f5aeaa6d62ce541ecaf941610abe Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 00:41:26 -0500 Subject: [PATCH 07/28] day 2 add comments and remove superfluous var --- ls8/cpu.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 62b2ad573..af475ed8a 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -56,10 +56,9 @@ def load(self): sys.exit( 1 ) address = 0 - filename = sys.argv[ 1 ] try: - with open( filename ) as f: + with open( sys.argv[ 1 ] ) as f: for line in f: line = line.split( '#' ) num = line[ 0 ].strip() From 384e15b078d3b3932b012734481b999c2d66d015 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 00:47:55 -0500 Subject: [PATCH 08/28] day 2 remove unneeded or --- ls8/cpu.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index af475ed8a..9302218fa 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -63,7 +63,7 @@ def load(self): line = line.split( '#' ) num = line[ 0 ].strip() - if num == '' or num == '\n': + if num == '': continue else: try: From 0efe1adb5ecf90f213630205638dd1aa17963767 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 11:42:56 -0500 Subject: [PATCH 09/28] day 2 pc increment function --- ls8/cpu.py | 76 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 19 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9302218fa..ba6e98519 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -26,14 +26,21 @@ def __init__(self): self.pc = 0 self.running = True + # ALU + self.alu = {} + self.alu[ ADD ] = self.hndl_add + self.alu[ SUB ] = self.hndl_sub + self.alu[ MUL ] = self.hndl_mul + self.alu[ DIV ] = self.hndl_div + # Branch Table self.b_tbl = {} self.b_tbl[ LDI ] = self.hndl_ldi self.b_tbl[ PRN ] = self.hdnl_prn - self.b_tbl[ ADD ] = self.hndl_alu - self.b_tbl[ SUB ] = self.hndl_alu - self.b_tbl[ MUL ] = self.hndl_alu - self.b_tbl[ DIV ] = self.hndl_alu + self.b_tbl[ ADD ] = self.alu[ ADD ] + self.b_tbl[ SUB ] = self.alu[ SUB ] + self.b_tbl[ MUL ] = self.alu[ MUL ] + self.b_tbl[ DIV ] = self.alu[ DIV ] # ====================================================> @@ -44,10 +51,12 @@ def ram_read( self, MAR ): return self.ram[ MAR ] # ===========> + def ram_write( self, MAR, MDR ): self.ram[ MAR ] = MDR # ===========> + def load(self): """Load a program into memory.""" @@ -79,25 +88,29 @@ def load(self): sys.exit( 1 ) # ====================================================> - + """ # ALU ------------------------------------------------> - def alu(self, op, reg_a, reg_b): - """ALU operations.""" - if op == ADD: + def alu(self, ins, reg_a, reg_b): + """'''ALU operations.'''""" + + if ins == ADD: self.reg[ reg_a ] += self.reg[ reg_b ] - elif op == SUB: + elif ins == SUB: self.reg[ reg_a ] -= self.reg[ reg_b ] - elif op == MUL: + elif ins == MUL: self.reg[ reg_a ] *= self.reg[ reg_b ] - elif op == DIV: + elif ins == DIV: self.reg[ reg_a ] /= self.reg[ reg_b ] else: raise Exception("Unsupported ALU operation") + self.pc += 3 # +1 base increment plus 1 for each used operand + """ + # Traceback ------------------------------------------> def trace(self): """ @@ -122,19 +135,44 @@ def trace(self): # Instruction Handlers -------------------------------> - def hndl_ldi( self, ins, a, b ): + def hndl_ldi( self, a, b ): self.reg[ a ] = b - self.pc += 3 # +1 base increment plus 1 for each used operand + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> - def hdnl_prn( self, ins, a, b ): + + def hdnl_prn( self, a, b ): print ( self.reg[ a ] ) - self.pc += 2 # +1 base increment plus 1 for each used operand + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ===========> - def hndl_alu( self, ins, a, b ): - self.alu( ins, a, b ) - self.pc += 3 # +1 base increment plus 1 for each used operand + + def hndl_add( self, a, b): + self.reg[ a ] += self.reg[ b ] + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_sub( self, a, b): + self.reg[ a ] -= self.reg[ b ] + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_mul( self, a, b): + self.reg[ a ] *= self.reg[ b ] + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_div( self, a, b): + self.reg[ a ] /= self.reg[ b ] + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def inc_pc( self, num ): + self.pc += num # ====================================================> @@ -157,5 +195,5 @@ def run(self): op_b = self.ram_read( self.pc + 2 ) func = self.b_tbl[ IR ] - func( IR, op_a, op_b ) + func( op_a, op_b ) # EoF ----------------------------------------------------> \ No newline at end of file From 36cd3f6fde60741d8ab85f0963b2cd90fda1e77c Mon Sep 17 00:00:00 2001 From: Kronykus Date: Sat, 3 Oct 2020 12:21:27 -0500 Subject: [PATCH 10/28] day 2 added limiter function for alu operations to limit values to 255 per spec --- ls8/cpu.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index ba6e98519..c34e02b60 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -134,7 +134,7 @@ def trace(self): # ====================================================> - # Instruction Handlers -------------------------------> + # Instruction Handlers & Helpers ---------------------> def hndl_ldi( self, a, b ): self.reg[ a ] = b self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand @@ -149,30 +149,39 @@ def hdnl_prn( self, a, b ): def hndl_add( self, a, b): self.reg[ a ] += self.reg[ b ] + self.limiter( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> def hndl_sub( self, a, b): self.reg[ a ] -= self.reg[ b ] + self.limiter( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> def hndl_mul( self, a, b): self.reg[ a ] *= self.reg[ b ] + self.limiter( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> def hndl_div( self, a, b): self.reg[ a ] /= self.reg[ b ] + self.limiter( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> def inc_pc( self, num ): self.pc += num + # ===========> + + + def limiter( self, a ): + self.reg[ a ] &= 0xFF # ====================================================> From e290ef980cb7887c707968ce6b35705cb8e1cc17 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Tue, 6 Oct 2020 11:17:57 -0500 Subject: [PATCH 11/28] day 3 stack --- ls8/cpu.py | 49 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index c34e02b60..93289c0c7 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -4,13 +4,15 @@ # Instructions -------------------------------------------> -LDI = 0b10000010 -PRN = 0b01000111 -HLT = 0b00000001 -ADD = 0b10100000 -SUB = 0b10100001 -MUL = 0b10100010 -DIV = 0b10100011 +LDI = 0b10000010 +PRN = 0b01000111 +HLT = 0b00000001 +ADD = 0b10100000 +SUB = 0b10100001 +MUL = 0b10100010 +DIV = 0b10100011 +POP = 0b01000110 +PUSH = 0b01000101 # ========================================================> @@ -25,6 +27,9 @@ def __init__(self): self.reg[ 7 ] = 0xF4 self.pc = 0 self.running = True + self.sp = 6 + + self.reg[ self.sp ] = len( self.ram ) - 1 # ALU self.alu = {} @@ -35,12 +40,14 @@ def __init__(self): # Branch Table self.b_tbl = {} - self.b_tbl[ LDI ] = self.hndl_ldi - self.b_tbl[ PRN ] = self.hdnl_prn - self.b_tbl[ ADD ] = self.alu[ ADD ] - self.b_tbl[ SUB ] = self.alu[ SUB ] - self.b_tbl[ MUL ] = self.alu[ MUL ] - self.b_tbl[ DIV ] = self.alu[ DIV ] + self.b_tbl[ LDI ] = self.hndl_ldi + self.b_tbl[ PRN ] = self.hndl_prn + self.b_tbl[ POP ] = self.hndl_pop + self.b_tbl[ PUSH ] = self.hndl_push + self.b_tbl[ ADD ] = self.alu[ ADD ] + self.b_tbl[ SUB ] = self.alu[ SUB ] + self.b_tbl[ MUL ] = self.alu[ MUL ] + self.b_tbl[ DIV ] = self.alu[ DIV ] # ====================================================> @@ -141,12 +148,26 @@ def hndl_ldi( self, a, b ): # ===========> - def hdnl_prn( self, a, b ): + def hndl_prn( self, a, b ): print ( self.reg[ a ] ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ===========> + def hndl_pop( self, a, b ): + self.reg[ a ] = self.ram[ self.reg[ self.sp ] ] + self.reg[ self.sp ] += 1 + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_push( self, a, b ): + self.reg[ self.sp ] -= 1 + self.ram[ self.reg[ self.sp ] ] = self.reg[ a ] + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ===========> + + def hndl_add( self, a, b): self.reg[ a ] += self.reg[ b ] self.limiter( a ) From 127514ac4ed63e36b05a867c4919845e77338a31 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Tue, 6 Oct 2020 15:45:45 -0500 Subject: [PATCH 12/28] day 4 call/ret --- ls8/cpu.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index 93289c0c7..9481f5eb2 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -13,6 +13,8 @@ DIV = 0b10100011 POP = 0b01000110 PUSH = 0b01000101 +CALL = 0b01010000 +RET = 0b00010001 # ========================================================> @@ -28,8 +30,10 @@ def __init__(self): self.pc = 0 self.running = True self.sp = 6 + self.fl = 5 self.reg[ self.sp ] = len( self.ram ) - 1 + self.reg[ self.fl ] = 0b00000000 # ALU self.alu = {} @@ -44,6 +48,8 @@ def __init__(self): self.b_tbl[ PRN ] = self.hndl_prn self.b_tbl[ POP ] = self.hndl_pop self.b_tbl[ PUSH ] = self.hndl_push + self.b_tbl[ CALL ] = self.hndl_call + self.b_tbl[ RET ] = self.hndl_ret self.b_tbl[ ADD ] = self.alu[ ADD ] self.b_tbl[ SUB ] = self.alu[ SUB ] self.b_tbl[ MUL ] = self.alu[ MUL ] @@ -116,6 +122,7 @@ def alu(self, ins, reg_a, reg_b): raise Exception("Unsupported ALU operation") self.pc += 3 # +1 base increment plus 1 for each used operand + # ====================================================> """ # Traceback ------------------------------------------> @@ -168,6 +175,19 @@ def hndl_push( self, a, b ): # ===========> + def hndl_call( self, a, b ): + self.reg[ self.sp ] -= 1 + self.ram[ self.reg[ self.sp ] ] = self.pc + 2 + self.pc = self.reg[ a ] + # ===========> + + + def hndl_ret( self, a, b ): + self.pc = self.ram[ self.reg[ self.sp ] ] + self.reg[ self.sp ] += 1 + # ===========> + + def hndl_add( self, a, b): self.reg[ a ] += self.reg[ b ] self.limiter( a ) From 476b671b3037de9f080ba82c4334482d55643a9f Mon Sep 17 00:00:00 2001 From: Kronykus Date: Tue, 6 Oct 2020 20:38:13 -0500 Subject: [PATCH 13/28] formatting --- ls8/cpu.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9481f5eb2..f5f8d721f 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -162,29 +162,29 @@ def hndl_prn( self, a, b ): def hndl_pop( self, a, b ): - self.reg[ a ] = self.ram[ self.reg[ self.sp ] ] - self.reg[ self.sp ] += 1 + self.reg[ a ] = self.ram_read( self.reg[ self.sp ] ) + self.inc_sp() self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ===========> def hndl_push( self, a, b ): - self.reg[ self.sp ] -= 1 - self.ram[ self.reg[ self.sp ] ] = self.reg[ a ] + self.dec_sp() + self.ram_write( self.reg[ self.sp ], self.reg[ a ] ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ===========> def hndl_call( self, a, b ): - self.reg[ self.sp ] -= 1 - self.ram[ self.reg[ self.sp ] ] = self.pc + 2 + self.dec_sp() + self.ram_write( self.reg[ self.sp ], self.pc + 2 ) self.pc = self.reg[ a ] # ===========> def hndl_ret( self, a, b ): - self.pc = self.ram[ self.reg[ self.sp ] ] - self.reg[ self.sp ] += 1 + self.pc = self.ram_read( self.reg[ self.sp ] ) + self.inc_sp() # ===========> @@ -221,6 +221,17 @@ def inc_pc( self, num ): # ===========> + def inc_sp( self ): + self.reg[ self.sp ] += 1 + self.limiter( self.sp ) + # ===========> + + + def dec_sp( self ): + self.reg[ self.sp ] -= 1 + # ===========> + + def limiter( self, a ): self.reg[ a ] &= 0xFF # ====================================================> From 027e966502685c09f7c922c0bc4190260ec86c9b Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 13:42:05 -0500 Subject: [PATCH 14/28] alu operations --- ls8/cpu.py | 171 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 143 insertions(+), 28 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index f5f8d721f..f29d04206 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -4,17 +4,33 @@ # Instructions -------------------------------------------> -LDI = 0b10000010 -PRN = 0b01000111 +CALL = 0b01010000 HLT = 0b00000001 -ADD = 0b10100000 -SUB = 0b10100001 -MUL = 0b10100010 -DIV = 0b10100011 +LDI = 0b10000010 POP = 0b01000110 +PRN = 0b01000111 PUSH = 0b01000101 -CALL = 0b01010000 RET = 0b00010001 +# ALU Instructions ----> +ADD = 0b10100000 +AND = 0b10101000 +CMP = 0b10100111 +DEC = 0b01100110 +DIV = 0b10100011 +INC = 0b01100101 +MOD = 0b10100100 +MUL = 0b10100010 +NOT = 0b01101001 +OR = 0b10101010 +SHL = 0b10101100 +SHR = 0b10101101 +SUB = 0b10100001 +XOR = 0b10101011 +# Flags ---------------> +FLB = 0b00000000 +FLE = 0b00000001 +FLG = 0b00000010 +FLL = 0b00000100 # ========================================================> @@ -33,14 +49,24 @@ def __init__(self): self.fl = 5 self.reg[ self.sp ] = len( self.ram ) - 1 - self.reg[ self.fl ] = 0b00000000 + self.reg[ self.fl ] = FLB # base flags state zero; no flags set # ALU self.alu = {} self.alu[ ADD ] = self.hndl_add - self.alu[ SUB ] = self.hndl_sub - self.alu[ MUL ] = self.hndl_mul + self.alu[ AND ] = self.hndl_and + self.alu[ CMP ] = self.hndl_cmp + self.alu[ DEC ] = self.hndl_dec self.alu[ DIV ] = self.hndl_div + self.alu[ INC ] = self.hndl_inc + self.alu[ MOD ] = self.hndl_mod + self.alu[ MUL ] = self.hndl_mul + self.alu[ NOT ] = self.hndl_not + self.alu[ OR ] = self.hndl_or + self.alu[ SHL ] = self.hndl_shl + self.alu[ SHR ] = self.hndl_shr + self.alu[ SUB ] = self.hndl_sub + self.alu[ XOR ] = self.hndl_xor # Branch Table self.b_tbl = {} @@ -51,9 +77,19 @@ def __init__(self): self.b_tbl[ CALL ] = self.hndl_call self.b_tbl[ RET ] = self.hndl_ret self.b_tbl[ ADD ] = self.alu[ ADD ] - self.b_tbl[ SUB ] = self.alu[ SUB ] - self.b_tbl[ MUL ] = self.alu[ MUL ] + self.b_tbl[ AND ] = self.alu[ AND ] + self.b_tbl[ CMP ] = self.alu[ CMP ] + self.b_tbl[ DEC ] = self.alu[ DEC ] self.b_tbl[ DIV ] = self.alu[ DIV ] + self.b_tbl[ INC ] = self.alu[ INC ] + self.b_tbl[ MOD ] = self.alu[ MOD ] + self.b_tbl[ MUL ] = self.alu[ MUL ] + self.b_tbl[ NOT ] = self.alu[ NOT ] + self.b_tbl[ OR ] = self.alu[ OR ] + self.b_tbl[ SHL ] = self.alu[ SHL ] + self.b_tbl[ SHR ] = self.alu[ SHR ] + self.b_tbl[ SUB ] = self.alu[ SUB ] + self.b_tbl[ XOR ] = self.alu[ XOR ] # ====================================================> @@ -148,7 +184,7 @@ def trace(self): # ====================================================> - # Instruction Handlers & Helpers ---------------------> + # Instruction Handlers -------------------------------> def hndl_ldi( self, a, b ): self.reg[ a ] = b self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand @@ -187,35 +223,115 @@ def hndl_ret( self, a, b ): self.inc_sp() # ===========> - - def hndl_add( self, a, b): + # ALU Instructions Handlers --------------------------> + def hndl_add( self, a, b ): self.reg[ a ] += self.reg[ b ] - self.limiter( a ) + self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> - def hndl_sub( self, a, b): - self.reg[ a ] -= self.reg[ b ] - self.limiter( a ) + def hndl_and( self, a, b ): + self.base_and( a, self.reg[ b ] ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_cmp( self, a, b ): + first = self.reg[ a ] + second = self.reg[ b ] + + if first == second: + # set equal flag + self.reg[ self.fl ] = FLE + elif first > second: + # set greater flag + self.reg[ self.fl ] = FLG + elif first < second: + #set less flag + self.reg[ self.fl ] = FLL + else: + self.reg[ self.fl ] = FLB + # ===========> + + + def hndl_dec( self, a, b ): + self.reg[ a ] -= 1 + self.base_and( a ) + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_div( self, a, b ): + self.reg[ a ] /= self.reg[ b ] + self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> - def hndl_mul( self, a, b): + def hndl_inc( self, a, b ): + self.reg[ a ] += 1 + self.base_and( a ) + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_mod( self, a, b ): + self.reg[ a ] %= self.reg[ b ] + self.base_and( a ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_mul( self, a, b ): self.reg[ a ] *= self.reg[ b ] - self.limiter( a ) + self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> - def hndl_div( self, a, b): - self.reg[ a ] /= self.reg[ b ] - self.limiter( a ) + def hndl_not( self, a, b ): + self.reg[ a ] = ~self.reg[ a ] + self.base_and( a ) + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_or( self, a, b ): + self.reg[ a ] |= self.reg[ b ] + self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> + def hndl_shl( self, a, b ): + self.reg[ a ] <<= self.reg[ b ] + self.base_and( a ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_shr( self, a, b ): + self.reg[ a ] >>= self.reg[ b ] + self.base_and( a ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_sub( self, a, b ): + self.reg[ a ] -= self.reg[ b ] + self.base_and( a ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + + def hndl_xor( self, a, b ): + self.reg[ a ] ^= self.reg[ b ] + self.base_and( a ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ===========> + + # Instruction Helpers --------------------------------> def inc_pc( self, num ): self.pc += num # ===========> @@ -223,7 +339,7 @@ def inc_pc( self, num ): def inc_sp( self ): self.reg[ self.sp ] += 1 - self.limiter( self.sp ) + self.base_and( self.sp ) # ===========> @@ -231,9 +347,8 @@ def dec_sp( self ): self.reg[ self.sp ] -= 1 # ===========> - - def limiter( self, a ): - self.reg[ a ] &= 0xFF + def base_and( self, a, b=0xFF ): + self.reg[ a ] &= b # ====================================================> From 828cb8fbb3328b777a5f5153e84b9d3138ce448f Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 13:49:43 -0500 Subject: [PATCH 15/28] consistent spacing --- ls8/cpu.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index f29d04206..f5ce527bc 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -137,6 +137,7 @@ def load(self): sys.exit( 1 ) # ====================================================> + """ # ALU ------------------------------------------------> def alu(self, ins, reg_a, reg_b): @@ -161,6 +162,7 @@ def alu(self, ins, reg_a, reg_b): # ====================================================> """ + # Traceback ------------------------------------------> def trace(self): """ @@ -223,6 +225,7 @@ def hndl_ret( self, a, b ): self.inc_sp() # ===========> + # ALU Instructions Handlers --------------------------> def hndl_add( self, a, b ): self.reg[ a ] += self.reg[ b ] @@ -331,6 +334,7 @@ def hndl_xor( self, a, b ): self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ===========> + # Instruction Helpers --------------------------------> def inc_pc( self, num ): self.pc += num @@ -347,6 +351,7 @@ def dec_sp( self ): self.reg[ self.sp ] -= 1 # ===========> + def base_and( self, a, b=0xFF ): self.reg[ a ] &= b # ====================================================> From 764e820f41e9a7b6cc29104d528214bea6d7ea6b Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 14:01:20 -0500 Subject: [PATCH 16/28] changed flags to internal register and ocd spacing on separators --- ls8/cpu.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index f5ce527bc..52e3d7707 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -45,11 +45,10 @@ def __init__(self): self.reg[ 7 ] = 0xF4 self.pc = 0 self.running = True - self.sp = 6 - self.fl = 5 + self.sp = 7 + self.fl = FLB self.reg[ self.sp ] = len( self.ram ) - 1 - self.reg[ self.fl ] = FLB # base flags state zero; no flags set # ALU self.alu = {} @@ -354,6 +353,11 @@ def dec_sp( self ): def base_and( self, a, b=0xFF ): self.reg[ a ] &= b + # ===========> + + + def set_flag( self, flag ): + self.fl = flag # ====================================================> From 9428c620a06abf558b251142744b42f5f1f3f135 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 14:07:16 -0500 Subject: [PATCH 17/28] changed flags to internal register and ocd spacing on separators --- ls8/cpu.py | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 52e3d7707..206290dc2 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -97,12 +97,12 @@ def __init__(self): # Memory Data Register (MDR) def ram_read( self, MAR ): return self.ram[ MAR ] - # ===========> + # ============> def ram_write( self, MAR, MDR ): self.ram[ MAR ] = MDR - # ===========> + # ============> def load(self): @@ -189,40 +189,40 @@ def trace(self): def hndl_ldi( self, a, b ): self.reg[ a ] = b self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_prn( self, a, b ): print ( self.reg[ a ] ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_pop( self, a, b ): self.reg[ a ] = self.ram_read( self.reg[ self.sp ] ) self.inc_sp() self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_push( self, a, b ): self.dec_sp() self.ram_write( self.reg[ self.sp ], self.reg[ a ] ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_call( self, a, b ): self.dec_sp() self.ram_write( self.reg[ self.sp ], self.pc + 2 ) self.pc = self.reg[ a ] - # ===========> + # ============> def hndl_ret( self, a, b ): self.pc = self.ram_read( self.reg[ self.sp ] ) self.inc_sp() - # ===========> + # ============> # ALU Instructions Handlers --------------------------> @@ -230,13 +230,13 @@ def hndl_add( self, a, b ): self.reg[ a ] += self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_and( self, a, b ): self.base_and( a, self.reg[ b ] ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_cmp( self, a, b ): @@ -244,116 +244,116 @@ def hndl_cmp( self, a, b ): second = self.reg[ b ] if first == second: - # set equal flag - self.reg[ self.fl ] = FLE + self.set_flag( FLE ) + elif first > second: - # set greater flag - self.reg[ self.fl ] = FLG + self.set_flag( FLG ) + elif first < second: - #set less flag - self.reg[ self.fl ] = FLL + self.set_flag( FLL ) + else: - self.reg[ self.fl ] = FLB - # ===========> + self.set_flag( FLB ) + # ============> def hndl_dec( self, a, b ): self.reg[ a ] -= 1 self.base_and( a ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_div( self, a, b ): self.reg[ a ] /= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_inc( self, a, b ): self.reg[ a ] += 1 self.base_and( a ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_mod( self, a, b ): self.reg[ a ] %= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_mul( self, a, b ): self.reg[ a ] *= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_not( self, a, b ): self.reg[ a ] = ~self.reg[ a ] self.base_and( a ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_or( self, a, b ): self.reg[ a ] |= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_shl( self, a, b ): self.reg[ a ] <<= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_shr( self, a, b ): self.reg[ a ] >>= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_sub( self, a, b ): self.reg[ a ] -= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> def hndl_xor( self, a, b ): self.reg[ a ] ^= self.reg[ b ] self.base_and( a ) self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand - # ===========> + # ============> # Instruction Helpers --------------------------------> def inc_pc( self, num ): self.pc += num - # ===========> + # ============> def inc_sp( self ): self.reg[ self.sp ] += 1 self.base_and( self.sp ) - # ===========> + # ============> def dec_sp( self ): self.reg[ self.sp ] -= 1 - # ===========> + # ============> def base_and( self, a, b=0xFF ): self.reg[ a ] &= b - # ===========> + # ============> def set_flag( self, flag ): From 035fcb8d8e30866733481629779f50fd97f259e3 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 14:18:20 -0500 Subject: [PATCH 18/28] removed unused alu function in favor of alu branch table & more spacing for consistency --- ls8/cpu.py | 45 ++++++++++----------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 206290dc2..970043d1b 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -105,7 +105,7 @@ def ram_write( self, MAR, MDR ): # ============> - def load(self): + def load( self ): """Load a program into memory.""" if len( sys.argv ) != 2: @@ -137,49 +137,24 @@ def load(self): # ====================================================> - """ - # ALU ------------------------------------------------> - def alu(self, ins, reg_a, reg_b): - """'''ALU operations.'''""" - - if ins == ADD: - self.reg[ reg_a ] += self.reg[ reg_b ] - - elif ins == SUB: - self.reg[ reg_a ] -= self.reg[ reg_b ] - - elif ins == MUL: - self.reg[ reg_a ] *= self.reg[ reg_b ] - - elif ins == DIV: - self.reg[ reg_a ] /= self.reg[ reg_b ] - - else: - raise Exception("Unsupported ALU operation") - - self.pc += 3 # +1 base increment plus 1 for each used operand - # ====================================================> - """ - - # Traceback ------------------------------------------> - def trace(self): + def trace( self ): """ Handy function to print out the CPU state. You might want to call this from run() if you need help debugging. """ - print(f"TRACE: %02X | %02X %02X %02X |" % ( + print( f"TRACE: %02X | %02X %02X %02X |" % ( self.pc, - #self.fl, + self.fl, #self.ie, - self.ram_read(self.pc), - self.ram_read(self.pc + 1), - self.ram_read(self.pc + 2) - ), end='') + self.ram_read( self.pc ), + self.ram_read( self.pc + 1 ), + self.ram_read( self.pc + 2 ) + ), end = '' ) - for i in range(8): - print(" %02X" % self.reg[i], end='') + for i in range( 8 ): + print( " %02X" % self.reg[ i ], end = '' ) print() # ====================================================> From 435cede810b786921f5c7b9d83e379cbe9505a1d Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 16:19:29 -0500 Subject: [PATCH 19/28] vscode folding tags added around instruction definitions --- ls8/cpu.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 970043d1b..a990dcf45 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -3,7 +3,8 @@ import sys -# Instructions -------------------------------------------> +# Instructions & Flags -----------------------------------> +# region CALL = 0b01010000 HLT = 0b00000001 LDI = 0b10000010 @@ -31,6 +32,7 @@ FLE = 0b00000001 FLG = 0b00000010 FLL = 0b00000100 +# endregion # ========================================================> From e0e12083976a191078542e7264642011c87c362f Mon Sep 17 00:00:00 2001 From: Kronykus Date: Wed, 7 Oct 2020 20:39:07 -0500 Subject: [PATCH 20/28] removed overwriting duplication of stack pointer --- ls8/cpu.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index a990dcf45..3613bf919 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -44,13 +44,12 @@ def __init__(self): """Construct a new CPU.""" self.ram = [ 0 ] * 256 self.reg = [ 0 ] * 8 - self.reg[ 7 ] = 0xF4 self.pc = 0 self.running = True self.sp = 7 self.fl = FLB - self.reg[ self.sp ] = len( self.ram ) - 1 + self.reg[ self.sp ] = 0xF4 # ALU self.alu = {} From cda637ccdf99f52e9c9ed166c40c58e705e73870 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Thu, 8 Oct 2020 19:52:50 -0500 Subject: [PATCH 21/28] timer interrupt --- ls8/cpu.py | 139 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 123 insertions(+), 16 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 3613bf919..d6b8a09db 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,7 +1,7 @@ """CPU functionality.""" import sys - +from time import time # Instructions & Flags -----------------------------------> # region @@ -12,6 +12,9 @@ PRN = 0b01000111 PUSH = 0b01000101 RET = 0b00010001 +ST = 0b10000100 +PRA = 0b01001000 +JMP = 0b01010100 # ALU Instructions ----> ADD = 0b10100000 AND = 0b10101000 @@ -32,6 +35,17 @@ FLE = 0b00000001 FLG = 0b00000010 FLL = 0b00000100 +# Interrupts ----------> +INT = 0b01010010 +IRET = 0b00010011 +I0 = 0b00000001 +I1 = 0b00000010 +I2 = 0b00000100 +I3 = 0b00001000 +I4 = 0b00010000 +I5 = 0b00100000 +I6 = 0b01000000 +I7 = 0b10000000 # endregion # ========================================================> @@ -42,14 +56,22 @@ class CPU: # Constructor ----------------------------------------> def __init__(self): """Construct a new CPU.""" - self.ram = [ 0 ] * 256 - self.reg = [ 0 ] * 8 - self.pc = 0 - self.running = True - self.sp = 7 - self.fl = FLB - - self.reg[ self.sp ] = 0xF4 + self.ram = [ 0 ] * 256 # RAM + self.reg = [ 0 ] * 8 # Registers + self.pc = 0 # Program Counter + self.running = True # Main Loop Var + self.sp = 7 # Stack Pointer + self.fl = FLB # Flag + self.imsk = 5 # Interrupt Mask + self.istat = 6 # Interrupt Status + + self.intrpts_enbld = True # Interrupt Bool + + self.reg[ self.sp ] = 0xF4 # Empty Stack + self.reg[ self.imsk ] = [ 0b00000011 ] + + # Interrupt Vector Table + self.ivt = [ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF ] # ALU self.alu = {} @@ -72,10 +94,15 @@ def __init__(self): self.b_tbl = {} self.b_tbl[ LDI ] = self.hndl_ldi self.b_tbl[ PRN ] = self.hndl_prn - self.b_tbl[ POP ] = self.hndl_pop self.b_tbl[ PUSH ] = self.hndl_push + self.b_tbl[ POP ] = self.hndl_pop self.b_tbl[ CALL ] = self.hndl_call self.b_tbl[ RET ] = self.hndl_ret + self.b_tbl[ INT ] = self.hndl_intrpt + self.b_tbl[ IRET ] = self.hndl_iret + self.b_tbl[ ST ] = self.hndl_st + self.b_tbl[ PRA ] = self.hndl_pra + self.b_tbl[ JMP ] = self.hndl_jmp self.b_tbl[ ADD ] = self.alu[ ADD ] self.b_tbl[ AND ] = self.alu[ AND ] self.b_tbl[ CMP ] = self.alu[ CMP ] @@ -174,16 +201,14 @@ def hndl_prn( self, a, b ): # ============> - def hndl_pop( self, a, b ): - self.reg[ a ] = self.ram_read( self.reg[ self.sp ] ) - self.inc_sp() + def hndl_push( self, a, b ): + self.base_push( self.reg[ a ] ) self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_push( self, a, b ): - self.dec_sp() - self.ram_write( self.reg[ self.sp ], self.reg[ a ] ) + def hndl_pop( self, a, b ): + self.reg[ a ] = self.base_pop() self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> @@ -201,6 +226,39 @@ def hndl_ret( self, a, b ): # ============> + def hndl_intrpt( self, a, b ): + val = self.reg[ a ] & self.reg[ self.imsk ] + if val in [ I0, I1 ]: + self.reg[ self.istat ] |= val + # ============> + + + def hndl_iret( self, a, b ): + for i in range( 6, -1, -1 ): + self.reg[ i ] = self.base_pop() + + self.fl = self.base_pop() + self.pc = self.base_pop() + + self.intrpts_enbld = True + # ============> + + def hndl_st( self, a, b ): + self.ram_write( self.reg[ a ], self.reg[ b ] ) + self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + # ============> + + + def hndl_pra( self, a, b ): + print( chr( self.reg[ a ] ) ) + self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ============> + + + def hndl_jmp( self, a, b ): + self.pc = self.reg[ a ] + # ============> + # ALU Instructions Handlers --------------------------> def hndl_add( self, a, b ): self.reg[ a ] += self.reg[ b ] @@ -326,6 +384,18 @@ def dec_sp( self ): self.reg[ self.sp ] -= 1 # ============> + def base_push( self, a ): + self.dec_sp() + self.ram_write( self.reg[ self.sp ], a ) + # ============> + + + def base_pop( self ): + val = self.ram_read( self.reg[ self.sp ] ) + self.inc_sp() + return val + # ============> + def base_and( self, a, b=0xFF ): self.reg[ a ] &= b @@ -334,6 +404,31 @@ def base_and( self, a, b=0xFF ): def set_flag( self, flag ): self.fl = flag + # ============> + + + def process_intrpt( self ): + self.intrpts_enbld = False + + pc = None + status = self.reg[ self.istat ] + + if status & I0: + self.reg[ self.istat ] -= I0 + pc = self.ram_read( self.ivt[ 0 ] ) + + elif status & I1: + self.reg[ self.istat ] -= I1 + pc = self.ram_read( self.ivt[ 1 ] ) + + if pc is not None: + self.base_push( self.pc ) + self.base_push( self.fl ) + + for i in range( 0, 7 ): + self.base_push( self.reg[ i ] ) + + self.pc = pc # ====================================================> @@ -341,7 +436,13 @@ def set_flag( self, flag ): def run(self): """Run the CPU.""" + start_time = time() + while self.running: + if self.intrpts_enbld: + if self.reg[ self.istat ] != 0: + self.process_intrpt() + # Instruction Register (IR) IR = self.ram_read( self.pc ) @@ -357,4 +458,10 @@ def run(self): func = self.b_tbl[ IR ] func( op_a, op_b ) + + time_check = time() + + if time_check - start_time >= 1: + self.reg[ self.istat ] += I0 + start_time = time() # EoF ----------------------------------------------------> \ No newline at end of file From d4cad77c8f288b9daa4fcaba96dce8d18513bf4e Mon Sep 17 00:00:00 2001 From: Kronykus Date: Thu, 8 Oct 2020 20:27:40 -0500 Subject: [PATCH 22/28] refactoring --- ls8/cpu.py | 402 ++++++++++++++++++++++++++--------------------------- 1 file changed, 201 insertions(+), 201 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index d6b8a09db..c48919038 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -56,80 +56,80 @@ class CPU: # Constructor ----------------------------------------> def __init__(self): """Construct a new CPU.""" - self.ram = [ 0 ] * 256 # RAM - self.reg = [ 0 ] * 8 # Registers - self.pc = 0 # Program Counter - self.running = True # Main Loop Var - self.sp = 7 # Stack Pointer - self.fl = FLB # Flag - self.imsk = 5 # Interrupt Mask - self.istat = 6 # Interrupt Status - - self.intrpts_enbld = True # Interrupt Bool - - self.reg[ self.sp ] = 0xF4 # Empty Stack - self.reg[ self.imsk ] = [ 0b00000011 ] + self.__ram = [ 0 ] * 256 # RAM + self.__reg = [ 0 ] * 8 # Registers + self.__pc = 0 # Program Counter + self.__running = True # Main Loop Var + self.__sp = 7 # Stack Pointer + self.__fl = FLB # Flag + self.__imsk = 5 # Interrupt Mask + self.__istat = 6 # Interrupt Status + + self.__intrpts_enbld = True # Interrupt Bool + + self.__reg[ self.__sp ] = 0xF4 # Empty Stack + self.__reg[ self.__imsk ] = [ 0b00000011 ] # Interrupt Vector Table - self.ivt = [ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF ] + self.__ivt = [ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF ] # ALU - self.alu = {} - self.alu[ ADD ] = self.hndl_add - self.alu[ AND ] = self.hndl_and - self.alu[ CMP ] = self.hndl_cmp - self.alu[ DEC ] = self.hndl_dec - self.alu[ DIV ] = self.hndl_div - self.alu[ INC ] = self.hndl_inc - self.alu[ MOD ] = self.hndl_mod - self.alu[ MUL ] = self.hndl_mul - self.alu[ NOT ] = self.hndl_not - self.alu[ OR ] = self.hndl_or - self.alu[ SHL ] = self.hndl_shl - self.alu[ SHR ] = self.hndl_shr - self.alu[ SUB ] = self.hndl_sub - self.alu[ XOR ] = self.hndl_xor + self.__alu = {} + self.__alu[ ADD ] = self.__hndl_add + self.__alu[ AND ] = self.__hndl_and + self.__alu[ CMP ] = self.__hndl_cmp + self.__alu[ DEC ] = self.__hndl_dec + self.__alu[ DIV ] = self.__hndl_div + self.__alu[ INC ] = self.__hndl_inc + self.__alu[ MOD ] = self.__hndl_mod + self.__alu[ MUL ] = self.__hndl_mul + self.__alu[ NOT ] = self.__hndl_not + self.__alu[ OR ] = self.__hndl_or + self.__alu[ SHL ] = self.__hndl_shl + self.__alu[ SHR ] = self.__hndl_shr + self.__alu[ SUB ] = self.__hndl_sub + self.__alu[ XOR ] = self.__hndl_xor # Branch Table - self.b_tbl = {} - self.b_tbl[ LDI ] = self.hndl_ldi - self.b_tbl[ PRN ] = self.hndl_prn - self.b_tbl[ PUSH ] = self.hndl_push - self.b_tbl[ POP ] = self.hndl_pop - self.b_tbl[ CALL ] = self.hndl_call - self.b_tbl[ RET ] = self.hndl_ret - self.b_tbl[ INT ] = self.hndl_intrpt - self.b_tbl[ IRET ] = self.hndl_iret - self.b_tbl[ ST ] = self.hndl_st - self.b_tbl[ PRA ] = self.hndl_pra - self.b_tbl[ JMP ] = self.hndl_jmp - self.b_tbl[ ADD ] = self.alu[ ADD ] - self.b_tbl[ AND ] = self.alu[ AND ] - self.b_tbl[ CMP ] = self.alu[ CMP ] - self.b_tbl[ DEC ] = self.alu[ DEC ] - self.b_tbl[ DIV ] = self.alu[ DIV ] - self.b_tbl[ INC ] = self.alu[ INC ] - self.b_tbl[ MOD ] = self.alu[ MOD ] - self.b_tbl[ MUL ] = self.alu[ MUL ] - self.b_tbl[ NOT ] = self.alu[ NOT ] - self.b_tbl[ OR ] = self.alu[ OR ] - self.b_tbl[ SHL ] = self.alu[ SHL ] - self.b_tbl[ SHR ] = self.alu[ SHR ] - self.b_tbl[ SUB ] = self.alu[ SUB ] - self.b_tbl[ XOR ] = self.alu[ XOR ] + self.__b_tbl = {} + self.__b_tbl[ LDI ] = self.__hndl_ldi + self.__b_tbl[ PRN ] = self.__hndl_prn + self.__b_tbl[ PUSH ] = self.__hndl_push + self.__b_tbl[ POP ] = self.__hndl_pop + self.__b_tbl[ CALL ] = self.__hndl_call + self.__b_tbl[ RET ] = self.__hndl_ret + self.__b_tbl[ INT ] = self.__hndl_intrpt + self.__b_tbl[ IRET ] = self.__hndl_iret + self.__b_tbl[ ST ] = self.__hndl_st + self.__b_tbl[ PRA ] = self.__hndl_pra + self.__b_tbl[ JMP ] = self.__hndl_jmp + self.__b_tbl[ ADD ] = self.__alu[ ADD ] + self.__b_tbl[ AND ] = self.__alu[ AND ] + self.__b_tbl[ CMP ] = self.__alu[ CMP ] + self.__b_tbl[ DEC ] = self.__alu[ DEC ] + self.__b_tbl[ DIV ] = self.__alu[ DIV ] + self.__b_tbl[ INC ] = self.__alu[ INC ] + self.__b_tbl[ MOD ] = self.__alu[ MOD ] + self.__b_tbl[ MUL ] = self.__alu[ MUL ] + self.__b_tbl[ NOT ] = self.__alu[ NOT ] + self.__b_tbl[ OR ] = self.__alu[ OR ] + self.__b_tbl[ SHL ] = self.__alu[ SHL ] + self.__b_tbl[ SHR ] = self.__alu[ SHR ] + self.__b_tbl[ SUB ] = self.__alu[ SUB ] + self.__b_tbl[ XOR ] = self.__alu[ XOR ] # ====================================================> # Memory Functions -----------------------------------> # Memory Address Register (MAR) # Memory Data Register (MDR) - def ram_read( self, MAR ): - return self.ram[ MAR ] + def __ram_read( self, MAR ): + return self.__ram[ MAR ] # ============> - def ram_write( self, MAR, MDR ): - self.ram[ MAR ] = MDR + def __ram_write( self, MAR, MDR ): + self.__ram[ MAR ] = MDR # ============> @@ -152,7 +152,7 @@ def load( self ): continue else: try: - self.ram_write( address, int( num, 2 ) ) + self.__ram_write( address, int( num, 2 ) ) except: print( 'Could not convert string to integer' ) @@ -166,269 +166,269 @@ def load( self ): # Traceback ------------------------------------------> - def trace( self ): + def __trace( self ): """ Handy function to print out the CPU state. You might want to call this from run() if you need help debugging. """ print( f"TRACE: %02X | %02X %02X %02X |" % ( - self.pc, - self.fl, + self.__pc, + self.__fl, #self.ie, - self.ram_read( self.pc ), - self.ram_read( self.pc + 1 ), - self.ram_read( self.pc + 2 ) + self.__ram_read( self.__pc ), + self.__ram_read( self.__pc + 1 ), + self.__ram_read( self.__pc + 2 ) ), end = '' ) for i in range( 8 ): - print( " %02X" % self.reg[ i ], end = '' ) + print( " %02X" % self.__reg[ i ], end = '' ) print() # ====================================================> # Instruction Handlers -------------------------------> - def hndl_ldi( self, a, b ): - self.reg[ a ] = b - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_ldi( self, a, b ): + self.__reg[ a ] = b + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_prn( self, a, b ): - print ( self.reg[ a ] ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_prn( self, a, b ): + print ( self.__reg[ a ] ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_push( self, a, b ): - self.base_push( self.reg[ a ] ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_push( self, a, b ): + self.__push( self.__reg[ a ] ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_pop( self, a, b ): - self.reg[ a ] = self.base_pop() - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_pop( self, a, b ): + self.__reg[ a ] = self.__pop() + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_call( self, a, b ): - self.dec_sp() - self.ram_write( self.reg[ self.sp ], self.pc + 2 ) - self.pc = self.reg[ a ] + def __hndl_call( self, a, b ): + self.__dec_sp() + self.__ram_write( self.__reg[ self.__sp ], self.__pc + 2 ) + self.__pc = self.__reg[ a ] # ============> - def hndl_ret( self, a, b ): - self.pc = self.ram_read( self.reg[ self.sp ] ) - self.inc_sp() + def __hndl_ret( self, a, b ): + self.__pc = self.__ram_read( self.__reg[ self.__sp ] ) + self.__inc_sp() # ============> - def hndl_intrpt( self, a, b ): - val = self.reg[ a ] & self.reg[ self.imsk ] + def __hndl_intrpt( self, a, b ): + val = self.__reg[ a ] & self.__reg[ self.__imsk ] if val in [ I0, I1 ]: - self.reg[ self.istat ] |= val + self.__reg[ self.__istat ] |= val # ============> - def hndl_iret( self, a, b ): + def __hndl_iret( self, a, b ): for i in range( 6, -1, -1 ): - self.reg[ i ] = self.base_pop() + self.__reg[ i ] = self.__pop() - self.fl = self.base_pop() - self.pc = self.base_pop() + self.__fl = self.__pop() + self.__pc = self.__pop() - self.intrpts_enbld = True + self.__intrpts_enbld = True # ============> - def hndl_st( self, a, b ): - self.ram_write( self.reg[ a ], self.reg[ b ] ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_st( self, a, b ): + self.__ram_write( self.__reg[ a ], self.__reg[ b ] ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_pra( self, a, b ): - print( chr( self.reg[ a ] ) ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_pra( self, a, b ): + print( chr( self.__reg[ a ] ) ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_jmp( self, a, b ): - self.pc = self.reg[ a ] + def __hndl_jmp( self, a, b ): + self.__pc = self.__reg[ a ] # ============> # ALU Instructions Handlers --------------------------> - def hndl_add( self, a, b ): - self.reg[ a ] += self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_add( self, a, b ): + self.__reg[ a ] += self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_and( self, a, b ): - self.base_and( a, self.reg[ b ] ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_and( self, a, b ): + self.__and( a, self.__reg[ b ] ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_cmp( self, a, b ): - first = self.reg[ a ] - second = self.reg[ b ] + def __hndl_cmp( self, a, b ): + first = self.__reg[ a ] + second = self.__reg[ b ] if first == second: - self.set_flag( FLE ) + self.__set_flag( FLE ) elif first > second: - self.set_flag( FLG ) + self.__set_flag( FLG ) elif first < second: - self.set_flag( FLL ) + self.__set_flag( FLL ) else: - self.set_flag( FLB ) + self.__set_flag( FLB ) # ============> - def hndl_dec( self, a, b ): - self.reg[ a ] -= 1 - self.base_and( a ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_dec( self, a, b ): + self.__reg[ a ] -= 1 + self.__and( a ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_div( self, a, b ): - self.reg[ a ] /= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_div( self, a, b ): + self.__reg[ a ] /= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_inc( self, a, b ): - self.reg[ a ] += 1 - self.base_and( a ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_inc( self, a, b ): + self.__reg[ a ] += 1 + self.__and( a ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_mod( self, a, b ): - self.reg[ a ] %= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_mod( self, a, b ): + self.__reg[ a ] %= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_mul( self, a, b ): - self.reg[ a ] *= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_mul( self, a, b ): + self.__reg[ a ] *= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_not( self, a, b ): - self.reg[ a ] = ~self.reg[ a ] - self.base_and( a ) - self.inc_pc( 2 ) # +1 base increment plus 1 for each used operand + def __hndl_not( self, a, b ): + self.__reg[ a ] = ~self.__reg[ a ] + self.__and( a ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_or( self, a, b ): - self.reg[ a ] |= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_or( self, a, b ): + self.__reg[ a ] |= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_shl( self, a, b ): - self.reg[ a ] <<= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_shl( self, a, b ): + self.__reg[ a ] <<= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_shr( self, a, b ): - self.reg[ a ] >>= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_shr( self, a, b ): + self.__reg[ a ] >>= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_sub( self, a, b ): - self.reg[ a ] -= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_sub( self, a, b ): + self.__reg[ a ] -= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> - def hndl_xor( self, a, b ): - self.reg[ a ] ^= self.reg[ b ] - self.base_and( a ) - self.inc_pc( 3 ) # +1 base increment plus 1 for each used operand + def __hndl_xor( self, a, b ): + self.__reg[ a ] ^= self.__reg[ b ] + self.__and( a ) + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> # Instruction Helpers --------------------------------> - def inc_pc( self, num ): - self.pc += num + def __inc_pc( self, num ): + self.__pc += num # ============> - def inc_sp( self ): - self.reg[ self.sp ] += 1 - self.base_and( self.sp ) + def __inc_sp( self ): + self.__reg[ self.__sp ] += 1 + self.__and( self.__sp ) # ============> - def dec_sp( self ): - self.reg[ self.sp ] -= 1 + def __dec_sp( self ): + self.__reg[ self.__sp ] -= 1 # ============> - def base_push( self, a ): - self.dec_sp() - self.ram_write( self.reg[ self.sp ], a ) + def __push( self, a ): + self.__dec_sp() + self.__ram_write( self.__reg[ self.__sp ], a ) # ============> - def base_pop( self ): - val = self.ram_read( self.reg[ self.sp ] ) - self.inc_sp() + def __pop( self ): + val = self.__ram_read( self.__reg[ self.__sp ] ) + self.__inc_sp() return val # ============> - def base_and( self, a, b=0xFF ): - self.reg[ a ] &= b + def __and( self, a, b=0xFF ): + self.__reg[ a ] &= b # ============> - def set_flag( self, flag ): - self.fl = flag + def __set_flag( self, flag ): + self.__fl = flag # ============> - def process_intrpt( self ): - self.intrpts_enbld = False + def __process_intrpt( self ): + self.__intrpts_enbld = False pc = None - status = self.reg[ self.istat ] + status = self.__reg[ self.__istat ] if status & I0: - self.reg[ self.istat ] -= I0 - pc = self.ram_read( self.ivt[ 0 ] ) + self.__reg[ self.__istat ] -= I0 + pc = self.__ram_read( self.__ivt[ 0 ] ) elif status & I1: - self.reg[ self.istat ] -= I1 - pc = self.ram_read( self.ivt[ 1 ] ) + self.__reg[ self.__istat ] -= I1 + pc = self.__ram_read( self.__ivt[ 1 ] ) if pc is not None: - self.base_push( self.pc ) - self.base_push( self.fl ) + self.__push( self.__pc ) + self.__push( self.__fl ) for i in range( 0, 7 ): - self.base_push( self.reg[ i ] ) + self.__push( self.__reg[ i ] ) - self.pc = pc + self.__pc = pc # ====================================================> @@ -438,30 +438,30 @@ def run(self): start_time = time() - while self.running: - if self.intrpts_enbld: - if self.reg[ self.istat ] != 0: - self.process_intrpt() + while self.__running: + if self.__intrpts_enbld: + if self.__reg[ self.__istat ] != 0: + self.__process_intrpt() # Instruction Register (IR) - IR = self.ram_read( self.pc ) + IR = self.__ram_read( self.__pc ) if IR == HLT: - self.running = False + self.__running = False - elif IR not in self.b_tbl: - print( f'Instruction Register Unknown: {IR} at program counter {self.pc}' ) - self.running = False + elif IR not in self.__b_tbl: + print( f'Instruction Register Unknown: {IR} at program counter {self.__pc}' ) + self.__running = False else: - op_a = self.ram_read( self.pc + 1 ) - op_b = self.ram_read( self.pc + 2 ) + op_a = self.__ram_read( self.__pc + 1 ) + op_b = self.__ram_read( self.__pc + 2 ) - func = self.b_tbl[ IR ] + func = self.__b_tbl[ IR ] func( op_a, op_b ) time_check = time() if time_check - start_time >= 1: - self.reg[ self.istat ] += I0 + self.__reg[ self.__istat ] += I0 start_time = time() # EoF ----------------------------------------------------> \ No newline at end of file From ea37c5b61f271460fd4f32d90de83950b9abf468 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Thu, 8 Oct 2020 21:02:55 -0500 Subject: [PATCH 23/28] spacing --- ls8/cpu.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index c48919038..0a937b9c6 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -243,6 +243,7 @@ def __hndl_iret( self, a, b ): self.__intrpts_enbld = True # ============> + def __hndl_st( self, a, b ): self.__ram_write( self.__reg[ a ], self.__reg[ b ] ) self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand @@ -259,6 +260,7 @@ def __hndl_jmp( self, a, b ): self.__pc = self.__reg[ a ] # ============> + # ALU Instructions Handlers --------------------------> def __hndl_add( self, a, b ): self.__reg[ a ] += self.__reg[ b ] @@ -384,6 +386,7 @@ def __dec_sp( self ): self.__reg[ self.__sp ] -= 1 # ============> + def __push( self, a ): self.__dec_sp() self.__ram_write( self.__reg[ self.__sp ], a ) @@ -452,6 +455,7 @@ def run(self): elif IR not in self.__b_tbl: print( f'Instruction Register Unknown: {IR} at program counter {self.__pc}' ) self.__running = False + else: op_a = self.__ram_read( self.__pc + 1 ) op_b = self.__ram_read( self.__pc + 2 ) From 0cfa02431361477bfa463feec2d9cf9084374420 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Thu, 8 Oct 2020 21:44:47 -0500 Subject: [PATCH 24/28] comments --- ls8/cpu.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 0a937b9c6..b3e8e1e9c 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -4,7 +4,7 @@ from time import time # Instructions & Flags -----------------------------------> -# region +# region <-- vscode collapse region tag CALL = 0b01010000 HLT = 0b00000001 LDI = 0b10000010 @@ -67,7 +67,8 @@ def __init__(self): self.__intrpts_enbld = True # Interrupt Bool - self.__reg[ self.__sp ] = 0xF4 # Empty Stack + self.__reg[ self.__sp ] = 0xF4 # Empty Stack + # Interrupt Mask; I0 & I1 only self.__reg[ self.__imsk ] = [ 0b00000011 ] # Interrupt Vector Table From bd65c2bfd2ffb54c47bb17b00a49374266133266 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 9 Oct 2020 11:55:01 -0500 Subject: [PATCH 25/28] code structure --- ls8/cpu.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index b3e8e1e9c..27bb4ed95 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -68,6 +68,7 @@ def __init__(self): self.__intrpts_enbld = True # Interrupt Bool self.__reg[ self.__sp ] = 0xF4 # Empty Stack + # Interrupt Mask; I0 & I1 only self.__reg[ self.__imsk ] = [ 0b00000011 ] @@ -122,6 +123,7 @@ def __init__(self): # Memory Functions -----------------------------------> + # region # Memory Address Register (MAR) # Memory Data Register (MDR) def __ram_read( self, MAR ): @@ -163,6 +165,20 @@ def load( self ): except: print( 'File not found' ) sys.exit( 1 ) + # ============> + + + def __push( self, a ): + self.__dec_sp() + self.__ram_write( self.__reg[ self.__sp ], a ) + # ============> + + + def __pop( self ): + val = self.__ram_read( self.__reg[ self.__sp ] ) + self.__inc_sp() + return val + # endregion # ====================================================> @@ -190,6 +206,7 @@ def __trace( self ): # Instruction Handlers -------------------------------> + # region def __hndl_ldi( self, a, b ): self.__reg[ a ] = b self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand @@ -260,9 +277,11 @@ def __hndl_pra( self, a, b ): def __hndl_jmp( self, a, b ): self.__pc = self.__reg[ a ] # ============> + # endregion # ALU Instructions Handlers --------------------------> + # region def __hndl_add( self, a, b ): self.__reg[ a ] += self.__reg[ b ] self.__and( a ) @@ -369,9 +388,11 @@ def __hndl_xor( self, a, b ): self.__and( a ) self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> + # endregion # Instruction Helpers --------------------------------> + # region def __inc_pc( self, num ): self.__pc += num # ============> @@ -388,19 +409,6 @@ def __dec_sp( self ): # ============> - def __push( self, a ): - self.__dec_sp() - self.__ram_write( self.__reg[ self.__sp ], a ) - # ============> - - - def __pop( self ): - val = self.__ram_read( self.__reg[ self.__sp ] ) - self.__inc_sp() - return val - # ============> - - def __and( self, a, b=0xFF ): self.__reg[ a ] &= b # ============> @@ -433,6 +441,7 @@ def __process_intrpt( self ): self.__push( self.__reg[ i ] ) self.__pc = pc + # endregion # ====================================================> From f2726f63f715ff9bc5687e2ab98e0d73bf2b236e Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 9 Oct 2020 21:03:45 -0500 Subject: [PATCH 26/28] comments and histogram --- ls8/cpu.py | 62 +++++++++++++++++++++++++++++++++++++- ls8/examples/histogram.ls8 | 29 ++++++++++++++++++ ls8/examples/sctest.ls8 | 48 ++++++++++++++--------------- 3 files changed, 114 insertions(+), 25 deletions(-) create mode 100644 ls8/examples/histogram.ls8 diff --git a/ls8/cpu.py b/ls8/cpu.py index 27bb4ed95..daecbc2b9 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -12,9 +12,14 @@ PRN = 0b01000111 PUSH = 0b01000101 RET = 0b00010001 +LD = 0b10000011 ST = 0b10000100 PRA = 0b01001000 +PRL = 0b01110011 JMP = 0b01010100 +JEQ = 0b01010101 +JNE = 0b01010110 +JLT = 0b01011000 # ALU Instructions ----> ADD = 0b10100000 AND = 0b10101000 @@ -68,7 +73,7 @@ def __init__(self): self.__intrpts_enbld = True # Interrupt Bool self.__reg[ self.__sp ] = 0xF4 # Empty Stack - + # Interrupt Mask; I0 & I1 only self.__reg[ self.__imsk ] = [ 0b00000011 ] @@ -102,9 +107,14 @@ def __init__(self): self.__b_tbl[ RET ] = self.__hndl_ret self.__b_tbl[ INT ] = self.__hndl_intrpt self.__b_tbl[ IRET ] = self.__hndl_iret + self.__b_tbl[ LD ] = self.__hndl_ld self.__b_tbl[ ST ] = self.__hndl_st self.__b_tbl[ PRA ] = self.__hndl_pra + self.__b_tbl[ PRL ] = self.__hndl_prl self.__b_tbl[ JMP ] = self.__hndl_jmp + self.__b_tbl[ JEQ ] = self.__hndl_jeq + self.__b_tbl[ JNE ] = self.__hndl_jne + self.__b_tbl[ JLT ] = self.__hndl_jlt self.__b_tbl[ ADD ] = self.__alu[ ADD ] self.__b_tbl[ AND ] = self.__alu[ AND ] self.__b_tbl[ CMP ] = self.__alu[ CMP ] @@ -262,6 +272,12 @@ def __hndl_iret( self, a, b ): # ============> + def __hndl_ld( self, a, b ): + self.__reg[ a ] = self.__ram_read( self.reg[ b ] ) + self.__inc_sp( 3 ) # +1 base increment plus 1 for each used operand + # ============> + + def __hndl_st( self, a, b ): self.__ram_write( self.__reg[ a ], self.__reg[ b ] ) self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand @@ -274,9 +290,49 @@ def __hndl_pra( self, a, b ): # ============> + def __hndl_prl( self, a, b ): + for i in range(0, self.__reg[ a ] ): + print( '*', end="" ) + print( '' ) + self.__inc_pc( 2 ) # +1 base increment plus 1 for each used operand + # ============> + + def __hndl_jmp( self, a, b ): self.__pc = self.__reg[ a ] # ============> + + + def __hndl_jeq( self, a, b ): + if self.__fl == FLE: + self.__pc = self.__reg[ a ] + + else: + self.__inc_pc( 2 ) + + self.__fl == FLB + # ============> + + + def __hndl_jne( self, a, b ): + if self.__fl in [ FLB, FLG, FLL ]: + self.__pc = self.__reg[ a ] + + else: + self.__inc_pc( 2 ) + + self.__fl == FLB + # ============> + + + def __hndl_jlt( self, a, b ): + if self.__fl == FLL: + self.__pc = self.__reg[ a ] + + else: + self.__inc_pc( 2 ) + + self.__fl == FLB # endregion @@ -300,6 +356,7 @@ def __hndl_cmp( self, a, b ): second = self.__reg[ b ] if first == second: + #print( 'equal' ) self.__set_flag( FLE ) elif first > second: @@ -309,7 +366,10 @@ def __hndl_cmp( self, a, b ): self.__set_flag( FLL ) else: + #print( 'not equal' ) self.__set_flag( FLB ) + + self.__inc_pc( 3 ) # +1 base increment plus 1 for each used operand # ============> diff --git a/ls8/examples/histogram.ls8 b/ls8/examples/histogram.ls8 new file mode 100644 index 000000000..20a548a55 --- /dev/null +++ b/ls8/examples/histogram.ls8 @@ -0,0 +1,29 @@ +10000010 # LDI R0,1 +00000000 +00000001 +10000010 # LDI R1,1 +00000001 +00000001 +10000010 # LDI R2,8 +00000010 +00001000 +10000010 # LDI R3,2 +00000011 +00000010 +10000010 # LDI R4,PRINT +00000100 +00001111 +# PRINT (address 15): +01110011 # PRL R0 +00000000 +10100010 # MUL R0,R3 +00000000 +00000011 +01100101 # INC R1 +00000001 +10100111 # CMP R1,R2 +00000001 +00000010 +01011000 # JLT R4 +00000100 +00000001 # HLT diff --git a/ls8/examples/sctest.ls8 b/ls8/examples/sctest.ls8 index 7853b76a4..a063d4bdb 100644 --- a/ls8/examples/sctest.ls8 +++ b/ls8/examples/sctest.ls8 @@ -1,31 +1,31 @@ 10000010 # LDI R0,10 00000000 -00001010 +00001010 # R0 = 10 10000010 # LDI R1,20 00000001 -00010100 +00010100 # R1 = 20 10000010 # LDI R2,TEST1 00000010 -00010011 +00010011 # R2 = address of test1 (19 line 21) 10100111 # CMP R0,R1 00000000 -00000001 +00000001 # 10 != 20 FLB 01010101 # JEQ R2 -00000010 +00000010 # not equal do nothing 10000010 # LDI R3,1 00000011 -00000001 +00000001 # R3 = 1 01000111 # PRN R3 -00000011 +00000011 # print 1 # TEST1 (address 19): 10000010 # LDI R2,TEST2 00000010 -00100000 +00100000 # R2 = address of test2 (32 line 35) 10100111 # CMP R0,R1 00000000 -00000001 +00000001 # 10 != 20 FLB 01010110 # JNE R2 -00000010 +00000010 # not equal jump to address in R2 (32 line 35) 10000010 # LDI R3,2 00000011 00000010 @@ -34,15 +34,15 @@ # TEST2 (address 32): 10000010 # LDI R1,10 00000001 -00001010 +00001010 # from jump line 28 R1 = 10 10000010 # LDI R2,TEST3 00000010 -00110000 +00110000 # R2 = address of test3 (48 line 52) 10100111 # CMP R0,R1 00000000 -00000001 +00000001 # 10 = 10 FLE 01010101 # JEQ R2 -00000010 +00000010 # equal jump to address in R2 (48 line 52) 10000010 # LDI R3,3 00000011 00000011 @@ -51,29 +51,29 @@ # TEST3 (address 48): 10000010 # LDI R2,TEST4 00000010 -00111101 +00111101 # from jump line 45 R2 = address of test4 (61 line 66) 10100111 # CMP R0,R1 00000000 -00000001 +00000001 # 10 = 10 FLE 01010110 # JNE R2 -00000010 +00000010 # equal do nothing 10000010 # LDI R3,4 00000011 -00000100 +00000100 # R3 = 4 01000111 # PRN R3 -00000011 +00000011 # print 4 # TEST4 (address 61): 10000010 # LDI R3,5 00000011 -00000101 +00000101 # R3 = 5 01000111 # PRN R3 -00000011 +00000011 # print 5 10000010 # LDI R2,TEST5 00000010 -01001001 +01001001 # R2 = address of test5 (73 line 79) 01010100 # JMP R2 -00000010 +00000010 # jump to address in R2 (73 line 79) 01000111 # PRN R3 00000011 # TEST5 (address 73): -00000001 # HLT +00000001 # HLT # end program From 7876764d2fa2ab419982421787d6022738b2837c Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 9 Oct 2020 21:06:53 -0500 Subject: [PATCH 27/28] separator --- ls8/cpu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index daecbc2b9..0bf9e05ea 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -333,6 +333,7 @@ def __hndl_jlt( self, a, b ): self.__inc_pc( 2 ) self.__fl == FLB + # ============> # endregion From 2d448e1ac48751c42a62bf0b10b00ddfdeb28a81 Mon Sep 17 00:00:00 2001 From: Kronykus Date: Fri, 9 Oct 2020 21:11:46 -0500 Subject: [PATCH 28/28] previous git add from subdir; missed files --- asm/asm.py | 1 + asm/histogram.asm | 26 ++++++++++++++++++++++++++ asm/mult.asm | 6 +++--- 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 asm/histogram.asm diff --git a/asm/asm.py b/asm/asm.py index b597d6418..7944b0cf6 100644 --- a/asm/asm.py +++ b/asm/asm.py @@ -44,6 +44,7 @@ "NOT": {"type": 1, "code": "01101001"}, "OR": {"type": 2, "code": "10101010"}, "POP": {"type": 1, "code": "01000110"}, + "PRL": {"type": 1, "code": "01110011"}, "PRA": {"type": 1, "code": "01001000"}, "PRN": {"type": 1, "code": "01000111"}, "PUSH": {"type": 1, "code": "01000101"}, diff --git a/asm/histogram.asm b/asm/histogram.asm new file mode 100644 index 000000000..99058d4fb --- /dev/null +++ b/asm/histogram.asm @@ -0,0 +1,26 @@ +; histogram.asm +; +; Expected output: +; * +; ** +; **** +; ******** +; **************** +; ******************************** +; **************************************************************** + +LDI R0,1 ; 0 - current asterisks +LDI R1,1 ; 1 - current line +LDI R2,8 ; 2 - max lines + 1 +LDI R3,2 ; 3 - multiply by +LDI R4,Print ; 4 - load print address + +Print: + +PRL R0 ; 5 - print line with current asterisks +MUL R0,R3 ; 6 - double current asterisks +INC R1 ; 7 - increment current line +CMP R1,R2 ; 8 - compare lines +JLT R4 ; 9 - less than max lines loop back to print +HLT ; 10 - halt when done + diff --git a/asm/mult.asm b/asm/mult.asm index ef8c65192..9761c4a4d 100644 --- a/asm/mult.asm +++ b/asm/mult.asm @@ -1,6 +1,6 @@ -# mult.asm -# -# Expected output: 72 +; mult.asm +; +; Expected output: 72 LDI R0,8 LDI R1,9