diff --git a/Lectures/LectureDayThree/lecture.py b/Lectures/LectureDayThree/lecture.py new file mode 100644 index 000000000..2360e00f4 --- /dev/null +++ b/Lectures/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/Lectures/LecturedayTwo/lecture.py b/Lectures/LecturedayTwo/lecture.py new file mode 100644 index 000000000..3cd06fa37 --- /dev/null +++ b/Lectures/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/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/Lectures/lecture day one/lecture.py b/Lectures/lecture day one/lecture.py new file mode 100644 index 000000000..fefac20da --- /dev/null +++ b/Lectures/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 deleted file mode 100644 index 9a307496e..000000000 --- a/ls8/cpu.py +++ /dev/null @@ -1,65 +0,0 @@ -"""CPU functionality.""" - -import sys - -class CPU: - """Main CPU class.""" - - def __init__(self): - """Construct a new CPU.""" - pass - - def load(self): - """Load a program into memory.""" - - address = 0 - - # 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 - - - 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.""" - pass diff --git a/ls8/examples/cpu.py b/ls8/examples/cpu.py new file mode 100644 index 000000000..c18910762 --- /dev/null +++ b/ls8/examples/cpu.py @@ -0,0 +1,217 @@ +"""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 = 0b00000001 +LDI = 0b10000010 +PRN = 0b01000111 +MUL = 0b10100010 +PUSH = 0b01000101 +POP = 0b01000110 +CALL = 0b01010000 +RET = 0b00010001 +ADD = 0b10100000 +CMP = 0b10100111 +JMP = 0b01010100 +JNE = 0b01010110 +JEQ = 0b01010101 + + +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 + self.stack_point_register = 7 + self.flags = [0] * 8 + self.flags[-1] = 0 + + def decimal_to_binary(self,x): + return int(bin(x)[:2]) + + def load(self, file_name): + """Load a program into memory.""" + current = 0 + temp = [] + 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 + temp.append(x) + current += 1 + except: + 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] + + 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.""" + + self.registers[self.stack_point_register] = len(self.ram) - 1 + + 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 + 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 == 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]] + + 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 + + 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 + # 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") + + 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..cd8561e7e --- /dev/null +++ b/ls8/examples/ls8.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +"""Main.""" + +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 = 'sctest.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/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/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 new file mode 100644 index 000000000..485328287 --- /dev/null +++ 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") + + 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 +