# 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}")
```