# CSPT13 Computer Architecture III ## Guided Project Pt. II ``` """CPU functionality.""" import sys HLT = 0b00000001 LDI = 0b10000010 PRN = 0b01000111 MUL = 0b10100010 class CPU: """Main CPU class.""" def __init__(self): """Construct a new CPU.""" self.registers = [0] * 8 self.registers[7] = 0xF4 self.pc = 0 self.ram = [0] * 256 self.halted = False def load(self, filename): """Load a program into memory.""" address = 0 # open the file with open(filename) as my_file: # go through each line to parse and get # the instruction for line in my_file: # try and get the instruction/operand in the line 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 def alu(self, op, reg_a, reg_b): """ALU operations.""" if op == MUL: self.registers[reg_a] *= self.registers[reg_b] self.pc += 3 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 ram_read(self, address): return self.ram[address] def ram_write(self, value, address): self.ram[address] = value def run(self): """Run the CPU.""" while not self.halted: instruction_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(instruction_to_execute, operand_a, operand_b) def execute_instruction(self, instruction, operand_a, operand_b): if instruction == HLT: self.halted = True self.pc += 1 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.alu(instruction, operand_a, operand_b) else: print("idk what to do.") pass ``` ## Push and Pop ``` 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 into reg 2 65, 2, SAVE, # SAVE 20 into reg 3 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() 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 address of stack pointer registers[stack_pointer_register] = len(memory) - 1 # 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 == HALT: running = False program_counter += 1 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_registers = registers[register_a] + registers[register_b] registers[register_a] = sum_of_registers 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_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(f"Unknown instruction {command_to_execute}") sys.exit(1) print(f"registers: {registers}") print(f"memory: {memory}") ```