---
# System prepended metadata

title: CSPT13 Computer Architecture II

---

# CSPT13 Computer Architecture II

## Guided Project Pt. 1
```
"""CPU functionality."""

import sys

HLT = 0b00000001
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.pc = 0
        self.ram = [0] * 256
        self.halted = False

    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 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
        else:
            print("idk what to do.")
            pass

```

## Parsing Operands from Instruction
```
# Meanings of the bits in the first byte of each instruction: `AABCDDDD`

# * `AA` Number of operands for this opcode, 0-2

INSTRUCTION = 0b10000010 # >> 6 --> 0b100001 & 0b001100 --> 0b10
PC = 0
number_of_times_to_increment_pc =  ((INSTRUCTION >> 6) & 0b11) + 1
PC += number_of_times_to_increment_pc
```

## File I/O
```
import sys

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} to an int")
                continue
except FileNotFoundError:
    print("file not found...")

```