From db0c335ea2869b3a65515fbba7cd75570c33cb84 Mon Sep 17 00:00:00 2001 From: bsherwood9 <36565536+bsherwood9@users.noreply.github.com> Date: Wed, 2 Dec 2020 20:24:16 -0700 Subject: [PATCH 1/5] after a lot of trial and error, got mvp. --- class_example.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ ls8/cpu.py | 54 +++++++++++++++++++++++++++------ 2 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 class_example.py diff --git a/class_example.py b/class_example.py new file mode 100644 index 000000000..70bb85e20 --- /dev/null +++ b/class_example.py @@ -0,0 +1,77 @@ +PRINT_TIM = 0b00000001 +HALT = 0b00000010 +PRINT_NUM = 0b00000011 # a 2-byte command, takes 1 argument +SAVE = 0b00000100 # a 3-byte command, takes 2 arguments +PRINT_REG = 0b00000101 +PRINT_SUM = 0b00000110 +​ +​ +# a data-driven machine +# function call +# a "variable" == registers for our programs to save things into +​ +​ +# RAM +memory = [ + PRINT_TIM, + PRINT_TIM, + PRINT_NUM, # print 99 or some other number + 42, + SAVE, # save 99 into register 2 # <-- PC + 99, # the number to save + 2, # the register to put it into + PRINT_REG, + 2, + PRINT_SUM, # R1 + R2 + HALT, +] +​ +​ +# registers, R0-R7 +registers = [0] * 8 +​ +running = True +​ +# program counter +pc = 0 +​ +while running: + command = memory[pc] +​ +​ +if command == PRINT_TIM: + print('tim!') +​ +elif command == PRINT_NUM: + num_to_print = memory[pc + 1] # we already incremented PC! + print(num_to_print) +​ +pc += 1 # but increment again +​ +​ +elif command == SAVE: + num_to_save = memory[pc + 1] + register_address = memory[pc + 2] +​ +registers[register_address] = num_to_save +​ +# shorter: +# registers[memory + 2] = memory[pc + 1] +​ +pc += 2 +​ +elif command == PRINT_REG: + reg_address = memory[pc + 1] +​ +saved_number = registers[reg_address] +​ +print(saved_number) +​ +# print(registers[memory[pc + 1]]) +​ +​ +elif command == HALT: + running = False +​ +​ +pc += 1 # so we don't get sucked into an infinite loop! diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..40890f388 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -2,12 +2,16 @@ import sys + 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 = False def load(self): """Load a program into memory.""" @@ -18,25 +22,27 @@ def load(self): program = [ # From print8.ls8 - 0b10000010, # LDI R0,8 + 0b10000010, # LDI R0,8 0b00000000, 0b00001000, - 0b01000111, # PRN R0 + 0b01000111, # PRN R0 0b00000000, - 0b00000001, # HLT + 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 + self.pc += 2 + elif op == "SUB": + self.reg[reg_a] -= self.reg[reg_b] + self.pc += 2 else: raise Exception("Unsupported ALU operation") @@ -48,8 +54,8 @@ def trace(self): print(f"TRACE: %02X | %02X %02X %02X |" % ( self.pc, - #self.fl, - #self.ie, + # self.fl, + # self.ie, self.ram_read(self.pc), self.ram_read(self.pc + 1), self.ram_read(self.pc + 2) @@ -61,5 +67,35 @@ def trace(self): print() def run(self): + ldi = 0b10000010 + prn = 0b01000111 + hlt = 0b00000001 """Run the CPU.""" - pass + self.running = True + # IR = {} + # IR[self.pc] = self.reg[self.pc] + + while self.running: + instruction = self.ram_read(self.pc) + operand_a = self.ram_read(self.pc+1) + operand_b = self.ram_read(self.pc+2) + if instruction == ldi: + self.reg[operand_a] = operand_b + self.pc += 3 + print("first loop") + elif instruction == prn: + print(self.reg[operand_a]) + self.pc += 2 + elif instruction == hlt: + print("halt, who goes there?") + self.running = False + else: + print("Could not find that particular instruction.{a}.".format( + a=instruction)) + return + + def ram_read(self, mar): + return self.ram[mar] + + def ram_write(self, mar, mdr): + self.ram[mar] = mdr From 81d90c98cd092135d10de48441e411e5792545df Mon Sep 17 00:00:00 2001 From: bsherwood9 <36565536+bsherwood9@users.noreply.github.com> Date: Sun, 6 Dec 2020 20:21:07 -0700 Subject: [PATCH 2/5] added class notes and finished day 2. --- class_example.py | 69 +++++++++++++++++++++++++++++- class_example2.py | 106 ++++++++++++++++++++++++++++++++++++++++++++++ ls8/cpu.py | 67 ++++++++++++++++++++--------- 3 files changed, 220 insertions(+), 22 deletions(-) create mode 100644 class_example2.py diff --git a/class_example.py b/class_example.py index 70bb85e20..92fd33e9d 100644 --- a/class_example.py +++ b/class_example.py @@ -73,5 +73,72 @@ elif command == HALT: running = False ​ -​ +​number pc += 1 # so we don't get sucked into an infinite loop! + +# masking +# >> and use & with ob1 to essentially delete any higher bits +ob1010 +& ob0000 +------ + +0b1010 +& 0b0011 zeros where you don't care, ones where you do +------ +0b0010 + +shift to the right, then masking +v + +10100000 >> 5 +101 +00000101 + +00000101 +&00000001 +-------- +00000001 + + +# LOADING STUFF +# file i/o in python +try: + if len(sys.argv) < 2: + print(f'error from {sys.argv[0]}: {sys.argv[1]} not found') + sys.exit(1) + + # add a counter that loads memory at that index + ram_index = 0 + + with open(file_name, sys.argv[1]) as f: + for line in f: + print(line.split("#")[0]) + print(split_line.strip()) + # how to only get the numbers + if stripped_split_line != "": + print(stripped_split_line) + command = int(stripped_split_line, 2) + # loead command into memory + memory[ram_index] = command + ram_index += 1 + +except FileNotFoundError: + print(f"could not find that file {sys.argv[1]}") + +file = open("print8.ls8", 'r') +lines = file.read() + +print(lines) +# make sure you close files +file.close() + +# read in filename from command line + +memory = [0] * 256 + + +elif command = ADD: + reg1_address = memory[pc + 1] + reg2_address = memory[pc + 2] + + registers[reg1_address] += registers[reg2_address] diff --git a/class_example2.py b/class_example2.py new file mode 100644 index 000000000..3d311c3d2 --- /dev/null +++ b/class_example2.py @@ -0,0 +1,106 @@ +import sys +​ +PRINT_TIM = 0b00000001 +HALT = 0b00000010 +PRINT_NUM = 0b01000011 # a 2-byte command, takes 1 argument +SAVE = 0b10000100 # a 3-byte command, takes 2 arguments +PRINT_REG = 0b01000101 +ADD = 0b10100110 +​ +​ +# a data-driven machine +# function call +# a "variable" == registers for our programs to save things into +​ +​ +# RAM +memory = [0] * 256 +​ +# registers, R0-R7 +registers = [0] * 8 +​ +running = True +​ +# program counter +pc = 0 +​ + + +def load_ram(): + try: + if len(sys.argv) < 2: + print(f'Error from {sys.argv[0]}: missing filename argument') + print(f'Usage: python3 {sys.argv[0]} ') + sys.exit(1) + + +​ +​ +# add a counter that adds to memory at that index +ram_index = 0 +​ +with open(sys.argv[1]) as f: + for line in f: + split_line = line.split("#")[0] + stripped_split_line = split_line.strip() +​ +if stripped_split_line != "": + command = int(stripped_split_line, 2) + + # load command into memory + memory[ram_index] = command +​ +ram_index += 1 +​ +except FileNotFoundError: + print(f'Error from {sys.argv[0]}: {sys.argv[1]} not found') + print("(Did you double check the file name?)") +​ +load_ram() +​ +while running: + command = memory[pc] +​ +​ +if command == PRINT_TIM: + print('tim!') +​ +elif command == PRINT_NUM: + num_to_print = memory[pc + 1] # we already incremented PC! + print(num_to_print) +​ +# pc += 1 # but increment again +​ +​ +elif command == SAVE: + num_to_save = memory[pc + 1] + register_address = memory[pc + 2] +​ +registers[register_address] = num_to_save +​ +# shorter: +# registers[memory + 2] = memory[pc + 1] +​ +# pc += 2 +​ +elif command == PRINT_REG: + reg_address = memory[pc + 1] +​ +saved_number = registers[reg_address] +​ +print(saved_number) +​ +# print(registers[memory[pc + 1]]) +​ +elif command == ADD: + reg1_address = memory[pc + 1] + reg2_address = memory[pc + 2] +​ +registers[reg1_address] += registers[reg2_address] +​ +elif command == HALT: + running = False +​ +number_of_operands = command >> 6 +pc += (1 + number_of_operands) +# pc += 1 # so we don't get sucked into an infinite loop! diff --git a/ls8/cpu.py b/ls8/cpu.py index 40890f388..53a1c8dbc 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -19,20 +19,37 @@ def load(self): 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 + try: + if len(sys.argv) < 2: + print(f'Error from {sys.argv[0]}): missing file name argument') + sys.exit(1) + + with open(sys.argv[1]) as f: + for line in f: + split_line = line.split("#")[0] + stripped_line = split_line.strip() + # print(int(stripped_line, 2)) + if stripped_line != "": + command = int(stripped_line, 2) + print(command) + self.ram[address] = command + address += 1 + except FileNotFoundError: + print(f'Error from {sys.argv[0]}: {sys.argv[1]} not found') + print("(Did you double check the file name?)") + # 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.""" @@ -43,6 +60,11 @@ def alu(self, op, reg_a, reg_b): elif op == "SUB": self.reg[reg_a] -= self.reg[reg_b] self.pc += 2 + elif op == 'MUL': + print("multiply") + result = self.reg[reg_a] * self.reg[reg_b] + self.pc += 2 + return result else: raise Exception("Unsupported ALU operation") @@ -67,9 +89,10 @@ def trace(self): print() def run(self): - ldi = 0b10000010 - prn = 0b01000111 - hlt = 0b00000001 + ldi = 130 + prn = 71 + mul = 162 + hlt = 1 """Run the CPU.""" self.running = True # IR = {} @@ -84,14 +107,16 @@ def run(self): self.pc += 3 print("first loop") elif instruction == prn: - print(self.reg[operand_a]) + print("Printing", self.reg[operand_a]) self.pc += 2 elif instruction == hlt: - print("halt, who goes there?") + print("Halt") self.running = False + elif instruction == mul: + print("alu", self.alu("MUL", operand_a, operand_b)) else: - print("Could not find that particular instruction.{a}.".format( - a=instruction)) + print( + f'Could not find that particular instruction.{instruction}') return def ram_read(self, mar): From e7d22b779640e7381f72298a8f926d445c67633f Mon Sep 17 00:00:00 2001 From: bsherwood9 <36565536+bsherwood9@users.noreply.github.com> Date: Tue, 8 Dec 2020 22:28:00 -0700 Subject: [PATCH 3/5] this was a bit confusing, got some of it. Will work on it tomorrow. --- ls8/README.md | 21 ++++++++++ ls8/cpu.py | 91 +++++++++++++++++++++++++++++++---------- ls8/examples/print8.ls8 | 2 + ls8/test.py | 29 +++++++++++++ 4 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 ls8/test.py diff --git a/ls8/README.md b/ls8/README.md index d9170d968..e86aaf318 100644 --- a/ls8/README.md +++ b/ls8/README.md @@ -60,8 +60,12 @@ but you'll have to implement those three above instructions first! ## Step 0: IMPORTANT: inventory what is here! * Make a list of files here. + We have a ls8 file and a cpu file. * Write a short 3-10-word description of what each file does. + The cpu file is setting up a cpu class with methods. + The ls8 file calls the class and runs the Run method on the cpu class. * Note what has been implemented, and what hasn't. + Alu and trace have some work done, but looks like the rest need built out≥ * Read this whole file. * Skim the spec. @@ -478,3 +482,20 @@ Doing this correctly requires implementing `CMP`, and some comparative forms of Hint: Look in the `asm/` directory and learn how to use the `asm.js` assembler. This way you can write your code in assembly language and use the assembler to build it to machine code and then run it on your emulator. + + +What we have built: +1. Ram - self.ram +2. registers +3. CPU - self.run() +4. ALU +5. Why ls8? - All instructions are 8 bits. + Also, 8-bit CPU and ALU architectures are those that are based on registers, address buses, and data buses of that size. + + Address bus is the 8 wires running from cpu to ram + With 8 bits, the cpu can address 256 bytes of ram + To have more ram you need more wires. + + General calculating machines, vs specialized calculating machines. + "computer" "calculator" + \ No newline at end of file diff --git a/ls8/cpu.py b/ls8/cpu.py index 53a1c8dbc..bd1bf854a 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -11,7 +11,16 @@ def __init__(self): self.ram = [0] * 256 self.reg = [0] * 8 self.pc = 0 + self.reg[7] = 0xf4 self.running = False + self.branchTable = { + 130: self.ldi, + 71: self.prn, + 162: self.mult, + 1: self.halt, + 69: self.pushy, + 70: self.poppy + } def load(self): """Load a program into memory.""" @@ -88,36 +97,76 @@ def trace(self): print() + def ldi(self, op_a, op_b): + self.reg[op_a] = op_b + self.pc += 3 + + def prn(self, op_a, op_b): + print("Printing", self.reg[op_a]) + self.pc += 2 + + def halt(self, op_a, op_b): + print("Halt") + self.running = False + + def mult(self, op_a, op_b): + print("alu", self.alu("MUL", op_a, op_b)) + + def pushy(self, op_a, op_b): + self.reg[7] -= 1 + register_address = self.ram[self.pc + 1] + value = self.reg[register_address] + self.ram[self.reg[7]] = value + self.pc += 2 + + def poppy(self, op_a, op_b): + value = self.ram[self.reg[7]] + register_address = self.ram[self.pc + 1] + self.reg[register_address] = value + self.reg[7] += 1 + self.pc += 2 + def run(self): - ldi = 130 - prn = 71 - mul = 162 - hlt = 1 - """Run the CPU.""" self.running = True - # IR = {} - # IR[self.pc] = self.reg[self.pc] while self.running: instruction = self.ram_read(self.pc) operand_a = self.ram_read(self.pc+1) operand_b = self.ram_read(self.pc+2) - if instruction == ldi: - self.reg[operand_a] = operand_b - self.pc += 3 - print("first loop") - elif instruction == prn: - print("Printing", self.reg[operand_a]) - self.pc += 2 - elif instruction == hlt: - print("Halt") - self.running = False - elif instruction == mul: - print("alu", self.alu("MUL", operand_a, operand_b)) - else: + try: + self.branchTable[instruction](operand_a, operand_b) + + except Exception: print( f'Could not find that particular instruction.{instruction}') - return + + # def run(self): + # ldi = 130 + # prn = 71 + # mul = 162 + # hlt = 1 + # """Run the CPU.""" + # self.running = True + + # while self.running: + # instruction = self.ram_read(self.pc) + # operand_a = self.ram_read(self.pc+1) + # operand_b = self.ram_read(self.pc+2) + # if instruction == ldi: + # self.reg[operand_a] = operand_b + # self.pc += 3 + # print("first loop") + # elif instruction == prn: + # print("Printing", self.reg[operand_a]) + # self.pc += 2 + # elif instruction == hlt: + # print("Halt") + # self.running = False + # elif instruction == mul: + # print("alu", self.alu("MUL", operand_a, operand_b)) + # else: + # print( + # f'Could not find that particular instruction.{instruction}') def ram_read(self, mar): return self.ram[mar] diff --git a/ls8/examples/print8.ls8 b/ls8/examples/print8.ls8 index e3b3457cf..d6aa4528b 100644 --- a/ls8/examples/print8.ls8 +++ b/ls8/examples/print8.ls8 @@ -9,3 +9,5 @@ 01000111 # PRN R0 00000000 00000001 # HLT + + diff --git a/ls8/test.py b/ls8/test.py new file mode 100644 index 000000000..d12afeea8 --- /dev/null +++ b/ls8/test.py @@ -0,0 +1,29 @@ +OP1 = 0b10101010 +OP2 = 0b11110000 + + +class Foo: + + def __init__(self): + # Set up the branch table + self.branchtable = {} + self.branchtable[OP1] = self.handle_op1 + self.branchtable[OP2] = self.handle_op2 + + def handle_op1(self, a): + print("op 1: " + a) + + def handle_op2(self, a): + print("op 2: " + a) + + def run(self): + # Example calls into the branch table + ir = OP1 + self.branchtable[ir]("foo") + + ir = OP2 + self.branchtable[ir]("bar") + + +c = Foo() +c.run() From 157b845a07f856adb532591270166eb3367e922f Mon Sep 17 00:00:00 2001 From: bsherwood9 <36565536+bsherwood9@users.noreply.github.com> Date: Thu, 10 Dec 2020 20:12:27 -0700 Subject: [PATCH 4/5] Followed the class lectures and got the answer. --- class3.py | 124 +++++++++++++++++++++++++++++++++++++++++++ class_example2.py | 88 +++++++++++++++++++++++++++++- ls8/cpu.py | 57 ++++++++++++++------ ls8/our_program2.ls8 | 0 4 files changed, 252 insertions(+), 17 deletions(-) create mode 100644 class3.py create mode 100644 ls8/our_program2.ls8 diff --git a/class3.py b/class3.py new file mode 100644 index 000000000..66c9fba22 --- /dev/null +++ b/class3.py @@ -0,0 +1,124 @@ + +Computer arch topics we have implemented in our project +- RAM, self.ram +- registers! +- CPU, self.run +- ALU +Why LS8? +- 8 bits +- not the registers, as you might think +- Also, 8-bit CPU and ALU architectures are those that are based on registers, +address buses, or data buses of that size + CPU + 00000000 + 00000000 + 00000000 + 00000000 + RAM +- with 8-bit address bus, the CPU can address 256 bytes of RAM +General purpose calculating machine vs specialized calculating machines + "computer" "calculator" + Can do anything hardwired for specific calculations + Broadly applicable Faster (often) +More memory? Stack! +- more variables +- function calls and nested function calls +To make a stack? +- Push +- Pop +- Memory space +-- RAM +-- 0-255 (256 bytes) +- a pointer to track where the top of the stack +-- variable that is a memory address +how to push +how to Pop +Handling 'leftovers' from push +Stack underflow +Why doesn't the CPU prevent underflow, or prevent wrapping around in memory? +- don't want the CPU to spend time/energy checking +- used to be dev's job, now it's the compiler's job +Stack overflow +- software's job to prevent this +Stacks and nested function calls +self.ram = [0] * 256 +registers[7] = F3 +SP = F3 +memory[SP] +FF: 00 +FE: 00 +FD: 00 +FC: 00 +FB: 00 +FA: 00 +F9: 00 +F8: 00 +F7: 00 +F6: 00 +F5: 00 +F4: 00 +F3: 42 <--- SP +F2: 42 +F1: 42 +F0: 00 +EF: 00 +EE: 00 +ED: 00 +EC: 00 +. +. +. +2B: 42 +2A: 42 +. +. +. +10: 42 +9: 42 +8: 42 +7: JUMP +6: R3 +5: PUSH +4: R3 +3: 42 +2: SAVE +1: PRINT_TIM +0: PRINT_TIM +R0: 99 +R1: 42 +R3: 42 +PUSH R0: +- decrement the SP +- copy the value from the given register +PUSH R1: +- decrement the SP +- copy the value from the given register +POP R3: +- copy into the register +- increment SP +PUSH R0: +- decrement the SP +- copy the value from the given register +POP R3: +- copy into the register +- increment SP +Stack +700: 4 +699: 2 +698: 3 +697: 6 +696: 6 +695: 7 <-- SP +694: 3 +693: 6 +registers[4] = 6 +a = 4 +def mult(x, y): + z = x * y + return z +def main(): + a = 2 + b = 3 + c = a * b + d = mult(a, b) + e = 7 diff --git a/class_example2.py b/class_example2.py index 3d311c3d2..6462cc7c6 100644 --- a/class_example2.py +++ b/class_example2.py @@ -6,6 +6,8 @@ SAVE = 0b10000100 # a 3-byte command, takes 2 arguments PRINT_REG = 0b01000101 ADD = 0b10100110 +PUSH = 0b0100111 +POP = 0b01001000 ​ ​ # a data-driven machine @@ -18,7 +20,8 @@ ​ # registers, R0-R7 registers = [0] * 8 -​ +registers[7] += 0xF4​ running = True ​ # program counter @@ -100,7 +103,90 @@ def load_ram(): ​ elif command == HALT: running = False + +elif command == PUSH +# decrement the stack pointer +# at address f4 +# can just do arithmetic, F4 - 1 +# R7 is our sp, has value f4 +registers[7] -= 1 + +# copy value from given register into address pointed to by SP +# value from register +register_address = memory[pc+1] +value = registers[register_address] + +# copy into sp address +# copy this value into memory, +# put it where stack pointer wants us to put it. +SP = register[7] +memory[SP] = value + +elif command = "POP": + # copy value from address pointed to sp to the given register + # get stack pointer and get value from memory at sp address + SP = registers[7] + value = memory[SP] + + # get register address + # aka where should we put this value from ram + register_address = memory[pc+1] + + # put value in that register + register[register_address] = value + + # increment the stack pointer + registers[7] += 1 + + ​ number_of_operands = command >> 6 pc += (1 + number_of_operands) # pc += 1 # so we don't get sucked into an infinite loop! + + +# 01000111 +# 00000010 #from r2 + + +# making call and return + +CALL = 0b01001001 +RET = 0b00001010 + + +def call(self): + # step 1:push the return address onto the stack + # find the address/index of the command AFTER Call + next_command_address = pc + 2 + + # push the address onto the stack + # decrement the stack pointer + reg[7] -= 1 + # put the next command address at the location in memory where the stack pointer points + SP = reg[7] + memory[SP] = next_command_address + + # step 2, jump, set the PC to wherever the registeer says + # find the number of the register to look at + register_num_jump = memory[pc+1] + + # get address of the subroutine out fo that register + address_to_jump_to = registers[register_num_jump] + + # set the pc + pc = address_to_jump_to + + elif command == RET: + # pop the value from the top of the stack and store it in the pc + + # pop from the top of the stack + # get the value first + SP = registers[7] + return_address = memory[SP] + + # then move the stack pointer up + registers[7] += 1 + + # step 2, jump back, set the pc to this value + pc = return_address diff --git a/ls8/cpu.py b/ls8/cpu.py index bd1bf854a..733dedc35 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -17,9 +17,12 @@ def __init__(self): 130: self.ldi, 71: self.prn, 162: self.mult, + 160: self.add, 1: self.halt, 69: self.pushy, - 70: self.poppy + 70: self.poppy, + 80: self.cal, + 17: self.retrn } def load(self): @@ -60,12 +63,14 @@ def load(self): # self.ram[address] = instruction # address += 1 - def alu(self, op, reg_a, reg_b): + def alu(self, op): """ALU operations.""" - + reg_a = self.ram_read(self.pc+1) + reg_b = self.ram_read(self.pc+2) if op == "ADD": self.reg[reg_a] += self.reg[reg_b] - self.pc += 2 + self.pc += 3 + elif op == "SUB": self.reg[reg_a] -= self.reg[reg_b] self.pc += 2 @@ -97,48 +102,68 @@ def trace(self): print() - def ldi(self, op_a, op_b): - self.reg[op_a] = op_b + def ldi(self): + self.reg[self.ram[self.pc+1]] = self.ram[self.pc+2] self.pc += 3 - def prn(self, op_a, op_b): - print("Printing", self.reg[op_a]) + def prn(self): + print("Printing", self.reg[self.ram[self.pc+1]]) self.pc += 2 - def halt(self, op_a, op_b): + def halt(self): print("Halt") self.running = False - def mult(self, op_a, op_b): - print("alu", self.alu("MUL", op_a, op_b)) + def mult(self): + print("alu", self.alu("MUL")) + + def add(self): + print("alu add", self.alu("ADD")) - def pushy(self, op_a, op_b): + def pushy(self): self.reg[7] -= 1 register_address = self.ram[self.pc + 1] value = self.reg[register_address] self.ram[self.reg[7]] = value self.pc += 2 - def poppy(self, op_a, op_b): + def poppy(self): value = self.ram[self.reg[7]] register_address = self.ram[self.pc + 1] self.reg[register_address] = value self.reg[7] += 1 self.pc += 2 + def cal(self): + next_command_address = self.pc + 2 + self.reg[7] -= 1 + SP = self.reg[7] + self.ram[SP] = next_command_address + register_num_jump = self.ram[self.pc + 1] + address_to_jump_to = self.reg[register_num_jump] + self.pc = address_to_jump_to + + def retrn(self): + SP = self.reg[7] + return_address = self.ram[SP] + self.reg[7] += 1 + self.pc = return_address + def run(self): self.running = True while self.running: instruction = self.ram_read(self.pc) - operand_a = self.ram_read(self.pc+1) - operand_b = self.ram_read(self.pc+2) + # print(instruction, "instruction") + # operand_a = self.ram_read(self.pc+1) + # operand_b = self.ram_read(self.pc+2) try: - self.branchTable[instruction](operand_a, operand_b) + self.branchTable[instruction]() except Exception: print( f'Could not find that particular instruction.{instruction}') + self.running = False # def run(self): # ldi = 130 diff --git a/ls8/our_program2.ls8 b/ls8/our_program2.ls8 new file mode 100644 index 000000000..e69de29bb From 15321599d27567de2f5fd08b6b744e724df5f74c Mon Sep 17 00:00:00 2001 From: bsherwood9 <36565536+bsherwood9@users.noreply.github.com> Date: Sun, 13 Dec 2020 20:48:40 -0700 Subject: [PATCH 5/5] met mvp --- ls8/cpu.py | 60 +++++++++++++++++++++++++++++++++++++++++--- ls8/our_program2.ls8 | 10 ++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 733dedc35..df5e3e3e9 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -11,6 +11,7 @@ def __init__(self): self.ram = [0] * 256 self.reg = [0] * 8 self.pc = 0 + self.flag = 0b00000000 self.reg[7] = 0xf4 self.running = False self.branchTable = { @@ -19,10 +20,14 @@ def __init__(self): 162: self.mult, 160: self.add, 1: self.halt, + 85: self.jeq_run, + 86: self.jne_run, 69: self.pushy, 70: self.poppy, 80: self.cal, - 17: self.retrn + 17: self.retrn, + 84: self.jump, + 167: self.cmp_run } def load(self): @@ -37,14 +42,17 @@ def load(self): sys.exit(1) with open(sys.argv[1]) as f: + code_line = 0 for line in f: split_line = line.split("#")[0] stripped_line = split_line.strip() # print(int(stripped_line, 2)) if stripped_line != "": command = int(stripped_line, 2) - print(command) + # print(command, code_line) + self.ram[address] = command + code_line += 1 address += 1 except FileNotFoundError: print(f'Error from {sys.argv[0]}: {sys.argv[1]} not found') @@ -75,10 +83,22 @@ def alu(self, op): self.reg[reg_a] -= self.reg[reg_b] self.pc += 2 elif op == 'MUL': - print("multiply") + # print("multiply") result = self.reg[reg_a] * self.reg[reg_b] self.pc += 2 return result + elif op == "CMP": + # print("reg_a vs reg_b", reg_a, reg_b) + if self.reg[reg_a] < self.reg[reg_b]: + # print("less than") + self.flag = 0b00000100 + if self.reg[reg_a] > self.reg[reg_b]: + # print("greater than") + self.flag = 0b00000010 + if self.reg[reg_a] == self.reg[reg_b]: + # print("equal") + self.flag = 0b00000001 + self.pc += 3 else: raise Exception("Unsupported ALU operation") @@ -111,7 +131,7 @@ def prn(self): self.pc += 2 def halt(self): - print("Halt") + # print("Halt") self.running = False def mult(self): @@ -149,6 +169,37 @@ def retrn(self): self.reg[7] += 1 self.pc = return_address + def cmp_run(self): + print("alu cmp", self.alu("CMP")) + + def jeq_run(self): + if self.flag == 1: + # print("it is true") + address = self.ram[self.pc + 1] + jump_address = self.reg[address] + self.pc = jump_address + else: + self.pc += 2 + + def jne_run(self): + # print("JNE") + if self.flag == 4 or self.flag == 2: + # print("jne true") + address = self.ram[self.pc + 1] + # print(address) + jump_address = self.reg[address] + # print("jump address", jump_address) + self.pc = jump_address + else: + self.pc += 2 + + def jump(self): + # print("JUMP") + given_address = self.ram[self.pc + 1] + address_to_jump_to = self.reg[given_address] + # print(address_to_jump_to) + self.pc = address_to_jump_to + def run(self): self.running = True @@ -164,6 +215,7 @@ def run(self): print( f'Could not find that particular instruction.{instruction}') self.running = False + break # def run(self): # ldi = 130 diff --git a/ls8/our_program2.ls8 b/ls8/our_program2.ls8 index e69de29bb..9e0cd18b1 100644 --- a/ls8/our_program2.ls8 +++ b/ls8/our_program2.ls8 @@ -0,0 +1,10 @@ +PRINT_NUM +42 + +CALL + +HALT + +PRINT_NUM +99 +RET \ No newline at end of file