From 515099fb376b43f4c87c1d69ca3687b2209abe27 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Wed, 2 Dec 2020 21:12:58 -0800 Subject: [PATCH 1/9] Ram read and write done. --- ls8/cpu.py | 47 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..69146f55c 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -3,11 +3,18 @@ import sys class CPU: - """Main CPU class.""" - def __init__(self): """Construct a new CPU.""" - pass + self.ram = [0] * 256 + self.pc = 0 + self.reg = [0] * 8 + self.running = True + + def ram_read(self,addr): + return self.ram[addr] + + def ram_write(self,val,addr): + self.ram[addr] = val def load(self): """Load a program into memory.""" @@ -62,4 +69,36 @@ def trace(self): def run(self): """Run the CPU.""" - pass + HLT = 0b00000001 + LDI = 0b10000010 + PRN = 0b01000111 + self.load() + ir = self.ram[self.pc] + operand_a = self.ram_read(self.pc+1) + operand_b = self.ram_read(self.pc+2) + + while self.running: + + if ir == LDI: + reg = self.reg[regval] + self.pc += 1 + reg = value + self.pc += 1 + elif command == '0b01000111': + PRN(command) + elif command == '0b00000001': + HLT() + + def LDI(self, regval, value): + reg = self.reg[regval] + self.pc += 1 + reg = value + self.pc += 1 + + def HLT(self): + self.running = False + + def PRN(self, regval): + reg = self.reg[regval] + print (reg) + self.pc +=1 From ed7f0deb8f07a561527a1dc18ce84edbfe63abaa Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 6 Dec 2020 19:44:01 -0800 Subject: [PATCH 2/9] HLT, PRN and LDI done --- ls8/cpu.py | 59 +++++++++++++++++++----------------------- ls8/lecture.py | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 33 deletions(-) create mode 100644 ls8/lecture.py diff --git a/ls8/cpu.py b/ls8/cpu.py index 69146f55c..521b26f16 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,12 +2,17 @@ import sys +HLT = 0b00000001 +LDI = 0b10000010 +PRN = 0b01000111 + class CPU: def __init__(self): """Construct a new CPU.""" self.ram = [0] * 256 self.pc = 0 self.reg = [0] * 8 + self.reg[7] = 0xF4 #refer PowerON state in Spec self.running = True def ram_read(self,addr): @@ -37,7 +42,6 @@ def load(self): self.ram[address] = instruction address += 1 - def alu(self, op, reg_a, reg_b): """ALU operations.""" @@ -69,36 +73,25 @@ def trace(self): def run(self): """Run the CPU.""" - HLT = 0b00000001 - LDI = 0b10000010 - PRN = 0b01000111 - self.load() - ir = self.ram[self.pc] - operand_a = self.ram_read(self.pc+1) - operand_b = self.ram_read(self.pc+2) - + + #self.load() while self.running: - - if ir == LDI: - reg = self.reg[regval] - self.pc += 1 - reg = value - self.pc += 1 - elif command == '0b01000111': - PRN(command) - elif command == '0b00000001': - HLT() - - def LDI(self, regval, value): - reg = self.reg[regval] - self.pc += 1 - reg = value - self.pc += 1 - - def HLT(self): - self.running = False - - def PRN(self, regval): - reg = self.reg[regval] - print (reg) - self.pc +=1 + instruction_to_excecute = self.ram[self.pc] + operand_a = self.ram_read(self.pc+1) + operand_b = self.ram_read(self.pc+2) + if instruction_to_excecute == LDI: + self.reg[operand_a] = operand_b + self.pc += 3 + elif instruction_to_excecute == PRN: + reg = self.reg[operand_a] + print (reg) + self.pc +=2 + elif instruction_to_excecute == HLT: + self.running = False + self.pc +=1 + else: + print ("idk what to to") + pass + + + diff --git a/ls8/lecture.py b/ls8/lecture.py new file mode 100644 index 000000000..15f6c1619 --- /dev/null +++ b/ls8/lecture.py @@ -0,0 +1,70 @@ +import sys + +# machine that excecutes an instruction + +# op-code - represent the instruction that is supposed to be executed +PRINT_HI = 1 +HALT = 2 +PRINT_NUM = 3 +SAVE = 4 # SAVE a val in reg +PRINT_REGISTER = 5 +ADD = 6 #takes 2 reg A and B, adds both and stores in reg A + +memory = [ + PRINT_HI, + SAVE, # save val 65 in reg 2 + 65, + 2, + SAVE, + 20, + 3, + ADD, # add vals in reg 2,3 abd store in reg 2 + 2, + 3, + PRINT_REGISTER, + 2, + HALT +] + +program_counter = 0 # points to curr inst we need to execute next +running = True +registers = [0] * 8 #8 registers + +#keep looping while not Halted + +while running: + command_to_execute = memory[program_counter] + + if command_to_execute == PRINT_HI: + print("hi") + program_counter+=1 + elif command_to_execute == PRINT_NUM: + number_to_print = memory[program_counter +1] + print(f"{number_to_print}") + program_counter+=2 + elif command_to_execute == SAVE: + value_to_save = memory[program_counter+1] + register_to_save_it_in = memory[program_counter+2] + registers[register_to_save_it_in] = value_to_save + program_counter+=3 + elif command_to_execute == PRINT_REGISTER: + register_to_print = memory[program_counter+1] + print(f"{registers[register_to_print]}") + program_counter +=2 + elif command_to_execute == ADD: + register_a = memory[program_counter+1] + register_b = memory[program_counter+2] + sum_of_reg = registers[register_a]+registers[register_b] + registers[register_a] = sum_of_reg + program_counter +=3 + + elif command_to_execute == HALT: + running = False + program_counter+=1 + else: + print("unknown instruction {command_to_execute}") + sys.exit(1) + + + + From d72da52599831dfc0066afa865d2e4b31763d80a Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 6 Dec 2020 20:57:27 -0800 Subject: [PATCH 3/9] Getting an error with MUL --- asm/mult.asm | 2 +- ls8/cpu.py | 41 +++++++++++++++++++++++++---------------- ls8/ls8.py | 14 ++++++++++++-- 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/asm/mult.asm b/asm/mult.asm index ef8c65192..d9c1f890c 100644 --- a/asm/mult.asm +++ b/asm/mult.asm @@ -2,7 +2,7 @@ # # Expected output: 72 -LDI R0,8 +LDI R0,8 LDI R1,9 MUL R0,R1 PRN R0 diff --git a/ls8/cpu.py b/ls8/cpu.py index 521b26f16..bc6268710 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -5,6 +5,7 @@ HLT = 0b00000001 LDI = 0b10000010 PRN = 0b01000111 +MUL = 0b10100010 class CPU: def __init__(self): @@ -21,33 +22,34 @@ def ram_read(self,addr): def ram_write(self,val,addr): self.ram[addr] = val - def load(self): + def load(self,filename): """Load a program into memory.""" address = 0 + # program = [] - # For now, we've just hardcoded a program: + with open(filename) as f: + for line in f: + comment_split = line.split("#") + maybe_binary_number = comment_split[0].strip() - program = [ - # From print8.ls8 - 0b10000010, # LDI R0,8 - 0b00000000, - 0b00001000, - 0b01000111, # PRN R0 - 0b00000000, - 0b00000001, # HLT - ] + try: + x = int(maybe_binary_number, 2) + # program.append(x) + + except: + continue - for instruction in program: - self.ram[address] = instruction - address += 1 + # for instruction in program: + self.ram[address] = x + address += 1 def alu(self, op, reg_a, reg_b): """ALU operations.""" - 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] else: raise Exception("Unsupported ALU operation") @@ -71,6 +73,10 @@ def trace(self): print() + + def num_of_operands(self, instruction_to_execute): + return ((instruction_to_execute >> 6) & 0b11) + 1 + def run(self): """Run the CPU.""" @@ -89,6 +95,9 @@ def run(self): elif instruction_to_excecute == HLT: self.running = False self.pc +=1 + elif instruction_to_excecute == MUL: + self.alu(instruction_to_excecute,operand_a,operand_b) + self.pc += self.num_of_operands(instruction_to_excecute) else: print ("idk what to to") pass diff --git a/ls8/ls8.py b/ls8/ls8.py index 74128d36b..3456c08bc 100755 --- a/ls8/ls8.py +++ b/ls8/ls8.py @@ -7,5 +7,15 @@ cpu = CPU() -cpu.load() -cpu.run() \ No newline at end of file +try: + filename = sys.argv[1] + with open(filename) as f: + cpu.load(filename) + cpu.run() +except IndexError: + print("please pass an input .ls8 file") +except FileNotFoundError: + print("file not found.") + +# cpu.load() +# cpu.run() \ No newline at end of file From a8305322b5a4dd4ae544c5dbda4660677fcfb697 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 16:39:42 -0800 Subject: [PATCH 4/9] Fixed the error --- ls8/cpu.py | 41 +++++++++++++++++++---------------------- ls8/ls8.py | 17 ++++++++--------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index bc6268710..9dd9eac43 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -27,28 +27,25 @@ def load(self,filename): address = 0 # program = [] - - with open(filename) as f: - for line in f: - comment_split = line.split("#") - maybe_binary_number = comment_split[0].strip() - - try: - x = int(maybe_binary_number, 2) - # program.append(x) - - except: - continue - - # for instruction in program: - self.ram[address] = x - address += 1 + try: + with open(filename) as f: + for line in f: + comment_split = line.split("#") + maybe_binary_number = comment_split[0] + try: + x = int(maybe_binary_number, 2) + self.ram_write(x, address) + address += 1 + except: + continue + except FileNotFoundError: + print("Cannot find this file..") def alu(self, op, reg_a, reg_b): """ALU operations.""" - if op == "ADD": - self.reg[reg_a] += self.reg[reg_b] - elif op == "MUL": + # if op == "ADD": + # self.reg[reg_a] += self.reg[reg_b] + if op == MUL: self.reg[reg_a] *= self.reg[reg_b] else: raise Exception("Unsupported ALU operation") @@ -87,14 +84,14 @@ def run(self): operand_b = self.ram_read(self.pc+2) if instruction_to_excecute == LDI: self.reg[operand_a] = operand_b - self.pc += 3 + self.pc += self.num_of_operands(instruction_to_excecute) elif instruction_to_excecute == PRN: reg = self.reg[operand_a] print (reg) - self.pc +=2 + self.pc += self.num_of_operands(instruction_to_excecute) elif instruction_to_excecute == HLT: self.running = False - self.pc +=1 + self.pc += self.num_of_operands(instruction_to_excecute) elif instruction_to_excecute == MUL: self.alu(instruction_to_excecute,operand_a,operand_b) self.pc += self.num_of_operands(instruction_to_excecute) diff --git a/ls8/ls8.py b/ls8/ls8.py index 3456c08bc..ea317c881 100755 --- a/ls8/ls8.py +++ b/ls8/ls8.py @@ -7,15 +7,14 @@ cpu = CPU() -try: - filename = sys.argv[1] - with open(filename) as f: - cpu.load(filename) - cpu.run() -except IndexError: - print("please pass an input .ls8 file") -except FileNotFoundError: - print("file not found.") + +filename = sys.argv[1] +cpu.load(filename) +cpu.run() +# except IndexError: +# print("please pass an input .ls8 file") +# except FileNotFoundError: +# print("file not found.") # cpu.load() # cpu.run() \ No newline at end of file From 7b99998f6a72ef08c74c1cd092b9f077c8de0ba8 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 18:13:28 -0800 Subject: [PATCH 5/9] Stack implementation from lecture --- ls8/lecture.py | 60 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/ls8/lecture.py b/ls8/lecture.py index 15f6c1619..83e19a56a 100644 --- a/ls8/lecture.py +++ b/ls8/lecture.py @@ -9,26 +9,40 @@ SAVE = 4 # SAVE a val in reg PRINT_REGISTER = 5 ADD = 6 #takes 2 reg A and B, adds both and stores in reg A +PUSH = 7 # takes in a register and stores a val in that reg on top of a stack +POP = 8 # takes in a register and stores topmost element in the stack in it. -memory = [ - PRINT_HI, - SAVE, # save val 65 in reg 2 - 65, - 2, - SAVE, - 20, - 3, - ADD, # add vals in reg 2,3 abd store in reg 2 - 2, - 3, - PRINT_REGISTER, - 2, - HALT -] +def load_memory(): + program = [ + PRINT_HI, + SAVE, # save val 65 in reg 2 + 65, + 2, + SAVE, + 20, + 3, + PUSH, + 2, + PUSH, + 3, + POP, + 4, + POP, + 0, + HALT + ] + space_for_stack = 128 - len(program) + memory = program + [0] * space_for_stack + return memory + +memory = load_memory() + +registers = [0] * 8 #8 registers +stack_pointer_register = 7 +registers[stack_pointer_register] = len(memory)-1 #address of stack pointer program_counter = 0 # points to curr inst we need to execute next running = True -registers = [0] * 8 #8 registers #keep looping while not Halted @@ -61,10 +75,24 @@ elif command_to_execute == HALT: running = False program_counter+=1 + elif command_to_execute == PUSH: + registers[stack_pointer_register] -=1 # decrement stack pointer + register_to_get_value_in = memory[program_counter+1] + value_in_register = registers[register_to_get_value_in] + memory[registers[stack_pointer_register]] = value_in_register + program_counter +=2 + elif command_to_execute == POP: + register_to_pop_value_in = memory[program_counter+1] + registers[register_to_pop_value_in] = memory[registers[stack_pointer_register]] + registers[stack_pointer_register]+=1 + program_counter+=2 else: print("unknown instruction {command_to_execute}") sys.exit(1) +print (registers) +print (memory) + From 2ce95c132396b378d039f9e7cd2bb5f808df2c83 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 18:35:24 -0800 Subject: [PATCH 6/9] Day 3 complete --- ls8/cpu.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9dd9eac43..f593134fb 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -6,6 +6,10 @@ LDI = 0b10000010 PRN = 0b01000111 MUL = 0b10100010 +PUSH = 0b01000101 +POP = 0b01000110 + +SP = 7 class CPU: def __init__(self): @@ -95,6 +99,14 @@ def run(self): elif instruction_to_excecute == MUL: self.alu(instruction_to_excecute,operand_a,operand_b) self.pc += self.num_of_operands(instruction_to_excecute) + elif instruction_to_excecute == PUSH: + self.reg[SP] -=1 # decrement the stack pointer + self.ram_write(self.reg[operand_a],self.reg[SP]) + self.pc += self.num_of_operands(instruction_to_excecute) + elif instruction_to_excecute == POP: + self.reg[operand_a] = self.ram_read(self.reg[SP]) + self.reg[SP]+=1 + self.pc += self.num_of_operands(instruction_to_excecute) else: print ("idk what to to") pass From 10e2154ea850c826b91e2feeaca57f30dbc57c7f Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 20:00:14 -0800 Subject: [PATCH 7/9] Day 4 lecture code --- ls8/lecture.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/ls8/lecture.py b/ls8/lecture.py index 83e19a56a..21cf13731 100644 --- a/ls8/lecture.py +++ b/ls8/lecture.py @@ -10,26 +10,25 @@ PRINT_REGISTER = 5 ADD = 6 #takes 2 reg A and B, adds both and stores in reg A PUSH = 7 # takes in a register and stores a val in that reg on top of a stack -POP = 8 # takes in a register and stores topmost element in the stack in it. +POP = 8 # takes in a register and stores topmost element in the stack in it. +CALL =9 +RET = 10 +PRINT_SUBROUTINE = 11 def load_memory(): program = [ PRINT_HI, SAVE, # save val 65 in reg 2 - 65, + 7, 2, - SAVE, - 20, - 3, - PUSH, + CALL, 2, - PUSH, - 3, - POP, - 4, - POP, + HALT, + PRINT_SUBROUTINE, + SAVE, + 500, 0, - HALT + RET ] space_for_stack = 128 - len(program) memory = program + [0] * space_for_stack @@ -71,7 +70,6 @@ def load_memory(): sum_of_reg = registers[register_a]+registers[register_b] registers[register_a] = sum_of_reg program_counter +=3 - elif command_to_execute == HALT: running = False program_counter+=1 @@ -86,6 +84,22 @@ def load_memory(): registers[register_to_pop_value_in] = memory[registers[stack_pointer_register]] registers[stack_pointer_register]+=1 program_counter+=2 + elif command_to_execute == PRINT_SUBROUTINE: + print('I am in a SubRoutine') + program_counter+=1 + elif command_to_execute == CALL: + #Takes in a register and stores address of next instruction on top of stack + # it jumps to address stored in that register + registers[stack_pointer_register] -=1 + address_of_next_inst = program_counter+2 + memory[registers[stack_pointer_register]] = address_of_next_inst + register_to_get_addr_from = memory[program_counter+1] + program_counter = registers[register_to_get_addr_from] + elif command_to_execute == RET: + # pops top element of stack and sets PC to it + # does not take any operand + program_counter = memory[registers[stack_pointer_register]] + registers[stack_pointer_register]+=1 else: print("unknown instruction {command_to_execute}") sys.exit(1) From 4ec9cfcb737de5aabf096f276ff022c13b40f599 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 20:23:35 -0800 Subject: [PATCH 8/9] Day 4 MVP --- asm/call.asm | 1 + ls8/cpu.py | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/asm/call.asm b/asm/call.asm index 82266f607..3472dba3a 100644 --- a/asm/call.asm +++ b/asm/call.asm @@ -1,3 +1,4 @@ + ; Demonstrate calls ; ; Expected output: diff --git a/ls8/cpu.py b/ls8/cpu.py index f593134fb..cced1440c 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -8,6 +8,8 @@ MUL = 0b10100010 PUSH = 0b01000101 POP = 0b01000110 +CALL = 0b01010000 +RET = 0b00010001 SP = 7 @@ -107,9 +109,20 @@ def run(self): self.reg[operand_a] = self.ram_read(self.reg[SP]) self.reg[SP]+=1 self.pc += self.num_of_operands(instruction_to_excecute) + elif instruction_to_excecute == CALL: + self.reg[SP]-=1 + addr_of_next_inst = self.pc+2 + self.ram_write(addr_of_next_inst,self.reg[SP]) + reg_to_get_addr_from = operand_a + jump_to_addr = self.reg[reg_to_get_addr_from] + self.pc = jump_to_addr + elif instruction_to_excecute == RET: + addr_to_return = self.ram_read(self.reg[SP]) + self.pc = addr_to_return + self.reg[SP]+=1 else: print ("idk what to to") - pass + sys.exit() From e1d5c74b69e56dbd09fc085bbb8be391e2f98348 Mon Sep 17 00:00:00 2001 From: kmk028 Date: Sun, 13 Dec 2020 21:31:15 -0800 Subject: [PATCH 9/9] SC MVP --- asm/test.asm | 15 +++++++++++++++ ls8/cpu.py | 29 +++++++++++++++++++++++++++-- ls8/ls8.py | 10 +++------- 3 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 asm/test.asm diff --git a/asm/test.asm b/asm/test.asm new file mode 100644 index 000000000..1c63c2116 --- /dev/null +++ b/asm/test.asm @@ -0,0 +1,15 @@ +; Code to test the Sprint Challenge +; +; Expected output: +; 1 +; 4 +; 5 + +LDI R0,10 +LDI R1,20 +LDI R2,Test1 +CMP R0,R1 +JEQ R2 ; Does not jump because R0 != R1 +LDI R3,1 +PRN R3 ; Prints 1 +HLT diff --git a/ls8/cpu.py b/ls8/cpu.py index cced1440c..402eb60ee 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -10,7 +10,10 @@ POP = 0b01000110 CALL = 0b01010000 RET = 0b00010001 - +JMP = 0b01010100 +CMP = 0b10100111 +JEQ = 0b01010101 +JNE = 0b01010110 SP = 7 class CPU: @@ -21,6 +24,7 @@ def __init__(self): self.reg = [0] * 8 self.reg[7] = 0xF4 #refer PowerON state in Spec self.running = True + self.fl = 0b00000000 def ram_read(self,addr): return self.ram[addr] @@ -37,7 +41,7 @@ def load(self,filename): with open(filename) as f: for line in f: comment_split = line.split("#") - maybe_binary_number = comment_split[0] + maybe_binary_number = comment_split[0].strip() try: x = int(maybe_binary_number, 2) self.ram_write(x, address) @@ -120,9 +124,30 @@ def run(self): addr_to_return = self.ram_read(self.reg[SP]) self.pc = addr_to_return self.reg[SP]+=1 + elif instruction_to_excecute == JMP: + self.pc = self.reg[operand_a] + elif instruction_to_excecute == CMP: + if self.reg[operand_a]>self.reg[operand_b]: + self.fl = 0b00000010 + elif self.reg[operand_a]