From 53947c5261583467b79d5de011ebc7922e6c1689 Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Wed, 9 Dec 2020 11:01:13 -0700 Subject: [PATCH 1/6] JUST GETTING STARTED --- ok.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ok.py diff --git a/ok.py b/ok.py new file mode 100644 index 000000000..e69de29bb From 3668e139f68bc1d43d0bbc95246784e2f1964348 Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Thu, 10 Dec 2020 14:32:30 -0700 Subject: [PATCH 2/6] Working mvp day one --- lecture day one/lecture.py | 78 +++++++++++++++++++++++++ ls8/cpu.py | 115 +++++++++++++++++++++++++++---------- 2 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 lecture day one/lecture.py diff --git a/lecture day one/lecture.py b/lecture day one/lecture.py new file mode 100644 index 000000000..fefac20da --- /dev/null +++ b/lecture day one/lecture.py @@ -0,0 +1,78 @@ +import sys +# a machine that simply executes an instruction + +# op-code - they represent the instruction that is supposed to be executed +PRINT_HI = 1 +HALT = 2 +PRINT_NUM = 3 +SAVE = 4 # save a value in a given register +PRINT_REGISTER = 5 # print value stored in register +ADD = 6 # TAKES IN TWO REGISTERS, a and b and adds both values contained in the registers and stores it in reg A + + +memory = [ + PRINT_HI, + SAVE, # Save 65 2 means save the value 65 in the register 2 + 65, + 2, + SAVE, # Save 20 3 means save the value 20 in the register 3 + 20, + 3, + ADD, # ADD 2 3 means add the values from register 2 and 3 and save them in 2 + 2, + 3, + PRINT_REGISTER, # Will print the value from register 2 + 2, + HALT +] + +program_counter = 0 # points to the current instruction we need to execute next +running = True + +registers = [0] * 8 + +# keep loopiing 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 == HALT: + running = False + program_counter += 1 + + elif command_to_execute == SAVE: + value_to_save = memory[program_counter + 1] + register_saving_to = memory[program_counter + 2] + registers[register_saving_to] = 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: + # 2 registers + register_a = memory[program_counter + 1] + register_b = memory[program_counter + 2] + + # 2 values + register_a_value = registers[register_a] + register_b_value = registers[register_b] + + registers[register_a] = register_a_value + register_b_value + program_counter += 3 + + else: + print(f"error: Uknown instruction {command_to_execute}") + sys.exit(1) + + \ No newline at end of file diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..63a8f83bf 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,12 +2,23 @@ import sys +""" + Inventory what is here + Implement the CPU constructor + Add RAM functions ram_read() and ram_write() + Implement the core of run() + Implement the HLT instruction handler + Add the LDI instruction + Add the PRN instruction + """ class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - pass + self.ram = [0] * 15 + self.pc = 0 + self.registers = [0] * 8 def load(self): """Load a program into memory.""" @@ -16,13 +27,13 @@ def load(self): # For now, we've just hardcoded a program: - program = [ + program = [ # LOOK IN THE SPECS # From print8.ls8 - 0b10000010, # LDI R0,8 - 0b00000000, - 0b00001000, + 0b10000010, # LDI R0,8 (--- one operand ---) + 0b00000000, # this indicates the register to be saved to '0' + 0b00001000, # ---- 8 ---- this indicates the value 0b01000111, # PRN R0 - 0b00000000, + 0b00000000, # index to print in register 0b00000001, # HLT ] @@ -30,36 +41,80 @@ def load(self): self.ram[address] = instruction address += 1 + def ram_read(self, pc): + pass - def alu(self, op, reg_a, reg_b): - """ALU operations.""" + def ram_write(self, pc): + pass - if op == "ADD": - self.reg[reg_a] += self.reg[reg_b] - #elif op == "SUB": etc - else: - raise Exception("Unsupported ALU operation") + # def alu(self, op, reg_a, reg_b): + # """ALU operations.""" - def trace(self): - """ - Handy function to print out the CPU state. You might want to call this - from run() if you need help debugging. - """ + # if op == "ADD": + # self.reg[reg_a] += self.reg[reg_b] + # #elif op == "SUB": etc + # else: + # raise Exception("Unsupported ALU operation") - print(f"TRACE: %02X | %02X %02X %02X |" % ( - self.pc, - #self.fl, - #self.ie, - self.ram_read(self.pc), - self.ram_read(self.pc + 1), - self.ram_read(self.pc + 2) - ), end='') + # def trace(self): + # """ + # Handy function to print out the CPU state. You might want to call this + # from run() if you need help debugging. + # """ - for i in range(8): - print(" %02X" % self.reg[i], end='') + # print(f"TRACE: %02X | %02X %02X %02X |" % ( + # self.pc, + # #self.fl, + # #self.ie, + # self.ram_read(self.pc), + # self.ram_read(self.pc + 1), + # self.ram_read(self.pc + 2) + # ), end='') - print() + # for i in range(8): + # print(" %02X" % self.reg[i], end='') + + # print() def run(self): """Run the CPU.""" - pass + running = True + register_count = -1 + for register in self.registers: + register_count += 1 + if register_count <= 6: + self.registers[register_count] = 0 + else: + self.registers[register_count] = '0xF4' + + self.ram = [0] * 15 + self.pc = 0 + self.load() + + while running: + command_to_execute = self.ram[self.pc] + + # LDI instruction + if command_to_execute == 130: + spot_to_store = self.ram[self.pc + 1] + value_to_store = self.ram[self.pc + 2] + + self.registers[spot_to_store] = value_to_store + + self.pc += 3 + + # PRN instruction + elif command_to_execute == 71: + selected_register = self.ram[self.pc + 1] + print(self.registers[selected_register]) + self.pc += 2 + + # HLT instruction + elif command_to_execute == 1: + running = False + + # EXCEPTION + else: + print("ERROR INCORRECT COMMAND") + + From 168f6d81218fb10d528d1b10ae3e18d091b7fd1e Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Thu, 10 Dec 2020 15:43:37 -0700 Subject: [PATCH 3/6] MARIOSImplementation of the assignment used now: --- ls8/cpu.py | 93 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 63a8f83bf..2e81730d0 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -11,14 +11,22 @@ Add the LDI instruction Add the PRN instruction """ + +HLT = 0b00000001 +LDI = 0b10000010 +PRN = 0b01000111 + + class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - self.ram = [0] * 15 - self.pc = 0 self.registers = [0] * 8 + self.registers[7] = 0XF4 + self.ram = [0] * 256 + self.pc = 0 + self.halted = False def load(self): """Load a program into memory.""" @@ -41,11 +49,11 @@ def load(self): self.ram[address] = instruction address += 1 - def ram_read(self, pc): - pass + def ram_read(self, address): + return self.ram[address] - def ram_write(self, pc): - pass + def ram_write(self, address, value): + self.ram[address] = value # def alu(self, op, reg_a, reg_b): # """ALU operations.""" @@ -78,43 +86,54 @@ def ram_write(self, pc): def run(self): """Run the CPU.""" - running = True - register_count = -1 - for register in self.registers: - register_count += 1 - if register_count <= 6: - self.registers[register_count] = 0 - else: - self.registers[register_count] = '0xF4' - - self.ram = [0] * 15 - self.pc = 0 - self.load() - while running: - command_to_execute = self.ram[self.pc] + while not self.halted: + command_to_execute = self.ram_read(self.pc) + operand_a = self.ram_read(self.pc + 1) + operand_b = self.ram_read(self.pc + 2) + self.execute_instruction(command_to_execute, operand_a, operand_b) + + + def execute_instruction(self, instruction, operand_a, operand_b): + if instruction == HLT: + self.halted = True + elif instruction == PRN: + print(self.registers[operand_a]) + self.pc += 2 + elif instruction == LDI: + self.registers[operand_a] = operand_b + self.pc += 3 + else: + print("ERROR") + + + + + + + - # LDI instruction - if command_to_execute == 130: - spot_to_store = self.ram[self.pc + 1] - value_to_store = self.ram[self.pc + 2] + # # LDI instruction + # if command_to_execute == 130: + # spot_to_store = self.ram[self.pc + 1] + # value_to_store = self.ram[self.pc + 2] - self.registers[spot_to_store] = value_to_store + # self.registers[spot_to_store] = value_to_store - self.pc += 3 + # self.pc += 3 - # PRN instruction - elif command_to_execute == 71: - selected_register = self.ram[self.pc + 1] - print(self.registers[selected_register]) - self.pc += 2 + # # PRN instruction + # elif command_to_execute == 71: + # selected_register = self.ram[self.pc + 1] + # print(self.registers[selected_register]) + # self.pc += 2 - # HLT instruction - elif command_to_execute == 1: - running = False + # # HLT instruction + # elif command_to_execute == 1: + # running = False - # EXCEPTION - else: - print("ERROR INCORRECT COMMAND") + # # EXCEPTION + # else: + # print("ERROR INCORRECT COMMAND") From 6360c537d2deeee5b98ba41e12fde2fa206627c9 Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Fri, 11 Dec 2020 12:36:33 -0700 Subject: [PATCH 4/6] DAY 2 MVP --- LecturedayTwo/lecture.py | 62 +++++++++++++++ ls8/{ => examples}/cpu.py | 47 +++++++----- ls8/examples/lecture-open.py | 17 +++++ ls8/examples/ls8.py | 17 +++++ ls8/ls8.py | 11 --- ok.py | 144 +++++++++++++++++++++++++++++++++++ 6 files changed, 268 insertions(+), 30 deletions(-) create mode 100644 LecturedayTwo/lecture.py rename ls8/{ => examples}/cpu.py (75%) create mode 100644 ls8/examples/lecture-open.py create mode 100755 ls8/examples/ls8.py delete mode 100755 ls8/ls8.py diff --git a/LecturedayTwo/lecture.py b/LecturedayTwo/lecture.py new file mode 100644 index 000000000..3cd06fa37 --- /dev/null +++ b/LecturedayTwo/lecture.py @@ -0,0 +1,62 @@ +#OPERANDS +a = 0b1001 +b = 0b0110 + +c = a & b #0b0000 +d = a | b #0b1111 +e = a ^ b # 0b1111 +# print(format(c, '04b')) +# print(format(d, '04b')) +# print(format(e, '04b')) + + +# SHIFTING +a = 0b1001 + +b = a << 2 # 100100 +print(format(b, '04b')) + +c = a >> 2 # 10 + +print(format(c, '04b')) + +# MASKING (selecting parts of binary) + +# Meanings of the bits int he first byte of each instruction: 'AABCDDDD' + +# * 'AA' number of operands for this opcode, 0-2 + +INSRUCTION = 0b10000010 # shift >> 6 times --> 0b10 & 0b11 --> 0b10 +PC = 0 +number_of_times_to_increment_pc = ((INSRUCTION >> 6) & 0b11) + 1 +PC += number_of_times_to_increment_pc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ls8/cpu.py b/ls8/examples/cpu.py similarity index 75% rename from ls8/cpu.py rename to ls8/examples/cpu.py index 2e81730d0..285da0eff 100644 --- a/ls8/cpu.py +++ b/ls8/examples/cpu.py @@ -1,6 +1,7 @@ """CPU functionality.""" import sys +import os """ Inventory what is here @@ -15,6 +16,7 @@ HLT = 0b00000001 LDI = 0b10000010 PRN = 0b01000111 +MUL = 0b10100010 class CPU: @@ -28,26 +30,30 @@ def __init__(self): self.pc = 0 self.halted = False - def load(self): - """Load a program into memory.""" - - address = 0 - - # For now, we've just hardcoded a program: + def decimal_to_binary(self,x): + return int(bin(x)[:2]) - program = [ # LOOK IN THE SPECS - # From print8.ls8 - 0b10000010, # LDI R0,8 (--- one operand ---) - 0b00000000, # this indicates the register to be saved to '0' - 0b00001000, # ---- 8 ---- this indicates the value - 0b01000111, # PRN R0 - 0b00000000, # index to print in register - 0b00000001, # HLT - ] - - for instruction in program: - self.ram[address] = instruction - address += 1 + def load(self, file_name): + """Load a program into memory.""" + current = 0 + counter = 0 + try: + with open(file_name) as my_file: + for line in my_file: + comment_split = line.split("#") + maybe_binary_number = comment_split[0] + + try: + x = int(maybe_binary_number, 2) + self.ram[current] = x + current += 1 + except: + print(f"failed to cast {maybe_binary_number} as an integer.") + continue + except FileNotFoundError: + print(os.getcwd()) + print("file not found") + sys.exit(1) def ram_read(self, address): return self.ram[address] @@ -103,6 +109,9 @@ def execute_instruction(self, instruction, operand_a, operand_b): elif instruction == LDI: self.registers[operand_a] = operand_b self.pc += 3 + elif instruction == MUL: + self.registers[operand_a] = self.registers[operand_a] * self.registers[operand_b] + self.pc += 3 else: print("ERROR") diff --git a/ls8/examples/lecture-open.py b/ls8/examples/lecture-open.py new file mode 100644 index 000000000..3a1e7a44b --- /dev/null +++ b/ls8/examples/lecture-open.py @@ -0,0 +1,17 @@ +import sys + +# print(sys.argv[0]) +try: + with open(sys.argv[1]) as my_file: + for line in my_file: + comment_split = line.split("#") + maybe_binary_number = comment_split[0] + + try: + x = int(maybe_binary_number, 2) + print("{:08b}: {:d}".format(x,x)) + except: + print(f"failed to cast {maybe_binary_number} as an integer") + continue +except FileNotFoundError: + print("file not found") \ No newline at end of file diff --git a/ls8/examples/ls8.py b/ls8/examples/ls8.py new file mode 100755 index 000000000..b7d9bfd7f --- /dev/null +++ b/ls8/examples/ls8.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python3 + +"""Main.""" + +import sys +from cpu import * + +cpu = CPU() + +# file_name_from_command_line = sys.argv[1] +file_name_from_command_line = 'mult.ls8' +print(file_name_from_command_line) + + +cpu.load(f"ls8/examples/{file_name_from_command_line}") +# cpu.load(file_name_from_command_line) +cpu.run() \ No newline at end of file diff --git a/ls8/ls8.py b/ls8/ls8.py deleted file mode 100755 index 74128d36b..000000000 --- a/ls8/ls8.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python3 - -"""Main.""" - -import sys -from cpu import * - -cpu = CPU() - -cpu.load() -cpu.run() \ No newline at end of file diff --git a/ok.py b/ok.py index e69de29bb..485328287 100644 --- a/ok.py +++ b/ok.py @@ -0,0 +1,144 @@ +"""CPU functionality.""" + +import sys +import os + +""" + Inventory what is here + Implement the CPU constructor + Add RAM functions ram_read() and ram_write() + Implement the core of run() + Implement the HLT instruction handler + Add the LDI instruction + Add the PRN instruction + """ + +HLT = '0b1' +LDI = '0b10000010' +PRN = '0b01000111' + + +class CPU: + """Main CPU class.""" + + def __init__(self): + """Construct a new CPU.""" + self.registers = [0] * 8 + self.registers[7] = 0XF4 + self.ram = [0] * 256 + self.pc = 0 + self.halted = False + + def decimal_to_binary(self,x): + return int(bin(x)[:2]) + + def load(self, file_name): + """Load a program into memory.""" + current = 0 + counter = 0 + try: + with open(file_name) as my_file: + for line in my_file: + comment_split = line.split("#") + maybe_binary_number = comment_split[0] + + try: + x = int(maybe_binary_number, 2) + self.ram[current] = x + current += 1 + except: + print(f"failed to cast {maybe_binary_number} as an integer.") + continue + except FileNotFoundError: + print(os.getcwd()) + print("file not found") + sys.exit(1) + + def ram_read(self, address): + return self.ram[address] + + def ram_write(self, address, value): + self.ram[address] = value + + # 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 + # else: + # raise Exception("Unsupported ALU operation") + + # 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.ie, + # 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() + + def run(self): + """Run the CPU.""" + + while not self.halted: + command_to_execute = self.ram_read(self.pc) + operand_a = self.ram_read(self.pc + 1) + operand_b = self.ram_read(self.pc + 2) + self.execute_instruction(command_to_execute, operand_a, operand_b) + + + def execute_instruction(self, instruction, operand_a, operand_b): + if instruction == HLT: + self.halted = True + elif instruction == PRN: + print(self.registers[operand_a]) + self.pc += 2 + elif instruction == LDI: + self.registers[operand_a] = operand_b + self.pc += 3 + else: + print("ERROR") + + + + + + + + + # # LDI instruction + # if command_to_execute == 130: + # spot_to_store = self.ram[self.pc + 1] + # value_to_store = self.ram[self.pc + 2] + + # self.registers[spot_to_store] = value_to_store + + # self.pc += 3 + + # # PRN instruction + # elif command_to_execute == 71: + # selected_register = self.ram[self.pc + 1] + # print(self.registers[selected_register]) + # self.pc += 2 + + # # HLT instruction + # elif command_to_execute == 1: + # running = False + + # # EXCEPTION + # else: + # print("ERROR INCORRECT COMMAND") + + From 3751fa7330243dfd4a06b659c9287b61fce919af Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Fri, 11 Dec 2020 17:40:08 -0700 Subject: [PATCH 5/6] DAY 3 MVP --- LectureDayThree/lecture.py | 108 +++++++++++++++++++++++++++++++++++++ ls8/examples/cpu.py | 33 ++++++++++-- ls8/examples/ls8.py | 12 ++++- 3 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 LectureDayThree/lecture.py diff --git a/LectureDayThree/lecture.py b/LectureDayThree/lecture.py new file mode 100644 index 000000000..2360e00f4 --- /dev/null +++ b/LectureDayThree/lecture.py @@ -0,0 +1,108 @@ +import sys +# a machine that simply executes an instruction + +# op-code - they represent the instruction that is supposed to be executed +PRINT_HI = 1 +HALT = 2 +PRINT_NUM = 3 +SAVE = 4 # save a value in a given register +PRINT_REGISTER = 5 # print value stored in register +ADD = 6 # TAKES IN TWO REGISTERS, a and b and adds both values contained in the registers and stores it in reg A +PUSH = 7 # takes in a register and stores the value in that register on top of the stack +POP = 8 # takes in a register and stores the topmost element in the stack in it + +def load_memory(): + PROGRAM = [ + PRINT_HI, + SAVE, # Save 65 2 means save the value 65 in the register 2 + 65, + 2, + SAVE, # Save 20 3 means save the value 20 in the register 3 + 20, + 3, + PUSH, # PUSH value stored in reg 2 on top of the stack + 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() +program_counter = 0 # points to the current instruction we need to execute next +running = True +registers = [0] * 8 +stack_pointer_register = 7 # register number that contains the address of the stack pointer +registers[stack_pointer_register] = len(memory) - 1 + + +#keep loopiing 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 == HALT: + running = False + program_counter += 1 + + elif command_to_execute == SAVE: + value_to_save = memory[program_counter + 1] + register_saving_to = memory[program_counter + 2] + registers[register_saving_to] = 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: + # 2 registers + register_a = memory[program_counter + 1] + register_b = memory[program_counter + 2] + + # 2 values + register_a_value = registers[register_a] + register_b_value = registers[register_b] + + registers[register_a] = register_a_value + register_b_value + program_counter += 3 + + 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_top_pop_value_in = memory[program_counter + 1] + registers[register_top_pop_value_in] = memory[registers[stack_pointer_register]] + + registers[stack_pointer_register] += 1 + + program_counter += 2 + + else: + print(f"error: Uknown instruction {command_to_execute}") + sys.exit(1) + +print(f"Registers: {registers}") +print(f"Memory: {memory}") \ No newline at end of file diff --git a/ls8/examples/cpu.py b/ls8/examples/cpu.py index 285da0eff..7d2f9ff0a 100644 --- a/ls8/examples/cpu.py +++ b/ls8/examples/cpu.py @@ -17,6 +17,8 @@ LDI = 0b10000010 PRN = 0b01000111 MUL = 0b10100010 +PUSH = 0b01000101 +POP = 0b01000110 class CPU: @@ -29,6 +31,7 @@ def __init__(self): self.ram = [0] * 256 self.pc = 0 self.halted = False + self.stack_point_register = 7 def decimal_to_binary(self,x): return int(bin(x)[:2]) @@ -36,7 +39,7 @@ def decimal_to_binary(self,x): def load(self, file_name): """Load a program into memory.""" current = 0 - counter = 0 + temp = [] try: with open(file_name) as my_file: for line in my_file: @@ -46,15 +49,19 @@ def load(self, file_name): try: x = int(maybe_binary_number, 2) self.ram[current] = x + temp.append(x) current += 1 except: - print(f"failed to cast {maybe_binary_number} as an integer.") continue except FileNotFoundError: print(os.getcwd()) print("file not found") sys.exit(1) + # space_for_stack = 128 - len(temp) + # self.ram += [0] * space_for_stack + + def ram_read(self, address): return self.ram[address] @@ -92,6 +99,8 @@ def ram_write(self, address, value): def run(self): """Run the CPU.""" + + self.registers[self.stack_point_register] = len(self.ram) - 1 while not self.halted: command_to_execute = self.ram_read(self.pc) @@ -99,7 +108,7 @@ def run(self): operand_b = self.ram_read(self.pc + 2) self.execute_instruction(command_to_execute, operand_a, operand_b) - + print(self.ram) def execute_instruction(self, instruction, operand_a, operand_b): if instruction == HLT: self.halted = True @@ -112,6 +121,24 @@ def execute_instruction(self, instruction, operand_a, operand_b): elif instruction == MUL: self.registers[operand_a] = self.registers[operand_a] * self.registers[operand_b] self.pc += 3 + + elif instruction == PUSH: + self.registers[self.stack_point_register] -= 1 + register_to_get_value_in = self.ram[self.pc + 1] + value_in_register = self.registers[register_to_get_value_in] + + self.ram[self.registers[self.stack_point_register]] = value_in_register + + self.pc += 2 + + elif instruction == POP: + register_to_pop_value_in = self.ram[self.pc + 1] + self.registers[register_to_pop_value_in] = self.ram[self.registers[self.stack_point_register]] + + self.registers[self.stack_point_register] += 1 + + self.pc += 2 + else: print("ERROR") diff --git a/ls8/examples/ls8.py b/ls8/examples/ls8.py index b7d9bfd7f..6fcfc0fe9 100755 --- a/ls8/examples/ls8.py +++ b/ls8/examples/ls8.py @@ -5,10 +5,20 @@ import sys from cpu import * +# # Mario's implementation +# if len(sys.argv) != 2: +# print("Wrong number of arguments!") + +# else: +# cpu = CPU() +# cpu.load(sys.argv[1]) +# cpu.run() +# ---------- + cpu = CPU() # file_name_from_command_line = sys.argv[1] -file_name_from_command_line = 'mult.ls8' +file_name_from_command_line = 'stack.ls8' print(file_name_from_command_line) From c864b3ef14741859dd9588b6cc4bc2c77b99dccb Mon Sep 17 00:00:00 2001 From: Kelson Hartle Date: Sun, 13 Dec 2020 18:13:17 -0700 Subject: [PATCH 6/6] SPRINT CHALLENGE MVP --- .../LectureDayThree}/lecture.py | 0 .../LecturedayTwo}/lecture.py | 0 Lectures/lecture day four/lecture.py | 126 ++++++++++++++++++ .../lecture day one}/lecture.py | 0 ls8/examples/cpu.py | 48 ++++++- ls8/examples/ls8.py | 2 +- ls8/examples/sctest.ls8 | 7 + sctest.asm | 52 ++++++++ 8 files changed, 231 insertions(+), 4 deletions(-) rename {LectureDayThree => Lectures/LectureDayThree}/lecture.py (100%) rename {LecturedayTwo => Lectures/LecturedayTwo}/lecture.py (100%) create mode 100644 Lectures/lecture day four/lecture.py rename {lecture day one => Lectures/lecture day one}/lecture.py (100%) create mode 100644 sctest.asm diff --git a/LectureDayThree/lecture.py b/Lectures/LectureDayThree/lecture.py similarity index 100% rename from LectureDayThree/lecture.py rename to Lectures/LectureDayThree/lecture.py diff --git a/LecturedayTwo/lecture.py b/Lectures/LecturedayTwo/lecture.py similarity index 100% rename from LecturedayTwo/lecture.py rename to Lectures/LecturedayTwo/lecture.py diff --git a/Lectures/lecture day four/lecture.py b/Lectures/lecture day four/lecture.py new file mode 100644 index 000000000..26edc843f --- /dev/null +++ b/Lectures/lecture day four/lecture.py @@ -0,0 +1,126 @@ +import sys +# a machine that simply executes an instruction + +# op-code - they represent the instruction that is supposed to be executed +PRINT_HI = 1 +HALT = 2 +PRINT_NUM = 3 +SAVE = 4 # save a value in a given register +PRINT_REGISTER = 5 # print value stored in register +ADD = 6 # TAKES IN TWO REGISTERS, a and b and adds both values contained in the registers and stores it in reg A +PUSH = 7 # takes in a register and stores the value in that register on top of the stack +POP = 8 # takes in a register and stores the topmost element in the stack in it +CALL = 9 +RET = 10 +PRINT_SUBROUTINE_INSTRUCTION = 11 + +def load_memory(): + PROGRAM = [ + PRINT_HI, + SAVE, + 7, + 2, + CALL, + 2, + HALT, + PRINT_SUBROUTINE_INSTRUCTION, + SAVE, + 500, + 0, + RET + ] + + space_for_stack = 128 - len(PROGRAM) + memory = PROGRAM + [0] * space_for_stack + return memory + +memory = load_memory() +program_counter = 0 # points to the current instruction we need to execute next +running = True +registers = [0] * 8 +stack_pointer_register = 7 # register number that contains the address of the stack pointer +registers[stack_pointer_register] = len(memory) - 1 + + +#keep loopiing 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 == HALT: + running = False + program_counter += 1 + + elif command_to_execute == SAVE: + value_to_save = memory[program_counter + 1] + register_saving_to = memory[program_counter + 2] + registers[register_saving_to] = 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: + # 2 registers + register_a = memory[program_counter + 1] + register_b = memory[program_counter + 2] + + # 2 values + register_a_value = registers[register_a] + register_b_value = registers[register_b] + + registers[register_a] = register_a_value + register_b_value + program_counter += 3 + + 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_top_pop_value_in = memory[program_counter + 1] + registers[register_top_pop_value_in] = memory[registers[stack_pointer_register]] + + registers[stack_pointer_register] += 1 + + program_counter += 2 + + elif command_to_execute == CALL: + # it stores the address of the next instruction on top of the stack + registers[stack_pointer_register] -= 1 + address_of_next_instruction = program_counter + 2 + memory[registers[stack_pointer_register]] = address_of_next_instruction + + # it then jumps to the address stored in that register + register_to_get_address_from = memory[program_counter + 1] + program_counter = registers[register_to_get_address_from] + + elif command_to_execute == RET: + # doesn't take in any operands, sets the program counter to the topmost element of the stack and pops it + program_counter = memory[registers[stack_pointer_register]] + registers[stack_pointer_register] += 1 + + + elif command_to_execute == PRINT_SUBROUTINE_INSTRUCTION: + print("Hi I am in a subroutine!") + program_counter += 1 + else: + print(f"error: Uknown instruction {command_to_execute}") + sys.exit(1) + +print(f"Registers: {registers}") +print(f"Memory: {memory}") \ No newline at end of file diff --git a/lecture day one/lecture.py b/Lectures/lecture day one/lecture.py similarity index 100% rename from lecture day one/lecture.py rename to Lectures/lecture day one/lecture.py diff --git a/ls8/examples/cpu.py b/ls8/examples/cpu.py index 7d2f9ff0a..c18910762 100644 --- a/ls8/examples/cpu.py +++ b/ls8/examples/cpu.py @@ -19,6 +19,13 @@ MUL = 0b10100010 PUSH = 0b01000101 POP = 0b01000110 +CALL = 0b01010000 +RET = 0b00010001 +ADD = 0b10100000 +CMP = 0b10100111 +JMP = 0b01010100 +JNE = 0b01010110 +JEQ = 0b01010101 class CPU: @@ -32,6 +39,8 @@ def __init__(self): self.pc = 0 self.halted = False self.stack_point_register = 7 + self.flags = [0] * 8 + self.flags[-1] = 0 def decimal_to_binary(self,x): return int(bin(x)[:2]) @@ -108,7 +117,6 @@ def run(self): operand_b = self.ram_read(self.pc + 2) self.execute_instruction(command_to_execute, operand_a, operand_b) - print(self.ram) def execute_instruction(self, instruction, operand_a, operand_b): if instruction == HLT: self.halted = True @@ -131,6 +139,10 @@ def execute_instruction(self, instruction, operand_a, operand_b): self.pc += 2 + elif instruction == ADD: + self.registers[operand_a] += self.registers[operand_b] + self.pc += 3 + elif instruction == POP: register_to_pop_value_in = self.ram[self.pc + 1] self.registers[register_to_pop_value_in] = self.ram[self.registers[self.stack_point_register]] @@ -138,15 +150,45 @@ def execute_instruction(self, instruction, operand_a, operand_b): self.registers[self.stack_point_register] += 1 self.pc += 2 + + elif instruction == CALL: + self.registers[self.stack_point_register] -= 1 + address_of_next_instruction = self.pc + 2 + self.ram[self.registers[self.stack_point_register]] = address_of_next_instruction - else: - print("ERROR") + register_to_get_address_from = self.ram[self.pc + 1] + self.pc = self.registers[register_to_get_address_from] + elif instruction == RET: + self.pc = self.ram[self.registers[self.stack_point_register]] + self.registers[self.stack_point_register] += 1 + elif instruction == CMP: + if self.registers[operand_a] == self.registers[operand_b]: + # set the equal flag to 1 + self.flags[-1] = 1 + else: + self.flags[-1] = 0 + self.pc += 3 + + elif instruction == JMP: + self.pc = self.registers[operand_a] + elif instruction == JEQ: + if self.flags[-1] == 1: + self.pc = self.registers[operand_a] + else: + self.pc += 2 + elif instruction == JNE: + if self.flags[-1] == 0: + self.pc = self.registers[operand_a] + else: + self.pc += 2 + else: + print("ERROR") # # LDI instruction diff --git a/ls8/examples/ls8.py b/ls8/examples/ls8.py index 6fcfc0fe9..cd8561e7e 100755 --- a/ls8/examples/ls8.py +++ b/ls8/examples/ls8.py @@ -18,7 +18,7 @@ cpu = CPU() # file_name_from_command_line = sys.argv[1] -file_name_from_command_line = 'stack.ls8' +file_name_from_command_line = 'sctest.ls8' print(file_name_from_command_line) diff --git a/ls8/examples/sctest.ls8 b/ls8/examples/sctest.ls8 index 7853b76a4..8f86bba7e 100644 --- a/ls8/examples/sctest.ls8 +++ b/ls8/examples/sctest.ls8 @@ -1,3 +1,10 @@ +# Code to test the Sprint Challenge +# +# Expected output: +# 1 +# 4 +# 5 + 10000010 # LDI R0,10 00000000 00001010 diff --git a/sctest.asm b/sctest.asm new file mode 100644 index 000000000..5da48db6b --- /dev/null +++ b/sctest.asm @@ -0,0 +1,52 @@ +; 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 + +Test1: + +LDI R2,Test2 +CMP R0,R1 +JNE R2 ; Jumps because R0 != R1 +LDI R3,2 +PRN R3 ; Skipped--does not print + +Test2: + +LDI R1,10 +LDI R2,Test3 +CMP R0,R1 +JEQ R2 ; Jumps becuase R0 == R1 +LDI R3,3 +PRN R3 ; Skipped--does not print + +Test3: + +LDI R2,Test4 +CMP R0,R1 +JNE R2 ; Does not jump because R0 == R1 +LDI R3,4 +PRN R3 ; Prints 4 + +Test4: + +LDI R3,5 +PRN R3 ; Prints 5 +LDI R2,Test5 +JMP R2 ; Jumps unconditionally +PRN R3 ; Skipped-does not print + +Test5: + +HLT +