From af98582416c2bda37a467ce61f4cb56904405af6 Mon Sep 17 00:00:00 2001 From: rfamilara Date: Wed, 2 Dec 2020 22:02:27 -0600 Subject: [PATCH 1/4] Day 1 - Get print8.ls8 running -Perform Inventory -Create CPU instructor -Add RAM functions ram_read() and ram_write() -Implement run() -Create HLT instruction handler -Add LDI Instruction -Add PRN instruction --- ls8/cpu.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index 9a307496e..cc9b888aa 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,13 +1,31 @@ """CPU functionality.""" import sys +SP = 7 +LDI = 0b10000010 +PRN = 0b01000111 +HLT = 0b00000001 +MUL = 0b10100010 +PUSH = 0b01000101 +POP = 0b01000110 class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - pass + + self.ram = [0] * 256 + self.registers = [0] * 8 # R0-R7 + self.registers[SP] = 0xF4 # stack pointer + self.pc = 0 # Program Counter, address of the currently-executing instuction + + + def ram_read(self, address): + return self.ram[address] + + def ram_write(self, value, address): + self.ram[address] = value def load(self): """Load a program into memory.""" @@ -62,4 +80,19 @@ def trace(self): def run(self): """Run the CPU.""" - pass + + self.running = True + while self.running: + ir = self.ram_read(self.pc) # Instruction register + operand_a = self.ram_read(self.pc + 1) + operand_b = self.ram_read(self.pc + 2) + + if ir == HLT: # HLT + self.running = False + self.pc += 1 + elif ir == PRN: + print(self.registers[operand_a]) + self.pc += 2 + elif ir == LDI: + self.registers[operand_a] = operand_b + self.pc += 3 From 8fb105e0ab919923910152118745c0bd711f9196 Mon Sep 17 00:00:00 2001 From: rfamilara Date: Sat, 5 Dec 2020 21:40:57 -0600 Subject: [PATCH 2/4] Add the ability to load files dynamically, get mult.ls8 running -Implement the System Stack and be able to run the stack.ls8 program --- ls8/cpu.py | 139 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 51 deletions(-) diff --git a/ls8/cpu.py b/ls8/cpu.py index cc9b888aa..82682a4c0 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -1,57 +1,99 @@ """CPU functionality.""" import sys -SP = 7 -LDI = 0b10000010 -PRN = 0b01000111 -HLT = 0b00000001 -MUL = 0b10100010 -PUSH = 0b01000101 -POP = 0b01000110 class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" - self.ram = [0] * 256 - self.registers = [0] * 8 # R0-R7 - self.registers[SP] = 0xF4 # stack pointer - self.pc = 0 # Program Counter, address of the currently-executing instuction - - - def ram_read(self, address): - return self.ram[address] - - def ram_write(self, value, address): - self.ram[address] = value + self.reg = [0] * 8 + self.sp = 7 + self.reg[self.sp] = 0xF4 # Stack pointer starts at F4 or 244 in RAM + self.pc = 0 # Program Counter, address of the currently executing instruction + self.ir = 0 # Instruction Register, contains a copy of the currently executing instruction + self.op_table = { + 0b10000010 : self.ldi, + 0b01000111 : self.prn, + 0b10100010 : self.mult, + 0b00000001 : self.hlt, + 0b01000101 : self.push, + 0b01000110 : self.pop, + 0b01010000 : self.call, + 0b00010001 : self.ret, + 0b10100000 : self.add} 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 + file = open('examples/call.ls8', "r") + for line in file.readlines(): + #load a line into memory (not including comments) + try: + x = line[:line.index("#")] + except ValueError: + x = line + + try: + #convert binary to decimal + y = int(x, 2) + self.ram[address] = y + except ValueError: + continue + address+=1 + + def ldi(self, op_a, op_b): + self.reg[op_a] = op_b + + def mult(self, op_a, op_b): + self.reg[op_a] = self.reg[op_a] * self.reg[op_b] + + # Push the value in the given register on the stack. + def push(self, op_a, op_b): + self.reg[self.sp] -= 1 + self.ram[self.reg[self.sp]] = self.reg[op_a] + + # Pop the value at the top of the stack into the given register. + def pop(self, op_a, op_b): + self.reg[op_a] = self.ram[self.reg[self.sp]] + self.reg[self.sp] += 1 + + # Sets the PC to the register value + def call(self, op_a, op_b): + # address of instruction after call is pushed on to the stack + self.reg[self.sp] -= 1 + self.ram[self.reg[self.sp]] = self.pc + 2 + # set PC to value stored in given register + self.pc = self.reg[op_a] + return True + + def ret(self, op_a, op_b): + # pop value from stack into register op_a + self.pop(op_a, 0) + self.pc = self.reg[op_a] + return True + + def add(self, op_a, op_b): + self.reg[op_a] = self.reg[op_a] + self.reg[op_b] + + # accept memory address to read read and return the value stored there + def ram_read(self, address): + return self.ram[address] + + def ram_write(self, value, address): + self.ram[address] = value + + def prn(self, op_a, op_b): + print(self.reg[op_a]) + def hlt(self, op_a, op_b): + sys.exit() 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 @@ -63,7 +105,6 @@ 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, @@ -80,19 +121,15 @@ def trace(self): def run(self): """Run the CPU.""" - - self.running = True - while self.running: - ir = self.ram_read(self.pc) # Instruction register - operand_a = self.ram_read(self.pc + 1) - operand_b = self.ram_read(self.pc + 2) - - if ir == HLT: # HLT - self.running = False - self.pc += 1 - elif ir == PRN: - print(self.registers[operand_a]) - self.pc += 2 - elif ir == LDI: - self.registers[operand_a] = operand_b - self.pc += 3 + #internal register + while True: + self.ir = self.ram[self.pc] + op_a = self.ram[self.pc + 1] + op_b = self.ram[self.pc + 2] + + willJump = self.op_table[self.ir](op_a, op_b) + + #self.ir is current address, shift right by 6 elements to find + #amount of arguments that this function takes + if not willJump: + self.pc += (self.ir >> 6) + 1; \ No newline at end of file From 32adcf05ae99bc23594ed6c8dc6c5a1ae832182b Mon Sep 17 00:00:00 2001 From: rfamilara Date: Tue, 8 Dec 2020 18:31:49 -0600 Subject: [PATCH 3/4] Completed the module activities --- ls8/cpu.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index 82682a4c0..01b7f5c74 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -104,7 +104,9 @@ 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, From c11a24f8cdaecd2a1e8e55032f26208928b39d1a Mon Sep 17 00:00:00 2001 From: rfamilara Date: Thu, 10 Dec 2020 22:13:53 -0600 Subject: [PATCH 4/4] Finalized and completed the project module --- ls8/cpu.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ls8/cpu.py b/ls8/cpu.py index 01b7f5c74..3ee3b4187 100644 --- a/ls8/cpu.py +++ b/ls8/cpu.py @@ -101,6 +101,7 @@ def alu(self, op, reg_a, reg_b): 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.